feat: 积分商城-供应商-对账-发票3

This commit is contained in:
2026-09-08 16:41:48 +08:00
parent 3abe4ce9c9
commit f42ea5b270
47 changed files with 1211 additions and 285 deletions
+146 -83
View File
@@ -11,16 +11,16 @@
"@vant/area-data": "^1.5.2",
"core-js": "^3.37.1",
"pinia": "^2.3.1",
"vant": "^2.13.9",
"vue": "^2.7.16",
"vue-router": "^3.6.5"
"vant": "^3.6.16",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-service": "~5.0.8",
"@vue/compiler-sfc": "^3.5.13",
"less": "^4.2.0",
"less-loader": "^10.2.0",
"vue-template-compiler": "^2.7.16"
"less-loader": "^10.2.0"
}
},
"node_modules/@achrinza/node-ipc": {
@@ -337,10 +337,12 @@
}
},
"node_modules/@babel/parser": {
"version": "7.29.7",
"version": "7.29.8",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
"integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
"license": "MIT",
"dependencies": {
"@babel/types": "^7.29.7"
"@babel/types": "^7.29.8"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1446,6 +1448,7 @@
},
"node_modules/@babel/runtime": {
"version": "7.29.7",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -1482,7 +1485,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.29.7",
"version": "7.29.8",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
"integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.29.7",
@@ -1550,7 +1555,6 @@
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
@@ -1859,15 +1863,27 @@
"license": "MIT"
},
"node_modules/@vant/icons": {
"version": "3.0.2",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@vant/icons/-/icons-1.8.0.tgz",
"integrity": "sha512-sKfEUo2/CkQFuERxvkuF6mGQZDKu3IQdj5rV9Fm0weJXtchDSSQ+zt8qPCNUEhh9Y8shy5PzxbvAfOOkCwlCXg==",
"license": "MIT"
},
"node_modules/@vant/popperjs": {
"version": "1.3.0",
"license": "MIT"
},
"node_modules/@vant/use": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@vant/use/-/use-1.6.0.tgz",
"integrity": "sha512-PHHxeAASgiOpSmMjceweIrv2AxDZIkWXyaczksMoWvKV2YAYEhoizRuk/xFnKF+emUIi46TsQ+rvlm/t2BBCfA==",
"license": "MIT",
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/@vue/babel-helper-vue-jsx-merge-props": {
"version": "1.4.0",
"dev": true,
"license": "MIT"
},
"node_modules/@vue/babel-helper-vue-transform-on": {
@@ -2277,49 +2293,53 @@
"license": "ISC"
},
"node_modules/@vue/compiler-core": {
"version": "3.5.39",
"dev": true,
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.42.tgz",
"integrity": "sha512-2Ye1ilMtKXxl8qZUrQ5j0CdgenFp/HFQmta6rfRyfEsTG69L6Wk+tWuNoHYHMx9E8tF2Slvdg1FuwDvAXdy1LQ==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.7",
"@vue/shared": "3.5.39",
"@babel/parser": "^7.29.8",
"@vue/shared": "3.5.42",
"entities": "^7.0.1",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.39",
"dev": true,
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.42.tgz",
"integrity": "sha512-qbhQZEFmycr+ni/qyuccS4sucNN7VAbDfbkvNxWOX2VfgFm90MNs3/UhRNKoPMEIVn0F8gdlYjLPvqxHwHeQOA==",
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.39",
"@vue/shared": "3.5.39"
"@vue/compiler-core": "3.5.42",
"@vue/shared": "3.5.42"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.39",
"dev": true,
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.42.tgz",
"integrity": "sha512-fkCAFB4okcAANGMThboWnScp/gzWjU0ZSkVnjTIiplmMDq2uq0tIB3j+xVu4rhv5rvOgBySCysudmbMd6xRRqw==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.7",
"@vue/compiler-core": "3.5.39",
"@vue/compiler-dom": "3.5.39",
"@vue/compiler-ssr": "3.5.39",
"@vue/shared": "3.5.39",
"@babel/parser": "^7.29.8",
"@vue/compiler-core": "3.5.42",
"@vue/compiler-dom": "3.5.42",
"@vue/compiler-ssr": "3.5.42",
"@vue/shared": "3.5.42",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.21",
"postcss": "^8.5.15",
"postcss": "^8.5.19",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.39",
"dev": true,
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.42.tgz",
"integrity": "sha512-xmLk3wLkbizPAiLyomjgFFosf2ys9b5Ghb+oh/k2tnvipNz8OFrQOiTcWCzyK7MpBp9KkyGtfvgfLUivbmuGYA==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.39",
"@vue/shared": "3.5.39"
"@vue/compiler-dom": "3.5.42",
"@vue/shared": "3.5.42"
}
},
"node_modules/@vue/component-compiler-utils": {
@@ -2386,9 +2406,52 @@
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
"license": "MIT"
},
"node_modules/@vue/reactivity": {
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.42.tgz",
"integrity": "sha512-TzNNfKpb7hDxbQltwAut8VDQA5YP+BuRlxntHUuRjyKwlMvmAPbs3unhCvieijifY6vFfVBwsS7wG/C7uq+bEQ==",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.5.42"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.42.tgz",
"integrity": "sha512-9uACtuHs7vJGkm5Bp3xu4xRDLFTIYy5DgxpToVjqGIAhAEKwQfsaLvKINhM6nFVp6bZPRFGdDqd1g52MqKsotA==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.42",
"@vue/shared": "3.5.42"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.42.tgz",
"integrity": "sha512-rsCmhiWLaRxGltLwhlCWyYkFn7WAbKRh0q17eZ1A6Dq6eqc2ACQ61IIryxz0LrsvCzHSilLA9JHovVwM8CNE2g==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.42",
"@vue/runtime-core": "3.5.42",
"@vue/shared": "3.5.42",
"csstype": "^3.2.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.42.tgz",
"integrity": "sha512-2++5dUyYS4gvo7xQXSECUDhB7TS0aOl5SeVfC5qSq1Jgfhjvegw1zqhwTIR3imZ+QYPJQw9gfcFvXGAjGZ7ajQ==",
"license": "MIT",
"dependencies": {
"@vue/compiler-ssr": "3.5.42",
"@vue/runtime-dom": "3.5.42",
"@vue/shared": "3.5.42"
}
},
"node_modules/@vue/shared": {
"version": "3.5.39",
"dev": true,
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.42.tgz",
"integrity": "sha512-2rPxex1jQf4jvl9MOHl6YaXCPcrNqz/FstMOEh3QWY+/OME9nQTvl9WYeCwhW7AFjaR0SnngZGlp/wkR6rkI6g==",
"license": "MIT"
},
"node_modules/@vue/vue-loader-v15": {
@@ -3981,11 +4044,8 @@
},
"node_modules/csstype": {
"version": "3.2.3",
"license": "MIT"
},
"node_modules/de-indent": {
"version": "1.0.2",
"dev": true,
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"license": "MIT"
},
"node_modules/debounce": {
@@ -4400,7 +4460,8 @@
},
"node_modules/entities": {
"version": "7.0.1",
"dev": true,
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
@@ -4531,7 +4592,8 @@
},
"node_modules/estree-walker": {
"version": "2.0.2",
"dev": true,
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"license": "MIT"
},
"node_modules/esutils": {
@@ -6048,7 +6110,6 @@
},
"node_modules/magic-string": {
"version": "0.30.21",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
@@ -6452,7 +6513,9 @@
}
},
"node_modules/nanoid": {
"version": "3.3.16",
"version": "3.3.18",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"funding": [
{
"type": "github",
@@ -7020,7 +7083,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.18",
"version": "8.5.28",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
"integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
"funding": [
{
"type": "opencollective",
@@ -7037,7 +7102,7 @@
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.12",
"nanoid": "^3.3.18",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -7553,6 +7618,7 @@
},
"node_modules/prettier": {
"version": "2.8.8",
"dev": true,
"license": "MIT",
"optional": true,
"bin": {
@@ -8397,6 +8463,7 @@
},
"node_modules/source-map": {
"version": "0.6.1",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -9025,19 +9092,17 @@
}
},
"node_modules/vant": {
"version": "2.13.9",
"resolved": "https://registry.npmmirror.com/vant/-/vant-2.13.9.tgz",
"integrity": "sha512-AIDYTUKOlqEolrTs18vZanLX9Mq6IftzwOnbozaNFmx9+xMrCeJIqRKefbGUPZ7irQvO6t397+VwRXqCSHnedQ==",
"version": "3.6.16",
"resolved": "https://registry.npmjs.org/vant/-/vant-3.6.16.tgz",
"integrity": "sha512-9pZao0NEeZQ0ZEb6N7SZxtqcdTp24o8IizhZS1G+FtStlXeKOFzCl+Nf1pIWRneQ9Kn+K+mNrfi2eiIZjVVppw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "7.x",
"@vant/icons": "^3.0.2",
"@vant/popperjs": "^1.1.0",
"@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
"vue-lazyload": "1.2.3"
"@vant/icons": "^1.8.0",
"@vant/popperjs": "^1.2.1",
"@vant/use": "^1.4.2"
},
"peerDependencies": {
"vue": ">= 2.6.0"
"vue": "^3.0.0"
}
},
"node_modules/vary": {
@@ -9049,11 +9114,24 @@
}
},
"node_modules/vue": {
"version": "2.7.16",
"version": "3.5.42",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.42.tgz",
"integrity": "sha512-4RyHQTbQvOPs3MfvUO1Sg0YRrKNnA0mAVtvpd12Tg1fKDN7OHBUl1IqSn8zGJjK9nI3NkNp8cgTpVrSZC5TTcA==",
"license": "MIT",
"dependencies": {
"@vue/compiler-sfc": "2.7.16",
"csstype": "^3.1.0"
"@vue/compiler-dom": "3.5.42",
"@vue/compiler-sfc": "3.5.42",
"@vue/runtime-dom": "3.5.42",
"@vue/server-renderer": "3.5.42",
"@vue/shared": "3.5.42"
},
"peerDependencies": {
"typescript": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/vue-hot-reload-api": {
@@ -9061,10 +9139,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/vue-lazyload": {
"version": "1.2.3",
"license": "MIT"
},
"node_modules/vue-loader": {
"version": "17.4.2",
"dev": true,
@@ -9102,10 +9176,19 @@
}
},
"node_modules/vue-router": {
"version": "3.6.5",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-3.6.5.tgz",
"integrity": "sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==",
"license": "MIT"
"version": "4.6.4",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz",
"integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^6.6.4"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"vue": "^3.5.0"
}
},
"node_modules/vue-style-loader": {
"version": "4.1.3",
@@ -9121,31 +9204,11 @@
"dev": true,
"license": "MIT"
},
"node_modules/vue-template-compiler": {
"version": "2.7.16",
"dev": true,
"license": "MIT",
"dependencies": {
"de-indent": "^1.0.2",
"he": "^1.2.0"
}
},
"node_modules/vue-template-es2015-compiler": {
"version": "1.9.1",
"dev": true,
"license": "MIT"
},
"node_modules/vue/node_modules/@vue/compiler-sfc": {
"version": "2.7.16",
"dependencies": {
"@babel/parser": "^7.23.5",
"postcss": "^8.4.14",
"source-map": "^0.6.1"
},
"optionalDependencies": {
"prettier": "^1.18.2 || ^2.0.0"
}
},
"node_modules/watchpack": {
"version": "2.5.2",
"dev": true,
+4 -4
View File
@@ -10,15 +10,15 @@
"@vant/area-data": "^1.5.2",
"core-js": "^3.37.1",
"pinia": "^2.3.1",
"vant": "^2.13.9",
"vue": "^2.7.16",
"vue-router": "^3.6.5"
"vant": "^3.6.16",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-service": "~5.0.8",
"less": "^4.2.0",
"less-loader": "^10.2.0",
"vue-template-compiler": "^2.7.16"
"@vue/compiler-sfc": "^3.5.13"
}
}
+3 -3
View File
@@ -14,7 +14,7 @@
<van-notice-bar class="notice" left-icon="volume-o" :text="shop.notice" />
<van-search v-model="keyword" placeholder="搜索商品" shape="round" />
<van-tabs v-model="activeCategory" sticky :color="shop.theme" title-active-color="var(--theme)">
<van-tabs v-model:active="activeCategory" sticky :color="shop.theme" title-active-color="var(--theme)">
<van-tab v-for="category in categories" :key="category" :title="category" />
</van-tabs>
@@ -44,7 +44,7 @@
<span class="selected">已选 {{ totalCount }} 件</span>
</van-submit-bar>
<van-popup v-model="checkoutVisible" round position="bottom" :style="{ minHeight: '68%' }" closeable>
<van-popup v-model:show="checkoutVisible" round position="bottom" :style="{ minHeight: '68%' }" closeable>
<section class="checkout">
<h2>确认订单</h2>
<van-contact-card type="add" name="商城收货人" tel="138****8888" @click="Toast('当前使用默认收货地址')" />
@@ -66,7 +66,7 @@
</section>
</van-popup>
<van-popup v-model="successVisible" round closeable class="result-popup">
<van-popup v-model:show="successVisible" round closeable class="result-popup">
<van-icon name="checked" color="#23b65d" size="62" />
<h2>订单提交成功</h2>
<p>订单号:{{ submittedOrderId }}</p>
+3 -12
View File
@@ -1,20 +1,11 @@
import Vue from 'vue'
import { createApp } from 'vue'
import Vant from 'vant'
import { Skeleton } from 'vant'
import { createPinia, PiniaVuePlugin } from 'pinia'
import { createPinia } from 'pinia'
import 'vant/lib/index.css'
import App from './App.vue'
import router from './router'
Vue.use(Vant)
Vue.use(Skeleton)
Vue.use(PiniaVuePlugin)
Vue.config.productionTip = false
const pinia = createPinia()
new Vue({
router,
pinia,
render: h => h(App)
}).$mount('#app')
createApp(App).use(pinia).use(router).use(Vant).mount('#app')
+4 -6
View File
@@ -1,5 +1,4 @@
import Vue from 'vue'
import Router from 'vue-router'
import { createRouter, createWebHashHistory } from 'vue-router'
import SupplierHome from '@/view/index.vue'
import JoyfulSelectionLayout from '@/view/joyful-selection/layout.vue'
import JoyfulSelectionHome from '@/view/joyful-selection/index.vue'
@@ -29,16 +28,15 @@ import HappyShopping from '@/view/happy-shopping/index.vue'
import FreshFruit from '@/view/fresh-fruit/index.vue'
import CuteSelection from '@/view/cute-selection/index.vue'
Vue.use(Router)
export default new Router({
export default createRouter({
history: createWebHashHistory(),
routes: [
{ path: '/', component: SupplierHome },
{
path: '/joyful-selection',
component: JoyfulSelectionLayout,
children: [
{ path: '', redirect: 'home' },
{ path: '', redirect: '/joyful-selection/home' },
{ path: 'home', component: JoyfulSelectionHome },
{ path: 'products', component: JoyfulSelectionProductList },
{ path: 'product-detail', component: JoyfulSelectionProductDetail },
+7
View File
@@ -20,6 +20,7 @@ const saveUser = data => {
export const useUserStore = defineStore('joyfulSelectionUser', {
state: () => ({
userId: '',
nickname: '',
supplierIdentification: '',
supplierId: '',
supplierName: '',
@@ -34,6 +35,7 @@ export const useUserStore = defineStore('joyfulSelectionUser', {
loadUser() {
const data = readUser()
this.userId = data.userId || ''
this.nickname = data.nickname || ''
const supplierIdentification = DEFAULT_SUPPLIER_IDENTIFICATION || data.supplierIdentification || ''
const supplierChanged = Boolean(data.supplierIdentification && supplierIdentification !== data.supplierIdentification)
@@ -46,6 +48,7 @@ export const useUserStore = defineStore('joyfulSelectionUser', {
persistUser() {
saveUser({
userId: this.userId,
nickname: this.nickname,
supplierIdentification: this.supplierIdentification,
supplierId: this.supplierId,
supplierName: this.supplierName,
@@ -60,6 +63,7 @@ export const useUserStore = defineStore('joyfulSelectionUser', {
const keyword = query.keyword || new URLSearchParams(window.location.search).get('keyword') || ''
let nextUserId = query.userId || ''
let nextNickname
if (keyword) {
const sessionKeyword = String(keyword).replace(/ /g, '+')
@@ -70,12 +74,15 @@ export const useUserStore = defineStore('joyfulSelectionUser', {
})
const data = await postFunction('supplier-session', { keyword: sessionKeyword })
nextUserId = data?.userId || ''
nextNickname = data?.userInfo?.nickname || ''
}
if (nextUserId && nextUserId !== this.userId) {
this.userId = nextUserId
this.nickname = ''
this.pointsBalance = 0
}
if (nextNickname !== undefined) this.nickname = nextNickname
if (!this.supplierIdentification) {
this.supplierIdentification = DEFAULT_SUPPLIER_IDENTIFICATION
}
@@ -87,7 +87,7 @@
<button v-else type="button" class="primary" @click="contactService">联系客服</button>
</footer>
<van-popup v-model="showLogisticsPopup" round position="bottom">
<van-popup v-model:show="showLogisticsPopup" round position="bottom">
<section class="logistics-popup">
<h3>填写物流单号</h3>
<van-field v-model="logisticsCompany" label="快递公司" placeholder="请输入快递公司" />
@@ -96,7 +96,7 @@
</section>
<van-button v-show="!loading" class="submit-button" block :loading="submitting" @click="submitReturn">提交申请</van-button>
<van-popup v-model="showReasonPopup" round position="bottom">
<van-popup v-model:show="showReasonPopup" round position="bottom">
<section class="reason-popup">
<h3>请选择换货原因</h3>
<van-radio-group v-model="selectedReason">
@@ -116,7 +116,7 @@
</van-radio-group>
</section>
</van-popup>
<van-popup v-model="showExchangeGoodsPopup" round position="bottom" :style="{ height: '80vh' }">
<van-popup v-model:show="showExchangeGoodsPopup" round position="bottom" :style="{ height: '80vh' }">
<section class="exchange-popup">
<h3>选择换货商品</h3>
<p>仅可选择价格为 ¥{{ originalProductPrice }} 的商品</p>
@@ -3,7 +3,7 @@
<van-nav-bar title="退款/售后" left-arrow @click-left="$router.replace('/joyful-selection/profile')" />
<van-pull-refresh v-model="refreshing" class="after-sale-list" @refresh="onRefresh">
<van-tabs v-model="activeTab" color="#ff5b20">
<van-tabs v-model:active="activeTab" color="#ff5b20">
<van-tab title="处理中" name="processing" />
<van-tab title="历史" name="history" />
</van-tabs>
@@ -76,7 +76,7 @@
</section>
<van-button v-show="!loading" class="submit-button" block :loading="submitting" @click="submitReturn">提交申请</van-button>
<van-popup v-model="showReasonPopup" round position="bottom">
<van-popup v-model:show="showReasonPopup" round position="bottom">
<section class="reason-popup">
<h3>请选择退货原因</h3>
<van-radio-group v-model="selectedReason">
@@ -18,10 +18,10 @@
class="cart-item"
>
<van-checkbox
:value="isItemChecked(item)"
:model-value="isItemChecked(item)"
class="item-check"
checked-color="#ff5b20"
@input="toggleItem(item, $event)"
@update:model-value="toggleItem(item, $event)"
/>
<van-image class="item-thumb" :src="item.image" fit="cover" />
<div class="item-info">
@@ -52,10 +52,10 @@
@submit="handleCheckout"
>
<van-checkbox
:value="isAllChecked"
:model-value="isAllChecked"
:indeterminate="isPartChecked"
checked-color="#ff5b20"
@input="toggleAll"
@update:model-value="toggleAll"
>全选</van-checkbox>
</van-submit-bar>
</section>
@@ -7,10 +7,10 @@
<van-empty v-if="!items.length" description="购物车还是空的" />
<article v-for="item in items" :key="item.cartId" class="edit-item">
<van-checkbox
:value="isItemChecked(item)"
:model-value="isItemChecked(item)"
class="item-check"
checked-color="#ff5b20"
@input="toggleItem(item, $event)"
@update:model-value="toggleItem(item, $event)"
/>
<van-image class="item-thumb" :src="item.image" fit="cover" />
<div class="item-info">
@@ -26,10 +26,10 @@
</section>
<van-submit-bar class="edit-submit" button-text="删除" @submit="remove">
<van-checkbox
:value="isAllChecked"
:model-value="isAllChecked"
:indeterminate="isPartChecked"
checked-color="#ff5b20"
@input="toggleAll"
@update:model-value="toggleAll"
>全选</van-checkbox>
</van-submit-bar>
</main>
@@ -91,7 +91,7 @@
</button>
</footer>
<van-popup v-model="showExchangeShipPopup" round position="bottom">
<van-popup v-model:show="showExchangeShipPopup" round position="bottom">
<section class="action-popup">
<h3>填写换货发货信息</h3>
<van-field v-model="exchangeShipForm.logisticsCompany" label="快递公司" placeholder="请输入快递公司" />
@@ -3,7 +3,7 @@
<van-nav-bar title="商家处理台" left-arrow @click-left="$router.back()" />
<van-pull-refresh v-model="refreshing" class="merchant-refresh" @refresh="onRefresh">
<van-tabs v-model="activeTab" sticky offset-top="46" color="#ff5b20" @change="loadCurrentTab">
<van-tabs v-model:active="activeTab" sticky offset-top="46" color="#ff5b20" @change="loadCurrentTab">
<van-tab title="待发货" name="ship" :badge="tabBadge('ship')">
<section class="list-panel">
<button v-if="orderItems.length" type="button" class="batch-ship-button" @click="quickShipAll">一键发货</button>
@@ -161,7 +161,7 @@
</van-tabs>
</van-pull-refresh>
<van-popup v-model="showShipPopup" round position="bottom">
<van-popup v-model:show="showShipPopup" round position="bottom">
<section class="action-popup">
<h3>填写发货信息</h3>
<van-field v-model="shipForm.crrgBsnNm" label="快递公司" placeholder="请输入快递公司" />
@@ -170,7 +170,7 @@
</section>
</van-popup>
<van-popup v-model="showExchangeShipPopup" round position="bottom">
<van-popup v-model:show="showExchangeShipPopup" round position="bottom">
<section class="action-popup">
<h3>填写换货发货信息</h3>
<van-field v-model="exchangeShipForm.logisticsCompany" label="快递公司" placeholder="请输入快递公司" />
@@ -43,7 +43,7 @@
立即支付 ¥{{ amountText }}
</van-button>
<van-popup v-model="showConfirm" class="pay-popup" round position="bottom">
<van-popup v-model:show="showConfirm" class="pay-popup" round position="bottom">
<article class="pay-panel">
<header>
<van-icon name="cross" @click="showConfirm = false" />
@@ -59,16 +59,16 @@
</div>
</section>
<van-goods-action>
<van-goods-action-icon icon="chat-o" text="客服" dot />
<van-goods-action-icon icon="cart-o" text="购物车" :badge="cartBadge" @click="openCartPopup" />
<van-goods-action-icon icon="star" text="已收藏" color="#ff5000" />
<van-goods-action-button type="warning" text="加入购物车" @click="openSku('cart')" />
<van-goods-action-button type="danger" text="立即购买" @click="openSku('buy')" />
</van-goods-action>
<van-action-bar>
<van-action-bar-icon icon="chat-o" text="客服" dot />
<van-action-bar-icon icon="cart-o" text="购物车" :badge="cartBadge" @click="openCartPopup" />
<van-action-bar-icon icon="star" text="已收藏" color="#ff5000" />
<van-action-bar-button type="warning" text="加入购物车" @click="openSku('cart')" />
<van-action-bar-button type="danger" text="立即购买" @click="openSku('buy')" />
</van-action-bar>
<joyful-sku-popup ref="skuPopup" @add-cart="loadCart" />
<van-popup v-model="showCartPopup" class="cart-popup" position="bottom" round>
<van-popup v-model:show="showCartPopup" class="cart-popup" position="bottom" round>
<header class="cart-popup-head">
<b>购物车</b>
<van-icon name="cross" @click="showCartPopup = false" />
@@ -251,7 +251,7 @@ export default {
}
.product-info {
margin-top: -4px;
margin-top: 12px;
padding: 18px 16px 16px;
}
@@ -1,26 +1,70 @@
<template>
<van-sku
:key="skuKey"
v-model="show"
<van-popup
v-model:show="show"
:class="`sku-popup--${mode}`"
:sku="sku"
:goods="skuGoods"
:goods-id="currentGoods.id"
:initial-sku="initialSku"
:hide-stock="sku.hide_stock"
:show-stepper="false"
:show-add-cart-btn="mode !== 'buy'"
:show-buy-btn="true"
:preview-on-click-image="true"
add-cart-text="加入购物车"
buy-text="立即购买"
@add-cart="onAddCartClicked"
@buy-clicked="onBuyClicked"
/>
class="van-sku-container"
position="bottom"
round
closeable
safe-area-inset-bottom
>
<div class="sku-content">
<div class="van-sku-header">
<div class="van-sku-header__goods-info">
<div class="van-sku__goods-price">
<span class="van-sku__price-symbol">¥</span>
<span class="van-sku__price-num">{{ sku.price }}</span>
</div>
<div class="van-sku__goods-name">{{ skuGoods.title }}</div>
<div class="van-sku__stock">库存 {{ sku.stock_num }} 件</div>
</div>
</div>
<van-cell-group class="van-sku-body" :border="false">
<div v-for="group in sku.tree" :key="group.k_s" class="van-sku-row">
<div class="van-sku-row__title">{{ group.k }}</div>
<div class="sku-options" :class="{ 'sku-options--colors': group.k_s === 's1' }">
<van-button
v-for="option in group.v"
:key="option.id"
size="small"
class="van-sku-row__item"
:class="{ 'van-sku-row__item--active': selectedSku[group.k_s] === option.id, 'sku-color-card': group.k_s === 's1' }"
@click="selectedSku[group.k_s] = option.id"
>
<span v-if="group.k_s === 's1'" class="sku-color-card__picture">
<van-image class="sku-color-card__image" :src="option.imgUrl" width="100%" height="100%" fit="cover" />
<van-icon
v-if="option.previewImgUrl"
name="expand-o"
class="sku-color-card__preview"
role="button"
tabindex="0"
aria-label="预览商品图片"
@click.stop="previewImage(option.previewImgUrl)"
@keydown.enter.stop.prevent="previewImage(option.previewImgUrl)"
@keydown.space.stop.prevent="previewImage(option.previewImgUrl)"
/>
</span>
<span :class="{ 'sku-color-card__name': group.k_s === 's1' }">{{ option.name }}</span>
</van-button>
</div>
</div>
<van-cell title="购买数量" class="sku-quantity" center>
<template #right-icon>
<van-stepper v-model="selectedNum" integer :min="1" :max="sku.stock_num" />
</template>
</van-cell>
</van-cell-group>
<div class="sku-actions">
<van-button v-if="mode !== 'buy'" round type="warning" @click="onAddCartClicked(selectionData())">加入购物车</van-button>
<van-button round type="danger" @click="onBuyClicked(selectionData())">立即购买</van-button>
</div>
</div>
</van-popup>
</template>
<script>
import { Toast } from 'vant'
import { ImagePreview, Toast } from 'vant'
import { useCartStore } from '@/store/cart'
const colorOptions = [
@@ -47,7 +91,8 @@ export default {
data: () => ({
show: false,
mode: 'cart',
skuKey: 0,
selectedSku: {},
selectedNum: 1,
currentGoods: emptyGoods
}),
computed: {
@@ -105,9 +150,19 @@ export default {
open(goods, mode = 'cart') {
this.currentGoods = goods
this.mode = mode
this.skuKey += 1
this.selectedSku = { ...this.initialSku }
this.selectedNum = 1
this.show = true
},
previewImage(image) {
if (image) ImagePreview([image])
},
selectionData() {
return {
selectedSkuComb: this.sku.list.find(item => item.s1 === this.selectedSku.s1 && item.s2 === this.selectedSku.s2),
selectedNum: Math.min(this.sku.stock_num, Math.max(1, Math.floor(Number(this.selectedNum) || 1)))
}
},
getCartPayload(data) {
const selectedSku = data.selectedSkuComb || {}
const selectedColor = colorOptions.find(item => item.id === selectedSku.s1) || colorOptions[0]
@@ -153,14 +208,110 @@ export default {
</script>
<style scoped lang="less">
::v-deep .van-sku-container {
.sku-content {
padding: 15px 15px 0;
}
.sku-options .van-sku-row__item.sku-color-card {
width: 100%;
min-width: 0;
overflow: hidden;
padding: 0;
border: 1px solid transparent;
border-radius: 3px;
background: #f6f7f9;
}
.sku-color-card :deep(.van-button__content),
.sku-color-card :deep(.van-button__text) {
display: block;
width: 100%;
}
.sku-color-card__picture {
position: relative;
display: block;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
line-height: 0;
background: #f1f1f3;
}
.sku-color-card__image {
position: absolute;
inset: 0;
display: block;
}
.sku-color-card__preview {
position: absolute;
top: 3px;
right: 3px;
padding: 2px;
border-radius: 2px;
background: rgba(0, 0, 0, .4);
color: #fff;
font-size: 14px;
}
.sku-color-card__name {
display: block;
padding: 10px 4px;
color: #333;
font-size: 12px;
line-height: 18px;
text-align: center;
}
.sku-color-card.van-sku-row__item--active .sku-color-card__name {
color: #ff5b20;
}
.sku-options,
.sku-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.sku-options.sku-options--colors {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 10px;
}
.sku-options .van-sku-row__item {
height: auto;
min-height: 36px;
padding: 6px 12px;
}
.sku-quantity {
padding: 12px 0;
}
.sku-actions {
padding: 15px 0;
}
.sku-actions .van-button {
flex: 1;
}
.van-sku-container {
max-height: 85vh;
overflow-y: auto;
border-radius: 14px 14px 0 0;
}
.van-sku-container.van-popup--safe-area-inset-bottom {
padding-bottom: env(safe-area-inset-bottom);
}
::v-deep .van-sku-header {
min-height: 96px;
padding: 18px 42px 12px 16px;
padding: 0 30px 15px 0;
}
::v-deep .van-sku-header__img-wrap {
@@ -210,7 +361,7 @@ export default {
}
::v-deep .van-sku-body {
padding: 0 16px;
padding: 0;
}
::v-deep .van-sku-group-container {
@@ -236,7 +387,7 @@ export default {
::v-deep .van-sku-row:not(:first-child) .van-sku-row__item {
height: 31px;
margin: 0 10px 8px 0;
margin: 0;
padding: 0 14px;
border: 0;
border-radius: 4px;
@@ -4,7 +4,7 @@
<main v-else class="orders-page">
<van-nav-bar title="我的订单" left-arrow @click-left="$router.replace('/joyful-selection/profile')" />
<van-tabs
v-model="active"
v-model:active="active"
class="order-tabs"
line-width="18"
line-height="2"
@@ -50,7 +50,7 @@ export default {
this.loadLogs()
this.startListening()
},
beforeDestroy() {
beforeUnmount() {
this.stopListening()
},
methods: {