8646 lines
316 KiB
JavaScript
8646 lines
316 KiB
JavaScript
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 || "false").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 || 0);
|
||
typeof process !== "undefined" && define_process_env_default && (define_process_env_default.VITE_APP_VIP_PRICE || define_process_env_default.VIP_PRICE) || "";
|
||
typeof uni !== "undefined" ? uni.getStorageSync("VIP_PRICE") || "" : "";
|
||
typeof process !== "undefined" && define_process_env_default && (define_process_env_default.VITE_APP_HOME_BANNER_IMG || define_process_env_default.HOME_BANNER_IMG) || "";
|
||
typeof uni !== "undefined" ? uni.getStorageSync("HOME_BANNER_IMG") || "" : "";
|
||
const KPI_ICONS = {
|
||
todaySales: "/static/icons/webwxgetmsgimg.jpg",
|
||
monthSales: "/static/icons/webwxgetmsgimg.jpg",
|
||
monthProfit: "/static/icons/icons8-profit-50.png",
|
||
stockCount: "/static/icons/product.png"
|
||
};
|
||
const envAuthLoginImg = typeof process !== "undefined" && define_process_env_default && (define_process_env_default.VITE_APP_AUTH_LOGIN_TOP_IMAGE || define_process_env_default.AUTH_LOGIN_TOP_IMAGE) || "";
|
||
const storageAuthLoginImg = typeof uni !== "undefined" ? uni.getStorageSync("AUTH_LOGIN_TOP_IMAGE") || "" : "";
|
||
const AUTH_LOGIN_TOP_IMAGE = String(envAuthLoginImg || storageAuthLoginImg || "/static/icons/undraw_visual-data_1eya.png");
|
||
function buildUrl(path) {
|
||
if (!path)
|
||
return API_BASE_URL;
|
||
if (path.startsWith("http"))
|
||
return path;
|
||
return API_BASE_URL + (path.startsWith("/") ? path : "/" + path);
|
||
}
|
||
function parseJwtClaims(token) {
|
||
try {
|
||
const parts = String(token || "").split(".");
|
||
if (parts.length < 2)
|
||
return {};
|
||
const payload = JSON.parse(decodeURIComponent(escape(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")))));
|
||
return payload || {};
|
||
} catch (_) {
|
||
return {};
|
||
}
|
||
}
|
||
function buildAuthHeaders(base = {}) {
|
||
const headers = { ...base };
|
||
try {
|
||
const token = typeof uni !== "undefined" ? uni.getStorageSync("TOKEN") || "" : "";
|
||
if (token) {
|
||
headers["Authorization"] = `Bearer ${token}`;
|
||
const claims = parseJwtClaims(token);
|
||
if (claims && claims.shopId)
|
||
headers["X-Shop-Id"] = claims.shopId;
|
||
if (claims && claims.userId)
|
||
headers["X-User-Id"] = claims.userId;
|
||
} else if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID) {
|
||
if (headers["Authorization"])
|
||
delete headers["Authorization"];
|
||
headers["X-User-Id"] = headers["X-User-Id"] || DEFAULT_USER_ID;
|
||
if (SHOP_ID)
|
||
headers["X-Shop-Id"] = headers["X-Shop-Id"] || SHOP_ID;
|
||
}
|
||
} catch (_) {
|
||
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID) {
|
||
headers["X-User-Id"] = headers["X-User-Id"] || DEFAULT_USER_ID;
|
||
if (SHOP_ID)
|
||
headers["X-Shop-Id"] = headers["X-Shop-Id"] || SHOP_ID;
|
||
}
|
||
}
|
||
return headers;
|
||
}
|
||
function requestWithFallback(options, candidates, idx, resolve, reject) {
|
||
const base = candidates[idx] || API_BASE_URL;
|
||
let url = options.url;
|
||
if (!/^https?:\/\//.test(url)) {
|
||
url = base + (url.startsWith("/") ? "" : "/") + url;
|
||
} else {
|
||
url = options.url.replace(/^https?:\/\/[^/]+/, base);
|
||
}
|
||
uni.request({ ...options, url, dataType: "json", 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 (!options.__noRetry && statusCode >= 500 && idx + 1 < candidates.length) {
|
||
return requestWithFallback(options, candidates, idx + 1, resolve, reject);
|
||
}
|
||
reject(new Error(msg));
|
||
}, fail: (err) => {
|
||
if (!options.__noRetry && 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 = buildAuthHeaders({});
|
||
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 = buildAuthHeaders({ "Content-Type": "application/json" });
|
||
const options = { url: buildUrl(path), method: "POST", data: body, header: headers };
|
||
const p = String(path || "");
|
||
if (p.includes("/api/auth/wxmp/login") || p.includes("/api/auth/sms/login") || p.includes("/api/auth/sms/send") || p.includes("/api/auth/email/login") || p.includes("/api/auth/email/send") || p.includes("/api/auth/password/login") || p.includes("/api/auth/register"))
|
||
options.__noRetry = true;
|
||
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject);
|
||
});
|
||
}
|
||
function put(path, body = {}) {
|
||
return new Promise((resolve, reject) => {
|
||
const headers = buildAuthHeaders({ "Content-Type": "application/json" });
|
||
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 = buildAuthHeaders({ "Content-Type": "application/json" });
|
||
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 (statusCode >= 400 && statusCode < 500) {
|
||
try {
|
||
const data = typeof res.data === "string" ? JSON.parse(res.data) : res.data;
|
||
return resolve(data);
|
||
} catch (e) {
|
||
return resolve({ success: false, message: "HTTP " + statusCode });
|
||
}
|
||
}
|
||
if (idx + 1 < candidates.length)
|
||
return uploadWithFallback(options, candidates, idx + 1, resolve, reject);
|
||
try {
|
||
const data = typeof res.data === "string" ? JSON.parse(res.data) : res.data;
|
||
return resolve(data);
|
||
} catch (e) {
|
||
return resolve({ success: false, message: "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 = buildAuthHeaders({});
|
||
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",
|
||
myVip: "/pages/my/vip",
|
||
report: "/pages/report/index",
|
||
customerSelect: "/pages/customer/select",
|
||
supplierSelect: "/pages/supplier/select",
|
||
accountSelect: "/pages/account/select"
|
||
};
|
||
const KPI_LABELS = {
|
||
todaySales: "今日销售额",
|
||
monthSales: "本月销售额",
|
||
monthProfit: "本月利润",
|
||
stockCount: "库存量"
|
||
};
|
||
const _export_sfc = (sfc, props) => {
|
||
const target = sfc.__vccOpts || sfc;
|
||
for (const [key, val] of props) {
|
||
target[key] = val;
|
||
}
|
||
return target;
|
||
};
|
||
const _sfc_main$u = {
|
||
data() {
|
||
return {
|
||
KPI_ICONS,
|
||
KPI_LABELS,
|
||
kpi: { todaySales: "0.00", monthSales: "0.00", monthProfit: "0.00", stockCount: "0" },
|
||
activeTab: "home",
|
||
notices: [],
|
||
loadingNotices: false,
|
||
noticeError: "",
|
||
consultLabel: "咨询",
|
||
consultDialogVisible: false,
|
||
consultMessage: "",
|
||
features: [
|
||
{ key: "product", title: "货品", img: "/static/icons/product.png", emoji: "📦" },
|
||
{ key: "customer", title: "客户", img: "/static/icons/webwxgetmsgimg.png", emoji: "👥" },
|
||
{ key: "sale", title: "销售", img: "/static/icons/webwxgetmsgimg.jpg", emoji: "💰" },
|
||
{ key: "account", title: "账户", img: "/static/icons/icons8-profile-50.png", emoji: "💳" },
|
||
{ key: "supplier", title: "供应商", img: "/static/icons/icons8-supplier-50.png", emoji: "🚚" },
|
||
{ key: "purchase", title: "进货", img: "/static/icons/icons8-dollar-ethereum-exchange-50.png", emoji: "🛒" },
|
||
{ key: "otherPay", title: "其他支出", img: "/static/icons/icons8-expenditure-64.png", emoji: "💸" },
|
||
{ key: "vip", title: "VIP会员", img: "/static/icons/icons8-vip-48.png", emoji: "👑" },
|
||
{ key: "report", title: "报表", img: "/static/icons/icons8-graph-report-50.png", emoji: "📊" }
|
||
]
|
||
};
|
||
},
|
||
onLoad() {
|
||
const hasToken = (() => {
|
||
try {
|
||
return !!uni.getStorageSync("TOKEN");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
})();
|
||
if (!hasToken) {
|
||
this.kpi = { todaySales: "0.00", monthSales: "0.00", monthProfit: "0.00", stockCount: "0" };
|
||
this.notices = [];
|
||
uni.showToast({ title: "请登录使用该功能", icon: "none" });
|
||
return;
|
||
}
|
||
this.fetchMetrics();
|
||
this.fetchNotices();
|
||
this.fetchLatestConsult();
|
||
},
|
||
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 fetchLatestConsult() {
|
||
try {
|
||
const d = await get("/api/consults");
|
||
if (d && d.replied)
|
||
this.consultLabel = "已回复";
|
||
else
|
||
this.consultLabel = "咨询";
|
||
this._latestConsult = d;
|
||
} catch (e) {
|
||
this.consultLabel = "咨询";
|
||
}
|
||
},
|
||
onConsultTap() {
|
||
if (this.consultLabel === "已回复" && this._latestConsult && this._latestConsult.id) {
|
||
const msg = this._latestConsult.latestReply ? this._latestConsult.latestReply : this._latestConsult.message || "";
|
||
uni.showModal({ title: "咨询回复", content: msg || "暂无内容", showCancel: false, success: async (res) => {
|
||
if (!res || res.confirm !== true)
|
||
return;
|
||
try {
|
||
const r = await put(`/api/consults/${this._latestConsult.id}/ack`, {});
|
||
this.consultLabel = "咨询";
|
||
this._latestConsult = null;
|
||
setTimeout(() => this.fetchLatestConsult(), 200);
|
||
} catch (e) {
|
||
try {
|
||
uni.showToast({ title: e && e.message || "已读同步失败", icon: "none" });
|
||
} catch (_) {
|
||
}
|
||
}
|
||
} });
|
||
return;
|
||
}
|
||
this.consultMessage = "";
|
||
this.consultDialogVisible = true;
|
||
},
|
||
closeConsultDialog() {
|
||
this.consultDialogVisible = false;
|
||
},
|
||
async submitConsult() {
|
||
const text = String(this.consultMessage || "").trim();
|
||
if (!text) {
|
||
uni.showToast({ title: "请输入咨询内容", icon: "none" });
|
||
return;
|
||
}
|
||
try {
|
||
await post("/api/consults", { message: text });
|
||
this.consultDialogVisible = false;
|
||
uni.showToast({ title: "已提交", icon: "success" });
|
||
setTimeout(() => this.fetchLatestConsult(), 300);
|
||
} catch (e) {
|
||
uni.showToast({ title: e && e.message || "提交失败", icon: "none" });
|
||
}
|
||
},
|
||
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 === "vip") {
|
||
uni.navigateTo({ url: "/pages/my/vip" });
|
||
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:259", "[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$t(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "home" }, [
|
||
vue.createCommentVNode(" 顶部统计卡片 "),
|
||
vue.createElementVNode("view", { class: "hero" }, [
|
||
vue.createElementVNode("view", { class: "hero-top" }, [
|
||
vue.createElementVNode("text", { class: "brand" }, "五金配件管家"),
|
||
vue.createElementVNode("view", {
|
||
class: "cta",
|
||
onClick: _cache[0] || (_cache[0] = (...args) => $options.onConsultTap && $options.onConsultTap(...args)),
|
||
"hover-class": "cta-active",
|
||
"hover-stay-time": "80"
|
||
}, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "cta-text" },
|
||
vue.toDisplayString($data.consultLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "kpi kpi-grid" }, [
|
||
vue.createElementVNode("view", { class: "kpi-item kpi-card" }, [
|
||
vue.createElementVNode("image", {
|
||
src: $data.KPI_ICONS.todaySales,
|
||
class: "kpi-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("view", { class: "kpi-content" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "kpi-label" },
|
||
vue.toDisplayString($data.KPI_LABELS.todaySales),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "kpi-value" },
|
||
vue.toDisplayString($data.kpi.todaySales),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "kpi-item kpi-card" }, [
|
||
vue.createElementVNode("image", {
|
||
src: $data.KPI_ICONS.monthSales,
|
||
class: "kpi-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("view", { class: "kpi-content" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "kpi-label" },
|
||
vue.toDisplayString($data.KPI_LABELS.monthSales),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "kpi-value" },
|
||
vue.toDisplayString($data.kpi.monthSales),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "kpi-item kpi-card" }, [
|
||
vue.createElementVNode("image", {
|
||
src: $data.KPI_ICONS.monthProfit,
|
||
class: "kpi-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("view", { class: "kpi-content" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "kpi-label" },
|
||
vue.toDisplayString($data.KPI_LABELS.monthProfit),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "kpi-value" },
|
||
vue.toDisplayString($data.kpi.monthProfit),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "kpi-item kpi-card" }, [
|
||
vue.createElementVNode("image", {
|
||
src: $data.KPI_ICONS.stockCount,
|
||
class: "kpi-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("view", { class: "kpi-content" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "kpi-label" },
|
||
vue.toDisplayString($data.KPI_LABELS.stockCount),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "kpi-value" },
|
||
vue.toDisplayString($data.kpi.stockCount),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
])
|
||
])
|
||
]),
|
||
vue.createCommentVNode(" 咨询输入弹层 "),
|
||
$data.consultDialogVisible ? (vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
key: 0,
|
||
class: "dialog-mask",
|
||
onTouchmove: _cache[4] || (_cache[4] = vue.withModifiers(() => {
|
||
}, ["stop", "prevent"])),
|
||
onClick: _cache[5] || (_cache[5] = vue.withModifiers(() => {
|
||
}, ["stop"]))
|
||
},
|
||
[
|
||
vue.createElementVNode("view", { class: "dialog" }, [
|
||
vue.createElementVNode("view", { class: "dialog-title" }, "咨询"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"textarea",
|
||
{
|
||
class: "dialog-textarea",
|
||
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $data.consultMessage = $event),
|
||
placeholder: "请输入咨询内容...",
|
||
maxlength: "500"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[vue.vModelText, $data.consultMessage]
|
||
]),
|
||
vue.createElementVNode("view", { class: "dialog-actions" }, [
|
||
vue.createElementVNode("view", {
|
||
class: "btn",
|
||
onClick: _cache[2] || (_cache[2] = (...args) => $options.closeConsultDialog && $options.closeConsultDialog(...args))
|
||
}, "取消"),
|
||
vue.createElementVNode("view", {
|
||
class: "btn primary",
|
||
onClick: _cache[3] || (_cache[3] = (...args) => $options.submitConsult && $options.submitConsult(...args))
|
||
}, "提交")
|
||
])
|
||
])
|
||
],
|
||
32
|
||
/* NEED_HYDRATION */
|
||
)) : vue.createCommentVNode("v-if", true),
|
||
vue.createCommentVNode(" 公告栏:放在常用功能上方、KPI 下方 "),
|
||
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: "feature-grid" }, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($data.features, (item) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
class: "feature-card",
|
||
key: item.key,
|
||
onClick: ($event) => $options.onFeatureTap(item)
|
||
}, [
|
||
vue.createElementVNode("view", { class: "fc-icon" }, [
|
||
item.img ? (vue.openBlock(), vue.createElementBlock("image", {
|
||
key: 0,
|
||
src: item.img,
|
||
class: "fc-img",
|
||
mode: "aspectFit",
|
||
onError: ($event) => $options.onIconError(item)
|
||
}, null, 40, ["src", "onError"])) : item.emoji ? (vue.openBlock(), vue.createElementBlock(
|
||
"text",
|
||
{
|
||
key: 1,
|
||
class: "fc-emoji"
|
||
},
|
||
vue.toDisplayString(item.emoji),
|
||
1
|
||
/* TEXT */
|
||
)) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 2,
|
||
class: "fc-placeholder"
|
||
}))
|
||
]),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "fc-title" },
|
||
vue.toDisplayString(item.title),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 8, ["onClick"]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])
|
||
]),
|
||
vue.createCommentVNode(" 底部操作条改为原生 tabBar,移除自定义栏 ")
|
||
]);
|
||
}
|
||
const PagesIndexIndex = /* @__PURE__ */ _export_sfc(_sfc_main$u, [["render", _sfc_render$t], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/index/index.vue"]]);
|
||
const _imports_0$4 = "/static/icons/icons8-shopping-cart-100.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$t = {
|
||
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,
|
||
SEG_ICONS: {
|
||
sale: {
|
||
out: "/static/icons/icons8-shopping-cart-100.png",
|
||
return: "/static/icons/icons8-return-purchase-50.png",
|
||
collect: "/static/icons/icons8-profit-50.png"
|
||
},
|
||
purchase: {
|
||
in: "/static/icons/icons8-purchase-order-100.png",
|
||
return: "/static/icons/icons8-return-purchase-50.png",
|
||
pay: "/static/icons/icons8-dollar-ethereum-exchange-50.png"
|
||
}
|
||
}
|
||
};
|
||
},
|
||
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: {
|
||
fixMojibake(s) {
|
||
try {
|
||
if (!s)
|
||
return s;
|
||
const bad = /[ÂÃæåé¼½¢]/.test(s);
|
||
if (!bad)
|
||
return s;
|
||
return decodeURIComponent(escape(s));
|
||
} catch (_) {
|
||
return s;
|
||
}
|
||
},
|
||
normalizeCats(list) {
|
||
if (!Array.isArray(list))
|
||
return [];
|
||
return list.map((it) => ({
|
||
key: it && it.key || "",
|
||
label: this.fixMojibake(it && it.label || "")
|
||
})).filter((it) => it.key && it.label);
|
||
},
|
||
async fetchCategories() {
|
||
try {
|
||
const res = await get("/api/finance/categories");
|
||
if (res && Array.isArray(res.incomeCategories))
|
||
this._incomeCategories = this.normalizeCats(res.incomeCategories);
|
||
if (res && Array.isArray(res.expenseCategories))
|
||
this._expenseCategories = this.normalizeCats(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$s(_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: "seg3"
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["seg3-item", $data.saleType === "out" && "active"]),
|
||
onClick: _cache[4] || (_cache[4] = ($event) => $data.saleType = "out")
|
||
},
|
||
[
|
||
vue.createElementVNode("image", {
|
||
src: $data.SEG_ICONS.sale.out,
|
||
class: "seg3-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("text", null, "出货")
|
||
],
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["seg3-item", $data.saleType === "return" && "active"]),
|
||
onClick: _cache[5] || (_cache[5] = ($event) => $data.saleType = "return")
|
||
},
|
||
[
|
||
vue.createElementVNode("image", {
|
||
src: $data.SEG_ICONS.sale.return,
|
||
class: "seg3-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("text", null, "退货")
|
||
],
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["seg3-item", $data.saleType === "collect" && "active"]),
|
||
onClick: _cache[6] || (_cache[6] = ($event) => $data.saleType = "collect")
|
||
},
|
||
[
|
||
vue.createElementVNode("image", {
|
||
src: $data.SEG_ICONS.sale.collect,
|
||
class: "seg3-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("text", null, "收款")
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)
|
||
])) : $data.biz === "purchase" ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "seg3"
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["seg3-item", $data.purchaseType === "in" && "active"]),
|
||
onClick: _cache[7] || (_cache[7] = ($event) => $data.purchaseType = "in")
|
||
},
|
||
[
|
||
vue.createElementVNode("image", {
|
||
src: $data.SEG_ICONS.purchase.in,
|
||
class: "seg3-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("text", null, "进货")
|
||
],
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["seg3-item", $data.purchaseType === "return" && "active"]),
|
||
onClick: _cache[8] || (_cache[8] = ($event) => $data.purchaseType = "return")
|
||
},
|
||
[
|
||
vue.createElementVNode("image", {
|
||
src: $data.SEG_ICONS.purchase.return,
|
||
class: "seg3-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("text", null, "退货")
|
||
],
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["seg3-item", $data.purchaseType === "pay" && "active"]),
|
||
onClick: _cache[9] || (_cache[9] = ($event) => $data.purchaseType = "pay")
|
||
},
|
||
[
|
||
vue.createElementVNode("image", {
|
||
src: $data.SEG_ICONS.purchase.pay,
|
||
class: "seg3-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("text", null, "付款")
|
||
],
|
||
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.createCommentVNode(" 快捷操作:加商品/选择客户(或供应商)/选择日期 → 不改功能,只换排版 "),
|
||
vue.createElementVNode("view", { class: "info-card" }, [
|
||
vue.createElementVNode("view", {
|
||
class: "info-field party-field",
|
||
onClick: _cache[24] || (_cache[24] = ($event) => $data.biz === "sale" ? $options.chooseCustomer() : $options.chooseSupplier())
|
||
}, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "info-label" },
|
||
vue.toDisplayString($data.biz === "sale" ? "客户" : "供应商"),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "info-value" },
|
||
vue.toDisplayString($data.biz === "sale" ? $options.customerLabel : $options.supplierLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("picker", {
|
||
class: "info-field time-field",
|
||
mode: "date",
|
||
value: $data.order.orderTime,
|
||
onChange: _cache[25] || (_cache[25] = (...args) => $options.onDateChange && $options.onDateChange(...args))
|
||
}, [
|
||
vue.createElementVNode("view", null, [
|
||
vue.createElementVNode("text", { class: "info-label" }, "时间"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "info-value" },
|
||
vue.toDisplayString($data.order.orderTime),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
], 40, ["value"]),
|
||
vue.createElementVNode("button", {
|
||
class: "info-action",
|
||
onClick: _cache[26] || (_cache[26] = (...args) => $options.chooseProduct && $options.chooseProduct(...args))
|
||
}, [
|
||
vue.createElementVNode("image", {
|
||
src: _imports_0$4,
|
||
class: "info-icon",
|
||
mode: "aspectFit"
|
||
}),
|
||
vue.createElementVNode("text", null, "加商品")
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "summary" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "sel" },
|
||
"选中货品(" + vue.toDisplayString($options.totalQuantity) + ")",
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "total-pill" },
|
||
"合计: ¥ " + vue.toDisplayString($options.totalAmount.toFixed(2)),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createCommentVNode(" 加号添加商品 "),
|
||
vue.createElementVNode("view", {
|
||
class: "add",
|
||
onClick: _cache[27] || (_cache[27] = (...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[28] || (_cache[28] = ($event) => $options.setCounterparty("customer"))
|
||
},
|
||
"客户",
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"button",
|
||
{
|
||
class: vue.normalizeClass(["subbtn", { active: $data.counterpartyType === "supplier" }]),
|
||
onClick: _cache[29] || (_cache[29] = ($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[30] || (_cache[30] = (...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[31] || (_cache[31] = (...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[32] || (_cache[32] = ($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[33] || (_cache[33] = ($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("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[34] || (_cache[34] = ($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[35] || (_cache[35] = (...args) => $options.saveAndReset && $options.saveAndReset(...args))
|
||
}, "再记一笔"),
|
||
vue.createElementVNode("button", {
|
||
class: "primary",
|
||
onClick: _cache[36] || (_cache[36] = (...args) => $options.submit && $options.submit(...args))
|
||
}, "保存")
|
||
])
|
||
]);
|
||
}
|
||
const PagesOrderCreate = /* @__PURE__ */ _export_sfc(_sfc_main$t, [["render", _sfc_render$s], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/order/create.vue"]]);
|
||
const _sfc_main$s = {
|
||
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$r(_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$s, [["render", _sfc_render$r], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/select.vue"]]);
|
||
const _sfc_main$r = {
|
||
data() {
|
||
return {
|
||
items: [],
|
||
query: { kw: "", page: 1, size: 20, categoryId: "", mode: "direct", templateId: "", params: {} },
|
||
finished: false,
|
||
loading: false,
|
||
tab: "all",
|
||
categories: [],
|
||
templates: [],
|
||
paramValues: {}
|
||
};
|
||
},
|
||
onLoad() {
|
||
const hasToken = (() => {
|
||
try {
|
||
return !!uni.getStorageSync("TOKEN");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
})();
|
||
if (!hasToken) {
|
||
this.items = [];
|
||
this.categories = [];
|
||
uni.showToast({ title: "请登录使用该功能", icon: "none" });
|
||
return;
|
||
}
|
||
this.fetchCategories();
|
||
this.reload();
|
||
},
|
||
onShow() {
|
||
const hasToken = (() => {
|
||
try {
|
||
return !!uni.getStorageSync("TOKEN");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
})();
|
||
if (!hasToken)
|
||
return;
|
||
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 : "选择类别";
|
||
},
|
||
modeLabel() {
|
||
const map = { direct: "直接查询", nameLike: "名称模糊查询", template: "按模板参数查询" };
|
||
return map[this.query.mode] || "直接查询";
|
||
},
|
||
templateNames() {
|
||
return this.templates.map((t) => t.name);
|
||
},
|
||
templateLabel() {
|
||
const t = this.templates.find((x) => String(x.id) === String(this.query.templateId));
|
||
return t ? "模板:" + t.name : "选择模板";
|
||
},
|
||
selectedTemplate() {
|
||
return this.templates.find((t) => String(t.id) === String(this.query.templateId)) || null;
|
||
},
|
||
selectedTemplateParams() {
|
||
return this.selectedTemplate && Array.isArray(this.selectedTemplate.params) ? this.selectedTemplate.params : [];
|
||
}
|
||
},
|
||
methods: {
|
||
switchTab(t) {
|
||
this.tab = t;
|
||
this.query.categoryId = "";
|
||
this.query.templateId = "";
|
||
this.paramValues = {};
|
||
this.reload();
|
||
},
|
||
onPickCategory(e) {
|
||
const idx = Number(e.detail.value);
|
||
const c = this.categories[idx];
|
||
this.query.categoryId = c ? c.id : "";
|
||
this.fetchTemplates();
|
||
},
|
||
onPickTemplate(e) {
|
||
const idx = Number(e.detail.value);
|
||
const t = this.templates[idx];
|
||
this.query.templateId = t ? t.id : "";
|
||
this.paramValues = {};
|
||
},
|
||
onPickParamEnumWrapper(p, e) {
|
||
const idx = Number(e.detail.value);
|
||
const arr = p.enumOptions || [];
|
||
this.paramValues[p.fieldKey] = arr[idx];
|
||
},
|
||
onParamBoolChange(p, e) {
|
||
var _a;
|
||
this.paramValues[p.fieldKey] = ((_a = e == null ? void 0 : e.detail) == null ? void 0 : _a.value) ? true : false;
|
||
},
|
||
onParamDateChange(p, e) {
|
||
var _a;
|
||
this.paramValues[p.fieldKey] = ((_a = e == null ? void 0 : e.detail) == null ? void 0 : _a.value) || "";
|
||
},
|
||
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 (_) {
|
||
}
|
||
},
|
||
async fetchTemplates() {
|
||
try {
|
||
const res = await get("/api/product-templates", this.query.categoryId ? { categoryId: this.query.categoryId } : {});
|
||
const list = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
|
||
this.templates = list;
|
||
} catch (_) {
|
||
this.templates = [];
|
||
}
|
||
},
|
||
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 === "search") {
|
||
if (this.query.categoryId)
|
||
params.categoryId = this.query.categoryId;
|
||
if (this.query.templateId)
|
||
params.templateId = this.query.templateId;
|
||
if (this.paramValues && Object.keys(this.paramValues).length) {
|
||
for (const k of Object.keys(this.paramValues)) {
|
||
const v = this.paramValues[k];
|
||
if (v !== void 0 && v !== null && v !== "")
|
||
params["param_" + k] = v;
|
||
}
|
||
}
|
||
}
|
||
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;
|
||
}
|
||
},
|
||
openDetail(id) {
|
||
uni.navigateTo({ url: "/pages/product/product-detail?id=" + id });
|
||
},
|
||
goMySubmissions() {
|
||
uni.navigateTo({ url: "/pages/product/submissions" });
|
||
},
|
||
async remove(it) {
|
||
try {
|
||
const r = await new Promise((resolve) => {
|
||
uni.showModal({ content: "确认删除该货品?删除后可在后台恢复", success: resolve });
|
||
});
|
||
if (!r || !r.confirm)
|
||
return;
|
||
const { del: del2 } = require("../../common/http.js");
|
||
await del2("/api/products/" + it.id);
|
||
uni.showToast({ title: "已删除", icon: "success" });
|
||
this.reload();
|
||
} catch (e) {
|
||
uni.showToast({ title: "删除失败", icon: "none" });
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$q(_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 === "search" }]),
|
||
onClick: _cache[1] || (_cache[1] = ($event) => $options.switchTab("search"))
|
||
},
|
||
"查询",
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode("view", {
|
||
class: "tab extra",
|
||
onClick: _cache[2] || (_cache[2] = (...args) => $options.goMySubmissions && $options.goMySubmissions(...args))
|
||
}, "我的提交")
|
||
]),
|
||
$data.tab === "search" ? (vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
key: 0,
|
||
class: vue.normalizeClass(["search", { "template-mode": $data.query.mode === "template" }])
|
||
},
|
||
[
|
||
vue.createElementVNode("view", { class: "mode" }, [
|
||
vue.createElementVNode(
|
||
"picker",
|
||
{
|
||
mode: "selector",
|
||
range: ["直接查询", "名称模糊查询", "按模板参数查询"],
|
||
onChange: _cache[3] || (_cache[3] = (e) => $data.query.mode = ["direct", "nameLike", "template"][Number(e.detail.value)] || "direct")
|
||
},
|
||
[
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
vue.toDisplayString($options.modeLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
],
|
||
32
|
||
/* NEED_HYDRATION */
|
||
)
|
||
]),
|
||
$data.query.mode === "direct" || $data.query.mode === "nameLike" ? vue.withDirectives((vue.openBlock(), vue.createElementBlock(
|
||
"input",
|
||
{
|
||
key: 0,
|
||
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.query.kw = $event),
|
||
placeholder: "输入名称/条码/规格查询",
|
||
onConfirm: _cache[5] || (_cache[5] = (...args) => $options.reload && $options.reload(...args))
|
||
},
|
||
null,
|
||
544
|
||
/* NEED_HYDRATION, NEED_PATCH */
|
||
)), [
|
||
[
|
||
vue.vModelText,
|
||
$data.query.kw,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]) : vue.createCommentVNode("v-if", true),
|
||
$data.query.mode === "template" ? (vue.openBlock(), vue.createElementBlock(
|
||
vue.Fragment,
|
||
{ key: 1 },
|
||
[
|
||
vue.createElementVNode("view", { class: "picker-row" }, [
|
||
vue.createElementVNode("picker", {
|
||
mode: "selector",
|
||
range: $options.categoryNames,
|
||
onChange: _cache[6] || (_cache[6] = (...args) => $options.onPickCategory && $options.onPickCategory(...args))
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
vue.toDisplayString($options.categoryLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["range"]),
|
||
vue.createElementVNode("picker", {
|
||
mode: "selector",
|
||
range: $options.templateNames,
|
||
onChange: _cache[7] || (_cache[7] = (...args) => $options.onPickTemplate && $options.onPickTemplate(...args))
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
vue.toDisplayString($options.templateLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["range"])
|
||
]),
|
||
vue.createElementVNode("view", { class: "params-wrap" }, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($options.selectedTemplateParams, (p, idx) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
class: "param-row",
|
||
key: p.fieldKey
|
||
}, [
|
||
p.type === "string" ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
|
||
key: 0,
|
||
"onUpdate:modelValue": ($event) => $data.paramValues[p.fieldKey] = $event,
|
||
placeholder: "输入" + p.fieldLabel
|
||
}, null, 8, ["onUpdate:modelValue", "placeholder"])), [
|
||
[
|
||
vue.vModelText,
|
||
$data.paramValues[p.fieldKey],
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]) : p.type === "number" ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
|
||
key: 1,
|
||
type: "number",
|
||
"onUpdate:modelValue": ($event) => $data.paramValues[p.fieldKey] = $event,
|
||
placeholder: "输入" + p.fieldLabel
|
||
}, null, 8, ["onUpdate:modelValue", "placeholder"])), [
|
||
[
|
||
vue.vModelText,
|
||
$data.paramValues[p.fieldKey],
|
||
void 0,
|
||
{ number: true }
|
||
]
|
||
]) : p.type === "boolean" ? (vue.openBlock(), vue.createElementBlock("switch", {
|
||
key: 2,
|
||
checked: !!$data.paramValues[p.fieldKey],
|
||
onChange: ($event) => $options.onParamBoolChange(p, $event)
|
||
}, null, 40, ["checked", "onChange"])) : p.type === "enum" ? (vue.openBlock(), vue.createElementBlock("picker", {
|
||
key: 3,
|
||
mode: "selector",
|
||
range: p.enumOptions || [],
|
||
onChange: ($event) => $options.onPickParamEnumWrapper(p, $event)
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
vue.toDisplayString(_ctx.displayParamEnum(p)),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["range", "onChange"])) : p.type === "date" ? (vue.openBlock(), vue.createElementBlock("picker", {
|
||
key: 4,
|
||
mode: "date",
|
||
onChange: ($event) => $options.onParamDateChange(p, $event)
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
vue.toDisplayString($data.paramValues[p.fieldKey] || "选择" + p.fieldLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["onChange"])) : vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
|
||
key: 5,
|
||
"onUpdate:modelValue": ($event) => $data.paramValues[p.fieldKey] = $event,
|
||
placeholder: "输入" + p.fieldLabel
|
||
}, null, 8, ["onUpdate:modelValue", "placeholder"])), [
|
||
[
|
||
vue.vModelText,
|
||
$data.paramValues[p.fieldKey],
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])
|
||
],
|
||
64
|
||
/* STABLE_FRAGMENT */
|
||
)) : vue.createCommentVNode("v-if", true),
|
||
vue.createElementVNode("button", {
|
||
size: "mini",
|
||
onClick: _cache[8] || (_cache[8] = (...args) => $options.reload && $options.reload(...args))
|
||
}, "查询")
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)) : vue.createCommentVNode("v-if", true),
|
||
vue.createElementVNode(
|
||
"scroll-view",
|
||
{
|
||
"scroll-y": "",
|
||
class: "list",
|
||
onScrolltolower: _cache[9] || (_cache[9] = (...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.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.createElementVNode(
|
||
"text",
|
||
null,
|
||
vue.toDisplayString(it.name),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
it.deleted ? (vue.openBlock(), vue.createElementBlock("text", {
|
||
key: 0,
|
||
class: "tag-deleted"
|
||
}, "已删除")) : vue.createCommentVNode("v-if", true),
|
||
it.platformStatus === "platform" ? (vue.openBlock(), vue.createElementBlock("text", {
|
||
key: 1,
|
||
class: "tag-platform"
|
||
}, "平台推荐")) : it.sourceSubmissionId ? (vue.openBlock(), vue.createElementBlock("text", {
|
||
key: 2,
|
||
class: "tag-custom"
|
||
}, "我的提交")) : vue.createCommentVNode("v-if", true)
|
||
]),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "meta" },
|
||
vue.toDisplayString(it.brand || "-") + " " + vue.toDisplayString(it.model || "") + " " + vue.toDisplayString(it.spec || ""),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
it.cardParams && Object.keys(it.cardParams).length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "card-params"
|
||
}, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList(it.cardParams, (v, k) => {
|
||
return vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
class: "param",
|
||
key: k
|
||
},
|
||
vue.toDisplayString(k) + ":" + vue.toDisplayString(v),
|
||
1
|
||
/* TEXT */
|
||
);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])) : vue.createCommentVNode("v-if", true)
|
||
])
|
||
], 8, ["onClick"]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
)) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "empty"
|
||
}, [
|
||
vue.createElementVNode("text", null, "暂无数据,点击右上角“+”新增")
|
||
]))
|
||
],
|
||
32
|
||
/* NEED_HYDRATION */
|
||
),
|
||
vue.createCommentVNode(" 保留“我的提交”页的+,此处不显示 ")
|
||
]);
|
||
}
|
||
const PagesProductList = /* @__PURE__ */ _export_sfc(_sfc_main$r, [["render", _sfc_render$q], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/list.vue"]]);
|
||
const _imports_0$3 = "/static/icons/icons8-close-48.png";
|
||
const ITEM_SIZE = 210;
|
||
const GAP = 18;
|
||
const COLS = 3;
|
||
function px(rpx) {
|
||
return rpx;
|
||
}
|
||
const _sfc_main$q = {
|
||
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;
|
||
},
|
||
adderStyle() {
|
||
const index = this.innerList.length;
|
||
const row = Math.floor(index / COLS);
|
||
const col = index % COLS;
|
||
const x = px(col * (ITEM_SIZE + GAP));
|
||
const y = px(row * (ITEM_SIZE + GAP));
|
||
return { left: x + "rpx", top: y + "rpx" };
|
||
}
|
||
},
|
||
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: this.ensureAbsoluteUrl(typeof u === "string" ? u : u.url || ""),
|
||
x: this.posOf(i).x,
|
||
y: this.posOf(i).y
|
||
}));
|
||
this.innerList = mapped;
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
ensureAbsoluteUrl(u) {
|
||
if (!u)
|
||
return "";
|
||
const s = String(u);
|
||
if (s.startsWith("http://") || s.startsWith("https://"))
|
||
return s;
|
||
return API_BASE_URL + (s.startsWith("/") ? s : "/" + s);
|
||
},
|
||
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 = this.ensureAbsoluteUrl((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$p(_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("image", {
|
||
class: "remove",
|
||
src: _imports_0$3,
|
||
mode: "aspectFit",
|
||
onClick: vue.withModifiers(($event) => $options.remove(index), ["stop"])
|
||
}, null, 8, ["onClick"])
|
||
], 44, ["x", "y", "onChange", "onTouchend"]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
)),
|
||
$data.innerList.length < $props.max ? (vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
key: 0,
|
||
class: "adder",
|
||
style: vue.normalizeStyle($options.adderStyle),
|
||
onClick: _cache[0] || (_cache[0] = (...args) => $options.choose && $options.choose(...args))
|
||
},
|
||
[
|
||
vue.createElementVNode("text", null, "+")
|
||
],
|
||
4
|
||
/* STYLE */
|
||
)) : vue.createCommentVNode("v-if", true)
|
||
],
|
||
4
|
||
/* STYLE */
|
||
)
|
||
],
|
||
4
|
||
/* STYLE */
|
||
)
|
||
]);
|
||
}
|
||
const ImageUploader = /* @__PURE__ */ _export_sfc(_sfc_main$q, [["render", _sfc_render$p], ["__scopeId", "data-v-7bd1ddd2"], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/components/ImageUploader.vue"]]);
|
||
const _sfc_main$p = {
|
||
components: { ImageUploader },
|
||
data() {
|
||
return {
|
||
form: {
|
||
model: "",
|
||
brand: "",
|
||
barcode: "",
|
||
categoryId: "",
|
||
templateId: "",
|
||
externalCode: "",
|
||
parameters: {},
|
||
images: [],
|
||
remark: "",
|
||
safeMin: null,
|
||
safeMax: null
|
||
},
|
||
templates: [],
|
||
paramValues: {},
|
||
checking: false,
|
||
parameterText: "",
|
||
categories: [],
|
||
submitting: false,
|
||
paramPlaceholder: '可输入 JSON,如 {"颜色":"黑","材质":"钢"}'
|
||
};
|
||
},
|
||
computed: {
|
||
categoryNames() {
|
||
return this.categories.map((c) => c.name);
|
||
},
|
||
templateNames() {
|
||
return this.templates.map((t) => t.name);
|
||
},
|
||
categoryLabel() {
|
||
const c = this.categories.find((x) => String(x.id) === String(this.form.categoryId));
|
||
return c ? c.name : "选择类别";
|
||
},
|
||
selectedTemplate() {
|
||
return this.templates.find((t) => String(t.id) === String(this.form.templateId));
|
||
},
|
||
templateLabel() {
|
||
const t = this.selectedTemplate;
|
||
return t ? `${t.name}` : "选择模板";
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
this.bootstrap();
|
||
if (options && options.prefill) {
|
||
try {
|
||
const data = JSON.parse(decodeURIComponent(options.prefill));
|
||
Object.assign(this.form, {
|
||
model: data.model || "",
|
||
brand: data.brand || "",
|
||
barcode: data.barcode || "",
|
||
categoryId: data.categoryId || "",
|
||
remark: data.remark || ""
|
||
});
|
||
if (data.parameters && typeof data.parameters === "object") {
|
||
this.parameterText = JSON.stringify(data.parameters, null, 2);
|
||
}
|
||
} catch (_) {
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
async bootstrap() {
|
||
await Promise.all([this.fetchCategories()]);
|
||
await this.fetchTemplates();
|
||
},
|
||
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 (_) {
|
||
this.categories = [];
|
||
}
|
||
},
|
||
async fetchTemplates() {
|
||
try {
|
||
const res = await get("/api/product-templates", this.form.categoryId ? { categoryId: this.form.categoryId } : {});
|
||
const list = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
|
||
this.templates = list;
|
||
} catch (_) {
|
||
this.templates = [];
|
||
}
|
||
},
|
||
onPickCategory(e) {
|
||
const idx = Number(e.detail.value);
|
||
const c = this.categories[idx];
|
||
this.form.categoryId = c ? c.id : "";
|
||
this.fetchTemplates();
|
||
},
|
||
onPickTemplate(e) {
|
||
const idx = Number(e.detail.value);
|
||
const t = this.templates[idx];
|
||
this.form.templateId = t ? t.id : "";
|
||
this.paramValues = {};
|
||
},
|
||
onPickDate(p, e) {
|
||
var _a;
|
||
this.paramValues[p.fieldKey] = ((_a = e == null ? void 0 : e.detail) == null ? void 0 : _a.value) || "";
|
||
},
|
||
onPickEnum(p, e) {
|
||
const idx = Number(e.detail.value);
|
||
const arr = p.enumOptions || [];
|
||
this.paramValues[p.fieldKey] = arr[idx];
|
||
},
|
||
displayEnum(p) {
|
||
const v = this.paramValues[p.fieldKey];
|
||
return v === void 0 || v === null || v === "" ? "选择" + p.fieldLabel : String(v);
|
||
},
|
||
async scanBarcode() {
|
||
var _a;
|
||
try {
|
||
const chooseRes = await uni.chooseImage({ count: 1, sourceType: ["camera", "album"], sizeType: ["compressed"] });
|
||
let filePath = chooseRes.tempFilePaths[0];
|
||
try {
|
||
const comp = await uni.compressImage({ src: filePath, quality: 80 });
|
||
filePath = comp.tempFilePath || filePath;
|
||
} catch (_) {
|
||
}
|
||
const data = await upload("/api/barcode/scan", filePath, {}, "file");
|
||
const barcode = (data == null ? void 0 : data.barcode) || ((_a = data == null ? void 0 : data.data) == null ? void 0 : _a.barcode);
|
||
if (barcode) {
|
||
this.form.barcode = barcode;
|
||
uni.showToast({ title: "识别成功", icon: "success" });
|
||
} else {
|
||
uni.showToast({ title: "未识别到条码", icon: "none" });
|
||
}
|
||
} catch (e) {
|
||
const msg = (e == null ? void 0 : e.message) || "识码失败";
|
||
uni.showToast({ title: msg, icon: "none" });
|
||
}
|
||
},
|
||
async checkModel() {
|
||
if (!this.form.model)
|
||
return uni.showToast({ title: "请填写型号", icon: "none" });
|
||
try {
|
||
this.checking = true;
|
||
const res = await post("/api/products/submissions/check-model", { templateId: this.form.templateId, model: this.form.model });
|
||
if (res && res.available) {
|
||
uni.showToast({ title: "可用,无重复", icon: "success" });
|
||
} else {
|
||
uni.showToast({ title: "已存在相同型号提交", icon: "none" });
|
||
}
|
||
} catch (e) {
|
||
const msg = (e == null ? void 0 : e.message) || "校验失败";
|
||
uni.showToast({ title: msg, icon: "none" });
|
||
} finally {
|
||
this.checking = false;
|
||
}
|
||
},
|
||
async submit() {
|
||
if (this.submitting)
|
||
return;
|
||
if (!this.form.model) {
|
||
return uni.showToast({ title: "请填写型号", icon: "none" });
|
||
}
|
||
let paramsObj = null;
|
||
if (this.parameterText) {
|
||
try {
|
||
paramsObj = JSON.parse(this.parameterText);
|
||
} catch (e) {
|
||
return uni.showToast({ title: "参数 JSON 不合法", icon: "none" });
|
||
}
|
||
}
|
||
if (this.form.safeMin != null && this.form.safeMax != null && Number(this.form.safeMin) > Number(this.form.safeMax)) {
|
||
return uni.showToast({ title: "安全库存区间不合法", icon: "none" });
|
||
}
|
||
let paramsForSubmit = paramsObj;
|
||
if (this.selectedTemplate) {
|
||
for (const p of this.selectedTemplate.params || []) {
|
||
if (p.required && (this.paramValues[p.fieldKey] === void 0 || this.paramValues[p.fieldKey] === null || this.paramValues[p.fieldKey] === "")) {
|
||
return uni.showToast({ title: `请填写 ${p.fieldLabel}`, icon: "none" });
|
||
}
|
||
}
|
||
const shaped = {};
|
||
for (const p of this.selectedTemplate.params || []) {
|
||
let v = this.paramValues[p.fieldKey];
|
||
if (p.type === "number" && v !== void 0 && v !== null && v !== "")
|
||
v = Number(v);
|
||
if (p.type === "boolean")
|
||
v = !!v;
|
||
shaped[p.fieldKey] = v;
|
||
}
|
||
paramsForSubmit = shaped;
|
||
}
|
||
const payload = {
|
||
model: this.form.model,
|
||
brand: this.form.brand,
|
||
barcode: this.form.barcode,
|
||
externalCode: this.form.externalCode || null,
|
||
categoryId: this.form.categoryId || null,
|
||
templateId: this.form.templateId || null,
|
||
parameters: paramsForSubmit,
|
||
images: this.form.images,
|
||
remark: this.form.remark,
|
||
safeMin: this.form.safeMin,
|
||
safeMax: this.form.safeMax
|
||
};
|
||
this.submitting = true;
|
||
try {
|
||
await post("/api/products/submissions", payload);
|
||
uni.showToast({ title: "提交成功", icon: "success" });
|
||
setTimeout(() => {
|
||
uni.redirectTo({ url: "/pages/product/submissions" });
|
||
}, 400);
|
||
} catch (e) {
|
||
const msg = (e == null ? void 0 : e.message) || "提交失败";
|
||
uni.showToast({ title: msg, icon: "none" });
|
||
} finally {
|
||
this.submitting = false;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$o(_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: "hero" }, [
|
||
vue.createElementVNode("text", { class: "title" }, "提交配件"),
|
||
vue.createElementVNode("text", { class: "desc" }, "填写型号、名称、参数与图片,提交后进入待审核状态")
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row required" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "型号"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($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.createElementVNode("text", { class: "label" }, "品牌"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($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.createElementVNode("text", { class: "label" }, "条码"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $data.form.barcode = $event),
|
||
placeholder: "可选,建议扫码录入"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.barcode,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
size: "mini",
|
||
class: "picker-btn",
|
||
onClick: _cache[3] || (_cache[3] = (...args) => $options.scanBarcode && $options.scanBarcode(...args))
|
||
}, "识码")
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "类别"),
|
||
vue.createElementVNode("picker", {
|
||
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.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "编号"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $data.form.externalCode = $event),
|
||
placeholder: "内部/外部编号(可选)"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.externalCode,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "模板")
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("picker", {
|
||
mode: "selector",
|
||
range: $options.templateNames,
|
||
onChange: _cache[6] || (_cache[6] = (...args) => $options.onPickTemplate && $options.onPickTemplate(...args))
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
vue.toDisplayString($options.templateLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["range"])
|
||
])
|
||
]),
|
||
vue.createCommentVNode(" 动态参数:根据模板渲染必填/可选项 "),
|
||
$options.selectedTemplate ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "section"
|
||
}, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "参数")
|
||
]),
|
||
vue.createElementVNode("view", { class: "param-list" }, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($options.selectedTemplate.params || [], (p, idx) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
class: "row",
|
||
key: p.fieldKey
|
||
}, [
|
||
vue.createElementVNode("text", { class: "label" }, [
|
||
vue.createTextVNode(
|
||
vue.toDisplayString(p.fieldLabel),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
p.unit ? (vue.openBlock(), vue.createElementBlock(
|
||
"text",
|
||
{ key: 0 },
|
||
"(" + vue.toDisplayString(p.unit) + ")",
|
||
1
|
||
/* TEXT */
|
||
)) : vue.createCommentVNode("v-if", true),
|
||
p.required ? (vue.openBlock(), vue.createElementBlock("text", {
|
||
key: 1,
|
||
style: { "color": "#ff5b5b" }
|
||
}, "*")) : vue.createCommentVNode("v-if", true)
|
||
]),
|
||
p.type === "string" ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
|
||
key: 0,
|
||
"onUpdate:modelValue": ($event) => $data.paramValues[p.fieldKey] = $event,
|
||
placeholder: "请输入" + p.fieldLabel
|
||
}, null, 8, ["onUpdate:modelValue", "placeholder"])), [
|
||
[
|
||
vue.vModelText,
|
||
$data.paramValues[p.fieldKey],
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]) : p.type === "number" ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
|
||
key: 1,
|
||
type: "number",
|
||
"onUpdate:modelValue": ($event) => $data.paramValues[p.fieldKey] = $event,
|
||
placeholder: "请输入" + p.fieldLabel
|
||
}, null, 8, ["onUpdate:modelValue", "placeholder"])), [
|
||
[
|
||
vue.vModelText,
|
||
$data.paramValues[p.fieldKey],
|
||
void 0,
|
||
{ number: true }
|
||
]
|
||
]) : p.type === "boolean" ? (vue.openBlock(), vue.createElementBlock("switch", {
|
||
key: 2,
|
||
checked: !!$data.paramValues[p.fieldKey],
|
||
onChange: (e) => $data.paramValues[p.fieldKey] = e.detail.value
|
||
}, null, 40, ["checked", "onChange"])) : p.type === "enum" ? (vue.openBlock(), vue.createElementBlock("picker", {
|
||
key: 3,
|
||
mode: "selector",
|
||
range: p.enumOptions || [],
|
||
onChange: ($event) => $options.onPickEnum(p, $event)
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
vue.toDisplayString($options.displayEnum(p)),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["range", "onChange"])) : p.type === "date" ? (vue.openBlock(), vue.createElementBlock("picker", {
|
||
key: 4,
|
||
mode: "date",
|
||
onChange: ($event) => $options.onPickDate(p, $event)
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
vue.toDisplayString($data.paramValues[p.fieldKey] || "选择" + p.fieldLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["onChange"])) : vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
|
||
key: 5,
|
||
"onUpdate:modelValue": ($event) => $data.paramValues[p.fieldKey] = $event,
|
||
placeholder: "请输入" + p.fieldLabel
|
||
}, null, 8, ["onUpdate:modelValue", "placeholder"])), [
|
||
[
|
||
vue.vModelText,
|
||
$data.paramValues[p.fieldKey],
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])
|
||
])) : vue.createCommentVNode("v-if", true),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "图片")
|
||
]),
|
||
vue.createVNode(_component_ImageUploader, {
|
||
modelValue: $data.form.images,
|
||
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $data.form.images = $event),
|
||
max: 9,
|
||
formData: { ownerType: "submission" }
|
||
}, null, 8, ["modelValue"])
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "备注")
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"textarea",
|
||
{
|
||
class: "textarea",
|
||
"onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => $data.form.remark = $event),
|
||
placeholder: "选填:补充说明"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.remark,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "安全库存")
|
||
]),
|
||
vue.createElementVNode("view", { class: "row triple" }, [
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
type: "number",
|
||
"onUpdate:modelValue": _cache[9] || (_cache[9] = ($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[10] || (_cache[10] = ($event) => $data.form.safeMax = $event),
|
||
placeholder: "上限"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.safeMax,
|
||
void 0,
|
||
{ number: true }
|
||
]
|
||
])
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "fixed" }, [
|
||
vue.createElementVNode("button", {
|
||
class: "primary",
|
||
loading: $data.submitting,
|
||
onClick: _cache[11] || (_cache[11] = (...args) => $options.submit && $options.submit(...args))
|
||
}, "提交审核", 8, ["loading"]),
|
||
vue.createElementVNode("button", {
|
||
class: "primary",
|
||
style: { "margin-top": "16rpx", "background": "#7aa9ff" },
|
||
loading: $data.checking,
|
||
onClick: _cache[12] || (_cache[12] = (...args) => $options.checkModel && $options.checkModel(...args))
|
||
}, "查重", 8, ["loading"])
|
||
])
|
||
]);
|
||
}
|
||
const PagesProductSubmit = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["render", _sfc_render$o], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/submit.vue"]]);
|
||
const _sfc_main$o = {
|
||
data() {
|
||
return {
|
||
status: "",
|
||
items: [],
|
||
page: 1,
|
||
size: 20,
|
||
total: 0,
|
||
loading: false,
|
||
finished: false,
|
||
cacheUnitsLoaded: false,
|
||
cacheCategoriesLoaded: false
|
||
};
|
||
},
|
||
onShow() {
|
||
this.preloadDictionaries();
|
||
this.reload();
|
||
},
|
||
methods: {
|
||
async preloadDictionaries() {
|
||
try {
|
||
const [units, categories, templates] = await Promise.all([
|
||
this.cacheUnitsLoaded ? Promise.resolve(null) : get("/api/product-units"),
|
||
this.cacheCategoriesLoaded ? Promise.resolve(null) : get("/api/product-categories"),
|
||
get("/api/product-templates")
|
||
]);
|
||
if (units) {
|
||
const list = Array.isArray(units == null ? void 0 : units.list) ? units.list : Array.isArray(units) ? units : [];
|
||
uni.setStorageSync("CACHE_UNITS", list);
|
||
this.cacheUnitsLoaded = true;
|
||
}
|
||
if (categories) {
|
||
const list = Array.isArray(categories == null ? void 0 : categories.list) ? categories.list : Array.isArray(categories) ? categories : [];
|
||
uni.setStorageSync("CACHE_CATEGORIES", list);
|
||
this.cacheCategoriesLoaded = true;
|
||
}
|
||
if (templates) {
|
||
const list = Array.isArray(templates == null ? void 0 : templates.list) ? templates.list : Array.isArray(templates) ? templates : [];
|
||
uni.setStorageSync("CACHE_TEMPLATES", list);
|
||
}
|
||
} catch (_) {
|
||
}
|
||
},
|
||
switchStatus(s) {
|
||
if (this.status === s)
|
||
return;
|
||
this.status = s;
|
||
this.reload();
|
||
},
|
||
async reload() {
|
||
this.page = 1;
|
||
this.items = [];
|
||
this.finished = false;
|
||
await this.loadMore();
|
||
},
|
||
async loadMore() {
|
||
if (this.loading || this.finished)
|
||
return;
|
||
this.loading = true;
|
||
try {
|
||
const params = { page: this.page, size: this.size };
|
||
if (this.status)
|
||
params.status = this.status;
|
||
const res = await get("/api/products/submissions", params);
|
||
const list = Array.isArray(res == null ? void 0 : res.list) ? res.list : [];
|
||
this.items = this.items.concat(list);
|
||
this.total = Number((res == null ? void 0 : res.total) || this.items.length);
|
||
if (list.length < this.size)
|
||
this.finished = true;
|
||
this.page += 1;
|
||
} catch (e) {
|
||
formatAppLog("warn", "at pages/product/submissions.vue:118", "加载提交记录失败", e);
|
||
const msg = (e == null ? void 0 : e.message) || "加载失败";
|
||
uni.showToast({ title: msg, icon: "none" });
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
statusLabel(s) {
|
||
if (s === "approved")
|
||
return "已通过";
|
||
if (s === "rejected")
|
||
return "已驳回";
|
||
return "待审核";
|
||
},
|
||
statusClass(s) {
|
||
if (s === "approved")
|
||
return "approved";
|
||
if (s === "rejected")
|
||
return "rejected";
|
||
return "pending";
|
||
},
|
||
formatTime(value) {
|
||
if (!value)
|
||
return "-";
|
||
try {
|
||
const d = new Date(value);
|
||
if (!Number.isFinite(d.getTime()))
|
||
return value;
|
||
const y = d.getFullYear();
|
||
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||
const day = String(d.getDate()).padStart(2, "0");
|
||
const hh = String(d.getHours()).padStart(2, "0");
|
||
const mm = String(d.getMinutes()).padStart(2, "0");
|
||
return `${y}-${m}-${day} ${hh}:${mm}`;
|
||
} catch (_) {
|
||
return value;
|
||
}
|
||
},
|
||
viewDetail(id) {
|
||
uni.navigateTo({ url: `/pages/product/submission-detail?id=${id}` });
|
||
},
|
||
notifyPending() {
|
||
uni.showToast({ title: "审核中,请耐心等待", icon: "none" });
|
||
},
|
||
resubmit(item) {
|
||
const payload = {
|
||
model: item.model,
|
||
name: item.name,
|
||
brand: item.brand,
|
||
spec: item.spec,
|
||
origin: item.origin,
|
||
unitId: item.unitId,
|
||
categoryId: item.categoryId,
|
||
remark: item.remark
|
||
};
|
||
const query = encodeURIComponent(JSON.stringify(payload));
|
||
uni.navigateTo({ url: `/pages/product/submit?prefill=${query}` });
|
||
},
|
||
goSubmit() {
|
||
uni.navigateTo({ url: "/pages/product/submit" });
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$n(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
|
||
vue.createElementVNode("view", { class: "hero" }, [
|
||
vue.createElementVNode("text", { class: "title" }, "我的配件提交"),
|
||
vue.createElementVNode("text", { class: "desc" }, "查看待审核、已通过、已驳回的记录")
|
||
]),
|
||
vue.createElementVNode("view", { class: "tabs" }, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["tab", { active: $data.status === "" }]),
|
||
onClick: _cache[0] || (_cache[0] = ($event) => $options.switchStatus(""))
|
||
},
|
||
"全部",
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["tab", { active: $data.status === "pending" }]),
|
||
onClick: _cache[1] || (_cache[1] = ($event) => $options.switchStatus("pending"))
|
||
},
|
||
"待审核",
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["tab", { active: $data.status === "approved" }]),
|
||
onClick: _cache[2] || (_cache[2] = ($event) => $options.switchStatus("approved"))
|
||
},
|
||
"已通过",
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["tab", { active: $data.status === "rejected" }]),
|
||
onClick: _cache[3] || (_cache[3] = ($event) => $options.switchStatus("rejected"))
|
||
},
|
||
"已驳回",
|
||
2
|
||
/* CLASS */
|
||
)
|
||
]),
|
||
vue.createElementVNode(
|
||
"scroll-view",
|
||
{
|
||
"scroll-y": "",
|
||
class: "list",
|
||
onScrolltolower: _cache[6] || (_cache[6] = (...args) => $options.loadMore && $options.loadMore(...args))
|
||
},
|
||
[
|
||
$data.items.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "cards"
|
||
}, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($data.items, (item) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
class: "card",
|
||
key: item.id
|
||
}, [
|
||
vue.createElementVNode("view", { class: "card-header" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "model" },
|
||
vue.toDisplayString(item.model || "-"),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{
|
||
class: vue.normalizeClass(["status", $options.statusClass(item.status)])
|
||
},
|
||
vue.toDisplayString($options.statusLabel(item.status)),
|
||
3
|
||
/* TEXT, CLASS */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "card-body" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "name" },
|
||
vue.toDisplayString(item.name || "未填写名称"),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "brand" },
|
||
"品牌:" + vue.toDisplayString(item.brand || "-"),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "time" },
|
||
"提交:" + vue.toDisplayString($options.formatTime(item.createdAt)),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
item.reviewedAt ? (vue.openBlock(), vue.createElementBlock(
|
||
"text",
|
||
{
|
||
key: 0,
|
||
class: "time"
|
||
},
|
||
"审核:" + vue.toDisplayString($options.formatTime(item.reviewedAt)),
|
||
1
|
||
/* TEXT */
|
||
)) : vue.createCommentVNode("v-if", true)
|
||
]),
|
||
vue.createElementVNode("view", { class: "card-footer" }, [
|
||
vue.createElementVNode("button", {
|
||
size: "mini",
|
||
onClick: ($event) => $options.viewDetail(item.id)
|
||
}, "详情", 8, ["onClick"]),
|
||
item.status === "pending" ? (vue.openBlock(), vue.createElementBlock("button", {
|
||
key: 0,
|
||
size: "mini",
|
||
type: "primary",
|
||
onClick: _cache[4] || (_cache[4] = (...args) => $options.notifyPending && $options.notifyPending(...args))
|
||
}, "等待审核")) : item.status === "rejected" ? (vue.openBlock(), vue.createElementBlock("button", {
|
||
key: 1,
|
||
size: "mini",
|
||
type: "warn",
|
||
onClick: ($event) => $options.resubmit(item)
|
||
}, "重新提交", 8, ["onClick"])) : vue.createCommentVNode("v-if", true)
|
||
])
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "empty"
|
||
}, [
|
||
vue.createElementVNode("text", null, "暂无提交记录,快去提交新的配件吧"),
|
||
vue.createElementVNode("button", {
|
||
size: "mini",
|
||
class: "primary",
|
||
onClick: _cache[5] || (_cache[5] = (...args) => $options.goSubmit && $options.goSubmit(...args))
|
||
}, "立即提交")
|
||
])),
|
||
$data.loading ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 2,
|
||
class: "loading"
|
||
}, "加载中...")) : $data.finished && $data.items.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 3,
|
||
class: "finished"
|
||
}, "没有更多了")) : vue.createCommentVNode("v-if", true)
|
||
],
|
||
32
|
||
/* NEED_HYDRATION */
|
||
),
|
||
vue.createElementVNode("view", {
|
||
class: "fab",
|
||
onClick: _cache[7] || (_cache[7] = (...args) => $options.goSubmit && $options.goSubmit(...args))
|
||
}, "+")
|
||
]);
|
||
}
|
||
const PagesProductSubmissions = /* @__PURE__ */ _export_sfc(_sfc_main$o, [["render", _sfc_render$n], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/submissions.vue"]]);
|
||
const _sfc_main$n = {
|
||
data() {
|
||
return {
|
||
id: "",
|
||
detail: null,
|
||
unitName: "-",
|
||
categoryName: "-",
|
||
templateName: "-"
|
||
};
|
||
},
|
||
async onLoad(query) {
|
||
this.id = (query == null ? void 0 : query.id) || "";
|
||
if (!this.id) {
|
||
uni.showToast({ title: "参数缺失", icon: "none" });
|
||
return;
|
||
}
|
||
await this.loadDetail();
|
||
},
|
||
methods: {
|
||
async loadDetail() {
|
||
try {
|
||
const data = await get(`/api/products/submissions/${this.id}`);
|
||
this.detail = data;
|
||
this.categoryName = this.categoryLookup(data.categoryId);
|
||
this.templateName = this.templateLookup(data.templateId);
|
||
} catch (e) {
|
||
const msg = (e == null ? void 0 : e.message) || "加载失败";
|
||
uni.showToast({ title: msg, icon: "none" });
|
||
}
|
||
},
|
||
statusLabel(s) {
|
||
if (s === "approved")
|
||
return "已通过";
|
||
if (s === "rejected")
|
||
return "已驳回";
|
||
return "待审核";
|
||
},
|
||
statusClass(s) {
|
||
if (s === "approved")
|
||
return "approved";
|
||
if (s === "rejected")
|
||
return "rejected";
|
||
return "pending";
|
||
},
|
||
preview(idx) {
|
||
var _a;
|
||
if (!((_a = this.detail) == null ? void 0 : _a.images) || !this.detail.images.length)
|
||
return;
|
||
uni.previewImage({ urls: this.detail.images, current: idx });
|
||
},
|
||
formatTime(value) {
|
||
if (!value)
|
||
return "-";
|
||
try {
|
||
const d = new Date(value);
|
||
if (!Number.isFinite(d.getTime()))
|
||
return value;
|
||
const y = d.getFullYear();
|
||
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||
const day = String(d.getDate()).padStart(2, "0");
|
||
const hh = String(d.getHours()).padStart(2, "0");
|
||
const mm = String(d.getMinutes()).padStart(2, "0");
|
||
return `${y}-${m}-${day} ${hh}:${mm}`;
|
||
} catch (_) {
|
||
return value;
|
||
}
|
||
},
|
||
unitLookup(id) {
|
||
try {
|
||
const list = [];
|
||
const found = list.find((x) => String(x.id) === String(id));
|
||
return found ? found.name : "-";
|
||
} catch (_) {
|
||
return "-";
|
||
}
|
||
},
|
||
categoryLookup(id) {
|
||
try {
|
||
const list = uni.getStorageSync("CACHE_CATEGORIES") || [];
|
||
const found = list.find((x) => String(x.id) === String(id));
|
||
return found ? found.name : "-";
|
||
} catch (_) {
|
||
return "-";
|
||
}
|
||
},
|
||
templateLookup(id) {
|
||
try {
|
||
const list = uni.getStorageSync("CACHE_TEMPLATES") || [];
|
||
const found = list.find((x) => String(x.id) === String(id));
|
||
return found ? found.name : "-";
|
||
} catch (_) {
|
||
return "-";
|
||
}
|
||
},
|
||
back() {
|
||
uni.navigateBack({ delta: 1 });
|
||
},
|
||
resubmit() {
|
||
const payload = {
|
||
model: this.detail.model,
|
||
name: this.detail.name,
|
||
brand: this.detail.brand,
|
||
spec: this.detail.spec,
|
||
origin: this.detail.origin,
|
||
unitId: this.detail.unitId,
|
||
categoryId: this.detail.categoryId,
|
||
remark: this.detail.remark,
|
||
barcode: this.detail.barcode,
|
||
parameters: this.detail.parameters
|
||
};
|
||
const query = encodeURIComponent(JSON.stringify(payload));
|
||
uni.navigateTo({ url: `/pages/product/submit?prefill=${query}` });
|
||
}
|
||
},
|
||
computed: {
|
||
stockRange() {
|
||
var _a, _b;
|
||
const min = (_a = this.detail) == null ? void 0 : _a.safeMin;
|
||
const max = (_b = this.detail) == null ? void 0 : _b.safeMax;
|
||
if (min == null && max == null)
|
||
return "-";
|
||
if (min != null && max != null)
|
||
return `${min} ~ ${max}`;
|
||
if (min != null)
|
||
return `≥ ${min}`;
|
||
return `≤ ${max}`;
|
||
},
|
||
labeledPairs() {
|
||
var _a;
|
||
const params = (_a = this.detail) == null ? void 0 : _a.parameters;
|
||
if (!params || typeof params !== "object")
|
||
return [];
|
||
let labelMap = {};
|
||
try {
|
||
const templates = uni.getStorageSync("CACHE_TEMPLATES") || [];
|
||
const tpl = templates.find((t) => {
|
||
var _a2;
|
||
return String(t.id) === String((_a2 = this.detail) == null ? void 0 : _a2.templateId);
|
||
});
|
||
if (tpl && Array.isArray(tpl.params)) {
|
||
for (const p of tpl.params)
|
||
labelMap[p.fieldKey] = p.fieldLabel;
|
||
}
|
||
} catch (_) {
|
||
}
|
||
return Object.keys(params).map((k) => ({ key: k, label: labelMap[k] || k, value: params[k] }));
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$m(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return $data.detail ? (vue.openBlock(), vue.createElementBlock("scroll-view", {
|
||
key: 0,
|
||
"scroll-y": "",
|
||
class: "page"
|
||
}, [
|
||
vue.createElementVNode("view", { class: "header" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "model" },
|
||
vue.toDisplayString($data.detail.model),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{
|
||
class: vue.normalizeClass(["status", $options.statusClass($data.detail.status)])
|
||
},
|
||
vue.toDisplayString($options.statusLabel($data.detail.status)),
|
||
3
|
||
/* TEXT, CLASS */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "名称"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.name || "-"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "品牌"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.brand || "-"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "规格"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.spec || "-"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "条码"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.barcode || "-"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "类别"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.categoryName),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "模板"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.templateName),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createCommentVNode(" 隐藏产地/单位/安全库存显示 ")
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "block-title" }, "参数"),
|
||
$options.labeledPairs.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "params"
|
||
}, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($options.labeledPairs, (item) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
class: "param",
|
||
key: item.key
|
||
}, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "param-key" },
|
||
vue.toDisplayString(item.label),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "param-val" },
|
||
vue.toDisplayString(item.value),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "placeholder"
|
||
}, "未填写参数"))
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "block-title" }, "图片"),
|
||
$data.detail.images && $data.detail.images.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "images"
|
||
}, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($data.detail.images, (img, idx) => {
|
||
return vue.openBlock(), vue.createElementBlock("image", {
|
||
key: idx,
|
||
src: img,
|
||
class: "image",
|
||
mode: "aspectFill",
|
||
onClick: ($event) => $options.preview(idx)
|
||
}, null, 8, ["src", "onClick"]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "placeholder"
|
||
}, "未上传图片"))
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "block-title" }, "备注"),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "placeholder" },
|
||
vue.toDisplayString($data.detail.remark || "无"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "提交时间"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($options.formatTime($data.detail.createdAt)),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "审核时间"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($options.formatTime($data.detail.reviewedAt)),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
$data.detail.reviewRemark ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "row"
|
||
}, [
|
||
vue.createElementVNode("text", { class: "label" }, "审核说明"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.reviewRemark),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])) : vue.createCommentVNode("v-if", true)
|
||
]),
|
||
vue.createElementVNode("view", { class: "footer" }, [
|
||
vue.createElementVNode("button", {
|
||
size: "mini",
|
||
onClick: _cache[0] || (_cache[0] = (...args) => $options.back && $options.back(...args))
|
||
}, "返回"),
|
||
$data.detail.status === "rejected" ? (vue.openBlock(), vue.createElementBlock("button", {
|
||
key: 0,
|
||
size: "mini",
|
||
type: "warn",
|
||
onClick: _cache[1] || (_cache[1] = (...args) => $options.resubmit && $options.resubmit(...args))
|
||
}, "重新提交")) : vue.createCommentVNode("v-if", true)
|
||
])
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "loading"
|
||
}, "加载中..."));
|
||
}
|
||
const PagesProductSubmissionDetail = /* @__PURE__ */ _export_sfc(_sfc_main$n, [["render", _sfc_render$m], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/submission-detail.vue"]]);
|
||
const _sfc_main$m = {
|
||
components: { ImageUploader },
|
||
data() {
|
||
return {
|
||
id: "",
|
||
form: {
|
||
name: "",
|
||
barcode: "",
|
||
brand: "",
|
||
model: "",
|
||
spec: "",
|
||
categoryId: "",
|
||
images: [],
|
||
remark: "",
|
||
platformStatus: "",
|
||
sourceSubmissionId: ""
|
||
},
|
||
categories: [],
|
||
keyboardHeight: 0
|
||
};
|
||
},
|
||
onLoad(query) {
|
||
this.id = (query == null ? void 0 : query.id) || "";
|
||
this.bootstrap();
|
||
this.initKeyboardListener();
|
||
},
|
||
onUnload() {
|
||
this.disposeKeyboardListener();
|
||
},
|
||
computed: {
|
||
categoryNames() {
|
||
return this.categories.map((c) => c.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.fetchCategories()]);
|
||
if (this.id)
|
||
this.loadDetail();
|
||
},
|
||
initKeyboardListener() {
|
||
try {
|
||
this.__keyboardListener = (e) => {
|
||
const h = e && (e.height || e.targetHeight || 0) || 0;
|
||
this.keyboardHeight = h;
|
||
};
|
||
uni.onKeyboardHeightChange && uni.onKeyboardHeightChange(this.__keyboardListener);
|
||
} catch (_) {
|
||
}
|
||
},
|
||
disposeKeyboardListener() {
|
||
try {
|
||
if (this.__keyboardListener && uni.offKeyboardHeightChange) {
|
||
uni.offKeyboardHeightChange(this.__keyboardListener);
|
||
}
|
||
} 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 (_) {
|
||
}
|
||
},
|
||
onPickCategory(e) {
|
||
const idx = Number(e.detail.value);
|
||
const c = this.categories[idx];
|
||
this.form.categoryId = c ? c.id : "";
|
||
},
|
||
async chooseAndScanBarcode() {
|
||
try {
|
||
const chooseRes = await uni.chooseImage({ count: 1, sourceType: ["camera", "album"], sizeType: ["compressed"] });
|
||
let filePath = chooseRes.tempFilePaths[0];
|
||
try {
|
||
const comp = await uni.compressImage({ src: filePath, quality: 80 });
|
||
filePath = comp.tempFilePath || filePath;
|
||
} catch (e) {
|
||
}
|
||
const data = await upload("/api/barcode/scan", filePath, {}, "file");
|
||
if (data && data.success && data.barcode) {
|
||
this.form.barcode = data.barcode;
|
||
uni.showToast({ title: "识别成功", icon: "success", mask: false });
|
||
return;
|
||
}
|
||
const msg = data && (data.message || data.error || data.msg) || "未识别";
|
||
uni.showToast({ title: msg, icon: "none", mask: false });
|
||
} catch (e) {
|
||
const msg = e && e.message ? String(e.message) : "网络异常或服务不可用";
|
||
uni.showToast({ title: msg, icon: "none", mask: false });
|
||
}
|
||
},
|
||
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,
|
||
categoryId: data.categoryId,
|
||
images: (data.images || []).map((i) => i.url || i),
|
||
remark: data.remark || "",
|
||
platformStatus: data.platformStatus || "",
|
||
sourceSubmissionId: data.sourceSubmissionId || ""
|
||
});
|
||
} catch (_) {
|
||
}
|
||
},
|
||
validate() {
|
||
if (!this.form.name) {
|
||
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,
|
||
categoryId: f.categoryId || null,
|
||
images: f.images,
|
||
remark: f.remark
|
||
};
|
||
},
|
||
async save(goOn) {
|
||
try {
|
||
uni.hideKeyboard && uni.hideKeyboard();
|
||
} catch (_) {
|
||
}
|
||
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", mask: false });
|
||
if (goOn && !this.id) {
|
||
this.form = { name: "", barcode: "", brand: "", model: "", spec: "", categoryId: "", images: [], remark: "", platformStatus: "", sourceSubmissionId: "" };
|
||
} else {
|
||
setTimeout(() => uni.navigateBack(), 400);
|
||
}
|
||
} catch (e) {
|
||
uni.showToast({ title: "保存失败", icon: "none", mask: false });
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$l(_ctx, _cache, $props, $setup, $data, $options) {
|
||
const _component_ImageUploader = vue.resolveComponent("ImageUploader");
|
||
return vue.openBlock(), vue.createElementBlock("scroll-view", {
|
||
"scroll-y": "",
|
||
class: "page"
|
||
}, [
|
||
vue.createCommentVNode(" 顶部标题与操作提示 "),
|
||
vue.createElementVNode("view", { class: "hero small" }, [
|
||
vue.createElementVNode("text", { class: "title" }, "编辑货品"),
|
||
vue.createElementVNode("text", { class: "sub" }, "完善基础信息与价格")
|
||
]),
|
||
$data.form.platformStatus === "platform" ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "tip platform"
|
||
}, "平台推荐货品,建议谨慎修改核心字段")) : $data.form.sourceSubmissionId ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "tip custom"
|
||
}, "此货品源于我的提交,审核通过后已入库")) : vue.createCommentVNode("v-if", true),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
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",
|
||
{
|
||
class: "input-long",
|
||
"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",
|
||
class: "picker-btn",
|
||
onClick: _cache[2] || (_cache[2] = (...args) => $options.chooseAndScanBarcode && $options.chooseAndScanBarcode(...args))
|
||
}, "图片识码")
|
||
]),
|
||
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.createCommentVNode(" 隐藏产地输入 "),
|
||
vue.createCommentVNode(" 隐藏主单位选择 "),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("picker", {
|
||
mode: "selector",
|
||
range: $options.categoryNames,
|
||
onChange: _cache[6] || (_cache[6] = (...args) => $options.onPickCategory && $options.onPickCategory(...args))
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "picker" },
|
||
"类别:" + vue.toDisplayString($options.categoryLabel),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["range"])
|
||
])
|
||
]),
|
||
vue.createCommentVNode(" 隐藏库存与安全库存输入 "),
|
||
vue.createCommentVNode(" 隐藏价格相关输入 "),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "图片"),
|
||
vue.createVNode(_component_ImageUploader, {
|
||
modelValue: $data.form.images,
|
||
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $data.form.images = $event),
|
||
formData: { ownerType: "product" }
|
||
}, null, 8, ["modelValue"])
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "备注"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"textarea",
|
||
{
|
||
"onUpdate:modelValue": _cache[8] || (_cache[8] = ($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",
|
||
style: vue.normalizeStyle({ bottom: ($data.keyboardHeight || 0) + "px" })
|
||
},
|
||
[
|
||
vue.createElementVNode("button", {
|
||
class: "ghost",
|
||
onClick: _cache[9] || (_cache[9] = ($event) => $options.save(false))
|
||
}, "保存"),
|
||
vue.createElementVNode("button", {
|
||
class: "primary",
|
||
onClick: _cache[10] || (_cache[10] = ($event) => $options.save(true))
|
||
}, "保存并继续")
|
||
],
|
||
4
|
||
/* STYLE */
|
||
)
|
||
]);
|
||
}
|
||
const PagesProductForm = /* @__PURE__ */ _export_sfc(_sfc_main$m, [["render", _sfc_render$l], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/form.vue"]]);
|
||
const _sfc_main$l = {
|
||
data() {
|
||
return { id: "", detail: null, categoryName: "-", templateName: "-" };
|
||
},
|
||
async onLoad(query) {
|
||
this.id = (query == null ? void 0 : query.id) || "";
|
||
if (!this.id) {
|
||
uni.showToast({ title: "参数缺失", icon: "none" });
|
||
return;
|
||
}
|
||
await this.preloadDictionaries();
|
||
await this.loadDetail();
|
||
},
|
||
methods: {
|
||
async preloadDictionaries() {
|
||
try {
|
||
const needCats = !Array.isArray(uni.getStorageSync("CACHE_CATEGORIES"));
|
||
const needTpls = !Array.isArray(uni.getStorageSync("CACHE_TEMPLATES"));
|
||
if (!needCats && !needTpls)
|
||
return;
|
||
const reqs = [];
|
||
if (needCats)
|
||
reqs.push(get("/api/product-categories"));
|
||
if (needTpls)
|
||
reqs.push(get("/api/product-templates"));
|
||
const res = await Promise.all(reqs);
|
||
let idx = 0;
|
||
if (needCats) {
|
||
const r = res[idx++];
|
||
const list = Array.isArray(r == null ? void 0 : r.list) ? r.list : Array.isArray(r) ? r : [];
|
||
uni.setStorageSync("CACHE_CATEGORIES", list);
|
||
}
|
||
if (needTpls) {
|
||
const r = res[idx++];
|
||
const list = Array.isArray(r == null ? void 0 : r.list) ? r.list : Array.isArray(r) ? r : [];
|
||
uni.setStorageSync("CACHE_TEMPLATES", list);
|
||
}
|
||
} catch (_) {
|
||
}
|
||
},
|
||
async loadDetail() {
|
||
try {
|
||
const data = await get("/api/products/" + this.id);
|
||
this.detail = data;
|
||
this.categoryName = this.categoryLookup(data.categoryId);
|
||
this.templateName = this.templateLookup(data.templateId);
|
||
} catch (e) {
|
||
uni.showToast({ title: (e == null ? void 0 : e.message) || "加载失败", icon: "none" });
|
||
}
|
||
},
|
||
preview(idx) {
|
||
var _a;
|
||
try {
|
||
const list = (((_a = this.detail) == null ? void 0 : _a.images) || []).map((i) => i.url || i);
|
||
uni.previewImage({ urls: list, current: idx });
|
||
} catch (_) {
|
||
}
|
||
},
|
||
categoryLookup(id) {
|
||
try {
|
||
const list = uni.getStorageSync("CACHE_CATEGORIES") || [];
|
||
const f = list.find((x) => String(x.id) === String(id));
|
||
return f ? f.name : "-";
|
||
} catch (_) {
|
||
return "-";
|
||
}
|
||
},
|
||
templateLookup(id) {
|
||
try {
|
||
const list = uni.getStorageSync("CACHE_TEMPLATES") || [];
|
||
const f = list.find((x) => String(x.id) === String(id));
|
||
return f ? f.name : "-";
|
||
} catch (_) {
|
||
return "-";
|
||
}
|
||
},
|
||
async remove() {
|
||
try {
|
||
const r = await new Promise((resolve) => {
|
||
uni.showModal({ content: "确认删除该货品?删除后可在后台恢复", success: resolve });
|
||
});
|
||
if (!r || !r.confirm)
|
||
return;
|
||
await del("/api/products/" + this.id);
|
||
uni.showToast({ title: "已删除", icon: "success" });
|
||
setTimeout(() => uni.navigateBack(), 400);
|
||
} catch (e) {
|
||
uni.showToast({ title: "删除失败", icon: "none" });
|
||
}
|
||
},
|
||
back() {
|
||
uni.navigateBack({ delta: 1 });
|
||
}
|
||
},
|
||
computed: {
|
||
labeledPairs() {
|
||
var _a;
|
||
const params = (_a = this.detail) == null ? void 0 : _a.parameters;
|
||
if (!params || typeof params !== "object")
|
||
return [];
|
||
let labelMap = {}, unitMap = {};
|
||
try {
|
||
const templates = uni.getStorageSync("CACHE_TEMPLATES") || [];
|
||
const tpl = templates.find((t) => {
|
||
var _a2;
|
||
return String(t.id) === String((_a2 = this.detail) == null ? void 0 : _a2.templateId);
|
||
});
|
||
if (tpl && Array.isArray(tpl.params))
|
||
for (const p of tpl.params) {
|
||
labelMap[p.fieldKey] = p.fieldLabel;
|
||
unitMap[p.fieldKey] = p.unit;
|
||
}
|
||
} catch (_) {
|
||
}
|
||
return Object.keys(params).map((k) => ({ key: k, label: labelMap[k] || k, unit: unitMap[k] || "", value: params[k] }));
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$k(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return $data.detail ? (vue.openBlock(), vue.createElementBlock("scroll-view", {
|
||
key: 0,
|
||
"scroll-y": "",
|
||
class: "page"
|
||
}, [
|
||
vue.createElementVNode("view", { class: "header" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "model" },
|
||
vue.toDisplayString($data.detail.model),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
$data.detail.deleted ? (vue.openBlock(), vue.createElementBlock("text", {
|
||
key: 0,
|
||
class: "status deleted"
|
||
}, "已删除")) : vue.createCommentVNode("v-if", true)
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "名称"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.name || "-"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "品牌"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.brand || "-"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "型号"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.model || "-"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "条码"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.barcode || "-"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "类别"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.categoryName),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "模板"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.templateName),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
$data.detail.externalCode ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "row"
|
||
}, [
|
||
vue.createElementVNode("text", { class: "label" }, "编号"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($data.detail.externalCode),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])) : vue.createCommentVNode("v-if", true)
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "block-title" }, "参数"),
|
||
$options.labeledPairs.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "params"
|
||
}, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($options.labeledPairs, (item) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
class: "param",
|
||
key: item.key
|
||
}, [
|
||
vue.createElementVNode("text", { class: "param-key" }, [
|
||
vue.createTextVNode(
|
||
vue.toDisplayString(item.label),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
item.unit ? (vue.openBlock(), vue.createElementBlock(
|
||
"text",
|
||
{ key: 0 },
|
||
"(" + vue.toDisplayString(item.unit) + ")",
|
||
1
|
||
/* TEXT */
|
||
)) : vue.createCommentVNode("v-if", true)
|
||
]),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "param-val" },
|
||
vue.toDisplayString(item.value),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "placeholder"
|
||
}, "未填写参数"))
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "block-title" }, "图片"),
|
||
$data.detail.images && $data.detail.images.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "images"
|
||
}, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($data.detail.images, (img, idx) => {
|
||
return vue.openBlock(), vue.createElementBlock("image", {
|
||
key: idx,
|
||
src: img.url || img,
|
||
class: "image",
|
||
mode: "aspectFill",
|
||
onClick: ($event) => $options.preview(idx)
|
||
}, null, 8, ["src", "onClick"]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "placeholder"
|
||
}, "未上传图片"))
|
||
]),
|
||
vue.createElementVNode("view", { class: "section" }, [
|
||
vue.createElementVNode("view", { class: "block-title" }, "备注"),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "placeholder" },
|
||
vue.toDisplayString($data.detail.remark || "无"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "footer" }, [
|
||
vue.createElementVNode("button", {
|
||
size: "mini",
|
||
onClick: _cache[0] || (_cache[0] = (...args) => $options.back && $options.back(...args))
|
||
}, "返回"),
|
||
vue.createElementVNode("button", {
|
||
size: "mini",
|
||
type: "warn",
|
||
onClick: _cache[1] || (_cache[1] = (...args) => $options.remove && $options.remove(...args))
|
||
}, "删除")
|
||
])
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "loading"
|
||
}, "加载中..."));
|
||
}
|
||
const PagesProductProductDetail = /* @__PURE__ */ _export_sfc(_sfc_main$l, [["render", _sfc_render$k], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/product-detail.vue"]]);
|
||
const _sfc_main$k = {
|
||
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$j(_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$k, [["render", _sfc_render$j], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/categories.vue"]]);
|
||
const _sfc_main$j = {
|
||
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$i(_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$j, [["render", _sfc_render$i], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/units.vue"]]);
|
||
const _sfc_main$i = {
|
||
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$h(_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$i, [["render", _sfc_render$h], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/settings.vue"]]);
|
||
const _sfc_main$h = {
|
||
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$g(_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$h, [["render", _sfc_render$g], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/customer/select.vue"]]);
|
||
const _sfc_main$g = {
|
||
data() {
|
||
return {
|
||
id: null,
|
||
form: { name: "", priceLevel: "retail", contactName: "", mobile: "", phone: "", address: "", arOpening: 0, remark: "" },
|
||
priceLevels: ["零售价", "批发价", "大单报价"],
|
||
priceLabels: ["零售价", "批发价", "大单报价"],
|
||
priceIdx: 0
|
||
};
|
||
},
|
||
onLoad(query) {
|
||
if (query && query.id) {
|
||
this.id = Number(query.id);
|
||
this.load();
|
||
}
|
||
},
|
||
methods: {
|
||
onPriceChange(e) {
|
||
this.priceIdx = Number(e.detail.value);
|
||
this.form.priceLevel = this.priceLevels[this.priceIdx];
|
||
},
|
||
async load() {
|
||
if (!this.id)
|
||
return;
|
||
try {
|
||
const d = await get(`/api/customers/${this.id}`);
|
||
this.form = {
|
||
name: (d == null ? void 0 : d.name) || "",
|
||
priceLevel: (d == null ? void 0 : d.priceLevel) || "零售价",
|
||
contactName: (d == null ? void 0 : d.contactName) || "",
|
||
mobile: (d == null ? void 0 : d.mobile) || "",
|
||
phone: (d == null ? void 0 : d.phone) || "",
|
||
address: (d == null ? void 0 : d.address) || "",
|
||
arOpening: Number((d == null ? void 0 : d.arOpening) || 0),
|
||
remark: (d == null ? void 0 : d.remark) || ""
|
||
};
|
||
const idx = this.priceLevels.indexOf(this.form.priceLevel || "零售价");
|
||
this.priceIdx = idx >= 0 ? idx : 0;
|
||
} catch (e) {
|
||
uni.showToast({ title: (e == null ? void 0 : e.message) || "加载失败", icon: "none" });
|
||
}
|
||
},
|
||
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$f(_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.createElementVNode("picker", {
|
||
range: $data.priceLabels,
|
||
value: $data.priceIdx,
|
||
onChange: _cache[1] || (_cache[1] = (...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[2] || (_cache[2] = ($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[3] || (_cache[3] = ($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[4] || (_cache[4] = ($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[5] || (_cache[5] = ($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[6] || (_cache[6] = ($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[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 PagesCustomerForm = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["render", _sfc_render$f], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/customer/form.vue"]]);
|
||
const _sfc_main$f = {
|
||
data() {
|
||
return { id: null, d: {}, editing: false, form: { name: "", contactName: "", mobile: "", phone: "", address: "", 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 || "",
|
||
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$e(_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.priceLevel),
|
||
1
|
||
/* TEXT */
|
||
)) : (vue.openBlock(), vue.createElementBlock("picker", {
|
||
key: 1,
|
||
range: $data.priceLabels,
|
||
value: $data.priceIdx,
|
||
onChange: _cache[5] || (_cache[5] = (...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[6] || (_cache[6] = ($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[7] || (_cache[7] = ($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[8] || (_cache[8] = (...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[9] || (_cache[9] = (...args) => $options.save && $options.save(...args))
|
||
}, "保存")) : (vue.openBlock(), vue.createElementBlock("button", {
|
||
key: 1,
|
||
class: "primary",
|
||
onClick: _cache[10] || (_cache[10] = (...args) => $options.choose && $options.choose(...args))
|
||
}, "选择此客户"))
|
||
])
|
||
]);
|
||
}
|
||
const PagesCustomerDetail = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["render", _sfc_render$e], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/customer/detail.vue"]]);
|
||
const _sfc_main$e = {
|
||
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) {
|
||
try {
|
||
const pages = getCurrentPages();
|
||
const opener = pages && pages.length >= 2 ? pages[pages.length - 2] : null;
|
||
const vm = opener && opener.$vm ? opener.$vm : null;
|
||
const canPick = !!(vm && vm.order);
|
||
if (canPick) {
|
||
vm.order.supplierId = s.id;
|
||
if (Object.prototype.hasOwnProperty.call(vm, "supplierName"))
|
||
vm.supplierName = s.name;
|
||
uni.navigateBack();
|
||
} else {
|
||
uni.navigateTo({ url: `/pages/supplier/form?id=${s.id}` });
|
||
}
|
||
} catch (_) {
|
||
uni.navigateTo({ url: `/pages/supplier/form?id=${s.id}` });
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$d(_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$e, [["render", _sfc_render$d], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/supplier/select.vue"]]);
|
||
const _sfc_main$d = {
|
||
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);
|
||
this.load();
|
||
}
|
||
},
|
||
methods: {
|
||
async load() {
|
||
if (!this.id)
|
||
return;
|
||
try {
|
||
const d = await get(`/api/suppliers/${this.id}`);
|
||
this.form = {
|
||
name: (d == null ? void 0 : d.name) || "",
|
||
contactName: (d == null ? void 0 : d.contactName) || "",
|
||
mobile: (d == null ? void 0 : d.mobile) || "",
|
||
phone: (d == null ? void 0 : d.phone) || "",
|
||
address: (d == null ? void 0 : d.address) || "",
|
||
apOpening: Number((d == null ? void 0 : d.apOpening) || 0),
|
||
apPayable: Number((d == null ? void 0 : d.apPayable) || 0),
|
||
remark: (d == null ? void 0 : d.remark) || ""
|
||
};
|
||
} catch (e) {
|
||
uni.showToast({ title: (e == null ? void 0 : e.message) || "加载失败", icon: "none" });
|
||
}
|
||
},
|
||
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$c(_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$d, [["render", _sfc_render$c], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/supplier/form.vue"]]);
|
||
const TYPE_MAP = { cash: "现金", bank: "银行", alipay: "支付宝", wechat: "微信", other: "其他" };
|
||
const _sfc_main$c = {
|
||
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$b(_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$c, [["render", _sfc_render$b], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/account/select.vue"]]);
|
||
const _sfc_main$b = {
|
||
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$a(_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$b, [["render", _sfc_render$a], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/account/ledger.vue"]]);
|
||
const _sfc_main$a = {
|
||
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$9(_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$a, [["render", _sfc_render$9], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/account/form.vue"]]);
|
||
const API_OF = {
|
||
sale: "/api/orders",
|
||
purchase: "/api/purchase-orders",
|
||
collect: "/api/payments",
|
||
fund: "/api/other-transactions"
|
||
};
|
||
const _sfc_main$9 = {
|
||
data() {
|
||
return {
|
||
biz: "sale",
|
||
bizList: [
|
||
{ key: "sale", name: "出货" },
|
||
{ key: "purchase", name: "进货" },
|
||
{ key: "collect", name: "收款" },
|
||
{ key: "fund", name: "资金" }
|
||
],
|
||
range: "month",
|
||
query: { kw: "" },
|
||
items: [],
|
||
page: 1,
|
||
size: 15,
|
||
finished: false,
|
||
loading: false,
|
||
startDate: "",
|
||
endDate: "",
|
||
nonVipRetentionDays: 0,
|
||
isVip: false
|
||
};
|
||
},
|
||
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() {
|
||
const hasToken = (() => {
|
||
try {
|
||
return !!uni.getStorageSync("TOKEN");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
})();
|
||
if (!hasToken) {
|
||
this.items = [];
|
||
this.total = 0;
|
||
uni.showToast({ title: "请登录使用该功能", icon: "none" });
|
||
return;
|
||
}
|
||
try {
|
||
formatAppLog("log", "at pages/detail/index.vue:104", "[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();
|
||
},
|
||
onStartChange(e) {
|
||
var _a;
|
||
this.startDate = ((_a = e == null ? void 0 : e.detail) == null ? void 0 : _a.value) || this.startDate;
|
||
if (this.endDate && this.startDate > this.endDate)
|
||
this.endDate = this.startDate;
|
||
this.reload();
|
||
},
|
||
onEndChange(e) {
|
||
var _a;
|
||
this.endDate = ((_a = e == null ? void 0 : e.detail) == null ? void 0 : _a.value) || this.endDate;
|
||
if (this.startDate && this.endDate < this.startDate)
|
||
this.startDate = this.endDate;
|
||
this.reload();
|
||
},
|
||
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;
|
||
await this.hintIfNonVipOutOfWindow();
|
||
} catch (e) {
|
||
uni.showToast({ title: "加载失败", icon: "none" });
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
async hintIfNonVipOutOfWindow() {
|
||
try {
|
||
if (this.isVip && this.isVip === true)
|
||
return;
|
||
if (!this.nonVipRetentionDays) {
|
||
const v = await get("/api/vip/status");
|
||
this.isVip = !!(v == null ? void 0 : v.isVip);
|
||
this.nonVipRetentionDays = Number((v == null ? void 0 : v.nonVipRetentionDays) || 60);
|
||
if (this.isVip)
|
||
return;
|
||
}
|
||
if (!this.startDate)
|
||
return;
|
||
const start = new Date(this.startDate).getTime();
|
||
const threshold = Date.now() - this.nonVipRetentionDays * 24 * 3600 * 1e3;
|
||
if (start < threshold) {
|
||
uni.showModal({
|
||
title: "提示",
|
||
content: `普通用户仅显示近${this.nonVipRetentionDays}天数据,开通VIP可查看全部历史。`,
|
||
confirmText: "去开通VIP",
|
||
cancelText: "我知道了",
|
||
success: (r) => {
|
||
if (r.confirm)
|
||
uni.navigateTo({ url: "/pages/my/vip" });
|
||
}
|
||
});
|
||
}
|
||
} catch (e) {
|
||
}
|
||
},
|
||
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$8(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "page" }, [
|
||
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: "period-group" }, [
|
||
vue.createElementVNode("text", { class: "period-label" }, "期间"),
|
||
vue.createElementVNode("picker", {
|
||
mode: "date",
|
||
value: $data.startDate,
|
||
onChange: _cache[0] || (_cache[0] = (...args) => $options.onStartChange && $options.onStartChange(...args))
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "date-chip" },
|
||
vue.toDisplayString($data.startDate),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["value"]),
|
||
vue.createElementVNode("text", { class: "sep" }, "~"),
|
||
vue.createElementVNode("picker", {
|
||
mode: "date",
|
||
value: $data.endDate,
|
||
onChange: _cache[1] || (_cache[1] = (...args) => $options.onEndChange && $options.onEndChange(...args))
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "date-chip" },
|
||
vue.toDisplayString($data.endDate),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["value"])
|
||
]),
|
||
vue.createElementVNode("view", { class: "search-row" }, [
|
||
vue.createElementVNode("view", { class: "search" }, [
|
||
vue.withDirectives(vue.createElementVNode("input", {
|
||
class: "search-input",
|
||
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $data.query.kw = $event),
|
||
placeholder: $options.placeholder,
|
||
onConfirm: _cache[3] || (_cache[3] = (...args) => $options.reload && $options.reload(...args))
|
||
}, null, 40, ["placeholder"]), [
|
||
[
|
||
vue.vModelText,
|
||
$data.query.kw,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn",
|
||
size: "mini",
|
||
onClick: _cache[4] || (_cache[4] = (...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[5] || (_cache[5] = (...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: vue.normalizeClass(["amount", { in: Number(it.amount || 0) >= 0, out: Number(it.amount || 0) < 0 }])
|
||
},
|
||
"¥ " + vue.toDisplayString((it.amount || 0).toFixed(2)),
|
||
3
|
||
/* TEXT, CLASS */
|
||
),
|
||
vue.createElementVNode("view", { class: "arrow" }, "›")
|
||
], 8, ["onClick"]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
)) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "empty"
|
||
}, "暂无数据")),
|
||
$data.items.length && !$data.finished ? vue.withDirectives((vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
key: 2,
|
||
class: "loading"
|
||
},
|
||
"加载中...",
|
||
512
|
||
/* NEED_PATCH */
|
||
)), [
|
||
[vue.vShow, $data.loading]
|
||
]) : vue.createCommentVNode("v-if", true),
|
||
$data.finished && $data.items.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 3,
|
||
class: "finished"
|
||
}, "没有更多了")) : vue.createCommentVNode("v-if", true)
|
||
],
|
||
32
|
||
/* NEED_HYDRATION */
|
||
),
|
||
vue.createCommentVNode(" 右下角新增按钮:根据业务类型跳转对应开单页或创建页 "),
|
||
vue.createElementVNode("view", {
|
||
class: "fab",
|
||
onClick: _cache[6] || (_cache[6] = (...args) => $options.onCreate && $options.onCreate(...args))
|
||
}, "+")
|
||
])
|
||
])
|
||
]);
|
||
}
|
||
const PagesDetailIndex = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["render", _sfc_render$8], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/detail/index.vue"]]);
|
||
const _sfc_main$8 = {
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
tab: "login",
|
||
authLoginTopImage: AUTH_LOGIN_TOP_IMAGE,
|
||
loginForm: { email: "", password: "" },
|
||
regForm: { name: "", email: "", code: "", password: "", password2: "" },
|
||
resetForm: { email: "", code: "", password: "", password2: "" },
|
||
regCountdown: 0,
|
||
resetCountdown: 0,
|
||
_timers: []
|
||
};
|
||
},
|
||
beforeUnmount() {
|
||
this._timers.forEach((t) => clearInterval(t));
|
||
},
|
||
methods: {
|
||
gotoRegister() {
|
||
this.tab = "register";
|
||
},
|
||
gotoReset() {
|
||
this.tab = "reset";
|
||
},
|
||
toast(msg) {
|
||
try {
|
||
uni.showToast({ title: String(msg || "操作失败"), icon: "none" });
|
||
} catch (_) {
|
||
}
|
||
},
|
||
validateEmail(v) {
|
||
return /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(String(v || "").trim());
|
||
},
|
||
startCountdown(key) {
|
||
if (this[key] > 0)
|
||
return;
|
||
this[key] = 60;
|
||
const timer = setInterval(() => {
|
||
this[key] = Math.max(0, this[key] - 1);
|
||
if (this[key] === 0)
|
||
clearInterval(timer);
|
||
}, 1e3);
|
||
this._timers.push(timer);
|
||
},
|
||
async onLogin() {
|
||
const { email, password } = this.loginForm;
|
||
if (!this.validateEmail(email))
|
||
return this.toast("请输入正确邮箱");
|
||
if (!password || password.length < 6)
|
||
return this.toast("请输入至少6位密码");
|
||
this.loading = true;
|
||
try {
|
||
const data = await post("/api/auth/password/login", { email, password });
|
||
this.afterLogin(data);
|
||
} catch (e) {
|
||
this.toast(e.message);
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
afterLogin(data) {
|
||
try {
|
||
if (data && data.token) {
|
||
uni.setStorageSync("TOKEN", data.token);
|
||
if (data.user && data.user.shopId)
|
||
uni.setStorageSync("SHOP_ID", data.user.shopId);
|
||
uni.setStorageSync("ENABLE_DEFAULT_USER", "false");
|
||
uni.removeStorageSync("DEFAULT_USER_ID");
|
||
this.toast("登录成功");
|
||
setTimeout(() => {
|
||
uni.reLaunch({ url: "/pages/index/index" });
|
||
}, 300);
|
||
} else {
|
||
this.toast("登录失败");
|
||
}
|
||
} catch (_) {
|
||
this.toast("登录失败");
|
||
}
|
||
},
|
||
async sendRegCode() {
|
||
if (!this.validateEmail(this.regForm.email))
|
||
return this.toast("请输入正确邮箱");
|
||
this.loading = true;
|
||
try {
|
||
const r = await post("/api/auth/email/send", { email: this.regForm.email, scene: "register" });
|
||
if (r && r.ok)
|
||
this.startCountdown("regCountdown");
|
||
this.toast(r && r.ok ? "验证码已发送" : "发送过于频繁");
|
||
} catch (e) {
|
||
this.toast(e.message);
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
async onRegister() {
|
||
const f = this.regForm;
|
||
if (!f.name || f.name.trim().length < 1)
|
||
return this.toast("请输入用户名");
|
||
if (!this.validateEmail(f.email))
|
||
return this.toast("请输入正确邮箱");
|
||
if (!f.code)
|
||
return this.toast("请输入验证码");
|
||
if (!f.password || f.password.length < 6)
|
||
return this.toast("密码至少6位");
|
||
if (f.password !== f.password2)
|
||
return this.toast("两次密码不一致");
|
||
this.loading = true;
|
||
try {
|
||
const data = await post("/api/auth/email/register", { name: f.name.trim(), email: f.email.trim(), code: f.code.trim(), password: f.password });
|
||
this.afterLogin(data);
|
||
} catch (e) {
|
||
this.toast(e.message);
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
async sendResetCode() {
|
||
if (!this.validateEmail(this.resetForm.email))
|
||
return this.toast("请输入正确邮箱");
|
||
this.loading = true;
|
||
try {
|
||
const r = await post("/api/auth/email/send", { email: this.resetForm.email, scene: "reset" });
|
||
if (r && r.ok)
|
||
this.startCountdown("resetCountdown");
|
||
this.toast(r && r.ok ? "验证码已发送" : "发送过于频繁");
|
||
} catch (e) {
|
||
this.toast(e.message);
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
async onReset() {
|
||
const f = this.resetForm;
|
||
if (!this.validateEmail(f.email))
|
||
return this.toast("请输入正确邮箱");
|
||
if (!f.code)
|
||
return this.toast("请输入验证码");
|
||
if (!f.password || f.password.length < 6)
|
||
return this.toast("新密码至少6位");
|
||
if (f.password !== f.password2)
|
||
return this.toast("两次密码不一致");
|
||
this.loading = true;
|
||
try {
|
||
const r = await post("/api/auth/email/reset-password", { email: f.email.trim(), code: f.code.trim(), newPassword: f.password, confirmPassword: f.password2 });
|
||
if (r && r.ok) {
|
||
this.toast("已重置,请使用新密码登录");
|
||
this.tab = "login";
|
||
this.loginForm.email = f.email;
|
||
} else
|
||
this.toast("重置失败");
|
||
} catch (e) {
|
||
this.toast(e.message);
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "auth-page" }, [
|
||
vue.createElementVNode("view", { class: "login-hero" }, [
|
||
vue.createElementVNode("image", {
|
||
class: "login-hero-img",
|
||
src: $data.authLoginTopImage,
|
||
mode: "widthFix"
|
||
}, null, 8, ["src"])
|
||
]),
|
||
vue.createElementVNode("view", { class: "header" }, [
|
||
vue.createElementVNode("text", { class: "title" }, "邮箱密码登录")
|
||
]),
|
||
$data.tab === "login" ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "panel"
|
||
}, [
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "text",
|
||
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.loginForm.email = $event),
|
||
placeholder: "输入邮箱"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.loginForm.email,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "password",
|
||
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $data.loginForm.password = $event),
|
||
placeholder: "输入密码"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[vue.vModelText, $data.loginForm.password]
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn primary",
|
||
disabled: $data.loading,
|
||
onClick: _cache[2] || (_cache[2] = (...args) => $options.onLogin && $options.onLogin(...args))
|
||
}, "登录", 8, ["disabled"]),
|
||
vue.createElementVNode("view", { class: "quick-inline" }, [
|
||
vue.createElementVNode("button", {
|
||
class: "quick-link",
|
||
onClick: _cache[3] || (_cache[3] = (...args) => $options.gotoRegister && $options.gotoRegister(...args))
|
||
}, "注册"),
|
||
vue.createElementVNode("button", {
|
||
class: "quick-link",
|
||
onClick: _cache[4] || (_cache[4] = (...args) => $options.gotoReset && $options.gotoReset(...args))
|
||
}, "忘记密码")
|
||
])
|
||
])) : vue.createCommentVNode("v-if", true),
|
||
$data.tab === "register" ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "panel minor"
|
||
}, [
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "text",
|
||
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $data.regForm.name = $event),
|
||
placeholder: "输入用户名"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.regForm.name,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "text",
|
||
"onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => $data.regForm.email = $event),
|
||
placeholder: "输入邮箱"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.regForm.email,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input flex1",
|
||
type: "text",
|
||
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $data.regForm.code = $event),
|
||
placeholder: "邮箱验证码"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.regForm.code,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn ghost",
|
||
disabled: $data.regCountdown > 0 || $data.loading,
|
||
onClick: _cache[8] || (_cache[8] = (...args) => $options.sendRegCode && $options.sendRegCode(...args))
|
||
}, vue.toDisplayString($data.regCountdown > 0 ? $data.regCountdown + "s" : "获取验证码"), 9, ["disabled"])
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "password",
|
||
"onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => $data.regForm.password = $event),
|
||
placeholder: "输入密码(≥6位)"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[vue.vModelText, $data.regForm.password]
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "password",
|
||
"onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => $data.regForm.password2 = $event),
|
||
placeholder: "再次输入密码"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[vue.vModelText, $data.regForm.password2]
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn primary",
|
||
disabled: $data.loading,
|
||
onClick: _cache[11] || (_cache[11] = (...args) => $options.onRegister && $options.onRegister(...args))
|
||
}, "注册新用户", 8, ["disabled"])
|
||
])) : vue.createCommentVNode("v-if", true),
|
||
$data.tab === "reset" ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 2,
|
||
class: "panel minor"
|
||
}, [
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "text",
|
||
"onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => $data.resetForm.email = $event),
|
||
placeholder: "输入邮箱"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.resetForm.email,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input flex1",
|
||
type: "text",
|
||
"onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => $data.resetForm.code = $event),
|
||
placeholder: "邮箱验证码"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.resetForm.code,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn ghost",
|
||
disabled: $data.resetCountdown > 0 || $data.loading,
|
||
onClick: _cache[14] || (_cache[14] = (...args) => $options.sendResetCode && $options.sendResetCode(...args))
|
||
}, vue.toDisplayString($data.resetCountdown > 0 ? $data.resetCountdown + "s" : "获取验证码"), 9, ["disabled"])
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "password",
|
||
"onUpdate:modelValue": _cache[15] || (_cache[15] = ($event) => $data.resetForm.password = $event),
|
||
placeholder: "新密码(≥6位)"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[vue.vModelText, $data.resetForm.password]
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "password",
|
||
"onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => $data.resetForm.password2 = $event),
|
||
placeholder: "再次输入新密码"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[vue.vModelText, $data.resetForm.password2]
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn primary",
|
||
disabled: $data.loading,
|
||
onClick: _cache[17] || (_cache[17] = (...args) => $options.onReset && $options.onReset(...args))
|
||
}, "重置密码", 8, ["disabled"])
|
||
])) : vue.createCommentVNode("v-if", true)
|
||
]);
|
||
}
|
||
const PagesAuthLogin = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$7], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/auth/login.vue"]]);
|
||
const _sfc_main$7 = {
|
||
data() {
|
||
return {
|
||
form: {
|
||
shopName: "",
|
||
name: "",
|
||
email: "",
|
||
code: "",
|
||
password: ""
|
||
},
|
||
shopNameFocused: false,
|
||
nameFocused: false,
|
||
emailFocused: false,
|
||
codeFocused: false,
|
||
pwdFocused: false,
|
||
countdown: 0,
|
||
timer: null,
|
||
sending: false
|
||
};
|
||
},
|
||
computed: {
|
||
btnText() {
|
||
if (this.countdown > 0)
|
||
return `${this.countdown}s`;
|
||
if (this.sending)
|
||
return "发送中...";
|
||
return "获取验证码";
|
||
}
|
||
},
|
||
methods: {
|
||
validate() {
|
||
const email = String(this.form.email || "").trim();
|
||
const ok = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(email);
|
||
if (!ok) {
|
||
uni.showToast({ title: "请输入正确的邮箱地址", icon: "none" });
|
||
return false;
|
||
}
|
||
if (!/^\d{6}$/.test(String(this.form.code || "").trim())) {
|
||
uni.showToast({ title: "验证码格式不正确", icon: "none" });
|
||
return false;
|
||
}
|
||
if (String(this.form.password || "").length < 6) {
|
||
uni.showToast({ title: "密码至少6位", icon: "none" });
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
startCountdown(sec) {
|
||
this.countdown = sec;
|
||
if (this.timer)
|
||
clearInterval(this.timer);
|
||
this.timer = setInterval(() => {
|
||
if (this.countdown <= 1) {
|
||
clearInterval(this.timer);
|
||
this.timer = null;
|
||
this.countdown = 0;
|
||
return;
|
||
}
|
||
this.countdown--;
|
||
}, 1e3);
|
||
},
|
||
async sendCode() {
|
||
if (this.sending || this.countdown > 0)
|
||
return;
|
||
const e = String(this.form.email || "").trim();
|
||
const ok = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(e);
|
||
if (!ok)
|
||
return uni.showToast({ title: "请输入正确的邮箱地址", icon: "none" });
|
||
this.sending = true;
|
||
try {
|
||
const res = await post("/api/auth/email/send", { email: e, scene: "login" });
|
||
const cd = Number(res && res.cooldownSec || 60);
|
||
this.startCountdown(cd);
|
||
uni.showToast({ title: "验证码已发送", icon: "none" });
|
||
} catch (e2) {
|
||
const msg = e2 && e2.message || "发送失败";
|
||
uni.showToast({ title: msg, icon: "none" });
|
||
} finally {
|
||
this.sending = false;
|
||
}
|
||
},
|
||
async onRegister() {
|
||
if (!this.validate())
|
||
return;
|
||
const email = String(this.form.email || "").trim();
|
||
const name = String(this.form.name || "").trim();
|
||
try {
|
||
const data = await post("/api/auth/email/register", { email, code: String(this.form.code || "").trim(), name, password: String(this.form.password || "") });
|
||
if (data && data.token) {
|
||
uni.setStorageSync("TOKEN", data.token);
|
||
if (data.user && data.user.email)
|
||
uni.setStorageSync("USER_EMAIL", data.user.email);
|
||
if (name)
|
||
try {
|
||
uni.setStorageSync("USER_NAME", name);
|
||
} catch (_) {
|
||
}
|
||
uni.showToast({ title: "注册成功", icon: "none" });
|
||
setTimeout(() => {
|
||
uni.reLaunch({ url: "/pages/index/index" });
|
||
}, 300);
|
||
}
|
||
} catch (e) {
|
||
const msg = e && e.message || "注册失败";
|
||
uni.showToast({ title: msg, icon: "none" });
|
||
}
|
||
},
|
||
onGoLogin() {
|
||
uni.navigateTo({
|
||
url: "/pages/auth/login"
|
||
});
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "register-container" }, [
|
||
vue.createCommentVNode(" 背景装饰 "),
|
||
vue.createElementVNode("view", { class: "background-decoration" }, [
|
||
vue.createElementVNode("view", { class: "circle circle-1" }),
|
||
vue.createElementVNode("view", { class: "circle circle-2" }),
|
||
vue.createElementVNode("view", { class: "circle circle-3" })
|
||
]),
|
||
vue.createCommentVNode(" 主要内容卡片 "),
|
||
vue.createElementVNode("view", { class: "register-card" }, [
|
||
vue.createCommentVNode(" 顶部Logo区域 "),
|
||
vue.createElementVNode("view", { class: "header-section" }, [
|
||
vue.createElementVNode("view", { class: "logo-container" }, [
|
||
vue.createElementVNode("view", { class: "logo-icon" }, [
|
||
(vue.openBlock(), vue.createElementBlock("svg", {
|
||
viewBox: "0 0 24 24",
|
||
class: "icon"
|
||
}, [
|
||
vue.createElementVNode("path", { d: "M12 2C13.1 2 14 2.9 14 4C14 5.1 13.1 6 12 6C10.9 6 10 5.1 10 4C10 2.9 10.9 2 12 2ZM21 9V7L15 4V6C15 7.66 13.66 9 12 9S9 7.66 9 6V4L3 7V9C3 10.1 3.9 11 5 11V17C5 18.1 5.9 19 7 19H9C9 20.1 9.9 21 11 21H13C14.1 21 15 20.1 15 19H17C18.1 19 19 18.1 19 17V11C20.1 11 21 10.1 21 9Z" })
|
||
]))
|
||
]),
|
||
vue.createElementVNode("text", { class: "app-name" }, "配件询价")
|
||
]),
|
||
vue.createElementVNode("text", { class: "welcome-text" }, "创建账户"),
|
||
vue.createElementVNode("text", { class: "subtitle" }, "请填写以下信息完成注册")
|
||
]),
|
||
vue.createCommentVNode(" 表单区域 "),
|
||
vue.createElementVNode("view", { class: "form-section" }, [
|
||
vue.createCommentVNode(" 店铺名称 "),
|
||
vue.createElementVNode("view", { class: "input-group" }, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["input-container", { focused: $data.shopNameFocused, filled: $data.form.shopName }])
|
||
},
|
||
[
|
||
vue.createElementVNode("view", { class: "input-icon" }, [
|
||
(vue.openBlock(), vue.createElementBlock("svg", {
|
||
viewBox: "0 0 24 24",
|
||
class: "icon"
|
||
}, [
|
||
vue.createElementVNode("path", { d: "M12,3L2,12H5V20H19V12H22L12,3M12,8.75A2.25,2.25 0 0,1 14.25,11A2.25,2.25 0 0,1 12,13.25A2.25,2.25 0 0,1 9.75,11A2.25,2.25 0 0,1 12,8.75Z" })
|
||
]))
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input-field",
|
||
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.form.shopName = $event),
|
||
type: "text",
|
||
placeholder: "请输入店铺名称",
|
||
onFocus: _cache[1] || (_cache[1] = ($event) => $data.shopNameFocused = true),
|
||
onBlur: _cache[2] || (_cache[2] = ($event) => $data.shopNameFocused = false)
|
||
},
|
||
null,
|
||
544
|
||
/* NEED_HYDRATION, NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.shopName,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)
|
||
]),
|
||
vue.createCommentVNode(" 姓名 "),
|
||
vue.createElementVNode("view", { class: "input-group" }, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["input-container", { focused: $data.nameFocused, filled: $data.form.name }])
|
||
},
|
||
[
|
||
vue.createElementVNode("view", { class: "input-icon" }, [
|
||
(vue.openBlock(), vue.createElementBlock("svg", {
|
||
viewBox: "0 0 24 24",
|
||
class: "icon"
|
||
}, [
|
||
vue.createElementVNode("path", { d: "M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z" })
|
||
]))
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input-field",
|
||
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.form.name = $event),
|
||
type: "text",
|
||
placeholder: "请输入您的姓名",
|
||
onFocus: _cache[4] || (_cache[4] = ($event) => $data.nameFocused = true),
|
||
onBlur: _cache[5] || (_cache[5] = ($event) => $data.nameFocused = false)
|
||
},
|
||
null,
|
||
544
|
||
/* NEED_HYDRATION, NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.name,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)
|
||
]),
|
||
vue.createCommentVNode(" 邮箱 "),
|
||
vue.createElementVNode("view", { class: "input-group" }, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["input-container", { focused: $data.emailFocused, filled: $data.form.email }])
|
||
},
|
||
[
|
||
vue.createElementVNode("view", { class: "input-icon" }, [
|
||
(vue.openBlock(), vue.createElementBlock("svg", {
|
||
viewBox: "0 0 24 24",
|
||
class: "icon"
|
||
}, [
|
||
vue.createElementVNode("path", { d: "M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-1 4l-7 4-7-4V6l7 4 7-4v2z" })
|
||
]))
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input-field",
|
||
"onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => $data.form.email = $event),
|
||
type: "text",
|
||
placeholder: "请输入邮箱地址",
|
||
onFocus: _cache[7] || (_cache[7] = ($event) => $data.emailFocused = true),
|
||
onBlur: _cache[8] || (_cache[8] = ($event) => $data.emailFocused = false)
|
||
},
|
||
null,
|
||
544
|
||
/* NEED_HYDRATION, NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.email,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)
|
||
]),
|
||
vue.createCommentVNode(" 验证码 "),
|
||
vue.createElementVNode("view", { class: "input-group" }, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["input-container", { focused: $data.codeFocused, filled: $data.form.code }])
|
||
},
|
||
[
|
||
vue.createElementVNode("view", { class: "input-icon" }, [
|
||
(vue.openBlock(), vue.createElementBlock("svg", {
|
||
viewBox: "0 0 24 24",
|
||
class: "icon"
|
||
}, [
|
||
vue.createElementVNode("path", { d: "M3 10h18v2H3v-2zm0 6h12v2H3v-2zM3 6h18v2H3V6z" })
|
||
]))
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input-field",
|
||
"onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => $data.form.code = $event),
|
||
type: "number",
|
||
maxlength: "6",
|
||
placeholder: "请输入6位验证码",
|
||
onFocus: _cache[10] || (_cache[10] = ($event) => $data.codeFocused = true),
|
||
onBlur: _cache[11] || (_cache[11] = ($event) => $data.codeFocused = false)
|
||
},
|
||
null,
|
||
544
|
||
/* NEED_HYDRATION, NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.code,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)
|
||
]),
|
||
vue.createCommentVNode(" 密码 "),
|
||
vue.createElementVNode("view", { class: "input-group" }, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["input-container", { focused: $data.pwdFocused, filled: $data.form.password }])
|
||
},
|
||
[
|
||
vue.createElementVNode("view", { class: "input-icon" }, [
|
||
(vue.openBlock(), vue.createElementBlock("svg", {
|
||
viewBox: "0 0 24 24",
|
||
class: "icon"
|
||
}, [
|
||
vue.createElementVNode("path", { d: "M12,17A2,2 0 0,0 14,15C14,13.89 13.1,13 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V10C4,8.89 4.9,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z" })
|
||
]))
|
||
]),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input-field",
|
||
"onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => $data.form.password = $event),
|
||
password: "",
|
||
placeholder: "请设置登录密码(至少6位)",
|
||
onFocus: _cache[13] || (_cache[13] = ($event) => $data.pwdFocused = true),
|
||
onBlur: _cache[14] || (_cache[14] = ($event) => $data.pwdFocused = false)
|
||
},
|
||
null,
|
||
544
|
||
/* NEED_HYDRATION, NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.password,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)
|
||
]),
|
||
vue.createCommentVNode(" 发送验证码按钮 "),
|
||
vue.createElementVNode("view", { class: "input-group" }, [
|
||
vue.createElementVNode("button", {
|
||
class: "login-button",
|
||
disabled: $data.countdown > 0 || $data.sending,
|
||
onClick: _cache[15] || (_cache[15] = (...args) => $options.sendCode && $options.sendCode(...args))
|
||
}, vue.toDisplayString($options.btnText), 9, ["disabled"])
|
||
])
|
||
]),
|
||
vue.createCommentVNode(" 按钮区域 "),
|
||
vue.createElementVNode("view", { class: "actions-section" }, [
|
||
vue.createElementVNode("button", {
|
||
class: "register-button",
|
||
onClick: _cache[16] || (_cache[16] = (...args) => $options.onRegister && $options.onRegister(...args))
|
||
}, [
|
||
vue.createElementVNode("text", { class: "button-text" }, "立即注册")
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "login-button",
|
||
onClick: _cache[17] || (_cache[17] = (...args) => $options.onGoLogin && $options.onGoLogin(...args))
|
||
}, [
|
||
vue.createElementVNode("text", { class: "button-text" }, "已有账户?去登录")
|
||
])
|
||
]),
|
||
vue.createCommentVNode(" 提示信息 "),
|
||
vue.createElementVNode("view", { class: "footer-section" }, [
|
||
vue.createElementVNode("text", { class: "hint-text" }, "注册即表示您同意我们的服务条款和隐私政策")
|
||
])
|
||
])
|
||
]);
|
||
}
|
||
const PagesAuthRegister = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$6], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/auth/register.vue"]]);
|
||
const _imports_0$2 = "/static/icons/icons8-login-50.png";
|
||
function normalizeAvatar(url) {
|
||
if (!url)
|
||
return "/static/icons/icons8-mitt-24.png";
|
||
const s = String(url);
|
||
if (/^https?:\/\//i.test(s))
|
||
return s;
|
||
if (!API_BASE_URL)
|
||
return s;
|
||
if (s.startsWith("/"))
|
||
return `${API_BASE_URL}${s}`;
|
||
return `${API_BASE_URL}/${s}`;
|
||
}
|
||
const _sfc_main$6 = {
|
||
data() {
|
||
return {
|
||
avatarUrl: "/static/icons/icons8-mitt-24.png",
|
||
shopName: "未登录",
|
||
mobile: "",
|
||
pendingJsCode: "",
|
||
logging: false,
|
||
vipIsVip: false,
|
||
vipStart: "",
|
||
vipEnd: ""
|
||
};
|
||
},
|
||
onShow() {
|
||
this.fetchProfile();
|
||
this.loadVip();
|
||
try {
|
||
if (uni.getStorageSync("TOKEN")) {
|
||
this.$forceUpdate && this.$forceUpdate();
|
||
}
|
||
} catch (e) {
|
||
}
|
||
},
|
||
computed: {
|
||
isLoggedIn() {
|
||
try {
|
||
return !!uni.getStorageSync("TOKEN");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
},
|
||
avatarDisplay() {
|
||
return normalizeAvatar(this.avatarUrl);
|
||
},
|
||
emailDisplay() {
|
||
if (!this.isLoggedIn)
|
||
return "";
|
||
const e = String(uni.getStorageSync("USER_EMAIL") || "");
|
||
if (!e)
|
||
return "未绑定邮箱";
|
||
const at = e.indexOf("@");
|
||
if (at > 1) {
|
||
const name = e.slice(0, at);
|
||
const domain = e.slice(at);
|
||
return (name.length <= 2 ? name[0] + "*" : name.slice(0, 2) + "***") + domain;
|
||
}
|
||
return e;
|
||
},
|
||
vipStartDisplay() {
|
||
return this.formatDisplay(this.vipStart);
|
||
},
|
||
vipEndDisplay() {
|
||
return this.formatDisplay(this.vipEnd);
|
||
}
|
||
},
|
||
methods: {
|
||
// 登录相关方法已移除
|
||
async fetchProfile() {
|
||
const hasToken = (() => {
|
||
try {
|
||
return !!uni.getStorageSync("TOKEN");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
})();
|
||
if (!hasToken) {
|
||
this.shopName = "未登录";
|
||
this.avatarUrl = "/static/icons/icons8-mitt-24.png";
|
||
this.mobile = "";
|
||
return;
|
||
}
|
||
try {
|
||
const profile = await get("/api/user/me");
|
||
const latestAvatar = (profile == null ? void 0 : profile.avatarUrl) || "";
|
||
if (latestAvatar) {
|
||
const bust = `${latestAvatar}${latestAvatar.includes("?") ? "&" : "?"}t=${Date.now()}`;
|
||
this.avatarUrl = bust;
|
||
try {
|
||
uni.setStorageSync("USER_AVATAR_RAW", latestAvatar);
|
||
uni.setStorageSync("USER_AVATAR", latestAvatar);
|
||
} catch (_) {
|
||
}
|
||
} else {
|
||
const cached = uni.getStorageSync("USER_AVATAR") || "";
|
||
this.avatarUrl = cached || "/static/icons/icons8-mitt-24.png";
|
||
}
|
||
const storeName = (profile == null ? void 0 : profile.name) || uni.getStorageSync("SHOP_NAME") || "未命名店铺";
|
||
this.shopName = storeName;
|
||
const phone = (profile == null ? void 0 : profile.phone) || uni.getStorageSync("USER_MOBILE") || "";
|
||
this.mobile = phone;
|
||
} 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 (_) {
|
||
}
|
||
}
|
||
},
|
||
async loadVip() {
|
||
try {
|
||
const hasToken = (() => {
|
||
try {
|
||
return !!uni.getStorageSync("TOKEN");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
})();
|
||
if (!hasToken) {
|
||
this.vipIsVip = false;
|
||
this.vipStart = "";
|
||
this.vipEnd = "";
|
||
return;
|
||
}
|
||
const data = await get("/api/vip/status");
|
||
const active = !!(data == null ? void 0 : data.isVip);
|
||
this.vipIsVip = active;
|
||
this.vipEnd = (data == null ? void 0 : data.expireAt) || "";
|
||
let computedStart = "";
|
||
const exp = this.vipEnd;
|
||
if (exp) {
|
||
const m = String(exp).match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?/);
|
||
if (m) {
|
||
const y = Number(m[1]);
|
||
const mo = Number(m[2]) - 1;
|
||
const da = Number(m[3]);
|
||
const hh = Number(m[4] || "0");
|
||
const mm = Number(m[5] || "0");
|
||
const ss = Number(m[6] || "0");
|
||
const startDate = new Date(y, mo - 1, da, hh, mm, ss);
|
||
const y2 = startDate.getFullYear();
|
||
const m2 = (startDate.getMonth() + 1).toString().padStart(2, "0");
|
||
const d2 = startDate.getDate().toString().padStart(2, "0");
|
||
const h2 = startDate.getHours().toString().padStart(2, "0");
|
||
const i2 = startDate.getMinutes().toString().padStart(2, "0");
|
||
computedStart = `${y2}-${m2}-${d2} ${h2}:${i2}`;
|
||
}
|
||
}
|
||
this.vipStart = computedStart;
|
||
try {
|
||
uni.setStorageSync("USER_VIP_IS_VIP", String(active));
|
||
uni.setStorageSync("USER_VIP_END", this.vipEnd);
|
||
if (this.vipStart)
|
||
uni.setStorageSync("USER_VIP_START", this.vipStart);
|
||
else
|
||
uni.removeStorageSync("USER_VIP_START");
|
||
} catch (_) {
|
||
}
|
||
} catch (e) {
|
||
try {
|
||
const isVip = String(uni.getStorageSync("USER_VIP_IS_VIP") || "false").toLowerCase() === "true";
|
||
this.vipIsVip = isVip;
|
||
this.vipStart = uni.getStorageSync("USER_VIP_START") || "";
|
||
this.vipEnd = uni.getStorageSync("USER_VIP_END") || "";
|
||
} catch (_) {
|
||
}
|
||
}
|
||
},
|
||
formatDisplay(value) {
|
||
if (!value)
|
||
return "-";
|
||
const s = String(value);
|
||
const m = s.match(/^(\d{4}-\d{2}-\d{2})/);
|
||
if (m)
|
||
return m[1];
|
||
const d = new Date(s);
|
||
if (!isNaN(d.getTime())) {
|
||
const y = d.getFullYear();
|
||
const mo = String(d.getMonth() + 1).padStart(2, "0");
|
||
const da = String(d.getDate()).padStart(2, "0");
|
||
return `${y}-${mo}-${da}`;
|
||
}
|
||
return s;
|
||
},
|
||
startLogin() {
|
||
if (this.logging)
|
||
return;
|
||
this.logging = true;
|
||
const tryOnce = async () => ({});
|
||
uni.login({ provider: "weixin", success: async (res) => {
|
||
this.pendingJsCode = res.code || "";
|
||
if (!this.pendingJsCode) {
|
||
this.logging = false;
|
||
return uni.showToast({ title: "获取登录code失败", icon: "none" });
|
||
}
|
||
try {
|
||
await tryOnce();
|
||
} catch (e) {
|
||
const msg = e && e.message || "";
|
||
if (msg.includes("40163") || msg.toLowerCase().includes("been used")) {
|
||
uni.login({ provider: "weixin", success: async (r2) => {
|
||
const fresh = r2.code || "";
|
||
if (!fresh) {
|
||
this.logging = false;
|
||
return;
|
||
}
|
||
try {
|
||
await tryOnce();
|
||
} finally {
|
||
this.logging = false;
|
||
}
|
||
} });
|
||
return;
|
||
}
|
||
} finally {
|
||
this.logging = false;
|
||
}
|
||
}, fail: () => {
|
||
this.logging = false;
|
||
uni.showToast({ title: "微信登录失败", icon: "none" });
|
||
} });
|
||
},
|
||
goLogin() {
|
||
uni.navigateTo({ url: "/pages/auth/login" });
|
||
},
|
||
onGetPhoneNumber(e) {
|
||
if (this.logging)
|
||
return;
|
||
this.logging = true;
|
||
uni.login({ provider: "weixin", success: (res) => {
|
||
const jsCode = res.code || "";
|
||
if (!jsCode) {
|
||
this.logging = false;
|
||
return uni.showToast({ title: "获取登录code失败", icon: "none" });
|
||
}
|
||
Promise.resolve().finally(() => {
|
||
this.logging = false;
|
||
});
|
||
}, fail: () => {
|
||
this.logging = false;
|
||
uni.showToast({ title: "微信登录失败", icon: "none" });
|
||
} });
|
||
},
|
||
goSmsLogin() {
|
||
uni.navigateTo({ url: "/pages/my/sms-login" });
|
||
},
|
||
onAvatarError() {
|
||
this.avatarUrl = "/static/icons/icons8-mitt-24.png";
|
||
},
|
||
goVip() {
|
||
uni.navigateTo({ url: "/pages/my/vip" });
|
||
},
|
||
goMyOrders() {
|
||
uni.navigateTo({ url: "/pages/my/orders" });
|
||
},
|
||
editProfile() {
|
||
uni.navigateTo({ url: "/pages/my/security" });
|
||
},
|
||
goAbout() {
|
||
uni.navigateTo({ url: "/pages/my/about" });
|
||
},
|
||
logout() {
|
||
try {
|
||
uni.removeStorageSync("TOKEN");
|
||
uni.removeStorageSync("LOGINED");
|
||
uni.removeStorageSync("LOGIN_PHONE");
|
||
uni.removeStorageSync("DEFAULT_USER_ID");
|
||
uni.setStorageSync("ENABLE_DEFAULT_USER", "false");
|
||
uni.removeStorageSync("USER_AVATAR");
|
||
uni.removeStorageSync("USER_AVATAR_RAW");
|
||
uni.removeStorageSync("USER_NAME");
|
||
uni.removeStorageSync("USER_MOBILE");
|
||
uni.removeStorageSync("USER_EMAIL");
|
||
uni.removeStorageSync("SHOP_NAME");
|
||
uni.removeStorageSync("USER_VIP_IS_VIP");
|
||
uni.removeStorageSync("USER_VIP_START");
|
||
uni.removeStorageSync("USER_VIP_END");
|
||
uni.showToast({ title: "已清理本地信息", icon: "none" });
|
||
setTimeout(() => {
|
||
uni.reLaunch({ url: "/pages/index/index" });
|
||
}, 300);
|
||
} catch (e) {
|
||
uni.reLaunch({ url: "/pages/index/index" });
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "me" }, [
|
||
$options.isLoggedIn ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "card user"
|
||
}, [
|
||
vue.createElementVNode("image", {
|
||
class: "avatar",
|
||
src: $options.avatarDisplay,
|
||
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.emailDisplay),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode("text", { class: "role" }, "老板")
|
||
])
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "card user guest"
|
||
}, [
|
||
vue.createElementVNode("image", {
|
||
class: "avatar",
|
||
src: _imports_0$2,
|
||
mode: "aspectFill"
|
||
}),
|
||
vue.createElementVNode("view", { class: "meta" }, [
|
||
vue.createElementVNode("text", { class: "name" }, "未登录"),
|
||
vue.createElementVNode("text", { class: "phone" }, "登录后同步数据"),
|
||
vue.createElementVNode("text", { class: "role" }, "访客")
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "login-entry",
|
||
onClick: _cache[1] || (_cache[1] = (...args) => $options.goLogin && $options.goLogin(...args))
|
||
}, "登录")
|
||
])),
|
||
vue.createCommentVNode(" VIP 卡片(置于“会员与订单”分组上方) "),
|
||
$options.isLoggedIn ? (vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
key: 2,
|
||
class: vue.normalizeClass(["card vip", { active: $data.vipIsVip }])
|
||
},
|
||
[
|
||
vue.createElementVNode("view", { class: "vip-row" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "vip-badge" },
|
||
vue.toDisplayString($data.vipIsVip ? "VIP" : "非VIP"),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode("text", { class: "vip-title" }, "会员状态")
|
||
]),
|
||
vue.createElementVNode("view", { class: "vip-meta" }, [
|
||
vue.createElementVNode("view", { class: "item" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "开始"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($options.vipStartDisplay),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "item" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "结束"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString($options.vipEndDisplay),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
])
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)) : vue.createCommentVNode("v-if", true),
|
||
vue.createElementVNode("view", { class: "group" }, [
|
||
vue.createElementVNode("view", { class: "group-title" }, "会员与订单"),
|
||
vue.createElementVNode("view", {
|
||
class: "cell",
|
||
onClick: _cache[2] || (_cache[2] = (...args) => $options.goVip && $options.goVip(...args))
|
||
}, [
|
||
vue.createElementVNode("view", { class: "cell-left" }, [
|
||
vue.createElementVNode("text", null, "VIP会员"),
|
||
$data.vipIsVip ? (vue.openBlock(), vue.createElementBlock("text", {
|
||
key: 0,
|
||
class: "vip-tag"
|
||
}, "已开通")) : (vue.openBlock(), vue.createElementBlock("text", {
|
||
key: 1,
|
||
class: "vip-tag pending"
|
||
}, "待开通"))
|
||
]),
|
||
vue.createElementVNode("text", { class: "arrow" }, "›")
|
||
]),
|
||
vue.createElementVNode("view", {
|
||
class: "cell",
|
||
onClick: _cache[3] || (_cache[3] = (...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[4] || (_cache[4] = (...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[5] || (_cache[5] = (...args) => $options.goAbout && $options.goAbout(...args))
|
||
}, [
|
||
vue.createElementVNode("text", null, "关于与协议"),
|
||
vue.createElementVNode("text", { class: "arrow" }, "›")
|
||
]),
|
||
$options.isLoggedIn ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "cell danger",
|
||
onClick: _cache[6] || (_cache[6] = (...args) => $options.logout && $options.logout(...args))
|
||
}, [
|
||
vue.createElementVNode("text", null, "退出登录")
|
||
])) : vue.createCommentVNode("v-if", true)
|
||
])
|
||
]);
|
||
}
|
||
const PagesMyIndex = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$5], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/index.vue"]]);
|
||
const _imports_0$1 = "/static/logo.png";
|
||
const _sfc_main$5 = {
|
||
methods: {
|
||
openPolicy() {
|
||
uni.showModal({ title: "隐私协议", content: "隐私协议(静态占位)", showCancel: false });
|
||
},
|
||
openTerms() {
|
||
uni.showModal({ title: "用户协议", content: "用户协议(静态占位)", showCancel: false });
|
||
},
|
||
openComplaint() {
|
||
uni.showToast({ title: "暂未开通", icon: "none" });
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$4(_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$1,
|
||
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$5, [["render", _sfc_render$4], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/about.vue"]]);
|
||
const _sfc_main$4 = {
|
||
data() {
|
||
return {
|
||
form: { name: "", avatarUrl: "" },
|
||
pwd: { oldPassword: "", newPassword: "" },
|
||
phone: { phone: "" },
|
||
savingProfile: false,
|
||
savingPwd: false,
|
||
savingPhone: false,
|
||
sendingCode: false,
|
||
originalAvatarUrl: ""
|
||
};
|
||
},
|
||
onShow() {
|
||
this.loadProfile();
|
||
},
|
||
computed: {
|
||
avatarPreview() {
|
||
return this.normalizeAvatar(this.form.avatarUrl);
|
||
},
|
||
canSendPhone() {
|
||
const p = String(this.phone.phone || "").trim();
|
||
return /^1\d{10}$/.test(p);
|
||
}
|
||
},
|
||
methods: {
|
||
async loadProfile() {
|
||
try {
|
||
const data = await get("/api/user/me");
|
||
const rawAvatar = (data == null ? void 0 : data.avatarUrl) || (uni.getStorageSync("USER_AVATAR_RAW") || "");
|
||
this.originalAvatarUrl = rawAvatar;
|
||
this.form.name = (data == null ? void 0 : data.name) || (uni.getStorageSync("USER_NAME") || "");
|
||
this.form.avatarUrl = rawAvatar;
|
||
} catch (e) {
|
||
}
|
||
},
|
||
normalizeAvatar(url) {
|
||
if (!url)
|
||
return "/static/icons/icons8-mitt-24.png";
|
||
const s = String(url);
|
||
if (/^https?:\/\//i.test(s))
|
||
return s;
|
||
const base = API_BASE_URL || "";
|
||
if (!base)
|
||
return s;
|
||
if (s.startsWith("/"))
|
||
return `${base}${s}`;
|
||
return `${base}/${s}`;
|
||
},
|
||
openAvatarDialog() {
|
||
uni.showActionSheet({
|
||
itemList: ["粘贴图片URL", "从相册选择并上传"],
|
||
success: (res) => {
|
||
if (res.tapIndex === 0) {
|
||
uni.showModal({
|
||
title: "头像URL",
|
||
editable: true,
|
||
placeholderText: "https://...",
|
||
success: async (m) => {
|
||
if (m.confirm && m.content) {
|
||
this.form.avatarUrl = m.content.trim();
|
||
await this.saveProfile({ auto: true });
|
||
}
|
||
}
|
||
});
|
||
} else if (res.tapIndex === 1) {
|
||
uni.chooseImage({ count: 1, sizeType: ["compressed"], success: (ci) => {
|
||
const filePath = ci.tempFilePaths && ci.tempFilePaths[0] || "";
|
||
if (!filePath)
|
||
return;
|
||
uni.showLoading({ title: "上传中..." });
|
||
upload("/api/attachments", filePath, { ownerType: "user_avatar", ownerId: 0 }).then(async (data) => {
|
||
const url = data && (data.url || data.path);
|
||
if (url) {
|
||
this.form.avatarUrl = url;
|
||
await this.saveProfile({ auto: true });
|
||
}
|
||
uni.showToast({ title: "已上传", icon: "success" });
|
||
}).catch((e) => {
|
||
uni.showToast({ title: e && e.message || "上传失败", icon: "none" });
|
||
}).finally(() => {
|
||
uni.hideLoading();
|
||
});
|
||
} });
|
||
}
|
||
}
|
||
});
|
||
},
|
||
async saveProfile(opts = {}) {
|
||
const auto = opts && opts.auto;
|
||
const payload = {};
|
||
if (this.form.name && this.form.name !== uni.getStorageSync("USER_NAME"))
|
||
payload.name = this.form.name;
|
||
if (this.form.avatarUrl && this.form.avatarUrl !== this.originalAvatarUrl)
|
||
payload.avatarUrl = this.form.avatarUrl;
|
||
if (Object.keys(payload).length === 0) {
|
||
if (!auto)
|
||
uni.showToast({ title: "无需修改", icon: "none" });
|
||
return;
|
||
}
|
||
if (this.savingProfile)
|
||
return;
|
||
this.savingProfile = true;
|
||
try {
|
||
await put("/api/user/me", payload);
|
||
try {
|
||
if (payload.name)
|
||
uni.setStorageSync("USER_NAME", payload.name);
|
||
if (payload.avatarUrl) {
|
||
const rawUrl = payload.avatarUrl;
|
||
const displayUrl = `${rawUrl}${rawUrl.includes("?") ? "&" : "?"}t=${Date.now()}`;
|
||
uni.setStorageSync("USER_AVATAR_RAW", rawUrl);
|
||
uni.setStorageSync("USER_AVATAR", rawUrl);
|
||
this.originalAvatarUrl = rawUrl;
|
||
this.form.avatarUrl = rawUrl;
|
||
}
|
||
} catch (_) {
|
||
}
|
||
if (!payload.avatarUrl && this.form.avatarUrl) {
|
||
uni.setStorageSync("USER_AVATAR_RAW", this.form.avatarUrl);
|
||
uni.setStorageSync("USER_AVATAR", this.form.avatarUrl);
|
||
}
|
||
uni.showToast({ title: auto ? "头像已更新" : "已保存", icon: "success" });
|
||
} catch (e) {
|
||
const msg = e && e.message || "保存失败";
|
||
uni.showToast({ title: msg, icon: "none" });
|
||
} finally {
|
||
this.savingProfile = false;
|
||
}
|
||
},
|
||
async changePassword() {
|
||
if (!this.pwd.newPassword || this.pwd.newPassword.length < 6)
|
||
return uni.showToast({ title: "新密码至少6位", icon: "none" });
|
||
this.savingPwd = true;
|
||
try {
|
||
await put("/api/user/me/password", { oldPassword: this.pwd.oldPassword || void 0, newPassword: this.pwd.newPassword });
|
||
this.pwd.oldPassword = "";
|
||
this.pwd.newPassword = "";
|
||
uni.showToast({ title: "密码已修改", icon: "success" });
|
||
} catch (e) {
|
||
uni.showToast({ title: e && e.message || "修改失败", icon: "none" });
|
||
} finally {
|
||
this.savingPwd = false;
|
||
}
|
||
},
|
||
async changePhoneDirect() {
|
||
if (!this.canSendPhone)
|
||
return uni.showToast({ title: "请输入正确手机号", icon: "none" });
|
||
this.savingPhone = true;
|
||
try {
|
||
await put("/api/user/me/phone", { phone: this.phone.phone });
|
||
uni.setStorageSync("USER_MOBILE", this.phone.phone);
|
||
uni.showToast({ title: "手机号已保存", icon: "success" });
|
||
} catch (e) {
|
||
uni.showToast({ title: e && e.message || "保存失败", icon: "none" });
|
||
} finally {
|
||
this.savingPhone = false;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "security" }, [
|
||
vue.createElementVNode("view", { class: "card" }, [
|
||
vue.createElementVNode("view", {
|
||
class: "cell",
|
||
onClick: _cache[0] || (_cache[0] = (...args) => $options.openAvatarDialog && $options.openAvatarDialog(...args))
|
||
}, [
|
||
vue.createElementVNode("text", { class: "cell-label" }, "头像"),
|
||
vue.createElementVNode("image", {
|
||
class: "avatar-preview",
|
||
src: $options.avatarPreview,
|
||
mode: "aspectFill"
|
||
}, null, 8, ["src"]),
|
||
vue.createElementVNode("text", { class: "arrow" }, "›")
|
||
]),
|
||
vue.createElementVNode("view", { class: "cell" }, [
|
||
vue.createElementVNode("text", { class: "cell-label" }, "姓名"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "cell-input",
|
||
type: "text",
|
||
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $data.form.name = $event),
|
||
placeholder: "请输入姓名"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.form.name,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn",
|
||
type: "primary",
|
||
loading: $data.savingProfile,
|
||
onClick: _cache[2] || (_cache[2] = (...args) => $options.saveProfile && $options.saveProfile(...args))
|
||
}, "保存资料", 8, ["loading"])
|
||
]),
|
||
vue.createElementVNode("view", { class: "card" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "旧密码"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
password: "",
|
||
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.pwd.oldPassword = $event),
|
||
placeholder: "如从未设置可留空"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.pwd.oldPassword,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "新密码"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
password: "",
|
||
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.pwd.newPassword = $event),
|
||
placeholder: "至少6位"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.pwd.newPassword,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn",
|
||
loading: $data.savingPwd,
|
||
onClick: _cache[5] || (_cache[5] = (...args) => $options.changePassword && $options.changePassword(...args))
|
||
}, "修改密码", 8, ["loading"])
|
||
]),
|
||
vue.createElementVNode("view", { class: "card" }, [
|
||
vue.createElementVNode("view", { class: "row" }, [
|
||
vue.createElementVNode("text", { class: "label" }, "手机号"),
|
||
vue.withDirectives(vue.createElementVNode(
|
||
"input",
|
||
{
|
||
class: "input",
|
||
type: "text",
|
||
"onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => $data.phone.phone = $event),
|
||
placeholder: "11位手机号"
|
||
},
|
||
null,
|
||
512
|
||
/* NEED_PATCH */
|
||
), [
|
||
[
|
||
vue.vModelText,
|
||
$data.phone.phone,
|
||
void 0,
|
||
{ trim: true }
|
||
]
|
||
])
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "btn",
|
||
loading: $data.savingPhone,
|
||
onClick: _cache[7] || (_cache[7] = (...args) => $options.changePhoneDirect && $options.changePhoneDirect(...args))
|
||
}, "保存手机号", 8, ["loading"])
|
||
])
|
||
]);
|
||
}
|
||
const PagesMySecurity = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$3], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/security.vue"]]);
|
||
const _imports_0 = "/static/icons/icons8-vip-48 (1).png";
|
||
const _sfc_main$3 = {
|
||
data() {
|
||
return {
|
||
isVip: false,
|
||
expire: "",
|
||
price: 0,
|
||
benefits: [],
|
||
normalAdmin: { isNormalAdmin: false, applicationStatus: "none" }
|
||
};
|
||
},
|
||
onShow() {
|
||
this.loadVip();
|
||
this.loadNormalAdminStatus();
|
||
this.composeBenefits();
|
||
},
|
||
computed: {
|
||
expireDisplay() {
|
||
const v = this.expire;
|
||
if (v === null || v === void 0)
|
||
return "";
|
||
if (typeof v === "number") {
|
||
const d = new Date(v);
|
||
if (!isNaN(d.getTime())) {
|
||
const y = d.getFullYear();
|
||
const m2 = String(d.getMonth() + 1).padStart(2, "0");
|
||
const dd = String(d.getDate()).padStart(2, "0");
|
||
return `${y}-${m2}-${dd}`;
|
||
}
|
||
return "";
|
||
}
|
||
const s = String(v);
|
||
const m = s.match(/^(\d{4}-\d{2}-\d{2})/);
|
||
if (m)
|
||
return m[1];
|
||
const idx = s.search(/[ T]/);
|
||
if (idx > 0) {
|
||
const head = s.slice(0, idx);
|
||
if (head)
|
||
return head;
|
||
}
|
||
const d2 = new Date(s);
|
||
if (!isNaN(d2.getTime())) {
|
||
const y = d2.getFullYear();
|
||
const m2 = String(d2.getMonth() + 1).padStart(2, "0");
|
||
const dd2 = String(d2.getDate()).padStart(2, "0");
|
||
return `${y}-${m2}-${dd2}`;
|
||
}
|
||
return s;
|
||
},
|
||
priceDisplay() {
|
||
const n = Number(this.price);
|
||
return Number.isFinite(n) && n > 0 ? n.toFixed(2) : "0.00";
|
||
},
|
||
applyDisabled() {
|
||
var _a, _b;
|
||
const s = String(((_a = this.normalAdmin) == null ? void 0 : _a.applicationStatus) || "none");
|
||
return !!(((_b = this.normalAdmin) == null ? void 0 : _b.isNormalAdmin) || s === "approved" || s === "pending");
|
||
},
|
||
applyBtnText() {
|
||
var _a, _b, _c;
|
||
if (((_a = this.normalAdmin) == null ? void 0 : _a.isNormalAdmin) || ((_b = this.normalAdmin) == null ? void 0 : _b.applicationStatus) === "approved")
|
||
return "已通过";
|
||
if (((_c = this.normalAdmin) == null ? void 0 : _c.applicationStatus) === "pending")
|
||
return "审核中";
|
||
if (!this.isVip)
|
||
return "仅限VIP";
|
||
return "提交申请";
|
||
}
|
||
},
|
||
methods: {
|
||
composeBenefits() {
|
||
this.benefits = [
|
||
{ key: "history", title: "完整历史留存", desc: "无限期保留交易、库存与客户数据", icon: "/static/icons/icons8-graph-report-50.png" },
|
||
{ key: "analysis", title: "高级统计面板", desc: "秒级汇总销售毛利,掌握生意节奏", icon: "/static/icons/icons8-profit-50.png" },
|
||
{ key: "priority", title: "优先客服支持", desc: "遇到问题优先处理,响应更迅速", icon: "/static/icons/icons8-account-male-100.png" }
|
||
];
|
||
},
|
||
async loadVip() {
|
||
try {
|
||
const data = await get("/api/vip/status");
|
||
this.isVip = !!(data == null ? void 0 : data.isVip);
|
||
this.expire = (data == null ? void 0 : data.expireAt) || "";
|
||
if (typeof (data == null ? void 0 : data.price) === "number")
|
||
this.price = data.price;
|
||
} catch (e) {
|
||
this.isVip = false;
|
||
}
|
||
},
|
||
async loadNormalAdminStatus() {
|
||
try {
|
||
const data = await get("/api/normal-admin/application/status");
|
||
this.normalAdmin = {
|
||
isNormalAdmin: !!(data == null ? void 0 : data.isNormalAdmin),
|
||
applicationStatus: String((data == null ? void 0 : data.applicationStatus) || "none")
|
||
};
|
||
} catch (e) {
|
||
this.normalAdmin = { isNormalAdmin: false, applicationStatus: "none" };
|
||
}
|
||
},
|
||
async onPay() {
|
||
try {
|
||
await post("/api/vip/pay", {});
|
||
uni.showToast({ title: "已开通VIP", icon: "success" });
|
||
await this.loadVip();
|
||
} catch (e) {
|
||
uni.showToast({ title: String(e.message || "开通失败"), icon: "none" });
|
||
}
|
||
},
|
||
async onApplyNormalAdmin() {
|
||
var _a, _b, _c;
|
||
if (this.applyDisabled) {
|
||
const msg = ((_a = this.normalAdmin) == null ? void 0 : _a.isNormalAdmin) || ((_b = this.normalAdmin) == null ? void 0 : _b.applicationStatus) === "approved" ? "已通过,无需重复申请" : ((_c = this.normalAdmin) == null ? void 0 : _c.applicationStatus) === "pending" ? "审核中,请耐心等待" : "不可申请";
|
||
return uni.showToast({ title: msg, icon: "none" });
|
||
}
|
||
try {
|
||
await post("/api/normal-admin/apply", { remark: "从我的-会员发起申请" });
|
||
uni.showToast({ title: "申请已提交", icon: "success" });
|
||
await this.loadNormalAdminStatus();
|
||
} catch (e) {
|
||
uni.showToast({ title: String(e.message || "申请失败"), icon: "none" });
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "vip-page" }, [
|
||
vue.createElementVNode("view", { class: "vip-hero" }, [
|
||
vue.createElementVNode("image", {
|
||
class: "hero-icon",
|
||
src: _imports_0,
|
||
mode: "aspectFit"
|
||
}),
|
||
vue.createElementVNode("view", { class: "hero-text" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "hero-title" },
|
||
vue.toDisplayString($data.isVip ? "VIP会员" : "升级 VIP 会员"),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "hero-subtitle" },
|
||
vue.toDisplayString($data.isVip ? "尊享完整数据与高效体验" : "开通后可查看全部历史数据并解锁高级功能"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["status-pill", { active: $data.isVip }])
|
||
},
|
||
[
|
||
vue.createElementVNode(
|
||
"text",
|
||
null,
|
||
vue.toDisplayString($data.isVip ? "已开通" : "普通用户"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)
|
||
]),
|
||
$data.isVip ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "vip-summary"
|
||
}, [
|
||
vue.createElementVNode("view", { class: "summary-item" }, [
|
||
vue.createElementVNode("text", { class: "summary-label" }, "会员状态"),
|
||
vue.createElementVNode("text", { class: "summary-value success" }, "已激活")
|
||
]),
|
||
vue.createElementVNode("view", { class: "summary-item" }, [
|
||
vue.createElementVNode("text", { class: "summary-label" }, "有效期至"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "summary-value" },
|
||
vue.toDisplayString($options.expireDisplay),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
])) : (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "vip-summary"
|
||
}, [
|
||
vue.createElementVNode("view", { class: "summary-item" }, [
|
||
vue.createElementVNode("text", { class: "summary-label" }, "当前身份"),
|
||
vue.createElementVNode("text", { class: "summary-value" }, "普通用户")
|
||
]),
|
||
vue.createElementVNode("view", { class: "summary-item" }, [
|
||
vue.createElementVNode("text", { class: "summary-label" }, "会员价格"),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "summary-value highlight" },
|
||
"¥" + vue.toDisplayString($options.priceDisplay) + "/月",
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])
|
||
])),
|
||
vue.createElementVNode("view", { class: "benefit-section" }, [
|
||
vue.createElementVNode("view", { class: "section-header" }, [
|
||
vue.createElementVNode("text", { class: "section-title" }, "会员特权"),
|
||
vue.createElementVNode("text", { class: "section-subtitle" }, "聚焦数据留存与专业形象,让经营更有底气")
|
||
]),
|
||
vue.createElementVNode("view", { class: "benefit-grid" }, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($data.benefits, (item) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
key: item.key,
|
||
class: "benefit-card"
|
||
}, [
|
||
item.icon ? (vue.openBlock(), vue.createElementBlock("image", {
|
||
key: 0,
|
||
src: item.icon,
|
||
class: "benefit-icon",
|
||
mode: "aspectFit"
|
||
}, null, 8, ["src"])) : vue.createCommentVNode("v-if", true),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "benefit-title" },
|
||
vue.toDisplayString(item.title),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "benefit-desc" },
|
||
vue.toDisplayString(item.desc),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])
|
||
]),
|
||
vue.createCommentVNode(" 已是VIP:展示申请普通管理员入口 "),
|
||
$data.isVip ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 2,
|
||
class: "apply-card"
|
||
}, [
|
||
vue.createElementVNode("view", { class: "apply-text" }, [
|
||
vue.createElementVNode("text", { class: "apply-title" }, "申请成为普通管理员"),
|
||
vue.createElementVNode("text", { class: "apply-desc" }, "在普通管理端参与配件审核")
|
||
]),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
role: "button",
|
||
class: vue.normalizeClass(["apply-btn", { disabled: $options.applyDisabled }]),
|
||
onClick: _cache[0] || (_cache[0] = (...args) => $options.onApplyNormalAdmin && $options.onApplyNormalAdmin(...args))
|
||
},
|
||
[
|
||
vue.createElementVNode(
|
||
"text",
|
||
null,
|
||
vue.toDisplayString($options.applyBtnText),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
],
|
||
2
|
||
/* CLASS */
|
||
)
|
||
])) : vue.createCommentVNode("v-if", true),
|
||
!$data.isVip ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 3,
|
||
class: "purchase-card"
|
||
}, [
|
||
vue.createElementVNode("view", { class: "purchase-text" }, [
|
||
vue.createElementVNode("text", { class: "purchase-title" }, "立即升级 VIP"),
|
||
vue.createElementVNode("text", { class: "purchase-desc" }, "不限历史数据、专属标识,助您高效管账")
|
||
]),
|
||
vue.createElementVNode("button", {
|
||
class: "purchase-btn",
|
||
onClick: _cache[1] || (_cache[1] = (...args) => $options.onPay && $options.onPay(...args))
|
||
}, [
|
||
vue.createElementVNode("text", null, "立即开通")
|
||
])
|
||
])) : vue.createCommentVNode("v-if", true)
|
||
]);
|
||
}
|
||
const PagesMyVip = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/vip.vue"]]);
|
||
const _sfc_main$2 = {
|
||
data() {
|
||
return { list: [], page: 1, size: 20, loading: false };
|
||
},
|
||
onShow() {
|
||
this.fetch(true);
|
||
},
|
||
computed: {
|
||
isLoggedIn() {
|
||
try {
|
||
return !!uni.getStorageSync("TOKEN");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
async fetch(reset = false) {
|
||
if (!this.isLoggedIn)
|
||
return;
|
||
if (this.loading)
|
||
return;
|
||
this.loading = true;
|
||
try {
|
||
const p = reset ? 1 : this.page;
|
||
const data = await get("/api/vip/recharges", { page: p, size: this.size });
|
||
const arr = Array.isArray(data == null ? void 0 : data.list) ? data.list : [];
|
||
this.list = reset ? arr : (this.list || []).concat(arr);
|
||
this.page = p + 1;
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
fmt(v) {
|
||
if (!v)
|
||
return "";
|
||
const s = String(v);
|
||
const m = s.match(/^(\d{4}-\d{2}-\d{2})([ T](\d{2}:\d{2}))/);
|
||
return m ? `${m[1]} ${m[3]}` : s;
|
||
},
|
||
toMoney(v) {
|
||
try {
|
||
return Number(v).toFixed(2);
|
||
} catch (_) {
|
||
return v;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "orders" }, [
|
||
!$options.isLoggedIn ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "hint"
|
||
}, "请先登录后查看VIP支付记录")) : (vue.openBlock(), vue.createElementBlock("view", { key: 1 }, [
|
||
(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: "row1" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "price" },
|
||
"¥ " + vue.toDisplayString($options.toMoney(it.price)),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "channel" },
|
||
vue.toDisplayString(it.channel || "支付"),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
vue.createElementVNode("view", { class: "row2" }, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "date" },
|
||
vue.toDisplayString($options.fmt(it.createdAt)),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "duration" },
|
||
vue.toDisplayString(it.durationDays) + " 天",
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]),
|
||
it.expireTo ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "row3"
|
||
}, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "expire" },
|
||
"有效期至 " + vue.toDisplayString($options.fmt(it.expireTo)),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
])) : vue.createCommentVNode("v-if", true)
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
)),
|
||
$data.list.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "empty"
|
||
}, "暂无支付记录")) : vue.createCommentVNode("v-if", true)
|
||
]))
|
||
]);
|
||
}
|
||
const PagesMyOrders = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__file", "C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/orders.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),
|
||
dim: "customer",
|
||
rows: [],
|
||
summary: { salesAmount: 0, costAmount: 0, profit: 0, profitRate: 0, itemCount: 0 },
|
||
loading: false,
|
||
error: ""
|
||
};
|
||
},
|
||
onLoad(query) {
|
||
try {
|
||
const d = query && query.dim;
|
||
if (d === "product" || d === "customer")
|
||
this.dim = d;
|
||
} catch (e) {
|
||
}
|
||
this.refresh();
|
||
},
|
||
computed: {
|
||
profitRateText() {
|
||
var _a;
|
||
const rate = Number(((_a = this.summary) == null ? void 0 : _a.profitRate) || 0);
|
||
return rate.toFixed(2) + "%";
|
||
},
|
||
summaryItems() {
|
||
if (!this.rows.length)
|
||
return [];
|
||
return [
|
||
{ label: "销售额", value: `¥ ${this.fmt(this.summary.salesAmount)}` },
|
||
{ label: "成本", value: `¥ ${this.fmt(this.summary.costAmount)}` },
|
||
{ label: "利润", value: `¥ ${this.fmt(this.summary.profit)}` },
|
||
{ label: "利润率", value: this.profitRateText }
|
||
];
|
||
}
|
||
},
|
||
methods: {
|
||
fmt(n) {
|
||
return Number(n || 0).toFixed(2);
|
||
},
|
||
showProductSpec(row) {
|
||
return this.dim === "product" && row && row.spec;
|
||
},
|
||
rowMetrics(row) {
|
||
if (!row)
|
||
return [];
|
||
return [
|
||
{ label: "销售额", value: `¥ ${this.fmt(row.salesAmount)}` },
|
||
{ label: "成本", value: `¥ ${this.fmt(row.costAmount)}` },
|
||
{ label: "利润", value: `¥ ${this.fmt(row.profit)}` },
|
||
{ label: "利润率", value: `${Number(row.profitRate || 0).toFixed(2)}%` }
|
||
];
|
||
},
|
||
setDimension(d) {
|
||
if (d !== "customer" && d !== "product")
|
||
return;
|
||
if (this.dim === d)
|
||
return;
|
||
this.dim = d;
|
||
this.refresh();
|
||
},
|
||
onStartChange(e) {
|
||
this.startDate = e.detail.value;
|
||
this.refresh();
|
||
},
|
||
onEndChange(e) {
|
||
this.endDate = e.detail.value;
|
||
this.refresh();
|
||
},
|
||
async refresh() {
|
||
var _a, _b, _c, _d, _e;
|
||
this.loading = true;
|
||
this.error = "";
|
||
try {
|
||
const resp = await get("/api/report/sales", {
|
||
dimension: this.dim,
|
||
startDate: this.startDate,
|
||
endDate: this.endDate
|
||
});
|
||
const items = Array.isArray(resp == null ? void 0 : resp.items) ? resp.items : [];
|
||
this.rows = items.map((it) => ({
|
||
name: (it == null ? void 0 : it.name) || (this.dim === "product" ? "未命名商品" : "未指定客户"),
|
||
spec: (it == null ? void 0 : it.spec) || "",
|
||
salesAmount: Number((it == null ? void 0 : it.salesAmount) || 0),
|
||
costAmount: Number((it == null ? void 0 : it.costAmount) || 0),
|
||
profit: Number((it == null ? void 0 : it.profit) || 0),
|
||
profitRate: Number((it == null ? void 0 : it.profitRate) || 0)
|
||
}));
|
||
this.summary = {
|
||
salesAmount: Number(((_a = resp == null ? void 0 : resp.summary) == null ? void 0 : _a.salesAmount) || 0),
|
||
costAmount: Number(((_b = resp == null ? void 0 : resp.summary) == null ? void 0 : _b.costAmount) || 0),
|
||
profit: Number(((_c = resp == null ? void 0 : resp.summary) == null ? void 0 : _c.profit) || 0),
|
||
profitRate: Number(((_d = resp == null ? void 0 : resp.summary) == null ? void 0 : _d.profitRate) || 0),
|
||
itemCount: Number(((_e = resp == null ? void 0 : resp.summary) == null ? void 0 : _e.itemCount) || this.rows.length)
|
||
};
|
||
} catch (e) {
|
||
this.error = e && e.message || "报表加载失败";
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||
return vue.openBlock(), vue.createElementBlock("view", { class: "report" }, [
|
||
vue.createElementVNode("view", { class: "header" }, "销售报表"),
|
||
vue.createElementVNode("view", { class: "toolbar" }, [
|
||
vue.createElementVNode("picker", {
|
||
mode: "date",
|
||
value: $data.startDate,
|
||
onChange: _cache[0] || (_cache[0] = (...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[1] || (_cache[1] = (...args) => $options.onEndChange && $options.onEndChange(...args))
|
||
}, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "date" },
|
||
vue.toDisplayString($data.endDate),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
], 40, ["value"])
|
||
]),
|
||
vue.createElementVNode("view", { class: "tabs" }, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["tab", { active: $data.dim === "customer" }]),
|
||
onClick: _cache[2] || (_cache[2] = ($event) => $options.setDimension("customer"))
|
||
},
|
||
"按客户",
|
||
2
|
||
/* CLASS */
|
||
),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{
|
||
class: vue.normalizeClass(["tab", { active: $data.dim === "product" }]),
|
||
onClick: _cache[3] || (_cache[3] = ($event) => $options.setDimension("product"))
|
||
},
|
||
"按货品",
|
||
2
|
||
/* CLASS */
|
||
)
|
||
]),
|
||
$options.summaryItems.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 0,
|
||
class: "summary"
|
||
}, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($options.summaryItems, (item, ix) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
class: "summary-item",
|
||
key: ix
|
||
}, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "label" },
|
||
vue.toDisplayString(item.label),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "value" },
|
||
vue.toDisplayString(item.value),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])) : vue.createCommentVNode("v-if", true),
|
||
$data.loading ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 1,
|
||
class: "loading"
|
||
}, "加载中...")) : $data.error ? (vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
key: 2,
|
||
class: "empty"
|
||
},
|
||
vue.toDisplayString($data.error),
|
||
1
|
||
/* TEXT */
|
||
)) : !$data.rows.length ? (vue.openBlock(), vue.createElementBlock("view", {
|
||
key: 3,
|
||
class: "empty"
|
||
}, "暂无统计数据")) : (vue.openBlock(), vue.createElementBlock("view", { key: 4 }, [
|
||
(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" }, [
|
||
vue.createElementVNode("view", { class: "row-title" }, [
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "title" },
|
||
vue.toDisplayString(row.name),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
$options.showProductSpec(row) ? (vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
key: 0,
|
||
class: "subtitle"
|
||
},
|
||
vue.toDisplayString(row.spec),
|
||
1
|
||
/* TEXT */
|
||
)) : vue.createCommentVNode("v-if", true)
|
||
])
|
||
]),
|
||
vue.createElementVNode("view", { class: "row-body" }, [
|
||
(vue.openBlock(true), vue.createElementBlock(
|
||
vue.Fragment,
|
||
null,
|
||
vue.renderList($options.rowMetrics(row), (metric, mIdx) => {
|
||
return vue.openBlock(), vue.createElementBlock("view", {
|
||
class: "metric",
|
||
key: mIdx
|
||
}, [
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "metric-label" },
|
||
vue.toDisplayString(metric.label),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
vue.createElementVNode(
|
||
"text",
|
||
{ class: "metric-value" },
|
||
vue.toDisplayString(metric.value),
|
||
1
|
||
/* TEXT */
|
||
)
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
])
|
||
]);
|
||
}),
|
||
128
|
||
/* KEYED_FRAGMENT */
|
||
))
|
||
]))
|
||
]);
|
||
}
|
||
const PagesReportIndex = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__file", "C:/Users/21826/Desktop/Wj/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/submit", PagesProductSubmit);
|
||
__definePage("pages/product/submissions", PagesProductSubmissions);
|
||
__definePage("pages/product/submission-detail", PagesProductSubmissionDetail);
|
||
__definePage("pages/product/form", PagesProductForm);
|
||
__definePage("pages/product/product-detail", PagesProductProductDetail);
|
||
__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/auth/login", PagesAuthLogin);
|
||
__definePage("pages/auth/register", PagesAuthRegister);
|
||
__definePage("pages/my/index", PagesMyIndex);
|
||
__definePage("pages/my/about", PagesMyAbout);
|
||
__definePage("pages/my/security", PagesMySecurity);
|
||
__definePage("pages/my/vip", PagesMyVip);
|
||
__definePage("pages/my/orders", PagesMyOrders);
|
||
__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", "C:/Users/21826/Desktop/Wj/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);
|