Files
PartsInquiry/frontend/unpackage/dist/dev/app-plus/app-service.js
2025-09-21 14:25:01 +08:00

5077 lines
180 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
Promise.prototype.finally = function(callback) {
const promise = this.constructor;
return this.then(
(value) => promise.resolve(callback()).then(() => value),
(reason) => promise.resolve(callback()).then(() => {
throw reason;
})
);
};
}
;
if (typeof uni !== "undefined" && uni && uni.requireGlobal) {
const global = uni.requireGlobal();
ArrayBuffer = global.ArrayBuffer;
Int8Array = global.Int8Array;
Uint8Array = global.Uint8Array;
Uint8ClampedArray = global.Uint8ClampedArray;
Int16Array = global.Int16Array;
Uint16Array = global.Uint16Array;
Int32Array = global.Int32Array;
Uint32Array = global.Uint32Array;
Float32Array = global.Float32Array;
Float64Array = global.Float64Array;
BigInt64Array = global.BigInt64Array;
BigUint64Array = global.BigUint64Array;
}
;
if (uni.restoreGlobal) {
uni.restoreGlobal(Vue, weex, plus, setTimeout, clearTimeout, setInterval, clearInterval);
}
(function(vue) {
"use strict";
function formatAppLog(type, filename, ...args) {
if (uni.__log__) {
uni.__log__(type, filename, ...args);
} else {
console[type].apply(console, [...args, filename]);
}
}
var define_process_env_default = {};
const envBaseUrl = typeof process !== "undefined" && define_process_env_default && (define_process_env_default.VITE_APP_API_BASE_URL || define_process_env_default.API_BASE_URL) || "";
const storageBaseUrl = typeof uni !== "undefined" ? uni.getStorageSync("API_BASE_URL") || "" : "";
const fallbackBaseUrl = "http://127.0.0.1:8080";
const API_BASE_URL = (envBaseUrl || storageBaseUrl || fallbackBaseUrl).replace(/\/$/, "");
const candidateBases = [envBaseUrl, storageBaseUrl, fallbackBaseUrl, "http://127.0.0.1:8080", "http://localhost:8080"];
const API_BASE_URL_CANDIDATES = Array.from(new Set(candidateBases.filter(Boolean))).map((u) => String(u).replace(/\/$/, ""));
const envShopId = typeof process !== "undefined" && define_process_env_default && (define_process_env_default.VITE_APP_SHOP_ID || define_process_env_default.SHOP_ID) || "";
const storageShopId = typeof uni !== "undefined" ? uni.getStorageSync("SHOP_ID") || "" : "";
const SHOP_ID = Number(envShopId || storageShopId || 1);
const envEnableDefaultUser = typeof process !== "undefined" && define_process_env_default && (define_process_env_default.VITE_APP_ENABLE_DEFAULT_USER || define_process_env_default.ENABLE_DEFAULT_USER) || "";
const storageEnableDefaultUser = typeof uni !== "undefined" ? uni.getStorageSync("ENABLE_DEFAULT_USER") || "" : "";
const ENABLE_DEFAULT_USER = String(envEnableDefaultUser || storageEnableDefaultUser || "true").toLowerCase() === "true";
const envDefaultUserId = typeof process !== "undefined" && define_process_env_default && (define_process_env_default.VITE_APP_DEFAULT_USER_ID || define_process_env_default.DEFAULT_USER_ID) || "";
const storageDefaultUserId = typeof uni !== "undefined" ? uni.getStorageSync("DEFAULT_USER_ID") || "" : "";
const DEFAULT_USER_ID = Number(envDefaultUserId || storageDefaultUserId || 2);
function buildUrl(path) {
if (!path)
return API_BASE_URL;
if (path.startsWith("http"))
return path;
return API_BASE_URL + (path.startsWith("/") ? path : "/" + path);
}
function requestWithFallback(options, candidates, idx, resolve, reject) {
const base = candidates[idx] || API_BASE_URL;
const url = options.url.replace(/^https?:\/\/[^/]+/, base);
uni.request({ ...options, url, success: (res) => {
const { statusCode, data } = res;
if (statusCode >= 200 && statusCode < 300)
return resolve(data);
const msg = data && (data.message || data.error || data.msg) || "HTTP " + statusCode;
uni.showToast({ title: msg, icon: "none" });
if (idx + 1 < candidates.length)
return requestWithFallback(options, candidates, idx + 1, resolve, reject);
reject(new Error(msg));
}, fail: (err) => {
if (idx + 1 < candidates.length)
return requestWithFallback(options, candidates, idx + 1, resolve, reject);
reject(err);
} });
}
function get(path, params = {}) {
return new Promise((resolve, reject) => {
const headers = { "X-Shop-Id": SHOP_ID };
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID)
headers["X-User-Id"] = DEFAULT_USER_ID;
const options = { url: buildUrl(path), method: "GET", data: params, header: headers };
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject);
});
}
function post(path, body = {}) {
return new Promise((resolve, reject) => {
const headers = { "Content-Type": "application/json", "X-Shop-Id": SHOP_ID };
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID)
headers["X-User-Id"] = DEFAULT_USER_ID;
const options = { url: buildUrl(path), method: "POST", data: body, header: headers };
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject);
});
}
function put(path, body = {}) {
return new Promise((resolve, reject) => {
const headers = { "Content-Type": "application/json", "X-Shop-Id": SHOP_ID };
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID)
headers["X-User-Id"] = DEFAULT_USER_ID;
const options = { url: buildUrl(path), method: "PUT", data: body, header: headers };
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject);
});
}
function del(path, body = {}) {
return new Promise((resolve, reject) => {
const headers = { "Content-Type": "application/json", "X-Shop-Id": SHOP_ID };
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID)
headers["X-User-Id"] = DEFAULT_USER_ID;
const options = { url: buildUrl(path), method: "DELETE", data: body, header: headers };
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject);
});
}
function uploadWithFallback(options, candidates, idx, resolve, reject) {
const base = candidates[idx] || API_BASE_URL;
const url = options.url.replace(/^https?:\/\/[^/]+/, base);
const uploadOptions = { ...options, url };
uni.uploadFile({
...uploadOptions,
success: (res) => {
const statusCode = res.statusCode || 0;
if (statusCode >= 200 && statusCode < 300) {
try {
const data = typeof res.data === "string" ? JSON.parse(res.data) : res.data;
return resolve(data);
} catch (e) {
return resolve(res.data);
}
}
if (idx + 1 < candidates.length)
return uploadWithFallback(options, candidates, idx + 1, resolve, reject);
reject(new Error("HTTP " + statusCode));
},
fail: (err) => {
if (idx + 1 < candidates.length)
return uploadWithFallback(options, candidates, idx + 1, resolve, reject);
reject(err);
}
});
}
function upload(path, filePath, formData = {}, name = "file") {
return new Promise((resolve, reject) => {
const header = { "X-Shop-Id": SHOP_ID };
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID)
header["X-User-Id"] = DEFAULT_USER_ID;
const options = { url: buildUrl(path), filePath, name, formData, header };
uploadWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject);
});
}
const INCOME_CATEGORIES = [
{ key: "sale_income", label: "销售收入" },
{ key: "operation_income", label: "经营所得" },
{ key: "interest_income", label: "利息收入" },
{ key: "investment_income", label: "投资收入" },
{ key: "other_income", label: "其它收入" }
];
const EXPENSE_CATEGORIES = [
{ key: "operation_expense", label: "经营支出" },
{ key: "office_supplies", label: "办公用品" },
{ key: "rent", label: "房租" },
{ key: "interest_expense", label: "利息支出" },
{ key: "other_expense", label: "其它支出" }
];
const ROUTES = {
home: "/pages/index/index",
productList: "/pages/product/list",
productForm: "/pages/product/form",
productSelect: "/pages/product/select",
productSettings: "/pages/product/settings",
orderCreate: "/pages/order/create",
detail: "/pages/detail/index",
my: "/pages/my/index",
myAbout: "/pages/my/about",
report: "/pages/report/index",
customerSelect: "/pages/customer/select",
supplierSelect: "/pages/supplier/select",
accountSelect: "/pages/account/select"
};
const _imports_0$1 = "/static/metal-bg.jpg";
const _export_sfc = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) {
target[key] = val;
}
return target;
};
const _sfc_main$l = {
data() {
return {
kpi: { todaySales: "0.00", monthSales: "0.00", monthProfit: "0.00", stockCount: "0" },
activeTab: "home",
notices: [],
loadingNotices: false,
noticeError: "",
features: [
{ key: "product", title: "货品", img: "/static/icons/product.png", emoji: "📦" },
{ key: "customer", title: "客户", img: "/static/icons/customer.png", emoji: "👥" },
{ key: "sale", title: "销售", img: "/static/icons/sale.png", emoji: "💰" },
{ key: "account", title: "账户", img: "/static/icons/account.png", emoji: "💳" },
{ key: "supplier", title: "供应商", img: "/static/icons/supplier.png", emoji: "🚚" },
{ key: "purchase", title: "进货", img: "/static/icons/purchase.png", emoji: "🛒" },
{ key: "otherPay", title: "其他支出", img: "/static/icons/other-pay.png", emoji: "💸" },
{ key: "vip", title: "VIP会员", img: "/static/icons/vip.png", emoji: "👑" },
{ key: "report", title: "报表", img: "/static/icons/report.png", emoji: "📊" },
{ key: "more", title: "更多", img: "/static/icons/more.png", emoji: "⋯" }
]
};
},
onLoad() {
this.fetchMetrics();
this.fetchNotices();
},
methods: {
async fetchMetrics() {
try {
const d = await get("/api/dashboard/overview");
const toNum = (v) => typeof v === "number" ? v : Number(v || 0);
this.kpi = {
...this.kpi,
todaySales: toNum(d && d.todaySalesAmount).toFixed(2),
monthSales: toNum(d && d.monthSalesAmount).toFixed(2),
monthProfit: toNum(d && d.monthGrossProfit).toFixed(2),
stockCount: String((d && d.stockTotalQuantity) != null ? d.stockTotalQuantity : 0)
};
} catch (e) {
}
},
async fetchNotices() {
this.loadingNotices = true;
this.noticeError = "";
try {
const list = await get("/api/notices");
this.notices = Array.isArray(list) ? list.map((n) => ({
text: n.content || n.title || "",
tag: n.tag || ""
})) : [];
} catch (e) {
this.noticeError = e && e.message || "公告加载失败";
} finally {
this.loadingNotices = false;
}
},
onFeatureTap(item) {
if (item.key === "product") {
uni.switchTab({ url: "/pages/product/list" });
return;
}
if (item.key === "sale") {
try {
uni.setStorageSync("ORDER_DEFAULT_PARAMS", { biz: "sale", type: "out" });
} catch (e) {
}
uni.switchTab({ url: "/pages/order/create" });
return;
}
if (item.key === "customer") {
uni.navigateTo({ url: "/pages/customer/select" });
return;
}
if (item.key === "account") {
uni.navigateTo({ url: "/pages/account/select" });
return;
}
if (item.key === "supplier") {
uni.navigateTo({ url: "/pages/supplier/select" });
return;
}
if (item.key === "purchase") {
try {
uni.setStorageSync("ORDER_DEFAULT_PARAMS", { biz: "purchase", type: "in" });
} catch (e) {
}
uni.switchTab({ url: "/pages/order/create" });
return;
}
if (item.key === "report") {
uni.navigateTo({ url: ROUTES.report });
return;
}
if (item.key === "otherPay") {
try {
uni.setStorageSync("ORDER_DEFAULT_PARAMS", { biz: "expense" });
} catch (e) {
}
uni.switchTab({ url: "/pages/order/create" });
return;
}
uni.showToast({ title: item.title + "(开发中)", icon: "none" });
},
goProduct() {
uni.switchTab({ url: "/pages/product/list" });
},
onCreateOrder() {
uni.switchTab({ url: "/pages/order/create" });
},
goDetail() {
try {
formatAppLog("log", "at pages/index/index.vue:177", "[index] goDetail → /pages/detail/index");
} catch (e) {
}
uni.switchTab({ url: "/pages/detail/index" });
},
goMe() {
uni.switchTab({ url: "/pages/my/index" });
},
onNoticeTap(n) {
uni.showModal({
title: "广告",
content: n && (n.text || n.title || n.content) || "",
showCancel: false
});
},
onIconError(item) {
item.img = "";
}
}
};
function _sfc_render$k(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "home" }, [
vue.createElementVNode("image", {
class: "home-bg",
src: _imports_0$1,
mode: "aspectFill"
}),
vue.createCommentVNode(" 顶部统计卡片 "),
vue.createElementVNode("view", { class: "hero" }, [
vue.createElementVNode("view", { class: "hero-top" }, [
vue.createElementVNode("text", { class: "brand" }, "五金配件管家"),
vue.createElementVNode("view", { class: "cta" }, [
vue.createElementVNode("text", { class: "cta-text" }, "咨询")
])
]),
vue.createElementVNode("view", { class: "kpi" }, [
vue.createElementVNode("view", { class: "kpi-item" }, [
vue.createElementVNode("text", { class: "kpi-label" }, "今日销售额"),
vue.createElementVNode(
"text",
{ class: "kpi-value" },
vue.toDisplayString($data.kpi.todaySales),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "kpi-item" }, [
vue.createElementVNode("text", { class: "kpi-label" }, "本月销售额"),
vue.createElementVNode(
"text",
{ class: "kpi-value" },
vue.toDisplayString($data.kpi.monthSales),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "kpi-item" }, [
vue.createElementVNode("text", { class: "kpi-label" }, "本月利润"),
vue.createElementVNode(
"text",
{ class: "kpi-value" },
vue.toDisplayString($data.kpi.monthProfit),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "kpi-item" }, [
vue.createElementVNode("text", { class: "kpi-label" }, "库存商品数量"),
vue.createElementVNode(
"text",
{ class: "kpi-value" },
vue.toDisplayString($data.kpi.stockCount),
1
/* TEXT */
)
])
])
]),
vue.createCommentVNode(" 广告栏:自动轮播,可点击查看详情 "),
vue.createElementVNode("view", { class: "notice" }, [
vue.createElementVNode("view", { class: "notice-left" }, "广告"),
$data.loadingNotices ? (vue.openBlock(), vue.createElementBlock("view", {
key: 0,
class: "notice-swiper",
style: { "display": "flex", "align-items": "center", "color": "#6b5a2a" }
}, "加载中...")) : $data.noticeError ? (vue.openBlock(), vue.createElementBlock(
"view",
{
key: 1,
class: "notice-swiper",
style: { "display": "flex", "align-items": "center", "color": "#dd524d" }
},
vue.toDisplayString($data.noticeError),
1
/* TEXT */
)) : !$data.notices.length ? (vue.openBlock(), vue.createElementBlock("view", {
key: 2,
class: "notice-swiper",
style: { "display": "flex", "align-items": "center", "color": "#6b5a2a" }
}, "暂无公告")) : (vue.openBlock(), vue.createElementBlock("swiper", {
key: 3,
class: "notice-swiper",
circular: "",
autoplay: "",
interval: "4000",
duration: "400",
vertical: ""
}, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.notices, (n, idx) => {
return vue.openBlock(), vue.createElementBlock("swiper-item", { key: idx }, [
vue.createElementVNode("view", {
class: "notice-item",
onClick: ($event) => $options.onNoticeTap(n)
}, [
vue.createElementVNode(
"text",
{ class: "notice-text" },
vue.toDisplayString(n.text),
1
/* TEXT */
),
n.tag ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "notice-tag"
},
vue.toDisplayString(n.tag),
1
/* TEXT */
)) : vue.createCommentVNode("v-if", true)
], 8, ["onClick"])
]);
}),
128
/* KEYED_FRAGMENT */
))
]))
]),
vue.createCommentVNode(" 分割标题:产品与功能 "),
vue.createElementVNode("view", { class: "section-title" }, [
vue.createElementVNode("text", { class: "section-text" }, "常用功能")
]),
vue.createCommentVNode(" 功能九宫格(玻璃容器 + 圆角方形图标) "),
vue.createElementVNode("view", { class: "grid-wrap" }, [
vue.createElementVNode("view", { class: "grid" }, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.features, (item) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "grid-item",
key: item.key,
onClick: ($event) => $options.onFeatureTap(item)
}, [
vue.createElementVNode("view", { class: "icon icon-squircle" }, [
item.img ? (vue.openBlock(), vue.createElementBlock("image", {
key: 0,
src: item.img,
class: "icon-img",
mode: "aspectFit",
onError: ($event) => $options.onIconError(item)
}, null, 40, ["src", "onError"])) : item.emoji ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 1,
class: "icon-emoji"
},
vue.toDisplayString(item.emoji),
1
/* TEXT */
)) : (vue.openBlock(), vue.createElementBlock("view", {
key: 2,
class: "icon-placeholder"
}))
]),
vue.createElementVNode(
"text",
{ class: "grid-chip" },
vue.toDisplayString(item.title),
1
/* TEXT */
)
], 8, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
))
])
]),
vue.createCommentVNode(" 底部操作条改为原生 tabBar移除自定义栏 ")
]);
}
const PagesIndexIndex = /* @__PURE__ */ _export_sfc(_sfc_main$l, [["render", _sfc_render$k], ["__file", "D:/wx/PartsInquiry/frontend/pages/index/index.vue"]]);
const _imports_0 = "/static/logo.png";
function todayString() {
const d = /* @__PURE__ */ new Date();
const m = (d.getMonth() + 1).toString().padStart(2, "0");
const day = d.getDate().toString().padStart(2, "0");
return `${d.getFullYear()}-${m}-${day}`;
}
const _sfc_main$k = {
data() {
return {
biz: "sale",
saleType: "out",
purchaseType: "in",
order: {
orderTime: todayString(),
customerId: null,
supplierId: null,
remark: ""
},
customerName: "",
customerPriceLevel: "零售价",
_lastCustomerId: null,
_priceCache: {},
supplierName: "",
items: [],
activeCategory: "sale_income",
counterpartyType: "customer",
trxAmount: 0,
selectedAccountId: null,
selectedAccountName: "",
// 收款/付款输入
payments: { cash: 0, bank: 0, wechat: 0 },
showMore: false
};
},
computed: {
totalQuantity() {
return this.items.reduce((s, it) => s + Number(it.quantity || 0), 0);
},
totalAmount() {
return this.items.reduce((s, it) => s + Number(it.quantity || 0) * Number(it.unitPrice || 0), 0);
},
customerLabel() {
return this.customerName || "零售客户";
},
supplierLabel() {
return this.supplierName || "零散供应商";
},
incomeCategories() {
return this._incomeCategories || INCOME_CATEGORIES;
},
expenseCategories() {
return this._expenseCategories || EXPENSE_CATEGORIES;
},
accountLabel() {
return this.selectedAccountName || "现金";
},
counterpartyLabel() {
return this.counterpartyType === "customer" ? 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);
}
},
onLoad(query) {
try {
const preset = uni.getStorageSync("ORDER_DEFAULT_PARAMS") || {};
const biz = query && query.biz || preset.biz;
const type = query && query.type || preset.type;
if (biz === "sale" || biz === "purchase" || biz === "income" || biz === "expense") {
this.biz = biz;
}
if (this.biz === "sale" && (type === "out" || type === "return" || type === "collect")) {
this.saleType = type;
}
if (this.biz === "purchase" && (type === "in" || type === "return" || type === "pay")) {
this.purchaseType = type;
}
try {
uni.removeStorageSync("ORDER_DEFAULT_PARAMS");
} catch (_) {
}
} catch (e) {
}
this.fetchCategories();
},
onShow() {
if (this.biz === "sale") {
if (this.order.customerId && this.order.customerId !== this._lastCustomerId) {
this.loadCustomerLevel(this.order.customerId).then(() => {
this._lastCustomerId = this.order.customerId;
for (const it of this.items) {
if (it && (it._autoPrice || !it.unitPrice))
this.autoPriceItem(it);
}
});
}
for (const it of this.items) {
if (it && !it.unitPrice)
this.autoPriceItem(it);
}
}
},
methods: {
async fetchCategories() {
try {
const res = await get("/api/finance/categories");
if (res && Array.isArray(res.incomeCategories))
this._incomeCategories = res.incomeCategories;
if (res && Array.isArray(res.expenseCategories))
this._expenseCategories = res.expenseCategories;
this.ensureActiveCategory();
} catch (_) {
this.ensureActiveCategory();
}
},
ensureActiveCategory() {
const list = this.biz === "income" ? this.incomeCategories || [] : this.expenseCategories || [];
if (!list.length)
return;
const exists = list.some((it) => it && it.key === this.activeCategory);
if (!exists)
this.activeCategory = list[0].key;
},
async loadCustomerLevel(customerId) {
try {
const d = await get(`/api/customers/${customerId}`);
this.customerPriceLevel = d && d.priceLevel ? d.priceLevel : "零售价";
} catch (e) {
this.customerPriceLevel = "零售价";
}
},
priceFieldForLevel() {
const lvl = this.customerPriceLevel || "零售价";
if (lvl === "批发价")
return "wholesalePrice";
if (lvl === "大单报价")
return "bigClientPrice";
return "retailPrice";
},
async autoPriceItem(it) {
if (this.biz !== "sale")
return;
if (!it || !it.productId)
return;
const pid = it.productId;
let detail = this._priceCache[pid];
if (!detail) {
try {
detail = await get(`/api/products/${pid}`);
this._priceCache[pid] = detail;
} catch (e) {
return;
}
}
const field = this.priceFieldForLevel();
let price = Number(detail && detail[field] != null ? detail[field] : 0);
if (!price && field !== "retailPrice") {
price = Number(detail && detail.retailPrice != null ? detail.retailPrice : 0);
}
it.unitPrice = price;
it._autoPrice = true;
this.recalc();
},
onPriceInput(it) {
if (it) {
it._autoPrice = false;
this.recalc();
}
},
switchBiz(type) {
this.biz = type;
this.ensureActiveCategory();
},
onDateChange(e) {
this.order.orderTime = e.detail.value;
},
chooseCustomer() {
uni.navigateTo({ url: "/pages/customer/select" });
},
chooseSupplier() {
uni.navigateTo({ url: "/pages/supplier/select" });
},
chooseProduct() {
uni.navigateTo({ url: "/pages/product/select" });
},
chooseAccount() {
uni.navigateTo({ url: "/pages/account/select?mode=pick" });
},
chooseCounterparty() {
if (!(this.biz === "income" || this.biz === "expense"))
return;
if (this.counterpartyType === "customer") {
uni.navigateTo({ url: "/pages/customer/select" });
} else {
uni.navigateTo({ url: "/pages/supplier/select" });
}
},
setCounterparty(t) {
this.counterpartyType = t;
this.ensureActiveCategory();
},
recalc() {
this.$forceUpdate();
},
recalcPay() {
this.$forceUpdate();
},
async submit() {
const isSaleOrPurchase = this.biz === "sale" || this.biz === "purchase";
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;
if (isSaleOrPurchase && !isCollectOrPay) {
if (!this.items.length) {
uni.showToast({ title: "请先选择商品", icon: "none" });
return;
}
const invalid = this.items.find((it) => !it.productId || Number(it.quantity || 0) <= 0);
if (invalid) {
uni.showToast({ title: "数量需大于0", icon: "none" });
return;
}
}
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,
items: this.items.map((it) => ({ productId: it.productId, quantity: Number(it.quantity || 0), unitPrice: Number(it.unitPrice || 0) })),
amount: this.totalAmount
} : {
type: this.biz,
category: this.activeCategory,
counterpartyType: this.counterpartyType,
counterpartyId: this.counterpartyType === "customer" ? this.order.customerId || null : this.order.supplierId || null,
accountId: this.selectedAccountId || null,
amount: Number(this.trxAmount || 0),
txTime: this.order.orderTime,
remark: this.order.remark
};
try {
const url = isSaleOrPurchase ? isCollectOrPay ? `/api/payments/${this.biz}` : "/api/orders" : "/api/other-transactions";
await post(url, payload);
uni.showToast({ title: "已保存", icon: "success" });
setTimeout(() => {
uni.navigateBack();
}, 600);
} catch (e) {
uni.showToast({ title: e && e.message || "保存失败", icon: "none" });
}
},
saveAndReset() {
this.items = [];
this.trxAmount = 0;
this.order.remark = "";
this.payments = { cash: 0, bank: 0, wechat: 0 };
}
}
};
function _sfc_render$j(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "order" }, [
vue.createCommentVNode(" 顶部 Tab "),
vue.createElementVNode("view", { class: "tabs" }, [
vue.createElementVNode(
"text",
{
class: vue.normalizeClass({ active: $data.biz === "sale" }),
onClick: _cache[0] || (_cache[0] = ($event) => $options.switchBiz("sale"))
},
"销售",
2
/* CLASS */
),
vue.createElementVNode(
"text",
{
class: vue.normalizeClass({ active: $data.biz === "purchase" }),
onClick: _cache[1] || (_cache[1] = ($event) => $options.switchBiz("purchase"))
},
"进货",
2
/* CLASS */
),
vue.createElementVNode(
"text",
{
class: vue.normalizeClass({ active: $data.biz === "income" }),
onClick: _cache[2] || (_cache[2] = ($event) => $options.switchBiz("income"))
},
"其他收入",
2
/* CLASS */
),
vue.createElementVNode(
"text",
{
class: vue.normalizeClass({ active: $data.biz === "expense" }),
onClick: _cache[3] || (_cache[3] = ($event) => $options.switchBiz("expense"))
},
"其他支出",
2
/* CLASS */
)
]),
vue.createCommentVNode(" 子类目按钮 "),
$data.biz === "sale" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 0,
class: "subtabs"
}, [
vue.createElementVNode(
"button",
{
class: vue.normalizeClass(["subbtn", { active: $data.saleType === "out" }]),
onClick: _cache[4] || (_cache[4] = ($event) => $data.saleType = "out")
},
"出货",
2
/* CLASS */
),
vue.createElementVNode(
"button",
{
class: vue.normalizeClass(["subbtn", { active: $data.saleType === "return" }]),
onClick: _cache[5] || (_cache[5] = ($event) => $data.saleType = "return")
},
"退货",
2
/* CLASS */
),
vue.createElementVNode(
"button",
{
class: vue.normalizeClass(["subbtn", { active: $data.saleType === "collect" }]),
onClick: _cache[6] || (_cache[6] = ($event) => $data.saleType = "collect")
},
"收款",
2
/* CLASS */
)
])) : $data.biz === "purchase" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 1,
class: "subtabs"
}, [
vue.createElementVNode(
"button",
{
class: vue.normalizeClass(["subbtn", { active: $data.purchaseType === "in" }]),
onClick: _cache[7] || (_cache[7] = ($event) => $data.purchaseType = "in")
},
"进货",
2
/* CLASS */
),
vue.createElementVNode(
"button",
{
class: vue.normalizeClass(["subbtn", { active: $data.purchaseType === "return" }]),
onClick: _cache[8] || (_cache[8] = ($event) => $data.purchaseType = "return")
},
"退货",
2
/* CLASS */
),
vue.createElementVNode(
"button",
{
class: vue.normalizeClass(["subbtn", { active: $data.purchaseType === "pay" }]),
onClick: _cache[9] || (_cache[9] = ($event) => $data.purchaseType = "pay")
},
"付款",
2
/* CLASS */
)
])) : vue.createCommentVNode("v-if", true),
vue.createCommentVNode(" 日期与客户 "),
vue.createElementVNode("picker", {
mode: "date",
value: $data.order.orderTime,
onChange: _cache[10] || (_cache[10] = (...args) => $options.onDateChange && $options.onDateChange(...args))
}, [
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "时间"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($data.order.orderTime),
1
/* TEXT */
)
])
], 40, ["value"]),
$data.biz === "sale" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 2,
class: "field",
onClick: _cache[11] || (_cache[11] = (...args) => $options.chooseCustomer && $options.chooseCustomer(...args))
}, [
vue.createElementVNode("text", { class: "label" }, "客户"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($options.customerLabel),
1
/* TEXT */
)
])) : $data.biz === "purchase" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 3,
class: "field",
onClick: _cache[12] || (_cache[12] = (...args) => $options.chooseSupplier && $options.chooseSupplier(...args))
}, [
vue.createElementVNode("text", { class: "label" }, "供应商"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($options.supplierLabel),
1
/* TEXT */
)
])) : vue.createCommentVNode("v-if", true),
vue.createCommentVNode(" 销售/进货:收款/付款 专用页面 "),
$data.biz === "sale" && $data.saleType === "collect" || $data.biz === "purchase" && $data.purchaseType === "pay" ? (vue.openBlock(), vue.createElementBlock("view", { key: 4 }, [
vue.createCommentVNode(" 客户 / 供应商 "),
$data.biz === "sale" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 0,
class: "field",
onClick: _cache[13] || (_cache[13] = (...args) => $options.chooseCustomer && $options.chooseCustomer(...args))
}, [
vue.createElementVNode("text", { class: "label" }, "客户"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($options.customerLabel),
1
/* TEXT */
)
])) : (vue.openBlock(), vue.createElementBlock("view", {
key: 1,
class: "field",
onClick: _cache[14] || (_cache[14] = (...args) => $options.chooseSupplier && $options.chooseSupplier(...args))
}, [
vue.createElementVNode("text", { class: "label" }, "供应商"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($options.supplierLabel),
1
/* TEXT */
)
])),
vue.createCommentVNode(" 三种收付款方式 "),
vue.createElementVNode("view", { class: "field pay-row" }, [
vue.createElementVNode("text", { class: "label" }, "现金"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "pay-input",
type: "digit",
"onUpdate:modelValue": _cache[15] || (_cache[15] = ($event) => $data.payments.cash = $event),
placeholder: "0.00",
onInput: _cache[16] || (_cache[16] = ($event) => $options.recalcPay())
},
null,
544
/* NEED_HYDRATION, NEED_PATCH */
), [
[
vue.vModelText,
$data.payments.cash,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode("view", { class: "field pay-row" }, [
vue.createElementVNode("text", { class: "label" }, "银行存款"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "pay-input",
type: "digit",
"onUpdate:modelValue": _cache[17] || (_cache[17] = ($event) => $data.payments.bank = $event),
placeholder: "0.00",
onInput: _cache[18] || (_cache[18] = ($event) => $options.recalcPay())
},
null,
544
/* NEED_HYDRATION, NEED_PATCH */
), [
[
vue.vModelText,
$data.payments.bank,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode("view", { class: "field pay-row" }, [
vue.createElementVNode("text", { class: "label" }, "微信"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "pay-input",
type: "digit",
"onUpdate:modelValue": _cache[19] || (_cache[19] = ($event) => $data.payments.wechat = $event),
placeholder: "0.00",
onInput: _cache[20] || (_cache[20] = ($event) => $options.recalcPay())
},
null,
544
/* NEED_HYDRATION, NEED_PATCH */
), [
[
vue.vModelText,
$data.payments.wechat,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode(
"view",
{
class: "collapse-trigger",
onClick: _cache[21] || (_cache[21] = ($event) => $data.showMore = !$data.showMore)
},
vue.toDisplayString($data.showMore ? "收起" : ""),
1
/* TEXT */
),
vue.createCommentVNode(" 备注与日期 "),
vue.createElementVNode("view", { class: "textarea" }, [
vue.createElementVNode(
"view",
{ class: "amount-badge" },
"总金额:" + vue.toDisplayString($options.payTotal.toFixed(2)),
1
/* TEXT */
),
vue.withDirectives(vue.createElementVNode(
"textarea",
{
"onUpdate:modelValue": _cache[22] || (_cache[22] = ($event) => $data.order.remark = $event),
maxlength: "200",
placeholder: "备注最多输入200个字"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.order.remark]
]),
vue.createElementVNode("view", { class: "date-mini" }, [
vue.createElementVNode("picker", {
mode: "date",
value: $data.order.orderTime,
onChange: _cache[23] || (_cache[23] = (...args) => $options.onDateChange && $options.onDateChange(...args))
}, [
vue.createElementVNode(
"text",
null,
vue.toDisplayString($data.order.orderTime),
1
/* TEXT */
)
], 40, ["value"])
])
])
])) : $data.biz === "sale" || $data.biz === "purchase" ? (vue.openBlock(), vue.createElementBlock(
vue.Fragment,
{ key: 5 },
[
vue.createCommentVNode(" 已选商品与合计(销售/进货 出入库) "),
vue.createElementVNode("view", null, [
vue.createElementVNode("view", { class: "summary" }, [
vue.createElementVNode(
"text",
null,
"选中货品(" + vue.toDisplayString($options.totalQuantity) + "",
1
/* TEXT */
),
vue.createElementVNode(
"text",
null,
"合计金额:¥ " + vue.toDisplayString($options.totalAmount.toFixed(2)),
1
/* TEXT */
)
]),
vue.createCommentVNode(" 加号添加商品 "),
vue.createElementVNode("view", {
class: "add",
onClick: _cache[24] || (_cache[24] = (...args) => $options.chooseProduct && $options.chooseProduct(...args))
}, "+")
])
],
2112
/* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
)) : (vue.openBlock(), vue.createElementBlock(
vue.Fragment,
{ key: 6 },
[
vue.createCommentVNode(" 其它收入/支出 表单 "),
vue.createElementVNode("view", null, [
vue.createCommentVNode(" 往来单位类型切换 "),
vue.createElementVNode("view", { class: "subtabs" }, [
vue.createElementVNode(
"button",
{
class: vue.normalizeClass(["subbtn", { active: $data.counterpartyType === "customer" }]),
onClick: _cache[25] || (_cache[25] = ($event) => $options.setCounterparty("customer"))
},
"客户",
2
/* CLASS */
),
vue.createElementVNode(
"button",
{
class: vue.normalizeClass(["subbtn", { active: $data.counterpartyType === "supplier" }]),
onClick: _cache[26] || (_cache[26] = ($event) => $options.setCounterparty("supplier"))
},
"供应商",
2
/* CLASS */
)
]),
vue.createElementVNode("view", { class: "chips" }, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.biz === "income" ? $options.incomeCategories : $options.expenseCategories, (c) => {
return vue.openBlock(), vue.createElementBlock("view", {
key: c.key,
class: vue.normalizeClass(["chip", { active: $data.activeCategory === c.key }]),
onClick: ($event) => $data.activeCategory = c.key
}, vue.toDisplayString(c.label), 11, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
))
]),
vue.createElementVNode("view", {
class: "field",
onClick: _cache[27] || (_cache[27] = (...args) => $options.chooseCounterparty && $options.chooseCounterparty(...args))
}, [
vue.createElementVNode("text", { class: "label" }, "往来单位"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($options.counterpartyLabel),
1
/* TEXT */
)
]),
vue.createElementVNode("view", {
class: "field",
onClick: _cache[28] || (_cache[28] = (...args) => $options.chooseAccount && $options.chooseAccount(...args))
}, [
vue.createElementVNode("text", { class: "label" }, "结算账户"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($options.accountLabel),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "金额"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
type: "digit",
"onUpdate:modelValue": _cache[29] || (_cache[29] = ($event) => $data.trxAmount = $event),
placeholder: "0.00"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.trxAmount,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode("view", { class: "textarea" }, [
vue.withDirectives(vue.createElementVNode(
"textarea",
{
"onUpdate:modelValue": _cache[30] || (_cache[30] = ($event) => $data.order.remark = $event),
maxlength: "200",
placeholder: "备注最多输入200个字"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.order.remark]
])
])
])
],
2112
/* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
)),
vue.createCommentVNode(" 购物车空态 "),
!$data.items.length ? (vue.openBlock(), vue.createElementBlock("view", {
key: 7,
class: "empty"
}, [
vue.createElementVNode("image", {
src: _imports_0,
mode: "widthFix",
class: "empty-img"
}),
vue.createElementVNode("text", { class: "empty-text" }, "购物车里空空如也"),
vue.createElementVNode("text", { class: "empty-sub" }, "扫描或点击 “+” 选择商品吧")
])) : (vue.openBlock(), vue.createElementBlock(
vue.Fragment,
{ key: 8 },
[
vue.createCommentVNode(" 商品列表 "),
vue.createElementVNode("view", { class: "list" }, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.items, (it, idx) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "row",
key: idx
}, [
vue.createElementVNode(
"view",
{ class: "col name" },
vue.toDisplayString(it.productName),
1
/* TEXT */
),
vue.createElementVNode("view", { class: "col qty" }, [
vue.withDirectives(vue.createElementVNode("input", {
type: "number",
"onUpdate:modelValue": ($event) => it.quantity = $event,
onInput: _cache[31] || (_cache[31] = ($event) => $options.recalc())
}, null, 40, ["onUpdate:modelValue"]), [
[
vue.vModelText,
it.quantity,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode("view", { class: "col price" }, [
vue.withDirectives(vue.createElementVNode("input", {
type: "number",
"onUpdate:modelValue": ($event) => it.unitPrice = $event,
onInput: ($event) => $options.onPriceInput(it)
}, null, 40, ["onUpdate:modelValue", "onInput"]), [
[
vue.vModelText,
it.unitPrice,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode(
"view",
{ class: "col amount" },
"¥ " + vue.toDisplayString((Number(it.quantity) * Number(it.unitPrice)).toFixed(2)),
1
/* TEXT */
)
]);
}),
128
/* KEYED_FRAGMENT */
))
])
],
2112
/* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
)),
vue.createCommentVNode(" 底部提交栏 "),
vue.createElementVNode("view", { class: "bottom" }, [
vue.createElementVNode("button", {
class: "ghost",
onClick: _cache[32] || (_cache[32] = (...args) => $options.saveAndReset && $options.saveAndReset(...args))
}, "再记一笔"),
vue.createElementVNode("button", {
class: "primary",
onClick: _cache[33] || (_cache[33] = (...args) => $options.submit && $options.submit(...args))
}, "保存")
])
]);
}
const PagesOrderCreate = /* @__PURE__ */ _export_sfc(_sfc_main$k, [["render", _sfc_render$j], ["__file", "D:/wx/PartsInquiry/frontend/pages/order/create.vue"]]);
const _sfc_main$j = {
data() {
return { kw: "", products: [] };
},
onLoad() {
this.search();
},
methods: {
async search() {
try {
const res = await get("/api/products", { kw: this.kw, page: 1, size: 50 });
this.products = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
select(p) {
const opener = getCurrentPages()[getCurrentPages().length - 2];
if (opener && opener.$vm && opener.$vm.items) {
const initPrice = Number(p.retailPrice != null ? p.retailPrice : p.price || 0);
opener.$vm.items.push({ productId: p.id, productName: p.name, quantity: 1, unitPrice: initPrice, _autoPrice: true });
}
uni.navigateBack();
}
}
};
function _sfc_render$i(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "search" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.kw = $event),
placeholder: "搜索商品名称/编码",
onConfirm: _cache[1] || (_cache[1] = (...args) => $options.search && $options.search(...args))
},
null,
544
/* NEED_HYDRATION, NEED_PATCH */
), [
[vue.vModelText, $data.kw]
]),
vue.createElementVNode("button", {
size: "mini",
onClick: _cache[2] || (_cache[2] = (...args) => $options.search && $options.search(...args))
}, "搜索")
]),
vue.createElementVNode("scroll-view", {
"scroll-y": "",
class: "list"
}, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.products, (p) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: p.id,
onClick: ($event) => $options.select(p)
}, [
vue.createElementVNode(
"view",
{ class: "name" },
vue.toDisplayString(p.name),
1
/* TEXT */
),
vue.createElementVNode(
"view",
{ class: "meta" },
vue.toDisplayString((p.brand || "") + " " + (p.model || "") + " " + (p.spec || "")) + " · 库存:" + vue.toDisplayString(p.stock ?? 0),
1
/* TEXT */
)
], 8, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
))
])
]);
}
const PagesProductSelect = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["render", _sfc_render$i], ["__file", "D:/wx/PartsInquiry/frontend/pages/product/select.vue"]]);
const _sfc_main$i = {
data() {
return {
items: [],
query: { kw: "", page: 1, size: 20, categoryId: "" },
finished: false,
loading: false,
tab: "all",
categories: []
};
},
onLoad() {
this.fetchCategories();
this.reload();
},
onShow() {
this.reload();
},
computed: {
categoryNames() {
return this.categories.map((c) => c.name);
},
categoryLabel() {
const c = this.categories.find((x) => String(x.id) === String(this.query.categoryId));
return c ? "类别:" + c.name : "选择类别";
}
},
methods: {
switchTab(t) {
this.tab = t;
this.query.categoryId = "";
this.reload();
},
onPickCategory(e) {
const idx = Number(e.detail.value);
const c = this.categories[idx];
this.query.categoryId = c ? c.id : "";
this.reload();
},
async fetchCategories() {
try {
const res = await get("/api/product-categories", {});
this.categories = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
} catch (_) {
}
},
reload() {
this.items = [];
this.query.page = 1;
this.finished = false;
this.loadMore();
},
async loadMore() {
if (this.loading || this.finished)
return;
this.loading = true;
try {
const params = { kw: this.query.kw, page: this.query.page, size: this.query.size };
if (this.tab === "category" && this.query.categoryId)
params.categoryId = this.query.categoryId;
const res = await get("/api/products", 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.query.size)
this.finished = true;
this.query.page += 1;
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
} finally {
this.loading = false;
}
},
openForm(id) {
const url = "/pages/product/form" + (id ? "?id=" + id : "");
uni.navigateTo({ url });
}
}
};
function _sfc_render$h(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "tabs" }, [
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.tab === "all" }]),
onClick: _cache[0] || (_cache[0] = ($event) => $options.switchTab("all"))
},
"全部",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.tab === "category" }]),
onClick: _cache[1] || (_cache[1] = ($event) => $options.switchTab("category"))
},
"按类别",
2
/* CLASS */
)
]),
vue.createElementVNode("view", { class: "search" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $data.query.kw = $event),
placeholder: "输入名称/条码/规格查询",
onConfirm: _cache[3] || (_cache[3] = (...args) => $options.reload && $options.reload(...args))
},
null,
544
/* NEED_HYDRATION, NEED_PATCH */
), [
[
vue.vModelText,
$data.query.kw,
void 0,
{ trim: true }
]
]),
$data.tab === "category" ? (vue.openBlock(), vue.createElementBlock("picker", {
key: 0,
mode: "selector",
range: $options.categoryNames,
onChange: _cache[4] || (_cache[4] = (...args) => $options.onPickCategory && $options.onPickCategory(...args))
}, [
vue.createElementVNode(
"view",
{ class: "picker" },
vue.toDisplayString($options.categoryLabel),
1
/* TEXT */
)
], 40, ["range"])) : vue.createCommentVNode("v-if", true),
vue.createElementVNode("button", {
size: "mini",
onClick: _cache[5] || (_cache[5] = (...args) => $options.reload && $options.reload(...args))
}, "查询")
]),
vue.createElementVNode(
"scroll-view",
{
"scroll-y": "",
class: "list",
onScrolltolower: _cache[6] || (_cache[6] = (...args) => $options.loadMore && $options.loadMore(...args))
},
[
$data.items.length ? (vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
{ key: 0 },
vue.renderList($data.items, (it) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: it.id,
onClick: ($event) => $options.openForm(it.id)
}, [
it.cover ? (vue.openBlock(), vue.createElementBlock("image", {
key: 0,
src: it.cover,
class: "thumb",
mode: "aspectFill"
}, null, 8, ["src"])) : vue.createCommentVNode("v-if", true),
vue.createElementVNode("view", { class: "content" }, [
vue.createElementVNode(
"view",
{ class: "name" },
vue.toDisplayString(it.name),
1
/* TEXT */
),
vue.createElementVNode(
"view",
{ class: "meta" },
vue.toDisplayString(it.brand || "-") + " " + vue.toDisplayString(it.model || "") + " " + vue.toDisplayString(it.spec || ""),
1
/* TEXT */
),
vue.createElementVNode("view", { class: "meta" }, [
vue.createTextVNode(
"库存:" + vue.toDisplayString(it.stock ?? 0) + " ",
1
/* TEXT */
),
vue.createElementVNode(
"text",
{ class: "price" },
"零售价:¥" + vue.toDisplayString((it.retailPrice ?? it.price ?? 0).toFixed(2)),
1
/* TEXT */
)
])
])
], 8, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
)) : (vue.openBlock(), vue.createElementBlock("view", {
key: 1,
class: "empty"
}, [
vue.createElementVNode("text", null, "暂无数据,点击右上角“+”新增")
]))
],
32
/* NEED_HYDRATION */
),
vue.createElementVNode("view", {
class: "fab",
onClick: _cache[7] || (_cache[7] = ($event) => $options.openForm())
}, "")
]);
}
const PagesProductList = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["render", _sfc_render$h], ["__file", "D:/wx/PartsInquiry/frontend/pages/product/list.vue"]]);
const ITEM_SIZE = 210;
const GAP = 18;
const COLS = 3;
function px(rpx) {
return rpx;
}
const _sfc_main$h = {
name: "ImageUploader",
props: {
modelValue: { type: Array, default: () => [] },
max: { type: Number, default: 9 },
uploadPath: { type: String, default: "/api/attachments" },
uploadFieldName: { type: String, default: "file" },
formData: { type: Object, default: () => ({ ownerType: "product" }) }
},
data() {
return {
innerList: []
};
},
computed: {
areaHeight() {
const rows = Math.ceil((this.innerList.length + 1) / COLS) || 1;
return rows * ITEM_SIZE + (rows - 1) * GAP;
}
},
watch: {
modelValue: {
immediate: true,
handler(list) {
const mapped = (list || []).map((u, i) => ({
uid: String(i) + "_" + (u.id || u.url || Math.random().toString(36).slice(2)),
url: typeof u === "string" ? u : u.url || "",
x: this.posOf(i).x,
y: this.posOf(i).y
}));
this.innerList = mapped;
}
}
},
methods: {
posOf(index) {
const row = Math.floor(index / COLS);
const col = index % COLS;
return { x: px(col * (ITEM_SIZE + GAP)), y: px(row * (ITEM_SIZE + GAP)) };
},
cellStyle(index) {
return {
width: ITEM_SIZE + "rpx",
height: ITEM_SIZE + "rpx"
};
},
preview(index) {
uni.previewImage({ urls: this.innerList.map((i) => i.url), current: index });
},
remove(index) {
this.innerList.splice(index, 1);
this.reflow();
this.emit();
},
choose() {
const remain = this.max - this.innerList.length;
if (remain <= 0)
return;
uni.chooseImage({ count: remain, success: async (res) => {
for (const path of res.tempFilePaths) {
await this.doUpload(path);
}
} });
},
async doUpload(filePath) {
var _a;
try {
const resp = await upload(this.uploadPath, filePath, this.formData, this.uploadFieldName);
const url = (resp == null ? void 0 : resp.url) || ((_a = resp == null ? void 0 : resp.data) == null ? void 0 : _a.url) || (resp == null ? void 0 : resp.path) || "";
if (!url)
throw new Error("上传响应无 url");
this.innerList.push({ uid: Math.random().toString(36).slice(2), url, ...this.posOf(this.innerList.length) });
this.reflow();
this.emit();
} catch (e) {
uni.showToast({ title: "上传失败", icon: "none" });
}
},
onMoving(index, e) {
const { x, y } = e.detail;
this.innerList[index].x = x;
this.innerList[index].y = y;
},
onMoveEnd(index) {
const mv = this.innerList[index];
const col = Math.round(mv.x / (ITEM_SIZE + GAP));
const row = Math.round(mv.y / (ITEM_SIZE + GAP));
let newIndex = row * COLS + col;
newIndex = Math.max(0, Math.min(newIndex, this.innerList.length - 1));
if (newIndex !== index) {
const moved = this.innerList.splice(index, 1)[0];
this.innerList.splice(newIndex, 0, moved);
}
this.reflow();
this.emit();
},
reflow() {
this.innerList.forEach((it, i) => {
const p = this.posOf(i);
it.x = p.x;
it.y = p.y;
});
},
emit() {
this.$emit("update:modelValue", this.innerList.map((i) => i.url));
this.$emit("change", this.innerList.map((i) => i.url));
}
}
};
function _sfc_render$g(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "uploader" }, [
vue.createElementVNode(
"view",
{
class: "grid",
style: vue.normalizeStyle({ height: $options.areaHeight + "rpx" })
},
[
vue.createElementVNode(
"movable-area",
{
class: "area",
style: vue.normalizeStyle({ height: $options.areaHeight + "rpx" })
},
[
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.innerList, (img, index) => {
return vue.openBlock(), vue.createElementBlock("movable-view", {
key: img.uid,
class: "cell",
style: vue.normalizeStyle($options.cellStyle(index)),
direction: "all",
damping: 40,
friction: 2,
x: img.x,
y: img.y,
onChange: ($event) => $options.onMoving(index, $event),
onTouchend: ($event) => $options.onMoveEnd(index)
}, [
vue.createElementVNode("image", {
src: img.url,
mode: "aspectFill",
class: "thumb",
onClick: ($event) => $options.preview(index)
}, null, 8, ["src", "onClick"]),
vue.createElementVNode("view", {
class: "remove",
onClick: vue.withModifiers(($event) => $options.remove(index), ["stop"])
}, "×", 8, ["onClick"])
], 44, ["x", "y", "onChange", "onTouchend"]);
}),
128
/* KEYED_FRAGMENT */
)),
$data.innerList.length < $props.max ? (vue.openBlock(), vue.createElementBlock("view", {
key: 0,
class: "adder",
onClick: _cache[0] || (_cache[0] = (...args) => $options.choose && $options.choose(...args))
}, [
vue.createElementVNode("text", null, "")
])) : vue.createCommentVNode("v-if", true)
],
4
/* STYLE */
)
],
4
/* STYLE */
)
]);
}
const ImageUploader = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["render", _sfc_render$g], ["__scopeId", "data-v-7bd1ddd2"], ["__file", "D:/wx/PartsInquiry/frontend/components/ImageUploader.vue"]]);
const _sfc_main$g = {
components: { ImageUploader },
data() {
return {
id: "",
form: {
name: "",
barcode: "",
brand: "",
model: "",
spec: "",
origin: "",
categoryId: "",
unitId: "",
stock: null,
safeMin: null,
safeMax: null,
purchasePrice: null,
retailPrice: null,
wholesalePrice: null,
bigClientPrice: null,
images: [],
remark: ""
},
units: [],
categories: []
};
},
onLoad(query) {
this.id = (query == null ? void 0 : query.id) || "";
this.bootstrap();
},
computed: {
unitNames() {
return this.units.map((u) => u.name);
},
categoryNames() {
return this.categories.map((c) => c.name);
},
unitLabel() {
const u = this.units.find((x) => String(x.id) === String(this.form.unitId));
return u ? u.name : "选择单位";
},
categoryLabel() {
const c = this.categories.find((x) => String(x.id) === String(this.form.categoryId));
return c ? c.name : "选择类别";
}
},
methods: {
async bootstrap() {
await Promise.all([this.fetchUnits(), this.fetchCategories()]);
if (this.id)
this.loadDetail();
},
async fetchUnits() {
try {
const res = await get("/api/product-units");
this.units = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
} catch (_) {
}
},
async fetchCategories() {
try {
const res = await get("/api/product-categories");
this.categories = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
} catch (_) {
}
},
onPickUnit(e) {
const idx = Number(e.detail.value);
const u = this.units[idx];
this.form.unitId = u ? u.id : "";
},
onPickCategory(e) {
const idx = Number(e.detail.value);
const c = this.categories[idx];
this.form.categoryId = c ? c.id : "";
},
scan() {
uni.scanCode({ onlyFromCamera: false, success: (res) => {
this.form.barcode = res.result;
} });
},
async loadDetail() {
try {
const data = await get("/api/products/" + this.id);
Object.assign(this.form, {
name: data.name,
barcode: data.barcode,
brand: data.brand,
model: data.model,
spec: data.spec,
origin: data.origin,
categoryId: data.categoryId,
unitId: data.unitId,
stock: data.stock,
safeMin: data.safeMin,
safeMax: data.safeMax,
purchasePrice: data.purchasePrice,
retailPrice: data.retailPrice,
wholesalePrice: data.wholesalePrice,
bigClientPrice: data.bigClientPrice,
images: (data.images || []).map((i) => i.url || i)
});
} catch (_) {
}
},
validate() {
if (!this.form.name) {
uni.showToast({ title: "请填写名称", icon: "none" });
return false;
}
if (this.form.safeMin != null && this.form.safeMax != null && Number(this.form.safeMin) > Number(this.form.safeMax)) {
uni.showToast({ title: "安全库存区间不合法", icon: "none" });
return false;
}
return true;
},
buildPayload() {
const f = this.form;
return {
name: f.name,
barcode: f.barcode,
brand: f.brand,
model: f.model,
spec: f.spec,
origin: f.origin,
categoryId: f.categoryId || null,
unitId: f.unitId,
safeMin: f.safeMin,
safeMax: f.safeMax,
prices: {
purchasePrice: f.purchasePrice,
retailPrice: f.retailPrice,
wholesalePrice: f.wholesalePrice,
bigClientPrice: f.bigClientPrice
},
stock: f.stock,
images: f.images,
remark: f.remark
};
},
async save(goOn) {
if (!this.validate())
return;
const payload = this.buildPayload();
try {
if (this.id)
await put("/api/products/" + this.id, payload);
else
await post("/api/products", payload);
uni.showToast({ title: "保存成功", icon: "success" });
if (goOn && !this.id) {
this.form = { name: "", barcode: "", brand: "", model: "", spec: "", origin: "", categoryId: "", unitId: "", stock: null, safeMin: null, safeMax: null, purchasePrice: null, retailPrice: null, wholesalePrice: null, bigClientPrice: null, images: [], remark: "" };
} else {
setTimeout(() => uni.navigateBack(), 400);
}
} catch (e) {
uni.showToast({ title: "保存失败", icon: "none" });
}
}
}
};
function _sfc_render$f(_ctx, _cache, $props, $setup, $data, $options) {
const _component_ImageUploader = vue.resolveComponent("ImageUploader");
return vue.openBlock(), vue.createElementBlock("scroll-view", {
"scroll-y": "",
class: "page"
}, [
vue.createElementVNode("view", { class: "card" }, [
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "商品名称"),
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.form.name = $event),
placeholder: "必填"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.name,
void 0,
{ trim: true }
]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "条形码"),
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $data.form.barcode = $event),
placeholder: "可扫码或输入"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.barcode,
void 0,
{ trim: true }
]
]),
vue.createElementVNode("button", {
size: "mini",
onClick: _cache[2] || (_cache[2] = (...args) => $options.scan && $options.scan(...args))
}, "扫码")
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "品牌/型号/规格/产地")
]),
vue.createElementVNode("view", { class: "row" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.form.brand = $event),
placeholder: "品牌"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.brand,
void 0,
{ trim: true }
]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.form.model = $event),
placeholder: "型号"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.model,
void 0,
{ trim: true }
]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $data.form.spec = $event),
placeholder: "规格"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.spec,
void 0,
{ trim: true }
]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => $data.form.origin = $event),
placeholder: "产地"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.origin,
void 0,
{ trim: true }
]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("picker", {
mode: "selector",
range: $options.unitNames,
onChange: _cache[7] || (_cache[7] = (...args) => $options.onPickUnit && $options.onPickUnit(...args))
}, [
vue.createElementVNode(
"view",
{ class: "picker" },
"主单位:" + vue.toDisplayString($options.unitLabel),
1
/* TEXT */
)
], 40, ["range"]),
vue.createElementVNode("picker", {
mode: "selector",
range: $options.categoryNames,
onChange: _cache[8] || (_cache[8] = (...args) => $options.onPickCategory && $options.onPickCategory(...args))
}, [
vue.createElementVNode(
"view",
{ class: "picker" },
"类别:" + vue.toDisplayString($options.categoryLabel),
1
/* TEXT */
)
], 40, ["range"])
])
]),
vue.createElementVNode("view", { class: "card" }, [
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "库存与安全库存")
]),
vue.createElementVNode("view", { class: "row" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
type: "number",
"onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => $data.form.stock = $event),
placeholder: "当前库存"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.stock,
void 0,
{ number: true }
]
]),
vue.withDirectives(vue.createElementVNode(
"input",
{
type: "number",
"onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => $data.form.safeMin = $event),
placeholder: "安全库存下限"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.safeMin,
void 0,
{ number: true }
]
]),
vue.withDirectives(vue.createElementVNode(
"input",
{
type: "number",
"onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => $data.form.safeMax = $event),
placeholder: "安全库存上限"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.safeMax,
void 0,
{ number: true }
]
])
])
]),
vue.createElementVNode("view", { class: "card" }, [
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "价格(进价/零售/批发/大单)")
]),
vue.createElementVNode("view", { class: "row prices" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
type: "number",
"onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => $data.form.purchasePrice = $event),
placeholder: "进货价"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.purchasePrice,
void 0,
{ number: true }
]
]),
vue.withDirectives(vue.createElementVNode(
"input",
{
type: "number",
"onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => $data.form.retailPrice = $event),
placeholder: "零售价"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.retailPrice,
void 0,
{ number: true }
]
]),
vue.withDirectives(vue.createElementVNode(
"input",
{
type: "number",
"onUpdate:modelValue": _cache[14] || (_cache[14] = ($event) => $data.form.wholesalePrice = $event),
placeholder: "批发价"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.wholesalePrice,
void 0,
{ number: true }
]
]),
vue.withDirectives(vue.createElementVNode(
"input",
{
type: "number",
"onUpdate:modelValue": _cache[15] || (_cache[15] = ($event) => $data.form.bigClientPrice = $event),
placeholder: "大单价"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.bigClientPrice,
void 0,
{ number: true }
]
])
])
]),
vue.createElementVNode("view", { class: "card" }, [
vue.createElementVNode("text", { class: "label" }, "图片"),
vue.createVNode(_component_ImageUploader, {
modelValue: $data.form.images,
"onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => $data.form.images = $event),
formData: { ownerType: "product" }
}, null, 8, ["modelValue"])
]),
vue.createElementVNode("view", { class: "card" }, [
vue.createElementVNode("text", { class: "label" }, "备注"),
vue.withDirectives(vue.createElementVNode(
"textarea",
{
"onUpdate:modelValue": _cache[17] || (_cache[17] = ($event) => $data.form.remark = $event),
placeholder: "可选",
"auto-height": ""
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.remark,
void 0,
{ trim: true }
]
])
]),
vue.createElementVNode("view", { class: "fixed" }, [
vue.createElementVNode("button", {
type: "default",
onClick: _cache[18] || (_cache[18] = ($event) => $options.save(false))
}, "保存"),
vue.createElementVNode("button", {
type: "primary",
onClick: _cache[19] || (_cache[19] = ($event) => $options.save(true))
}, "保存并继续")
])
]);
}
const PagesProductForm = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["render", _sfc_render$f], ["__file", "D:/wx/PartsInquiry/frontend/pages/product/form.vue"]]);
const _sfc_main$f = {
data() {
return { name: "", list: [] };
},
onLoad() {
this.reload();
},
methods: {
async reload() {
try {
const res = await get("/api/product-categories");
this.list = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
} catch (_) {
}
},
async create() {
if (!this.name)
return;
await post("/api/product-categories", { name: this.name });
this.name = "";
this.reload();
},
async update(c) {
await put("/api/product-categories/" + c.id, { name: c.name });
uni.showToast({ title: "已保存", icon: "success" });
},
async remove(c) {
uni.showModal({ content: "确定删除该类别?", success: async (r) => {
if (!r.confirm)
return;
await del("/api/product-categories/" + c.id);
this.reload();
} });
}
}
};
function _sfc_render$e(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "toolbar" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.name = $event),
placeholder: "新类别名称"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.name,
void 0,
{ trim: true }
]
]),
vue.createElementVNode("button", {
size: "mini",
onClick: _cache[1] || (_cache[1] = (...args) => $options.create && $options.create(...args))
}, "新增")
]),
vue.createElementVNode("scroll-view", {
"scroll-y": "",
class: "list"
}, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.list, (c) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: c.id
}, [
vue.withDirectives(vue.createElementVNode("input", {
"onUpdate:modelValue": ($event) => c.name = $event
}, null, 8, ["onUpdate:modelValue"]), [
[
vue.vModelText,
c.name,
void 0,
{ trim: true }
]
]),
vue.createElementVNode("view", { class: "ops" }, [
vue.createElementVNode("button", {
size: "mini",
onClick: ($event) => $options.update(c)
}, "保存", 8, ["onClick"]),
vue.createElementVNode("button", {
size: "mini",
type: "warn",
onClick: ($event) => $options.remove(c)
}, "删除", 8, ["onClick"])
])
]);
}),
128
/* KEYED_FRAGMENT */
))
])
]);
}
const PagesProductCategories = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["render", _sfc_render$e], ["__file", "D:/wx/PartsInquiry/frontend/pages/product/categories.vue"]]);
const _sfc_main$e = {
data() {
return { name: "", list: [] };
},
onLoad() {
this.reload();
},
methods: {
async reload() {
try {
const res = await get("/api/product-units");
this.list = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
} catch (_) {
}
},
async create() {
if (!this.name)
return;
await post("/api/product-units", { name: this.name });
this.name = "";
this.reload();
},
async update(u) {
await put("/api/product-units/" + u.id, { name: u.name });
uni.showToast({ title: "已保存", icon: "success" });
},
async remove(u) {
uni.showModal({ content: "确定删除该单位?", success: async (r) => {
if (!r.confirm)
return;
await del("/api/product-units/" + u.id);
this.reload();
} });
}
}
};
function _sfc_render$d(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "toolbar" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.name = $event),
placeholder: "新单位名称"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.name,
void 0,
{ trim: true }
]
]),
vue.createElementVNode("button", {
size: "mini",
onClick: _cache[1] || (_cache[1] = (...args) => $options.create && $options.create(...args))
}, "新增")
]),
vue.createElementVNode("scroll-view", {
"scroll-y": "",
class: "list"
}, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.list, (u) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: u.id
}, [
vue.withDirectives(vue.createElementVNode("input", {
"onUpdate:modelValue": ($event) => u.name = $event
}, null, 8, ["onUpdate:modelValue"]), [
[
vue.vModelText,
u.name,
void 0,
{ trim: true }
]
]),
vue.createElementVNode("view", { class: "ops" }, [
vue.createElementVNode("button", {
size: "mini",
onClick: ($event) => $options.update(u)
}, "保存", 8, ["onClick"]),
vue.createElementVNode("button", {
size: "mini",
type: "warn",
onClick: ($event) => $options.remove(u)
}, "删除", 8, ["onClick"])
])
]);
}),
128
/* KEYED_FRAGMENT */
))
])
]);
}
const PagesProductUnits = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["render", _sfc_render$d], ["__file", "D:/wx/PartsInquiry/frontend/pages/product/units.vue"]]);
const _sfc_main$d = {
data() {
return { settings: { hideZeroStock: false, hidePurchasePrice: false } };
},
onLoad() {
this.load();
},
methods: {
async load() {
try {
const res = await get("/api/product-settings");
this.settings = { hideZeroStock: !!(res == null ? void 0 : res.hideZeroStock), hidePurchasePrice: !!(res == null ? void 0 : res.hidePurchasePrice) };
} catch (_) {
}
},
async update(key, val) {
const next = { ...this.settings, [key]: val };
this.settings = next;
try {
await put("/api/product-settings", next);
} catch (_) {
}
}
}
};
function _sfc_render$c(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "item" }, [
vue.createElementVNode("text", null, "隐藏零库存商品"),
vue.createElementVNode("switch", {
checked: $data.settings.hideZeroStock,
onChange: _cache[0] || (_cache[0] = (e) => $options.update("hideZeroStock", e.detail.value))
}, null, 40, ["checked"])
]),
vue.createElementVNode("view", { class: "item" }, [
vue.createElementVNode("text", null, "隐藏进货价"),
vue.createElementVNode("switch", {
checked: $data.settings.hidePurchasePrice,
onChange: _cache[1] || (_cache[1] = (e) => $options.update("hidePurchasePrice", e.detail.value))
}, null, 40, ["checked"])
])
]);
}
const PagesProductSettings = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["render", _sfc_render$c], ["__file", "D:/wx/PartsInquiry/frontend/pages/product/settings.vue"]]);
const _sfc_main$c = {
data() {
return { kw: "", debtOnly: false, customers: [] };
},
onLoad() {
this.search();
},
onShow() {
this.search();
},
methods: {
toggleDebtOnly() {
this.debtOnly = !this.debtOnly;
this.search();
},
async search() {
try {
const res = await get("/api/customers", { kw: this.kw, debtOnly: this.debtOnly, page: 1, size: 50 });
this.customers = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
createCustomer() {
uni.navigateTo({ url: "/pages/customer/form" });
},
select(c) {
const pages = getCurrentPages();
const prev = pages.length >= 2 ? pages[pages.length - 2] : null;
const vm = prev && prev.$vm ? prev.$vm : null;
if (vm && vm.order) {
vm.order.customerId = c.id;
vm.customerName = c.name;
}
uni.navigateBack();
},
openDetail(c) {
uni.navigateTo({ url: "/pages/customer/detail?id=" + c.id });
}
}
};
function _sfc_render$b(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "search" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.kw = $event),
placeholder: "搜索客户名称/电话",
onConfirm: _cache[1] || (_cache[1] = (...args) => $options.search && $options.search(...args))
},
null,
544
/* NEED_HYDRATION, NEED_PATCH */
), [
[vue.vModelText, $data.kw]
]),
vue.createElementVNode("button", {
size: "mini",
onClick: _cache[2] || (_cache[2] = (...args) => $options.search && $options.search(...args))
}, "搜索"),
vue.createElementVNode("button", {
size: "mini",
type: $data.debtOnly ? "primary" : "default",
onClick: _cache[3] || (_cache[3] = (...args) => $options.toggleDebtOnly && $options.toggleDebtOnly(...args))
}, "只看欠款", 8, ["type"])
]),
vue.createElementVNode("scroll-view", {
"scroll-y": "",
class: "list"
}, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.customers, (c) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: c.id,
onClick: ($event) => $options.openDetail(c)
}, [
vue.createElementVNode(
"view",
{ class: "name" },
vue.toDisplayString(c.name),
1
/* TEXT */
),
vue.createElementVNode("view", { class: "meta" }, [
vue.createTextVNode(
vue.toDisplayString(c.mobile || "—") + " ",
1
/* TEXT */
),
typeof c.receivable === "number" ? (vue.openBlock(), vue.createElementBlock(
"text",
{ key: 0 },
"|应收:¥ " + vue.toDisplayString(Number(c.receivable).toFixed(2)),
1
/* TEXT */
)) : vue.createCommentVNode("v-if", true)
])
], 8, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
))
]),
vue.createElementVNode("view", { class: "bottom" }, [
vue.createElementVNode("button", {
class: "primary",
onClick: _cache[4] || (_cache[4] = (...args) => $options.createCustomer && $options.createCustomer(...args))
}, "新增客户")
])
]);
}
const PagesCustomerSelect = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["render", _sfc_render$b], ["__file", "D:/wx/PartsInquiry/frontend/pages/customer/select.vue"]]);
const _sfc_main$b = {
data() {
return {
id: null,
form: { name: "", level: "", priceLevel: "retail", contactName: "", mobile: "", phone: "", address: "", arOpening: 0, remark: "" },
priceLevels: ["零售价", "批发价", "大单报价"],
priceLabels: ["零售价", "批发价", "大单报价"],
priceIdx: 0
};
},
onLoad(query) {
if (query && query.id) {
this.id = Number(query.id);
}
},
methods: {
onPriceChange(e) {
this.priceIdx = Number(e.detail.value);
this.form.priceLevel = this.priceLevels[this.priceIdx];
},
async save() {
if (!this.form.name)
return uni.showToast({ title: "请填写客户名称", icon: "none" });
try {
if (this.id)
await put(`/api/customers/${this.id}`, this.form);
else
await post("/api/customers", this.form);
uni.showToast({ title: "保存成功", icon: "success" });
setTimeout(() => uni.navigateBack(), 500);
} catch (e) {
uni.showToast({ title: (e == null ? void 0 : e.message) || "保存失败", icon: "none" });
}
}
}
};
function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "客户名称"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.form.name = $event),
placeholder: "必填"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.name]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "客户等级"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $data.form.level = $event),
placeholder: "可选,如 VIP/A/B"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.level]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "售价档位"),
vue.createElementVNode("picker", {
range: $data.priceLabels,
value: $data.priceIdx,
onChange: _cache[2] || (_cache[2] = (...args) => $options.onPriceChange && $options.onPriceChange(...args))
}, [
vue.createElementVNode(
"view",
{ class: "value" },
vue.toDisplayString($data.priceLabels[$data.priceIdx]),
1
/* TEXT */
)
], 40, ["range", "value"])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "联系人"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.form.contactName = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.contactName]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "手机"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.form.mobile = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.mobile]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "电话"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $data.form.phone = $event),
placeholder: "可选(座机)"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.phone]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "送货地址"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => $data.form.address = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.address]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "初始应收"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
type: "digit",
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $data.form.arOpening = $event),
placeholder: "默认 0.00"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.arOpening,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode("view", { class: "textarea" }, [
vue.withDirectives(vue.createElementVNode(
"textarea",
{
"onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => $data.form.remark = $event),
maxlength: "200",
placeholder: "备注最多200字"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.remark]
])
]),
vue.createElementVNode("view", { class: "bottom" }, [
vue.createElementVNode("button", {
class: "primary",
onClick: _cache[9] || (_cache[9] = (...args) => $options.save && $options.save(...args))
}, "保存")
])
]);
}
const PagesCustomerForm = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["render", _sfc_render$a], ["__file", "D:/wx/PartsInquiry/frontend/pages/customer/form.vue"]]);
const _sfc_main$a = {
data() {
return { id: null, d: {}, editing: false, form: { name: "", contactName: "", mobile: "", phone: "", address: "", level: "", priceLevel: "零售价", arOpening: 0, remark: "" }, priceLevels: ["零售价", "批发价", "大单报价"], priceLabels: ["零售价", "批发价", "大单报价"], priceIdx: 0 };
},
onLoad(q) {
if (q && q.id) {
this.id = Number(q.id);
this.fetch();
}
},
methods: {
async fetch() {
try {
this.d = await get(`/api/customers/${this.id}`);
this.form = {
name: this.d.name || "",
contactName: this.d.contactName || "",
mobile: this.d.mobile || "",
phone: this.d.phone || "",
address: this.d.address || "",
level: this.d.level || "",
priceLevel: this.d.priceLevel || "retail",
arOpening: Number(this.d.arOpening || 0),
remark: this.d.remark || ""
};
const idx = this.priceLevels.indexOf(this.form.priceLevel);
this.priceIdx = idx >= 0 ? idx : 0;
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
toggleEdit() {
this.editing = !this.editing;
},
onPriceChange(e) {
this.priceIdx = Number(e.detail.value);
this.form.priceLevel = this.priceLevels[this.priceIdx];
},
choose() {
const pages = getCurrentPages();
let targetIdx = -1;
for (let i = pages.length - 2; i >= 0; i--) {
const vm = pages[i] && pages[i].$vm ? pages[i].$vm : null;
if (vm && vm.order) {
vm.order.customerId = this.d.id;
vm.customerName = this.d.name;
targetIdx = i;
break;
}
}
if (targetIdx >= 0) {
const delta = pages.length - 1 - targetIdx;
uni.navigateBack({ delta });
} else {
uni.navigateBack();
}
},
async save() {
if (!this.form.name)
return uni.showToast({ title: "请填写客户名称", icon: "none" });
try {
await put(`/api/customers/${this.id}`, this.form);
uni.showToast({ title: "已保存", icon: "success" });
this.editing = false;
await this.fetch();
} catch (e) {
uni.showToast({ title: (e == null ? void 0 : e.message) || "保存失败", icon: "none" });
}
}
}
};
function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "card" }, [
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "名称"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
vue.toDisplayString($data.d.name),
1
/* TEXT */
)) : vue.withDirectives((vue.openBlock(), vue.createElementBlock(
"input",
{
key: 1,
class: "value-input",
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.form.name = $event),
placeholder: "必填"
},
null,
512
/* NEED_PATCH */
)), [
[vue.vModelText, $data.form.name]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "联系人"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
vue.toDisplayString($data.d.contactName || "—"),
1
/* TEXT */
)) : vue.withDirectives((vue.openBlock(), vue.createElementBlock(
"input",
{
key: 1,
class: "value-input",
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $data.form.contactName = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
)), [
[vue.vModelText, $data.form.contactName]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "手机"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
vue.toDisplayString($data.d.mobile || "—"),
1
/* TEXT */
)) : vue.withDirectives((vue.openBlock(), vue.createElementBlock(
"input",
{
key: 1,
class: "value-input",
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $data.form.mobile = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
)), [
[vue.vModelText, $data.form.mobile]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "电话"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
vue.toDisplayString($data.d.phone || "—"),
1
/* TEXT */
)) : vue.withDirectives((vue.openBlock(), vue.createElementBlock(
"input",
{
key: 1,
class: "value-input",
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.form.phone = $event),
placeholder: "可选(座机)"
},
null,
512
/* NEED_PATCH */
)), [
[vue.vModelText, $data.form.phone]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "地址"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
vue.toDisplayString($data.d.address || "—"),
1
/* TEXT */
)) : vue.withDirectives((vue.openBlock(), vue.createElementBlock(
"input",
{
key: 1,
class: "value-input",
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.form.address = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
)), [
[vue.vModelText, $data.form.address]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "等级"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
vue.toDisplayString($data.d.level || "—"),
1
/* TEXT */
)) : vue.withDirectives((vue.openBlock(), vue.createElementBlock(
"input",
{
key: 1,
class: "value-input",
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $data.form.level = $event),
placeholder: "可选,如 VIP/A/B"
},
null,
512
/* NEED_PATCH */
)), [
[vue.vModelText, $data.form.level]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "售价档位"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
vue.toDisplayString($data.d.priceLevel),
1
/* TEXT */
)) : (vue.openBlock(), vue.createElementBlock("picker", {
key: 1,
range: $data.priceLabels,
value: $data.priceIdx,
onChange: _cache[6] || (_cache[6] = (...args) => $options.onPriceChange && $options.onPriceChange(...args))
}, [
vue.createElementVNode(
"view",
{ class: "value" },
vue.toDisplayString($data.priceLabels[$data.priceIdx]),
1
/* TEXT */
)
], 40, ["range", "value"]))
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "初始应收"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
"¥ " + vue.toDisplayString(Number($data.d.arOpening || 0).toFixed(2)),
1
/* TEXT */
)) : vue.withDirectives((vue.openBlock(), vue.createElementBlock(
"input",
{
key: 1,
class: "value-input",
type: "digit",
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $data.form.arOpening = $event),
placeholder: "0.00"
},
null,
512
/* NEED_PATCH */
)), [
[
vue.vModelText,
$data.form.arOpening,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "当前应收"),
vue.createElementVNode(
"text",
{ class: "value emp" },
"¥ " + vue.toDisplayString(Number($data.d.receivable || 0).toFixed(2)),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "备注"),
!$data.editing ? (vue.openBlock(), vue.createElementBlock(
"text",
{
key: 0,
class: "value"
},
vue.toDisplayString($data.d.remark || "—"),
1
/* TEXT */
)) : vue.withDirectives((vue.openBlock(), vue.createElementBlock(
"input",
{
key: 1,
class: "value-input",
"onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => $data.form.remark = $event),
placeholder: "—"
},
null,
512
/* NEED_PATCH */
)), [
[vue.vModelText, $data.form.remark]
])
])
]),
vue.createElementVNode("view", { class: "bottom" }, [
vue.createElementVNode(
"button",
{
class: "ghost",
onClick: _cache[9] || (_cache[9] = (...args) => $options.toggleEdit && $options.toggleEdit(...args))
},
vue.toDisplayString($data.editing ? "取消" : "编辑"),
1
/* TEXT */
),
$data.editing ? (vue.openBlock(), vue.createElementBlock("button", {
key: 0,
class: "primary",
onClick: _cache[10] || (_cache[10] = (...args) => $options.save && $options.save(...args))
}, "保存")) : (vue.openBlock(), vue.createElementBlock("button", {
key: 1,
class: "primary",
onClick: _cache[11] || (_cache[11] = (...args) => $options.choose && $options.choose(...args))
}, "选择此客户"))
])
]);
}
const PagesCustomerDetail = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["render", _sfc_render$9], ["__file", "D:/wx/PartsInquiry/frontend/pages/customer/detail.vue"]]);
const _sfc_main$9 = {
data() {
return { kw: "", debtOnly: false, suppliers: [] };
},
onLoad() {
this.search();
},
methods: {
toggleDebtOnly() {
this.debtOnly = !this.debtOnly;
this.search();
},
async search() {
try {
const res = await get("/api/suppliers", { kw: this.kw, debtOnly: this.debtOnly, page: 1, size: 50 });
this.suppliers = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
createSupplier() {
uni.navigateTo({ url: "/pages/supplier/form" });
},
select(s) {
const opener = getCurrentPages()[getCurrentPages().length - 2];
if (opener && opener.$vm) {
opener.$vm.order.supplierId = s.id;
opener.$vm.supplierName = s.name;
}
uni.navigateBack();
}
}
};
function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "search" }, [
vue.withDirectives(vue.createElementVNode(
"input",
{
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.kw = $event),
placeholder: "搜索供应商名称/电话",
onConfirm: _cache[1] || (_cache[1] = (...args) => $options.search && $options.search(...args))
},
null,
544
/* NEED_HYDRATION, NEED_PATCH */
), [
[vue.vModelText, $data.kw]
]),
vue.createElementVNode("button", {
size: "mini",
onClick: _cache[2] || (_cache[2] = (...args) => $options.search && $options.search(...args))
}, "搜索"),
vue.createElementVNode("button", {
size: "mini",
type: $data.debtOnly ? "primary" : "default",
onClick: _cache[3] || (_cache[3] = (...args) => $options.toggleDebtOnly && $options.toggleDebtOnly(...args))
}, "只看欠款", 8, ["type"])
]),
vue.createElementVNode("scroll-view", {
"scroll-y": "",
class: "list"
}, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.suppliers, (s) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: s.id,
onClick: ($event) => $options.select(s)
}, [
vue.createElementVNode(
"view",
{ class: "name" },
vue.toDisplayString(s.name),
1
/* TEXT */
),
vue.createElementVNode("view", { class: "meta" }, [
vue.createTextVNode(
vue.toDisplayString(s.mobile || "—") + " ",
1
/* TEXT */
),
typeof s.apPayable === "number" ? (vue.openBlock(), vue.createElementBlock(
"text",
{ key: 0 },
"|应付:¥ " + vue.toDisplayString(Number(s.apPayable).toFixed(2)),
1
/* TEXT */
)) : vue.createCommentVNode("v-if", true)
])
], 8, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
))
]),
vue.createElementVNode("view", { class: "bottom" }, [
vue.createElementVNode("button", {
class: "primary",
onClick: _cache[4] || (_cache[4] = (...args) => $options.createSupplier && $options.createSupplier(...args))
}, "新增供应商")
])
]);
}
const PagesSupplierSelect = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["render", _sfc_render$8], ["__file", "D:/wx/PartsInquiry/frontend/pages/supplier/select.vue"]]);
const _sfc_main$8 = {
data() {
return {
id: null,
form: { name: "", contactName: "", mobile: "", phone: "", address: "", apOpening: 0, apPayable: 0, remark: "" }
};
},
onLoad(query) {
if (query && query.id) {
this.id = Number(query.id);
}
},
methods: {
async save() {
if (!this.form.name)
return uni.showToast({ title: "请填写供应商名称", icon: "none" });
try {
if (this.id)
await put(`/api/suppliers/${this.id}`, this.form);
else
await post("/api/suppliers", this.form);
uni.showToast({ title: "保存成功", icon: "success" });
setTimeout(() => uni.navigateBack(), 500);
} catch (e) {
uni.showToast({ title: (e == null ? void 0 : e.message) || "保存失败", icon: "none" });
}
}
}
};
function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "供应商名称"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.form.name = $event),
placeholder: "必填"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.name]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "联系人"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $data.form.contactName = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.contactName]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "手机"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $data.form.mobile = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.mobile]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "电话"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.form.phone = $event),
placeholder: "可选(座机)"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.phone]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "经营地址"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.form.address = $event),
placeholder: "可选"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.address]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "初始应付款"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
type: "digit",
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $data.form.apOpening = $event),
placeholder: "默认 0.00"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.apOpening,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "应付款"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "value",
type: "digit",
"onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => $data.form.apPayable = $event),
placeholder: "默认 0.00"
},
null,
512
/* NEED_PATCH */
), [
[
vue.vModelText,
$data.form.apPayable,
void 0,
{ number: true }
]
])
]),
vue.createElementVNode("view", { class: "textarea" }, [
vue.withDirectives(vue.createElementVNode(
"textarea",
{
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $data.form.remark = $event),
maxlength: "200",
placeholder: "备注最多200字"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.remark]
])
]),
vue.createElementVNode("view", { class: "bottom" }, [
vue.createElementVNode("button", {
class: "primary",
onClick: _cache[8] || (_cache[8] = (...args) => $options.save && $options.save(...args))
}, "保存")
])
]);
}
const PagesSupplierForm = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$7], ["__file", "D:/wx/PartsInquiry/frontend/pages/supplier/form.vue"]]);
const TYPE_MAP = { cash: "现金", bank: "银行", alipay: "支付宝", wechat: "微信", other: "其他" };
const _sfc_main$7 = {
data() {
return { accounts: [], mode: "view" };
},
async onLoad(q) {
this.mode = q && q.mode || "view";
try {
const res = await get("/api/accounts");
this.accounts = Array.isArray(res) ? res : (res == null ? void 0 : res.list) || [];
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
methods: {
select(a) {
if (this.mode === "pick") {
const opener = getCurrentPages()[getCurrentPages().length - 2];
if (opener && opener.$vm) {
opener.$vm.selectedAccountId = a.id;
opener.$vm.selectedAccountName = a.name;
}
uni.navigateBack();
} else {
uni.navigateTo({ url: `/pages/account/ledger?id=${a.id}` });
}
},
create() {
uni.navigateTo({ url: "/pages/account/form" });
},
typeLabel(t) {
return TYPE_MAP[t] || t;
}
}
};
function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("scroll-view", {
"scroll-y": "",
class: "list"
}, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.accounts, (a) => {
var _a;
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: a.id,
onClick: ($event) => $options.select(a)
}, [
vue.createElementVNode(
"view",
{ class: "name" },
vue.toDisplayString(a.name),
1
/* TEXT */
),
vue.createElementVNode(
"view",
{ class: "meta" },
vue.toDisplayString($options.typeLabel(a.type)) + " · 余额:" + vue.toDisplayString(((_a = a.balance) == null ? void 0 : _a.toFixed) ? a.balance.toFixed(2) : a.balance),
1
/* TEXT */
)
], 8, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
))
]),
vue.createElementVNode("view", {
class: "fab",
onClick: _cache[0] || (_cache[0] = (...args) => $options.create && $options.create(...args))
}, "")
]);
}
const PagesAccountSelect = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$6], ["__file", "D:/wx/PartsInquiry/frontend/pages/account/select.vue"]]);
const _sfc_main$6 = {
data() {
return { accountId: null, startDate: "", endDate: "", list: [], opening: 0, income: 0, expense: 0, ending: 0 };
},
onLoad(query) {
this.accountId = Number(query && query.id);
this.quickInit();
this.load();
},
methods: {
quickInit() {
const now = /* @__PURE__ */ new Date();
const y = now.getFullYear(), m = now.getMonth() + 1;
this.startDate = `${y}-${String(m).padStart(2, "0")}-01`;
const lastDay = new Date(y, m, 0).getDate();
this.endDate = `${y}-${String(m).padStart(2, "0")}-${String(lastDay).padStart(2, "0")}`;
},
async load(page = 1, size = 50) {
try {
const res = await get(`/api/accounts/${this.accountId}/ledger`, { startDate: this.startDate, endDate: this.endDate, page, size });
this.list = res && res.list || [];
this.opening = Number(res && res.opening || 0);
this.income = Number(res && res.income || 0);
this.expense = Number(res && res.expense || 0);
this.ending = Number(res && res.ending || 0);
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
fmt(v) {
return (typeof v === "number" ? v : Number(v || 0)).toFixed(2);
},
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())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
} catch (e) {
return s;
}
}
}
};
function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "filters" }, [
vue.createElementVNode("picker", {
mode: "date",
value: $data.startDate,
onChange: _cache[0] || (_cache[0] = (e) => {
$data.startDate = e.detail.value;
$options.load();
})
}, [
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "开始"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($data.startDate || "—"),
1
/* TEXT */
)
])
], 40, ["value"]),
vue.createElementVNode("picker", {
mode: "date",
value: $data.endDate,
onChange: _cache[1] || (_cache[1] = (e) => {
$data.endDate = e.detail.value;
$options.load();
})
}, [
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "结束"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($data.endDate || "—"),
1
/* TEXT */
)
])
], 40, ["value"])
]),
vue.createElementVNode("view", { class: "summary" }, [
vue.createElementVNode("view", { class: "sum-item" }, [
vue.createElementVNode("text", { class: "k" }, "收入"),
vue.createElementVNode(
"text",
{ class: "v" },
vue.toDisplayString($options.fmt($data.income)),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "sum-item" }, [
vue.createElementVNode("text", { class: "k" }, "支出"),
vue.createElementVNode(
"text",
{ class: "v" },
vue.toDisplayString($options.fmt($data.expense)),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "sum-item" }, [
vue.createElementVNode("text", { class: "k" }, "期初"),
vue.createElementVNode(
"text",
{ class: "v" },
vue.toDisplayString($options.fmt($data.opening)),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "sum-item" }, [
vue.createElementVNode("text", { class: "k" }, "期末"),
vue.createElementVNode(
"text",
{ class: "v" },
vue.toDisplayString($options.fmt($data.ending)),
1
/* TEXT */
)
])
]),
vue.createElementVNode("scroll-view", {
"scroll-y": "",
class: "list"
}, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.list, (it) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: it.id
}, [
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode(
"text",
{ class: "title" },
vue.toDisplayString(it.src === "other" ? it.category || "其他" : it.remark || "收付款"),
1
/* TEXT */
),
vue.createElementVNode(
"text",
{
class: vue.normalizeClass(["amount", { in: it.direction === "in", out: it.direction === "out" }])
},
vue.toDisplayString(it.direction === "in" ? "+" : "-") + vue.toDisplayString($options.fmt(it.amount)),
3
/* TEXT, CLASS */
)
]),
vue.createElementVNode(
"view",
{ class: "meta" },
vue.toDisplayString($options.formatDate(it.tx_time || it.txTime)) + " · " + vue.toDisplayString(it.remark || "-"),
1
/* TEXT */
)
]);
}),
128
/* KEYED_FRAGMENT */
))
])
]);
}
const PagesAccountLedger = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$5], ["__file", "D:/wx/PartsInquiry/frontend/pages/account/ledger.vue"]]);
const _sfc_main$5 = {
data() {
return {
id: null,
form: { name: "", type: "cash", bankName: "", bankAccount: "", openingBalance: "" },
showType: false,
types: [
{ key: "cash", name: "现金" },
{ key: "bank", name: "银行存款" },
{ key: "wechat", name: "微信" },
{ key: "alipay", name: "支付宝" },
{ key: "other", name: "其他" }
]
};
},
onLoad(q) {
this.id = q && q.id ? Number(q.id) : null;
if (this.id)
this.load();
},
methods: {
typeLabel(t) {
const m = { cash: "现金", bank: "银行存款", wechat: "微信", alipay: "支付宝", other: "其他" };
return m[t] || t;
},
async load() {
try {
const list = await get("/api/accounts");
const a = (Array.isArray(list) ? list : (list == null ? void 0 : list.list) || []).find((x) => x.id == this.id);
if (a) {
this.form = { name: a.name, type: a.type, bankName: a.bank_name || a.bankName || "", bankAccount: a.bank_account || a.bankAccount || "", openingBalance: "" };
}
} catch (e) {
}
},
async save() {
if (!this.form.name) {
uni.showToast({ title: "请输入名称", icon: "none" });
return;
}
try {
const body = { ...this.form, openingBalance: Number(this.form.openingBalance || 0) };
if (this.id)
await put(`/api/accounts/${this.id}`, body);
else
await post("/api/accounts", { ...body, status: 1 });
uni.showToast({ title: "已保存", icon: "success" });
setTimeout(() => uni.navigateBack(), 300);
} catch (e) {
uni.showToast({ title: "保存失败", icon: "none" });
}
}
}
};
function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
const _component_uni_popup = vue.resolveComponent("uni-popup");
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createElementVNode("view", { class: "form" }, [
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "账户名称"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "input",
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.form.name = $event),
placeholder: "必填"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.name]
])
]),
vue.createElementVNode("view", {
class: "field",
onClick: _cache[1] || (_cache[1] = ($event) => $data.showType = true)
}, [
vue.createElementVNode("text", { class: "label" }, "账户类型"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($options.typeLabel($data.form.type)),
1
/* TEXT */
)
]),
$data.form.type === "bank" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 0,
class: "field"
}, [
vue.createElementVNode("text", { class: "label" }, "银行名称"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "input",
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $data.form.bankName = $event),
placeholder: "选填"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.bankName]
])
])) : vue.createCommentVNode("v-if", true),
$data.form.type === "bank" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 1,
class: "field"
}, [
vue.createElementVNode("text", { class: "label" }, "银行账号"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "input",
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.form.bankAccount = $event),
placeholder: "选填"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.bankAccount]
])
])) : vue.createCommentVNode("v-if", true),
vue.createElementVNode("view", { class: "field" }, [
vue.createElementVNode("text", { class: "label" }, "当前余额"),
vue.withDirectives(vue.createElementVNode(
"input",
{
class: "input",
type: "number",
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.form.openingBalance = $event),
placeholder: "0.00"
},
null,
512
/* NEED_PATCH */
), [
[vue.vModelText, $data.form.openingBalance]
])
])
]),
vue.createElementVNode("view", { class: "actions" }, [
vue.createElementVNode("button", {
class: "primary",
onClick: _cache[5] || (_cache[5] = (...args) => $options.save && $options.save(...args))
}, "保存")
]),
vue.createVNode(_component_uni_popup, {
ref: "popup",
type: "bottom",
modelValue: $data.showType,
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $data.showType = $event)
}, {
default: vue.withCtx(() => [
vue.createElementVNode("view", { class: "sheet" }, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.types, (t) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "sheet-item",
key: t.key,
onClick: ($event) => {
$data.form.type = t.key;
$data.showType = false;
}
}, vue.toDisplayString(t.name), 9, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
)),
vue.createElementVNode("view", {
class: "sheet-cancel",
onClick: _cache[6] || (_cache[6] = ($event) => $data.showType = false)
}, "取消")
])
]),
_: 1
/* STABLE */
}, 8, ["modelValue"])
]);
}
const PagesAccountForm = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$4], ["__file", "D:/wx/PartsInquiry/frontend/pages/account/form.vue"]]);
const API_OF = {
sale: "/api/orders",
purchase: "/api/purchase-orders",
collect: "/api/payments",
fund: "/api/other-transactions",
stock: "/api/inventories/logs"
};
const _sfc_main$4 = {
data() {
return {
biz: "sale",
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.items.reduce((s, it) => s + Number(it.amount || 0), 0);
}
},
onLoad() {
try {
formatAppLog("log", "at pages/detail/index.vue:92", "[detail] onLoad route = pages/detail/index");
} catch (e) {
}
this.computeRange();
this.reload();
},
methods: {
switchBiz(k) {
if (this.biz === k)
return;
this.biz = k;
this.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 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 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) {
uni.showToast({ title: "加载失败", icon: "none" });
} finally {
this.loading = false;
}
},
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);
}
},
onCreate() {
if (this.biz === "sale") {
uni.switchTab({ url: "/pages/order/create" });
return;
}
uni.showToast({ title: "该类型创建页待实现", icon: "none" });
},
openDetail(it) {
uni.showToast({ title: "详情开发中", icon: "none" });
}
}
};
function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
vue.createCommentVNode(" 顶部时间维度筛选 "),
vue.createElementVNode("view", { class: "seg" }, [
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["seg-item", $data.range === "custom" && "active"]),
onClick: _cache[0] || (_cache[0] = ($event) => $options.switchRange("custom"))
},
"自定义",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["seg-item", $data.range === "week" && "active"]),
onClick: _cache[1] || (_cache[1] = ($event) => $options.switchRange("week"))
},
"本周",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["seg-item", $data.range === "today" && "active"]),
onClick: _cache[2] || (_cache[2] = ($event) => $options.switchRange("today"))
},
"今日",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["seg-item", $data.range === "month" && "active"]),
onClick: _cache[3] || (_cache[3] = ($event) => $options.switchRange("month"))
},
"本月",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["seg-item", $data.range === "year" && "active"]),
onClick: _cache[4] || (_cache[4] = ($event) => $options.switchRange("year"))
},
"本年",
2
/* CLASS */
)
]),
vue.createCommentVNode(" 业务类型侧边切换:销售/进货/收款/资金/盘点 "),
vue.createElementVNode("view", { class: "content" }, [
vue.createElementVNode("view", { class: "biz-tabs" }, [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.bizList, (b) => {
return vue.openBlock(), vue.createElementBlock("view", {
key: b.key,
class: vue.normalizeClass(["biz", $data.biz === b.key && "active"]),
onClick: ($event) => $options.switchBiz(b.key)
}, vue.toDisplayString(b.name), 11, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
))
]),
vue.createElementVNode("view", { class: "panel" }, [
vue.createCommentVNode(" 搜索框与期间显示、总额 "),
vue.createElementVNode("view", { class: "toolbar" }, [
vue.createElementVNode("view", { class: "search" }, [
vue.withDirectives(vue.createElementVNode("input", {
class: "search-input",
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $data.query.kw = $event),
placeholder: $options.placeholder,
onConfirm: _cache[6] || (_cache[6] = (...args) => $options.reload && $options.reload(...args))
}, null, 40, ["placeholder"]), [
[
vue.vModelText,
$data.query.kw,
void 0,
{ trim: true }
]
])
]),
vue.createElementVNode(
"view",
{ class: "period" },
vue.toDisplayString($options.periodLabel),
1
/* TEXT */
),
vue.createElementVNode("button", {
size: "mini",
onClick: _cache[7] || (_cache[7] = (...args) => $options.reload && $options.reload(...args))
}, "查询")
]),
vue.createElementVNode(
"view",
{ class: "total" },
"合计:¥" + vue.toDisplayString($options.totalAmount.toFixed(2)),
1
/* TEXT */
),
vue.createCommentVNode(" 列表 "),
vue.createElementVNode(
"scroll-view",
{
"scroll-y": "",
class: "list",
onScrolltolower: _cache[8] || (_cache[8] = (...args) => $options.loadMore && $options.loadMore(...args))
},
[
$data.items.length ? (vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
{ key: 0 },
vue.renderList($data.items, (it) => {
return vue.openBlock(), vue.createElementBlock("view", {
class: "item",
key: it.id,
onClick: ($event) => $options.openDetail(it)
}, [
vue.createElementVNode("view", { class: "item-left" }, [
vue.createElementVNode(
"view",
{ class: "date" },
vue.toDisplayString($options.formatDate(it.orderTime || it.txTime || it.createdAt)),
1
/* TEXT */
),
vue.createElementVNode(
"view",
{ class: "name" },
vue.toDisplayString(it.customerName || it.supplierName || it.accountName || it.remark || "-"),
1
/* TEXT */
),
vue.createElementVNode(
"view",
{ class: "no" },
vue.toDisplayString(it.orderNo || it.code || it.id),
1
/* TEXT */
)
]),
vue.createElementVNode(
"view",
{ class: "amount" },
"¥ " + vue.toDisplayString((it.amount || 0).toFixed(2)),
1
/* TEXT */
),
vue.createElementVNode("view", { class: "arrow" }, "")
], 8, ["onClick"]);
}),
128
/* KEYED_FRAGMENT */
)) : (vue.openBlock(), vue.createElementBlock("view", {
key: 1,
class: "empty"
}, "暂无数据"))
],
32
/* NEED_HYDRATION */
),
vue.createCommentVNode(" 右下角新增按钮:根据业务类型跳转对应开单页或创建页 "),
vue.createElementVNode("view", {
class: "fab",
onClick: _cache[9] || (_cache[9] = (...args) => $options.onCreate && $options.onCreate(...args))
}, "")
])
])
]);
}
const PagesDetailIndex = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$3], ["__file", "D:/wx/PartsInquiry/frontend/pages/detail/index.vue"]]);
const _sfc_main$3 = {
data() {
return {
avatarUrl: "/static/logo.png",
shopName: "我的店铺",
mobile: ""
};
},
onLoad() {
this.fetchProfile();
},
computed: {
mobileDisplay() {
const m = String(this.mobile || "");
return m.length === 11 ? m.slice(0, 3) + "****" + m.slice(7) : m || "未绑定手机号";
}
},
methods: {
async fetchProfile() {
try {
await get("/api/dashboard/overview");
} catch (e) {
}
try {
const storeName = uni.getStorageSync("SHOP_NAME") || "";
const avatar = uni.getStorageSync("USER_AVATAR") || "";
const phone = uni.getStorageSync("USER_MOBILE") || "";
if (storeName)
this.shopName = storeName;
if (avatar)
this.avatarUrl = avatar;
this.mobile = phone;
} catch (e) {
}
},
onAvatarError() {
this.avatarUrl = "/static/logo.png";
},
goVip() {
uni.showToast({ title: "VIP会员开发中", icon: "none" });
},
goMyOrders() {
uni.switchTab({ url: "/pages/detail/index" });
},
goSupplier() {
uni.navigateTo({ url: "/pages/supplier/select" });
},
goCustomer() {
uni.navigateTo({ url: "/pages/customer/select" });
},
goCustomerQuote() {
uni.showToast({ title: "客户报价(开发中)", icon: "none" });
},
goShop() {
uni.showToast({ title: "店铺管理(开发中)", icon: "none" });
},
editProfile() {
uni.showToast({ title: "账号与安全(开发中)", icon: "none" });
},
goProductSettings() {
uni.navigateTo({ url: "/pages/product/settings" });
},
goSystemParams() {
uni.showToast({ title: "系统参数(开发中)", icon: "none" });
},
goAbout() {
uni.navigateTo({ url: "/pages/my/about" });
},
logout() {
try {
uni.removeStorageSync("TOKEN");
uni.removeStorageSync("USER_AVATAR");
uni.removeStorageSync("USER_NAME");
uni.removeStorageSync("USER_MOBILE");
uni.removeStorageSync("SHOP_NAME");
uni.showToast({ title: "已退出", icon: "none" });
setTimeout(() => {
uni.reLaunch({ url: "/pages/index/index" });
}, 300);
} catch (e) {
uni.reLaunch({ url: "/pages/index/index" });
}
}
}
};
function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "me" }, [
vue.createElementVNode("view", { class: "card user" }, [
vue.createElementVNode("image", {
class: "avatar",
src: $data.avatarUrl,
mode: "aspectFill",
onError: _cache[0] || (_cache[0] = (...args) => $options.onAvatarError && $options.onAvatarError(...args))
}, null, 40, ["src"]),
vue.createElementVNode("view", { class: "meta" }, [
vue.createElementVNode(
"text",
{ class: "name" },
vue.toDisplayString($data.shopName),
1
/* TEXT */
),
vue.createElementVNode(
"text",
{ class: "phone" },
vue.toDisplayString($options.mobileDisplay),
1
/* TEXT */
),
vue.createElementVNode("text", { class: "role" }, "老板")
])
]),
vue.createElementVNode("view", { class: "group" }, [
vue.createElementVNode("view", { class: "group-title" }, "会员与订单"),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[1] || (_cache[1] = (...args) => $options.goVip && $options.goVip(...args))
}, [
vue.createElementVNode("text", null, "VIP会员"),
vue.createElementVNode("text", { class: "arrow" }, "")
]),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[2] || (_cache[2] = (...args) => $options.goMyOrders && $options.goMyOrders(...args))
}, [
vue.createElementVNode("text", null, "我的订单"),
vue.createElementVNode("text", { class: "arrow" }, "")
])
]),
vue.createElementVNode("view", { class: "group" }, [
vue.createElementVNode("view", { class: "group-title" }, "基础管理"),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[3] || (_cache[3] = (...args) => $options.goSupplier && $options.goSupplier(...args))
}, [
vue.createElementVNode("text", null, "供应商管理"),
vue.createElementVNode("text", { class: "arrow" }, "")
]),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[4] || (_cache[4] = (...args) => $options.goCustomer && $options.goCustomer(...args))
}, [
vue.createElementVNode("text", null, "客户管理"),
vue.createElementVNode("text", { class: "arrow" }, "")
]),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[5] || (_cache[5] = (...args) => $options.goCustomerQuote && $options.goCustomerQuote(...args))
}, [
vue.createElementVNode("text", null, "客户报价"),
vue.createElementVNode("text", { class: "arrow" }, "")
]),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[6] || (_cache[6] = (...args) => $options.goShop && $options.goShop(...args))
}, [
vue.createElementVNode("text", null, "店铺管理"),
vue.createElementVNode("text", { class: "arrow" }, "")
])
]),
vue.createElementVNode("view", { class: "group" }, [
vue.createElementVNode("view", { class: "group-title" }, "设置中心"),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[7] || (_cache[7] = (...args) => $options.editProfile && $options.editProfile(...args))
}, [
vue.createElementVNode("text", null, "账号与安全"),
vue.createElementVNode("text", { class: "desc" }, "修改头像、姓名、密码"),
vue.createElementVNode("text", { class: "arrow" }, "")
]),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[8] || (_cache[8] = (...args) => $options.goProductSettings && $options.goProductSettings(...args))
}, [
vue.createElementVNode("text", null, "商品设置"),
vue.createElementVNode("text", { class: "arrow" }, "")
]),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[9] || (_cache[9] = (...args) => $options.goSystemParams && $options.goSystemParams(...args))
}, [
vue.createElementVNode("text", null, "系统参数"),
vue.createElementVNode("text", { class: "desc" }, "低价提示、默认收款、单行折扣等"),
vue.createElementVNode("text", { class: "arrow" }, "")
]),
vue.createElementVNode("view", {
class: "cell",
onClick: _cache[10] || (_cache[10] = (...args) => $options.goAbout && $options.goAbout(...args))
}, [
vue.createElementVNode("text", null, "关于与协议"),
vue.createElementVNode("text", { class: "arrow" }, "")
]),
vue.createElementVNode("view", {
class: "cell danger",
onClick: _cache[11] || (_cache[11] = (...args) => $options.logout && $options.logout(...args))
}, [
vue.createElementVNode("text", null, "退出登录")
])
])
]);
}
const PagesMyIndex = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2], ["__file", "D:/wx/PartsInquiry/frontend/pages/my/index.vue"]]);
const _sfc_main$2 = {
methods: {
openPolicy() {
uni.showModal({ title: "隐私协议", content: "隐私协议(静态占位)", showCancel: false });
},
openTerms() {
uni.showModal({ title: "用户协议", content: "用户协议(静态占位)", showCancel: false });
},
openComplaint() {
uni.showToast({ title: "暂未开通", icon: "none" });
}
}
};
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "about" }, [
vue.createElementVNode("view", { class: "hero" }, [
vue.createElementVNode("image", {
class: "logo",
src: _imports_0,
mode: "aspectFit"
}),
vue.createElementVNode("text", { class: "title" }, "五金配件管家"),
vue.createElementVNode("text", { class: "subtitle" }, "专注小微门店的极简进销存")
]),
vue.createElementVNode("view", { class: "card" }, [
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "版本"),
vue.createElementVNode("text", { class: "value" }, "1.0.0")
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "隐私协议"),
vue.createElementVNode("text", {
class: "link",
onClick: _cache[0] || (_cache[0] = (...args) => $options.openPolicy && $options.openPolicy(...args))
}, "查看")
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "用户协议"),
vue.createElementVNode("text", {
class: "link",
onClick: _cache[1] || (_cache[1] = (...args) => $options.openTerms && $options.openTerms(...args))
}, "查看")
]),
vue.createElementVNode("view", { class: "row" }, [
vue.createElementVNode("text", { class: "label" }, "个人信息安全投诉"),
vue.createElementVNode("text", {
class: "link",
onClick: _cache[2] || (_cache[2] = (...args) => $options.openComplaint && $options.openComplaint(...args))
}, "提交")
])
])
]);
}
const PagesMyAbout = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__file", "D:/wx/PartsInquiry/frontend/pages/my/about.vue"]]);
function formatDate(d) {
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
return `${y}-${m}-${day}`;
}
const _sfc_main$1 = {
data() {
const now = /* @__PURE__ */ new Date();
const start = new Date(now.getFullYear(), now.getMonth(), 1);
return {
startDate: formatDate(start),
endDate: formatDate(now),
mode: "sale",
dim: "customer",
rows: [],
total: { sales: 0, cost: 0, profit: 0 }
};
},
onLoad(query) {
try {
const m = query && query.mode;
const d = query && query.dim;
if (m)
this.mode = m;
if (d)
this.dim = d;
} catch (e) {
}
this.refresh();
},
computed: {
profitRate() {
const { sales, profit } = this.total;
if (!sales)
return "0.00%";
return (profit / sales * 100).toFixed(2) + "%";
}
},
methods: {
fmt(n) {
return Number(n || 0).toFixed(2);
},
setMode(m) {
this.mode = m;
this.dim = m === "sale" ? "customer" : m === "purchase" ? "supplier" : m === "inventory" ? "qty" : "ar";
this.refresh();
},
onStartChange(e) {
this.startDate = e.detail.value;
this.refresh();
},
onEndChange(e) {
this.endDate = e.detail.value;
this.refresh();
},
async refresh() {
if (this.mode === "sale") {
if (this.dim === "customer")
return this.loadByCustomer();
if (this.dim === "product")
return this.loadByProduct();
}
if (this.mode === "purchase") {
if (this.dim === "supplier")
return this.loadPurchaseBySupplier();
if (this.dim === "product")
return this.loadPurchaseByProduct();
}
if (this.mode === "inventory") {
if (this.dim === "qty")
return this.loadInventoryByQty();
if (this.dim === "amount")
return this.loadInventoryByAmount();
}
if (this.mode === "arap") {
if (this.dim === "ar")
return this.loadAR();
if (this.dim === "ap")
return this.loadAP();
}
},
async loadByCustomer() {
try {
const listResp = await get("/api/orders", { biz: "sale", type: "out", startDate: this.startDate, endDate: this.endDate, page: 1, size: 200 });
const list = listResp && (listResp.list || listResp) || [];
const map = /* @__PURE__ */ new Map();
let totalSales = 0;
for (const it of list) {
const name = it.customerName || "未知客户";
const amount = Number(it.amount || 0);
totalSales += amount;
if (!map.has(name))
map.set(name, { name, sales: 0, cost: 0, profit: 0 });
const row = map.get(name);
row.sales += amount;
}
const rows = Array.from(map.values()).map((r) => ({ ...r, profit: r.sales - r.cost }));
const total = { sales: totalSales, cost: 0, profit: totalSales };
this.rows = rows;
this.total = total;
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
async loadByProduct() {
try {
const listResp = await get("/api/orders", { biz: "sale", type: "out", startDate: this.startDate, endDate: this.endDate, page: 1, size: 200 });
const list = listResp && (listResp.list || listResp) || [];
const agg = /* @__PURE__ */ new Map();
for (const it of list) {
try {
const d = await get(`/api/orders/${it.id}`);
const items = d && d.items || [];
for (const m of items) {
const key = String(m.productId || m.name);
if (!agg.has(key))
agg.set(key, { name: m.name || "#" + key, sales: 0, cost: 0, profit: 0 });
const row = agg.get(key);
const sales = Number(m.amount || 0);
row.sales += sales;
}
} catch (_) {
}
}
const rows = Array.from(agg.values()).map((r) => ({ ...r, profit: r.sales - r.cost }));
const totalSales = rows.reduce((s, r) => s + r.sales, 0);
this.rows = rows;
this.total = { sales: totalSales, cost: 0, profit: totalSales };
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
async loadPurchaseBySupplier() {
try {
const listResp = await get("/api/purchase-orders", { startDate: this.startDate, endDate: this.endDate, page: 1, size: 200 });
const list = listResp && (listResp.list || listResp) || [];
const map = /* @__PURE__ */ new Map();
let total = 0;
for (const it of list) {
const name = it.supplierName || "未知供应商";
const amount = Number(it.amount || 0);
total += amount;
if (!map.has(name))
map.set(name, { name, sales: 0, cost: 0, profit: 0 });
const row = map.get(name);
row.sales += amount;
}
this.rows = Array.from(map.values());
this.total = { sales: total, cost: 0, profit: 0 };
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
async loadPurchaseByProduct() {
try {
const listResp = await get("/api/purchase-orders", { startDate: this.startDate, endDate: this.endDate, page: 1, size: 200 });
const list = listResp && (listResp.list || listResp) || [];
const agg = /* @__PURE__ */ new Map();
for (const it of list) {
try {
const d = await get(`/api/purchase-orders/${it.id}`);
for (const m of (d == null ? void 0 : d.items) || []) {
const key = String(m.productId || m.name);
if (!agg.has(key))
agg.set(key, { name: m.name || "#" + key, sales: 0, cost: 0, profit: 0 });
const row = agg.get(key);
row.sales += Number(m.amount || 0);
}
} catch (_) {
}
}
const rows = Array.from(agg.values());
const total = rows.reduce((s, r) => s + r.sales, 0);
this.rows = rows;
this.total = { sales: total, cost: 0, profit: 0 };
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
async loadInventoryByQty() {
try {
const resp = await get("/api/inventories/logs", { startDate: this.startDate, endDate: this.endDate, page: 1, size: 200 });
const list = resp && (resp.list || resp) || [];
const map = /* @__PURE__ */ new Map();
let totalQty = 0;
for (const it of list) {
const key = it.productId || "未知";
if (!map.has(key))
map.set(key, { name: String(key), sales: 0, cost: 0, profit: 0 });
const row = map.get(key);
const q = Number(it.qtyDelta || 0);
row.sales += q;
totalQty += q;
}
this.rows = Array.from(map.values());
this.total = { sales: totalQty, cost: 0, profit: 0 };
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
async loadInventoryByAmount() {
try {
const resp = await get("/api/inventories/logs", { startDate: this.startDate, endDate: this.endDate, page: 1, size: 200 });
const list = resp && (resp.list || resp) || [];
const map = /* @__PURE__ */ new Map();
let totalAmt = 0;
for (const it of list) {
const key = it.productId || "未知";
if (!map.has(key))
map.set(key, { name: String(key), sales: 0, cost: 0, profit: 0 });
const row = map.get(key);
const a = Number(it.amount || it.amountDelta || 0);
row.sales += a;
totalAmt += a;
}
this.rows = Array.from(map.values());
this.total = { sales: totalAmt, cost: 0, profit: 0 };
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
async loadAR() {
try {
const res = await get("/api/customers", { page: 1, size: 100, debtOnly: false });
const list = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
const rows = list.map((c) => ({ name: c.name, sales: Number(c.receivable || 0), cost: 0, profit: 0 }));
const total = rows.reduce((s, r) => s + r.sales, 0);
this.rows = rows;
this.total = { sales: total, cost: 0, profit: 0 };
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
},
async loadAP() {
try {
const res = await get("/api/suppliers", { page: 1, size: 100 });
const list = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
const rows = list.map((s) => ({ name: s.name, sales: Number(s.apPayable || 0), cost: 0, profit: 0 }));
const total = rows.reduce((s, r) => s + r.sales, 0);
this.rows = rows;
this.total = { sales: total, cost: 0, profit: 0 };
} catch (e) {
uni.showToast({ title: "加载失败", icon: "none" });
}
}
}
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "report" }, [
vue.createElementVNode("view", { class: "modes" }, [
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["mode-tab", { active: $data.mode === "sale" }]),
onClick: _cache[0] || (_cache[0] = ($event) => $options.setMode("sale"))
},
"销售统计",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["mode-tab", { active: $data.mode === "purchase" }]),
onClick: _cache[1] || (_cache[1] = ($event) => $options.setMode("purchase"))
},
"进货统计",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["mode-tab", { active: $data.mode === "inventory" }]),
onClick: _cache[2] || (_cache[2] = ($event) => $options.setMode("inventory"))
},
"库存统计",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["mode-tab", { active: $data.mode === "arap" }]),
onClick: _cache[3] || (_cache[3] = ($event) => $options.setMode("arap"))
},
"应收/应付对账",
2
/* CLASS */
)
]),
vue.createElementVNode("view", { class: "toolbar" }, [
vue.createElementVNode("picker", {
mode: "date",
value: $data.startDate,
onChange: _cache[4] || (_cache[4] = (...args) => $options.onStartChange && $options.onStartChange(...args))
}, [
vue.createElementVNode(
"view",
{ class: "date" },
vue.toDisplayString($data.startDate),
1
/* TEXT */
)
], 40, ["value"]),
vue.createElementVNode("text", { style: { "margin": "0 8rpx" } }, "—"),
vue.createElementVNode("picker", {
mode: "date",
value: $data.endDate,
onChange: _cache[5] || (_cache[5] = (...args) => $options.onEndChange && $options.onEndChange(...args))
}, [
vue.createElementVNode(
"view",
{ class: "date" },
vue.toDisplayString($data.endDate),
1
/* TEXT */
)
], 40, ["value"])
]),
$data.mode === "sale" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 0,
class: "tabs"
}, [
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.dim === "customer" }]),
onClick: _cache[6] || (_cache[6] = ($event) => {
$data.dim = "customer";
$options.refresh();
})
},
"按客户",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.dim === "product" }]),
onClick: _cache[7] || (_cache[7] = ($event) => {
$data.dim = "product";
$options.refresh();
})
},
"按货品",
2
/* CLASS */
)
])) : $data.mode === "purchase" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 1,
class: "tabs"
}, [
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.dim === "supplier" }]),
onClick: _cache[8] || (_cache[8] = ($event) => {
$data.dim = "supplier";
$options.refresh();
})
},
"按供应商",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.dim === "product" }]),
onClick: _cache[9] || (_cache[9] = ($event) => {
$data.dim = "product";
$options.refresh();
})
},
"按货品",
2
/* CLASS */
)
])) : $data.mode === "inventory" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 2,
class: "tabs"
}, [
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.dim === "qty" }]),
onClick: _cache[10] || (_cache[10] = ($event) => {
$data.dim = "qty";
$options.refresh();
})
},
"按数量",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.dim === "amount" }]),
onClick: _cache[11] || (_cache[11] = ($event) => {
$data.dim = "amount";
$options.refresh();
})
},
"按金额",
2
/* CLASS */
)
])) : $data.mode === "arap" ? (vue.openBlock(), vue.createElementBlock("view", {
key: 3,
class: "tabs"
}, [
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.dim === "ar" }]),
onClick: _cache[12] || (_cache[12] = ($event) => {
$data.dim = "ar";
$options.refresh();
})
},
"应收对账",
2
/* CLASS */
),
vue.createElementVNode(
"view",
{
class: vue.normalizeClass(["tab", { active: $data.dim === "ap" }]),
onClick: _cache[13] || (_cache[13] = ($event) => {
$data.dim = "ap";
$options.refresh();
})
},
"应付对账",
2
/* CLASS */
)
])) : vue.createCommentVNode("v-if", true),
vue.createElementVNode("view", { class: "summary" }, [
vue.createElementVNode("view", { class: "item" }, [
vue.createElementVNode("text", { class: "label" }, "销售额"),
vue.createElementVNode(
"text",
{ class: "value" },
"¥ " + vue.toDisplayString($options.fmt($data.total.sales)),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "item" }, [
vue.createElementVNode("text", { class: "label" }, "成本"),
vue.createElementVNode(
"text",
{ class: "value" },
"¥ " + vue.toDisplayString($options.fmt($data.total.cost)),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "item" }, [
vue.createElementVNode("text", { class: "label" }, "利润"),
vue.createElementVNode(
"text",
{ class: "value" },
"¥ " + vue.toDisplayString($options.fmt($data.total.profit)),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "item" }, [
vue.createElementVNode("text", { class: "label" }, "利润率"),
vue.createElementVNode(
"text",
{ class: "value" },
vue.toDisplayString($options.profitRate),
1
/* TEXT */
)
])
]),
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($data.rows, (row, idx) => {
return vue.openBlock(), vue.createElementBlock("view", {
key: idx,
class: "card"
}, [
vue.createElementVNode("view", { class: "row-head" }, [
row.avatar ? (vue.openBlock(), vue.createElementBlock("image", {
key: 0,
class: "thumb",
src: row.avatar
}, null, 8, ["src"])) : vue.createCommentVNode("v-if", true),
vue.createElementVNode(
"view",
{ class: "title" },
vue.toDisplayString(row.name),
1
/* TEXT */
)
]),
vue.createElementVNode("view", { class: "row-body" }, [
vue.createElementVNode(
"text",
null,
"销售额:¥ " + vue.toDisplayString($options.fmt(row.sales)),
1
/* TEXT */
),
vue.createElementVNode(
"text",
{ style: { "margin-left": "18rpx" } },
"成本:¥ " + vue.toDisplayString($options.fmt(row.cost)),
1
/* TEXT */
),
vue.createElementVNode(
"text",
{ style: { "margin-left": "18rpx" } },
"利润:¥ " + vue.toDisplayString($options.fmt(row.profit)),
1
/* TEXT */
)
])
]);
}),
128
/* KEYED_FRAGMENT */
))
]);
}
const PagesReportIndex = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__file", "D:/wx/PartsInquiry/frontend/pages/report/index.vue"]]);
__definePage("pages/index/index", PagesIndexIndex);
__definePage("pages/order/create", PagesOrderCreate);
__definePage("pages/product/select", PagesProductSelect);
__definePage("pages/product/list", PagesProductList);
__definePage("pages/product/form", PagesProductForm);
__definePage("pages/product/categories", PagesProductCategories);
__definePage("pages/product/units", PagesProductUnits);
__definePage("pages/product/settings", PagesProductSettings);
__definePage("pages/customer/select", PagesCustomerSelect);
__definePage("pages/customer/form", PagesCustomerForm);
__definePage("pages/customer/detail", PagesCustomerDetail);
__definePage("pages/supplier/select", PagesSupplierSelect);
__definePage("pages/supplier/form", PagesSupplierForm);
__definePage("pages/account/select", PagesAccountSelect);
__definePage("pages/account/ledger", PagesAccountLedger);
__definePage("pages/account/form", PagesAccountForm);
__definePage("pages/detail/index", PagesDetailIndex);
__definePage("pages/my/index", PagesMyIndex);
__definePage("pages/my/about", PagesMyAbout);
__definePage("pages/report/index", PagesReportIndex);
const _sfc_main = {
onLaunch: function() {
formatAppLog("log", "at App.vue:4", "App Launch");
},
onShow: function() {
formatAppLog("log", "at App.vue:7", "App Show");
},
onHide: function() {
formatAppLog("log", "at App.vue:10", "App Hide");
}
};
const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "D:/wx/PartsInquiry/frontend/App.vue"]]);
function createApp() {
const app = vue.createVueApp(App);
return {
app
};
}
const { app: __app__, Vuex: __Vuex__, Pinia: __Pinia__ } = createApp();
uni.Vuex = __Vuex__;
uni.Pinia = __Pinia__;
__app__.provide("__globalStyles", __uniConfig.styles);
__app__._component.mpType = "app";
__app__._component.render = () => {
};
__app__.mount("#app");
})(Vue);