This commit is contained in:
2025-09-27 22:57:59 +08:00
parent 8a458ff0a4
commit ed26244cdb
12585 changed files with 1914308 additions and 3474 deletions

View File

@@ -24,15 +24,22 @@ const _sfc_main = {
wholesalePrice: null,
bigClientPrice: null,
images: [],
remark: ""
remark: "",
platformStatus: "",
sourceSubmissionId: ""
},
units: [],
categories: []
categories: [],
keyboardHeight: 0
};
},
onLoad(query) {
this.id = (query == null ? void 0 : query.id) || "";
this.bootstrap();
this.initKeyboardListener();
},
onUnload() {
this.disposeKeyboardListener();
},
computed: {
unitNames() {
@@ -56,6 +63,24 @@ const _sfc_main = {
if (this.id)
this.loadDetail();
},
initKeyboardListener() {
try {
this.__keyboardListener = (e) => {
const h = e && (e.height || e.targetHeight || 0) || 0;
this.keyboardHeight = h;
};
common_vendor.index.onKeyboardHeightChange && common_vendor.index.onKeyboardHeightChange(this.__keyboardListener);
} catch (_) {
}
},
disposeKeyboardListener() {
try {
if (this.__keyboardListener && common_vendor.index.offKeyboardHeightChange) {
common_vendor.index.offKeyboardHeightChange(this.__keyboardListener);
}
} catch (_) {
}
},
async fetchUnits() {
try {
const res = await common_http.get("/api/product-units");
@@ -80,10 +105,27 @@ const _sfc_main = {
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 chooseAndScanBarcode() {
try {
const chooseRes = await common_vendor.index.chooseImage({ count: 1, sourceType: ["camera", "album"], sizeType: ["compressed"] });
let filePath = chooseRes.tempFilePaths[0];
try {
const comp = await common_vendor.index.compressImage({ src: filePath, quality: 80 });
filePath = comp.tempFilePath || filePath;
} catch (e) {
}
const data = await common_http.upload("/api/barcode/scan", filePath, {}, "file");
if (data && data.success && data.barcode) {
this.form.barcode = data.barcode;
common_vendor.index.showToast({ title: "识别成功", icon: "success", mask: false });
return;
}
const msg = data && (data.message || data.error || data.msg) || "未识别";
common_vendor.index.showToast({ title: msg, icon: "none", mask: false });
} catch (e) {
const msg = e && e.message ? String(e.message) : "网络异常或服务不可用";
common_vendor.index.showToast({ title: msg, icon: "none", mask: false });
}
},
async loadDetail() {
try {
@@ -104,7 +146,10 @@ const _sfc_main = {
retailPrice: data.retailPrice,
wholesalePrice: data.wholesalePrice,
bigClientPrice: data.bigClientPrice,
images: (data.images || []).map((i) => i.url || i)
images: (data.images || []).map((i) => i.url || i),
remark: data.remark || "",
platformStatus: data.platformStatus || "",
sourceSubmissionId: data.sourceSubmissionId || ""
});
} catch (_) {
}
@@ -145,6 +190,10 @@ const _sfc_main = {
};
},
async save(goOn) {
try {
common_vendor.index.hideKeyboard && common_vendor.index.hideKeyboard();
} catch (_) {
}
if (!this.validate())
return;
const payload = this.buildPayload();
@@ -153,14 +202,14 @@ const _sfc_main = {
await common_http.put("/api/products/" + this.id, payload);
else
await common_http.post("/api/products", payload);
common_vendor.index.showToast({ title: "保存成功", icon: "success" });
common_vendor.index.showToast({ title: "保存成功", icon: "success", mask: false });
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: "" };
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: "", platformStatus: "", sourceSubmissionId: "" };
} else {
setTimeout(() => common_vendor.index.navigateBack(), 400);
}
} catch (e) {
common_vendor.index.showToast({ title: "保存失败", icon: "none" });
common_vendor.index.showToast({ title: "保存失败", icon: "none", mask: false });
}
}
}
@@ -170,79 +219,84 @@ if (!Array) {
_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, {
return common_vendor.e({
a: $data.form.platformStatus === "platform"
}, $data.form.platformStatus === "platform" ? {} : $data.form.sourceSubmissionId ? {} : {}, {
b: $data.form.sourceSubmissionId,
c: $data.form.name,
d: 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, {
e: $data.form.barcode,
f: 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, {
g: common_vendor.o((...args) => $options.chooseAndScanBarcode && $options.chooseAndScanBarcode(...args)),
h: $data.form.brand,
i: 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, {
j: $data.form.model,
k: 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, {
l: $data.form.spec,
m: 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, {
n: $data.form.origin,
o: 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, {
p: common_vendor.t($options.unitLabel),
q: $options.unitNames,
r: common_vendor.o((...args) => $options.onPickUnit && $options.onPickUnit(...args)),
s: common_vendor.t($options.categoryLabel),
t: $options.categoryNames,
v: common_vendor.o((...args) => $options.onPickCategory && $options.onPickCategory(...args)),
w: $data.form.stock,
x: 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, {
y: $data.form.safeMin,
z: 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, {
A: $data.form.safeMax,
B: 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, {
C: $data.form.purchasePrice,
D: 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, {
E: $data.form.retailPrice,
F: 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, {
G: $data.form.wholesalePrice,
H: 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, {
I: $data.form.bigClientPrice,
J: 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({
K: common_vendor.o(($event) => $data.form.images = $event),
L: 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, {
M: $data.form.remark,
N: 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))
};
O: common_vendor.o(($event) => $options.save(false)),
P: common_vendor.o(($event) => $options.save(true)),
Q: ($data.keyboardHeight || 0) + "px"
});
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
wx.createPage(MiniProgramPage);

View File

@@ -1 +1 @@
<scroll-view scroll-y class="page"><view class="hero small"><text class="title">编辑货品</text><text class="sub">完善基础信息与价格</text></view><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 class="ghost" bindtap="{{L}}">保存</button><button class="primary" bindtap="{{M}}">保存并继续</button></view></scroll-view>
<scroll-view scroll-y class="page"><view class="hero small"><text class="title">编辑货品</text><text class="sub">完善基础信息与价格</text></view><view wx:if="{{a}}" class="tip platform">平台推荐货品,建议谨慎修改核心字段</view><view wx:elif="{{b}}" class="tip custom">此货品源于我的提交,审核通过后已入库</view><view class="section"><view class="row"><text class="label">商品名称</text><input placeholder="必填" value="{{c}}" bindinput="{{d}}"/></view><view class="row"><text class="label">条形码</text><input class="input-long" placeholder="可扫码或输入" value="{{e}}" bindinput="{{f}}"/><button size="mini" class="picker-btn" bindtap="{{g}}">图片识码</button></view><view class="row"><input placeholder="品牌" value="{{h}}" bindinput="{{i}}"/></view><view class="row"><input placeholder="型号" value="{{j}}" bindinput="{{k}}"/></view><view class="row"><input placeholder="规格" value="{{l}}" bindinput="{{m}}"/></view><view class="row"><input placeholder="产地" value="{{n}}" bindinput="{{o}}"/></view><view class="row"><picker mode="selector" range="{{q}}" bindchange="{{r}}"><view class="picker">主单位:{{p}}</view></picker><picker mode="selector" range="{{t}}" bindchange="{{v}}"><view class="picker">类别:{{s}}</view></picker></view></view><view class="section"><view class="row"><text class="label">库存与安全库存</text></view><view class="row"><input type="number" placeholder="当前库存" value="{{w}}" bindinput="{{x}}"/><input type="number" placeholder="安全库存下限" value="{{y}}" bindinput="{{z}}"/><input type="number" placeholder="安全库存上限" value="{{A}}" bindinput="{{B}}"/></view></view><view class="section"><view class="row"><text class="label">价格(进价/零售/批发/大单)</text></view><view class="row prices"><input type="number" placeholder="进货价" value="{{C}}" bindinput="{{D}}"/><input type="number" placeholder="零售价" value="{{E}}" bindinput="{{F}}"/><input type="number" placeholder="批发价" value="{{G}}" bindinput="{{H}}"/><input type="number" placeholder="大单价" value="{{I}}" bindinput="{{J}}"/></view></view><view class="section"><text class="label">图片</text><image-uploader wx:if="{{L}}" u-i="4a3f460a-0" bind:__l="__l" bindupdateModelValue="{{K}}" u-p="{{L}}"/></view><view class="section"><text class="label">备注</text><block wx:if="{{r0}}"><textarea placeholder="可选" auto-height value="{{M}}" bindinput="{{N}}"/></block></view><view class="fixed" style="{{'bottom:' + Q}}"><button class="ghost" bindtap="{{O}}">保存</button><button class="primary" bindtap="{{P}}">保存并继续</button></view></scroll-view>

View File

@@ -26,71 +26,107 @@
/* 文章场景相关 */
.page {
background: #ffffff;
height: 100vh;
min-height: 100vh;
padding-bottom: 160rpx;
box-sizing: border-box;
}
.hero.small {
margin: 16rpx;
padding: 16rpx;
background: #ffffff;
border: 2rpx solid #e5e7eb;
border-radius: 16rpx;
margin: 22rpx 24rpx 12rpx;
padding: 0 4rpx 18rpx;
color: #111;
border-bottom: 2rpx solid rgba(94, 124, 174, 0.12);
}
.hero.small .title {
font-size: 32rpx;
font-size: 34rpx;
font-weight: 800;
color: #111;
}
.hero.small .sub {
margin-left: 12rpx;
display: block;
margin-top: 6rpx;
color: #444;
font-size: 24rpx;
}
.card {
background: #ffffff;
margin: 16rpx;
padding: 16rpx;
border-radius: 16rpx;
border: 2rpx solid #e5e7eb;
.section {
margin: 0 24rpx 28rpx;
padding-bottom: 6rpx;
border-bottom: 2rpx solid rgba(94, 124, 174, 0.1);
}
.section:last-of-type {
border-bottom: 0;
margin-bottom: 0;
}
.section .row:first-child .label {
font-weight: 700;
color: #111;
}
.row {
display: flex;
gap: 12rpx;
gap: 8rpx;
align-items: center;
margin-bottom: 12rpx;
margin-top: 18rpx;
}
.row .input-long {
flex: 1.2;
}
.row:first-child {
margin-top: 0;
}
.label {
width: 180rpx;
width: 150rpx;
color: #444;
font-size: 26rpx;
}
.row input {
flex: 1;
background: #f1f1f1;
border-radius: 12rpx;
padding: 14rpx;
background: #f7f9fc;
border-radius: 14rpx;
padding: 18rpx 20rpx;
color: #111;
border: 2rpx solid #e5e7eb;
border: 0;
box-shadow: inset 0 0 0 2rpx rgba(134, 155, 191, 0.06);
}
.picker-btn {
background: #ffffff;
border: 2rpx solid rgba(76, 141, 255, 0.45);
color: #4C8DFF;
padding: 0 24rpx;
border-radius: 999rpx;
font-size: 24rpx;
}
.picker {
padding: 10rpx 14rpx;
background: #f1f1f1;
border-radius: 12rpx;
padding: 16rpx 22rpx;
background: #f7f9fc;
border-radius: 14rpx;
color: #444;
margin-left: 8rpx;
border: 2rpx solid #e5e7eb;
border: 0;
box-shadow: inset 0 0 0 2rpx rgba(134, 155, 191, 0.06);
}
.prices input {
width: 30%;
}
.section textarea {
width: 100%;
min-height: 160rpx;
background: #f7f9fc;
border-radius: 14rpx;
padding: 20rpx 22rpx;
box-sizing: border-box;
color: #111;
border: 0;
box-shadow: inset 0 0 0 2rpx rgba(134, 155, 191, 0.06);
}
.fixed {
position: fixed;
left: 0;
right: 0;
bottom: 0;
bottom: env(safe-area-inset-bottom);
background: #ffffff;
padding: 12rpx 16rpx;
padding: 16rpx 16rpx calc(16rpx + constant(safe-area-inset-bottom)) 16rpx;
display: flex;
gap: 16rpx;
border-top: 2rpx solid #e5e7eb;
box-shadow: 0 -6rpx 18rpx rgba(24, 55, 105, 0.08);
z-index: 999;
}
.fixed .primary {
flex: 1;
@@ -107,4 +143,18 @@
border: 2rpx solid rgba(76, 141, 255, 0.45);
border-radius: 999rpx;
padding: 18rpx 0;
}
.tip {
margin: 0 30rpx 20rpx;
padding: 16rpx 20rpx;
border-radius: 16rpx;
font-size: 24rpx;
}
.tip.platform {
background: rgba(45, 140, 240, 0.12);
color: #2d8cf0;
}
.tip.custom {
background: rgba(103, 194, 58, 0.12);
color: #67c23a;
}

View File

@@ -98,6 +98,9 @@ const _sfc_main = {
openForm(id) {
const url = "/pages/product/form" + (id ? "?id=" + id : "");
common_vendor.index.navigateTo({ url });
},
goMySubmissions() {
common_vendor.index.navigateTo({ url: "/pages/product/submissions" });
}
}
};
@@ -107,39 +110,42 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
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, {
e: common_vendor.o((...args) => $options.goMySubmissions && $options.goMySubmissions(...args)),
f: common_vendor.o((...args) => $options.reload && $options.reload(...args)),
g: $data.query.kw,
h: common_vendor.o(common_vendor.m(($event) => $data.query.kw = $event.detail.value, {
trim: true
})),
h: $data.tab === "category"
i: $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))
j: common_vendor.t($options.categoryLabel),
k: $options.categoryNames,
l: common_vendor.o((...args) => $options.onPickCategory && $options.onPickCategory(...args))
} : {}, {
l: common_vendor.o((...args) => $options.reload && $options.reload(...args)),
m: $data.items.length
m: common_vendor.o((...args) => $options.reload && $options.reload(...args)),
n: $data.items.length
}, $data.items.length ? {
n: common_vendor.f($data.items, (it, k0, i0) => {
o: 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)
d: it.platformStatus === "platform"
}, it.platformStatus === "platform" ? {} : it.sourceSubmissionId ? {} : {}, {
e: it.sourceSubmissionId,
f: common_vendor.t(it.brand || "-"),
g: common_vendor.t(it.model || ""),
h: common_vendor.t(it.spec || ""),
i: common_vendor.t(it.stock ?? 0),
j: common_vendor.t((it.retailPrice ?? it.price ?? 0).toFixed(2)),
k: it.id,
l: 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())
p: common_vendor.o((...args) => $options.loadMore && $options.loadMore(...args))
});
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);

View File

@@ -1 +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>
<view class="page"><view class="tabs"><view class="{{['tab', a && 'active']}}" bindtap="{{b}}">全部</view><view class="{{['tab', c && 'active']}}" bindtap="{{d}}">按类别</view><view class="tab extra" bindtap="{{e}}">我的提交</view></view><view class="search"><input placeholder="输入名称/条码/规格查询" bindconfirm="{{f}}" value="{{g}}" bindinput="{{h}}"/><picker wx:if="{{i}}" mode="selector" range="{{k}}" bindchange="{{l}}"><view class="picker">{{j}}</view></picker><button size="mini" bindtap="{{m}}">查询</button></view><scroll-view scroll-y class="list" bindscrolltolower="{{p}}"><block wx:if="{{n}}"><view wx:for="{{o}}" wx:for-item="it" wx:key="k" class="item" bindtap="{{it.l}}"><image wx:if="{{it.a}}" src="{{it.b}}" class="thumb" mode="aspectFill"/><view class="content"><view class="name"><text>{{it.c}}</text><text wx:if="{{it.d}}" class="tag-platform">平台推荐</text><text wx:elif="{{it.e}}" class="tag-custom">我的提交</text></view><view class="meta">{{it.f}} {{it.g}} {{it.h}}</view><view class="meta">库存:{{it.i}} <text class="price">零售价:¥{{it.j}}</text></view></view></view></block><view wx:else class="empty"><text>暂无数据,点击右上角“+”新增</text></view></scroll-view></view>

View File

@@ -43,6 +43,11 @@
color: #4C8DFF;
font-weight: 600;
}
.tab.extra {
flex: 0 0 180rpx;
color: #4C8DFF;
font-weight: 600;
}
.search {
display: flex;
gap: 12rpx;
@@ -86,6 +91,23 @@
color: #111;
margin-bottom: 6rpx;
font-weight: 600;
display: flex;
align-items: center;
gap: 12rpx;
}
.tag-platform {
font-size: 22rpx;
color: #fff;
background: #2d8cf0;
padding: 4rpx 10rpx;
border-radius: 8rpx;
}
.tag-custom {
font-size: 22rpx;
color: #fff;
background: #67c23a;
padding: 4rpx 10rpx;
border-radius: 8rpx;
}
.meta {
color: #444;

View File

@@ -0,0 +1,180 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const common_http = require("../../common/http.js");
const _sfc_main = {
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] = await Promise.all([
this.cacheUnitsLoaded ? Promise.resolve(null) : common_http.get("/api/product-units"),
this.cacheCategoriesLoaded ? Promise.resolve(null) : common_http.get("/api/product-categories")
]);
if (units) {
const list = Array.isArray(units == null ? void 0 : units.list) ? units.list : Array.isArray(units) ? units : [];
common_vendor.index.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 : [];
common_vendor.index.setStorageSync("CACHE_CATEGORIES", list);
this.cacheCategoriesLoaded = true;
}
} 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 common_http.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) {
common_vendor.index.__f__("warn", "at pages/product/submissions.vue:113", "加载提交记录失败", e);
const msg = (e == null ? void 0 : e.message) || "加载失败";
common_vendor.index.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) {
common_vendor.index.navigateTo({ url: `/pages/product/submission-detail?id=${id}` });
},
notifyPending() {
common_vendor.index.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));
common_vendor.index.navigateTo({ url: `/pages/product/submit?prefill=${query}` });
},
goSubmit() {
common_vendor.index.navigateTo({ url: "/pages/product/submit" });
}
}
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return common_vendor.e({
a: $data.status === "" ? 1 : "",
b: common_vendor.o(($event) => $options.switchStatus("")),
c: $data.status === "pending" ? 1 : "",
d: common_vendor.o(($event) => $options.switchStatus("pending")),
e: $data.status === "approved" ? 1 : "",
f: common_vendor.o(($event) => $options.switchStatus("approved")),
g: $data.status === "rejected" ? 1 : "",
h: common_vendor.o(($event) => $options.switchStatus("rejected")),
i: $data.items.length
}, $data.items.length ? {
j: common_vendor.f($data.items, (item, k0, i0) => {
return common_vendor.e({
a: common_vendor.t(item.model || "-"),
b: common_vendor.t($options.statusLabel(item.status)),
c: common_vendor.n($options.statusClass(item.status)),
d: common_vendor.t(item.name || "未填写名称"),
e: common_vendor.t(item.brand || "-"),
f: common_vendor.t($options.formatTime(item.createdAt)),
g: item.reviewedAt
}, item.reviewedAt ? {
h: common_vendor.t($options.formatTime(item.reviewedAt))
} : {}, {
i: common_vendor.o(($event) => $options.viewDetail(item.id), item.id),
j: item.status === "pending"
}, item.status === "pending" ? {
k: common_vendor.o((...args) => $options.notifyPending && $options.notifyPending(...args), item.id)
} : item.status === "rejected" ? {
m: common_vendor.o(($event) => $options.resubmit(item), item.id)
} : {}, {
l: item.status === "rejected",
n: item.id
});
})
} : {
k: common_vendor.o((...args) => $options.goSubmit && $options.goSubmit(...args))
}, {
l: $data.loading
}, $data.loading ? {} : $data.finished && $data.items.length ? {} : {}, {
m: $data.finished && $data.items.length,
n: common_vendor.o((...args) => $options.loadMore && $options.loadMore(...args)),
o: common_vendor.o((...args) => $options.goSubmit && $options.goSubmit(...args))
});
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
wx.createPage(MiniProgramPage);
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/submissions.js.map

View File

@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "我的提交",
"usingComponents": {}
}

View File

@@ -0,0 +1 @@
<view class="page"><view class="hero"><text class="title">我的配件提交</text><text class="desc">查看待审核、已通过、已驳回的记录</text></view><view class="tabs"><view class="{{['tab', a && 'active']}}" bindtap="{{b}}">全部</view><view class="{{['tab', c && 'active']}}" bindtap="{{d}}">待审核</view><view class="{{['tab', e && 'active']}}" bindtap="{{f}}">已通过</view><view class="{{['tab', g && 'active']}}" bindtap="{{h}}">已驳回</view></view><scroll-view scroll-y class="list" bindscrolltolower="{{n}}"><view wx:if="{{i}}" class="cards"><view wx:for="{{j}}" wx:for-item="item" wx:key="n" class="card"><view class="card-header"><text class="model">{{item.a}}</text><text class="{{['status', item.c]}}">{{item.b}}</text></view><view class="card-body"><text class="name">{{item.d}}</text><text class="brand">品牌:{{item.e}}</text><text class="time">提交:{{item.f}}</text><text wx:if="{{item.g}}" class="time">审核:{{item.h}}</text></view><view class="card-footer"><button size="mini" bindtap="{{item.i}}">详情</button><button wx:if="{{item.j}}" size="mini" type="primary" bindtap="{{item.k}}">等待审核</button><button wx:elif="{{item.l}}" size="mini" type="warn" bindtap="{{item.m}}">重新提交</button></view></view></view><view wx:else class="empty"><text>暂无提交记录,快去提交新的配件吧</text><button size="mini" class="primary" bindtap="{{k}}">立即提交</button></view><view wx:if="{{l}}" class="loading">加载中...</view><view wx:elif="{{m}}" class="finished">没有更多了</view></scroll-view><view class="fab" bindtap="{{o}}"></view></view>

View File

@@ -0,0 +1,163 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
.page {
display: flex;
flex-direction: column;
height: 100vh;
background: #f6f7fb;
padding-bottom: 140rpx;
}
.hero {
padding: 24rpx;
background: #fff;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.04);
}
.title {
font-size: 34rpx;
font-weight: 700;
color: #2d3a4a;
}
.desc {
font-size: 24rpx;
color: #7a8899;
margin-top: 8rpx;
}
.tabs {
display: flex;
background: #fff;
margin: 16rpx;
border-radius: 999rpx;
overflow: hidden;
box-shadow: inset 0 0 0 1rpx rgba(76, 141, 255, 0.1);
}
.tab {
flex: 1;
text-align: center;
padding: 20rpx 0;
font-size: 28rpx;
color: #7a8899;
}
.tab.active {
background: linear-gradient(135deg, #4c8dff, #6ab7ff);
color: #fff;
font-weight: 600;
}
.list {
flex: 1;
padding: 0 20rpx;
}
.cards {
display: flex;
flex-direction: column;
gap: 20rpx;
padding-bottom: 40rpx;
}
.card {
background: #fff;
border-radius: 18rpx;
padding: 22rpx;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.05);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12rpx;
}
.model {
font-size: 30rpx;
font-weight: 700;
color: #2d3a4a;
}
.status {
font-size: 24rpx;
padding: 6rpx 18rpx;
border-radius: 999rpx;
}
.status.pending {
background: rgba(246, 190, 0, 0.15);
color: #c47f00;
}
.status.approved {
background: rgba(103, 194, 58, 0.15);
color: #409eff;
}
.status.rejected {
background: rgba(255, 87, 115, 0.18);
color: #f56c6c;
}
.card-body {
display: flex;
flex-direction: column;
gap: 6rpx;
color: #4f5969;
font-size: 26rpx;
}
.name {
font-weight: 600;
color: #2d3a4a;
}
.card-footer {
display: flex;
gap: 12rpx;
margin-top: 16rpx;
}
.empty {
height: 60vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #8894a3;
gap: 20rpx;
}
.empty .primary {
background: #4c8dff;
color: #fff;
border-radius: 999rpx;
padding: 12rpx 30rpx;
}
.loading, .finished {
text-align: center;
padding: 20rpx 0;
color: #7a8899;
}
.fab {
position: fixed;
right: 30rpx;
bottom: 120rpx;
width: 100rpx;
height: 100rpx;
background: linear-gradient(135deg, #4c8dff, #6ab7ff);
color: #fff;
border-radius: 50rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 48rpx;
box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.2);
}

View File

@@ -0,0 +1,264 @@
"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 {
form: {
model: "",
brand: "",
barcode: "",
categoryId: "",
templateId: "",
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 common_http.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 common_http.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 = {};
},
onPickEnum(p, e) {
const idx = Number(e.detail.value);
const arr = p.enumOptions || [];
this.paramValues[p.fieldKey] = arr[idx];
},
async scanBarcode() {
var _a;
try {
const chooseRes = await common_vendor.index.chooseImage({ count: 1, sourceType: ["camera", "album"], sizeType: ["compressed"] });
let filePath = chooseRes.tempFilePaths[0];
try {
const comp = await common_vendor.index.compressImage({ src: filePath, quality: 80 });
filePath = comp.tempFilePath || filePath;
} catch (_) {
}
const data = await common_http.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;
common_vendor.index.showToast({ title: "识别成功", icon: "success" });
} else {
common_vendor.index.showToast({ title: "未识别到条码", icon: "none" });
}
} catch (e) {
const msg = (e == null ? void 0 : e.message) || "识码失败";
common_vendor.index.showToast({ title: msg, icon: "none" });
}
},
async checkModel() {
if (!this.form.model)
return common_vendor.index.showToast({ title: "请填写型号", icon: "none" });
try {
this.checking = true;
const res = await common_http.post("/api/products/submissions/check-model", { templateId: this.form.templateId, model: this.form.model });
if (res && res.available) {
common_vendor.index.showToast({ title: "可用,无重复", icon: "success" });
} else {
common_vendor.index.showToast({ title: "已存在相同型号提交", icon: "none" });
}
} catch (e) {
const msg = (e == null ? void 0 : e.message) || "校验失败";
common_vendor.index.showToast({ title: msg, icon: "none" });
} finally {
this.checking = false;
}
},
async submit() {
if (this.submitting)
return;
if (!this.form.model) {
return common_vendor.index.showToast({ title: "请填写型号", icon: "none" });
}
let paramsObj = null;
if (this.parameterText) {
try {
paramsObj = JSON.parse(this.parameterText);
} catch (e) {
return common_vendor.index.showToast({ title: "参数 JSON 不合法", icon: "none" });
}
}
if (this.form.safeMin != null && this.form.safeMax != null && Number(this.form.safeMin) > Number(this.form.safeMax)) {
return common_vendor.index.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 common_vendor.index.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,
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 common_http.post("/api/products/submissions", payload);
common_vendor.index.showToast({ title: "提交成功", icon: "success" });
setTimeout(() => {
common_vendor.index.redirectTo({ url: "/pages/product/submissions" });
}, 400);
} catch (e) {
const msg = (e == null ? void 0 : e.message) || "提交失败";
common_vendor.index.showToast({ title: msg, icon: "none" });
} finally {
this.submitting = false;
}
}
}
};
if (!Array) {
const _component_ImageUploader = common_vendor.resolveComponent("ImageUploader");
_component_ImageUploader();
}
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return {
a: $data.form.model,
b: common_vendor.o(common_vendor.m(($event) => $data.form.model = $event.detail.value, {
trim: true
})),
c: $data.form.brand,
d: common_vendor.o(common_vendor.m(($event) => $data.form.brand = $event.detail.value, {
trim: true
})),
e: $data.form.barcode,
f: common_vendor.o(common_vendor.m(($event) => $data.form.barcode = $event.detail.value, {
trim: true
})),
g: common_vendor.o((...args) => $options.scanBarcode && $options.scanBarcode(...args)),
h: common_vendor.t($options.categoryLabel),
i: $options.categoryNames,
j: common_vendor.o((...args) => $options.onPickCategory && $options.onPickCategory(...args)),
k: common_vendor.t($options.templateLabel),
l: $options.templateNames,
m: common_vendor.o((...args) => $options.onPickTemplate && $options.onPickTemplate(...args)),
n: common_vendor.o(($event) => $data.form.images = $event),
o: common_vendor.p({
max: 9,
formData: {
ownerType: "submission"
},
modelValue: $data.form.images
}),
p: $data.form.remark,
q: common_vendor.o(common_vendor.m(($event) => $data.form.remark = $event.detail.value, {
trim: true
})),
r: $data.form.safeMin,
s: common_vendor.o(common_vendor.m(($event) => $data.form.safeMin = $event.detail.value, {
number: true
})),
t: $data.form.safeMax,
v: common_vendor.o(common_vendor.m(($event) => $data.form.safeMax = $event.detail.value, {
number: true
})),
w: $data.submitting,
x: common_vendor.o((...args) => $options.submit && $options.submit(...args)),
y: $data.checking,
z: common_vendor.o((...args) => $options.checkModel && $options.checkModel(...args))
};
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
wx.createPage(MiniProgramPage);
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/submit.js.map

View File

@@ -0,0 +1,7 @@
{
"navigationBarTitleText": "提交配件",
"navigationBarBackgroundColor": "#ffffff",
"usingComponents": {
"image-uploader": "../../components/ImageUploader"
}
}

View File

@@ -0,0 +1 @@
<scroll-view scroll-y class="page"><view class="hero"><text class="title">提交配件</text><text class="desc">填写型号、名称、参数与图片,提交后进入待审核状态</text></view><view class="section"><view class="row required"><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><input placeholder="可选,建议扫码录入" value="{{e}}" bindinput="{{f}}"/><button size="mini" class="picker-btn" bindtap="{{g}}">识码</button></view></view><view class="section"><view class="row"><text class="label">类别</text><picker mode="selector" range="{{i}}" bindchange="{{j}}"><view class="picker">{{h}}</view></picker></view></view><view class="section"><view class="row"><text class="label">模板</text></view><view class="row"><picker mode="selector" range="{{l}}" bindchange="{{m}}"><view class="picker">{{k}}</view></picker></view></view><view class="section"><view class="row"><text class="label">图片</text></view><image-uploader wx:if="{{o}}" u-i="7f3a3bde-0" bind:__l="__l" bindupdateModelValue="{{n}}" u-p="{{o}}"/></view><view class="section"><view class="row"><text class="label">备注</text></view><block wx:if="{{r0}}"><textarea class="textarea" placeholder="选填:补充说明" value="{{p}}" bindinput="{{q}}"/></block></view><view class="section"><view class="row"><text class="label">安全库存</text></view><view class="row triple"><input type="number" placeholder="下限" value="{{r}}" bindinput="{{s}}"/><input type="number" placeholder="上限" value="{{t}}" bindinput="{{v}}"/></view></view><view class="fixed"><button class="primary" loading="{{w}}" bindtap="{{x}}">提交审核</button><button class="primary" style="margin-top:16rpx;background:#7aa9ff" loading="{{y}}" bindtap="{{z}}">查重</button></view></scroll-view>

View File

@@ -0,0 +1,125 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
.page {
padding: 24rpx 24rpx 120rpx;
background: #f6f7fb;
}
.hero {
padding: 24rpx;
background: linear-gradient(135deg, #4c8dff, #6ab7ff);
border-radius: 20rpx;
color: #fff;
margin-bottom: 24rpx;
}
.title {
font-size: 36rpx;
font-weight: 700;
}
.desc {
font-size: 26rpx;
margin-top: 8rpx;
opacity: 0.9;
}
.section {
background: #fff;
border-radius: 16rpx;
padding: 20rpx 22rpx;
margin-bottom: 24rpx;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.04);
}
.row {
display: flex;
align-items: center;
gap: 16rpx;
padding: 16rpx 0;
border-bottom: 1rpx solid #f1f2f5;
}
.row:last-child {
border-bottom: none;
}
.row.required .label::after {
content: "*";
color: #ff5b5b;
margin-left: 6rpx;
}
.label {
width: 130rpx;
font-size: 28rpx;
color: #2d3a4a;
}
input {
flex: 1;
background: #f8f9fb;
border-radius: 12rpx;
padding: 16rpx 18rpx;
font-size: 28rpx;
color: #222;
}
.textarea {
width: 100%;
min-height: 160rpx;
background: #f8f9fb;
border-radius: 12rpx;
padding: 18rpx;
font-size: 28rpx;
color: #222;
}
.picker {
flex: 1;
background: #f8f9fb;
border-radius: 12rpx;
padding: 18rpx;
font-size: 28rpx;
color: #222;
}
.picker-btn {
background: #4c8dff;
color: #fff;
border-radius: 999rpx;
padding: 10rpx 22rpx;
}
.triple input {
flex: 1;
}
.fixed {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 20rpx 24rpx 40rpx;
background: rgba(255, 255, 255, 0.96);
box-shadow: 0 -6rpx 20rpx rgba(0, 0, 0, 0.08);
}
.primary {
width: 100%;
height: 88rpx;
border-radius: 999rpx;
background: #4c8dff;
color: #fff;
font-size: 32rpx;
font-weight: 600;
}