9.17/1
This commit is contained in:
5
frontend/unpackage/dist/dev/mp-weixin/app.js
vendored
5
frontend/unpackage/dist/dev/mp-weixin/app.js
vendored
@@ -5,6 +5,11 @@ if (!Math) {
|
||||
"./pages/index/index.js";
|
||||
"./pages/order/create.js";
|
||||
"./pages/product/select.js";
|
||||
"./pages/product/list.js";
|
||||
"./pages/product/form.js";
|
||||
"./pages/product/categories.js";
|
||||
"./pages/product/units.js";
|
||||
"./pages/product/settings.js";
|
||||
"./pages/customer/select.js";
|
||||
"./pages/supplier/select.js";
|
||||
"./pages/account/select.js";
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
"pages/index/index",
|
||||
"pages/order/create",
|
||||
"pages/product/select",
|
||||
"pages/product/list",
|
||||
"pages/product/form",
|
||||
"pages/product/categories",
|
||||
"pages/product/units",
|
||||
"pages/product/settings",
|
||||
"pages/customer/select",
|
||||
"pages/supplier/select",
|
||||
"pages/account/select"
|
||||
|
||||
@@ -2,18 +2,21 @@
|
||||
const common_vendor = require("./vendor.js");
|
||||
const envBaseUrl = typeof process !== "undefined" && process.env && (process.env.VITE_APP_API_BASE_URL || process.env.API_BASE_URL) || "";
|
||||
const storageBaseUrl = typeof common_vendor.index !== "undefined" ? common_vendor.index.getStorageSync("API_BASE_URL") || "" : "";
|
||||
const fallbackBaseUrl = "http://localhost:8080";
|
||||
const fallbackBaseUrl = "http://192.168.31.193: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" && process.env && (process.env.VITE_APP_SHOP_ID || process.env.SHOP_ID) || "";
|
||||
const storageShopId = typeof common_vendor.index !== "undefined" ? common_vendor.index.getStorageSync("SHOP_ID") || "" : "";
|
||||
const SHOP_ID = Number(envShopId || storageShopId || 1);
|
||||
const envEnableDefaultUser = typeof process !== "undefined" && process.env && (process.env.VITE_APP_ENABLE_DEFAULT_USER || process.env.ENABLE_DEFAULT_USER) || "";
|
||||
const storageEnableDefaultUser = typeof common_vendor.index !== "undefined" ? common_vendor.index.getStorageSync("ENABLE_DEFAULT_USER") || "" : "";
|
||||
const ENABLE_DEFAULT_USER = String(envEnableDefaultUser || storageEnableDefaultUser || "false").toLowerCase() === "true";
|
||||
const ENABLE_DEFAULT_USER = String(envEnableDefaultUser || storageEnableDefaultUser || "true").toLowerCase() === "true";
|
||||
const envDefaultUserId = typeof process !== "undefined" && process.env && (process.env.VITE_APP_DEFAULT_USER_ID || process.env.DEFAULT_USER_ID) || "";
|
||||
const storageDefaultUserId = typeof common_vendor.index !== "undefined" ? common_vendor.index.getStorageSync("DEFAULT_USER_ID") || "" : "";
|
||||
const DEFAULT_USER_ID = Number(envDefaultUserId || storageDefaultUserId || 2);
|
||||
exports.API_BASE_URL = API_BASE_URL;
|
||||
exports.API_BASE_URL_CANDIDATES = API_BASE_URL_CANDIDATES;
|
||||
exports.DEFAULT_USER_ID = DEFAULT_USER_ID;
|
||||
exports.ENABLE_DEFAULT_USER = ENABLE_DEFAULT_USER;
|
||||
exports.SHOP_ID = SHOP_ID;
|
||||
|
||||
103
frontend/unpackage/dist/dev/mp-weixin/common/http.js
vendored
103
frontend/unpackage/dist/dev/mp-weixin/common/http.js
vendored
@@ -8,24 +8,29 @@ function buildUrl(path) {
|
||||
return path;
|
||||
return common_config.API_BASE_URL + (path.startsWith("/") ? path : "/" + path);
|
||||
}
|
||||
function requestWithFallback(options, candidates, idx, resolve, reject) {
|
||||
const base = candidates[idx] || common_config.API_BASE_URL;
|
||||
const url = options.url.replace(/^https?:\/\/[^/]+/, base);
|
||||
common_vendor.index.request({ ...options, url, success: (res) => {
|
||||
const { statusCode, data } = res;
|
||||
if (statusCode >= 200 && statusCode < 300)
|
||||
return resolve(data);
|
||||
if (idx + 1 < candidates.length)
|
||||
return requestWithFallback(options, candidates, idx + 1, resolve, reject);
|
||||
reject(new Error("HTTP " + statusCode));
|
||||
}, fail: (err) => {
|
||||
if (idx + 1 < candidates.length)
|
||||
return requestWithFallback(options, candidates, idx + 1, resolve, reject);
|
||||
reject(err);
|
||||
} });
|
||||
}
|
||||
function get(path, params = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const headers = { "X-Shop-Id": common_config.SHOP_ID };
|
||||
if (common_config.ENABLE_DEFAULT_USER && common_config.DEFAULT_USER_ID)
|
||||
headers["X-User-Id"] = common_config.DEFAULT_USER_ID;
|
||||
common_vendor.index.request({
|
||||
url: buildUrl(path),
|
||||
method: "GET",
|
||||
data: params,
|
||||
header: headers,
|
||||
success: (res) => {
|
||||
const { statusCode, data } = res;
|
||||
if (statusCode >= 200 && statusCode < 300)
|
||||
return resolve(data);
|
||||
reject(new Error("HTTP " + statusCode));
|
||||
},
|
||||
fail: (err) => reject(err)
|
||||
});
|
||||
const options = { url: buildUrl(path), method: "GET", data: params, header: headers };
|
||||
requestWithFallback(options, common_config.API_BASE_URL_CANDIDATES, 0, resolve, reject);
|
||||
});
|
||||
}
|
||||
function post(path, body = {}) {
|
||||
@@ -33,21 +38,67 @@ function post(path, body = {}) {
|
||||
const headers = { "Content-Type": "application/json", "X-Shop-Id": common_config.SHOP_ID };
|
||||
if (common_config.ENABLE_DEFAULT_USER && common_config.DEFAULT_USER_ID)
|
||||
headers["X-User-Id"] = common_config.DEFAULT_USER_ID;
|
||||
common_vendor.index.request({
|
||||
url: buildUrl(path),
|
||||
method: "POST",
|
||||
data: body,
|
||||
header: headers,
|
||||
success: (res) => {
|
||||
const { statusCode, data } = res;
|
||||
if (statusCode >= 200 && statusCode < 300)
|
||||
return resolve(data);
|
||||
reject(new Error("HTTP " + statusCode));
|
||||
},
|
||||
fail: (err) => reject(err)
|
||||
});
|
||||
const options = { url: buildUrl(path), method: "POST", data: body, header: headers };
|
||||
requestWithFallback(options, common_config.API_BASE_URL_CANDIDATES, 0, resolve, reject);
|
||||
});
|
||||
}
|
||||
function put(path, body = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const headers = { "Content-Type": "application/json", "X-Shop-Id": common_config.SHOP_ID };
|
||||
if (common_config.ENABLE_DEFAULT_USER && common_config.DEFAULT_USER_ID)
|
||||
headers["X-User-Id"] = common_config.DEFAULT_USER_ID;
|
||||
const options = { url: buildUrl(path), method: "PUT", data: body, header: headers };
|
||||
requestWithFallback(options, common_config.API_BASE_URL_CANDIDATES, 0, resolve, reject);
|
||||
});
|
||||
}
|
||||
function del(path, body = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const headers = { "Content-Type": "application/json", "X-Shop-Id": common_config.SHOP_ID };
|
||||
if (common_config.ENABLE_DEFAULT_USER && common_config.DEFAULT_USER_ID)
|
||||
headers["X-User-Id"] = common_config.DEFAULT_USER_ID;
|
||||
const options = { url: buildUrl(path), method: "DELETE", data: body, header: headers };
|
||||
requestWithFallback(options, common_config.API_BASE_URL_CANDIDATES, 0, resolve, reject);
|
||||
});
|
||||
}
|
||||
function uploadWithFallback(options, candidates, idx, resolve, reject) {
|
||||
const base = candidates[idx] || common_config.API_BASE_URL;
|
||||
const url = options.url.replace(/^https?:\/\/[^/]+/, base);
|
||||
const uploadOptions = { ...options, url };
|
||||
common_vendor.index.uploadFile({
|
||||
...uploadOptions,
|
||||
success: (res) => {
|
||||
const statusCode = res.statusCode || 0;
|
||||
if (statusCode >= 200 && statusCode < 300) {
|
||||
try {
|
||||
const data = typeof res.data === "string" ? JSON.parse(res.data) : res.data;
|
||||
return resolve(data);
|
||||
} catch (e) {
|
||||
return resolve(res.data);
|
||||
}
|
||||
}
|
||||
if (idx + 1 < candidates.length)
|
||||
return uploadWithFallback(options, candidates, idx + 1, resolve, reject);
|
||||
reject(new Error("HTTP " + statusCode));
|
||||
},
|
||||
fail: (err) => {
|
||||
if (idx + 1 < candidates.length)
|
||||
return uploadWithFallback(options, candidates, idx + 1, resolve, reject);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
function upload(path, filePath, formData = {}, name = "file") {
|
||||
return new Promise((resolve, reject) => {
|
||||
const header = { "X-Shop-Id": common_config.SHOP_ID };
|
||||
if (common_config.ENABLE_DEFAULT_USER && common_config.DEFAULT_USER_ID)
|
||||
header["X-User-Id"] = common_config.DEFAULT_USER_ID;
|
||||
const options = { url: buildUrl(path), filePath, name, formData, header };
|
||||
uploadWithFallback(options, common_config.API_BASE_URL_CANDIDATES, 0, resolve, reject);
|
||||
});
|
||||
}
|
||||
exports.del = del;
|
||||
exports.get = get;
|
||||
exports.post = post;
|
||||
exports.put = put;
|
||||
exports.upload = upload;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/http.js.map
|
||||
|
||||
@@ -68,8 +68,8 @@ const capitalize = cacheStringFunction((str) => {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
});
|
||||
const toHandlerKey = cacheStringFunction((str) => {
|
||||
const s = str ? `on${capitalize(str)}` : ``;
|
||||
return s;
|
||||
const s2 = str ? `on${capitalize(str)}` : ``;
|
||||
return s2;
|
||||
});
|
||||
const hasChanged = (value, oldValue) => !Object.is(value, oldValue);
|
||||
const invokeArrayFns$1 = (fns, arg) => {
|
||||
@@ -92,6 +92,36 @@ const toNumber = (val) => {
|
||||
const n = isString(val) ? Number(val) : NaN;
|
||||
return isNaN(n) ? val : n;
|
||||
};
|
||||
function normalizeStyle(value) {
|
||||
if (isArray(value)) {
|
||||
const res = {};
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const item = value[i];
|
||||
const normalized = isString(item) ? parseStringStyle(item) : normalizeStyle(item);
|
||||
if (normalized) {
|
||||
for (const key in normalized) {
|
||||
res[key] = normalized[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
} else if (isString(value) || isObject(value)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
const listDelimiterRE = /;(?![^(]*\))/g;
|
||||
const propertyDelimiterRE = /:([^]+)/;
|
||||
const styleCommentRE = /\/\*[^]*?\*\//g;
|
||||
function parseStringStyle(cssText) {
|
||||
const ret = {};
|
||||
cssText.replace(styleCommentRE, "").split(listDelimiterRE).forEach((item) => {
|
||||
if (item) {
|
||||
const tmp = item.split(propertyDelimiterRE);
|
||||
tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim());
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
const toDisplayString = (val) => {
|
||||
return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val);
|
||||
};
|
||||
@@ -1287,6 +1317,9 @@ function isReadonly(value) {
|
||||
function isShallow(value) {
|
||||
return !!(value && value["__v_isShallow"]);
|
||||
}
|
||||
function isProxy(value) {
|
||||
return isReactive(value) || isReadonly(value);
|
||||
}
|
||||
function toRaw(observed) {
|
||||
const raw = observed && observed["__v_raw"];
|
||||
return raw ? toRaw(raw) : observed;
|
||||
@@ -2078,6 +2111,47 @@ function setCurrentRenderingInstance(instance) {
|
||||
instance && instance.type.__scopeId || null;
|
||||
return prev;
|
||||
}
|
||||
const COMPONENTS = "components";
|
||||
function resolveComponent(name, maybeSelfReference) {
|
||||
return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name;
|
||||
}
|
||||
function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) {
|
||||
const instance = currentRenderingInstance || currentInstance;
|
||||
if (instance) {
|
||||
const Component2 = instance.type;
|
||||
if (type === COMPONENTS) {
|
||||
const selfName = getComponentName(
|
||||
Component2,
|
||||
false
|
||||
);
|
||||
if (selfName && (selfName === name || selfName === camelize(name) || selfName === capitalize(camelize(name)))) {
|
||||
return Component2;
|
||||
}
|
||||
}
|
||||
const res = (
|
||||
// local registration
|
||||
// check instance[type] first which is resolved for options API
|
||||
resolve(instance[type] || Component2[type], name) || // global registration
|
||||
resolve(instance.appContext[type], name)
|
||||
);
|
||||
if (!res && maybeSelfReference) {
|
||||
return Component2;
|
||||
}
|
||||
if (warnMissing && !res) {
|
||||
const extra = type === COMPONENTS ? `
|
||||
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.` : ``;
|
||||
warn$1(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
warn$1(
|
||||
`resolve${capitalize(type.slice(0, -1))} can only be used in render() or setup().`
|
||||
);
|
||||
}
|
||||
}
|
||||
function resolve(registry, name) {
|
||||
return registry && (registry[name] || registry[camelize(name)] || registry[capitalize(camelize(name))]);
|
||||
}
|
||||
const INITIAL_WATCHER_VALUE = {};
|
||||
function watch(source, cb, options) {
|
||||
if (!isFunction(cb)) {
|
||||
@@ -3692,6 +3766,12 @@ const Static = Symbol.for("v-stc");
|
||||
function isVNode(value) {
|
||||
return value ? value.__v_isVNode === true : false;
|
||||
}
|
||||
const InternalObjectKey = `__vInternal`;
|
||||
function guardReactiveProps(props) {
|
||||
if (!props)
|
||||
return null;
|
||||
return isProxy(props) || InternalObjectKey in props ? extend({}, props) : props;
|
||||
}
|
||||
const emptyAppContext = createAppContext();
|
||||
let uid = 0;
|
||||
function createComponentInstance(vnode, parent, suspense) {
|
||||
@@ -4932,6 +5012,11 @@ function initApp(app) {
|
||||
}
|
||||
}
|
||||
const propsCaches = /* @__PURE__ */ Object.create(null);
|
||||
function renderProps(props) {
|
||||
const { uid: uid2, __counter } = getCurrentInstance();
|
||||
const propsId = (propsCaches[uid2] || (propsCaches[uid2] = [])).push(guardReactiveProps(props)) - 1;
|
||||
return uid2 + "," + propsId + "," + __counter;
|
||||
}
|
||||
function pruneComponentPropsCache(uid2) {
|
||||
delete propsCaches[uid2];
|
||||
}
|
||||
@@ -4972,6 +5057,22 @@ function getCreateApp() {
|
||||
return my[method];
|
||||
}
|
||||
}
|
||||
function stringifyStyle(value) {
|
||||
if (isString(value)) {
|
||||
return value;
|
||||
}
|
||||
return stringify(normalizeStyle(value));
|
||||
}
|
||||
function stringify(styles) {
|
||||
let ret = "";
|
||||
if (!styles || isString(styles)) {
|
||||
return ret;
|
||||
}
|
||||
for (const key in styles) {
|
||||
ret += `${key.startsWith(`--`) ? key : hyphenate(key)}:${styles[key]};`;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
function vOn(value, key) {
|
||||
const instance = getCurrentInstance();
|
||||
const ctx = instance.ctx;
|
||||
@@ -5121,8 +5222,10 @@ function withModelModifiers(fn, { number, trim }, isComponent = false) {
|
||||
}
|
||||
const o = (value, key) => vOn(value, key);
|
||||
const f = (source, renderItem) => vFor(source, renderItem);
|
||||
const s = (value) => stringifyStyle(value);
|
||||
const e = (target, ...sources) => extend(target, ...sources);
|
||||
const t = (val) => toDisplayString(val);
|
||||
const p = (props) => renderProps(props);
|
||||
const m = (fn, modifiers, isComponent = false) => withModelModifiers(fn, modifiers, isComponent);
|
||||
function createApp$1(rootComponent, rootProps = null) {
|
||||
rootComponent && (rootComponent.mpType = "app");
|
||||
@@ -5445,8 +5548,8 @@ function promisify$1(name, fn) {
|
||||
if (hasCallback(args)) {
|
||||
return wrapperReturnValue(name, invokeApi(name, fn, extend({}, args), rest));
|
||||
}
|
||||
return wrapperReturnValue(name, handlePromise(new Promise((resolve, reject) => {
|
||||
invokeApi(name, fn, extend({}, args, { success: resolve, fail: reject }), rest);
|
||||
return wrapperReturnValue(name, handlePromise(new Promise((resolve2, reject) => {
|
||||
invokeApi(name, fn, extend({}, args, { success: resolve2, fail: reject }), rest);
|
||||
})));
|
||||
};
|
||||
}
|
||||
@@ -5767,7 +5870,7 @@ function invokeGetPushCidCallbacks(cid2, errMsg) {
|
||||
getPushCidCallbacks.length = 0;
|
||||
}
|
||||
const API_GET_PUSH_CLIENT_ID = "getPushClientId";
|
||||
const getPushClientId = defineAsyncApi(API_GET_PUSH_CLIENT_ID, (_, { resolve, reject }) => {
|
||||
const getPushClientId = defineAsyncApi(API_GET_PUSH_CLIENT_ID, (_, { resolve: resolve2, reject }) => {
|
||||
Promise.resolve().then(() => {
|
||||
if (typeof enabled === "undefined") {
|
||||
enabled = false;
|
||||
@@ -5776,7 +5879,7 @@ const getPushClientId = defineAsyncApi(API_GET_PUSH_CLIENT_ID, (_, { resolve, re
|
||||
}
|
||||
getPushCidCallbacks.push((cid2, errMsg) => {
|
||||
if (cid2) {
|
||||
resolve({ cid: cid2 });
|
||||
resolve2({ cid: cid2 });
|
||||
} else {
|
||||
reject(errMsg);
|
||||
}
|
||||
@@ -5845,9 +5948,9 @@ function promisify(name, api) {
|
||||
if (isFunction(options.success) || isFunction(options.fail) || isFunction(options.complete)) {
|
||||
return wrapperReturnValue(name, invokeApi(name, api, extend({}, options), rest));
|
||||
}
|
||||
return wrapperReturnValue(name, handlePromise(new Promise((resolve, reject) => {
|
||||
return wrapperReturnValue(name, handlePromise(new Promise((resolve2, reject) => {
|
||||
invokeApi(name, api, extend({}, options, {
|
||||
success: resolve,
|
||||
success: resolve2,
|
||||
fail: reject
|
||||
}), rest);
|
||||
})));
|
||||
@@ -6454,13 +6557,13 @@ function initRuntimeSocket(hosts, port, id) {
|
||||
}
|
||||
const SOCKET_TIMEOUT = 500;
|
||||
function tryConnectSocket(host2, port, id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve2, reject) => {
|
||||
const socket = index.connectSocket({
|
||||
url: `ws://${host2}:${port}/${id}`,
|
||||
multiple: true,
|
||||
// 支付宝小程序 是否开启多实例
|
||||
fail() {
|
||||
resolve(null);
|
||||
resolve2(null);
|
||||
}
|
||||
});
|
||||
const timer = setTimeout(() => {
|
||||
@@ -6468,19 +6571,19 @@ function tryConnectSocket(host2, port, id) {
|
||||
code: 1006,
|
||||
reason: "connect timeout"
|
||||
});
|
||||
resolve(null);
|
||||
resolve2(null);
|
||||
}, SOCKET_TIMEOUT);
|
||||
socket.onOpen((e2) => {
|
||||
clearTimeout(timer);
|
||||
resolve(socket);
|
||||
resolve2(socket);
|
||||
});
|
||||
socket.onClose((e2) => {
|
||||
clearTimeout(timer);
|
||||
resolve(null);
|
||||
resolve2(null);
|
||||
});
|
||||
socket.onError((e2) => {
|
||||
clearTimeout(timer);
|
||||
resolve(null);
|
||||
resolve2(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -7898,5 +8001,8 @@ exports.f = f;
|
||||
exports.index = index;
|
||||
exports.m = m;
|
||||
exports.o = o;
|
||||
exports.p = p;
|
||||
exports.resolveComponent = resolveComponent;
|
||||
exports.s = s;
|
||||
exports.t = t;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/vendor.js.map
|
||||
|
||||
144
frontend/unpackage/dist/dev/mp-weixin/components/ImageUploader.js
vendored
Normal file
144
frontend/unpackage/dist/dev/mp-weixin/components/ImageUploader.js
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../common/vendor.js");
|
||||
const common_http = require("../common/http.js");
|
||||
const ITEM_SIZE = 210;
|
||||
const GAP = 18;
|
||||
const COLS = 3;
|
||||
function px(rpx) {
|
||||
return rpx;
|
||||
}
|
||||
const _sfc_main = {
|
||||
name: "ImageUploader",
|
||||
props: {
|
||||
modelValue: { type: Array, default: () => [] },
|
||||
max: { type: Number, default: 9 },
|
||||
uploadPath: { type: String, default: "/api/attachments" },
|
||||
uploadFieldName: { type: String, default: "file" },
|
||||
formData: { type: Object, default: () => ({ ownerType: "product" }) }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
innerList: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
areaHeight() {
|
||||
const rows = Math.ceil((this.innerList.length + 1) / COLS) || 1;
|
||||
return rows * ITEM_SIZE + (rows - 1) * GAP;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
handler(list) {
|
||||
const mapped = (list || []).map((u, i) => ({
|
||||
uid: String(i) + "_" + (u.id || u.url || Math.random().toString(36).slice(2)),
|
||||
url: typeof u === "string" ? u : u.url || "",
|
||||
x: this.posOf(i).x,
|
||||
y: this.posOf(i).y
|
||||
}));
|
||||
this.innerList = mapped;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
posOf(index) {
|
||||
const row = Math.floor(index / COLS);
|
||||
const col = index % COLS;
|
||||
return { x: px(col * (ITEM_SIZE + GAP)), y: px(row * (ITEM_SIZE + GAP)) };
|
||||
},
|
||||
cellStyle(index) {
|
||||
return {
|
||||
width: ITEM_SIZE + "rpx",
|
||||
height: ITEM_SIZE + "rpx"
|
||||
};
|
||||
},
|
||||
preview(index) {
|
||||
common_vendor.index.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;
|
||||
common_vendor.index.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 common_http.upload(this.uploadPath, filePath, this.formData, this.uploadFieldName);
|
||||
const url = (resp == null ? void 0 : resp.url) || ((_a = resp == null ? void 0 : resp.data) == null ? void 0 : _a.url) || (resp == null ? void 0 : resp.path) || "";
|
||||
if (!url)
|
||||
throw new Error("上传响应无 url");
|
||||
this.innerList.push({ uid: Math.random().toString(36).slice(2), url, ...this.posOf(this.innerList.length) });
|
||||
this.reflow();
|
||||
this.emit();
|
||||
} catch (e) {
|
||||
common_vendor.index.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(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return common_vendor.e({
|
||||
a: common_vendor.f($data.innerList, (img, index, i0) => {
|
||||
return {
|
||||
a: img.url,
|
||||
b: common_vendor.o(($event) => $options.preview(index), img.uid),
|
||||
c: common_vendor.o(($event) => $options.remove(index), img.uid),
|
||||
d: img.uid,
|
||||
e: common_vendor.s($options.cellStyle(index)),
|
||||
f: img.x,
|
||||
g: img.y,
|
||||
h: common_vendor.o(($event) => $options.onMoving(index, $event), img.uid),
|
||||
i: common_vendor.o(($event) => $options.onMoveEnd(index), img.uid)
|
||||
};
|
||||
}),
|
||||
b: $data.innerList.length < $props.max
|
||||
}, $data.innerList.length < $props.max ? {
|
||||
c: common_vendor.o((...args) => $options.choose && $options.choose(...args))
|
||||
} : {}, {
|
||||
d: $options.areaHeight + "rpx",
|
||||
e: $options.areaHeight + "rpx"
|
||||
});
|
||||
}
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||
wx.createComponent(Component);
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/components/ImageUploader.js.map
|
||||
4
frontend/unpackage/dist/dev/mp-weixin/components/ImageUploader.json
vendored
Normal file
4
frontend/unpackage/dist/dev/mp-weixin/components/ImageUploader.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
1
frontend/unpackage/dist/dev/mp-weixin/components/ImageUploader.wxml
vendored
Normal file
1
frontend/unpackage/dist/dev/mp-weixin/components/ImageUploader.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view class="uploader"><view class="grid" style="{{'height:' + e}}"><movable-area class="area" style="{{'height:' + d}}"><movable-view wx:for="{{a}}" wx:for-item="img" wx:key="d" class="cell" style="{{img.e}}" direction="{{'all'}}" damping="{{40}}" friction="{{2}}" x="{{img.f}}" y="{{img.g}}" bindchange="{{img.h}}" bindtouchend="{{img.i}}"><image src="{{img.a}}" mode="aspectFill" class="thumb" bindtap="{{img.b}}"/><view class="remove" catchtap="{{img.c}}">×</view></movable-view><view wx:if="{{b}}" class="adder" bindtap="{{c}}"><text>+</text></view></movable-area></view></view>
|
||||
15
frontend/unpackage/dist/dev/mp-weixin/components/ImageUploader.wxss
vendored
Normal file
15
frontend/unpackage/dist/dev/mp-weixin/components/ImageUploader.wxss
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
.uploader { padding: 12rpx; background: #fff;
|
||||
}
|
||||
.grid { position: relative;
|
||||
}
|
||||
.area { width: 100%; position: relative;
|
||||
}
|
||||
.cell { position: absolute; border-radius: 12rpx; overflow: hidden; box-shadow: 0 0 1rpx rgba(0,0,0,0.08);
|
||||
}
|
||||
.thumb { width: 100%; height: 100%;
|
||||
}
|
||||
.remove { position: absolute; right: 6rpx; top: 6rpx; background: rgba(0,0,0,0.45); color: #fff; width: 40rpx; height: 40rpx; text-align: center; line-height: 40rpx; border-radius: 20rpx; font-size: 28rpx;
|
||||
}
|
||||
.adder { width: 210rpx; height: 210rpx; border: 2rpx dashed #ccc; border-radius: 12rpx; display: flex; align-items: center; justify-content: center; color: #999; position: absolute; left: 0; top: 0;
|
||||
}
|
||||
@@ -11,6 +11,7 @@ const _sfc_main = {
|
||||
loadingNotices: false,
|
||||
noticeError: "",
|
||||
features: [
|
||||
{ key: "product", title: "货品", img: "/static/icons/product.png", emoji: "📦" },
|
||||
{ key: "customer", title: "客户", img: "/static/icons/customer.png", emoji: "👥" },
|
||||
{ key: "sale", title: "销售", img: "/static/icons/sale.png", emoji: "💰" },
|
||||
{ key: "account", title: "账户", img: "/static/icons/account.png", emoji: "💳" },
|
||||
@@ -30,12 +31,14 @@ const _sfc_main = {
|
||||
methods: {
|
||||
async fetchMetrics() {
|
||||
try {
|
||||
const d = await common_http.get("/api/metrics/overview");
|
||||
const d = await common_http.get("/api/dashboard/overview");
|
||||
const toNum = (v) => typeof v === "number" ? v : Number(v || 0);
|
||||
this.kpi = {
|
||||
todaySales: d && d.todaySales || "0.00",
|
||||
monthSales: d && d.monthSales || "0.00",
|
||||
monthProfit: d && d.monthProfit || "0.00",
|
||||
stockCount: d && d.stockCount || "0"
|
||||
...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) {
|
||||
}
|
||||
@@ -56,8 +59,16 @@ const _sfc_main = {
|
||||
}
|
||||
},
|
||||
onFeatureTap(item) {
|
||||
if (item.key === "product") {
|
||||
common_vendor.index.navigateTo({ url: "/pages/product/list" });
|
||||
return;
|
||||
}
|
||||
common_vendor.index.showToast({ title: item.title + "(开发中)", icon: "none" });
|
||||
},
|
||||
goProduct() {
|
||||
this.activeTab = "product";
|
||||
common_vendor.index.navigateTo({ url: "/pages/product/list" });
|
||||
},
|
||||
onCreateOrder() {
|
||||
common_vendor.index.navigateTo({ url: "/pages/order/create" });
|
||||
},
|
||||
@@ -116,7 +127,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
l: $data.activeTab === "home" ? 1 : "",
|
||||
m: common_vendor.o(($event) => $data.activeTab = "home"),
|
||||
n: $data.activeTab === "product" ? 1 : "",
|
||||
o: common_vendor.o(($event) => $data.activeTab = "product"),
|
||||
o: common_vendor.o((...args) => $options.goProduct && $options.goProduct(...args)),
|
||||
p: common_vendor.o((...args) => $options.onCreateOrder && $options.onCreateOrder(...args)),
|
||||
q: $data.activeTab === "detail" ? 1 : "",
|
||||
r: common_vendor.o(($event) => $data.activeTab = "detail"),
|
||||
|
||||
62
frontend/unpackage/dist/dev/mp-weixin/pages/product/categories.js
vendored
Normal file
62
frontend/unpackage/dist/dev/mp-weixin/pages/product/categories.js
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const common_http = require("../../common/http.js");
|
||||
const _sfc_main = {
|
||||
data() {
|
||||
return { name: "", list: [] };
|
||||
},
|
||||
onLoad() {
|
||||
this.reload();
|
||||
},
|
||||
methods: {
|
||||
async reload() {
|
||||
try {
|
||||
const res = await common_http.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 common_http.post("/api/product-categories", { name: this.name });
|
||||
this.name = "";
|
||||
this.reload();
|
||||
},
|
||||
async update(c) {
|
||||
await common_http.put("/api/product-categories/" + c.id, { name: c.name });
|
||||
common_vendor.index.showToast({ title: "已保存", icon: "success" });
|
||||
},
|
||||
async remove(c) {
|
||||
common_vendor.index.showModal({ content: "确定删除该类别?", success: async (r) => {
|
||||
if (!r.confirm)
|
||||
return;
|
||||
await common_http.del("/api/product-categories/" + c.id);
|
||||
this.reload();
|
||||
} });
|
||||
}
|
||||
}
|
||||
};
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return {
|
||||
a: $data.name,
|
||||
b: common_vendor.o(common_vendor.m(($event) => $data.name = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
c: common_vendor.o((...args) => $options.create && $options.create(...args)),
|
||||
d: common_vendor.f($data.list, (c, k0, i0) => {
|
||||
return {
|
||||
a: c.name,
|
||||
b: common_vendor.o(common_vendor.m(($event) => c.name = $event.detail.value, {
|
||||
trim: true
|
||||
}), c.id),
|
||||
c: common_vendor.o(($event) => $options.update(c), c.id),
|
||||
d: common_vendor.o(($event) => $options.remove(c), c.id),
|
||||
e: c.id
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/categories.js.map
|
||||
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/categories.json
vendored
Normal file
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/categories.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "类别管理",
|
||||
"usingComponents": {}
|
||||
}
|
||||
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/categories.wxml
vendored
Normal file
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/categories.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view class="page"><view class="toolbar"><input placeholder="新类别名称" value="{{a}}" bindinput="{{b}}"/><button size="mini" bindtap="{{c}}">新增</button></view><scroll-view scroll-y class="list"><view wx:for="{{d}}" wx:for-item="c" wx:key="e" class="item"><input value="{{c.a}}" bindinput="{{c.b}}"/><view class="ops"><button size="mini" bindtap="{{c.c}}">保存</button><button size="mini" type="warn" bindtap="{{c.d}}">删除</button></view></view></scroll-view></view>
|
||||
15
frontend/unpackage/dist/dev/mp-weixin/pages/product/categories.wxss
vendored
Normal file
15
frontend/unpackage/dist/dev/mp-weixin/pages/product/categories.wxss
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
.page { display:flex; flex-direction: column; height: 100vh;
|
||||
}
|
||||
.toolbar { display:flex; gap: 12rpx; padding: 16rpx; background:#fff;
|
||||
}
|
||||
.toolbar input { flex:1; background:#f6f6f6; border-radius: 12rpx; padding: 12rpx;
|
||||
}
|
||||
.list { flex:1;
|
||||
}
|
||||
.item { display:flex; gap: 12rpx; align-items:center; padding: 16rpx; background:#fff; border-bottom: 1rpx solid #f1f1f1;
|
||||
}
|
||||
.item input { flex:1; background:#f7f7f7; border-radius: 10rpx; padding: 12rpx;
|
||||
}
|
||||
.ops { display:flex; gap: 10rpx;
|
||||
}
|
||||
251
frontend/unpackage/dist/dev/mp-weixin/pages/product/edit.js
vendored
Normal file
251
frontend/unpackage/dist/dev/mp-weixin/pages/product/edit.js
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const common_http = require("../../common/http.js");
|
||||
function parseSafeStock(text) {
|
||||
const m = String(text || "").match(/\s*(\d+(?:\.\d+)?)\s*(?:-|~|—|到|,)?\s*(\d+(?:\.\d+)?)?\s*/);
|
||||
if (!m)
|
||||
return { min: null, max: null };
|
||||
return { min: m[1] ? Number(m[1]) : null, max: m[2] ? Number(m[2]) : null };
|
||||
}
|
||||
const _sfc_main = {
|
||||
data() {
|
||||
return {
|
||||
id: null,
|
||||
units: [],
|
||||
categories: [],
|
||||
form: {
|
||||
name: "",
|
||||
categoryId: null,
|
||||
unitId: null,
|
||||
barcode: "",
|
||||
brand: "",
|
||||
model: "",
|
||||
spec: "",
|
||||
purchasePrice: 0,
|
||||
wholesalePrice: 0,
|
||||
bigClientPrice: 0,
|
||||
retailPrice: 0,
|
||||
stock: 0,
|
||||
safeMin: null,
|
||||
safeMax: null,
|
||||
images: []
|
||||
}
|
||||
};
|
||||
},
|
||||
onLoad(query) {
|
||||
this.id = query && query.id ? Number(query.id) : null;
|
||||
this.bootstrap();
|
||||
},
|
||||
computed: {
|
||||
categoryLabel() {
|
||||
const c = this.categories.find((x) => x.id === this.form.categoryId);
|
||||
return c ? c.name : "未选择";
|
||||
},
|
||||
unitLabel() {
|
||||
const u = this.units.find((x) => x.id === this.form.unitId);
|
||||
return u ? u.name : "未选择";
|
||||
},
|
||||
safeStockText: {
|
||||
get() {
|
||||
const a = this.form.safeMin != null ? String(this.form.safeMin) : "";
|
||||
const b = this.form.safeMax != null ? String(this.form.safeMax) : "";
|
||||
if (!a && !b)
|
||||
return "";
|
||||
if (a && b)
|
||||
return a + "-" + b;
|
||||
return a || b;
|
||||
},
|
||||
set(v) {
|
||||
const { min, max } = parseSafeStock(v);
|
||||
this.form.safeMin = min;
|
||||
this.form.safeMax = max;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async bootstrap() {
|
||||
try {
|
||||
const [units, cats] = await Promise.all([
|
||||
common_http.get("/api/product/units"),
|
||||
common_http.get("/api/product/categories")
|
||||
]);
|
||||
this.units = Array.isArray(units == null ? void 0 : units.list) ? units.list : Array.isArray(units) ? units : [];
|
||||
this.categories = Array.isArray(cats == null ? void 0 : cats.list) ? cats.list : Array.isArray(cats) ? cats : [];
|
||||
} catch (_) {
|
||||
}
|
||||
if (this.id) {
|
||||
try {
|
||||
const d = await common_http.get("/api/product/detail", { id: this.id });
|
||||
Object.assign(this.form, {
|
||||
name: d.name || "",
|
||||
categoryId: d.categoryId || null,
|
||||
unitId: d.unitId || null,
|
||||
barcode: d.barcode || "",
|
||||
brand: d.brand || "",
|
||||
model: d.model || "",
|
||||
spec: d.spec || "",
|
||||
purchasePrice: Number(d.purchasePrice || 0),
|
||||
wholesalePrice: Number(d.wholesalePrice || 0),
|
||||
bigClientPrice: Number(d.bigClientPrice || 0),
|
||||
retailPrice: Number(d.retailPrice || 0),
|
||||
stock: Number(d.stock || 0),
|
||||
safeMin: d.safeMin ?? null,
|
||||
safeMax: d.safeMax ?? null,
|
||||
images: Array.isArray(d.images) ? d.images : []
|
||||
});
|
||||
} catch (_) {
|
||||
}
|
||||
}
|
||||
},
|
||||
chooseCategory() {
|
||||
if (!this.categories.length)
|
||||
return;
|
||||
common_vendor.index.showActionSheet({ itemList: this.categories.map((c) => c.name), success: ({ tapIndex }) => {
|
||||
this.form.categoryId = this.categories[tapIndex].id;
|
||||
} });
|
||||
},
|
||||
chooseUnit() {
|
||||
if (!this.units.length)
|
||||
return;
|
||||
common_vendor.index.showActionSheet({ itemList: this.units.map((u) => u.name), success: ({ tapIndex }) => {
|
||||
this.form.unitId = this.units[tapIndex].id;
|
||||
} });
|
||||
},
|
||||
scanBarcode() {
|
||||
common_vendor.index.scanCode({ onlyFromCamera: false, success: (res) => {
|
||||
this.form.barcode = res.result;
|
||||
}, fail: () => {
|
||||
common_vendor.index.showToast({ title: "扫码失败,请手动录入", icon: "none" });
|
||||
} });
|
||||
},
|
||||
async chooseImages() {
|
||||
common_vendor.index.chooseImage({ count: 6, sizeType: ["compressed"], success: async (res) => {
|
||||
try {
|
||||
const uploaded = [];
|
||||
for (const path of res.tempFilePaths) {
|
||||
const ret = await common_http.upload("/api/upload", path, { biz: "product" });
|
||||
uploaded.push(ret.url || ret.path || path);
|
||||
}
|
||||
this.form.images = (this.form.images || []).concat(uploaded).slice(0, 9);
|
||||
} catch (e) {
|
||||
common_vendor.index.showToast({ title: "上传失败", icon: "none" });
|
||||
}
|
||||
} });
|
||||
},
|
||||
moveLeft(i) {
|
||||
if (i <= 0)
|
||||
return;
|
||||
const a = this.form.images;
|
||||
[a[i - 1], a[i]] = [a[i], a[i - 1]];
|
||||
},
|
||||
moveRight(i) {
|
||||
const a = this.form.images;
|
||||
if (i >= a.length - 1)
|
||||
return;
|
||||
[a[i + 1], a[i]] = [a[i], a[i + 1]];
|
||||
},
|
||||
removeImg(i) {
|
||||
this.form.images.splice(i, 1);
|
||||
},
|
||||
async submit() {
|
||||
if (!this.form.name) {
|
||||
common_vendor.index.showToast({ title: "请填写名称", icon: "none" });
|
||||
return;
|
||||
}
|
||||
const payload = {
|
||||
name: this.form.name,
|
||||
categoryId: this.form.categoryId,
|
||||
unitId: this.form.unitId,
|
||||
barcode: this.form.barcode,
|
||||
brand: this.form.brand,
|
||||
model: this.form.model,
|
||||
spec: this.form.spec,
|
||||
purchasePrice: Number(this.form.purchasePrice || 0),
|
||||
wholesalePrice: Number(this.form.wholesalePrice || 0),
|
||||
bigClientPrice: Number(this.form.bigClientPrice || 0),
|
||||
retailPrice: Number(this.form.retailPrice || 0),
|
||||
stock: Number(this.form.stock || 0),
|
||||
safeMin: this.form.safeMin,
|
||||
safeMax: this.form.safeMax,
|
||||
images: this.form.images
|
||||
};
|
||||
try {
|
||||
if (this.id)
|
||||
await common_http.put("/api/product", { id: this.id, ...payload });
|
||||
else
|
||||
await common_http.post("/api/product", payload);
|
||||
common_vendor.index.showToast({ title: "已保存", icon: "success" });
|
||||
setTimeout(() => {
|
||||
common_vendor.index.navigateBack();
|
||||
}, 600);
|
||||
} catch (e) {
|
||||
common_vendor.index.showToast({ title: e && e.message || "保存失败", icon: "none" });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return {
|
||||
a: $data.form.name,
|
||||
b: common_vendor.o(common_vendor.m(($event) => $data.form.name = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
c: common_vendor.t($options.categoryLabel),
|
||||
d: common_vendor.o((...args) => $options.chooseCategory && $options.chooseCategory(...args)),
|
||||
e: common_vendor.t($options.unitLabel),
|
||||
f: common_vendor.o((...args) => $options.chooseUnit && $options.chooseUnit(...args)),
|
||||
g: $data.form.barcode,
|
||||
h: common_vendor.o(common_vendor.m(($event) => $data.form.barcode = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
i: common_vendor.o((...args) => $options.scanBarcode && $options.scanBarcode(...args)),
|
||||
j: $data.form.brand,
|
||||
k: common_vendor.o(common_vendor.m(($event) => $data.form.brand = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
l: $data.form.model,
|
||||
m: common_vendor.o(common_vendor.m(($event) => $data.form.model = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
n: $data.form.spec,
|
||||
o: common_vendor.o(common_vendor.m(($event) => $data.form.spec = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
p: $data.form.purchasePrice,
|
||||
q: common_vendor.o(common_vendor.m(($event) => $data.form.purchasePrice = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
r: $data.form.wholesalePrice,
|
||||
s: common_vendor.o(common_vendor.m(($event) => $data.form.wholesalePrice = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
t: $data.form.bigClientPrice,
|
||||
v: common_vendor.o(common_vendor.m(($event) => $data.form.bigClientPrice = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
w: $data.form.retailPrice,
|
||||
x: common_vendor.o(common_vendor.m(($event) => $data.form.retailPrice = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
y: $data.form.stock,
|
||||
z: common_vendor.o(common_vendor.m(($event) => $data.form.stock = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
A: $options.safeStockText,
|
||||
B: common_vendor.o(($event) => $options.safeStockText = $event.detail.value),
|
||||
C: common_vendor.o((...args) => $options.chooseImages && $options.chooseImages(...args)),
|
||||
D: common_vendor.f($data.form.images, (url, idx, i0) => {
|
||||
return {
|
||||
a: url,
|
||||
b: common_vendor.o(($event) => $options.moveLeft(idx), idx),
|
||||
c: common_vendor.o(($event) => $options.moveRight(idx), idx),
|
||||
d: common_vendor.o(($event) => $options.removeImg(idx), idx),
|
||||
e: idx
|
||||
};
|
||||
}),
|
||||
E: common_vendor.o((...args) => $options.submit && $options.submit(...args))
|
||||
};
|
||||
}
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/edit.js.map
|
||||
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/edit.json
vendored
Normal file
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/edit.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "编辑货品",
|
||||
"usingComponents": {}
|
||||
}
|
||||
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/edit.wxml
vendored
Normal file
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/edit.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view class="page"><view class="form"><view class="field"><text class="label">名称</text><input class="value" placeholder="必填" value="{{a}}" bindinput="{{b}}"/></view><view class="field" bindtap="{{d}}"><text class="label">类别</text><text class="value">{{c}}</text></view><view class="field" bindtap="{{f}}"><text class="label">主单位</text><text class="value">{{e}}</text></view><view class="field"><text class="label">条形码</text><input class="value" placeholder="手动录入或扫码" value="{{g}}" bindinput="{{h}}"/><button size="mini" class="scan" bindtap="{{i}}">扫码</button></view><view class="field"><text class="label">品牌</text><input class="value" placeholder="可选" value="{{j}}" bindinput="{{k}}"/></view><view class="field"><text class="label">型号</text><input class="value" placeholder="可选" value="{{l}}" bindinput="{{m}}"/></view><view class="field"><text class="label">规格</text><input class="value" placeholder="可选" value="{{n}}" bindinput="{{o}}"/></view><view class="grid2"><view class="field"><text class="label">进货价</text><input class="value" type="digit" value="{{p}}" bindinput="{{q}}"/></view><view class="field"><text class="label">批发价</text><input class="value" type="digit" value="{{r}}" bindinput="{{s}}"/></view><view class="field"><text class="label">大单报价</text><input class="value" type="digit" value="{{t}}" bindinput="{{v}}"/></view><view class="field"><text class="label">零售价</text><input class="value" type="digit" value="{{w}}" bindinput="{{x}}"/></view></view><view class="grid2"><view class="field"><text class="label">当前库存</text><input class="value" type="digit" value="{{y}}" bindinput="{{z}}"/></view><view class="field"><text class="label">安全库存</text><input class="value" type="text" placeholder="如 10-100" value="{{A}}" bindinput="{{B}}"/></view></view><view class="photos"><view class="photos-header"><text>商品图片</text><button size="mini" bindtap="{{C}}">选择图片</button></view><view class="photo-list"><view wx:for="{{D}}" wx:for-item="url" wx:key="e" class="photo"><image src="{{url.a}}" mode="aspectFill"/><view class="photo-actions"><text class="btn" bindtap="{{url.b}}">←</text><text class="btn" bindtap="{{url.c}}">→</text><text class="btn danger" bindtap="{{url.d}}">删</text></view></view></view></view></view><view class="bottom"><button class="primary" bindtap="{{E}}">保存</button></view></view>
|
||||
35
frontend/unpackage/dist/dev/mp-weixin/pages/product/edit.wxss
vendored
Normal file
35
frontend/unpackage/dist/dev/mp-weixin/pages/product/edit.wxss
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
.page{ padding-bottom: 140rpx;
|
||||
}
|
||||
.form{ background:#fff;
|
||||
}
|
||||
.field{ display:flex; align-items:center; gap: 12rpx; padding: 22rpx 20rpx; border-bottom: 1rpx solid #f2f2f2;
|
||||
}
|
||||
.label{ color:#666; width: 160rpx;
|
||||
}
|
||||
.value{ flex:1; color:#333;
|
||||
}
|
||||
.scan{ flex: 0 0 auto;
|
||||
}
|
||||
.grid2{ display:grid; grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.photos{ padding: 16rpx 20rpx;
|
||||
}
|
||||
.photos-header{ display:flex; justify-content: space-between; align-items:center; margin-bottom: 12rpx;
|
||||
}
|
||||
.photo-list{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 12rpx;
|
||||
}
|
||||
.photo{ position: relative;
|
||||
}
|
||||
.photo image{ width: 100%; height: 200rpx; border-radius: 12rpx; background:#f6f6f6; display:block;
|
||||
}
|
||||
.photo-actions{ position:absolute; right:6rpx; bottom:6rpx; display:flex; gap: 6rpx;
|
||||
}
|
||||
.btn{ font-size: 22rpx; padding: 4rpx 8rpx; background: rgba(0,0,0,0.45); color:#fff; border-radius: 8rpx;
|
||||
}
|
||||
.btn.danger{ background: rgba(221,82,77,0.85);
|
||||
}
|
||||
.bottom{ position: fixed; left:0; right:0; bottom:0; background:#fff; padding: 16rpx 24rpx calc(env(safe-area-inset-bottom) + 16rpx); box-shadow: 0 -4rpx 12rpx rgba(0,0,0,0.06);
|
||||
}
|
||||
.primary{ width: 100%; background: linear-gradient(135deg, #FFE69A 0%, #F4CF62 45%, #D7A72E 100%); color:#493c1b; border-radius: 999rpx; padding: 20rpx 0; font-weight:800;
|
||||
}
|
||||
249
frontend/unpackage/dist/dev/mp-weixin/pages/product/form.js
vendored
Normal file
249
frontend/unpackage/dist/dev/mp-weixin/pages/product/form.js
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const common_http = require("../../common/http.js");
|
||||
const ImageUploader = () => "../../components/ImageUploader.js";
|
||||
const _sfc_main = {
|
||||
components: { ImageUploader },
|
||||
data() {
|
||||
return {
|
||||
id: "",
|
||||
form: {
|
||||
name: "",
|
||||
barcode: "",
|
||||
brand: "",
|
||||
model: "",
|
||||
spec: "",
|
||||
origin: "",
|
||||
categoryId: "",
|
||||
unitId: "",
|
||||
stock: null,
|
||||
safeMin: null,
|
||||
safeMax: null,
|
||||
purchasePrice: null,
|
||||
retailPrice: null,
|
||||
wholesalePrice: null,
|
||||
bigClientPrice: null,
|
||||
images: [],
|
||||
remark: ""
|
||||
},
|
||||
units: [],
|
||||
categories: []
|
||||
};
|
||||
},
|
||||
onLoad(query) {
|
||||
this.id = (query == null ? void 0 : query.id) || "";
|
||||
this.bootstrap();
|
||||
},
|
||||
computed: {
|
||||
unitNames() {
|
||||
return this.units.map((u) => u.name);
|
||||
},
|
||||
categoryNames() {
|
||||
return this.categories.map((c) => c.name);
|
||||
},
|
||||
unitLabel() {
|
||||
const u = this.units.find((x) => String(x.id) === String(this.form.unitId));
|
||||
return u ? u.name : "选择单位";
|
||||
},
|
||||
categoryLabel() {
|
||||
const c = this.categories.find((x) => String(x.id) === String(this.form.categoryId));
|
||||
return c ? c.name : "选择类别";
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async bootstrap() {
|
||||
await Promise.all([this.fetchUnits(), this.fetchCategories()]);
|
||||
if (this.id)
|
||||
this.loadDetail();
|
||||
},
|
||||
async fetchUnits() {
|
||||
try {
|
||||
const res = await common_http.get("/api/product-units");
|
||||
this.units = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
|
||||
} catch (_) {
|
||||
}
|
||||
},
|
||||
async fetchCategories() {
|
||||
try {
|
||||
const res = await common_http.get("/api/product-categories");
|
||||
this.categories = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
|
||||
} catch (_) {
|
||||
}
|
||||
},
|
||||
onPickUnit(e) {
|
||||
const idx = Number(e.detail.value);
|
||||
const u = this.units[idx];
|
||||
this.form.unitId = u ? u.id : "";
|
||||
},
|
||||
onPickCategory(e) {
|
||||
const idx = Number(e.detail.value);
|
||||
const c = this.categories[idx];
|
||||
this.form.categoryId = c ? c.id : "";
|
||||
},
|
||||
scan() {
|
||||
common_vendor.index.scanCode({ onlyFromCamera: false, success: (res) => {
|
||||
this.form.barcode = res.result;
|
||||
} });
|
||||
},
|
||||
async loadDetail() {
|
||||
try {
|
||||
const data = await common_http.get("/api/products/" + this.id);
|
||||
Object.assign(this.form, {
|
||||
name: data.name,
|
||||
barcode: data.barcode,
|
||||
brand: data.brand,
|
||||
model: data.model,
|
||||
spec: data.spec,
|
||||
origin: data.origin,
|
||||
categoryId: data.categoryId,
|
||||
unitId: data.unitId,
|
||||
stock: data.stock,
|
||||
safeMin: data.safeMin,
|
||||
safeMax: data.safeMax,
|
||||
purchasePrice: data.purchasePrice,
|
||||
retailPrice: data.retailPrice,
|
||||
wholesalePrice: data.wholesalePrice,
|
||||
bigClientPrice: data.bigClientPrice,
|
||||
images: (data.images || []).map((i) => i.url || i)
|
||||
});
|
||||
} catch (_) {
|
||||
}
|
||||
},
|
||||
validate() {
|
||||
if (!this.form.name) {
|
||||
common_vendor.index.showToast({ title: "请填写名称", icon: "none" });
|
||||
return false;
|
||||
}
|
||||
if (this.form.safeMin != null && this.form.safeMax != null && Number(this.form.safeMin) > Number(this.form.safeMax)) {
|
||||
common_vendor.index.showToast({ title: "安全库存区间不合法", icon: "none" });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
buildPayload() {
|
||||
const f = this.form;
|
||||
return {
|
||||
name: f.name,
|
||||
barcode: f.barcode,
|
||||
brand: f.brand,
|
||||
model: f.model,
|
||||
spec: f.spec,
|
||||
origin: f.origin,
|
||||
categoryId: f.categoryId || null,
|
||||
unitId: f.unitId,
|
||||
safeMin: f.safeMin,
|
||||
safeMax: f.safeMax,
|
||||
prices: {
|
||||
purchasePrice: f.purchasePrice,
|
||||
retailPrice: f.retailPrice,
|
||||
wholesalePrice: f.wholesalePrice,
|
||||
bigClientPrice: f.bigClientPrice
|
||||
},
|
||||
stock: f.stock,
|
||||
images: f.images,
|
||||
remark: f.remark
|
||||
};
|
||||
},
|
||||
async save(goOn) {
|
||||
if (!this.validate())
|
||||
return;
|
||||
const payload = this.buildPayload();
|
||||
try {
|
||||
if (this.id)
|
||||
await common_http.put("/api/products/" + this.id, payload);
|
||||
else
|
||||
await common_http.post("/api/products", payload);
|
||||
common_vendor.index.showToast({ title: "保存成功", icon: "success" });
|
||||
if (goOn && !this.id) {
|
||||
this.form = { name: "", barcode: "", brand: "", model: "", spec: "", origin: "", categoryId: "", unitId: "", stock: null, safeMin: null, safeMax: null, purchasePrice: null, retailPrice: null, wholesalePrice: null, bigClientPrice: null, images: [], remark: "" };
|
||||
} else {
|
||||
setTimeout(() => common_vendor.index.navigateBack(), 400);
|
||||
}
|
||||
} catch (e) {
|
||||
common_vendor.index.showToast({ title: "保存失败", icon: "none" });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!Array) {
|
||||
const _component_ImageUploader = common_vendor.resolveComponent("ImageUploader");
|
||||
_component_ImageUploader();
|
||||
}
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return {
|
||||
a: $data.form.name,
|
||||
b: common_vendor.o(common_vendor.m(($event) => $data.form.name = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
c: $data.form.barcode,
|
||||
d: common_vendor.o(common_vendor.m(($event) => $data.form.barcode = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
e: $data.form.brand,
|
||||
f: common_vendor.o(common_vendor.m(($event) => $data.form.brand = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
g: $data.form.model,
|
||||
h: common_vendor.o(common_vendor.m(($event) => $data.form.model = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
i: $data.form.spec,
|
||||
j: common_vendor.o(common_vendor.m(($event) => $data.form.spec = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
k: $data.form.origin,
|
||||
l: common_vendor.o(common_vendor.m(($event) => $data.form.origin = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
m: common_vendor.t($options.unitLabel),
|
||||
n: $options.unitNames,
|
||||
o: common_vendor.o((...args) => $options.onPickUnit && $options.onPickUnit(...args)),
|
||||
p: common_vendor.t($options.categoryLabel),
|
||||
q: $options.categoryNames,
|
||||
r: common_vendor.o((...args) => $options.onPickCategory && $options.onPickCategory(...args)),
|
||||
s: $data.form.stock,
|
||||
t: common_vendor.o(common_vendor.m(($event) => $data.form.stock = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
v: $data.form.safeMin,
|
||||
w: common_vendor.o(common_vendor.m(($event) => $data.form.safeMin = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
x: $data.form.safeMax,
|
||||
y: common_vendor.o(common_vendor.m(($event) => $data.form.safeMax = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
z: $data.form.purchasePrice,
|
||||
A: common_vendor.o(common_vendor.m(($event) => $data.form.purchasePrice = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
B: $data.form.retailPrice,
|
||||
C: common_vendor.o(common_vendor.m(($event) => $data.form.retailPrice = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
D: $data.form.wholesalePrice,
|
||||
E: common_vendor.o(common_vendor.m(($event) => $data.form.wholesalePrice = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
F: $data.form.bigClientPrice,
|
||||
G: common_vendor.o(common_vendor.m(($event) => $data.form.bigClientPrice = $event.detail.value, {
|
||||
number: true
|
||||
})),
|
||||
H: common_vendor.o(($event) => $data.form.images = $event),
|
||||
I: common_vendor.p({
|
||||
formData: {
|
||||
ownerType: "product"
|
||||
},
|
||||
modelValue: $data.form.images
|
||||
}),
|
||||
J: $data.form.remark,
|
||||
K: common_vendor.o(common_vendor.m(($event) => $data.form.remark = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
L: common_vendor.o(($event) => $options.save(false)),
|
||||
M: common_vendor.o(($event) => $options.save(true))
|
||||
};
|
||||
}
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/form.js.map
|
||||
6
frontend/unpackage/dist/dev/mp-weixin/pages/product/form.json
vendored
Normal file
6
frontend/unpackage/dist/dev/mp-weixin/pages/product/form.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"navigationBarTitleText": "编辑货品",
|
||||
"usingComponents": {
|
||||
"image-uploader": "../../components/ImageUploader"
|
||||
}
|
||||
}
|
||||
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/form.wxml
vendored
Normal file
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/form.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<scroll-view scroll-y class="page"><view class="card"><view class="row"><text class="label">商品名称</text><input placeholder="必填" value="{{a}}" bindinput="{{b}}"/></view><view class="row"><text class="label">条形码</text><input placeholder="可扫码或输入" value="{{c}}" bindinput="{{d}}"/></view><view class="row"><text class="label">品牌/型号/规格/产地</text></view><view class="row"><input placeholder="品牌" value="{{e}}" bindinput="{{f}}"/></view><view class="row"><input placeholder="型号" value="{{g}}" bindinput="{{h}}"/></view><view class="row"><input placeholder="规格" value="{{i}}" bindinput="{{j}}"/></view><view class="row"><input placeholder="产地" value="{{k}}" bindinput="{{l}}"/></view><view class="row"><picker mode="selector" range="{{n}}" bindchange="{{o}}"><view class="picker">主单位:{{m}}</view></picker><picker mode="selector" range="{{q}}" bindchange="{{r}}"><view class="picker">类别:{{p}}</view></picker></view></view><view class="card"><view class="row"><text class="label">库存与安全库存</text></view><view class="row"><input type="number" placeholder="当前库存" value="{{s}}" bindinput="{{t}}"/><input type="number" placeholder="安全库存下限" value="{{v}}" bindinput="{{w}}"/><input type="number" placeholder="安全库存上限" value="{{x}}" bindinput="{{y}}"/></view></view><view class="card"><view class="row"><text class="label">价格(进价/零售/批发/大单)</text></view><view class="row prices"><input type="number" placeholder="进货价" value="{{z}}" bindinput="{{A}}"/><input type="number" placeholder="零售价" value="{{B}}" bindinput="{{C}}"/><input type="number" placeholder="批发价" value="{{D}}" bindinput="{{E}}"/><input type="number" placeholder="大单价" value="{{F}}" bindinput="{{G}}"/></view></view><view class="card"><text class="label">图片</text><image-uploader wx:if="{{I}}" u-i="4a3f460a-0" bind:__l="__l" bindupdateModelValue="{{H}}" u-p="{{I}}"/></view><view class="card"><text class="label">备注</text><block wx:if="{{r0}}"><textarea placeholder="可选" auto-height value="{{J}}" bindinput="{{K}}"/></block></view><view class="fixed"><button type="default" bindtap="{{L}}">保存</button><button type="primary" bindtap="{{M}}">保存并继续</button></view></scroll-view>
|
||||
17
frontend/unpackage/dist/dev/mp-weixin/pages/product/form.wxss
vendored
Normal file
17
frontend/unpackage/dist/dev/mp-weixin/pages/product/form.wxss
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
.page { background:#f6f6f6; height: 100vh;
|
||||
}
|
||||
.card { background:#fff; margin: 16rpx; padding: 16rpx; border-radius: 12rpx;
|
||||
}
|
||||
.row { display:flex; gap: 12rpx; align-items: center; margin-bottom: 12rpx;
|
||||
}
|
||||
.label { width: 180rpx; color:#666;
|
||||
}
|
||||
.row input { flex:1; background:#f7f7f7; border-radius: 10rpx; padding: 12rpx;
|
||||
}
|
||||
.picker { padding: 8rpx 12rpx; background:#f0f0f0; border-radius: 10rpx; color:#666; margin-left: 8rpx;
|
||||
}
|
||||
.prices input { width: 30%;
|
||||
}
|
||||
.fixed { position: fixed; left: 0; right: 0; bottom: 0; background:#fff; padding: 12rpx 16rpx; display:flex; gap: 16rpx;
|
||||
}
|
||||
122
frontend/unpackage/dist/dev/mp-weixin/pages/product/list.js
vendored
Normal file
122
frontend/unpackage/dist/dev/mp-weixin/pages/product/list.js
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const common_http = require("../../common/http.js");
|
||||
const _sfc_main = {
|
||||
data() {
|
||||
return {
|
||||
items: [],
|
||||
query: { kw: "", page: 1, size: 20, categoryId: "" },
|
||||
finished: false,
|
||||
loading: false,
|
||||
tab: "all",
|
||||
categories: []
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.fetchCategories();
|
||||
this.reload();
|
||||
},
|
||||
computed: {
|
||||
categoryNames() {
|
||||
return this.categories.map((c) => c.name);
|
||||
},
|
||||
categoryLabel() {
|
||||
const c = this.categories.find((x) => String(x.id) === String(this.query.categoryId));
|
||||
return c ? "类别:" + c.name : "选择类别";
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
switchTab(t) {
|
||||
this.tab = t;
|
||||
this.query.categoryId = "";
|
||||
this.reload();
|
||||
},
|
||||
onPickCategory(e) {
|
||||
const idx = Number(e.detail.value);
|
||||
const c = this.categories[idx];
|
||||
this.query.categoryId = c ? c.id : "";
|
||||
this.reload();
|
||||
},
|
||||
async fetchCategories() {
|
||||
try {
|
||||
const res = await common_http.get("/api/product-categories", {});
|
||||
this.categories = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
|
||||
} catch (_) {
|
||||
}
|
||||
},
|
||||
reload() {
|
||||
this.items = [];
|
||||
this.query.page = 1;
|
||||
this.finished = false;
|
||||
this.loadMore();
|
||||
},
|
||||
async loadMore() {
|
||||
if (this.loading || this.finished)
|
||||
return;
|
||||
this.loading = true;
|
||||
try {
|
||||
const params = { kw: this.query.kw, page: this.query.page, size: this.query.size };
|
||||
if (this.tab === "category" && this.query.categoryId)
|
||||
params.categoryId = this.query.categoryId;
|
||||
const res = await common_http.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) {
|
||||
common_vendor.index.showToast({ title: "加载失败", icon: "none" });
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
openForm(id) {
|
||||
const url = "/pages/product/form" + (id ? "?id=" + id : "");
|
||||
common_vendor.index.navigateTo({ url });
|
||||
}
|
||||
}
|
||||
};
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return common_vendor.e({
|
||||
a: $data.tab === "all" ? 1 : "",
|
||||
b: common_vendor.o(($event) => $options.switchTab("all")),
|
||||
c: $data.tab === "category" ? 1 : "",
|
||||
d: common_vendor.o(($event) => $options.switchTab("category")),
|
||||
e: common_vendor.o((...args) => $options.reload && $options.reload(...args)),
|
||||
f: $data.query.kw,
|
||||
g: common_vendor.o(common_vendor.m(($event) => $data.query.kw = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
h: $data.tab === "category"
|
||||
}, $data.tab === "category" ? {
|
||||
i: common_vendor.t($options.categoryLabel),
|
||||
j: $options.categoryNames,
|
||||
k: common_vendor.o((...args) => $options.onPickCategory && $options.onPickCategory(...args))
|
||||
} : {}, {
|
||||
l: common_vendor.o((...args) => $options.reload && $options.reload(...args)),
|
||||
m: $data.items.length
|
||||
}, $data.items.length ? {
|
||||
n: common_vendor.f($data.items, (it, k0, i0) => {
|
||||
return common_vendor.e({
|
||||
a: it.cover
|
||||
}, it.cover ? {
|
||||
b: it.cover
|
||||
} : {}, {
|
||||
c: common_vendor.t(it.name),
|
||||
d: common_vendor.t(it.brand || "-"),
|
||||
e: common_vendor.t(it.model || ""),
|
||||
f: common_vendor.t(it.spec || ""),
|
||||
g: common_vendor.t(it.stock ?? 0),
|
||||
h: common_vendor.t((it.retailPrice ?? it.price ?? 0).toFixed(2)),
|
||||
i: it.id,
|
||||
j: common_vendor.o(($event) => $options.openForm(it.id), it.id)
|
||||
});
|
||||
})
|
||||
} : {}, {
|
||||
o: common_vendor.o((...args) => $options.loadMore && $options.loadMore(...args)),
|
||||
p: common_vendor.o(($event) => $options.openForm())
|
||||
});
|
||||
}
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/list.js.map
|
||||
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/list.json
vendored
Normal file
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/list.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "货品列表",
|
||||
"usingComponents": {}
|
||||
}
|
||||
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/list.wxml
vendored
Normal file
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/list.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view class="page"><view class="tabs"><view class="{{['tab', a && 'active']}}" bindtap="{{b}}">全部</view><view class="{{['tab', c && 'active']}}" bindtap="{{d}}">按类别</view></view><view class="search"><input placeholder="输入名称/条码/规格查询" bindconfirm="{{e}}" value="{{f}}" bindinput="{{g}}"/><picker wx:if="{{h}}" mode="selector" range="{{j}}" bindchange="{{k}}"><view class="picker">{{i}}</view></picker><button size="mini" bindtap="{{l}}">查询</button></view><scroll-view scroll-y class="list" bindscrolltolower="{{o}}"><block wx:if="{{m}}"><view wx:for="{{n}}" wx:for-item="it" wx:key="i" class="item" bindtap="{{it.j}}"><image wx:if="{{it.a}}" src="{{it.b}}" class="thumb" mode="aspectFill"/><view class="content"><view class="name">{{it.c}}</view><view class="meta">{{it.d}} {{it.e}} {{it.f}}</view><view class="meta">库存:{{it.g}} <text class="price">零售价:¥{{it.h}}</text></view></view></view></block><view wx:else class="empty"><text>暂无数据,点击右上角“+”新增</text></view></scroll-view><view class="fab" bindtap="{{p}}">+</view></view>
|
||||
33
frontend/unpackage/dist/dev/mp-weixin/pages/product/list.wxss
vendored
Normal file
33
frontend/unpackage/dist/dev/mp-weixin/pages/product/list.wxss
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
.page { display:flex; flex-direction: column; height: 100vh;
|
||||
}
|
||||
.tabs { display:flex; background:#fff;
|
||||
}
|
||||
.tab { flex:1; text-align:center; padding: 20rpx 0; color:#666;
|
||||
}
|
||||
.tab.active { color:#18b566; font-weight: 600;
|
||||
}
|
||||
.search { display:flex; gap: 12rpx; padding: 16rpx; background:#fff; align-items: center;
|
||||
}
|
||||
.search input { flex:1; background:#f6f6f6; border-radius: 12rpx; padding: 12rpx;
|
||||
}
|
||||
.picker { padding: 8rpx 12rpx; background:#f0f0f0; border-radius: 10rpx; color:#666;
|
||||
}
|
||||
.list { flex:1;
|
||||
}
|
||||
.item { display:flex; padding: 20rpx; background:#fff; border-bottom: 1rpx solid #f1f1f1;
|
||||
}
|
||||
.thumb { width: 120rpx; height: 120rpx; border-radius: 12rpx; margin-right: 16rpx; background:#fafafa;
|
||||
}
|
||||
.content { flex:1;
|
||||
}
|
||||
.name { color:#333; margin-bottom: 6rpx; font-weight: 600;
|
||||
}
|
||||
.meta { color:#888; font-size: 24rpx;
|
||||
}
|
||||
.price { margin-left: 20rpx; color:#f60;
|
||||
}
|
||||
.empty { height: 60vh; display:flex; align-items:center; justify-content:center; color:#999;
|
||||
}
|
||||
.fab { position: fixed; right: 30rpx; bottom: 120rpx; width: 100rpx; height: 100rpx; background:#18b566; color:#fff; border-radius: 50rpx; text-align:center; line-height: 100rpx; font-size: 48rpx; box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.15);
|
||||
}
|
||||
39
frontend/unpackage/dist/dev/mp-weixin/pages/product/settings.js
vendored
Normal file
39
frontend/unpackage/dist/dev/mp-weixin/pages/product/settings.js
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
const common_http = require("../../common/http.js");
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const _sfc_main = {
|
||||
data() {
|
||||
return { settings: { hideZeroStock: false, hidePurchasePrice: false } };
|
||||
},
|
||||
onLoad() {
|
||||
this.load();
|
||||
},
|
||||
methods: {
|
||||
async load() {
|
||||
try {
|
||||
const res = await common_http.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 common_http.put("/api/product-settings", next);
|
||||
} catch (_) {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return {
|
||||
a: $data.settings.hideZeroStock,
|
||||
b: common_vendor.o((e) => $options.update("hideZeroStock", e.detail.value)),
|
||||
c: $data.settings.hidePurchasePrice,
|
||||
d: common_vendor.o((e) => $options.update("hidePurchasePrice", e.detail.value))
|
||||
};
|
||||
}
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/settings.js.map
|
||||
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/settings.json
vendored
Normal file
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "货品设置",
|
||||
"usingComponents": {}
|
||||
}
|
||||
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/settings.wxml
vendored
Normal file
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/settings.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view class="page"><view class="item"><text>隐藏零库存商品</text><switch checked="{{a}}" bindchange="{{b}}"/></view><view class="item"><text>隐藏进货价</text><switch checked="{{c}}" bindchange="{{d}}"/></view></view>
|
||||
5
frontend/unpackage/dist/dev/mp-weixin/pages/product/settings.wxss
vendored
Normal file
5
frontend/unpackage/dist/dev/mp-weixin/pages/product/settings.wxss
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
.page { background:#fff;
|
||||
}
|
||||
.item { display:flex; justify-content: space-between; align-items:center; padding: 20rpx; border-bottom: 1rpx solid #f1f1f1;
|
||||
}
|
||||
62
frontend/unpackage/dist/dev/mp-weixin/pages/product/units.js
vendored
Normal file
62
frontend/unpackage/dist/dev/mp-weixin/pages/product/units.js
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const common_http = require("../../common/http.js");
|
||||
const _sfc_main = {
|
||||
data() {
|
||||
return { name: "", list: [] };
|
||||
},
|
||||
onLoad() {
|
||||
this.reload();
|
||||
},
|
||||
methods: {
|
||||
async reload() {
|
||||
try {
|
||||
const res = await common_http.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 common_http.post("/api/product-units", { name: this.name });
|
||||
this.name = "";
|
||||
this.reload();
|
||||
},
|
||||
async update(u) {
|
||||
await common_http.put("/api/product-units/" + u.id, { name: u.name });
|
||||
common_vendor.index.showToast({ title: "已保存", icon: "success" });
|
||||
},
|
||||
async remove(u) {
|
||||
common_vendor.index.showModal({ content: "确定删除该单位?", success: async (r) => {
|
||||
if (!r.confirm)
|
||||
return;
|
||||
await common_http.del("/api/product-units/" + u.id);
|
||||
this.reload();
|
||||
} });
|
||||
}
|
||||
}
|
||||
};
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return {
|
||||
a: $data.name,
|
||||
b: common_vendor.o(common_vendor.m(($event) => $data.name = $event.detail.value, {
|
||||
trim: true
|
||||
})),
|
||||
c: common_vendor.o((...args) => $options.create && $options.create(...args)),
|
||||
d: common_vendor.f($data.list, (u, k0, i0) => {
|
||||
return {
|
||||
a: u.name,
|
||||
b: common_vendor.o(common_vendor.m(($event) => u.name = $event.detail.value, {
|
||||
trim: true
|
||||
}), u.id),
|
||||
c: common_vendor.o(($event) => $options.update(u), u.id),
|
||||
d: common_vendor.o(($event) => $options.remove(u), u.id),
|
||||
e: u.id
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/units.js.map
|
||||
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/units.json
vendored
Normal file
4
frontend/unpackage/dist/dev/mp-weixin/pages/product/units.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "单位管理",
|
||||
"usingComponents": {}
|
||||
}
|
||||
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/units.wxml
vendored
Normal file
1
frontend/unpackage/dist/dev/mp-weixin/pages/product/units.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view class="page"><view class="toolbar"><input placeholder="新单位名称" value="{{a}}" bindinput="{{b}}"/><button size="mini" bindtap="{{c}}">新增</button></view><scroll-view scroll-y class="list"><view wx:for="{{d}}" wx:for-item="u" wx:key="e" class="item"><input value="{{u.a}}" bindinput="{{u.b}}"/><view class="ops"><button size="mini" bindtap="{{u.c}}">保存</button><button size="mini" type="warn" bindtap="{{u.d}}">删除</button></view></view></scroll-view></view>
|
||||
15
frontend/unpackage/dist/dev/mp-weixin/pages/product/units.wxss
vendored
Normal file
15
frontend/unpackage/dist/dev/mp-weixin/pages/product/units.wxss
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
.page { display:flex; flex-direction: column; height: 100vh;
|
||||
}
|
||||
.toolbar { display:flex; gap: 12rpx; padding: 16rpx; background:#fff;
|
||||
}
|
||||
.toolbar input { flex:1; background:#f6f6f6; border-radius: 12rpx; padding: 12rpx;
|
||||
}
|
||||
.list { flex:1;
|
||||
}
|
||||
.item { display:flex; gap: 12rpx; align-items:center; padding: 16rpx; background:#fff; border-bottom: 1rpx solid #f1f1f1;
|
||||
}
|
||||
.item input { flex:1; background:#f7f7f7; border-radius: 10rpx; padding: 12rpx;
|
||||
}
|
||||
.ops { display:flex; gap: 10rpx;
|
||||
}
|
||||
5
frontend/unpackage/dist/dev/mp-weixin/project.private.config.json
vendored
Normal file
5
frontend/unpackage/dist/dev/mp-weixin/project.private.config.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user