Browse Source

Merge branch 'master' of http://gitlab.frkj.cc/php/zhjwxt into yuhongzhe

# Conflicts:
#	admin/src/app/lang/zh-cn/customer_resources.customer_resources.json
#	admin/src/app/lang/zh-cn/physical_test.physical_test.json
#	admin/src/app/lang/zh-cn/physical_test.physical_test_edit.json
#	admin/src/app/views/customer_resources/customer_resources.vue
#	admin/src/app/views/physical_test/physical_test.vue
#	admin/src/app/views/physical_test/physical_test_edit.vue
#	niucloud/app/adminapi/controller/customer_resources/CustomerResources.php
#	niucloud/app/adminapi/controller/physical_test/PhysicalTest.php
#	niucloud/app/adminapi/route/physical_test.php
#	niucloud/app/model/physical_test/PhysicalTest.php
#	niucloud/app/service/admin/physical_test/PhysicalTestService.php
yuhongzhe
于宏哲PHP 10 months ago
parent
commit
3350cdb256
  1. 1
      admin/components.d.ts
  2. 58
      admin/package-lock.json
  3. 12
      admin/package.json
  4. 24
      admin/src/App.vue
  5. 106
      admin/src/addon/shop/api/delivery.ts
  6. 60
      admin/src/addon/shop/api/electronic_sheet.ts
  7. 325
      admin/src/addon/shop/api/goods.ts
  8. 231
      admin/src/addon/shop/api/marketing.ts
  9. 77
      admin/src/addon/shop/api/order.ts
  10. 12
      admin/src/addon/shop/api/shop.ts
  11. 25
      admin/src/addon/shop/api/shop_address.ts
  12. 8
      admin/src/addon/shop/api/stat.ts
  13. 68
      admin/src/addon/shop/lang/zh-cn/address.edit.json
  14. 2
      admin/src/addon/shop/lang/zh-cn/address.list.json
  15. 58
      admin/src/addon/shop/lang/zh-cn/common.json
  16. 38
      admin/src/addon/shop/lang/zh-cn/delivery.company.json
  17. 85
      admin/src/addon/shop/lang/zh-cn/delivery.company_edit.json
  18. 20
      admin/src/addon/shop/lang/zh-cn/delivery.config.json
  19. 2
      admin/src/addon/shop/lang/zh-cn/delivery.electronic_sheet.json
  20. 2
      admin/src/addon/shop/lang/zh-cn/delivery.electronic_sheet_config.json
  21. 2
      admin/src/addon/shop/lang/zh-cn/delivery.electronic_sheet_edit.json
  22. 108
      admin/src/addon/shop/lang/zh-cn/delivery.local.json
  23. 38
      admin/src/addon/shop/lang/zh-cn/delivery.search.json
  24. 16
      admin/src/addon/shop/lang/zh-cn/delivery.staff.json
  25. 34
      admin/src/addon/shop/lang/zh-cn/delivery.store.json
  26. 74
      admin/src/addon/shop/lang/zh-cn/delivery.store_edit.json
  27. 22
      admin/src/addon/shop/lang/zh-cn/delivery.template.json
  28. 76
      admin/src/addon/shop/lang/zh-cn/delivery.template_edit.json
  29. 4
      admin/src/addon/shop/lang/zh-cn/goods.attr.json
  30. 2
      admin/src/addon/shop/lang/zh-cn/goods.attr_edit.json
  31. 28
      admin/src/addon/shop/lang/zh-cn/goods.brand_list.json
  32. 50
      admin/src/addon/shop/lang/zh-cn/goods.category.json
  33. 52
      admin/src/addon/shop/lang/zh-cn/goods.category_config.json
  34. 96
      admin/src/addon/shop/lang/zh-cn/goods.evaluate.json
  35. 72
      admin/src/addon/shop/lang/zh-cn/goods.evaluate_edit.json
  36. 2
      admin/src/addon/shop/lang/zh-cn/goods.label_group_list.json
  37. 2
      admin/src/addon/shop/lang/zh-cn/goods.label_list.json
  38. 13
      admin/src/addon/shop/lang/zh-cn/goods.list.json
  39. 30
      admin/src/addon/shop/lang/zh-cn/goods.real_edit.json
  40. 18
      admin/src/addon/shop/lang/zh-cn/goods.service.json
  41. 30
      admin/src/addon/shop/lang/zh-cn/goods.virtual_edit.json
  42. 38
      admin/src/addon/shop/lang/zh-cn/index.index.json
  43. 82
      admin/src/addon/shop/lang/zh-cn/marketing.coupon.add.json
  44. 82
      admin/src/addon/shop/lang/zh-cn/marketing.coupon.edit.json
  45. 90
      admin/src/addon/shop/lang/zh-cn/marketing.coupon.list.json
  46. 72
      admin/src/addon/shop/lang/zh-cn/marketing.discount.add.json
  47. 14
      admin/src/addon/shop/lang/zh-cn/marketing.discount.config.json
  48. 2
      admin/src/addon/shop/lang/zh-cn/marketing.discount.detail.json
  49. 72
      admin/src/addon/shop/lang/zh-cn/marketing.discount.edit.json
  50. 98
      admin/src/addon/shop/lang/zh-cn/marketing.discount.list.json
  51. 124
      admin/src/addon/shop/lang/zh-cn/marketing.exchange.goods_add.json
  52. 123
      admin/src/addon/shop/lang/zh-cn/marketing.exchange.goods_edit.json
  53. 52
      admin/src/addon/shop/lang/zh-cn/marketing.exchange.goods_list.json
  54. 106
      admin/src/addon/shop/lang/zh-cn/marketing.exchange.order_list.json
  55. 72
      admin/src/addon/shop/lang/zh-cn/marketing.manjian.detail.json
  56. 2
      admin/src/addon/shop/lang/zh-cn/marketing.manjian.edit.json
  57. 88
      admin/src/addon/shop/lang/zh-cn/marketing.newcomer.config.json
  58. 110
      admin/src/addon/shop/lang/zh-cn/marketing.newcomer.order_list.json
  59. 48
      admin/src/addon/shop/lang/zh-cn/order.batch_delivery.json
  60. 76
      admin/src/addon/shop/lang/zh-cn/order.config.json
  61. 2
      admin/src/addon/shop/lang/zh-cn/order.detail.json
  62. 78
      admin/src/addon/shop/lang/zh-cn/order.invoice.json
  63. 210
      admin/src/addon/shop/lang/zh-cn/order.refund.json
  64. 2
      admin/src/addon/shop/lang/zh-cn/order.refund_detail.json
  65. 72
      admin/src/addon/shop/lang/zh-cn/stat.goods.json
  66. 726
      admin/src/addon/shop/views/address/edit.vue
  67. 275
      admin/src/addon/shop/views/address/list.vue
  68. 281
      admin/src/addon/shop/views/delivery/company.vue
  69. 626
      admin/src/addon/shop/views/delivery/company_edit.vue
  70. 171
      admin/src/addon/shop/views/delivery/components/delivery-personnel-edit.vue
  71. 248
      admin/src/addon/shop/views/delivery/config.vue
  72. 350
      admin/src/addon/shop/views/delivery/electronic_sheet.vue
  73. 341
      admin/src/addon/shop/views/delivery/electronic_sheet_config.vue
  74. 626
      admin/src/addon/shop/views/delivery/electronic_sheet_edit.vue
  75. 773
      admin/src/addon/shop/views/delivery/local.vue
  76. 260
      admin/src/addon/shop/views/delivery/search.vue
  77. 228
      admin/src/addon/shop/views/delivery/staff.vue
  78. 288
      admin/src/addon/shop/views/delivery/store.vue
  79. 688
      admin/src/addon/shop/views/delivery/store_edit.vue
  80. 256
      admin/src/addon/shop/views/delivery/template.vue
  81. 937
      admin/src/addon/shop/views/delivery/template_edit.vue
  82. 494
      admin/src/addon/shop/views/diy/components/edit-goods-coupon.vue
  83. 742
      admin/src/addon/shop/views/diy/components/edit-goods-list.vue
  84. 1054
      admin/src/addon/shop/views/diy/components/edit-many-goods-list.vue
  85. 211
      admin/src/addon/shop/views/diy/components/edit-shop-exchange-goods.vue
  86. 41
      admin/src/addon/shop/views/diy/components/edit-shop-exchange-info.vue
  87. 281
      admin/src/addon/shop/views/diy/components/edit-shop-goods-ranking.vue
  88. 388
      admin/src/addon/shop/views/diy/components/edit-shop-goods-recommend.vue
  89. 71
      admin/src/addon/shop/views/diy/components/edit-shop-member-info.vue
  90. 609
      admin/src/addon/shop/views/diy/components/edit-shop-newcomer.vue
  91. 205
      admin/src/addon/shop/views/diy/components/edit-shop-order-info.vue
  92. 43
      admin/src/addon/shop/views/diy/components/edit-shop-search.vue
  93. 639
      admin/src/addon/shop/views/diy/components/edit-single-recommend.vue
  94. 444
      admin/src/addon/shop/views/goods/attr.vue
  95. 862
      admin/src/addon/shop/views/goods/attr_edit.vue
  96. 328
      admin/src/addon/shop/views/goods/brand_list.vue
  97. 399
      admin/src/addon/shop/views/goods/category.vue
  98. 439
      admin/src/addon/shop/views/goods/category_config.vue
  99. 197
      admin/src/addon/shop/views/goods/components/brand-edit.vue
  100. 232
      admin/src/addon/shop/views/goods/components/category-edit.vue

1
admin/components.d.ts

@ -10,7 +10,6 @@ declare module '@vue/runtime-core' {
Attachment: typeof import('./src/components/upload-attachment/attachment.vue')['default'] Attachment: typeof import('./src/components/upload-attachment/attachment.vue')['default']
DiyLink: typeof import('./src/components/diy-link/index.vue')['default'] DiyLink: typeof import('./src/components/diy-link/index.vue')['default']
Editor: typeof import('./src/components/editor/index.vue')['default'] Editor: typeof import('./src/components/editor/index.vue')['default']
ElAlert: typeof import('element-plus/es')['ElAlert']
ElAside: typeof import('element-plus/es')['ElAside'] ElAside: typeof import('element-plus/es')['ElAside']
ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']

58
admin/package-lock.json

@ -9,6 +9,11 @@
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "2.0.10", "@element-plus/icons-vue": "2.0.10",
"@fullcalendar/core": "^6.1.17",
"@fullcalendar/daygrid": "^6.1.17",
"@fullcalendar/interaction": "^6.1.17",
"@fullcalendar/timegrid": "^6.1.17",
"@fullcalendar/vue3": "^6.1.17",
"@highlightjs/vue-plugin": "2.1.0", "@highlightjs/vue-plugin": "2.1.0",
"@types/lodash-es": "4.17.6", "@types/lodash-es": "4.17.6",
"@vueuse/core": "9.12.0", "@vueuse/core": "9.12.0",
@ -962,6 +967,50 @@
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.1.6.tgz", "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.1.6.tgz",
"integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A=="
}, },
"node_modules/@fullcalendar/core": {
"version": "6.1.17",
"resolved": "https://registry.npmmirror.com/@fullcalendar/core/-/core-6.1.17.tgz",
"integrity": "sha512-0W7lnIrv18ruJ5zeWBeNZXO8qCWlzxDdp9COFEsZnyNjiEhUVnrW/dPbjRKYpL0edGG0/Lhs0ghp1z/5ekt8ZA==",
"dependencies": {
"preact": "~10.12.1"
}
},
"node_modules/@fullcalendar/daygrid": {
"version": "6.1.17",
"resolved": "https://registry.npmmirror.com/@fullcalendar/daygrid/-/daygrid-6.1.17.tgz",
"integrity": "sha512-K7m+pd7oVJ9fW4h7CLDdDGJbc9szJ1xDU1DZ2ag+7oOo1aCNLv44CehzkkknM6r8EYlOOhgaelxQpKAI4glj7A==",
"peerDependencies": {
"@fullcalendar/core": "~6.1.17"
}
},
"node_modules/@fullcalendar/interaction": {
"version": "6.1.17",
"resolved": "https://registry.npmmirror.com/@fullcalendar/interaction/-/interaction-6.1.17.tgz",
"integrity": "sha512-AudvQvgmJP2FU89wpSulUUjeWv24SuyCx8FzH2WIPVaYg+vDGGYarI7K6PcM3TH7B/CyaBjm5Rqw9lXgnwt5YA==",
"peerDependencies": {
"@fullcalendar/core": "~6.1.17"
}
},
"node_modules/@fullcalendar/timegrid": {
"version": "6.1.17",
"resolved": "https://registry.npmmirror.com/@fullcalendar/timegrid/-/timegrid-6.1.17.tgz",
"integrity": "sha512-K4PlA3L3lclLOs3IX8cvddeiJI9ZVMD7RA9IqaWwbvac771971foc9tFze9YY+Pqesf6S+vhS2dWtEVlERaGlQ==",
"dependencies": {
"@fullcalendar/daygrid": "~6.1.17"
},
"peerDependencies": {
"@fullcalendar/core": "~6.1.17"
}
},
"node_modules/@fullcalendar/vue3": {
"version": "6.1.17",
"resolved": "https://registry.npmmirror.com/@fullcalendar/vue3/-/vue3-6.1.17.tgz",
"integrity": "sha512-0+qi/PK/xCkTQXh2CaeN2AkP+SvQTznPhwBXuIyrtsR0Ua8UpmGEXI+my3qQ6o003r8gPUY2e785ywIyhX2zCA==",
"peerDependencies": {
"@fullcalendar/core": "~6.1.17",
"vue": "^3.0.11"
}
},
"node_modules/@highlightjs/vue-plugin": { "node_modules/@highlightjs/vue-plugin": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmmirror.com/@highlightjs/vue-plugin/-/vue-plugin-2.1.0.tgz", "resolved": "https://registry.npmmirror.com/@highlightjs/vue-plugin/-/vue-plugin-2.1.0.tgz",
@ -4997,6 +5046,15 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true "dev": true
}, },
"node_modules/preact": {
"version": "10.12.1",
"resolved": "https://registry.npmmirror.com/preact/-/preact-10.12.1.tgz",
"integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/prelude-ls": { "node_modules/prelude-ls": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",

12
admin/package.json

@ -6,10 +6,18 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build && node publish.cjs", "build": "vite build && node publish.cjs",
"preview": "vite preview" "preview": "vite preview",
"lint": "eslint .",
"lint:fix": "eslint . --ext .ts --ext .vue --ext .js --fix",
"format": "prettier --write src/**/*.{ts,vue,js,json}"
}, },
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "2.0.10", "@element-plus/icons-vue": "2.0.10",
"@fullcalendar/core": "^6.1.17",
"@fullcalendar/daygrid": "^6.1.17",
"@fullcalendar/interaction": "^6.1.17",
"@fullcalendar/timegrid": "^6.1.17",
"@fullcalendar/vue3": "^6.1.17",
"@highlightjs/vue-plugin": "2.1.0", "@highlightjs/vue-plugin": "2.1.0",
"@types/lodash-es": "4.17.6", "@types/lodash-es": "4.17.6",
"@vueuse/core": "9.12.0", "@vueuse/core": "9.12.0",
@ -55,4 +63,4 @@
"vite": "4.1.0", "vite": "4.1.0",
"vue-tsc": "1.0.24" "vue-tsc": "1.0.24"
} }
} }

24
admin/src/App.vue

@ -1,7 +1,7 @@
<template> <template>
<el-config-provider :locale="locale"> <el-config-provider :locale="locale">
<router-view></router-view> <router-view></router-view>
</el-config-provider> </el-config-provider>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -22,16 +22,20 @@ const locale = computed(() => (systemStore.lang === 'zh-cn' ? zhCn : en))
const toggleDark = useToggle(useDark()) const toggleDark = useToggle(useDark())
watch(route, () => { watch(
useAppStore().$patch(state => { route,
state.route = route () => {
useAppStore().$patch((state) => {
state.route = route
}) })
}, { immediate: true }) },
{ immediate: true }
)
onMounted(() => { onMounted(() => {
// //
toggleDark(systemStore.dark) toggleDark(systemStore.dark)
setThemeColor(systemStore.theme, systemStore.dark ? 'dark' : 'light') setThemeColor(systemStore.theme, systemStore.dark ? 'dark' : 'light')
}) })
</script> </script>

106
admin/src/addon/shop/api/delivery.ts

@ -7,7 +7,7 @@ import request from '@/utils/request'
* @returns * @returns
*/ */
export function getCompanyPageList(params: Record<string, any>) { export function getCompanyPageList(params: Record<string, any>) {
return request.get(`shop/delivery/company`, { params }) return request.get(`shop/delivery/company`, { params })
} }
/** /**
@ -16,7 +16,7 @@ export function getCompanyPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCompanyList(params: Record<string, any>) { export function getCompanyList(params: Record<string, any>) {
return request.get(`shop/delivery/company/list`, { params }) return request.get(`shop/delivery/company/list`, { params })
} }
/** /**
@ -25,7 +25,7 @@ export function getCompanyList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCompanyInfo(company_id: number) { export function getCompanyInfo(company_id: number) {
return request.get(`shop/delivery/company/${ company_id }`); return request.get(`shop/delivery/company/${company_id}`)
} }
/** /**
@ -34,7 +34,10 @@ export function getCompanyInfo(company_id: number) {
* @returns * @returns
*/ */
export function addCompany(params: Record<string, any>) { export function addCompany(params: Record<string, any>) {
return request.post('shop/delivery/company', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/delivery/company', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -43,10 +46,10 @@ export function addCompany(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editCompany(params: Record<string, any>) { export function editCompany(params: Record<string, any>) {
return request.put(`shop/delivery/company/${ params.company_id }`, params, { return request.put(`shop/delivery/company/${params.company_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -55,10 +58,12 @@ export function editCompany(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteCompany(company_id: number) { export function deleteCompany(company_id: number) {
return request.delete(`shop/delivery/company/${ company_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/delivery/company/${company_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/********************************* 运费模版 ***************************************/ /********************************* 运费模版 ***************************************/
/** /**
* *
@ -66,7 +71,7 @@ export function deleteCompany(company_id: number) {
* @returns * @returns
*/ */
export function getShippingTemplatePageList(params: Record<string, any>) { export function getShippingTemplatePageList(params: Record<string, any>) {
return request.get(`shop/shipping/template`, { params }) return request.get(`shop/shipping/template`, { params })
} }
/** /**
@ -75,7 +80,7 @@ export function getShippingTemplatePageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getShippingTemplateList(params: Record<string, any>) { export function getShippingTemplateList(params: Record<string, any>) {
return request.get(`shop/shipping/template/list`, { params }) return request.get(`shop/shipping/template/list`, { params })
} }
/** /**
@ -84,7 +89,7 @@ export function getShippingTemplateList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getShippingTemplateInfo(template_id: number) { export function getShippingTemplateInfo(template_id: number) {
return request.get(`shop/shipping/template/${ template_id }`); return request.get(`shop/shipping/template/${template_id}`)
} }
/** /**
@ -93,7 +98,10 @@ export function getShippingTemplateInfo(template_id: number) {
* @returns * @returns
*/ */
export function addShippingTemplate(params: Record<string, any>) { export function addShippingTemplate(params: Record<string, any>) {
return request.post('shop/shipping/template', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/shipping/template', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -102,10 +110,10 @@ export function addShippingTemplate(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editShippingTemplate(params: Record<string, any>) { export function editShippingTemplate(params: Record<string, any>) {
return request.put(`shop/shipping/template/${ params.template_id }`, params, { return request.put(`shop/shipping/template/${params.template_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -114,13 +122,12 @@ export function editShippingTemplate(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteShippingTemplate(template_id: number) { export function deleteShippingTemplate(template_id: number) {
return request.delete(`shop/shipping/template/${ template_id }`, { return request.delete(`shop/shipping/template/${template_id}`, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/********************************* 自提门店 ***************************************/ /********************************* 自提门店 ***************************************/
/** /**
* *
@ -128,7 +135,7 @@ export function deleteShippingTemplate(template_id: number) {
* @returns * @returns
*/ */
export function getStoreList(params: Record<string, any>) { export function getStoreList(params: Record<string, any>) {
return request.get(`shop/delivery/store`, { params }) return request.get(`shop/delivery/store`, { params })
} }
/** /**
@ -137,7 +144,7 @@ export function getStoreList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getStoreInfo(store_id: number) { export function getStoreInfo(store_id: number) {
return request.get(`shop/delivery/store/${ store_id }`); return request.get(`shop/delivery/store/${store_id}`)
} }
/** /**
@ -146,7 +153,10 @@ export function getStoreInfo(store_id: number) {
* @returns * @returns
*/ */
export function addStore(params: Record<string, any>) { export function addStore(params: Record<string, any>) {
return request.post('shop/delivery/store', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/delivery/store', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -155,10 +165,10 @@ export function addStore(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editStore(params: Record<string, any>) { export function editStore(params: Record<string, any>) {
return request.put(`shop/delivery/store/${ params.store_id }`, params, { return request.put(`shop/delivery/store/${params.store_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -167,7 +177,10 @@ export function editStore(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteStore(store_id: number) { export function deleteStore(store_id: number) {
return request.delete(`shop/delivery/store/${ store_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/delivery/store/${store_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/********************************* 物流查询 ***************************************/ /********************************* 物流查询 ***************************************/
@ -177,7 +190,10 @@ export function deleteStore(store_id: number) {
* @returns * @returns
*/ */
export function setDeliverySearch(params: Record<string, any>) { export function setDeliverySearch(params: Record<string, any>) {
return request.post('shop/delivery/search', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/delivery/search', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -185,7 +201,7 @@ export function setDeliverySearch(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getDeliverySearch() { export function getDeliverySearch() {
return request.get('shop/delivery/search') return request.get('shop/delivery/search')
} }
/** /**
@ -193,7 +209,7 @@ export function getDeliverySearch() {
* @returns * @returns
*/ */
export function getShopDeliveryList() { export function getShopDeliveryList() {
return request.get('shop/delivery/deliveryList') return request.get('shop/delivery/deliveryList')
} }
/** /**
@ -202,7 +218,7 @@ export function getShopDeliveryList() {
* @returns * @returns
*/ */
export function setShopDeliveryConfig(params: Record<string, any>) { export function setShopDeliveryConfig(params: Record<string, any>) {
return request.put(`shop/delivery/setConfig`, params) return request.put(`shop/delivery/setConfig`, params)
} }
/** /**
@ -211,7 +227,7 @@ export function setShopDeliveryConfig(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getShopDelivery(params: Record<string, any>) { export function getShopDelivery(params: Record<string, any>) {
return request.get('shop/delivery/staff', { params }) return request.get('shop/delivery/staff', { params })
} }
/** /**
@ -220,7 +236,7 @@ export function getShopDelivery(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getShopDeliverInfo(staff_id: number) { export function getShopDeliverInfo(staff_id: number) {
return request.get(`shop/delivery/staff/${ staff_id }`); return request.get(`shop/delivery/staff/${staff_id}`)
} }
/** /**
@ -229,7 +245,9 @@ export function getShopDeliverInfo(staff_id: number) {
* @returns * @returns
*/ */
export function addShopDeliver(params: Record<string, any>) { export function addShopDeliver(params: Record<string, any>) {
return request.post('shop/delivery/staff', params, { showSuccessMessage: true }) return request.post('shop/delivery/staff', params, {
showSuccessMessage: true,
})
} }
/** /**
@ -238,7 +256,9 @@ export function addShopDeliver(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editShopDeliver(params: Record<string, any>) { export function editShopDeliver(params: Record<string, any>) {
return request.put(`shop/delivery/staff/${ params.deliver_id }`, params, { showSuccessMessage: true }) return request.put(`shop/delivery/staff/${params.deliver_id}`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -247,7 +267,7 @@ export function editShopDeliver(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteShopDeliver(staff_id: number) { export function deleteShopDeliver(staff_id: number) {
return request.delete(`shop/delivery/staff/${ staff_id }`) return request.delete(`shop/delivery/staff/${staff_id}`)
} }
/** /**
@ -255,7 +275,7 @@ export function deleteShopDeliver(staff_id: number) {
* @returns * @returns
*/ */
export function getLocal() { export function getLocal() {
return request.get('shop/local'); return request.get('shop/local')
} }
/** /**
@ -264,5 +284,5 @@ export function getLocal() {
* @returns * @returns
*/ */
export function setLocal(params: Record<string, any>) { export function setLocal(params: Record<string, any>) {
return request.put('shop/local', params, { showSuccessMessage: true }) return request.put('shop/local', params, { showSuccessMessage: true })
} }

60
admin/src/addon/shop/api/electronic_sheet.ts

@ -6,7 +6,7 @@ import request from '@/utils/request'
* @returns * @returns
*/ */
export function getElectronicSheetPageList(params: Record<string, any>) { export function getElectronicSheetPageList(params: Record<string, any>) {
return request.get(`shop/electronic_sheet`, { params }) return request.get(`shop/electronic_sheet`, { params })
} }
/** /**
@ -15,7 +15,7 @@ export function getElectronicSheetPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getElectronicSheetList(params: Record<string, any>) { export function getElectronicSheetList(params: Record<string, any>) {
return request.get(`shop/electronic_sheet/list`, { params }) return request.get(`shop/electronic_sheet/list`, { params })
} }
/** /**
@ -24,7 +24,7 @@ export function getElectronicSheetList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getElectronicSheetInfo(id: number) { export function getElectronicSheetInfo(id: number) {
return request.get(`shop/electronic_sheet/${ id }`); return request.get(`shop/electronic_sheet/${id}`)
} }
/** /**
@ -33,10 +33,10 @@ export function getElectronicSheetInfo(id: number) {
* @returns * @returns
*/ */
export function addElectronicSheet(params: Record<string, any>) { export function addElectronicSheet(params: Record<string, any>) {
return request.post('shop/electronic_sheet', params, { return request.post('shop/electronic_sheet', params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -45,10 +45,10 @@ export function addElectronicSheet(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editElectronicSheet(params: Record<string, any>) { export function editElectronicSheet(params: Record<string, any>) {
return request.put(`shop/electronic_sheet/${ params.id }`, params, { return request.put(`shop/electronic_sheet/${params.id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -57,10 +57,10 @@ export function editElectronicSheet(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteElectronicSheet(id: number) { export function deleteElectronicSheet(id: number) {
return request.delete(`shop/electronic_sheet/${ id }`, { return request.delete(`shop/electronic_sheet/${id}`, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -69,10 +69,10 @@ export function deleteElectronicSheet(id: number) {
* @returns * @returns
*/ */
export function setDefaultElectronicSheet(params: Record<string, any>) { export function setDefaultElectronicSheet(params: Record<string, any>) {
return request.put(`shop/electronic_sheet/setDefault/${ params.id }`, params, { return request.put(`shop/electronic_sheet/setDefault/${params.id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -81,10 +81,10 @@ export function setDefaultElectronicSheet(params: Record<string, any>) {
* @returns * @returns
*/ */
export function setElectronicSheetConfig(params: Record<string, any>) { export function setElectronicSheetConfig(params: Record<string, any>) {
return request.post('shop/electronic_sheet/config', params, { return request.post('shop/electronic_sheet/config', params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -92,7 +92,7 @@ export function setElectronicSheetConfig(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getElectronicSheetConfig() { export function getElectronicSheetConfig() {
return request.get(`shop/electronic_sheet/config`) return request.get(`shop/electronic_sheet/config`)
} }
/** /**
@ -100,7 +100,7 @@ export function getElectronicSheetConfig() {
* @returns * @returns
*/ */
export function getElectronicSheetPayType() { export function getElectronicSheetPayType() {
return request.get(`shop/electronic_sheet/paytype`) return request.get(`shop/electronic_sheet/paytype`)
} }
/** /**
@ -109,8 +109,8 @@ export function getElectronicSheetPayType() {
* @returns * @returns
*/ */
export function printElectronicSheet(params: Record<string, any>) { export function printElectronicSheet(params: Record<string, any>) {
return request.post('shop/electronic_sheet/print', params, { return request.post('shop/electronic_sheet/print', params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }

325
admin/src/addon/shop/api/goods.ts

@ -6,7 +6,7 @@ import request from '@/utils/request'
* @returns * @returns
*/ */
export function getGoodsPageList(params: Record<string, any>) { export function getGoodsPageList(params: Record<string, any>) {
return request.get(`shop/goods`, { params }) return request.get(`shop/goods`, { params })
} }
/** /**
@ -15,7 +15,7 @@ export function getGoodsPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsInfo(goods_id: number) { export function getGoodsInfo(goods_id: number) {
return request.get(`shop/goods/${ goods_id }`); return request.get(`shop/goods/${goods_id}`)
} }
/** /**
@ -24,7 +24,10 @@ export function getGoodsInfo(goods_id: number) {
* @returns * @returns
*/ */
export function addGoods(params: Record<string, any>) { export function addGoods(params: Record<string, any>) {
return request.post('shop/goods', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -32,7 +35,10 @@ export function addGoods(params: Record<string, any>) {
* @param params * @param params
*/ */
export function editGoods(params: Record<string, any>) { export function editGoods(params: Record<string, any>) {
return request.put(`shop/goods/${ params.goods_id }`, params, { showErrorMessage: true, showSuccessMessage: true }) return request.put(`shop/goods/${params.goods_id}`, params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -40,7 +46,7 @@ export function editGoods(params: Record<string, any>) {
* @param params * @param params
*/ */
export function getGoodsInit(params: Record<string, any>) { export function getGoodsInit(params: Record<string, any>) {
return request.get(`shop/goods/init`, { params }); return request.get(`shop/goods/init`, { params })
} }
/** /**
@ -49,7 +55,10 @@ export function getGoodsInit(params: Record<string, any>) {
* @returns * @returns
*/ */
export function addVirtualGoods(params: Record<string, any>) { export function addVirtualGoods(params: Record<string, any>) {
return request.post('shop/goods/virtual', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods/virtual', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -57,10 +66,10 @@ export function addVirtualGoods(params: Record<string, any>) {
* @param params * @param params
*/ */
export function editVirtualGoods(params: Record<string, any>) { export function editVirtualGoods(params: Record<string, any>) {
return request.put(`shop/goods/virtual/${ params.goods_id }`, params, { return request.put(`shop/goods/virtual/${params.goods_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -68,7 +77,7 @@ export function editVirtualGoods(params: Record<string, any>) {
* @param params * @param params
*/ */
export function getVirtualGoodsInit(params: Record<string, any>) { export function getVirtualGoodsInit(params: Record<string, any>) {
return request.get(`shop/goods/virtual/init`, { params }); return request.get(`shop/goods/virtual/init`, { params })
} }
/** /**
@ -77,7 +86,10 @@ export function getVirtualGoodsInit(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteGoods(params: Record<string, any>) { export function deleteGoods(params: Record<string, any>) {
return request.put(`shop/goods/delete`, params, { showErrorMessage: true, showSuccessMessage: true }) return request.put(`shop/goods/delete`, params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -86,7 +98,7 @@ export function deleteGoods(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getRecycleGoodsPageList(params: Record<string, any>) { export function getRecycleGoodsPageList(params: Record<string, any>) {
return request.get(`shop/goods/recycle`, { params }) return request.get(`shop/goods/recycle`, { params })
} }
/** /**
@ -95,7 +107,10 @@ export function getRecycleGoodsPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function recycleGoods(params: Record<string, any>) { export function recycleGoods(params: Record<string, any>) {
return request.put(`shop/goods/recycle`, params, { showErrorMessage: true, showSuccessMessage: true }) return request.put(`shop/goods/recycle`, params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -103,7 +118,7 @@ export function recycleGoods(params: Record<string, any>) {
* @param params * @param params
*/ */
export function editGoodsSort(params: Record<string, any>) { export function editGoodsSort(params: Record<string, any>) {
return request.put(`shop/goods/sort`, params, { showSuccessMessage: true }) return request.put(`shop/goods/sort`, params, { showSuccessMessage: true })
} }
/** /**
@ -111,7 +126,7 @@ export function editGoodsSort(params: Record<string, any>) {
* @param params * @param params
*/ */
export function editGoodsStatus(params: Record<string, any>) { export function editGoodsStatus(params: Record<string, any>) {
return request.put(`shop/goods/status`, params, { showSuccessMessage: true }) return request.put(`shop/goods/status`, params, { showSuccessMessage: true })
} }
/** /**
@ -119,7 +134,9 @@ export function editGoodsStatus(params: Record<string, any>) {
* @param params * @param params
*/ */
export function copyGoods(params: Record<string, any>) { export function copyGoods(params: Record<string, any>) {
return request.put(`shop/goods/copy/${ params.goods_id }`, params, { showSuccessMessage: true }) return request.put(`shop/goods/copy/${params.goods_id}`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -128,7 +145,7 @@ export function copyGoods(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsSelectPageList(params: Record<string, any>) { export function getGoodsSelectPageList(params: Record<string, any>) {
return request.get(`shop/goods/select`, { params }) return request.get(`shop/goods/select`, { params })
} }
/** /**
@ -137,7 +154,7 @@ export function getGoodsSelectPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsSkuList(params: Record<string, any>) { export function getGoodsSkuList(params: Record<string, any>) {
return request.get(`shop/goods/sku`, { params }) return request.get(`shop/goods/sku`, { params })
} }
/** /**
@ -146,7 +163,7 @@ export function getGoodsSkuList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsSkuNoPageList(params: Record<string, any>) { export function getGoodsSkuNoPageList(params: Record<string, any>) {
return request.get(`shop/goods/selectgoodssku`, { params }) return request.get(`shop/goods/selectgoodssku`, { params })
} }
/** /**
@ -154,7 +171,7 @@ export function getGoodsSkuNoPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getActiveGoodsCount(params: Record<string, any>) { export function getActiveGoodsCount(params: Record<string, any>) {
return request.get(`shop/goods/active/count`, { params }) return request.get(`shop/goods/active/count`, { params })
} }
/** /**
@ -163,7 +180,9 @@ export function getActiveGoodsCount(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editGoodsListStock(params: Record<string, any>) { export function editGoodsListStock(params: Record<string, any>) {
return request.put(`shop/goods/sku/stock`, params, { showSuccessMessage: true }) return request.put(`shop/goods/sku/stock`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -172,7 +191,9 @@ export function editGoodsListStock(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editGoodsListPrice(params: Record<string, any>) { export function editGoodsListPrice(params: Record<string, any>) {
return request.put(`shop/goods/sku/price`, params, { showSuccessMessage: true }) return request.put(`shop/goods/sku/price`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -181,7 +202,9 @@ export function editGoodsListPrice(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editGoodsListMemberPrice(params: Record<string, any>) { export function editGoodsListMemberPrice(params: Record<string, any>) {
return request.put(`shop/goods/sku/member_price`, params, { showSuccessMessage: true }) return request.put(`shop/goods/sku/member_price`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -189,7 +212,7 @@ export function editGoodsListMemberPrice(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsType() { export function getGoodsType() {
return request.get(`shop/goods/type`); return request.get(`shop/goods/type`)
} }
/** /**
@ -198,7 +221,7 @@ export function getGoodsType() {
* @returns * @returns
*/ */
export function getLabelPageList(params: Record<string, any>) { export function getLabelPageList(params: Record<string, any>) {
return request.get(`shop/goods/label`, { params }) return request.get(`shop/goods/label`, { params })
} }
/** /**
@ -207,7 +230,7 @@ export function getLabelPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getLabelList(params: Record<string, any>) { export function getLabelList(params: Record<string, any>) {
return request.get(`shop/goods/label/list`, { params }) return request.get(`shop/goods/label/list`, { params })
} }
/** /**
@ -216,7 +239,7 @@ export function getLabelList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getLabelInfo(label_id: number) { export function getLabelInfo(label_id: number) {
return request.get(`shop/goods/label/${ label_id }`); return request.get(`shop/goods/label/${label_id}`)
} }
/** /**
@ -225,7 +248,10 @@ export function getLabelInfo(label_id: number) {
* @returns * @returns
*/ */
export function addLabel(params: Record<string, any>) { export function addLabel(params: Record<string, any>) {
return request.post('shop/goods/label', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods/label', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -234,10 +260,10 @@ export function addLabel(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editLabel(params: Record<string, any>) { export function editLabel(params: Record<string, any>) {
return request.put(`shop/goods/label/${ params.label_id }`, params, { return request.put(`shop/goods/label/${params.label_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -245,7 +271,9 @@ export function editLabel(params: Record<string, any>) {
* @param params * @param params
*/ */
export function modifyLabelStatus(params: Record<string, any>) { export function modifyLabelStatus(params: Record<string, any>) {
return request.put(`shop/goods/label/status`, params, { showSuccessMessage: true }) return request.put(`shop/goods/label/status`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -254,7 +282,10 @@ export function modifyLabelStatus(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteLabel(label_id: number) { export function deleteLabel(label_id: number) {
return request.delete(`shop/goods/label/${ label_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/goods/label/${label_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -262,7 +293,9 @@ export function deleteLabel(label_id: number) {
* @param params * @param params
*/ */
export function modifyLabelSort(params: Record<string, any>) { export function modifyLabelSort(params: Record<string, any>) {
return request.put(`shop/goods/label/sort`, params, { showSuccessMessage: true }) return request.put(`shop/goods/label/sort`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -271,7 +304,7 @@ export function modifyLabelSort(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getLabelGroupPageList(params: Record<string, any>) { export function getLabelGroupPageList(params: Record<string, any>) {
return request.get(`shop/goods/label/group`, { params }) return request.get(`shop/goods/label/group`, { params })
} }
/** /**
@ -280,7 +313,7 @@ export function getLabelGroupPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getLabelGroupList(params: Record<string, any>) { export function getLabelGroupList(params: Record<string, any>) {
return request.get(`shop/goods/label/group/list`, { params }) return request.get(`shop/goods/label/group/list`, { params })
} }
/** /**
@ -289,7 +322,7 @@ export function getLabelGroupList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getLabelGroupInfo(label_id: number) { export function getLabelGroupInfo(label_id: number) {
return request.get(`shop/goods/label/group/${ label_id }`); return request.get(`shop/goods/label/group/${label_id}`)
} }
/** /**
@ -298,7 +331,10 @@ export function getLabelGroupInfo(label_id: number) {
* @returns * @returns
*/ */
export function addLabelGroup(params: Record<string, any>) { export function addLabelGroup(params: Record<string, any>) {
return request.post('shop/goods/label/group', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods/label/group', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -307,10 +343,10 @@ export function addLabelGroup(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editLabelGroup(params: Record<string, any>) { export function editLabelGroup(params: Record<string, any>) {
return request.put(`shop/goods/label/group/${ params.group_id }`, params, { return request.put(`shop/goods/label/group/${params.group_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -319,7 +355,10 @@ export function editLabelGroup(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteLabelGroup(group_id: number) { export function deleteLabelGroup(group_id: number) {
return request.delete(`shop/goods/label/group/${ group_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/goods/label/group/${group_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -327,7 +366,9 @@ export function deleteLabelGroup(group_id: number) {
* @param params * @param params
*/ */
export function modifyLabelGroupSort(params: Record<string, any>) { export function modifyLabelGroupSort(params: Record<string, any>) {
return request.put(`shop/goods/label/group/sort`, params, { showSuccessMessage: true }) return request.put(`shop/goods/label/group/sort`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -336,7 +377,7 @@ export function modifyLabelGroupSort(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getBrandPageList(params: Record<string, any>) { export function getBrandPageList(params: Record<string, any>) {
return request.get(`shop/goods/brand`, { params }) return request.get(`shop/goods/brand`, { params })
} }
/** /**
@ -345,7 +386,7 @@ export function getBrandPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getBrandList(params: Record<string, any>) { export function getBrandList(params: Record<string, any>) {
return request.get(`shop/goods/brand/list`, { params }) return request.get(`shop/goods/brand/list`, { params })
} }
/** /**
@ -354,7 +395,7 @@ export function getBrandList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getBrandInfo(brand_id: number) { export function getBrandInfo(brand_id: number) {
return request.get(`shop/goods/brand/${ brand_id }`); return request.get(`shop/goods/brand/${brand_id}`)
} }
/** /**
@ -363,7 +404,10 @@ export function getBrandInfo(brand_id: number) {
* @returns * @returns
*/ */
export function addBrand(params: Record<string, any>) { export function addBrand(params: Record<string, any>) {
return request.post('shop/goods/brand', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods/brand', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -372,10 +416,10 @@ export function addBrand(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editBrand(params: Record<string, any>) { export function editBrand(params: Record<string, any>) {
return request.put(`shop/goods/brand/${ params.brand_id }`, params, { return request.put(`shop/goods/brand/${params.brand_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -383,7 +427,9 @@ export function editBrand(params: Record<string, any>) {
* @param params * @param params
*/ */
export function modifyBrandSort(params: Record<string, any>) { export function modifyBrandSort(params: Record<string, any>) {
return request.put(`shop/goods/brand/sort`, params, { showSuccessMessage: true }) return request.put(`shop/goods/brand/sort`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -392,7 +438,10 @@ export function modifyBrandSort(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteBrand(brand_id: number) { export function deleteBrand(brand_id: number) {
return request.delete(`shop/goods/brand/${ brand_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/goods/brand/${brand_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -401,7 +450,7 @@ export function deleteBrand(brand_id: number) {
* @returns * @returns
*/ */
export function getServePageList(params: Record<string, any>) { export function getServePageList(params: Record<string, any>) {
return request.get(`shop/goods/service`, { params }) return request.get(`shop/goods/service`, { params })
} }
/** /**
@ -410,7 +459,7 @@ export function getServePageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getServeList(params: Record<string, any>) { export function getServeList(params: Record<string, any>) {
return request.get(`shop/goods/service/list`, { params }) return request.get(`shop/goods/service/list`, { params })
} }
/** /**
@ -419,7 +468,7 @@ export function getServeList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getServeInfo(service_id: number) { export function getServeInfo(service_id: number) {
return request.get(`shop/goods/service/${ service_id }`); return request.get(`shop/goods/service/${service_id}`)
} }
/** /**
@ -428,7 +477,10 @@ export function getServeInfo(service_id: number) {
* @returns * @returns
*/ */
export function addServe(params: Record<string, any>) { export function addServe(params: Record<string, any>) {
return request.post('shop/goods/service', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods/service', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -437,10 +489,10 @@ export function addServe(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editServe(params: Record<string, any>) { export function editServe(params: Record<string, any>) {
return request.put(`shop/goods/service/${ params.service_id }`, params, { return request.put(`shop/goods/service/${params.service_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -449,7 +501,10 @@ export function editServe(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteServe(service_id: number) { export function deleteServe(service_id: number) {
return request.delete(`shop/goods/service/${ service_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/goods/service/${service_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -457,7 +512,7 @@ export function deleteServe(service_id: number) {
* @returns * @returns
*/ */
export function getCategoryTree() { export function getCategoryTree() {
return request.get(`shop/goods/tree`) return request.get(`shop/goods/tree`)
} }
/** /**
@ -466,7 +521,7 @@ export function getCategoryTree() {
* @returns * @returns
*/ */
export function getCategoryList(params: Record<string, any>) { export function getCategoryList(params: Record<string, any>) {
return request.get(`shop/goods/category`, { params }) return request.get(`shop/goods/category`, { params })
} }
/** /**
@ -475,7 +530,7 @@ export function getCategoryList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCategoryInfo(category_id: number) { export function getCategoryInfo(category_id: number) {
return request.get(`shop/goods/category/${ category_id }`); return request.get(`shop/goods/category/${category_id}`)
} }
/** /**
@ -484,7 +539,10 @@ export function getCategoryInfo(category_id: number) {
* @returns * @returns
*/ */
export function addCategory(params: Record<string, any>) { export function addCategory(params: Record<string, any>) {
return request.post('shop/goods/category', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods/category', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -493,10 +551,10 @@ export function addCategory(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editCategory(params: Record<string, any>) { export function editCategory(params: Record<string, any>) {
return request.put(`shop/goods/category/${ params.category_id }`, params, { return request.put(`shop/goods/category/${params.category_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -505,7 +563,10 @@ export function editCategory(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteCategory(category_id: number) { export function deleteCategory(category_id: number) {
return request.delete(`shop/goods/category/${ category_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/goods/category/${category_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -514,7 +575,10 @@ export function deleteCategory(category_id: number) {
* @returns * @returns
*/ */
export function updateCategory(params: Record<string, any>) { export function updateCategory(params: Record<string, any>) {
return request.post(`shop/goods/category/update`, params, { showErrorMessage: true, showSuccessMessage: true }) return request.post(`shop/goods/category/update`, params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -523,7 +587,10 @@ export function updateCategory(params: Record<string, any>) {
* @returns * @returns
*/ */
export function setCategoryConfig(params: Record<string, any>) { export function setCategoryConfig(params: Record<string, any>) {
return request.post(`shop/goods/category/config`, params, { showErrorMessage: true, showSuccessMessage: true }) return request.post(`shop/goods/category/config`, params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -531,7 +598,7 @@ export function setCategoryConfig(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCategoryConfig() { export function getCategoryConfig() {
return request.get(`shop/goods/category/config`); return request.get(`shop/goods/category/config`)
} }
/** /**
@ -539,7 +606,7 @@ export function getCategoryConfig() {
* @returns * @returns
*/ */
export function getCategoryTreeComponents() { export function getCategoryTreeComponents() {
return request.get(`shop/goods/category/components`) return request.get(`shop/goods/category/components`)
} }
/** /**
@ -548,7 +615,7 @@ export function getCategoryTreeComponents() {
* @returns * @returns
*/ */
export function getSupplierList(params: Record<string, any>) { export function getSupplierList(params: Record<string, any>) {
return request.get(`shop_supplier/supplier/list`, { params }) return request.get(`shop_supplier/supplier/list`, { params })
} }
/** /**
@ -557,7 +624,7 @@ export function getSupplierList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getEvaluateList(params: Record<string, any>) { export function getEvaluateList(params: Record<string, any>) {
return request.get(`shop/goods/evaluate`, { params }) return request.get(`shop/goods/evaluate`, { params })
} }
/** /**
@ -566,7 +633,10 @@ export function getEvaluateList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function addEvaluate(params: Record<string, any>) { export function addEvaluate(params: Record<string, any>) {
return request.post('shop/goods/evaluate', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods/evaluate', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -575,7 +645,10 @@ export function addEvaluate(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteEvaluate(evaluate_id: number) { export function deleteEvaluate(evaluate_id: number) {
return request.delete(`shop/goods/evaluate/${ evaluate_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/goods/evaluate/${evaluate_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -584,10 +657,10 @@ export function deleteEvaluate(evaluate_id: number) {
* @returns * @returns
*/ */
export function adoptEvaluate(evaluate_id: number) { export function adoptEvaluate(evaluate_id: number) {
return request.put(`shop/goods/evaluate/adopt/${ evaluate_id }`, { return request.put(`shop/goods/evaluate/adopt/${evaluate_id}`, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -596,10 +669,10 @@ export function adoptEvaluate(evaluate_id: number) {
* @returns * @returns
*/ */
export function refuseEvaluate(evaluate_id: number) { export function refuseEvaluate(evaluate_id: number) {
return request.put(`shop/goods/evaluate/refuse/${ evaluate_id }`, { return request.put(`shop/goods/evaluate/refuse/${evaluate_id}`, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -608,10 +681,14 @@ export function refuseEvaluate(evaluate_id: number) {
* @returns * @returns
*/ */
export function replyEvaluate(params: Record<string, any>) { export function replyEvaluate(params: Record<string, any>) {
return request.put(`shop/goods/evaluate/reply/${ params.evaluate_id }`, params, { return request.put(
showErrorMessage: true, `shop/goods/evaluate/reply/${params.evaluate_id}`,
showSuccessMessage: true params,
}) {
showErrorMessage: true,
showSuccessMessage: true,
}
)
} }
/** /**
@ -620,10 +697,10 @@ export function replyEvaluate(params: Record<string, any>) {
* @returns * @returns
*/ */
export function toppingEvaluate(evaluate_id: number) { export function toppingEvaluate(evaluate_id: number) {
return request.put(`shop/goods/evaluate/topping/${ evaluate_id }`, { return request.put(`shop/goods/evaluate/topping/${evaluate_id}`, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -632,10 +709,10 @@ export function toppingEvaluate(evaluate_id: number) {
* @returns * @returns
*/ */
export function cancelToppingEvaluate(evaluate_id: number) { export function cancelToppingEvaluate(evaluate_id: number) {
return request.put(`shop/goods/evaluate/cancel_topping/${ evaluate_id }`, { return request.put(`shop/goods/evaluate/cancel_topping/${evaluate_id}`, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -644,7 +721,7 @@ export function cancelToppingEvaluate(evaluate_id: number) {
* @returns * @returns
*/ */
export function getAttrPageList(params: Record<string, any>) { export function getAttrPageList(params: Record<string, any>) {
return request.get(`shop/goods/attr`, { params }) return request.get(`shop/goods/attr`, { params })
} }
/** /**
@ -653,7 +730,7 @@ export function getAttrPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getAttrList(params: Record<string, any>) { export function getAttrList(params: Record<string, any>) {
return request.get(`shop/goods/attr/list`, { params }) return request.get(`shop/goods/attr/list`, { params })
} }
/** /**
@ -662,7 +739,7 @@ export function getAttrList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getAttrInfo(attr_id: number) { export function getAttrInfo(attr_id: number) {
return request.get(`shop/goods/attr/${ attr_id }`); return request.get(`shop/goods/attr/${attr_id}`)
} }
/** /**
@ -671,7 +748,10 @@ export function getAttrInfo(attr_id: number) {
* @returns * @returns
*/ */
export function addAttr(params: Record<string, any>) { export function addAttr(params: Record<string, any>) {
return request.post('shop/goods/attr', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/goods/attr', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -680,10 +760,10 @@ export function addAttr(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editAttr(params: Record<string, any>) { export function editAttr(params: Record<string, any>) {
return request.put(`shop/goods/attr/${ params.attr_id }`, params, { return request.put(`shop/goods/attr/${params.attr_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -692,7 +772,10 @@ export function editAttr(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteAttr(attr_id: number) { export function deleteAttr(attr_id: number) {
return request.delete(`shop/goods/attr/${ attr_id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/goods/attr/${attr_id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -700,7 +783,9 @@ export function deleteAttr(attr_id: number) {
* @param params * @param params
*/ */
export function modifyAttrSort(params: Record<string, any>) { export function modifyAttrSort(params: Record<string, any>) {
return request.put(`shop/goods/attr/sort`, params, { showSuccessMessage: true }) return request.put(`shop/goods/attr/sort`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -708,7 +793,9 @@ export function modifyAttrSort(params: Record<string, any>) {
* @param params * @param params
*/ */
export function modifyAttrName(params: Record<string, any>) { export function modifyAttrName(params: Record<string, any>) {
return request.put(`shop/goods/attr/attr_name`, params, { showSuccessMessage: true }) return request.put(`shop/goods/attr/attr_name`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -716,7 +803,9 @@ export function modifyAttrName(params: Record<string, any>) {
* @param params * @param params
*/ */
export function modifyAttrValue(params: Record<string, any>) { export function modifyAttrValue(params: Record<string, any>) {
return request.put(`shop/goods/attr/attr_value`, params, { showSuccessMessage: true }) return request.put(`shop/goods/attr/attr_value`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -724,7 +813,7 @@ export function modifyAttrValue(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsBatchSetDict() { export function getGoodsBatchSetDict() {
return request.get(`shop/goods/batchSet/dict`) return request.get(`shop/goods/batchSet/dict`)
} }
/** /**
@ -732,5 +821,7 @@ export function getGoodsBatchSetDict() {
* @param params * @param params
*/ */
export function goodsBatchSet(params: Record<string, any>) { export function goodsBatchSet(params: Record<string, any>) {
return request.put(`shop/goods/batchSet`, params, { showSuccessMessage: true }) return request.put(`shop/goods/batchSet`, params, {
} showSuccessMessage: true,
})
}

231
admin/src/addon/shop/api/marketing.ts

@ -6,7 +6,7 @@ import request from '@/utils/request'
* @returns * @returns
*/ */
export function getMarketingIndex(params: Record<string, any>) { export function getMarketingIndex(params: Record<string, any>) {
return request.get(`shop/marketing`, { params }) return request.get(`shop/marketing`, { params })
} }
/** /**
@ -15,7 +15,7 @@ export function getMarketingIndex(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsCategoryList(params: Record<string, any>) { export function getGoodsCategoryList(params: Record<string, any>) {
return request.get(`shop/goods/coupon/init`, { params }) return request.get(`shop/goods/coupon/init`, { params })
} }
/** /**
@ -24,7 +24,10 @@ export function getGoodsCategoryList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function addCoupon(params: Record<string, any>) { export function addCoupon(params: Record<string, any>) {
return request.post(`shop/goods/coupon`, params, { showErrorMessage: true, showSuccessMessage: true }) return request.post(`shop/goods/coupon`, params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -32,7 +35,7 @@ export function addCoupon(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCouponStatusList() { export function getCouponStatusList() {
return request.get(`shop/goods/coupon/status`) return request.get(`shop/goods/coupon/status`)
} }
/** /**
@ -41,7 +44,7 @@ export function getCouponStatusList() {
* @returns * @returns
*/ */
export function getCouponList(params: Record<string, any>) { export function getCouponList(params: Record<string, any>) {
return request.get(`shop/goods/coupon`, { params }) return request.get(`shop/goods/coupon`, { params })
} }
/** /**
@ -50,7 +53,7 @@ export function getCouponList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCouponSelectList(params: Record<string, any>) { export function getCouponSelectList(params: Record<string, any>) {
return request.get(`shop/goods/coupon/select`, { params }) return request.get(`shop/goods/coupon/select`, { params })
} }
/** /**
@ -59,7 +62,7 @@ export function getCouponSelectList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCouponRecords(params: Record<string, any>) { export function getCouponRecords(params: Record<string, any>) {
return request.get(`shop/goods/coupon/records`, { params }); return request.get(`shop/goods/coupon/records`, { params })
} }
/** /**
@ -68,7 +71,7 @@ export function getCouponRecords(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getCouponInfo(id: number) { export function getCouponInfo(id: number) {
return request.get(`shop/goods/coupon/detail/${ id }`); return request.get(`shop/goods/coupon/detail/${id}`)
} }
/** /**
@ -77,7 +80,9 @@ export function getCouponInfo(id: number) {
* @returns * @returns
*/ */
export function editCouponStatus(params: Record<string, any>) { export function editCouponStatus(params: Record<string, any>) {
return request.put(`shop/goods/coupon/setstatus/${ params.status }`, params, { showSuccessMessage: true }) return request.put(`shop/goods/coupon/setstatus/${params.status}`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -86,10 +91,10 @@ export function editCouponStatus(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editCoupon(params: Record<string, any>) { export function editCoupon(params: Record<string, any>) {
return request.put(`shop/goods/coupon/edit/${ params.id }`, params, { return request.put(`shop/goods/coupon/edit/${params.id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -98,7 +103,7 @@ export function editCoupon(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteCoupon(id: number) { export function deleteCoupon(id: number) {
return request.delete(`shop/goods/coupon/${ id }`, { showSuccessMessage: true }) return request.delete(`shop/goods/coupon/${id}`, { showSuccessMessage: true })
} }
/** /**
@ -107,7 +112,9 @@ export function deleteCoupon(id: number) {
* @returns * @returns
*/ */
export function closeCoupon(id: number) { export function closeCoupon(id: number) {
return request.put(`shop/goods/coupon/invalid/${ id }`, { showSuccessMessage: true }) return request.put(`shop/goods/coupon/invalid/${id}`, {
showSuccessMessage: true,
})
} }
/** /**
@ -116,7 +123,7 @@ export function closeCoupon(id: number) {
* @returns * @returns
*/ */
export function getSelectedCouponList(params: Record<string, any>) { export function getSelectedCouponList(params: Record<string, any>) {
return request.get(`shop/goods/coupon/selected`, { params }) return request.get(`shop/goods/coupon/selected`, { params })
} }
/************ 限时折扣 ****************/ /************ 限时折扣 ****************/
@ -126,7 +133,7 @@ export function getSelectedCouponList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getActiveDiscountPageList(params: Record<string, any>) { export function getActiveDiscountPageList(params: Record<string, any>) {
return request.get(`shop/active/discount`, { params }) return request.get(`shop/active/discount`, { params })
} }
/** /**
@ -134,7 +141,7 @@ export function getActiveDiscountPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getActiveDiscountStatusList() { export function getActiveDiscountStatusList() {
return request.get(`shop/active/status`) return request.get(`shop/active/status`)
} }
/** /**
@ -143,7 +150,7 @@ export function getActiveDiscountStatusList() {
* @returns * @returns
*/ */
export function getActiveDiscountInfo(active_id: number) { export function getActiveDiscountInfo(active_id: number) {
return request.get(`shop/active/discount/${ active_id }`); return request.get(`shop/active/discount/${active_id}`)
} }
/** /**
@ -152,7 +159,10 @@ export function getActiveDiscountInfo(active_id: number) {
* @returns * @returns
*/ */
export function addActiveDiscount(params: Record<string, any>) { export function addActiveDiscount(params: Record<string, any>) {
return request.post('shop/active/discount', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/active/discount', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -161,10 +171,10 @@ export function addActiveDiscount(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editActiveDiscount(params: Record<string, any>) { export function editActiveDiscount(params: Record<string, any>) {
return request.put(`shop/active/discount/${ params.active_id }`, params, { return request.put(`shop/active/discount/${params.active_id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -173,10 +183,14 @@ export function editActiveDiscount(params: Record<string, any>) {
* @returns * @returns
*/ */
export function closeActiveDiscount(active_id: number) { export function closeActiveDiscount(active_id: number) {
return request.put(`shop/active/discount/close/${ active_id }`, {}, { return request.put(
showErrorMessage: true, `shop/active/discount/close/${active_id}`,
showSuccessMessage: true {},
}) {
showErrorMessage: true,
showSuccessMessage: true,
}
)
} }
/** /**
@ -185,7 +199,9 @@ export function closeActiveDiscount(active_id: number) {
* @returns * @returns
*/ */
export function deleteActiveDiscount(active_id: number) { export function deleteActiveDiscount(active_id: number) {
return request.delete(`shop/active/discount/${ active_id }`, { showSuccessMessage: true }) return request.delete(`shop/active/discount/${active_id}`, {
showSuccessMessage: true,
})
} }
/** /**
@ -194,7 +210,9 @@ export function deleteActiveDiscount(active_id: number) {
* @returns * @returns
*/ */
export function getActiveDiscountGoodsPageList(params: Record<string, any>) { export function getActiveDiscountGoodsPageList(params: Record<string, any>) {
return request.get(`shop/active/discount/goods/${ params.active_id }`, { params }) return request.get(`shop/active/discount/goods/${params.active_id}`, {
params,
})
} }
/** /**
@ -203,7 +221,9 @@ export function getActiveDiscountGoodsPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getActiveDiscountOrderPageList(params: Record<string, any>) { export function getActiveDiscountOrderPageList(params: Record<string, any>) {
return request.get(`shop/active/discount/order/${ params.active_id }`, { params }) return request.get(`shop/active/discount/order/${params.active_id}`, {
params,
})
} }
/** /**
@ -212,7 +232,9 @@ export function getActiveDiscountOrderPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getActiveDiscountMemberPageList(params: Record<string, any>) { export function getActiveDiscountMemberPageList(params: Record<string, any>) {
return request.get(`shop/active/discount/member/${ params.active_id }`, { params }) return request.get(`shop/active/discount/member/${params.active_id}`, {
params,
})
} }
/** /**
@ -220,7 +242,7 @@ export function getActiveDiscountMemberPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getActiveDiscountConfig() { export function getActiveDiscountConfig() {
return request.get(`shop/active/discount/config`); return request.get(`shop/active/discount/config`)
} }
/** /**
@ -229,10 +251,10 @@ export function getActiveDiscountConfig() {
* @returns * @returns
*/ */
export function editActiveDiscountConfig(params: Record<string, any>) { export function editActiveDiscountConfig(params: Record<string, any>) {
return request.put(`shop/active/discount/config`, params, { return request.put(`shop/active/discount/config`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/********** 积分商品 ***********/ /********** 积分商品 ***********/
@ -243,7 +265,7 @@ export function editActiveDiscountConfig(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getActiveExchangePageList(params: Record<string, any>) { export function getActiveExchangePageList(params: Record<string, any>) {
return request.get(`shop/active/exchange`, { params }) return request.get(`shop/active/exchange`, { params })
} }
/** /**
@ -252,7 +274,7 @@ export function getActiveExchangePageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getActiveExchangeInfo(id: number) { export function getActiveExchangeInfo(id: number) {
return request.get(`shop/active/exchange/${ id }`); return request.get(`shop/active/exchange/${id}`)
} }
/** /**
@ -261,7 +283,10 @@ export function getActiveExchangeInfo(id: number) {
* @returns * @returns
*/ */
export function addActiveExchange(params: Record<string, any>) { export function addActiveExchange(params: Record<string, any>) {
return request.post('shop/active/exchange', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/active/exchange', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -270,10 +295,10 @@ export function addActiveExchange(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editActiveExchange(params: Record<string, any>) { export function editActiveExchange(params: Record<string, any>) {
return request.put(`shop/active/exchange/${ params.id }`, params, { return request.put(`shop/active/exchange/${params.id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -282,10 +307,10 @@ export function editActiveExchange(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editActiveExchangeStatus(params: Record<string, any>) { export function editActiveExchangeStatus(params: Record<string, any>) {
return request.put(`shop/active/exchange/status/${ params.id }`, params, { return request.put(`shop/active/exchange/status/${params.id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -294,7 +319,9 @@ export function editActiveExchangeStatus(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteActiveExchange(id: number) { export function deleteActiveExchange(id: number) {
return request.delete(`shop/active/exchange/${ id }`, { showSuccessMessage: true }) return request.delete(`shop/active/exchange/${id}`, {
showSuccessMessage: true,
})
} }
/** /**
@ -302,7 +329,7 @@ export function deleteActiveExchange(id: number) {
* @returns * @returns
*/ */
export function getActiveExchangeStatus() { export function getActiveExchangeStatus() {
return request.get(`shop/active/exchange/status`) return request.get(`shop/active/exchange/status`)
} }
/************ 新人专享 ****************/ /************ 新人专享 ****************/
@ -312,7 +339,7 @@ export function getActiveExchangeStatus() {
* @returns * @returns
*/ */
export function getActiveNewcomerConfig() { export function getActiveNewcomerConfig() {
return request.get(`shop/active/newcomer/config`); return request.get(`shop/active/newcomer/config`)
} }
/** /**
@ -321,10 +348,10 @@ export function getActiveNewcomerConfig() {
* @returns * @returns
*/ */
export function editActiveNewcomerConfig(params: Record<string, any>) { export function editActiveNewcomerConfig(params: Record<string, any>) {
return request.put(`shop/active/newcomer/config`, params, { return request.put(`shop/active/newcomer/config`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -333,7 +360,7 @@ export function editActiveNewcomerConfig(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getNewcomerGoodsList(params: Record<string, any>) { export function getNewcomerGoodsList(params: Record<string, any>) {
return request.get('shop/active/newcomer/goods/select', { params }) return request.get('shop/active/newcomer/goods/select', { params })
} }
/** /**
@ -342,7 +369,7 @@ export function getNewcomerGoodsList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getNewcomerSelectGoodsList(params: Record<string, any>) { export function getNewcomerSelectGoodsList(params: Record<string, any>) {
return request.get('shop/active/newcomer/goods/selectgoodssku', { params }) return request.get('shop/active/newcomer/goods/selectgoodssku', { params })
} }
/************ 商品榜单 ****************/ /************ 商品榜单 ****************/
@ -353,7 +380,10 @@ export function getNewcomerSelectGoodsList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function setRankConfig(params: Record<string, any>) { export function setRankConfig(params: Record<string, any>) {
return request.post('shop/good/rank/config', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/good/rank/config', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -361,7 +391,7 @@ export function setRankConfig(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getRankConfig() { export function getRankConfig() {
return request.get(`shop/good/rank/config`) return request.get(`shop/good/rank/config`)
} }
/** /**
@ -370,7 +400,7 @@ export function getRankConfig() {
* @returns * @returns
*/ */
export function getRankPageList(params: Record<string, any>) { export function getRankPageList(params: Record<string, any>) {
return request.get(`shop/good/rank`, { params }) return request.get(`shop/good/rank`, { params })
} }
/** /**
@ -378,7 +408,7 @@ export function getRankPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function optionData() { export function optionData() {
return request.get(`shop/good/rank/dict`) return request.get(`shop/good/rank/dict`)
} }
/** /**
@ -387,7 +417,7 @@ export function optionData() {
* @returns * @returns
*/ */
export function getRankInfo(rank_id: number) { export function getRankInfo(rank_id: number) {
return request.get(`shop/good/rank/${ rank_id }`); return request.get(`shop/good/rank/${rank_id}`)
} }
/** /**
@ -396,7 +426,10 @@ export function getRankInfo(rank_id: number) {
* @returns * @returns
*/ */
export function addGoodRank(params: Record<string, any>) { export function addGoodRank(params: Record<string, any>) {
return request.post('shop/good/rank', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/good/rank', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -405,10 +438,10 @@ export function addGoodRank(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editGoodRank(params: Record<string, any>) { export function editGoodRank(params: Record<string, any>) {
return request.put(`shop/good/rank/${ params.id }`, params, { return request.put(`shop/good/rank/${params.id}`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -417,10 +450,10 @@ export function editGoodRank(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editRankStatus(params: Record<string, any>) { export function editRankStatus(params: Record<string, any>) {
return request.put(`shop/goods/rank/status`, params, { return request.put(`shop/goods/rank/status`, params, {
showErrorMessage: true, showErrorMessage: true,
showSuccessMessage: true showSuccessMessage: true,
}) })
} }
/** /**
@ -429,7 +462,7 @@ export function editRankStatus(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteGoodRank(id: number) { export function deleteGoodRank(id: number) {
return request.delete(`shop/good/rank/${ id }`, { showSuccessMessage: true }) return request.delete(`shop/good/rank/${id}`, { showSuccessMessage: true })
} }
/** /**
@ -438,7 +471,9 @@ export function deleteGoodRank(id: number) {
* @returns * @returns
*/ */
export function batchDelete(params: Record<string, any>) { export function batchDelete(params: Record<string, any>) {
return request.put(`shop/good/rank/batchDelete`, params, { showSuccessMessage: true }) return request.put(`shop/good/rank/batchDelete`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -447,7 +482,9 @@ export function batchDelete(params: Record<string, any>) {
* @returns * @returns
*/ */
export function modifyGoodsRankSort(params: Record<string, any>) { export function modifyGoodsRankSort(params: Record<string, any>) {
return request.put(`shop/good/rank/sort`, params, { showSuccessMessage: true }) return request.put(`shop/good/rank/sort`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -456,7 +493,7 @@ export function modifyGoodsRankSort(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getSelectRankPageList(params: Record<string, any>) { export function getSelectRankPageList(params: Record<string, any>) {
return request.get(`shop/good/rank/select`, { params }) return request.get(`shop/good/rank/select`, { params })
} }
/************ 满减 ****************/ /************ 满减 ****************/
@ -467,7 +504,7 @@ export function getSelectRankPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getManjianList(params: Record<string, any>) { export function getManjianList(params: Record<string, any>) {
return request.get(`shop/manjian`, { params }) return request.get(`shop/manjian`, { params })
} }
/** /**
@ -475,7 +512,7 @@ export function getManjianList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getManjianStatusList() { export function getManjianStatusList() {
return request.get(`shop/manjian/status`) return request.get(`shop/manjian/status`)
} }
/** /**
@ -484,7 +521,7 @@ export function getManjianStatusList() {
* @returns * @returns
*/ */
export function addManjian(params: Record<string, any>) { export function addManjian(params: Record<string, any>) {
return request.post('shop/manjian', params) return request.post('shop/manjian', params)
} }
/** /**
@ -493,7 +530,7 @@ export function addManjian(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editManjian(params: Record<string, any>) { export function editManjian(params: Record<string, any>) {
return request.put(`shop/manjian/${ params.id }`, params) return request.put(`shop/manjian/${params.id}`, params)
} }
/** /**
@ -502,7 +539,7 @@ export function editManjian(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getManjianInfo(params: Record<string, any>) { export function getManjianInfo(params: Record<string, any>) {
return request.get(`shop/manjian/init`, { params }); return request.get(`shop/manjian/init`, { params })
} }
/** /**
@ -511,7 +548,7 @@ export function getManjianInfo(params: Record<string, any>) {
* @returns * @returns
*/ */
export function goodsCheck(params: Record<string, any>) { export function goodsCheck(params: Record<string, any>) {
return request.post('shop/manjian/goods/check', params) return request.post('shop/manjian/goods/check', params)
} }
/** /**
@ -520,7 +557,7 @@ export function goodsCheck(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getManjianMemberPageList(params: Record<string, any>) { export function getManjianMemberPageList(params: Record<string, any>) {
return request.get(`shop/manjian/member/${ params.id }`, { params }) return request.get(`shop/manjian/member/${params.id}`, { params })
} }
/** /**
@ -529,10 +566,14 @@ export function getManjianMemberPageList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function closeManjian(manjian_id: number) { export function closeManjian(manjian_id: number) {
return request.put(`shop/manjian/close/${ manjian_id }`, {}, { return request.put(
showErrorMessage: true, `shop/manjian/close/${manjian_id}`,
showSuccessMessage: true {},
}) {
showErrorMessage: true,
showSuccessMessage: true,
}
)
} }
/** /**
@ -541,7 +582,7 @@ export function closeManjian(manjian_id: number) {
* @returns * @returns
*/ */
export function getGoodsSelectByReplaceBuy(params: Record<string, any>) { export function getGoodsSelectByReplaceBuy(params: Record<string, any>) {
return request.get(`shop/goods/buy/goods/select`, { params }) return request.get(`shop/goods/buy/goods/select`, { params })
} }
/** /**
@ -550,7 +591,7 @@ export function getGoodsSelectByReplaceBuy(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsSelectedByReplaceBuy(params: Record<string, any>) { export function getGoodsSelectedByReplaceBuy(params: Record<string, any>) {
return request.get(`shop/goods/buy/goods/selected`, { params }) return request.get(`shop/goods/buy/goods/selected`, { params })
} }
/** /**
@ -559,7 +600,7 @@ export function getGoodsSelectedByReplaceBuy(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsSkuInfo(params: Record<string, any>) { export function getGoodsSkuInfo(params: Record<string, any>) {
return request.get(`shop/goods/buy/sku/select`, { params }) return request.get(`shop/goods/buy/sku/select`, { params })
} }
/* /*
@ -568,7 +609,9 @@ export function getGoodsSkuInfo(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteManjian(manjian_id: number) { export function deleteManjian(manjian_id: number) {
return request.delete(`shop/manjian/${ manjian_id }`, { showSuccessMessage: true }) return request.delete(`shop/manjian/${manjian_id}`, {
showSuccessMessage: true,
})
} }
/** /**
@ -577,7 +620,9 @@ export function deleteManjian(manjian_id: number) {
* @returns * @returns
*/ */
export function batchDeleteManjian(params: Record<string, any>) { export function batchDeleteManjian(params: Record<string, any>) {
return request.put(`shop/manjian/goods/batchDelete`, params, { showSuccessMessage: true }) return request.put(`shop/manjian/goods/batchDelete`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -586,5 +631,7 @@ export function batchDeleteManjian(params: Record<string, any>) {
* @returns * @returns
*/ */
export function batchCloseMajian(params: Record<string, any>) { export function batchCloseMajian(params: Record<string, any>) {
return request.put(`shop/manjian/goods/batchClose`, params, { showSuccessMessage: true }) return request.put(`shop/manjian/goods/batchClose`, params, {
showSuccessMessage: true,
})
} }

77
admin/src/addon/shop/api/order.ts

@ -5,7 +5,7 @@ import request from '@/utils/request'
* @returns * @returns
*/ */
export function getConfig() { export function getConfig() {
return request.get('shop/order/config') return request.get('shop/order/config')
} }
/** /**
@ -13,7 +13,7 @@ export function getConfig() {
* @returns * @returns
*/ */
export function setConfig(param: any) { export function setConfig(param: any) {
return request.post('shop/order/config', param, { showSuccessMessage: true }) return request.post('shop/order/config', param, { showSuccessMessage: true })
} }
/** /**
@ -21,7 +21,7 @@ export function setConfig(param: any) {
* @returns * @returns
*/ */
export function getOrderList(params: Record<string, any>) { export function getOrderList(params: Record<string, any>) {
return request.get('shop/order/list', { params }) return request.get('shop/order/list', { params })
} }
/** /**
@ -29,7 +29,7 @@ export function getOrderList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getOrderDetail(order_id: number) { export function getOrderDetail(order_id: number) {
return request.get(`shop/order/detail/${ order_id }`) return request.get(`shop/order/detail/${order_id}`)
} }
/** /**
@ -37,7 +37,7 @@ export function getOrderDetail(order_id: number) {
* @return * @return
*/ */
export function getOrderStatus() { export function getOrderStatus() {
return request.get(`shop/order/status`) return request.get(`shop/order/status`)
} }
/** /**
@ -45,7 +45,7 @@ export function getOrderStatus() {
* @return * @return
*/ */
export function getOrderType() { export function getOrderType() {
return request.get(`shop/order/type`) return request.get(`shop/order/type`)
} }
/** /**
@ -53,7 +53,7 @@ export function getOrderType() {
* @return * @return
*/ */
export function orderClose(order_id: number) { export function orderClose(order_id: number) {
return request.put(`shop/order/close/${ order_id }`) return request.put(`shop/order/close/${order_id}`)
} }
/** /**
@ -61,7 +61,7 @@ export function orderClose(order_id: number) {
* @return * @return
*/ */
export function getOrderDeliveryType(params: Record<string, any>) { export function getOrderDeliveryType(params: Record<string, any>) {
return request.get(`shop/order/delivery_type`, { params }) return request.get(`shop/order/delivery_type`, { params })
} }
/** /**
@ -69,7 +69,7 @@ export function getOrderDeliveryType(params: Record<string, any>) {
* @return * @return
*/ */
export function orderDelivery(params: Record<string, any>) { export function orderDelivery(params: Record<string, any>) {
return request.put(`shop/order/delivery`, params) return request.put(`shop/order/delivery`, params)
} }
/** /**
@ -77,7 +77,7 @@ export function orderDelivery(params: Record<string, any>) {
* @return * @return
*/ */
export function setShopRemark(params: Record<string, any>) { export function setShopRemark(params: Record<string, any>) {
return request.put(`shop/order/shop_remark`, params) return request.put(`shop/order/shop_remark`, params)
} }
/** /**
@ -85,7 +85,7 @@ export function setShopRemark(params: Record<string, any>) {
* @return * @return
*/ */
export function orderFinish(order_id: number) { export function orderFinish(order_id: number) {
return request.put(`shop/order/finish/${ order_id }`) return request.put(`shop/order/finish/${order_id}`)
} }
/** /**
@ -93,7 +93,7 @@ export function orderFinish(order_id: number) {
* @return * @return
*/ */
export function deliveryPackage(params: Record<string, any>) { export function deliveryPackage(params: Record<string, any>) {
return request.get(`shop/order/delivery/package`, { params }) return request.get(`shop/order/delivery/package`, { params })
} }
/** /**
@ -101,7 +101,7 @@ export function deliveryPackage(params: Record<string, any>) {
* @return * @return
*/ */
export function deliveryPackageList(params: Record<string, any>) { export function deliveryPackageList(params: Record<string, any>) {
return request.get(`shop/order/delivery/package/list`, { params }) return request.get(`shop/order/delivery/package/list`, { params })
} }
/** /**
@ -110,14 +110,14 @@ export function deliveryPackageList(params: Record<string, any>) {
* @return * @return
*/ */
export function orderRefund(params: Record<string, any>) { export function orderRefund(params: Record<string, any>) {
return request.get(`shop/order/refund`, { params }) return request.get(`shop/order/refund`, { params })
} }
/** /**
* 退 * 退
*/ */
export function orderRefundDetail(refund_id: number) { export function orderRefundDetail(refund_id: number) {
return request.get(`shop/order/refund/${ refund_id }`) return request.get(`shop/order/refund/${refund_id}`)
} }
/** /**
@ -125,7 +125,10 @@ export function orderRefundDetail(refund_id: number) {
* @return * @return
*/ */
export function auditRefund(params: Record<string, any>) { export function auditRefund(params: Record<string, any>) {
return request.put(`shop/order/refund/audit/${ params.order_refund_no }`, params) return request.put(
`shop/order/refund/audit/${params.order_refund_no}`,
params
)
} }
/** /**
@ -133,56 +136,61 @@ export function auditRefund(params: Record<string, any>) {
* @return * @return
*/ */
export function refundDelivery(params: Record<string, any>) { export function refundDelivery(params: Record<string, any>) {
return request.put(`shop/order/refund/delivery/${ params.order_refund_no }`, params) return request.put(
`shop/order/refund/delivery/${params.order_refund_no}`,
params
)
} }
/** /**
* 退 * 退
*/ */
export function getRefundMoney(params: Record<string, any>) { export function getRefundMoney(params: Record<string, any>) {
return request.get(`shop/order/refund/refund_money`, { params }) return request.get(`shop/order/refund/refund_money`, { params })
} }
/** /**
* 退 * 退
*/ */
export function shopActiveRefund(params: Record<string, any>) { export function shopActiveRefund(params: Record<string, any>) {
return request.post(`shop/order/refund/active`, params, { showSuccessMessage: true }) return request.post(`shop/order/refund/active`, params, {
showSuccessMessage: true,
})
} }
/** /**
* *
*/ */
export function getInvoiceList(params: Record<string, any>) { export function getInvoiceList(params: Record<string, any>) {
return request.get(`shop/invoice`, { params }) return request.get(`shop/invoice`, { params })
} }
/** /**
* *
*/ */
export function getInvoiceDetail(id: number) { export function getInvoiceDetail(id: number) {
return request.get(`shop/invoice/${ id }`) return request.get(`shop/invoice/${id}`)
} }
/** /**
* *
*/ */
export function setInvoice(id: number, params: Record<string, any>) { export function setInvoice(id: number, params: Record<string, any>) {
return request.put(`shop/invoice/${ id }`, params, { showSuccessMessage: true }) return request.put(`shop/invoice/${id}`, params, { showSuccessMessage: true })
} }
/** /**
* *
*/ */
export function getOrderPayType() { export function getOrderPayType() {
return request.get(`shop/order/pay/type`) return request.get(`shop/order/pay/type`)
} }
/** /**
* *
*/ */
export function getOrderFrom() { export function getOrderFrom() {
return request.get(`shop/order/from`) return request.get(`shop/order/from`)
} }
/** /**
@ -190,7 +198,9 @@ export function getOrderFrom() {
* @return * @return
*/ */
export function orderEditPrice(params: Record<string, any>) { export function orderEditPrice(params: Record<string, any>) {
return request.put(`shop/order/edit_price`, params, { showSuccessMessage: true }) return request.put(`shop/order/edit_price`, params, {
showSuccessMessage: true,
})
} }
/** /**
@ -198,7 +208,7 @@ export function orderEditPrice(params: Record<string, any>) {
* @return * @return
*/ */
export function getOrderEditAddress(params: Record<string, any>) { export function getOrderEditAddress(params: Record<string, any>) {
return request.get(`shop/order/edit_delivery`, { params }) return request.get(`shop/order/edit_delivery`, { params })
} }
/** /**
@ -206,7 +216,7 @@ export function getOrderEditAddress(params: Record<string, any>) {
* @return * @return
*/ */
export function getDeliveryList() { export function getDeliveryList() {
return request.get(`shop/delivery/store/list`) return request.get(`shop/delivery/store/list`)
} }
/** /**
@ -214,7 +224,7 @@ export function getDeliveryList() {
* @return * @return
*/ */
export function orderEditAddress(params: Record<string, any>) { export function orderEditAddress(params: Record<string, any>) {
return request.put(`shop/order/edit_delivery`, params) return request.put(`shop/order/edit_delivery`, params)
} }
/** /**
@ -222,7 +232,7 @@ export function orderEditAddress(params: Record<string, any>) {
* @return * @return
*/ */
export function getOrderBatchDeliveryList(params: Record<string, any>) { export function getOrderBatchDeliveryList(params: Record<string, any>) {
return request.get(`shop/order_batch_delivery`, { params }) return request.get(`shop/order_batch_delivery`, { params })
} }
/** /**
@ -230,7 +240,10 @@ export function getOrderBatchDeliveryList(params: Record<string, any>) {
* @return * @return
*/ */
export function addBatchOrderDelivery(params: Record<string, any>) { export function addBatchOrderDelivery(params: Record<string, any>) {
return request.put(`shop/order_batch_delivery/add_batch_order_delivery`, params) return request.put(
`shop/order_batch_delivery/add_batch_order_delivery`,
params
)
} }
/** /**
@ -238,7 +251,7 @@ export function addBatchOrderDelivery(params: Record<string, any>) {
* @return * @return
*/ */
export function getOrderBatchDeliveryState() { export function getOrderBatchDeliveryState() {
return request.get(`shop/order_batch_delivery/get_status`) return request.get(`shop/order_batch_delivery/get_status`)
} }
/** /**
@ -246,5 +259,5 @@ export function getOrderBatchDeliveryState() {
* @return * @return
*/ */
export function getOrderBatchDeliveryType() { export function getOrderBatchDeliveryType() {
return request.get(`shop/order_batch_delivery/get_type`) return request.get(`shop/order_batch_delivery/get_type`)
} }

12
admin/src/addon/shop/api/shop.ts

@ -4,40 +4,40 @@ import request from '@/utils/request'
* *
*/ */
export function getShopCountList() { export function getShopCountList() {
return request.get(`shop/stat/total`) return request.get(`shop/stat/total`)
} }
/** /**
* *
*/ */
export function getShopTodayCountList() { export function getShopTodayCountList() {
return request.get(`shop/stat/today`) return request.get(`shop/stat/today`)
} }
/** /**
* *
*/ */
export function getShopYesterdayCountList() { export function getShopYesterdayCountList() {
return request.get(`shop/stat/yesterday`) return request.get(`shop/stat/yesterday`)
} }
/** /**
* *
*/ */
export function getShopStat() { export function getShopStat() {
return request.get(`shop/stat`) return request.get(`shop/stat`)
} }
/** /**
* *
*/ */
export function getShopOrderStat() { export function getShopOrderStat() {
return request.get(`shop/stat/order`) return request.get(`shop/stat/order`)
} }
/** /**
* *
*/ */
export function getShopGoodsStat() { export function getShopGoodsStat() {
return request.get(`shop/stat/goods`) return request.get(`shop/stat/goods`)
} }

25
admin/src/addon/shop/api/shop_address.ts

@ -6,7 +6,7 @@ import request from '@/utils/request'
* @returns * @returns
*/ */
export function getShopAddressList(params: Record<string, any>) { export function getShopAddressList(params: Record<string, any>) {
return request.get(`shop/shop_address`, { params }) return request.get(`shop/shop_address`, { params })
} }
/** /**
@ -15,7 +15,7 @@ export function getShopAddressList(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getShopAddressInfo(id: number) { export function getShopAddressInfo(id: number) {
return request.get(`shop/shop_address/${ id }`); return request.get(`shop/shop_address/${id}`)
} }
/** /**
@ -24,7 +24,10 @@ export function getShopAddressInfo(id: number) {
* @returns * @returns
*/ */
export function addShopAddress(params: Record<string, any>) { export function addShopAddress(params: Record<string, any>) {
return request.post('shop/shop_address', params, { showErrorMessage: true, showSuccessMessage: true }) return request.post('shop/shop_address', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -33,7 +36,10 @@ export function addShopAddress(params: Record<string, any>) {
* @returns * @returns
*/ */
export function editShopAddress(params: Record<string, any>) { export function editShopAddress(params: Record<string, any>) {
return request.put(`shop/shop_address/${ params.id }`, params, { showErrorMessage: true, showSuccessMessage: true }) return request.put(`shop/shop_address/${params.id}`, params, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -42,7 +48,10 @@ export function editShopAddress(params: Record<string, any>) {
* @returns * @returns
*/ */
export function deleteShopAddress(id: number) { export function deleteShopAddress(id: number) {
return request.delete(`shop/shop_address/${ id }`, { showErrorMessage: true, showSuccessMessage: true }) return request.delete(`shop/shop_address/${id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
} }
/** /**
@ -50,7 +59,7 @@ export function deleteShopAddress(id: number) {
* @returns * @returns
*/ */
export function getShopDefaultDeliveryAddressInfo() { export function getShopDefaultDeliveryAddressInfo() {
return request.get('shop/shop_address/default/delivery'); return request.get('shop/shop_address/default/delivery')
} }
/** /**
@ -58,5 +67,5 @@ export function getShopDefaultDeliveryAddressInfo() {
* @returns * @returns
*/ */
export function getOrderRefundAddress() { export function getOrderRefundAddress() {
return request.get('shop/order/refund/address'); return request.get('shop/order/refund/address')
} }

8
admin/src/addon/shop/api/stat.ts

@ -4,7 +4,7 @@ import request from '@/utils/request'
* @returns * @returns
*/ */
export function getGoodsStatisticsBasic(params: Record<string, any>) { export function getGoodsStatisticsBasic(params: Record<string, any>) {
return request.get('shop/goods/statistics/basic', { params }) return request.get('shop/goods/statistics/basic', { params })
} }
/** /**
@ -12,13 +12,13 @@ export function getGoodsStatisticsBasic(params: Record<string, any>) {
* @returns * @returns
*/ */
export function getGoodsStatisticsTrend(params: Record<string, any>) { export function getGoodsStatisticsTrend(params: Record<string, any>) {
return request.get('shop/goods/statistics/trend', { params }) return request.get('shop/goods/statistics/trend', { params })
} }
/** /**
* *
*/ */
export function getGoodsStatisticsType() { export function getGoodsStatisticsType() {
return request.get(`shop/goods/statistics/type`) return request.get(`shop/goods/statistics/type`)
} }
/** /**
@ -26,5 +26,5 @@ export function getGoodsStatisticsType() {
* @returns * @returns
*/ */
export function getGoodsStatisticsRank(params: Record<string, any>) { export function getGoodsStatisticsRank(params: Record<string, any>) {
return request.get('shop/goods/statistics/rank', { params }) return request.get('shop/goods/statistics/rank', { params })
} }

68
admin/src/addon/shop/lang/zh-cn/address.edit.json

@ -1,35 +1,35 @@
{ {
"contactName":"联系人", "contactName": "联系人",
"mobile":"联系方式", "mobile": "联系方式",
"provinceId":"省", "provinceId": "省",
"cityId":"市", "cityId": "市",
"districtId":"区", "districtId": "区",
"address":"详细地址", "address": "详细地址",
"fullAddress":"地址", "fullAddress": "地址",
"lat":"纬度", "lat": "纬度",
"lng":"经度", "lng": "经度",
"isDeliveryAddress":"是否是发货地址", "isDeliveryAddress": "是否是发货地址",
"isRefundAddress":"是否是退货地址", "isRefundAddress": "是否是退货地址",
"isDefaultDelivery":"默认发货地址", "isDefaultDelivery": "默认发货地址",
"isDefaultRefund":"默认收货地址", "isDefaultRefund": "默认收货地址",
"contactNamePlaceholder":"请输入联系人", "contactNamePlaceholder": "请输入联系人",
"mobilePlaceholder":"请输入联系方式", "mobilePlaceholder": "请输入联系方式",
"mobileTips":"请输入正确的手机号", "mobileTips": "请输入正确的手机号",
"addressPlaceholder":"请输入详细地址", "addressPlaceholder": "请输入详细地址",
"fullAddressPlaceholder":"请输入地址", "fullAddressPlaceholder": "请输入地址",
"latPlaceholder":"请输入纬度", "latPlaceholder": "请输入纬度",
"lngPlaceholder":"请输入经度", "lngPlaceholder": "请输入经度",
"isDeliveryAddressPlaceholder":"请输入是否是发货地址", "isDeliveryAddressPlaceholder": "请输入是否是发货地址",
"isRefundAddressPlaceholder":"请输入是否是退货地址", "isRefundAddressPlaceholder": "请输入是否是退货地址",
"isDefaultDeliveryPlaceholder":"请输入默认发货地址", "isDefaultDeliveryPlaceholder": "请输入默认发货地址",
"isDefaultRefundPlaceholder":"请输入默认收货地址", "isDefaultRefundPlaceholder": "请输入默认收货地址",
"addShopAddress":"添加商家地址库", "addShopAddress": "添加商家地址库",
"updateShopAddress":"编辑商家地址库", "updateShopAddress": "编辑商家地址库",
"shopAddressDeleteTips":"确定要删除该商家地址库吗?", "shopAddressDeleteTips": "确定要删除该商家地址库吗?",
"addressType": "地址类型", "addressType": "地址类型",
"deliveryAddress": "发货地址", "deliveryAddress": "发货地址",
"refundAddress": "收货地址", "refundAddress": "收货地址",
"defaultDeliveryAddress": "是否设为默认发货地址", "defaultDeliveryAddress": "是否设为默认发货地址",
"defaultRefundAddress": "是否设为默认收货地址", "defaultRefundAddress": "是否设为默认收货地址",
"addressTypeRequire": "至少需设置一项类型" "addressTypeRequire": "至少需设置一项类型"
} }

2
admin/src/addon/shop/lang/zh-cn/address.list.json

@ -22,4 +22,4 @@
"deliveryAddress": "发货地址", "deliveryAddress": "发货地址",
"refundAddress": "收货地址", "refundAddress": "收货地址",
"default": "默认" "default": "默认"
} }

58
admin/src/addon/shop/lang/zh-cn/common.json

@ -88,41 +88,41 @@
"goodsSearchSet": "搜索设置", "goodsSearchSet": "搜索设置",
"goodsSearchText": "搜索内容", "goodsSearchText": "搜索内容",
"goodsSearchTextPlaceholder": "请输入搜索内容", "goodsSearchTextPlaceholder": "请输入搜索内容",
"shopMemberInfoComponentUidTextColor":"编号颜色", "shopMemberInfoComponentUidTextColor": "编号颜色",
"shopMemberInfoComponentAccount":"账号信息", "shopMemberInfoComponentAccount": "账号信息",
"shopGoodsRecommendComponentTag":"标签", "shopGoodsRecommendComponentTag": "标签",
"shopGoodsRecommendComponentTagcolor":"标签颜色", "shopGoodsRecommendComponentTagcolor": "标签颜色",
"shopGoodsRecommendComponentTagPlaceholder":"请输入标签内容", "shopGoodsRecommendComponentTagPlaceholder": "请输入标签内容",
"shopGoodsRecommendComponentButtonBorderColor":"按钮边框颜色", "shopGoodsRecommendComponentButtonBorderColor": "按钮边框颜色",
"carouselStyle":"轮播样式", "carouselStyle": "轮播样式",
"recommendIndicatorStyle":"指示器设置", "recommendIndicatorStyle": "指示器设置",
"recommendIndicatorColor":"常规颜色", "recommendIndicatorColor": "常规颜色",
"recommendIndicatorActiveColor":"选中颜色", "recommendIndicatorActiveColor": "选中颜色",
"activeCubeBlockContent":"板块内容" , "activeCubeBlockContent": "板块内容",
"bgImage":"背景图片", "bgImage": "背景图片",
"rankingTitleIcon":"图标" , "rankingTitleIcon": "图标",
"rankSelect":"榜单选择", "rankSelect": "榜单选择",
"rankName":"榜单名称", "rankName": "榜单名称",
"rankNamePlaceholder":"请输入榜单名称", "rankNamePlaceholder": "请输入榜单名称",
"showGoodsNum":"榜单商品数量", "showGoodsNum": "榜单商品数量",
"goodsSourceName":"商品来源", "goodsSourceName": "商品来源",
"ruleTypeName":"排序规则", "ruleTypeName": "排序规则",
"rankTypeName":"排行周期", "rankTypeName": "排行周期",
"rankSelectPopupAfterTip": "个榜单", "rankSelectPopupAfterTip": "个榜单",
"rankSelectPopupGoodsMinTip": "所选榜单数量不能少于", "rankSelectPopupGoodsMinTip": "所选榜单数量不能少于",
"rankSelectPopupGoodsMaxTip": "所选榜单数量不能超过", "rankSelectPopupGoodsMaxTip": "所选榜单数量不能超过",
"rankingTitleImage":"头部图片" , "rankingTitleImage": "头部图片",
"rankingSubTitle":"副标题", "rankingSubTitle": "副标题",
"rankingSubTitleTextColor":"副标题颜色", "rankingSubTitleTextColor": "副标题颜色",
"rankTextColor":"名称颜色", "rankTextColor": "名称颜色",
"rankingSubTitleLink":"副标题链接", "rankingSubTitleLink": "副标题链接",
"listFrameColor":"背景颜色", "listFrameColor": "背景颜色",
"topRounded":"上圆角", "topRounded": "上圆角",
"bottomRounded":"下圆角", "bottomRounded": "下圆角",
"rankingStyle": "板块样式", "rankingStyle": "板块样式",
"styleRecommend": "风格推荐", "styleRecommend": "风格推荐",
"countDownStyle": "倒计时样式", "countDownStyle": "倒计时样式",
"newcomerNumberColor": "数字颜色", "newcomerNumberColor": "数字颜色",
"newcomerNumberBg": "数字背景色", "newcomerNumberBg": "数字背景色",
"newcomerOtherColor": "文字颜色" "newcomerOtherColor": "文字颜色"
} }

38
admin/src/addon/shop/lang/zh-cn/delivery.company.json

@ -1,20 +1,20 @@
{ {
"companyId":"", "companyId": "",
"companyIdPlaceholder":"请输入", "companyIdPlaceholder": "请输入",
"companyName":"名称", "companyName": "名称",
"companyNamePlaceholder":"请输入物流公司名称", "companyNamePlaceholder": "请输入物流公司名称",
"logo":"LOGO", "logo": "LOGO",
"logoPlaceholder":"请输入物流公司logo", "logoPlaceholder": "请输入物流公司logo",
"url":"网址", "url": "网址",
"urlPlaceholder":"请输入物流公司网址", "urlPlaceholder": "请输入物流公司网址",
"expressNoPlaceholder":"请输入物流公司编号", "expressNoPlaceholder": "请输入物流公司编号",
"expressNoTips": "物流公司编号作用于物流查询,请根据物流跟踪对应配置设置编号", "expressNoTips": "物流公司编号作用于物流查询,请根据物流跟踪对应配置设置编号",
"expressNoKd100":"快递100编码", "expressNoKd100": "快递100编码",
"expressNoKd100Placeholder":"请输入快递100编码", "expressNoKd100Placeholder": "请输入快递100编码",
"addCompany":"添加物流公司", "addCompany": "添加物流公司",
"updateCompany":"编辑物流公司", "updateCompany": "编辑物流公司",
"electronicSheetSwitchName": "是否支持电子面单", "electronicSheetSwitchName": "是否支持电子面单",
"expressNoElectronicSheet":"电子面单编号", "expressNoElectronicSheet": "电子面单编号",
"expressNo":"物流跟踪编号", "expressNo": "物流跟踪编号",
"companyDeleteTips":"确定要删除该数据吗?" "companyDeleteTips": "确定要删除该数据吗?"
} }

85
admin/src/addon/shop/lang/zh-cn/delivery.company_edit.json

@ -1,44 +1,43 @@
{ {
"companyId":"", "companyId": "",
"companyIdPlaceholder":"请输入", "companyIdPlaceholder": "请输入",
"companyName":"名称", "companyName": "名称",
"companyNamePlaceholder":"请输入物流公司名称", "companyNamePlaceholder": "请输入物流公司名称",
"logo":"LOGO", "logo": "LOGO",
"logoPlaceholder":"请输入物流公司logo", "logoPlaceholder": "请输入物流公司logo",
"url":"网址", "url": "网址",
"urlPlaceholder":"请输入物流公司网址", "urlPlaceholder": "请输入物流公司网址",
"expressNo":"物流跟踪编号", "expressNo": "物流跟踪编号",
"expressNoPlaceholder":"请输入物流公司编号", "expressNoPlaceholder": "请输入物流公司编号",
"expressNoTips": "物流公司编号作用于物流查询,请根据物流跟踪对应配置设置编号", "expressNoTips": "物流公司编号作用于物流查询,请根据物流跟踪对应配置设置编号",
"expressNoKd100":"快递100编码", "expressNoKd100": "快递100编码",
"expressNoKd100Placeholder":"请输入快递100编码", "expressNoKd100Placeholder": "请输入快递100编码",
"addCompany":"添加物流公司", "addCompany": "添加物流公司",
"updateCompany":"编辑物流公司", "updateCompany": "编辑物流公司",
"expressNoElectronicSheet":"电子面单编号", "expressNoElectronicSheet": "电子面单编号",
"expressNoElectronicSheetTips":"电子面单编号作用于电子面单查询,请根据电子面单对应配置设置编号", "expressNoElectronicSheetTips": "电子面单编号作用于电子面单查询,请根据电子面单对应配置设置编号",
"printStyle": "模板样式", "printStyle": "模板样式",
"addPrintStyle": "添加模板样式", "addPrintStyle": "添加模板样式",
"expType": "业务类型", "expType": "业务类型",
"addExpType": "添加业务类型", "addExpType": "添加业务类型",
"expTypeName": "业务名称", "expTypeName": "业务名称",
"expTypeTextTips": "业务名称不能为空", "expTypeTextTips": "业务名称不能为空",
"expTypeValueTips": "业务值不能为空", "expTypeValueTips": "业务值不能为空",
"expTypeTextRepeatTips": "业务名称不可以重复,请重新填写", "expTypeTextRepeatTips": "业务名称不可以重复,请重新填写",
"expTypeValueRepeatTips": "业务值不可以重复,请重新填写", "expTypeValueRepeatTips": "业务值不可以重复,请重新填写",
"expTypeValueNullTips": "业务值不可以为零", "expTypeValueNullTips": "业务值不可以为零",
"expTypeValue": "业务值", "expTypeValue": "业务值",
"electronicSheetSwitch": "是否支持电子面单", "electronicSheetSwitch": "是否支持电子面单",
"printStyleName": "模板名称" , "printStyleName": "模板名称",
"printStyleNameTips": "模板名称不能为空", "printStyleNameTips": "模板名称不能为空",
"printStyleSizeTips": "模板尺寸不能为空", "printStyleSizeTips": "模板尺寸不能为空",
"printStyleNameRepeatTips": "模板名称不可以重复,请重新填写", "printStyleNameRepeatTips": "模板名称不可以重复,请重新填写",
"printStyleSizeRepeatTips": "模板尺寸不可以重复,请重新填写", "printStyleSizeRepeatTips": "模板尺寸不可以重复,请重新填写",
"printStyleId": "模板尺寸", "printStyleId": "模板尺寸",
"expTypeTips": "快递鸟业务类型" , "expTypeTips": "快递鸟业务类型",
"expTypeTips1": "不填默认为1" , "expTypeTips1": "不填默认为1",
"printStyleTips": "快递鸟模版规格(常用)", "printStyleTips": "快递鸟模版规格(常用)",
"printStyleTips1": "主流快递单打印纸尺寸一般为:76*130,100*180(单位mm)", "printStyleTips1": "主流快递单打印纸尺寸一般为:76*130,100*180(单位mm)",
"printStyleTips2": "不填写则取物流公司的默认模板", "printStyleTips2": "不填写则取物流公司的默认模板",
"examine": "点击查看" "examine": "点击查看"
}
}

20
admin/src/addon/shop/lang/zh-cn/delivery.config.json

@ -1,11 +1,11 @@
{ {
"store":"启动门店自提后,买家可选择自提点提货。", "store": "启动门店自提后,买家可选择自提点提货。",
"express":"启用物流配送后,买家下单可以选择快递发货。", "express": "启用物流配送后,买家下单可以选择快递发货。",
"local_delivery":"启用同城配送后,在配送范围内的买家可以选择同城配送。", "local_delivery": "启用同城配送后,在配送范围内的买家可以选择同城配送。",
"deliveryStaff":"配送员", "deliveryStaff": "配送员",
"deliveryCompany":"物流公司", "deliveryCompany": "物流公司",
"deliveryTemplate":"运费模版", "deliveryTemplate": "运费模版",
"deliverySearch":"物流跟踪", "deliverySearch": "物流跟踪",
"deliveryStore":"自提点", "deliveryStore": "自提点",
"localConfig": "同城配送设置" "localConfig": "同城配送设置"
} }

2
admin/src/addon/shop/lang/zh-cn/delivery.electronic_sheet.json

@ -14,4 +14,4 @@
"setDefault": "设为默认", "setDefault": "设为默认",
"electronicSheetDeleteTips": "确定要删除该数据吗?", "electronicSheetDeleteTips": "确定要删除该数据吗?",
"electronicSheetSetDefaultTips": "确定要设置为默认模版吗?" "electronicSheetSetDefaultTips": "确定要设置为默认模版吗?"
} }

2
admin/src/addon/shop/lang/zh-cn/delivery.electronic_sheet_config.json

@ -18,4 +18,4 @@
"serverPort2Placeholder": "请输入服务器端口2", "serverPort2Placeholder": "请输入服务器端口2",
"httpsPort": "HTTPS端口", "httpsPort": "HTTPS端口",
"httpsPortPlaceholder": "请输入HTTPS端口" "httpsPortPlaceholder": "请输入HTTPS端口"
} }

2
admin/src/addon/shop/lang/zh-cn/delivery.electronic_sheet_edit.json

@ -31,4 +31,4 @@
"examine": "点击查看", "examine": "点击查看",
"customerNameTips": "快递鸟电子面单账号申请", "customerNameTips": "快递鸟电子面单账号申请",
"customerNameTips1": "电子面单账号对照表" "customerNameTips1": "电子面单账号对照表"
} }

108
admin/src/addon/shop/lang/zh-cn/delivery.local.json

@ -1,55 +1,55 @@
{ {
"basicSettings":"同城配送基础设置", "basicSettings": "同城配送基础设置",
"timeIsOpen":"配送时间设置", "timeIsOpen": "配送时间设置",
"timeIsOpenTips":"开启后,买家下单选择同城配送时,可选择配送时间,提交订单后,将在买家备注中显示。", "timeIsOpenTips": "开启后,买家下单选择同城配送时,可选择配送时间,提交订单后,将在买家备注中显示。",
"close": "关闭", "close": "关闭",
"open": "开启", "open": "开启",
"everyDay": "每天", "everyDay": "每天",
"monday": "周一", "monday": "周一",
"tuesday": "周二", "tuesday": "周二",
"wednesday": "周三", "wednesday": "周三",
"thursday": "周四", "thursday": "周四",
"friday": "周五", "friday": "周五",
"saturday": "周六", "saturday": "周六",
"sunday": "周日", "sunday": "周日",
"timeWeekRequire": "请选择配送时间", "timeWeekRequire": "请选择配送时间",
"deliveryTimeSetting": "配送时间设置", "deliveryTimeSetting": "配送时间设置",
"feeType": "收费标准", "feeType": "收费标准",
"region": "按区域收取配送费", "region": "按区域收取配送费",
"distance": "按距离收取配送费", "distance": "按距离收取配送费",
"district": "按行政区域收取配送费", "district": "按行政区域收取配送费",
"feeSetting": "费用设置", "feeSetting": "费用设置",
"weightFee": "续重收费", "weightFee": "续重收费",
"feeSettingTextOne": "km内按", "feeSettingTextOne": "km内按",
"feeSettingTextTwo": "元收取配送费,每超出", "feeSettingTextTwo": "元收取配送费,每超出",
"feeSettingTextThree": "km费用增加", "feeSettingTextThree": "km费用增加",
"priceUnit": "元", "priceUnit": "元",
"weightFeeTextOne": "商品重量", "weightFeeTextOne": "商品重量",
"weightFeeTextTwo": "kg 内不额外收费,每超出", "weightFeeTextTwo": "kg 内不额外收费,每超出",
"weightFeeTextThree": "kg 费用增加", "weightFeeTextThree": "kg 费用增加",
"areaName": "区域名称", "areaName": "区域名称",
"startPrice": "起送价", "startPrice": "起送价",
"deliveryPrice": "配送费", "deliveryPrice": "配送费",
"areaType": "划分方式", "areaType": "划分方式",
"radius": "半径", "radius": "半径",
"custom": "自定义", "custom": "自定义",
"addDeliveryArea": "添加配送区域", "addDeliveryArea": "添加配送区域",
"baseDistRequire": "请输入起始公里数", "baseDistRequire": "请输入起始公里数",
"gradDistRequire": "请输入超出公里数", "gradDistRequire": "请输入超出公里数",
"basePriceRequire": "请输入起始公里内的配送费用", "basePriceRequire": "请输入起始公里内的配送费用",
"gradPriceRequire": "请输入每超出公里部分的费用", "gradPriceRequire": "请输入每超出公里部分的费用",
"areaNameRequire": "请输入区域名称", "areaNameRequire": "请输入区域名称",
"startPriceRequire": "请输入起送价", "startPriceRequire": "请输入起送价",
"startPriceMin": "起送价不能小于0", "startPriceMin": "起送价不能小于0",
"deliveryPriceRequire": "请输入配送费", "deliveryPriceRequire": "请输入配送费",
"deliveryPriceMin": "配送费不能小于0", "deliveryPriceMin": "配送费不能小于0",
"areaPlaceholder": "请添加配送区域", "areaPlaceholder": "请添加配送区域",
"deliveryType": "配送方式", "deliveryType": "配送方式",
"business": "商家自配送", "business": "商家自配送",
"deliveryTypeRequire": "至少需选择一种配送方式", "deliveryTypeRequire": "至少需选择一种配送方式",
"deliveryAddress": "取货地址", "deliveryAddress": "取货地址",
"defaultDeliveryAddressEmpty": "请先配置默认发货地址", "defaultDeliveryAddressEmpty": "请先配置默认发货地址",
"toSetting": "去配置", "toSetting": "去配置",
"update": "修改", "update": "修改",
"deliveryAddressChange": "取货地址已变更请注意是否需重新调整配送区域" "deliveryAddressChange": "取货地址已变更请注意是否需重新调整配送区域"
} }

38
admin/src/addon/shop/lang/zh-cn/delivery.search.json

@ -1,20 +1,20 @@
{ {
"prompt": "提示", "prompt": "提示",
"promptTips1-1": "请到快递鸟官网申请", "promptTips1-1": "请到快递鸟官网申请",
"promptTips1-2": "快递鸟接口:目前只支持“申通,圆通、百世,极兔”免费查询。", "promptTips1-2": "快递鸟接口:目前只支持“申通,圆通、百世,极兔”免费查询。",
"promptTips2": "请到快递100官网申请", "promptTips2": "请到快递100官网申请",
"interfaceType": "接口类型", "interfaceType": "接口类型",
"kdn": "快递鸟", "kdn": "快递鸟",
"kd100": "快递100", "kd100": "快递100",
"kdnEBusinessIDPlaceholder": "请输入快递鸟EBusinessID", "kdnEBusinessIDPlaceholder": "请输入快递鸟EBusinessID",
"kdnEBusinessIDTips": "快递鸟电商ID", "kdnEBusinessIDTips": "快递鸟电商ID",
"kdnAppKeyPlaceholder": "请输入快递鸟AppKey", "kdnAppKeyPlaceholder": "请输入快递鸟AppKey",
"kdnAppKeyTips": "快递鸟分配的电商加密私钥", "kdnAppKeyTips": "快递鸟分配的电商加密私钥",
"isPayEdition": "快递鸟套餐", "isPayEdition": "快递鸟套餐",
"free": "免费", "free": "免费",
"pay": "付费", "pay": "付费",
"kd100AppKeyPlaceholder": "请输入快递100AppKey", "kd100AppKeyPlaceholder": "请输入快递100AppKey",
"kd100AppKeyTips": "快递100应用密钥", "kd100AppKeyTips": "快递100应用密钥",
"kd100CustomerPlaceholder": "请输入快递100Customer", "kd100CustomerPlaceholder": "请输入快递100Customer",
"kd100CustomerTips": "快递100分配给的公司编号" "kd100CustomerTips": "快递100分配给的公司编号"
} }

16
admin/src/addon/shop/lang/zh-cn/delivery.staff.json

@ -1,9 +1,9 @@
{ {
"addDeliveryPersonnel":"添加配送员", "addDeliveryPersonnel": "添加配送员",
"updateDeliver":"编辑配送员", "updateDeliver": "编辑配送员",
"deliverName":"配送员名称", "deliverName": "配送员名称",
"deliverMobile":"配送员手机号", "deliverMobile": "配送员手机号",
"deliverNamePlaceholder":"请输入配送员名称", "deliverNamePlaceholder": "请输入配送员名称",
"deliverMobilePlaceholder":"请输入配送员手机号", "deliverMobilePlaceholder": "请输入配送员手机号",
"deliverDeleteTips":"确定要删除该数据吗?" "deliverDeleteTips": "确定要删除该数据吗?"
} }

34
admin/src/addon/shop/lang/zh-cn/delivery.store.json

@ -1,18 +1,18 @@
{ {
"storeId":"", "storeId": "",
"storeName":"自提点信息", "storeName": "自提点信息",
"storeNamePlaceholder":"请输入自提点名称", "storeNamePlaceholder": "请输入自提点名称",
"storeLogo":"自提点logo", "storeLogo": "自提点logo",
"storeMobile":"联系电话", "storeMobile": "联系电话",
"address":"详细地址", "address": "详细地址",
"fullAddress":"联系地址", "fullAddress": "联系地址",
"longitude":"经度", "longitude": "经度",
"latitude":"纬度", "latitude": "纬度",
"tradeTime":"营业时间", "tradeTime": "营业时间",
"createTime":"添加时间", "createTime": "添加时间",
"createTimePlaceholder":"请输入添加时间", "createTimePlaceholder": "请输入添加时间",
"addStore":"添加自提点", "addStore": "添加自提点",
"updateStore":"编辑自提点", "updateStore": "编辑自提点",
"storeDeleteTips":"确定要删除该数据吗?", "storeDeleteTips": "确定要删除该数据吗?",
"storeInfo": "自提点信息" "storeInfo": "自提点信息"
} }

74
admin/src/addon/shop/lang/zh-cn/delivery.store_edit.json

@ -1,38 +1,38 @@
{ {
"storeName":"自提点名称", "storeName": "自提点名称",
"storeDesc":"简介", "storeDesc": "简介",
"storeLogo":"自提点logo", "storeLogo": "自提点logo",
"storeMobile":"手机号", "storeMobile": "手机号",
"provinceId":"省id", "provinceId": "省id",
"cityId":"市", "cityId": "市",
"districtId":"县(区)", "districtId": "县(区)",
"address":"详细地址", "address": "详细地址",
"fullAddress":"完整地址", "fullAddress": "完整地址",
"longitude":"经度", "longitude": "经度",
"latitude":"纬度", "latitude": "纬度",
"tradeTime":"营业时间", "tradeTime": "营业时间",
"createTime":"下单时间", "createTime": "下单时间",
"updateTime":"更新时间", "updateTime": "更新时间",
"storeNamePlaceholder":"请输入自提点名称", "storeNamePlaceholder": "请输入自提点名称",
"storeDescPlaceholder":"请输入简介", "storeDescPlaceholder": "请输入简介",
"storeLogoPlaceholder":"请上传自提点logo", "storeLogoPlaceholder": "请上传自提点logo",
"storeMobilePlaceholder":"请输入手机号", "storeMobilePlaceholder": "请输入手机号",
"provinceIdPlaceholder":"请选择省id", "provinceIdPlaceholder": "请选择省id",
"cityIdPlaceholder":"请选择市", "cityIdPlaceholder": "请选择市",
"districtIdPlaceholder":"请选择县(区)", "districtIdPlaceholder": "请选择县(区)",
"addressPlaceholder":"请输入详细地址", "addressPlaceholder": "请输入详细地址",
"fullAddressPlaceholder":"请输入完整地址", "fullAddressPlaceholder": "请输入完整地址",
"longitudePlaceholder":"请输入经度", "longitudePlaceholder": "请输入经度",
"latitudePlaceholder":"请输入纬度", "latitudePlaceholder": "请输入纬度",
"tradeTimePlaceholder":"请输入营业时间", "tradeTimePlaceholder": "请输入营业时间",
"tradeTimeTips": "例:上午9:00-12:00,下午2:00-6:00", "tradeTimeTips": "例:上午9:00-12:00,下午2:00-6:00",
"createTimePlaceholder":"请选择添加时间", "createTimePlaceholder": "请选择添加时间",
"updateTimePlaceholder":"请输入更新时间", "updateTimePlaceholder": "请输入更新时间",
"addStore":"添加自提点", "addStore": "添加自提点",
"updateStore":"编辑自提点", "updateStore": "编辑自提点",
"storeDeleteTips":"确定要删除该自提点吗?", "storeDeleteTips": "确定要删除该自提点吗?",
"storeAddress": "自提点地址", "storeAddress": "自提点地址",
"storeAddressPlaceholder": "请选择自提点地址", "storeAddressPlaceholder": "请选择自提点地址",
"storeAddressDetail": "自提点详细地址", "storeAddressDetail": "自提点详细地址",
"storeAddressDetailPlaceholder": "请输入自提点详细地址" "storeAddressDetailPlaceholder": "请输入自提点详细地址"
} }

22
admin/src/addon/shop/lang/zh-cn/delivery.template.json

@ -1,12 +1,12 @@
{ {
"templateName":"运费模板名称", "templateName": "运费模板名称",
"templateNamePlaceholder":"请输入运费模板名称", "templateNamePlaceholder": "请输入运费模板名称",
"createTime":"创建时间", "createTime": "创建时间",
"addTemplate":"添加运费模板", "addTemplate": "添加运费模板",
"updateTemplate":"编辑运费模板", "updateTemplate": "编辑运费模板",
"templateDeleteTips":"确定要删除该模板吗?", "templateDeleteTips": "确定要删除该模板吗?",
"feeTypeName": "计费类型", "feeTypeName": "计费类型",
"freeShipping": "指定区域包邮", "freeShipping": "指定区域包邮",
"open": "启用", "open": "启用",
"close": "关闭" "close": "关闭"
} }

76
admin/src/addon/shop/lang/zh-cn/delivery.template_edit.json

@ -1,39 +1,39 @@
{ {
"templateName":"运费模板名称", "templateName": "运费模板名称",
"templateNamePlaceholder":"请输入运费模板名称", "templateNamePlaceholder": "请输入运费模板名称",
"createTime":"创建时间", "createTime": "创建时间",
"addTemplate":"添加运费模板", "addTemplate": "添加运费模板",
"updateTemplate":"编辑运费模板", "updateTemplate": "编辑运费模板",
"templateDeleteTips":"确定要删除该模板吗?", "templateDeleteTips": "确定要删除该模板吗?",
"feeTypeName": "计费类型", "feeTypeName": "计费类型",
"isDefault": "默认模板", "isDefault": "默认模板",
"num": "按件", "num": "按件",
"weight": "按重量", "weight": "按重量",
"volume": "按体积", "volume": "按体积",
"feeSetting": "费用设置", "feeSetting": "费用设置",
"selectArea": "选择地区", "selectArea": "选择地区",
"firstNum": "首件(件)", "firstNum": "首件(件)",
"continueNum": "续件(件)", "continueNum": "续件(件)",
"firstWeight": "首件重量(kg)", "firstWeight": "首件重量(kg)",
"fee": "运费(元)", "fee": "运费(元)",
"continueFee": "续费(元)", "continueFee": "续费(元)",
"continueWeight": "续件重量(kg)", "continueWeight": "续件重量(kg)",
"firstVolume": "首件体积(m³)", "firstVolume": "首件体积(m³)",
"continueVolume": "续件体积(m³)", "continueVolume": "续件体积(m³)",
"deliveryArea": "配送区域", "deliveryArea": "配送区域",
"addDeliveryArea": "添加单独配送区域", "addDeliveryArea": "添加单独配送区域",
"freeShipping": "指定区域包邮", "freeShipping": "指定区域包邮",
"freeShippingArea": "包邮区域", "freeShippingArea": "包邮区域",
"addFreeShippingArea": "添加包邮区域", "addFreeShippingArea": "添加包邮区域",
"freeShippingAreaTips": "两个条件满足其一便可以包邮", "freeShippingAreaTips": "两个条件满足其一便可以包邮",
"noDelivery": "不配送区域", "noDelivery": "不配送区域",
"addNoDelivery": "添加不配送区域", "addNoDelivery": "添加不配送区域",
"freeShippingNum": "包邮件数", "freeShippingNum": "包邮件数",
"freeShippingWeight": "包邮重量(kg)", "freeShippingWeight": "包邮重量(kg)",
"freeShippingVolume": "包邮体积(m³)", "freeShippingVolume": "包邮体积(m³)",
"freeShippingPrice": "包邮金额", "freeShippingPrice": "包邮金额",
"areaPlaceholder":"请选择地区", "areaPlaceholder": "请选择地区",
"noDeliveryPlaceholder": "请选择不配送的地区", "noDeliveryPlaceholder": "请选择不配送的地区",
"freeShippingPlaceholder": "请选择包邮的地区", "freeShippingPlaceholder": "请选择包邮的地区",
"notUnderZero": "不能小于等于0" "notUnderZero": "不能小于等于0"
} }

4
admin/src/addon/shop/lang/zh-cn/goods.attr.json

@ -5,6 +5,6 @@
"addShopGoodsAttr": "添加参数模板", "addShopGoodsAttr": "添加参数模板",
"updateShopGoodsAttr": "编辑参数模板", "updateShopGoodsAttr": "编辑参数模板",
"goodsAttrDeleteTips": "确定要删除该数据吗?", "goodsAttrDeleteTips": "确定要删除该数据吗?",
"sortTips":"排序号格式输入错误", "sortTips": "排序号格式输入错误",
"manage": "管理" "manage": "管理"
} }

2
admin/src/addon/shop/lang/zh-cn/goods.attr_edit.json

@ -15,4 +15,4 @@
"attrValueName": "参数名称", "attrValueName": "参数名称",
"addAttrValue": "添加参数", "addAttrValue": "添加参数",
"attrValueNamePlaceholder": "请输入参数名称" "attrValueNamePlaceholder": "请输入参数名称"
} }

28
admin/src/addon/shop/lang/zh-cn/goods.brand_list.json

@ -1,15 +1,15 @@
{ {
"brandId":"品牌ID", "brandId": "品牌ID",
"brandIdPlaceholder":"请输入品牌ID", "brandIdPlaceholder": "请输入品牌ID",
"brandName":"品牌名称", "brandName": "品牌名称",
"brandNamePlaceholder":"请输入品牌名称", "brandNamePlaceholder": "请输入品牌名称",
"logo":"品牌logo", "logo": "品牌logo",
"logoPlaceholder":"请输入品牌logo", "logoPlaceholder": "请输入品牌logo",
"desc":"品牌介绍", "desc": "品牌介绍",
"descPlaceholder":"请输入品牌介绍", "descPlaceholder": "请输入品牌介绍",
"sort":"排序", "sort": "排序",
"sortPlaceholder":"请输入排序", "sortPlaceholder": "请输入排序",
"addBrand":"添加商品品牌", "addBrand": "添加商品品牌",
"updateBrand":"编辑商品品牌", "updateBrand": "编辑商品品牌",
"brandDeleteTips":"确定要删除该数据吗?" "brandDeleteTips": "确定要删除该数据吗?"
} }

50
admin/src/addon/shop/lang/zh-cn/goods.category.json

@ -1,26 +1,26 @@
{ {
"categoryId":"商品分类id", "categoryId": "商品分类id",
"categoryIdPlaceholder":"请输入商品分类id", "categoryIdPlaceholder": "请输入商品分类id",
"categoryName":"分类名称", "categoryName": "分类名称",
"categoryNamePlaceholder":"请输入分类名称", "categoryNamePlaceholder": "请输入分类名称",
"image":"分类图片", "image": "分类图片",
"imagePlaceholder":"请输入分类图片", "imagePlaceholder": "请输入分类图片",
"pid":"上级分类", "pid": "上级分类",
"pidPlaceholder":"请选择上级分类", "pidPlaceholder": "请选择上级分类",
"categoryFullName":"组装分类名称", "categoryFullName": "组装分类名称",
"categoryFullNamePlaceholder":"请输入组装分类名称", "categoryFullNamePlaceholder": "请输入组装分类名称",
"isShow":"是否显示", "isShow": "是否显示",
"sort":"排序号", "sort": "排序号",
"sortPlaceholder":"请输入排序号", "sortPlaceholder": "请输入排序号",
"addCategory":"添加商品分类", "addCategory": "添加商品分类",
"updateCategory":"编辑商品分类", "updateCategory": "编辑商品分类",
"categoryDeleteTips":"确定要删除该数据吗?", "categoryDeleteTips": "确定要删除该数据吗?",
"categoryDeleteTips1":"子级分类也会删除,确定要删除该数据吗?", "categoryDeleteTips1": "子级分类也会删除,确定要删除该数据吗?",
"spreadGoodsCategory": "推广", "spreadGoodsCategory": "推广",
"goodsCategorySpreadTitle": "商品分类推广", "goodsCategorySpreadTitle": "商品分类推广",
"spreadLink": "推广链接", "spreadLink": "推广链接",
"copy": "复制", "copy": "复制",
"downloadQrcode": "下载二维码", "downloadQrcode": "下载二维码",
"tabGoodsCategory": "商品分类", "tabGoodsCategory": "商品分类",
"tabGoodsCategoryConfig": "分类设置" "tabGoodsCategoryConfig": "分类设置"
} }

52
admin/src/addon/shop/lang/zh-cn/goods.category_config.json

@ -1,27 +1,27 @@
{ {
"categoryTemplate":"分类模板", "categoryTemplate": "分类模板",
"categoryType":"分类类型", "categoryType": "分类类型",
"categorystyleOne":"一级分类", "categorystyleOne": "一级分类",
"categorystyleTwo":"二级分类", "categorystyleTwo": "二级分类",
"pageSettings":"页面设置", "pageSettings": "页面设置",
"pageTitle":"页面名称", "pageTitle": "页面名称",
"pageTitlePlaceholder":"请输入页面名称", "pageTitlePlaceholder": "请输入页面名称",
"searchControl":"搜索栏", "searchControl": "搜索栏",
"searchTitle":"搜索栏文字", "searchTitle": "搜索栏文字",
"searchTitlePlaceholder":"请输入搜索栏文字", "searchTitlePlaceholder": "请输入搜索栏文字",
"open":"开启", "open": "开启",
"close":"关闭", "close": "关闭",
"goodsStyle":"商品排列", "goodsStyle": "商品排列",
"singleCols": "单列", "singleCols": "单列",
"doubleCols": "双列", "doubleCols": "双列",
"sort":"商品排序", "sort": "商品排序",
"sortPlaceholder":"请选择商品排序", "sortPlaceholder": "请选择商品排序",
"cartControl":"购物车显示", "cartControl": "购物车显示",
"cartStyle":"购物车样式", "cartStyle": "购物车样式",
"cartTextPlaceholder":"请输入购物车按钮文字", "cartTextPlaceholder": "请输入购物车按钮文字",
"cartEvent":"点击按钮", "cartEvent": "点击按钮",
"detail": "跳转商品详情", "detail": "跳转商品详情",
"cart": "加入购物车", "cart": "加入购物车",
"tabGoodsCategory": "商品分类", "tabGoodsCategory": "商品分类",
"tabGoodsCategoryConfig": "分类设置" "tabGoodsCategoryConfig": "分类设置"
} }

96
admin/src/addon/shop/lang/zh-cn/goods.evaluate.json

@ -1,49 +1,49 @@
{ {
"evaluateId":"", "evaluateId": "",
"evaluateIdPlaceholder":"请输入", "evaluateIdPlaceholder": "请输入",
"orderId":"订单id", "orderId": "订单id",
"orderIdPlaceholder":"请输入订单id", "orderIdPlaceholder": "请输入订单id",
"orderGoodsId":"订单项ID", "orderGoodsId": "订单项ID",
"orderGoodsIdPlaceholder":"请输入订单项ID", "orderGoodsIdPlaceholder": "请输入订单项ID",
"goodsId":"商品ID", "goodsId": "商品ID",
"goodsIdPlaceholder":"请选择商品", "goodsIdPlaceholder": "请选择商品",
"memberId":"会员ID", "memberId": "会员ID",
"memberIdPlaceholder":"请输入会员ID", "memberIdPlaceholder": "请输入会员ID",
"content":"评价内容", "content": "评价内容",
"contentPlaceholder":"请输入评价内容", "contentPlaceholder": "请输入评价内容",
"images":"评价图片", "images": "评价图片",
"imagesPlaceholder":"请输入评价图片", "imagesPlaceholder": "请输入评价图片",
"isAnonymous":"是否匿名", "isAnonymous": "是否匿名",
"anonymous": "匿名", "anonymous": "匿名",
"notAnonymous": "不匿名", "notAnonymous": "不匿名",
"scores":"评价等级", "scores": "评价等级",
"scoresPlaceholder":"请输入评价分数 1-5", "scoresPlaceholder": "请输入评价分数 1-5",
"auditName":"审核状态", "auditName": "审核状态",
"explainFirst":"商家回复", "explainFirst": "商家回复",
"explainFirstPlaceholder": "请输入商家回复", "explainFirstPlaceholder": "请输入商家回复",
"createTime":"评价时间", "createTime": "评价时间",
"createTimePlaceholder":"请输入评价时间", "createTimePlaceholder": "请输入评价时间",
"again": "追评", "again": "追评",
"againTime":"追评时间", "againTime": "追评时间",
"againTimePlaceholder":"请输入追评时间", "againTimePlaceholder": "请输入追评时间",
"isShow":"是否显示", "isShow": "是否显示",
"show": "显示", "show": "显示",
"notShow": "不显示", "notShow": "不显示",
"isShowPlaceholder":"请输入是否显示 1显示 2不显示", "isShowPlaceholder": "请输入是否显示 1显示 2不显示",
"addEvaluate":"添加自评", "addEvaluate": "添加自评",
"updateEvaluate":"编辑商品评价", "updateEvaluate": "编辑商品评价",
"evaluateDeleteTips":"确定要删除该数据吗?", "evaluateDeleteTips": "确定要删除该数据吗?",
"goodsInfo": "商品信息", "goodsInfo": "商品信息",
"memberHead": "会员头像", "memberHead": "会员头像",
"memberName": "会员名称", "memberName": "会员名称",
"memberNamePlaceholder": "请输入会员名称", "memberNamePlaceholder": "请输入会员名称",
"adopt": "通过", "adopt": "通过",
"refuse": "拒绝", "refuse": "拒绝",
"auditAdoptTips": "确定要通过审核吗?", "auditAdoptTips": "确定要通过审核吗?",
"reply": "回复", "reply": "回复",
"goodsName": "商品名称", "goodsName": "商品名称",
"goodsNamePlaceholder": "请输入商品名称", "goodsNamePlaceholder": "请输入商品名称",
"topping": "置顶", "topping": "置顶",
"cancelTopping": "取消置顶", "cancelTopping": "取消置顶",
"memberHeadPlaceholder": "请上传会员头像" "memberHeadPlaceholder": "请上传会员头像"
} }

72
admin/src/addon/shop/lang/zh-cn/goods.evaluate_edit.json

@ -1,37 +1,37 @@
{ {
"orderId":"订单id", "orderId": "订单id",
"orderGoodsId":"订单项ID", "orderGoodsId": "订单项ID",
"goodsId":"商品ID", "goodsId": "商品ID",
"memberId":"会员ID", "memberId": "会员ID",
"content":"评价内容", "content": "评价内容",
"images":"评价图片", "images": "评价图片",
"isAnonymous":"0 匿名 1不匿名", "isAnonymous": "0 匿名 1不匿名",
"scores":"评价分数 1-5", "scores": "评价分数 1-5",
"isAudit":"审核状态 1待审 2通过 3拒绝", "isAudit": "审核状态 1待审 2通过 3拒绝",
"explainFirst":"解释内容", "explainFirst": "解释内容",
"againContent":"追评内容", "againContent": "追评内容",
"againImages":"追评图片", "againImages": "追评图片",
"againExplain":"追评解释", "againExplain": "追评解释",
"againTime":"追评时间", "againTime": "追评时间",
"againIsAudit":"审核状态 1待审 2通过 3拒绝", "againIsAudit": "审核状态 1待审 2通过 3拒绝",
"isShow":"是否显示 1显示 2不显示", "isShow": "是否显示 1显示 2不显示",
"orderIdPlaceholder":"请输入订单id", "orderIdPlaceholder": "请输入订单id",
"orderGoodsIdPlaceholder":"请输入订单项ID", "orderGoodsIdPlaceholder": "请输入订单项ID",
"goodsIdPlaceholder":"请输入商品ID", "goodsIdPlaceholder": "请输入商品ID",
"memberIdPlaceholder":"请输入会员ID", "memberIdPlaceholder": "请输入会员ID",
"contentPlaceholder":"请输入评价内容", "contentPlaceholder": "请输入评价内容",
"imagesPlaceholder":"请上传评价图片", "imagesPlaceholder": "请上传评价图片",
"isAnonymousPlaceholder":"请输入0 匿名 1不匿名", "isAnonymousPlaceholder": "请输入0 匿名 1不匿名",
"scoresPlaceholder":"请输入评价分数 1-5", "scoresPlaceholder": "请输入评价分数 1-5",
"isAuditPlaceholder":"请输入审核状态 1待审 2通过 3拒绝", "isAuditPlaceholder": "请输入审核状态 1待审 2通过 3拒绝",
"explainFirstPlaceholder":"请输入解释内容", "explainFirstPlaceholder": "请输入解释内容",
"againContentPlaceholder":"请输入追评内容", "againContentPlaceholder": "请输入追评内容",
"againImagesPlaceholder":"请上传追评图片", "againImagesPlaceholder": "请上传追评图片",
"againExplainPlaceholder":"请输入追评解释", "againExplainPlaceholder": "请输入追评解释",
"againTimePlaceholder":"请输入追评时间", "againTimePlaceholder": "请输入追评时间",
"againIsAuditPlaceholder":"请输入审核状态 1待审 2通过 3拒绝", "againIsAuditPlaceholder": "请输入审核状态 1待审 2通过 3拒绝",
"isShowPlaceholder":"请输入是否显示 1显示 2不显示", "isShowPlaceholder": "请输入是否显示 1显示 2不显示",
"addEvaluate":"添加商品评价", "addEvaluate": "添加商品评价",
"updateEvaluate":"编辑商品评价", "updateEvaluate": "编辑商品评价",
"evaluateDeleteTips":"确定要删除该商品评价吗?" "evaluateDeleteTips": "确定要删除该商品评价吗?"
} }

2
admin/src/addon/shop/lang/zh-cn/goods.label_group_list.json

@ -9,4 +9,4 @@
"updateLabelGroup": "编辑标签分组", "updateLabelGroup": "编辑标签分组",
"sortTips": "排序号格式输入错误", "sortTips": "排序号格式输入错误",
"labelGroupDeleteTips": "确定要删除该数据吗?" "labelGroupDeleteTips": "确定要删除该数据吗?"
} }

2
admin/src/addon/shop/lang/zh-cn/goods.label_list.json

@ -27,4 +27,4 @@
"status": "状态", "status": "状态",
"label": "标签", "label": "标签",
"createTime": "创建时间" "createTime": "创建时间"
} }

13
admin/src/addon/shop/lang/zh-cn/goods.list.json

@ -14,13 +14,13 @@
"startSaleNumTips": "最低销量输入错误", "startSaleNumTips": "最低销量输入错误",
"endSaleNumPlaceholder": "最高销量", "endSaleNumPlaceholder": "最高销量",
"endSaleNumTips": "最高销量输入错误", "endSaleNumTips": "最高销量输入错误",
"shopSaleNumTips":"最低销量不能大于最高销量", "shopSaleNumTips": "最低销量不能大于最高销量",
"skuPrice": "价格", "skuPrice": "价格",
"startPricePlaceholder": "最低价格", "startPricePlaceholder": "最低价格",
"startPriceTips": "最低价格输入错误", "startPriceTips": "最低价格输入错误",
"endPricePlaceholder": "最高价格", "endPricePlaceholder": "最高价格",
"endPriceTips": "最高价格输入错误", "endPriceTips": "最高价格输入错误",
"shopPriceTips":"最低价格不能大于最高价格", "shopPriceTips": "最低价格不能大于最高价格",
"statusOn": "销售中", "statusOn": "销售中",
"statusOff": "仓库中", "statusOff": "仓库中",
"statusAll": "全部商品", "statusAll": "全部商品",
@ -40,7 +40,7 @@
"addGoods": "添加商品", "addGoods": "添加商品",
"statusActionOn": "上架", "statusActionOn": "上架",
"statusActionOff": "下架", "statusActionOff": "下架",
"statusChangeTips":"确定要下架该商品吗?", "statusChangeTips": "确定要下架该商品吗?",
"spreadGoods": "推广", "spreadGoods": "推广",
"copyGoods": "复制", "copyGoods": "复制",
@ -105,7 +105,6 @@
"discountHint": "会员折扣说明:按照默认会员等级折扣优惠", "discountHint": "会员折扣说明:按照默认会员等级折扣优惠",
"fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准", "fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准",
"addGoodsLabel": "添加商品标签", "addGoodsLabel": "添加商品标签",
"addGoodsService": "添加商品服务", "addGoodsService": "添加商品服务",
"addGoodsCategory": "添加分类", "addGoodsCategory": "添加分类",
@ -133,9 +132,9 @@
"addDeliveryTemplateId": "添加运费模板", "addDeliveryTemplateId": "添加运费模板",
"deliveryType": "配送方式", "deliveryType": "配送方式",
"deliveryTypePlaceholder": "请选择配送方式", "deliveryTypePlaceholder": "请选择配送方式",
"yuan":"元", "yuan": "元",
"label":"商品标签", "label": "商品标签",
"service":"商品服务", "service": "商品服务",
"virtualSaleNum": "虚拟销量", "virtualSaleNum": "虚拟销量",
"goodsBrand": "商品品牌", "goodsBrand": "商品品牌",
"goodsPoster": "商品海报", "goodsPoster": "商品海报",

30
admin/src/addon/shop/lang/zh-cn/goods.real_edit.json

@ -11,9 +11,9 @@
"subTitlePlaceholder": "请输入副标题", "subTitlePlaceholder": "请输入副标题",
"subTitleMaxLengthTips": "副标题不能超过80个字符", "subTitleMaxLengthTips": "副标题不能超过80个字符",
"goodsImage": "商品图片", "goodsImage": "商品图片",
"goodsImagePlaceholder":"请上传商品图片", "goodsImagePlaceholder": "请上传商品图片",
"goodsVideo": "商品视频", "goodsVideo": "商品视频",
"goodsVideoPlaceholder":"请上传商品视频", "goodsVideoPlaceholder": "请上传商品视频",
"goodsCategory": "商品分类", "goodsCategory": "商品分类",
"refresh": "刷新", "refresh": "刷新",
"addGoodsCategory": "添加分类", "addGoodsCategory": "添加分类",
@ -87,21 +87,21 @@
"deliveryTab": "配送设置", "deliveryTab": "配送设置",
"deliveryType": "配送方式", "deliveryType": "配送方式",
"deliveryTypePlaceholder": "请选择配送方式", "deliveryTypePlaceholder": "请选择配送方式",
"pleaseSelectSku":"请先选择商品规格", "pleaseSelectSku": "请先选择商品规格",
"isLimit":"是否限购", "isLimit": "是否限购",
"isLimitTips":"启用限购后,购买商品时,会对该商品购买量做限制判断。", "isLimitTips": "启用限购后,购买商品时,会对该商品购买量做限制判断。",
"limitType":"限购类型", "limitType": "限购类型",
"limitTypeTips":"单次限购是针对于每次下单不能超过限购数量,单人限购是针对于会员账号购买这个商品的总数不能超过限购数量。", "limitTypeTips": "单次限购是针对于每次下单不能超过限购数量,单人限购是针对于会员账号购买这个商品的总数不能超过限购数量。",
"singleTime":"单次限购", "singleTime": "单次限购",
"singlePerson":"单人限购", "singlePerson": "单人限购",
"maxBuy":"限购数量", "maxBuy": "限购数量",
"maxBuyPlaceholder":"请输入限购数量", "maxBuyPlaceholder": "请输入限购数量",
"maxBuyTips": "[限购数量]格式输入错误", "maxBuyTips": "[限购数量]格式输入错误",
"maxBuyWarnTips":"限购数量超出商品库存时,买家将无法购买该商品", "maxBuyWarnTips": "限购数量超出商品库存时,买家将无法购买该商品",
"maxBuyNotZeroTips": "限购数量不能小于1", "maxBuyNotZeroTips": "限购数量不能小于1",
"minBuy":"起购数量", "minBuy": "起购数量",
"minBuyTips":"起购数量超出商品库存时,买家将无法购买该商品", "minBuyTips": "起购数量超出商品库存时,买家将无法购买该商品",
"minBuyFormatErrorTips":"[起购数量]格式输入错误", "minBuyFormatErrorTips": "[起购数量]格式输入错误",
"minBuyNotZeroTips": "起购数量不能小于0", "minBuyNotZeroTips": "起购数量不能小于0",
"minBuyGreaterThanMaxBuyTips": "起购数量不能大于限购数量", "minBuyGreaterThanMaxBuyTips": "起购数量不能大于限购数量",

18
admin/src/addon/shop/lang/zh-cn/goods.service.json

@ -1,10 +1,10 @@
{ {
"serviceName":"服务名称", "serviceName": "服务名称",
"serviceNamePlaceholder":"请输入服务名称", "serviceNamePlaceholder": "请输入服务名称",
"desc":"描述", "desc": "描述",
"descPlaceholder":"请输入描述", "descPlaceholder": "请输入描述",
"addServe":"添加商品服务", "addServe": "添加商品服务",
"updateServe":"编辑商品服务", "updateServe": "编辑商品服务",
"serveDeleteTips":"确定要删除该数据吗?", "serveDeleteTips": "确定要删除该数据吗?",
"imagePlaceholder": "请上传服务图片" "imagePlaceholder": "请上传服务图片"
} }

30
admin/src/addon/shop/lang/zh-cn/goods.virtual_edit.json

@ -11,9 +11,9 @@
"subTitlePlaceholder": "请输入副标题", "subTitlePlaceholder": "请输入副标题",
"subTitleMaxLengthTips": "副标题不能超过80个字符", "subTitleMaxLengthTips": "副标题不能超过80个字符",
"goodsImage": "商品图片", "goodsImage": "商品图片",
"goodsImagePlaceholder":"请上传商品图片", "goodsImagePlaceholder": "请上传商品图片",
"goodsVideo": "商品视频", "goodsVideo": "商品视频",
"goodsVideoPlaceholder":"请上传商品视频", "goodsVideoPlaceholder": "请上传商品视频",
"goodsCategory": "商品分类", "goodsCategory": "商品分类",
"refresh": "刷新", "refresh": "刷新",
"addGoodsCategory": "添加分类", "addGoodsCategory": "添加分类",
@ -81,20 +81,20 @@
"maxAddSpecTips": "最多添加5个规格项", "maxAddSpecTips": "最多添加5个规格项",
"pleaseEditSpecPlaceholder": "请编辑规格信息", "pleaseEditSpecPlaceholder": "请编辑规格信息",
"refreshSuccess": "刷新成功", "refreshSuccess": "刷新成功",
"isLimit":"是否限购", "isLimit": "是否限购",
"isLimitTips":"启用限购后,购买商品时,会对该商品购买量做限制判断。", "isLimitTips": "启用限购后,购买商品时,会对该商品购买量做限制判断。",
"limitType":"限购类型", "limitType": "限购类型",
"limitTypeTips":"单次限购是针对于每次下单不能超过限购数量,单人限购是针对于会员账号购买这个商品的总数不能超过限购数量。", "limitTypeTips": "单次限购是针对于每次下单不能超过限购数量,单人限购是针对于会员账号购买这个商品的总数不能超过限购数量。",
"singleTime":"单次限购", "singleTime": "单次限购",
"singlePerson":"单人限购", "singlePerson": "单人限购",
"maxBuy":"限购数量", "maxBuy": "限购数量",
"maxBuyPlaceholder":"请输入限购数量", "maxBuyPlaceholder": "请输入限购数量",
"maxBuyTips": "[限购数量]格式输入错误", "maxBuyTips": "[限购数量]格式输入错误",
"maxBuyWarnTips":"限购数量超出商品库存时,买家将无法购买该商品", "maxBuyWarnTips": "限购数量超出商品库存时,买家将无法购买该商品",
"maxBuyNotZeroTips": "限购数量不能小于1", "maxBuyNotZeroTips": "限购数量不能小于1",
"minBuy":"起购数量", "minBuy": "起购数量",
"minBuyTips":"起购数量超出商品库存时,买家将无法购买该商品", "minBuyTips": "起购数量超出商品库存时,买家将无法购买该商品",
"minBuyFormatErrorTips":"[起购数量]格式输入错误", "minBuyFormatErrorTips": "[起购数量]格式输入错误",
"minBuyNotZeroTips": "起购数量不能小于0", "minBuyNotZeroTips": "起购数量不能小于0",
"minBuyGreaterThanMaxBuyTips": "起购数量不能大于限购数量", "minBuyGreaterThanMaxBuyTips": "起购数量不能大于限购数量",
@ -124,7 +124,6 @@
"specValueNameRepeat": "规格值不能重复", "specValueNameRepeat": "规格值不能重复",
"lackDefaultSpec": "商品缺少默认规格", "lackDefaultSpec": "商品缺少默认规格",
"setDeliverGoods": "发货设置", "setDeliverGoods": "发货设置",
"autoDeliverGoods": "自动发货", "autoDeliverGoods": "自动发货",
"handDeliverGoods": "手动发货", "handDeliverGoods": "手动发货",
@ -163,5 +162,4 @@
"fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准", "fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准",
"participateInActiveDisableTips": "商品正在参与营销活动,禁止操作" "participateInActiveDisableTips": "商品正在参与营销活动,禁止操作"
} }

38
admin/src/addon/shop/lang/zh-cn/index.index.json

@ -1,20 +1,20 @@
{ {
"realtimeOverview":"实时概况", "realtimeOverview": "实时概况",
"updateTime":"更新时间:", "updateTime": "更新时间:",
"todayOrderCount":"今日订单数", "todayOrderCount": "今日订单数",
"todayOrderSale":"今日销售额", "todayOrderSale": "今日销售额",
"todayAddMemberCount":"今日退款金额", "todayAddMemberCount": "今日退款金额",
"todayBrowseCount":"今日浏览量", "todayBrowseCount": "今日浏览量",
"yesterday":"昨日:", "yesterday": "昨日:",
"orderCount":"订单总数", "orderCount": "订单总数",
"salesTotal":"销售总额(元)", "salesTotal": "销售总额(元)",
"memberTotal":"退款金额", "memberTotal": "退款金额",
"browseTotal":"总浏览量", "browseTotal": "总浏览量",
"agentMatters":"待办事项", "agentMatters": "待办事项",
"waitPayOrder":"待付款订单", "waitPayOrder": "待付款订单",
"waitDeliveryOrder":"待发货订单", "waitDeliveryOrder": "待发货订单",
"waitTakeOrder":"待收货订单", "waitTakeOrder": "待收货订单",
"refundOrder":"退款订单", "refundOrder": "退款订单",
"saleGoodsNum":"出售商品数量", "saleGoodsNum": "出售商品数量",
"warehouseGoodsNum":"仓库商品数量" "warehouseGoodsNum": "仓库商品数量"
} }

82
admin/src/addon/shop/lang/zh-cn/marketing.coupon.add.json

@ -1,42 +1,42 @@
{ {
"addCoupon": "添加优惠券", "addCoupon": "添加优惠券",
"title": "名称", "title": "名称",
"titlePlaceholder": "请如:XXX优惠券,最多20个字", "titlePlaceholder": "请如:XXX优惠券,最多20个字",
"type": "类型", "type": "类型",
"price": "面值", "price": "面值",
"receiveType": "是否手动领取", "receiveType": "是否手动领取",
"startTime": "开始时间", "startTime": "开始时间",
"endTime": "结束时间", "endTime": "结束时间",
"remainCount": "剩余数量", "remainCount": "剩余数量",
"limitCount": "已领取数量", "limitCount": "已领取数量",
"receive": "领取记录", "receive": "领取记录",
"user": "是", "user": "是",
"grant": "否", "grant": "否",
"limit": "限量", "limit": "限量",
"unlimited": "不限量", "unlimited": "不限量",
"receiveNumber": "发放数量", "receiveNumber": "发放数量",
"pricePlaceholder": "请输入优惠券面值", "pricePlaceholder": "请输入优惠券面值",
"remainCountPlaceholder": "最多发放100000张", "remainCountPlaceholder": "最多发放100000张",
"reduction": "满减券", "reduction": "满减券",
"noThreshold": "无门槛券", "noThreshold": "无门槛券",
"threshold": "使用门槛", "threshold": "使用门槛",
"minConditionMoneyPlaceholder": "请输入优惠券的最低消费金额", "minConditionMoneyPlaceholder": "请输入优惠券的最低消费金额",
"userLimitCount": "限领张数", "userLimitCount": "限领张数",
"userLimitCountPlaceholder": "请输入限领张数", "userLimitCountPlaceholder": "请输入限领张数",
"receiveTime": "领取时间", "receiveTime": "领取时间",
"limitedTime": "限时", "limitedTime": "限时",
"unlimitedTime": "不限时", "unlimitedTime": "不限时",
"days":"天数", "days": "天数",
"times": "固定时间", "times": "固定时间",
"validType": "有效期", "validType": "有效期",
"lengthPlaceholder": "请输入使用时间", "lengthPlaceholder": "请输入使用时间",
"status": "状态", "status": "状态",
"open": "开启", "open": "开启",
"close": "关闭", "close": "关闭",
"cancel": "取消", "cancel": "取消",
"save": "保存", "save": "保存",
"startDate": "开始时间", "startDate": "开始时间",
"endDate": "结束时间", "endDate": "结束时间",
"validTimePlaceholder": "用券截止时间", "validTimePlaceholder": "用券截止时间",
"arrivalTimePlaceholder": "领券截止时间" "arrivalTimePlaceholder": "领券截止时间"
} }

82
admin/src/addon/shop/lang/zh-cn/marketing.coupon.edit.json

@ -1,42 +1,42 @@
{ {
"editCoupon": "编辑优惠券", "editCoupon": "编辑优惠券",
"title": "名称", "title": "名称",
"titlePlaceholder": "请如:XXX优惠券,最多20个字", "titlePlaceholder": "请如:XXX优惠券,最多20个字",
"type": "类型", "type": "类型",
"price": "面值", "price": "面值",
"receiveType": "是否手动领取", "receiveType": "是否手动领取",
"startTime": "开始时间", "startTime": "开始时间",
"endTime": "结束时间", "endTime": "结束时间",
"remainCount": "剩余数量", "remainCount": "剩余数量",
"limitCount": "已领取数量", "limitCount": "已领取数量",
"receive": "领取记录", "receive": "领取记录",
"user": "是", "user": "是",
"grant": "否", "grant": "否",
"limit": "限量", "limit": "限量",
"unlimited": "不限量", "unlimited": "不限量",
"receiveNumber": "发放数量", "receiveNumber": "发放数量",
"pricePlaceholder": "请输入优惠券面值", "pricePlaceholder": "请输入优惠券面值",
"remainCountPlaceholder": "最多发放100000张", "remainCountPlaceholder": "最多发放100000张",
"reduction": "满减券", "reduction": "满减券",
"noThreshold": "无门槛券", "noThreshold": "无门槛券",
"threshold": "使用门槛", "threshold": "使用门槛",
"minConditionMoneyPlaceholder": "请输入优惠券的最低消费金额", "minConditionMoneyPlaceholder": "请输入优惠券的最低消费金额",
"userLimitCount": "限领张数", "userLimitCount": "限领张数",
"userLimitCountPlaceholder": "请输入限领张数", "userLimitCountPlaceholder": "请输入限领张数",
"receiveTime": "领取时间", "receiveTime": "领取时间",
"limitedTime": "限时", "limitedTime": "限时",
"unlimitedTime": "不限时", "unlimitedTime": "不限时",
"days":"天数", "days": "天数",
"times": "固定时间", "times": "固定时间",
"validType": "使用时间", "validType": "使用时间",
"lengthPlaceholder": "请输入使用时间", "lengthPlaceholder": "请输入使用时间",
"status": "状态", "status": "状态",
"open": "开启", "open": "开启",
"close": "关闭", "close": "关闭",
"cancel": "取消", "cancel": "取消",
"save": "保存", "save": "保存",
"startDate": "开始时间", "startDate": "开始时间",
"endDate": "结束时间", "endDate": "结束时间",
"validTimePlaceholder": "用券截止时间", "validTimePlaceholder": "用券截止时间",
"arrivalTimePlaceholder": "领券截止时间" "arrivalTimePlaceholder": "领券截止时间"
} }

90
admin/src/addon/shop/lang/zh-cn/marketing.coupon.list.json

@ -1,47 +1,47 @@
{ {
"addCoupon": "添加优惠券", "addCoupon": "添加优惠券",
"title": "名称", "title": "名称",
"titlePlaceholder": "请输入优惠券名称", "titlePlaceholder": "请输入优惠券名称",
"type": "类型", "type": "类型",
"price": "面值", "price": "面值",
"receiveType": "是否手动领取", "receiveType": "是否手动领取",
"startTime": "开始时间", "startTime": "开始时间",
"endTime": "结束时间", "endTime": "结束时间",
"sumCount": "剩余数量/发放数量", "sumCount": "剩余数量/发放数量",
"remainCount": "已领用/已使用", "remainCount": "已领用/已使用",
"receive": "领取记录", "receive": "领取记录",
"edit": "编辑", "edit": "编辑",
"Status": "是否关闭领取", "Status": "是否关闭领取",
"threshold": "使用门槛", "threshold": "使用门槛",
"reduction": "满减券", "reduction": "满减券",
"noThreshold": "无门槛券", "noThreshold": "无门槛券",
"couponDeleteTips": "确定要删除该优惠券吗?", "couponDeleteTips": "确定要删除该优惠券吗?",
"couponColseTips": "确定要关闭该优惠券吗?关闭后将不可领取,若会员已领取将变为失效", "couponColseTips": "确定要关闭该优惠券吗?关闭后将不可领取,若会员已领取将变为失效",
"validType": "有效期", "validType": "有效期",
"statusName":"状态", "statusName": "状态",
"receiveTypeTime": "领取有效期", "receiveTypeTime": "领取有效期",
"spreadGoods":"推广", "spreadGoods": "推广",
"close":"关闭", "close": "关闭",
"couponSpreadTitle":"优惠券推广", "couponSpreadTitle": "优惠券推广",
"downloadQrcode": "下载二维码", "downloadQrcode": "下载二维码",
"spreadLink": "推广链接", "spreadLink": "推广链接",
"receiveUseCount": "已使用", "receiveUseCount": "已使用",
"collectionCoupon":"领取记录", "collectionCoupon": "领取记录",
"collectionTtitle": "优惠券名称", "collectionTtitle": "优惠券名称",
"userName": "领用会员", "userName": "领用会员",
"collectionReceiveType": "领用方式", "collectionReceiveType": "领用方式",
"createTime": "领取时间", "createTime": "领取时间",
"expireTime": "到期时间", "expireTime": "到期时间",
"status":"当前状态", "status": "当前状态",
"useTime": "使用时间", "useTime": "使用时间",
"validity":"使用有效期", "validity": "使用有效期",
"mobile": "手机号", "mobile": "手机号",
"memberInfo": "会员信息", "memberInfo": "会员信息",
"memberInfoPlaceholder":"请输入会员昵称/手机号", "memberInfoPlaceholder": "请输入会员昵称/手机号",
"collectionSumCount": "发放数量", "collectionSumCount": "发放数量",
"couponInfo": "优惠券基本信息", "couponInfo": "优惠券基本信息",
"receiveCount":"已领取", "receiveCount": "已领取",
"receiveExpireCount":"已过期", "receiveExpireCount": "已过期",
"showOrder": "查看订单" "showOrder": "查看订单"
} }

72
admin/src/addon/shop/lang/zh-cn/marketing.discount.add.json

@ -1,38 +1,38 @@
{ {
"editDiscount":"添加限时折扣", "editDiscount": "添加限时折扣",
"name": "活动名称", "name": "活动名称",
"namePlaceholder":"请输入活动名称", "namePlaceholder": "请输入活动名称",
"nameTip":"活动标题用于在手机或者电脑前端,建议输入长度不要大于5", "nameTip": "活动标题用于在手机或者电脑前端,建议输入长度不要大于5",
"title":"标题", "title": "标题",
"titlePlaceholder":"请输入活动标题", "titlePlaceholder": "请输入活动标题",
"titleTip":"活动标题用户展示在手机或者电脑前端展示使用,建议输入长度不要大于5", "titleTip": "活动标题用户展示在手机或者电脑前端展示使用,建议输入长度不要大于5",
"activityTime": "活动时间", "activityTime": "活动时间",
"discountTimePlaceholder":"请选择活动时间", "discountTimePlaceholder": "请选择活动时间",
"selectProduct": "选择商品", "selectProduct": "选择商品",
"selectProductPlaceholder": "请选择商品", "selectProductPlaceholder": "请选择商品",
"noSpaceAllowed": "内容不能为空", "noSpaceAllowed": "内容不能为空",
"batchOperation": "批量设置", "batchOperation": "批量设置",
"batchEmptySelectedGoodsTips": "请选择要操作的商品", "batchEmptySelectedGoodsTips": "请选择要操作的商品",
"discountType":"折扣类型", "discountType": "折扣类型",
"price":"原价", "price": "原价",
"discounts":"打折", "discounts": "打折",
"discountsTips":"[打折]格式错误", "discountsTips": "[打折]格式错误",
"discountsTipsTwo":"打折折扣不可小于0", "discountsTipsTwo": "打折折扣不可小于0",
"discountsTipsThree":"打折折扣不可大于9.9", "discountsTipsThree": "打折折扣不可大于9.9",
"discountsPlaceholder":"请输入打折折扣", "discountsPlaceholder": "请输入打折折扣",
"reduceMoney":"减钱", "reduceMoney": "减钱",
"reduceMoneyTips":"[减钱]格式错误", "reduceMoneyTips": "[减钱]格式错误",
"reduceMoneyTipsTwo":"减钱金额不可小于等于0", "reduceMoneyTipsTwo": "减钱金额不可小于等于0",
"reduceMoneyTipsThree":"减钱金额不可大于等于原价金额", "reduceMoneyTipsThree": "减钱金额不可大于等于原价金额",
"reduceMoneyPlaceholder":"请输入减钱金额", "reduceMoneyPlaceholder": "请输入减钱金额",
"promotional":"促销价", "promotional": "促销价",
"promotionalTips":"[促销价]格式错误", "promotionalTips": "[促销价]格式错误",
"promotionalTipsTwo":"促销价金额不可小于等于0", "promotionalTipsTwo": "促销价金额不可小于等于0",
"promotionalTipsThree":"促销价金额不可大于等于原价金额", "promotionalTipsThree": "促销价金额不可大于等于原价金额",
"promotionalPlaceholder":"请输入促销价", "promotionalPlaceholder": "请输入促销价",
"delete":"删除", "delete": "删除",
"enabled":"设为参与", "enabled": "设为参与",
"noEnabled":"设为不参与", "noEnabled": "设为不参与",
"skuDiscountSettings":"规格折扣设置", "skuDiscountSettings": "规格折扣设置",
"skuDiscountSettingsPlaceholder":"请输入规格折扣设置" "skuDiscountSettingsPlaceholder": "请输入规格折扣设置"
} }

14
admin/src/addon/shop/lang/zh-cn/marketing.discount.config.json

@ -1,8 +1,8 @@
{ {
"headTitle":"顶部广告图", "headTitle": "顶部广告图",
"image":"图片上传", "image": "图片上传",
"imagePlaceholder":"请上传图片", "imagePlaceholder": "请上传图片",
"toLink":"跳转链接", "toLink": "跳转链接",
"toLinkPlaceholder":"请输入跳转链接", "toLinkPlaceholder": "请输入跳转链接",
"addConfigList":"添加广告图" "addConfigList": "添加广告图"
} }

2
admin/src/addon/shop/lang/zh-cn/marketing.discount.detail.json

@ -34,4 +34,4 @@
"participationNum": "参与次数", "participationNum": "参与次数",
"orderTime": "最后下单时间", "orderTime": "最后下单时间",
"memberInfo": "会员信息" "memberInfo": "会员信息"
} }

72
admin/src/addon/shop/lang/zh-cn/marketing.discount.edit.json

@ -1,38 +1,38 @@
{ {
"editDiscount":"编辑限时折扣", "editDiscount": "编辑限时折扣",
"name": "活动名称", "name": "活动名称",
"namePlaceholder":"请输入活动名称", "namePlaceholder": "请输入活动名称",
"nameTip":"活动名称用于展示在商家后台管理", "nameTip": "活动名称用于展示在商家后台管理",
"title":"标题", "title": "标题",
"titlePlaceholder":"请输入活动标题", "titlePlaceholder": "请输入活动标题",
"titleTip":"活动标题用于在手机或者电脑前端,建议输入长度不要大于5", "titleTip": "活动标题用于在手机或者电脑前端,建议输入长度不要大于5",
"activityTime": "活动时间", "activityTime": "活动时间",
"discountTimePlaceholder":"请选择活动时间", "discountTimePlaceholder": "请选择活动时间",
"noSpaceAllowed":"内容不能为空", "noSpaceAllowed": "内容不能为空",
"selectProduct": "选择商品", "selectProduct": "选择商品",
"selectProductPlaceholder": "请选择商品", "selectProductPlaceholder": "请选择商品",
"batchOperation": "批量设置", "batchOperation": "批量设置",
"batchEmptySelectedGoodsTips": "请选择要操作的商品", "batchEmptySelectedGoodsTips": "请选择要操作的商品",
"discountType":"折扣类型", "discountType": "折扣类型",
"price":"原价", "price": "原价",
"discounts":"打折", "discounts": "打折",
"discountsTips":"[打折]格式错误", "discountsTips": "[打折]格式错误",
"discountsTipsTwo":"打折折扣不可小于0", "discountsTipsTwo": "打折折扣不可小于0",
"discountsTipsThree":"打折折扣不可大于9.9", "discountsTipsThree": "打折折扣不可大于9.9",
"discountsPlaceholder":"请输入打折折扣", "discountsPlaceholder": "请输入打折折扣",
"reduceMoney":"减钱", "reduceMoney": "减钱",
"reduceMoneyTips":"[减钱]格式错误", "reduceMoneyTips": "[减钱]格式错误",
"reduceMoneyTipsTwo":"减钱金额不可小于等于0", "reduceMoneyTipsTwo": "减钱金额不可小于等于0",
"reduceMoneyTipsThree":"减钱金额不可大于等于原价金额", "reduceMoneyTipsThree": "减钱金额不可大于等于原价金额",
"reduceMoneyPlaceholder":"请输入减钱金额", "reduceMoneyPlaceholder": "请输入减钱金额",
"promotional":"促销价", "promotional": "促销价",
"promotionalTips":"[促销价]格式错误", "promotionalTips": "[促销价]格式错误",
"promotionalTipsTwo":"促销价金额不可小于等于0", "promotionalTipsTwo": "促销价金额不可小于等于0",
"promotionalTipsThree":"促销价金额不可大于等于原价金额", "promotionalTipsThree": "促销价金额不可大于等于原价金额",
"promotionalPlaceholder":"请输入促销价", "promotionalPlaceholder": "请输入促销价",
"delete":"删除", "delete": "删除",
"enabled":"设为参与", "enabled": "设为参与",
"noEnabled":"设为不参与", "noEnabled": "设为不参与",
"skuDiscountSettings":"规格折扣设置", "skuDiscountSettings": "规格折扣设置",
"skuDiscountSettingsPlaceholder":"请输入规格折扣设置" "skuDiscountSettingsPlaceholder": "请输入规格折扣设置"
} }

98
admin/src/addon/shop/lang/zh-cn/marketing.discount.list.json

@ -1,50 +1,50 @@
{ {
"addDiscount":"添加限时折扣", "addDiscount": "添加限时折扣",
"name":"名称", "name": "名称",
"namePlaceholder":"请输入活动名称", "namePlaceholder": "请输入活动名称",
"title":"标题", "title": "标题",
"status":"状态", "status": "状态",
"statusPlaceholder":"请选择状态", "statusPlaceholder": "请选择状态",
"paymentAmount":"支付金额", "paymentAmount": "支付金额",
"memberCount":"会员数", "memberCount": "会员数",
"orderCount":"订单数", "orderCount": "订单数",
"discountTime":"活动时间", "discountTime": "活动时间",
"detail":"详情", "detail": "详情",
"close":"关闭", "close": "关闭",
"closeTips":"活动正在进行中,是否确认关闭当前活动?", "closeTips": "活动正在进行中,是否确认关闭当前活动?",
"deleteTips":"是否确认删除当前活动", "deleteTips": "是否确认删除当前活动",
"baseInfo": "基础信息", "baseInfo": "基础信息",
"createTime": "创建时间", "createTime": "创建时间",
"startTime": "活动开始时间", "startTime": "活动开始时间",
"endTime": "活动结束时间", "endTime": "活动结束时间",
"keywordPlaceholder": "请输入商品名称", "keywordPlaceholder": "请输入商品名称",
"keyword": "商品名称", "keyword": "商品名称",
"goodsInfo": "商品信息", "goodsInfo": "商品信息",
"price": "商品价格", "price": "商品价格",
"activeOrderMoney": "累计订单金额", "activeOrderMoney": "累计订单金额",
"activeOrderNum": "累计订单数", "activeOrderNum": "累计订单数",
"activeMemberNum": "参与会员数", "activeMemberNum": "参与会员数",
"activeSuccessNum": "支付销量", "activeSuccessNum": "支付销量",
"orderInfo": "订单编号", "orderInfo": "订单编号",
"payTime": "支付时间", "payTime": "支付时间",
"orderNo": "订单编号", "orderNo": "订单编号",
"orderMoney": "订单金额", "orderMoney": "订单金额",
"buyInfo": "买家/收货人", "buyInfo": "买家/收货人",
"payType": "支付类型", "payType": "支付类型",
"orderStatus": "订单状态", "orderStatus": "订单状态",
"toBePaid": "待支付", "toBePaid": "待支付",
"toBeShipped": "待发货", "toBeShipped": "待发货",
"shipped": "已发货", "shipped": "已发货",
"receivedGoods": "已收货", "receivedGoods": "已收货",
"completed": "已完成", "completed": "已完成",
"closed": "已关闭", "closed": "已关闭",
"consumptionMoney": "消费总额", "consumptionMoney": "消费总额",
"participationNum": "参与次数", "participationNum": "参与次数",
"orderTime": "最后下单时间", "orderTime": "最后下单时间",
"memberInfo": "会员信息", "memberInfo": "会员信息",
"activeName": "活动名称", "activeName": "活动名称",
"participationMemberCount": "参与会员数", "participationMemberCount": "参与会员数",
"payOrderCount": "支付订单数", "payOrderCount": "支付订单数",
"startDate": "开始时间", "startDate": "开始时间",
"endDate": "结束时间" "endDate": "结束时间"
} }

124
admin/src/addon/shop/lang/zh-cn/marketing.exchange.goods_add.json

@ -1,66 +1,66 @@
{ {
"addGoods":"添加商品", "addGoods": "添加商品",
"baseInfo":"基础设置", "baseInfo": "基础设置",
"goodsType":"商品类型", "goodsType": "商品类型",
"goodsName":"商品名称", "goodsName": "商品名称",
"goodsNamePlaceholder":"请输入商品名称", "goodsNamePlaceholder": "请输入商品名称",
"goodsTitle":"副标题", "goodsTitle": "副标题",
"goodsTitlePlaceholder":"请输入副标题", "goodsTitlePlaceholder": "请输入副标题",
"image":"商品图片", "image": "商品图片",
"imagePlaceholder":"请选择商品图片", "imagePlaceholder": "请选择商品图片",
"selectProduct": "选择商品", "selectProduct": "选择商品",
"selectGoodsPlaceholder": "请选择商品", "selectGoodsPlaceholder": "请选择商品",
"goodsStatus":"商品状态", "goodsStatus": "商品状态",
"goodsSelect":"选择商品", "goodsSelect": "选择商品",
"redemptionSettings":"积分设置", "redemptionSettings": "积分设置",
"batchOperation": "批量设置", "batchOperation": "批量设置",
"batchEmptySelectedGoodsTips": "请选择要操作的商品", "batchEmptySelectedGoodsTips": "请选择要操作的商品",
"goodsSelectPopupGoodsInfo":"商品信息", "goodsSelectPopupGoodsInfo": "商品信息",
"price":"销售价", "price": "销售价",
"stock":"兑换库存", "stock": "兑换库存",
"stockPlaceholder":"请输入兑换库存", "stockPlaceholder": "请输入兑换库存",
"stockTips":"[兑换库存]格式错误", "stockTips": "[兑换库存]格式错误",
"stockTipsTwo":"兑换库存不可小于等于0", "stockTipsTwo": "兑换库存不可小于等于0",
"stockTipsThree":"兑换限制数量不可大于商品库存", "stockTipsThree": "兑换限制数量不可大于商品库存",
"limit":"兑换限制", "limit": "兑换限制",
"limitPlaceholder":"请输入兑换限制", "limitPlaceholder": "请输入兑换限制",
"limitTips":"[兑换限制]格式错误", "limitTips": "[兑换限制]格式错误",
"limitTipsTwo":"兑换限制数量不可小于等于0", "limitTipsTwo": "兑换限制数量不可小于等于0",
"limitTipsThree":"兑换限制数量不能大于兑换库存", "limitTipsThree": "兑换限制数量不能大于兑换库存",
"limitUnit":"件/人", "limitUnit": "件/人",
"integralUnit":"积分", "integralUnit": "积分",
"prickUnit":"元", "prickUnit": "元",
"pointPlaceholder":"请输入积分积分", "pointPlaceholder": "请输入积分积分",
"pointTips":"[积分]格式错误", "pointTips": "[积分]格式错误",
"pointTipsTwo":"积分不可小于等于0", "pointTipsTwo": "积分不可小于等于0",
"money":"兑换价", "money": "兑换价",
"newPrice":"价格", "newPrice": "价格",
"moneyTips":"[价格]格式错误", "moneyTips": "[价格]格式错误",
"moneyTipsTwo":"价格不可小于0", "moneyTipsTwo": "价格不可小于0",
"limitRules":"每人每单可兑换件数", "limitRules": "每人每单可兑换件数",
"couponSelect":"选择优惠券",
"couponSelectPlaceholder":"请选择优惠券",
"couponName":"优惠券名称",
"couponType":"类型",
"couponPrice":"面值",
"sumCount":"总库存",
"threshold": "使用门槛",
"validType": "有效期",
"receiveTypeTime": "领取有效期",
"balance":"兑换余额", "couponSelect": "选择优惠券",
"balancePlaceholder":"请输入兑换余额", "couponSelectPlaceholder": "请选择优惠券",
"balanceTips":"[兑换余额]格式错误", "couponName": "优惠券名称",
"balanceTipsTwo":"兑换余额不可小于等于0", "couponType": "类型",
"balanceType":"余额类型", "couponPrice": "面值",
"sumCount": "总库存",
"threshold": "使用门槛",
"validType": "有效期",
"receiveTypeTime": "领取有效期",
"goodsSkuTitle":"选择商品规格", "balance": "兑换余额",
"goodsSkuPlaceholder":"请选择商品规格", "balancePlaceholder": "请输入兑换余额",
"goodsStock":"库存", "balanceTips": "[兑换余额]格式错误",
"enabled":"设为参与", "balanceTipsTwo": "兑换余额不可小于等于0",
"noEnabled":"设为不参与", "balanceType": "余额类型",
"noEnabledTip":"请至少设置一个规格参与",
"goodsDetail":"商品详情" "goodsSkuTitle": "选择商品规格",
} "goodsSkuPlaceholder": "请选择商品规格",
"goodsStock": "库存",
"enabled": "设为参与",
"noEnabled": "设为不参与",
"noEnabledTip": "请至少设置一个规格参与",
"goodsDetail": "商品详情"
}

123
admin/src/addon/shop/lang/zh-cn/marketing.exchange.goods_edit.json

@ -1,67 +1,66 @@
{ {
"editGoods":"编辑商品", "editGoods": "编辑商品",
"baseInfo":"基础设置", "baseInfo": "基础设置",
"goodsType":"商品类型", "goodsType": "商品类型",
"goodsName":"商品名称", "goodsName": "商品名称",
"goodsNamePlaceholder":"请输入商品名称", "goodsNamePlaceholder": "请输入商品名称",
"goodsTitle":"副标题", "goodsTitle": "副标题",
"goodsTitlePlaceholder":"请输入副标题", "goodsTitlePlaceholder": "请输入副标题",
"image":"商品图片", "image": "商品图片",
"imagePlaceholder":"请选择商品图片", "imagePlaceholder": "请选择商品图片",
"selectProduct": "选择商品", "selectProduct": "选择商品",
"selectGoodsPlaceholder": "请选择商品", "selectGoodsPlaceholder": "请选择商品",
"goodsStatus":"商品状态", "goodsStatus": "商品状态",
"goodsSelect":"选择商品", "goodsSelect": "选择商品",
"redemptionSettings":"积分设置", "redemptionSettings": "积分设置",
"batchOperation": "批量设置", "batchOperation": "批量设置",
"batchEmptySelectedGoodsTips": "请选择要操作的商品", "batchEmptySelectedGoodsTips": "请选择要操作的商品",
"goodsSelectPopupGoodsInfo":"商品信息", "goodsSelectPopupGoodsInfo": "商品信息",
"price":"销售价", "price": "销售价",
"stock":"兑换库存", "stock": "兑换库存",
"stockPlaceholder":"请输入兑换库存", "stockPlaceholder": "请输入兑换库存",
"stockTips":"[兑换库存]格式错误", "stockTips": "[兑换库存]格式错误",
"stockTipsTwo":"兑换库存不可小于等于0", "stockTipsTwo": "兑换库存不可小于等于0",
"stockTipsThree":"兑换限制数量不可大于商品库存", "stockTipsThree": "兑换限制数量不可大于商品库存",
"limit":"兑换限制", "limit": "兑换限制",
"limitPlaceholder":"请输入兑换限制", "limitPlaceholder": "请输入兑换限制",
"limitTips":"[兑换限制]格式错误", "limitTips": "[兑换限制]格式错误",
"limitTipsTwo":"兑换限制数量不可小于等于0", "limitTipsTwo": "兑换限制数量不可小于等于0",
"limitTipsThree":"兑换限制数量不能大于兑换库存", "limitTipsThree": "兑换限制数量不能大于兑换库存",
"limitUnit":"件/人", "limitUnit": "件/人",
"integralUnit":"积分", "integralUnit": "积分",
"prickUnit":"元", "prickUnit": "元",
"pointPlaceholder":"请输入积分积分", "pointPlaceholder": "请输入积分积分",
"pointTips":"[积分]格式错误", "pointTips": "[积分]格式错误",
"pointTipsTwo":"积分不可小于等于0", "pointTipsTwo": "积分不可小于等于0",
"money":"兑换价", "money": "兑换价",
"newPrice":"价格", "newPrice": "价格",
"moneyTips":"[价格]格式错误", "moneyTips": "[价格]格式错误",
"moneyTipsTwo":"价格不可小于0", "moneyTipsTwo": "价格不可小于0",
"limitRules":"每人每单可兑换件数", "limitRules": "每人每单可兑换件数",
"couponSelect": "选择优惠券",
"couponSelect":"选择优惠券", "couponSelectPlaceholder": "请选择优惠券",
"couponSelectPlaceholder":"请选择优惠券", "couponName": "优惠券名称",
"couponName":"优惠券名称", "couponType": "类型",
"couponType":"类型", "couponPrice": "面值",
"couponPrice":"面值", "sumCount": "总库存",
"sumCount":"总库存", "threshold": "使用门槛",
"threshold": "使用门槛", "validType": "有效期",
"validType": "有效期", "receiveTypeTime": "领取有效期",
"receiveTypeTime": "领取有效期",
"balance":"兑换余额", "balance": "兑换余额",
"balancePlaceholder":"请输入兑换余额", "balancePlaceholder": "请输入兑换余额",
"balanceTips":"[兑换余额]格式错误", "balanceTips": "[兑换余额]格式错误",
"balanceTipsTwo":"兑换余额不可小于等于0", "balanceTipsTwo": "兑换余额不可小于等于0",
"balanceType":"余额类型", "balanceType": "余额类型",
"goodsSkuTitle":"选择商品规格", "goodsSkuTitle": "选择商品规格",
"goodsSkuPlaceholder":"请选择商品规格", "goodsSkuPlaceholder": "请选择商品规格",
"goodsStock":"库存", "goodsStock": "库存",
"enabled":"设为参与", "enabled": "设为参与",
"noEnabled":"设为不参与", "noEnabled": "设为不参与",
"noEnabledTip":"请至少设置一个规格参与", "noEnabledTip": "请至少设置一个规格参与",
"goodsDetail":"商品详情" "goodsDetail": "商品详情"
} }

52
admin/src/addon/shop/lang/zh-cn/marketing.exchange.goods_list.json

@ -1,27 +1,27 @@
{ {
"addGoods":"添加商品", "addGoods": "添加商品",
"goods":"商品", "goods": "商品",
"goodsName":"商品名称", "goodsName": "商品名称",
"goodsNamePlaceholder":"请输入商品名称", "goodsNamePlaceholder": "请输入商品名称",
"status":"状态", "status": "状态",
"statusPlaceholder":"请选择状态", "statusPlaceholder": "请选择状态",
"goodsType":"商品类型", "goodsType": "商品类型",
"exchangePrice":"兑换价格", "exchangePrice": "兑换价格",
"pointUnit":"积分", "pointUnit": "积分",
"priceUnit":"元", "priceUnit": "元",
"redeemedAndSurplus":"已兑/剩余", "redeemedAndSurplus": "已兑/剩余",
"deleteTips":"是否确认删除当前商品", "deleteTips": "是否确认删除当前商品",
"createTime":"创建时间", "createTime": "创建时间",
"spreadGoods": "推广", "spreadGoods": "推广",
"copyGoods": "复制", "copyGoods": "复制",
"spreadLink": "推广链接", "spreadLink": "推广链接",
"copy": "复制", "copy": "复制",
"downloadQrcode": "下载二维码", "downloadQrcode": "下载二维码",
"goodsSpreadTitle": "积分商品推广", "goodsSpreadTitle": "积分商品推广",
"up":"上架", "up": "上架",
"upTips":"是否确认上架当前商品", "upTips": "是否确认上架当前商品",
"down":"下架", "down": "下架",
"downTips":"是否确认下架当前商品", "downTips": "是否确认下架当前商品",
"startDate":"开始时间", "startDate": "开始时间",
"endDate":"结束时间" "endDate": "结束时间"
} }

106
admin/src/addon/shop/lang/zh-cn/marketing.exchange.order_list.json

@ -1,55 +1,55 @@
{ {
"orderNo":"订单编号", "orderNo": "订单编号",
"orderNoPlaceholder": "请输入订单编号", "orderNoPlaceholder": "请输入订单编号",
"orderStatus": "订单状态", "orderStatus": "订单状态",
"orderStatusPlaceholder": "请选择订单状态", "orderStatusPlaceholder": "请选择订单状态",
"orderFrom": "订单类型", "orderFrom": "订单类型",
"orderFromPlaceholder": "请选择订单类型", "orderFromPlaceholder": "请选择订单类型",
"payTime": "支付时间", "payTime": "支付时间",
"orderGoods": "商品", "orderGoods": "商品",
"goodsPriceNumber": "单价(元)/数量", "goodsPriceNumber": "单价(元)/数量",
"orderMoney": "实付金额(元)", "orderMoney": "实付金额(元)",
"startDate": "开始时间", "startDate": "开始时间",
"endDate": "结束时间", "endDate": "结束时间",
"piece": "件", "piece": "件",
"activeRefund": "主动退款", "activeRefund": "主动退款",
"notes": "备注", "notes": "备注",
"offlinePayment": "线下支付", "offlinePayment": "线下支付",
"orderClose": "关闭订单", "orderClose": "关闭订单",
"editPrice": "修改价格", "editPrice": "修改价格",
"editAddress": "修改地址", "editAddress": "修改地址",
"sendOutGoods": "发货", "sendOutGoods": "发货",
"confirmTakeDelivery": "确认收货", "confirmTakeDelivery": "确认收货",
"all": "全部", "all": "全部",
"toBeShipped": "待发货", "toBeShipped": "待发货",
"shipped": "已发货", "shipped": "已发货",
"receivedGoods": "已收货", "receivedGoods": "已收货",
"completed": "已完成", "completed": "已完成",
"closed": "已关闭", "closed": "已关闭",
"refunding": "退款中", "refunding": "退款中",
"notesDetail": "备注信息", "notesDetail": "备注信息",
"delivery": "订单发货",
"company": "物流公司",
"companyPlaceholder": "请选择物流公司",
"expressNumber": "物流单号",
"expressNumberPlaceholder": "请输入物流单号",
"orderGoodsIdsPlaceholder": "请选择订单项",
"virtualDelivery": "虚拟发货",
"goodsName": "商品名称",
"num": "商品数量",
"orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
"orderFinishTips": "是否确认用户已经收货?",
"orderGoodsPlaceholder": "请选择要发货的商品",
"deliveryStatusName": "发货状态",
"fromType": "订单来源",
"payType": "支付类型",
"orderInfo": "订单信息",
"refundStatusName": "退款状态",
"outTradeNo": "交易流水号",
"exportOrderType": "导出订单类型", "delivery": "订单发货",
"shopOrder": "订单数据表", "company": "物流公司",
"shopOrderGoods": "订单商品表", "companyPlaceholder": "请选择物流公司",
"point":"积分" "expressNumber": "物流单号",
} "expressNumberPlaceholder": "请输入物流单号",
"orderGoodsIdsPlaceholder": "请选择订单项",
"virtualDelivery": "虚拟发货",
"goodsName": "商品名称",
"num": "商品数量",
"orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
"orderFinishTips": "是否确认用户已经收货?",
"orderGoodsPlaceholder": "请选择要发货的商品",
"deliveryStatusName": "发货状态",
"fromType": "订单来源",
"payType": "支付类型",
"orderInfo": "订单信息",
"refundStatusName": "退款状态",
"outTradeNo": "交易流水号",
"exportOrderType": "导出订单类型",
"shopOrder": "订单数据表",
"shopOrderGoods": "订单商品表",
"point": "积分"
}

72
admin/src/addon/shop/lang/zh-cn/marketing.manjian.detail.json

@ -1,37 +1,37 @@
{ {
"baseInfo": "基础信息", "baseInfo": "基础信息",
"name": "活动名称", "name": "活动名称",
"title": "标题", "title": "标题",
"status": "状态", "status": "状态",
"paymentAmount": "支付金额", "paymentAmount": "支付金额",
"memberCount": "参与会员数", "memberCount": "参与会员数",
"orderCount": "支付订单数", "orderCount": "支付订单数",
"createTime": "创建时间", "createTime": "创建时间",
"startTime": "活动开始时间", "startTime": "活动开始时间",
"endTime": "活动结束时间", "endTime": "活动结束时间",
"keywordPlaceholder": "请输入商品名称", "keywordPlaceholder": "请输入商品名称",
"keyword": "商品名称", "keyword": "商品名称",
"goodsInfo": "商品信息", "goodsInfo": "商品信息",
"price": "商品价格", "price": "商品价格",
"activeOrderMoney": "累计订单金额", "activeOrderMoney": "累计订单金额",
"activeOrderNum": "累计订单数", "activeOrderNum": "累计订单数",
"activeMemberNum": "参与会员数", "activeMemberNum": "参与会员数",
"activeSuccessNum": "支付销量", "activeSuccessNum": "支付销量",
"orderInfo": "订单编号", "orderInfo": "订单编号",
"payTime": "支付时间", "payTime": "支付时间",
"orderNo": "订单编号", "orderNo": "订单编号",
"orderMoney": "订单金额", "orderMoney": "订单金额",
"buyInfo": "买家/收货人", "buyInfo": "买家/收货人",
"payType": "支付类型", "payType": "支付类型",
"orderStatus": "订单状态", "orderStatus": "订单状态",
"toBePaid": "待支付", "toBePaid": "待支付",
"toBeShipped": "待发货", "toBeShipped": "待发货",
"shipped": "已发货", "shipped": "已发货",
"receivedGoods": "已收货", "receivedGoods": "已收货",
"completed": "已完成", "completed": "已完成",
"closed": "已关闭", "closed": "已关闭",
"consumptionMoney": "消费总额", "consumptionMoney": "消费总额",
"participationNum": "参与次数", "participationNum": "参与次数",
"orderTime": "最后下单时间", "orderTime": "最后下单时间",
"memberInfo": "会员信息" "memberInfo": "会员信息"
} }

2
admin/src/addon/shop/lang/zh-cn/marketing.manjian.edit.json

@ -84,5 +84,5 @@
"limitTipsThree": "必须大于上一层级的优惠门槛", "limitTipsThree": "必须大于上一层级的优惠门槛",
"ruleTypeTips": "阶梯优惠根据设定的门槛逐级增加优惠,达到特定层级门槛即可享受对应优惠,最高可设5个层级。", "ruleTypeTips": "阶梯优惠根据设定的门槛逐级增加优惠,达到特定层级门槛即可享受对应优惠,最高可设5个层级。",
"ruleTypeTipsTwo": "循环优惠指每次达到门槛即获赠一次优惠,无次数上限,需合理设置门槛。", "ruleTypeTipsTwo": "循环优惠指每次达到门槛即获赠一次优惠,无次数上限,需合理设置门槛。",
"goodsOffTips":"该商品已下架" "goodsOffTips": "该商品已下架"
} }

88
admin/src/addon/shop/lang/zh-cn/marketing.newcomer.config.json

@ -1,45 +1,45 @@
{ {
"basicInfoTab":"基础设置", "basicInfoTab": "基础设置",
"bannerList":"顶部广告图", "bannerList": "顶部广告图",
"activeStatus":"是否启用", "activeStatus": "是否启用",
"validityType":"有效期", "validityType": "有效期",
"validityDay":"天数", "validityDay": "天数",
"validityDayPlaceholder":"请输入有效天数", "validityDayPlaceholder": "请输入有效天数",
"validityDayTips":"有效天数不可小于等于0", "validityDayTips": "有效天数不可小于等于0",
"validityDayTipsLeft":"达成门槛立即生效,", "validityDayTipsLeft": "达成门槛立即生效,",
"validityDayTipsRight":"天有效期", "validityDayTipsRight": "天有效期",
"validityTime":"固定时间", "validityTime": "固定时间",
"validityTimePlaceholder":"请选择有效期截止时间", "validityTimePlaceholder": "请选择有效期截止时间",
"validityTimePlaceholderTwo":"请先选择参与门槛时间", "validityTimePlaceholderTwo": "请先选择参与门槛时间",
"validityTimePlaceholderThree":"有效期截止时间不可小于参与门槛时间", "validityTimePlaceholderThree": "有效期截止时间不可小于参与门槛时间",
"validityTimeTips":"达成门槛立即生效,有效期截止为", "validityTimeTips": "达成门槛立即生效,有效期截止为",
"validityTimeTipsTwo":"修改有效期将同步更新所有未参与活动用户的结束时间", "validityTimeTipsTwo": "修改有效期将同步更新所有未参与活动用户的结束时间",
"participationWay":"参与门槛", "participationWay": "参与门槛",
"neverOrder":"从未下过单的会员", "neverOrder": "从未下过单的会员",
"assignTimeOrder":"指定时间内未下过单的会员", "assignTimeOrder": "指定时间内未下过单的会员",
"assignTimeRegister":"指定时间内注册的会员", "assignTimeRegister": "指定时间内注册的会员",
"appointTimePlaceholder":"请选择指定时间", "appointTimePlaceholder": "请选择指定时间",
"activityGoods":"活动商品", "activityGoods": "活动商品",
"selectGoods":"选择商品", "selectGoods": "选择商品",
"goodsSkuIdsPlaceholder":"请选择商品", "goodsSkuIdsPlaceholder": "请选择商品",
"limitNum":"限购数量", "limitNum": "限购数量",
"limitNumPlaceholder":"请输入限购数量", "limitNumPlaceholder": "请输入限购数量",
"limitNumTips":"限购数量不可小于等于0", "limitNumTips": "限购数量不可小于等于0",
"limitNumTipsThree":"限购数量不可超过已选商品数量", "limitNumTipsThree": "限购数量不可超过已选商品数量",
"oldPrice":"原价", "oldPrice": "原价",
"newcomerPrice":"新人价", "newcomerPrice": "新人价",
"newcomerPricePlaceholder":"请输入新人价", "newcomerPricePlaceholder": "请输入新人价",
"newcomerPriceTips":"[新人价]格式错误", "newcomerPriceTips": "[新人价]格式错误",
"newcomerPriceTipsOne":"新人价不可小于0", "newcomerPriceTipsOne": "新人价不可小于0",
"newcomerPriceTipsTwo":"新人价不可大于原价", "newcomerPriceTipsTwo": "新人价不可大于原价",
"batchOperation":"批量操作", "batchOperation": "批量操作",
"batchEmptySelectedGoodsTips": "请选择要操作的商品", "batchEmptySelectedGoodsTips": "请选择要操作的商品",
"activeDesc":"规则说明", "activeDesc": "规则说明",
"activeDescPlaceholder":"请输入规则说明", "activeDescPlaceholder": "请输入规则说明",
"useDefaultActiveDesc": "使用默认说明", "useDefaultActiveDesc": "使用默认说明",
"image":"图片上传", "image": "图片上传",
"imagePlaceholder":"请上传图片", "imagePlaceholder": "请上传图片",
"toLink":"跳转链接", "toLink": "跳转链接",
"toLinkPlaceholder":"请输入跳转链接", "toLinkPlaceholder": "请输入跳转链接",
"addConfigList":"添加广告图" "addConfigList": "添加广告图"
} }

110
admin/src/addon/shop/lang/zh-cn/marketing.newcomer.order_list.json

@ -1,57 +1,57 @@
{ {
"orderNo":"订单编号", "orderNo": "订单编号",
"orderNoPlaceholder": "请输入订单编号", "orderNoPlaceholder": "请输入订单编号",
"orderStatus": "订单状态", "orderStatus": "订单状态",
"orderStatusPlaceholder": "请选择订单状态", "orderStatusPlaceholder": "请选择订单状态",
"orderFrom": "订单类型", "orderFrom": "订单类型",
"orderFromPlaceholder": "请选择订单类型", "orderFromPlaceholder": "请选择订单类型",
"payTime": "支付时间", "payTime": "支付时间",
"orderGoods": "商品", "orderGoods": "商品",
"goodsPriceNumber": "单价(元)/数量", "goodsPriceNumber": "单价(元)/数量",
"goodsPriceNumberTips": "新人价商品购买数量为1时,单价显示新人价,购买数量大于1时,单价显示原价或折扣价或会员价", "goodsPriceNumberTips": "新人价商品购买数量为1时,单价显示新人价,购买数量大于1时,单价显示原价或折扣价或会员价",
"orderMoney": "实付金额(元)", "orderMoney": "实付金额(元)",
"startDate": "开始时间", "startDate": "开始时间",
"endDate": "结束时间", "endDate": "结束时间",
"piece": "件", "piece": "件",
"createTime": "创建时间", "createTime": "创建时间",
"activeRefund": "主动退款", "activeRefund": "主动退款",
"notes": "备注", "notes": "备注",
"offlinePayment": "线下支付", "offlinePayment": "线下支付",
"orderClose": "关闭订单", "orderClose": "关闭订单",
"editPrice": "修改价格", "editPrice": "修改价格",
"editAddress": "修改地址", "editAddress": "修改地址",
"sendOutGoods": "发货", "sendOutGoods": "发货",
"confirmTakeDelivery": "确认收货", "confirmTakeDelivery": "确认收货",
"all": "全部", "all": "全部",
"toBeShipped": "待发货", "toBeShipped": "待发货",
"shipped": "已发货", "shipped": "已发货",
"receivedGoods": "已收货", "receivedGoods": "已收货",
"completed": "已完成", "completed": "已完成",
"closed": "已关闭", "closed": "已关闭",
"refunding": "退款中", "refunding": "退款中",
"notesDetail": "备注信息", "notesDetail": "备注信息",
"delivery": "订单发货",
"company": "物流公司",
"companyPlaceholder": "请选择物流公司",
"expressNumber": "物流单号",
"expressNumberPlaceholder": "请输入物流单号",
"orderGoodsIdsPlaceholder": "请选择订单项",
"virtualDelivery": "虚拟发货",
"goodsName": "商品名称",
"num": "商品数量",
"orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
"orderFinishTips": "是否确认用户已经收货?",
"orderGoodsPlaceholder": "请选择要发货的商品",
"deliveryStatusName": "发货状态",
"fromType": "订单来源",
"payType": "支付类型",
"orderInfo": "订单信息",
"refundStatusName": "退款状态",
"outTradeNo": "交易流水号",
"exportOrderType": "导出订单类型", "delivery": "订单发货",
"shopOrder": "订单数据表", "company": "物流公司",
"shopOrderGoods": "订单商品表", "companyPlaceholder": "请选择物流公司",
"point":"积分" "expressNumber": "物流单号",
} "expressNumberPlaceholder": "请输入物流单号",
"orderGoodsIdsPlaceholder": "请选择订单项",
"virtualDelivery": "虚拟发货",
"goodsName": "商品名称",
"num": "商品数量",
"orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
"orderFinishTips": "是否确认用户已经收货?",
"orderGoodsPlaceholder": "请选择要发货的商品",
"deliveryStatusName": "发货状态",
"fromType": "订单来源",
"payType": "支付类型",
"orderInfo": "订单信息",
"refundStatusName": "退款状态",
"outTradeNo": "交易流水号",
"exportOrderType": "导出订单类型",
"shopOrder": "订单数据表",
"shopOrderGoods": "订单商品表",
"point": "积分"
}

48
admin/src/addon/shop/lang/zh-cn/order.batch_delivery.json

@ -1,25 +1,25 @@
{ {
"failuresNum":"发货失败单数", "failuresNum": "发货失败单数",
"succeedNum":"发货成功单数", "succeedNum": "发货成功单数",
"totalNum":"总发货单数", "totalNum": "总发货单数",
"operationTime":"操作时间", "operationTime": "操作时间",
"operationType":"操作类型", "operationType": "操作类型",
"state":"状态", "state": "状态",
"operator":"操作人", "operator": "操作人",
"importData":"批量发货", "importData": "批量发货",
"templateType":"模板类型", "templateType": "模板类型",
"fullOrderDelivery":"整单发货模板", "fullOrderDelivery": "整单发货模板",
"openOrderDelivery":"拆单发货模板", "openOrderDelivery": "拆单发货模板",
"uploadFile":"上传文件", "uploadFile": "上传文件",
"createTime":"时间", "createTime": "时间",
"uploadFilePlaceholder":"请上传文件", "uploadFilePlaceholder": "请上传文件",
"operatorPlaceholder":"请选择操作人", "operatorPlaceholder": "请选择操作人",
"causeFailure":"下载失败记录", "causeFailure": "下载失败记录",
"downloadRecord":"下载记录", "downloadRecord": "下载记录",
"orderTemplate":"下载整单发货模板.xls", "orderTemplate": "下载整单发货模板.xls",
"orderGoodsTemplate":"下载拆单发货模板.xls", "orderGoodsTemplate": "下载拆单发货模板.xls",
"checkCause": "查看失败原因", "checkCause": "查看失败原因",
"startTime": "开始时间", "startTime": "开始时间",
"endTime": "结束时间", "endTime": "结束时间",
"checkCause1": "失败原因" "checkCause1": "失败原因"
} }

76
admin/src/addon/shop/lang/zh-cn/order.config.json

@ -1,41 +1,41 @@
{ {
"closeOrderInfo":"自动取消订单", "closeOrderInfo": "自动取消订单",
"closeOrderInfoLeft":"提交订单", "closeOrderInfoLeft": "提交订单",
"closeOrderInfoRight":"分钟未付款,自动取消订单", "closeOrderInfoRight": "分钟未付款,自动取消订单",
"closeOrderInfoBottom":"订单取消时间必须在10-1440分钟之间", "closeOrderInfoBottom": "订单取消时间必须在10-1440分钟之间",
"CloseLengthPlaceholder":"请输入订单取消时间", "CloseLengthPlaceholder": "请输入订单取消时间",
"isClose":"自动取消订单", "isClose": "自动取消订单",
"confirm":"自动确认收货", "confirm": "自动确认收货",
"confirmLeft":"发货后", "confirmLeft": "发货后",
"confirmRight":"天,自动确认收货", "confirmRight": "天,自动确认收货",
"confirmBottom":"自动确认收货时间必须在1-30天之间", "confirmBottom": "自动确认收货时间必须在1-30天之间",
"finishLengthPlaceholder":"请输入自动确认收货时间", "finishLengthPlaceholder": "请输入自动确认收货时间",
"isFinish":"自动确认收货", "isFinish": "自动确认收货",
"refund":"确认收货后售后", "refund": "确认收货后售后",
"refundLeft":"确认收货", "refundLeft": "确认收货",
"refundRight":"天内,可申请售后", "refundRight": "天内,可申请售后",
"refundBottom":"确认收货后售后时间必须在1-30天之间", "refundBottom": "确认收货后售后时间必须在1-30天之间",
"noAllowRefund":"确认收货后不支持售后", "noAllowRefund": "确认收货后不支持售后",
"validRefundLengthPlaceholder":"请输入确认收货后售后时间", "validRefundLengthPlaceholder": "请输入确认收货后售后时间",
"invoice":"发票设置", "invoice": "发票设置",
"isInvoice":"发票开关", "isInvoice": "发票开关",
"isInvoiceClose":"关闭", "isInvoiceClose": "关闭",
"isInvoiceOpen":"开启", "isInvoiceOpen": "开启",
"invoiceContent":"发票内容", "invoiceContent": "发票内容",
"insert":"添加", "insert": "添加",
"paperInvoice":"纸质发票", "paperInvoice": "纸质发票",
"electronicInvoice":"电子发票", "electronicInvoice": "电子发票",
"invoicePlaceholder":"所有发票内容不能为空", "invoicePlaceholder": "所有发票内容不能为空",
"invoiceType":"发票类型", "invoiceType": "发票类型",
"invoiceTypePlaceholder":"请至少选择一个发票类型", "invoiceTypePlaceholder": "请至少选择一个发票类型",
"evaluate": "评价设置", "evaluate": "评价设置",
"isEvaluate": "评价开关", "isEvaluate": "评价开关",
"evaluateIsToExamine": "评价审核", "evaluateIsToExamine": "评价审核",
"evaluateIsShow": "评价显示", "evaluateIsShow": "评价显示",
"isEvaluateOpen": "开启", "isEvaluateOpen": "开启",
"isEvaluateClose": "关闭", "isEvaluateClose": "关闭",
"diyForm": "万能表单", "diyForm": "万能表单",
"diyFormPlaceholder": "请选择万能表单", "diyFormPlaceholder": "请选择万能表单",
"addDiyForm": "添加表单" "addDiyForm": "添加表单"
} }

2
admin/src/addon/shop/lang/zh-cn/order.detail.json

@ -131,4 +131,4 @@
"refundGoodsNum": "数量", "refundGoodsNum": "数量",
"refundGoodsPlaceholder": "请选择退款的商品", "refundGoodsPlaceholder": "请选择退款的商品",
"formDetail": "表单详情" "formDetail": "表单详情"
} }

78
admin/src/addon/shop/lang/zh-cn/order.invoice.json

@ -1,40 +1,40 @@
{ {
"isInvoice":"是否开票", "isInvoice": "是否开票",
"isInvoicePlaceholder":"请输入开票类型", "isInvoicePlaceholder": "请输入开票类型",
"startDate":"开始时间", "startDate": "开始时间",
"endDate":"结束时间", "endDate": "结束时间",
"headType":"抬头类型", "headType": "抬头类型",
"headerTypeName":"抬头类型", "headerTypeName": "抬头类型",
"person":"个人", "person": "个人",
"firm":"企业", "firm": "企业",
"headTypePlaceholder":"请输入抬头类型", "headTypePlaceholder": "请输入抬头类型",
"headerName":"发票抬头", "headerName": "发票抬头",
"headerNamePlaceholder":"请输入发票抬头", "headerNamePlaceholder": "请输入发票抬头",
"name":"发票内容", "name": "发票内容",
"tradeType":"发票类型", "tradeType": "发票类型",
"typeName":"发票名称", "typeName": "发票名称",
"headTypeName":"抬头类型", "headTypeName": "抬头类型",
"taxNumber":"纳税人识别号", "taxNumber": "纳税人识别号",
"mobile":"手机号", "mobile": "手机号",
"email":"邮件", "email": "邮件",
"telephone":"电话号", "telephone": "电话号",
"address":"地址", "address": "地址",
"bankTame":"开户银行", "bankTame": "开户银行",
"bankCardNumber":"开户行账号", "bankCardNumber": "开户行账号",
"money":"开票金额", "money": "开票金额",
"invoiceNumber":"发票号码", "invoiceNumber": "发票号码",
"invoiceVoucher":"发票凭证", "invoiceVoucher": "发票凭证",
"remark":"备注", "remark": "备注",
"createTime":"创建时间", "createTime": "创建时间",
"invoiceTime":"开票时间", "invoiceTime": "开票时间",
"status":"状态", "status": "状态",
"operation":"操作", "operation": "操作",
"detail":"详情", "detail": "详情",
"hasInvoice":"已开票", "hasInvoice": "已开票",
"noInvoice":"未开票", "noInvoice": "未开票",
"all":"全部", "all": "全部",
"invoice":"开票", "invoice": "开票",
"viewOrder":"查看订单", "viewOrder": "查看订单",
"invoiceNumberPlaceholder":"请输入发票号码", "invoiceNumberPlaceholder": "请输入发票号码",
"invoiceVoucherPlaceholder":"请输入发票凭证" "invoiceVoucherPlaceholder": "请输入发票凭证"
} }

210
admin/src/addon/shop/lang/zh-cn/order.refund.json

@ -1,106 +1,106 @@
{ {
"goodsName": "商品名称", "goodsName": "商品名称",
"orderNo": "订单编号", "orderNo": "订单编号",
"orderRefundNo": "退款编号", "orderRefundNo": "退款编号",
"refundTime": "退款时间", "refundTime": "退款时间",
"startDate": "开始时间", "startDate": "开始时间",
"endDate": "结束时间", "endDate": "结束时间",
"goodsNamePlaceholder": "请输入商品名称", "goodsNamePlaceholder": "请输入商品名称",
"orderNoPlaceholder": "请输入订单编号", "orderNoPlaceholder": "请输入订单编号",
"orderRefundNoPlaceholder": "请输入退款编号", "orderRefundNoPlaceholder": "请输入退款编号",
"goodsInfo": "商品信息", "goodsInfo": "商品信息",
"orderMoney": "订单金额", "orderMoney": "订单金额",
"realityMoney":"实付金额", "realityMoney": "实付金额",
"goodsMoney": "商品金额", "goodsMoney": "商品金额",
"buyMember": "买家", "buyMember": "买家",
"refundMoney": "退款金额", "refundMoney": "退款金额",
"createTime": "申请时间", "createTime": "申请时间",
"refundStatus": "退款状态", "refundStatus": "退款状态",
"all": "全部", "all": "全部",
"refundType": "退款方式", "refundType": "退款方式",
"applyForRefund": "申请退款", "applyForRefund": "申请退款",
"refundEnd": "维权结束", "refundEnd": "维权结束",
"toBeReturned": "买家待退货", "toBeReturned": "买家待退货",
"receivedGoods": "卖家待收货", "receivedGoods": "卖家待收货",
"refundRefuse": "卖家拒绝", "refundRefuse": "卖家拒绝",
"orderInfo": "订单信息", "orderInfo": "订单信息",
"outTradeNo": "交易流水号", "outTradeNo": "交易流水号",
"orderType": "订单类型", "orderType": "订单类型",
"orderForm": "订单来源", "orderForm": "订单来源",
"takerName": "收货人", "takerName": "收货人",
"takerMobile": "收货人手机号", "takerMobile": "收货人手机号",
"takerFullAddress": "收货地址", "takerFullAddress": "收货地址",
"goodsDetail": "商品信息", "goodsDetail": "商品信息",
"price": "价格", "price": "价格",
"num": "数量", "num": "数量",
"preferentialMoney": "优惠金额", "preferentialMoney": "优惠金额",
"deliveryMoney": "配送金额", "deliveryMoney": "配送金额",
"operateLog": "订单日志", "operateLog": "订单日志",
"orderStatus": "订单状态", "orderStatus": "订单状态",
"orderStatusPlaceholder": "请选择订单状态", "orderStatusPlaceholder": "请选择订单状态",
"orderFrom": "订单类型", "orderFrom": "订单类型",
"orderFromPlaceholder": "请选择订单类型", "orderFromPlaceholder": "请选择订单类型",
"payTime": "支付时间", "payTime": "支付时间",
"orderGoods": "商品", "orderGoods": "商品",
"goodsPriceNumber": "单价(元)/数量", "goodsPriceNumber": "单价(元)/数量",
"detailOrderMoney": "实付金额(元)", "detailOrderMoney": "实付金额(元)",
"buyInfo": "买家/收货人", "buyInfo": "买家/收货人",
"deliveryType": "配送方式", "deliveryType": "配送方式",
"piece": "件", "piece": "件",
"payType": "支付方式", "payType": "支付方式",
"notes": "备注", "notes": "备注",
"editAddress": "修改地址", "editAddress": "修改地址",
"remind": "提醒", "remind": "提醒",
"remindTips1": "如果未发货,请点击同意退款给买家。", "remindTips1": "如果未发货,请点击同意退款给买家。",
"remindTips2": "如果实际已发货,请主动与买家联系。", "remindTips2": "如果实际已发货,请主动与买家联系。",
"remindTips3": "如果订单整体退款后,优惠券和余额会退还给买家。", "remindTips3": "如果订单整体退款后,优惠券和余额会退还给买家。",
"close": "关闭订单", "close": "关闭订单",
"finish": "确认收货", "finish": "确认收货",
"delivery": "订单发货", "delivery": "订单发货",
"deliveryTypePlaceholder": "请选择配送方式", "deliveryTypePlaceholder": "请选择配送方式",
"company": "物流公司", "company": "物流公司",
"companyPlaceholder": "请选择物流公司", "companyPlaceholder": "请选择物流公司",
"expressNumber": "物流单号", "expressNumber": "物流单号",
"expressNumberPlaceholder": "请输入物流单号", "expressNumberPlaceholder": "请输入物流单号",
"orderGoodsIdsPlaceholder": "请选择订单项", "orderGoodsIdsPlaceholder": "请选择订单项",
"virtualDelivery": "虚拟发货", "virtualDelivery": "虚拟发货",
"orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?", "orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
"orderFinishTips": "是否确认用户已经收货?", "orderFinishTips": "是否确认用户已经收货?",
"orderGoodsPlaceholder": "请选择要发货的商品", "orderGoodsPlaceholder": "请选择要发货的商品",
"memberRemark": "买家留言", "memberRemark": "买家留言",
"discountMoney": "订单详情", "discountMoney": "订单详情",
"orderDelivery": "物流信息", "orderDelivery": "物流信息",
"devliveryTime": "发货时间", "devliveryTime": "发货时间",
"companyName": "物流公司", "companyName": "物流公司",
"logisticNo": "物流单号", "logisticNo": "物流单号",
"packageInfo": "物流包裹信息", "packageInfo": "物流包裹信息",
"deliveryInfo": "发货信息", "deliveryInfo": "发货信息",
"logisticInfo": "物流信息", "logisticInfo": "物流信息",
"storeName": "自提点名称", "storeName": "自提点名称",
"storeAddress": "自提点地址", "storeAddress": "自提点地址",
"storeMobile": "自提点电话", "storeMobile": "自提点电话",
"tradeTime": "营业时间", "tradeTime": "营业时间",
"deliveryStatusName": "发货状态", "deliveryStatusName": "发货状态",
"refundReason": "退款原因", "refundReason": "退款原因",
"afterSales": "售后信息", "afterSales": "售后信息",
"orderRefundRefuse": "退款拒绝", "orderRefundRefuse": "退款拒绝",
"orderRefundAgree": "同意退款", "orderRefundAgree": "同意退款",
"agree": "同意", "agree": "同意",
"applyMoney": "申请金额", "applyMoney": "申请金额",
"refuse": "拒绝", "refuse": "拒绝",
"transferAccounts": "转账", "transferAccounts": "转账",
"refuseReason": "拒绝原因", "refuseReason": "拒绝原因",
"shopReasonPlaceholder": "请输入拒绝原因", "shopReasonPlaceholder": "请输入拒绝原因",
"confirmDelivery": "确认收货", "confirmDelivery": "确认收货",
"orderDeliveryTips": "确定商品收到了吗?", "orderDeliveryTips": "确定商品收到了吗?",
"agreeRefundDelivery": "同意买家收货", "agreeRefundDelivery": "同意买家收货",
"refundDeliveryAddress": "退货地址", "refundDeliveryAddress": "退货地址",
"refundVoucher": "申请凭证", "refundVoucher": "申请凭证",
"refundRemark": "退款描述", "refundRemark": "退款描述",
"agreeMoney": "退款金额", "agreeMoney": "退款金额",
"moneyPlaceholder": "请输入退款金额", "moneyPlaceholder": "请输入退款金额",
"refundaddressPlaceholder": "请输入退货地址", "refundaddressPlaceholder": "请输入退货地址",
"expressCompany": "物流公司", "expressCompany": "物流公司",
"expressRemark": "物流说明", "expressRemark": "物流说明",
"orderInfoEmpty": "暂无数据" "orderInfoEmpty": "暂无数据"
} }

2
admin/src/addon/shop/lang/zh-cn/order.refund_detail.json

@ -91,4 +91,4 @@
"expressCompany": "物流公司", "expressCompany": "物流公司",
"expressRemark": "物流说明", "expressRemark": "物流说明",
"orderInfoEmpty": "暂无数据" "orderInfoEmpty": "暂无数据"
} }

72
admin/src/addon/shop/lang/zh-cn/stat.goods.json

@ -1,37 +1,37 @@
{ {
"goodsOverview": "商品概况", "goodsOverview": "商品概况",
"timeFilter": "时间筛选", "timeFilter": "时间筛选",
"startTime": "开始时间", "startTime": "开始时间",
"endTime": "结束时间", "endTime": "结束时间",
"search": "搜索", "search": "搜索",
"goodsAccessNum": "商品浏览量", "goodsAccessNum": "商品浏览量",
"goodsAccessNumTip": "统计时间内,所有商品详情页被访问的次数,一个人在统计时间内访问多次记为多次", "goodsAccessNumTip": "统计时间内,所有商品详情页被访问的次数,一个人在统计时间内访问多次记为多次",
"goodsVisitCount": "商品访客数", "goodsVisitCount": "商品访客数",
"goodsVisitCountTips":"统计时间内,访问任何商品详情页的人数,一个人在统计时间范围内访问多次只记为一个", "goodsVisitCountTips": "统计时间内,访问任何商品详情页的人数,一个人在统计时间范围内访问多次只记为一个",
"cartNum":"加购件数", "cartNum": "加购件数",
"cartNumTips":"统计时间内,添加商品进入购物车的商品件数", "cartNumTips": "统计时间内,添加商品进入购物车的商品件数",
"saleNum": "下单件数", "saleNum": "下单件数",
"saleNumTips": "统计时间内,成功下单的商品件数之和(不剔除退款订单)", "saleNumTips": "统计时间内,成功下单的商品件数之和(不剔除退款订单)",
"payNum": "支付件数", "payNum": "支付件数",
"payNumTips": "统计时间内, 成功付款订单的商品件数之和(不剔除退款订单)", "payNumTips": "统计时间内, 成功付款订单的商品件数之和(不剔除退款订单)",
"payMoney":"支付金额", "payMoney": "支付金额",
"payMoneyTips":"统计时间内,成功付款订单的商品金额之和(不剔除退款订单)", "payMoneyTips": "统计时间内,成功付款订单的商品金额之和(不剔除退款订单)",
"refundMoney":"退款金额", "refundMoney": "退款金额",
"refundMoneyTips":"统计时间内,成功退款的商品金额之和", "refundMoneyTips": "统计时间内,成功退款的商品金额之和",
"refundNum":"退款件数", "refundNum": "退款件数",
"refundNumTips":"统计时间内,成功退款的商品件数之和", "refundNumTips": "统计时间内,成功退款的商品件数之和",
"goodsRank": "商品排行", "goodsRank": "商品排行",
"goodsName":"商品名称", "goodsName": "商品名称",
"goodsNamePlaceholder":"请输入商品名称", "goodsNamePlaceholder": "请输入商品名称",
"goodsCategory": "商品分类", "goodsCategory": "商品分类",
"all":"全部", "all": "全部",
"totalType":"统计类型", "totalType": "统计类型",
"totalTypePlaceholder":"请选择统计类型", "totalTypePlaceholder": "请选择统计类型",
"goodsInfo":"商品信息", "goodsInfo": "商品信息",
"accessNum":"访问次数", "accessNum": "访问次数",
"visitCount":"访客数", "visitCount": "访客数",
"cartNumber":"加入购物车数量", "cartNumber": "加入购物车数量",
"saleNumber":"商品销量", "saleNumber": "商品销量",
"payTotal":"支付总金额", "payTotal": "支付总金额",
"collectNum":"收藏数量" "collectNum": "收藏数量"
} }

726
admin/src/addon/shop/views/address/edit.vue

@ -1,69 +1,158 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never"> <el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" /> <el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card> </el-card>
<el-card class="box-card !border-none" shadow="never" v-loading="loading"> <el-card class="box-card !border-none" shadow="never" v-loading="loading">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form"> <el-form
<el-form-item :label="t('addressType')" prop="address_type"> :model="formData"
<div class="flex flex-col"> label-width="90px"
<div> ref="formRef"
<el-checkbox v-model="formData.is_delivery_address" :label="t('deliveryAddress')" :true-label="1" :false-label="0"/> :rules="formRules"
<el-checkbox v-model="formData.is_default_delivery" :label="t('defaultDeliveryAddress')" :true-label="1" :false-label="0" v-show="formData.is_delivery_address"/> class="page-form"
</div> >
<div> <el-form-item :label="t('addressType')" prop="address_type">
<el-checkbox v-model="formData.is_refund_address" :label="t('refundAddress')" :true-label="1" :false-label="0"/> <div class="flex flex-col">
<el-checkbox v-model="formData.is_default_refund" :label="t('defaultRefundAddress')" :true-label="1" :false-label="0" v-show="formData.is_refund_address"/> <div>
</div> <el-checkbox
</div> v-model="formData.is_delivery_address"
</el-form-item> :label="t('deliveryAddress')"
:true-label="1"
<el-form-item :label="t('contactName')" prop="contact_name"> :false-label="0"
<el-input v-model.trim="formData.contact_name" clearable :placeholder="t('contactNamePlaceholder')" class="input-width" maxlength="10" /> />
</el-form-item> <el-checkbox
v-model="formData.is_default_delivery"
<el-form-item :label="t('mobile')" prop="mobile"> :label="t('defaultDeliveryAddress')"
<el-input v-model.trim="formData.mobile" clearable :placeholder="t('mobilePlaceholder')" class="input-width" @keyup="filterNumber($event)" @blur="formData.mobile = $event.target.value"/> :true-label="1"
</el-form-item> :false-label="0"
v-show="formData.is_delivery_address"
<el-form-item :label="t('fullAddress')" prop="address_area"> />
<el-select v-model="formData.province_id" value-key="id" clearable class="w-[200px]" ref="provinceRef"> </div>
<el-option :label="t('provincePlaceholder')" :value="0"/> <div>
<el-option v-for="(item, index) in areaList.province" :key="index" :label="item.name" :value="item.id"/> <el-checkbox
</el-select> v-model="formData.is_refund_address"
<el-select v-model="formData.city_id" value-key="id" clearable class="w-[200px] ml-3" ref="cityRef"> :label="t('refundAddress')"
<el-option :label="t('cityPlaceholder')" :value="0"/> :true-label="1"
<el-option v-for="(item, index) in areaList.city " :key="index" :label="item.name" :value="item.id"/> :false-label="0"
</el-select> />
<el-select v-model="formData.district_id" value-key="id" clearable class="w-[200px] ml-3" ref="districtRef"> <el-checkbox
<el-option :label="t('districtPlaceholder')" :value="0"/> v-model="formData.is_default_refund"
<el-option v-for="(item, index) in areaList.district " :key="index" :label="item.name" :value="item.id"/> :label="t('defaultRefundAddress')"
</el-select> :true-label="1"
</el-form-item> :false-label="0"
v-show="formData.is_refund_address"
<el-form-item prop="address"> />
<el-input v-model.trim="formData.address" clearable :placeholder="t('addressPlaceholder')" class="input-width"/> </div>
</el-form-item> </div>
</el-form-item>
<el-form-item>
<div id="container" class="w-[800px] h-[520px] relative" v-loading="mapLoading"></div> <el-form-item :label="t('contactName')" prop="contact_name">
</el-form-item> <el-input
</el-form> v-model.trim="formData.contact_name"
</el-card> clearable
<div class="fixed-footer-wrap"> :placeholder="t('contactNamePlaceholder')"
<div class="fixed-footer !z-[9999]"> class="input-width"
<el-button type="primary" @click="onSave(formRef)">{{ t('save') }}</el-button> maxlength="10"
<el-button @click="back()">{{ t('cancel') }}</el-button> />
</div> </el-form-item>
</div>
</div> <el-form-item :label="t('mobile')" prop="mobile">
<el-input
v-model.trim="formData.mobile"
clearable
:placeholder="t('mobilePlaceholder')"
class="input-width"
@keyup="filterNumber($event)"
@blur="formData.mobile = $event.target.value"
/>
</el-form-item>
<el-form-item :label="t('fullAddress')" prop="address_area">
<el-select
v-model="formData.province_id"
value-key="id"
clearable
class="w-[200px]"
ref="provinceRef"
>
<el-option :label="t('provincePlaceholder')" :value="0" />
<el-option
v-for="(item, index) in areaList.province"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
<el-select
v-model="formData.city_id"
value-key="id"
clearable
class="w-[200px] ml-3"
ref="cityRef"
>
<el-option :label="t('cityPlaceholder')" :value="0" />
<el-option
v-for="(item, index) in areaList.city"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
<el-select
v-model="formData.district_id"
value-key="id"
clearable
class="w-[200px] ml-3"
ref="districtRef"
>
<el-option :label="t('districtPlaceholder')" :value="0" />
<el-option
v-for="(item, index) in areaList.district"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item prop="address">
<el-input
v-model.trim="formData.address"
clearable
:placeholder="t('addressPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item>
<div
id="container"
class="w-[800px] h-[520px] relative"
v-loading="mapLoading"
></div>
</el-form-item>
</el-form>
</el-card>
<div class="fixed-footer-wrap">
<div class="fixed-footer !z-[9999]">
<el-button type="primary" @click="onSave(formRef)">{{
t('save')
}}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, computed, onMounted, watch } from 'vue' import { ref, reactive, computed, onMounted, watch } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { getShopAddressInfo, addShopAddress, editShopAddress } from '@/addon/shop/api/shop_address' import {
getShopAddressInfo,
addShopAddress,
editShopAddress,
} from '@/addon/shop/api/shop_address'
import { getMap, getAreaListByPid, getAreaByCode } from '@/app/api/sys' import { getMap, getAreaListByPid, getAreaByCode } from '@/app/api/sys'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { createMarker, latLngToAddress, addressToLatLng } from '@/utils/qqmap' import { createMarker, latLngToAddress, addressToLatLng } from '@/utils/qqmap'
@ -73,15 +162,15 @@ const route = useRoute()
const id: number = parseInt(route.query.id as string) const id: number = parseInt(route.query.id as string)
const loading = ref(false) const loading = ref(false)
const pageName = route.meta.title const pageName = route.meta.title
interface areaType{ interface areaType {
province: any[], province: any[]
city: any[], city: any[]
district: any[] district: any[]
} }
const areaList = reactive<areaType>({ const areaList = reactive<areaType>({
province: [], province: [],
city: [], city: [],
district: [] district: [],
}) })
const provinceRef = ref() const provinceRef = ref()
const cityRef = ref() const cityRef = ref()
@ -90,116 +179,120 @@ const districtRef = ref()
/** /**
* 获取省 * 获取省
*/ */
getAreaListByPid(0).then(res => { getAreaListByPid(0).then((res) => {
areaList.province = res.data areaList.province = res.data
}) })
let mapKey: string = '' let mapKey: string = ''
onMounted(() => { onMounted(() => {
const mapScript = document.createElement('script') const mapScript = document.createElement('script')
getMap().then(res => { getMap().then((res) => {
mapKey = res.data.key mapKey = res.data.key
mapScript.type = 'text/javascript' mapScript.type = 'text/javascript'
mapScript.src = 'https://map.qq.com/api/gljs?libraries=tools,service&v=1.exp&key=' + res.data.key mapScript.src =
document.body.appendChild(mapScript) 'https://map.qq.com/api/gljs?libraries=tools,service&v=1.exp&key=' +
}) res.data.key
mapScript.onload = () => { document.body.appendChild(mapScript)
setTimeout(() => { })
initMap() mapScript.onload = () => {
}, 500) setTimeout(() => {
} initMap()
}, 500)
}
}) })
/** /**
* 初始化地图 * 初始化地图
*/ */
let map: any let map: any
let marker: any let marker: any
const mapLoading = ref(true) const mapLoading = ref(true)
const initMap = () => { const initMap = () => {
const TMap = (window as any).TMap const TMap = (window as any).TMap
const LatLng = TMap.LatLng const LatLng = TMap.LatLng
const center = new LatLng(formData.lat, formData.lng) const center = new LatLng(formData.lat, formData.lng)
map = new TMap.Map('container', { map = new TMap.Map('container', {
center, center,
zoom: 14 zoom: 14,
}) })
map.on('tilesloaded', () => { map.on('tilesloaded', () => {
mapLoading.value = false mapLoading.value = false
})
marker = createMarker(map)
map.on('click', (evt: any) => {
map.setCenter(evt.latLng)
marker.updateGeometries({
id: 'center',
position: evt.latLng,
}) })
latLngChange(evt.latLng.lat, evt.latLng.lng)
})
marker = createMarker(map) latLngChange(center.lat, center.lng)
map.on('click', (evt: any) => {
map.setCenter(evt.latLng)
marker.updateGeometries({
id: 'center',
position: evt.latLng
})
latLngChange(evt.latLng.lat, evt.latLng.lng)
})
latLngChange(center.lat, center.lng)
} }
const storeArea = reactive({ const storeArea = reactive({
province_id: 0, province_id: 0,
city_id: 0, city_id: 0,
district_id: 0 district_id: 0,
}) })
const latLngChange = (lat: number, lng: number) => { const latLngChange = (lat: number, lng: number) => {
latLngToAddress({ mapKey, lat, lng }).then(({ message, result }) => { latLngToAddress({ mapKey, lat, lng })
if (message == 'query ok' || message == 'Success') { .then(({ message, result }) => {
formData.lat = result.location.lat if (message == 'query ok' || message == 'Success') {
formData.lng = result.location.lng formData.lat = result.location.lat
formData.address = result.formatted_addresses.recommend formData.lng = result.location.lng
formData.address = result.formatted_addresses.recommend
getAreaByCode(result.ad_info.adcode).then(({ data }) => {
storeArea.province_id = data.province ? data.province.id : 0 getAreaByCode(result.ad_info.adcode).then(({ data }) => {
storeArea.city_id = data.city ? data.city.id : 0 storeArea.province_id = data.province ? data.province.id : 0
storeArea.district_id = data.district ? data.district.id : 0 storeArea.city_id = data.city ? data.city.id : 0
}) storeArea.district_id = data.district ? data.district.id : 0
} else { })
console.error(message, result) } else {
} console.error(message, result)
}).catch(err => { }
console.log(err) })
.catch((err) => {
console.log(err)
}) })
} }
/** /**
* 表单数据 * 表单数据
*/ */
const initialFormData = { const initialFormData = {
id: 0, id: 0,
contact_name: '', contact_name: '',
mobile: '', mobile: '',
province_id: 0, province_id: 0,
city_id: 0, city_id: 0,
district_id: 0, district_id: 0,
address: '', address: '',
full_address: '', full_address: '',
lat: 39.908626, lat: 39.908626,
lng: 116.397190, lng: 116.39719,
is_delivery_address: 0, is_delivery_address: 0,
is_refund_address: 0, is_refund_address: 0,
is_default_delivery: 0, is_default_delivery: 0,
is_default_refund: 0 is_default_refund: 0,
} }
const formData: Record<string, any> = reactive({ ...initialFormData }) const formData: Record<string, any> = reactive({ ...initialFormData })
const setFormData = async (id: number = 0) => { const setFormData = async (id: number = 0) => {
loading.value = true loading.value = true
Object.assign(formData, initialFormData) Object.assign(formData, initialFormData)
const data = await (await getShopAddressInfo(id)).data const data = await (await getShopAddressInfo(id)).data
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
loading.value = false loading.value = false
} }
if (id) setFormData(id) if (id) setFormData(id)
@ -207,208 +300,233 @@ const formRef = ref<FormInstance>()
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
address_type: [ address_type: [
{ {
validator: (rule: any, value: any, callback: any) => { validator: (rule: any, value: any, callback: any) => {
if (!formData.is_delivery_address && !formData.is_refund_address) { if (!formData.is_delivery_address && !formData.is_refund_address) {
callback(new Error(t('addressTypeRequire'))) callback(new Error(t('addressTypeRequire')))
} }
callback() callback()
} },
} },
], ],
contact_name: [ contact_name: [
{ required: true, message: t('contactNamePlaceholder'), trigger: 'blur' } { required: true, message: t('contactNamePlaceholder'), trigger: 'blur' },
], ],
mobile: [ mobile: [
{ required: true, message: t('mobilePlaceholder'), trigger: 'blur' }, { required: true, message: t('mobilePlaceholder'), trigger: 'blur' },
{ {
trigger: 'blur', trigger: 'blur',
validator: (rule: any, value: any, callback: any) => { validator: (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) { if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('mobileTips'))) callback(new Error(t('mobileTips')))
} }
callback() callback()
} },
} },
], ],
address_area: [ address_area: [
{ {
validator: (rule: any, value: any, callback: any) => { validator: (rule: any, value: any, callback: any) => {
if (!formData.province_id) { if (!formData.province_id) {
callback(new Error(t('provincePlaceholder'))) callback(new Error(t('provincePlaceholder')))
} }
if (!formData.city_id) { if (!formData.city_id) {
callback(new Error(t('cityPlaceholder'))) callback(new Error(t('cityPlaceholder')))
} }
if (areaList.district.length && !formData.district_id) { if (areaList.district.length && !formData.district_id) {
callback(new Error(t('districtPlaceholder'))) callback(new Error(t('districtPlaceholder')))
} }
callback() callback()
} },
} },
], ],
address: [ address: [
{ required: true, message: t('addressPlaceholder'), trigger: 'blur' } { required: true, message: t('addressPlaceholder'), trigger: 'blur' },
] ],
} }
}) })
/** /**
* 获取市 * 获取市
*/ */
watch(() => formData.province_id, (nval) => { watch(
() => formData.province_id,
(nval) => {
if (nval) { if (nval) {
getAreaListByPid(formData.province_id).then(res => { getAreaListByPid(formData.province_id).then((res) => {
areaList.city = res.data areaList.city = res.data
const cityId = formData.city_id const cityId = formData.city_id
if (cityId) { if (cityId) {
let isExist = false let isExist = false
for (let i = 0; i < res.data.length; i++) { for (let i = 0; i < res.data.length; i++) {
if (cityId == res.data[i].id) { if (cityId == res.data[i].id) {
isExist = true isExist = true
break break
}
}
if (isExist) {
formData.city_id = cityId
return
}
} }
formData.city_id = 0 }
areaChange() if (isExist) {
}) formData.city_id = cityId
} else { return
}
}
formData.city_id = 0 formData.city_id = 0
areaChange()
})
} else {
formData.city_id = 0
} }
}) }
)
/** /**
* 获取区 * 获取区
*/ */
watch(() => formData.city_id, (nval) => { watch(
() => formData.city_id,
(nval) => {
if (nval) { if (nval) {
getAreaListByPid(formData.city_id).then(res => { getAreaListByPid(formData.city_id).then((res) => {
areaList.district = res.data areaList.district = res.data
const districtId = formData.district_id const districtId = formData.district_id
if (districtId) { if (districtId) {
let isExist = false let isExist = false
for (let i = 0; i < res.data.length; i++) { for (let i = 0; i < res.data.length; i++) {
if (districtId == res.data[i].id) { if (districtId == res.data[i].id) {
isExist = true isExist = true
break break
}
}
if (isExist) {
formData.district_id = districtId
return
}
} }
areaChange() }
formData.district_id = 0 if (isExist) {
}) formData.district_id = districtId
} else { return
}
}
areaChange()
formData.district_id = 0 formData.district_id = 0
})
} else {
formData.district_id = 0
} }
}) }
)
watch(() => formData.district_id, (nval) => { watch(
() => formData.district_id,
(nval) => {
if (nval) { if (nval) {
areaChange() areaChange()
} }
}) }
)
const areaChange = debounce(() => { const areaChange = debounce(() => {
setTimeout(() => { setTimeout(() => {
const address = [ const address = [
formData.province_id ? provinceRef.value.selectedLabel : '', formData.province_id ? provinceRef.value.selectedLabel : '',
formData.city_id ? cityRef.value.selectedLabel : '', formData.city_id ? cityRef.value.selectedLabel : '',
formData.district_id ? districtRef.value.selectedLabel : '' formData.district_id ? districtRef.value.selectedLabel : '',
] ]
addressToLatLng({ mapKey, address: address.join('') }).then(({ message, result }) => { addressToLatLng({ mapKey, address: address.join('') }).then(
if (message == 'Success' || message == 'query ok') { ({ message, result }) => {
const latLng = new (window as any).TMap.LatLng(result.location.lat, result.location.lng) if (message == 'Success' || message == 'query ok') {
map.setCenter(latLng) const latLng = new (window as any).TMap.LatLng(
marker.updateGeometries({ result.location.lat,
id: 'center', result.location.lng
position: latLng )
}) map.setCenter(latLng)
formData.lat = result.location.lat marker.updateGeometries({
formData.lng = result.location.lng id: 'center',
} else { position: latLng,
console.error(message, result) })
} formData.lat = result.location.lat
}) formData.lng = result.location.lng
}, 500) } else {
console.error(message, result)
}
}
)
}, 500)
}, 500) }, 500)
/** /**
* 地图点选获取市 * 地图点选获取市
*/ */
watch(() => storeArea.province_id, (nval) => { watch(
() => storeArea.province_id,
(nval) => {
if (nval) { if (nval) {
getAreaListByPid(storeArea.province_id).then(res => { getAreaListByPid(storeArea.province_id).then((res) => {
areaList.city = res.data areaList.city = res.data
formData.province_id = storeArea.province_id formData.province_id = storeArea.province_id
formData.city_id = storeArea.city_id formData.city_id = storeArea.city_id
}) })
} }
}) }
)
/** /**
* 地图点选获取区 * 地图点选获取区
*/ */
watch(() => storeArea.city_id, (nval) => { watch(
() => storeArea.city_id,
(nval) => {
if (nval) { if (nval) {
getAreaListByPid(storeArea.city_id).then(res => { getAreaListByPid(storeArea.city_id).then((res) => {
areaList.district = res.data areaList.district = res.data
formData.city_id = storeArea.city_id formData.city_id = storeArea.city_id
formData.district_id = storeArea.district_id formData.district_id = storeArea.district_id
}) })
} }
}) }
)
/** /**
* 地图点选获取区 * 地图点选获取区
*/ */
watch(() => storeArea.district_id, (nval) => { watch(
() => storeArea.district_id,
(nval) => {
if (nval) { if (nval) {
formData.district_id = storeArea.district_id formData.district_id = storeArea.district_id
} }
}) }
)
const onSave = async (formEl: FormInstance | undefined) => { const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
const data = formData const data = formData
const address = [ const address = [
data.province_id ? provinceRef.value.selectedLabel : '', data.province_id ? provinceRef.value.selectedLabel : '',
data.city_id ? cityRef.value.selectedLabel : '', data.city_id ? cityRef.value.selectedLabel : '',
data.district_id ? districtRef.value.selectedLabel : '', data.district_id ? districtRef.value.selectedLabel : '',
data.address data.address,
] ]
data.full_address = address.join('') data.full_address = address.join('')
const save = id ? editShopAddress : addShopAddress const save = id ? editShopAddress : addShopAddress
save(data).then(res => { save(data)
loading.value = false .then((res) => {
history.back() loading.value = false
}).catch(() => { history.back()
loading.value = false })
}) .catch(() => {
} loading.value = false
}) })
}
})
} }
const back = () => { const back = () => {
history.back() history.back()
} }
</script> </script>

275
admin/src/addon/shop/views/address/list.vue

@ -1,89 +1,144 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<div class="flex justify-between items-center"> <span class="text-page-title">{{ pageName }}</span>
<span class="text-page-title">{{ pageName }}</span> <el-button type="primary" @click="addEvent">
<el-button type="primary" @click="addEvent"> {{ t('addShopAddress') }}
{{ t('addShopAddress') }} </el-button>
</el-button> </div>
</div>
<el-card
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> class="box-card !border-none my-[10px] table-search-wrap"
<el-form :inline="true" :model="shopAddressTable.searchParam" ref="searchFormRef"> shadow="never"
<el-form-item :label="t('mobile')" prop="mobile"> >
<el-input v-model.trim="shopAddressTable.searchParam.mobile" :placeholder="t('mobilePlaceholder')"/> <el-form
</el-form-item> :inline="true"
<el-form-item :label="t('fullAddress')" prop="full_address"> :model="shopAddressTable.searchParam"
<el-input v-model.trim="shopAddressTable.searchParam.full_address" :placeholder="t('fullAddressPlaceholder')"/> ref="searchFormRef"
</el-form-item> >
<el-form-item :label="t('mobile')" prop="mobile">
<el-form-item> <el-input
<el-button type="primary" @click="loadShopAddressList()">{{ t('search') }}</el-button> v-model.trim="shopAddressTable.searchParam.mobile"
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> :placeholder="t('mobilePlaceholder')"
</el-form-item> />
</el-form> </el-form-item>
</el-card> <el-form-item :label="t('fullAddress')" prop="full_address">
<el-input
<div class="mt-[10px]"> v-model.trim="shopAddressTable.searchParam.full_address"
<el-table :data="shopAddressTable.data" size="large" v-loading="shopAddressTable.loading"> :placeholder="t('fullAddressPlaceholder')"
<template #empty> />
<span>{{ !shopAddressTable.loading ? t('emptyData') : '' }}</span> </el-form-item>
</template>
<el-table-column prop="contact_name" :label="t('contactName')" min-width="120"/> <el-form-item>
<el-table-column prop="mobile" :label="t('mobile')" min-width="120"/> <el-button type="primary" @click="loadShopAddressList()">{{
<el-table-column prop="full_address" :label="t('fullAddress')" min-width="120" :show-overflow-tooltip="true"/> t('search')
<el-table-column prop="is_delivery_address" :label="t('addressType')" min-width="120" align="left"> }}</el-button>
<template #default="{ row }"> <el-button @click="resetForm(searchFormRef)">{{
<div v-if="row.is_delivery_address"> t('reset')
{{ t('deliveryAddress') }} }}</el-button>
<el-tag size="small" v-if="row.is_default_delivery">{{ t('default') }}</el-tag> </el-form-item>
</div> </el-form>
<div v-if="row.is_refund_address"> </el-card>
{{ t('refundAddress') }}
<el-tag size="small" v-if="row.is_default_refund">{{ t('default') }}</el-tag> <div class="mt-[10px]">
</div> <el-table
</template> :data="shopAddressTable.data"
</el-table-column> size="large"
v-loading="shopAddressTable.loading"
<el-table-column :label="t('operation')" fixed="right" min-width="120" align="right"> >
<template #default="{ row }"> <template #empty>
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> <span>{{ !shopAddressTable.loading ? t('emptyData') : '' }}</span>
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button> </template>
</template> <el-table-column
</el-table-column> prop="contact_name"
:label="t('contactName')"
</el-table> min-width="120"
<div class="mt-[16px] flex justify-end"> />
<el-pagination v-model:current-page="shopAddressTable.page" v-model:page-size="shopAddressTable.limit" layout="total, sizes, prev, pager, next, jumper" :total="shopAddressTable.total" @size-change="loadShopAddressList()" @current-change="loadShopAddressList"/> <el-table-column prop="mobile" :label="t('mobile')" min-width="120" />
</div> <el-table-column
</div> prop="full_address"
:label="t('fullAddress')"
</el-card> min-width="120"
</div> :show-overflow-tooltip="true"
/>
<el-table-column
prop="is_delivery_address"
:label="t('addressType')"
min-width="120"
align="left"
>
<template #default="{ row }">
<div v-if="row.is_delivery_address">
{{ t('deliveryAddress') }}
<el-tag size="small" v-if="row.is_default_delivery">{{
t('default')
}}</el-tag>
</div>
<div v-if="row.is_refund_address">
{{ t('refundAddress') }}
<el-tag size="small" v-if="row.is_default_refund">{{
t('default')
}}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column
:label="t('operation')"
fixed="right"
min-width="120"
align="right"
>
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button type="primary" link @click="deleteEvent(row.id)">{{
t('delete')
}}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="shopAddressTable.page"
v-model:page-size="shopAddressTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="shopAddressTable.total"
@size-change="loadShopAddressList()"
@current-change="loadShopAddressList"
/>
</div>
</div>
</el-card>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getShopAddressList, deleteShopAddress } from '@/addon/shop/api/shop_address' import {
getShopAddressList,
deleteShopAddress,
} from '@/addon/shop/api/shop_address'
import { ElMessageBox, FormInstance } from 'element-plus' import { ElMessageBox, FormInstance } from 'element-plus'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { setTablePageStorage,getTablePageStorage } from "@/utils/common"; import { setTablePageStorage, getTablePageStorage } from '@/utils/common'
const route = useRoute() const route = useRoute()
const pageName = route.meta.title const pageName = route.meta.title
const shopAddressTable = reactive({ const shopAddressTable = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
total: 0, total: 0,
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
mobile: '', mobile: '',
full_address: '' full_address: '',
} },
}) })
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()
@ -92,23 +147,29 @@ const searchFormRef = ref<FormInstance>()
* 获取商家地址库列表 * 获取商家地址库列表
*/ */
const loadShopAddressList = (page: number = 1) => { const loadShopAddressList = (page: number = 1) => {
shopAddressTable.loading = true shopAddressTable.loading = true
shopAddressTable.page = page shopAddressTable.page = page
getShopAddressList({ getShopAddressList({
page: shopAddressTable.page, page: shopAddressTable.page,
limit: shopAddressTable.limit, limit: shopAddressTable.limit,
...shopAddressTable.searchParam ...shopAddressTable.searchParam,
}).then(res => { })
shopAddressTable.loading = false .then((res) => {
shopAddressTable.data = res.data.data shopAddressTable.loading = false
shopAddressTable.total = res.data.total shopAddressTable.data = res.data.data
setTablePageStorage(shopAddressTable.page, shopAddressTable.limit, shopAddressTable.searchParam); shopAddressTable.total = res.data.total
}).catch(() => { setTablePageStorage(
shopAddressTable.loading = false shopAddressTable.page,
shopAddressTable.limit,
shopAddressTable.searchParam
)
})
.catch(() => {
shopAddressTable.loading = false
}) })
} }
loadShopAddressList(getTablePageStorage(shopAddressTable.searchParam).page); loadShopAddressList(getTablePageStorage(shopAddressTable.searchParam).page)
const router = useRouter() const router = useRouter()
@ -116,41 +177,39 @@ const router = useRouter()
* 添加商家地址库 * 添加商家地址库
*/ */
const addEvent = () => { const addEvent = () => {
router.push('/shop/order/address/edit') router.push('/shop/order/address/edit')
} }
/** /**
* 编辑商家地址库 * 编辑商家地址库
* @param data * @param data
*/ */
const editEvent = (data: any) => { const editEvent = (data: any) => {
router.push('/shop/order/address/edit?id=' + data.id) router.push('/shop/order/address/edit?id=' + data.id)
} }
/** /**
* 删除商家地址库 * 删除商家地址库
*/ */
const deleteEvent = (id: number) => { const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('shopAddressDeleteTips'), t('warning'), ElMessageBox.confirm(t('shopAddressDeleteTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning' }).then(() => {
} deleteShopAddress(id)
).then(() => { .then(() => {
deleteShopAddress(id).then(() => { loadShopAddressList()
loadShopAddressList() })
}).catch(() => { .catch(() => {})
}) })
})
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
loadShopAddressList() loadShopAddressList()
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

281
admin/src/addon/shop/views/delivery/company.vue

@ -1,67 +1,124 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<div class="flex justify-between items-center"> <div class="detail-head !m-0">
<div class="detail-head !m-0"> <div class="left" @click="router.push('/shop/order/delivery')">
<div class="left" @click="router.push('/shop/order/delivery')"> <span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="iconfont iconxiangzuojiantou !text-xs"></span> <span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span>
<span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span> </div>
</div> <span class="adorn">|</span>
<span class="adorn">|</span> <span class="right">{{ pageName }}</span>
<span class="right">{{ pageName }}</span> </div>
</div> <el-button type="primary" @click="addEvent">{{
<el-button type="primary" @click="addEvent">{{ t('addCompany') }}</el-button> t('addCompany')
</div> }}</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="companyTable.searchParam" ref="searchFormRef"> <el-card
<el-form-item :label="t('companyName')" prop="company_name"> class="box-card !border-none my-[10px] table-search-wrap"
<el-input v-model.trim="companyTable.searchParam.company_name" :placeholder="t('companyNamePlaceholder')"/> shadow="never"
</el-form-item> >
<el-form-item> <el-form
<el-button type="primary" @click="loadCompanyList()">{{ t('search') }}</el-button> :inline="true"
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> :model="companyTable.searchParam"
</el-form-item> ref="searchFormRef"
</el-form> >
</el-card> <el-form-item :label="t('companyName')" prop="company_name">
<el-input
<div class="mt-[10px]"> v-model.trim="companyTable.searchParam.company_name"
<el-table :data="companyTable.data" size="large" v-loading="companyTable.loading"> :placeholder="t('companyNamePlaceholder')"
<template #empty> />
<span>{{ !companyTable.loading ? t('emptyData') : '' }}</span> </el-form-item>
</template> <el-form-item>
<el-table-column prop="company_name" :label="t('companyName')" min-width="120"/> <el-button type="primary" @click="loadCompanyList()">{{
<el-table-column prop="logo" :label="t('logo')" min-width="120"> t('search')
<template #default="{ row }"> }}</el-button>
<div class="w-[50px] h-[50px] flex items-center justify-center"> <el-button @click="resetForm(searchFormRef)">{{
<img v-if="row.logo" class="max-w-[100%] max-h-[100%]" :src="img(row.logo)"/> t('reset')
</div> }}</el-button>
</template> </el-form-item>
</el-table-column> </el-form>
<el-table-column prop="url" :label="t('url')" min-width="120"/> </el-card>
<el-table-column prop="express_no" :label="t('expressNo')" min-width="120"/>
<el-table-column prop="express_no_electronic_sheet" :label="t('expressNoElectronicSheet')" min-width="120"/> <div class="mt-[10px]">
<el-table-column :label="t('electronicSheetSwitchName')" min-width="120"> <el-table
<template #default="{ row }"> :data="companyTable.data"
<span>{{row.electronic_sheet_switch == 1 ? '支持' : '不支持'}}</span> size="large"
</template> v-loading="companyTable.loading"
</el-table-column> >
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120"> <template #empty>
<template #default="{ row }"> <span>{{ !companyTable.loading ? t('emptyData') : '' }}</span>
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> </template>
<el-button type="primary" link @click="deleteEvent(row.company_id)">{{ t('delete') }} <el-table-column
</el-button> prop="company_name"
</template> :label="t('companyName')"
</el-table-column> min-width="120"
/>
</el-table> <el-table-column prop="logo" :label="t('logo')" min-width="120">
<div class="mt-[16px] flex justify-end"> <template #default="{ row }">
<el-pagination v-model:current-page="companyTable.page" v-model:page-size="companyTable.limit" layout="total, sizes, prev, pager, next, jumper" :total="companyTable.total" @size-change="loadCompanyList()" @current-change="loadCompanyList"/> <div class="w-[50px] h-[50px] flex items-center justify-center">
</div> <img
</div> v-if="row.logo"
</el-card> class="max-w-[100%] max-h-[100%]"
</div> :src="img(row.logo)"
/>
</div>
</template>
</el-table-column>
<el-table-column prop="url" :label="t('url')" min-width="120" />
<el-table-column
prop="express_no"
:label="t('expressNo')"
min-width="120"
/>
<el-table-column
prop="express_no_electronic_sheet"
:label="t('expressNoElectronicSheet')"
min-width="120"
/>
<el-table-column
:label="t('electronicSheetSwitchName')"
min-width="120"
>
<template #default="{ row }">
<span>{{
row.electronic_sheet_switch == 1 ? '支持' : '不支持'
}}</span>
</template>
</el-table-column>
<el-table-column
:label="t('operation')"
fixed="right"
align="right"
min-width="120"
>
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button
type="primary"
link
@click="deleteEvent(row.company_id)"
>{{ t('delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="companyTable.page"
v-model:page-size="companyTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="companyTable.total"
@size-change="loadCompanyList()"
@current-change="loadCompanyList"
/>
</div>
</div>
</el-card>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -71,25 +128,25 @@ import { getCompanyPageList, deleteCompany } from '@/addon/shop/api/delivery'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus' import { ElMessageBox, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { setTablePageStorage,getTablePageStorage } from "@/utils/common"; import { setTablePageStorage, getTablePageStorage } from '@/utils/common'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title const pageName = route.meta.title
const companyTable = reactive({ const companyTable = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
total: 0, total: 0,
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
company_name: '', company_name: '',
logo: '', logo: '',
url: '', url: '',
create_time: '', create_time: '',
modify_time: '' modify_time: '',
} },
}) })
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()
@ -98,30 +155,36 @@ const searchFormRef = ref<FormInstance>()
* 获取物流公司列表 * 获取物流公司列表
*/ */
const loadCompanyList = (page: number = 1) => { const loadCompanyList = (page: number = 1) => {
companyTable.loading = true companyTable.loading = true
companyTable.page = page companyTable.page = page
getCompanyPageList({ getCompanyPageList({
page: companyTable.page, page: companyTable.page,
limit: companyTable.limit, limit: companyTable.limit,
...companyTable.searchParam ...companyTable.searchParam,
}).then(res => { })
companyTable.loading = false .then((res) => {
companyTable.data = res.data.data companyTable.loading = false
companyTable.total = res.data.total companyTable.data = res.data.data
setTablePageStorage(companyTable.page, companyTable.limit, companyTable.searchParam); companyTable.total = res.data.total
}).catch(() => { setTablePageStorage(
companyTable.loading = false companyTable.page,
companyTable.limit,
companyTable.searchParam
)
})
.catch(() => {
companyTable.loading = false
}) })
} }
loadCompanyList(getTablePageStorage(companyTable.searchParam).page); loadCompanyList(getTablePageStorage(companyTable.searchParam).page)
/** /**
* 添加物流公司 * 添加物流公司
*/ */
const addEvent = () => { const addEvent = () => {
router.push('/shop/order/delivery/company_add') router.push('/shop/order/delivery/company_add')
} }
/** /**
@ -129,33 +192,31 @@ const addEvent = () => {
* @param data * @param data
*/ */
const editEvent = (data: any) => { const editEvent = (data: any) => {
router.push('/shop/order/delivery/company_edit?company_id=' + data.company_id) router.push('/shop/order/delivery/company_edit?company_id=' + data.company_id)
} }
/** /**
* 删除物流公司 * 删除物流公司
*/ */
const deleteEvent = (id: number) => { const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('companyDeleteTips'), t('warning'), ElMessageBox.confirm(t('companyDeleteTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning' }).then(() => {
} deleteCompany(id)
).then(() => { .then(() => {
deleteCompany(id).then(() => { loadCompanyList()
loadCompanyList() })
}).catch(() => { .catch(() => {})
}) })
})
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
loadCompanyList() loadCompanyList()
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

626
admin/src/addon/shop/views/delivery/company_edit.vue

@ -1,122 +1,281 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<el-page-header :content="formData.company_id ? t('updateCompany') : t('addCompany')" :icon="ArrowLeft" @back="back()" /> <el-page-header
</el-card> :content="formData.company_id ? t('updateCompany') : t('addCompany')"
<el-card class="box-card mt-[15px] !border-none" shadow="never"> :icon="ArrowLeft"
<el-form :model="formData" label-width="130px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading"> @back="back()"
<el-form-item :label="t('companyName')" prop="company_name"> />
<el-input v-model.trim="formData.company_name" maxlength="20" clearable :placeholder="t('companyNamePlaceholder')" class="input-width"/> </el-card>
</el-form-item> <el-card class="box-card mt-[15px] !border-none" shadow="never">
<el-form-item :label="t('logo')"> <el-form
<upload-image v-model="formData.logo"/> :model="formData"
</el-form-item> label-width="130px"
<el-form-item :label="t('url')"> ref="formRef"
<el-input v-model.trim="formData.url" clearable :placeholder="t('urlPlaceholder')" class="input-width"/> :rules="formRules"
</el-form-item> class="page-form"
<el-form-item :label="t('expressNo')"> v-loading="loading"
<div> >
<el-input v-model.trim="formData.express_no" clearable :placeholder="t('expressNoPlaceholder')" class="input-width"/> <el-form-item :label="t('companyName')" prop="company_name">
<p class="w-[380px] text-[12px] text-[#999] mt-[5px] leading-[20px]">{{ t('expressNoTips') }}</p> <el-input
</div> v-model.trim="formData.company_name"
</el-form-item> maxlength="20"
<el-form-item :label="t('expressNoElectronicSheet')"> clearable
<div> :placeholder="t('companyNamePlaceholder')"
<el-input v-model.trim="formData.express_no_electronic_sheet" clearable :placeholder="t('expressNoPlaceholder')" class="input-width"/> class="input-width"
<p class="w-[380px] text-[12px] text-[#999] mt-[5px] leading-[20px]">{{ t('expressNoElectronicSheetTips') }}</p> />
</div> </el-form-item>
</el-form-item> <el-form-item :label="t('logo')">
<el-form-item :label="t('electronicSheetSwitch')"> <upload-image v-model="formData.logo" />
<el-switch v-model="formData.electronic_sheet_switch" :active-value="1" :inactive-value="0" /> </el-form-item>
</el-form-item> <el-form-item :label="t('url')">
<el-input
v-model.trim="formData.url"
clearable
:placeholder="t('urlPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('expressNo')">
<div>
<el-input
v-model.trim="formData.express_no"
clearable
:placeholder="t('expressNoPlaceholder')"
class="input-width"
/>
<p
class="w-[380px] text-[12px] text-[#999] mt-[5px] leading-[20px]"
>
{{ t('expressNoTips') }}
</p>
</div>
</el-form-item>
<el-form-item :label="t('expressNoElectronicSheet')">
<div>
<el-input
v-model.trim="formData.express_no_electronic_sheet"
clearable
:placeholder="t('expressNoPlaceholder')"
class="input-width"
/>
<p
class="w-[380px] text-[12px] text-[#999] mt-[5px] leading-[20px]"
>
{{ t('expressNoElectronicSheetTips') }}
</p>
</div>
</el-form-item>
<el-form-item :label="t('electronicSheetSwitch')">
<el-switch
v-model="formData.electronic_sheet_switch"
:active-value="1"
:inactive-value="0"
/>
</el-form-item>
<el-form-item :label="t('expType')" prop="exp_type" v-show="formData.electronic_sheet_switch"> <el-form-item
<div class="w-[600px]"> :label="t('expType')"
<el-table :data="formData.exp_type" size="large" v-show="formData.exp_type.length"> prop="exp_type"
<template #empty> v-show="formData.electronic_sheet_switch"
<span>{{ formData.exp_type.length == 0 ? t('emptyData') : '' }}</span> >
</template> <div class="w-[600px]">
<el-table
:data="formData.exp_type"
size="large"
v-show="formData.exp_type.length"
>
<template #empty>
<span>{{
formData.exp_type.length == 0 ? t('emptyData') : ''
}}</span>
</template>
<el-table-column prop="name" :label="t('expTypeName')" min-width="200"> <el-table-column
<template #default="{ row }"> prop="name"
<el-input v-model.trim="row.text" class="input-width" maxlength="20" clearable show-word-limit /> :label="t('expTypeName')"
</template> min-width="200"
</el-table-column> >
<template #default="{ row }">
<el-input
v-model.trim="row.text"
class="input-width"
maxlength="20"
clearable
show-word-limit
/>
</template>
</el-table-column>
<el-table-column prop="name" :label="t('expTypeValue')" min-width="120"> <el-table-column
<template #default="{ row }"> prop="name"
<el-input v-model.trim="row.value" class="!w-[150px]" maxlength="6" clearable show-word-limit @keyup="filterNumber($event)" /> :label="t('expTypeValue')"
</template> min-width="120"
</el-table-column> >
<template #default="{ row }">
<el-input
v-model.trim="row.value"
class="!w-[150px]"
maxlength="6"
clearable
show-word-limit
@keyup="filterNumber($event)"
/>
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="60"> <el-table-column
<template #default="{ row,$index }"> :label="t('operation')"
<el-button type="primary" link @click="deleteExpTypeValueEvent($index)">{{ t('delete') }}</el-button> fixed="right"
</template> align="right"
</el-table-column> min-width="60"
</el-table> >
<template #default="{ row, $index }">
<el-button
type="primary"
link
@click="deleteExpTypeValueEvent($index)"
>{{ t('delete') }}</el-button
>
</template>
</el-table-column>
</el-table>
<el-button type="primary" plain @click="addExpTypeValueEvent" :class="{'mt-[10px]': formData.exp_type.length}" v-show="formData.exp_type.length < expTypeMaxLength">{{ t('addExpType') }}</el-button> <el-button
<div class="text-[12px] text-[#999] mt-[5px] leading-[20px]"> type="primary"
<span>{{ t('expTypeTips') }}</span> plain
<a class="ml-[3px] text-[var(--el-color-primary)]" target="_blank" href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/hgx758hom5p6wz0l">{{t('examine')}}</a> @click="addExpTypeValueEvent"
</div> :class="{ 'mt-[10px]': formData.exp_type.length }"
<p class="text-[12px] text-[#999] mt-[3px] leading-[20px]">{{ t('expTypeTips1') }}</p> v-show="formData.exp_type.length < expTypeMaxLength"
</div> >{{ t('addExpType') }}</el-button
</el-form-item> >
<div class="text-[12px] text-[#999] mt-[5px] leading-[20px]">
<el-form-item :label="t('printStyle')" prop="print_style" v-show="formData.electronic_sheet_switch"> <span>{{ t('expTypeTips') }}</span>
<div class="w-[600px]"> <a
<el-table :data="formData.print_style" size="large" v-show="formData.print_style.length"> class="ml-[3px] text-[var(--el-color-primary)]"
<template #empty> target="_blank"
<span>{{ formData.print_style.length == 0 ? t('emptyData') : '' }}</span> href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/hgx758hom5p6wz0l"
</template> >{{ t('examine') }}</a
>
<el-table-column prop="name" :label="t('printStyleName')" min-width="200"> </div>
<template #default="{ row }"> <p class="text-[12px] text-[#999] mt-[3px] leading-[20px]">
<el-input v-model.trim="row.template_name" class="input-width" maxlength="20" clearable show-word-limit /> {{ t('expTypeTips1') }}
</template> </p>
</el-table-column> </div>
</el-form-item>
<el-table-column prop="name" :label="t('printStyleId')" min-width="120"> <el-form-item
<template #default="{ row }"> :label="t('printStyle')"
<el-input v-model.trim="row.template_size" class="!w-[150px]" maxlength="6" clearable show-word-limit /> prop="print_style"
</template> v-show="formData.electronic_sheet_switch"
</el-table-column> >
<div class="w-[600px]">
<el-table
:data="formData.print_style"
size="large"
v-show="formData.print_style.length"
>
<template #empty>
<span>{{
formData.print_style.length == 0 ? t('emptyData') : ''
}}</span>
</template>
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="60"> <el-table-column
<template #default="{ row,$index }"> prop="name"
<el-button type="primary" link @click="deletePrintStyleValueEvent($index)">{{ t('delete') }}</el-button> :label="t('printStyleName')"
</template> min-width="200"
</el-table-column> >
<template #default="{ row }">
<el-input
v-model.trim="row.template_name"
class="input-width"
maxlength="20"
clearable
show-word-limit
/>
</template>
</el-table-column>
</el-table> <el-table-column
prop="name"
:label="t('printStyleId')"
min-width="120"
>
<template #default="{ row }">
<el-input
v-model.trim="row.template_size"
class="!w-[150px]"
maxlength="6"
clearable
show-word-limit
/>
</template>
</el-table-column>
<el-button type="primary" plain @click="addPrintStyleValueEvent" :class="{'mt-[10px]': formData.print_style.length}" v-show="formData.print_style.length < printStyleMaxLength">{{ t('addPrintStyle') }}</el-button> <el-table-column
<div class="text-[12px] text-[#999] mt-[5px] leading-[20px]"> :label="t('operation')"
<span>{{ t('printStyleTips') }}</span> fixed="right"
<a class="ml-[3px] text-[var(--el-color-primary)]" target="_blank" href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/vpptucr1q5ahcxa7">{{t('examine')}}</a> align="right"
</div> min-width="60"
<p class="text-[12px] text-[#999] mt-[3px] leading-[20px]">{{ t('printStyleTips1') }}</p> >
<p class="text-[12px] text-[#999] mt-[3px] leading-[20px]">{{ t('printStyleTips2') }}</p> <template #default="{ row, $index }">
</div> <el-button
</el-form-item> type="primary"
link
@click="deletePrintStyleValueEvent($index)"
>{{ t('delete') }}</el-button
>
</template>
</el-table-column>
</el-table>
</el-form> <el-button
</el-card> type="primary"
<div class="fixed-footer-wrap"> plain
<div class="fixed-footer"> @click="addPrintStyleValueEvent"
<el-button type="primary" @click="save(formRef)">{{ t('save') }}</el-button> :class="{ 'mt-[10px]': formData.print_style.length }"
<el-button @click="back()">{{ t('back') }}</el-button> v-show="formData.print_style.length < printStyleMaxLength"
>{{ t('addPrintStyle') }}</el-button
>
<div class="text-[12px] text-[#999] mt-[5px] leading-[20px]">
<span>{{ t('printStyleTips') }}</span>
<a
class="ml-[3px] text-[var(--el-color-primary)]"
target="_blank"
href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/vpptucr1q5ahcxa7"
>{{ t('examine') }}</a
>
</div> </div>
</div> <p class="text-[12px] text-[#999] mt-[3px] leading-[20px]">
</div> {{ t('printStyleTips1') }}
</p>
<p class="text-[12px] text-[#999] mt-[3px] leading-[20px]">
{{ t('printStyleTips2') }}
</p>
</div>
</el-form-item>
</el-form>
</el-card>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" @click="save(formRef)">{{
t('save')
}}</el-button>
<el-button @click="back()">{{ t('back') }}</el-button>
</div>
</div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref, computed } from 'vue' import { reactive, ref, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { addCompany, editCompany, getCompanyInfo } from '@/addon/shop/api/delivery' import {
addCompany,
editCompany,
getCompanyInfo,
} from '@/addon/shop/api/delivery'
import { FormInstance } from 'element-plus' import { FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { filterNumber } from '@/utils/common' import { filterNumber } from '@/utils/common'
@ -127,22 +286,22 @@ const pageName = route.meta.title
const loading = ref(true) const loading = ref(true)
const back = () => { const back = () => {
router.push('/shop/order/delivery/company') router.push('/shop/order/delivery/company')
} }
/** /**
* 表单数据 * 表单数据
*/ */
const initialFormData = { const initialFormData = {
company_id: '', company_id: '',
company_name: '', company_name: '',
logo: '', logo: '',
url: '', url: '',
express_no: '', express_no: '',
express_no_electronic_sheet: "", express_no_electronic_sheet: '',
print_style: [], print_style: [],
exp_type: [], exp_type: [],
electronic_sheet_switch: 1 electronic_sheet_switch: 1,
} }
const printStyleMaxLength = ref(10) const printStyleMaxLength = ref(10)
@ -151,157 +310,156 @@ const expTypeMaxLength = ref(10)
const formData: Record<string, any> = reactive({ ...initialFormData }) const formData: Record<string, any> = reactive({ ...initialFormData })
formData.company_id = ref(route.query.company_id) formData.company_id = ref(route.query.company_id)
const getCompanyInfoFn = ()=>{ const getCompanyInfoFn = () => {
getCompanyInfo(formData.company_id).then(res => { getCompanyInfo(formData.company_id).then((res) => {
loading.value = false; loading.value = false
let data = res.data; let data = res.data
if (data) { if (data) {
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
} }
}) })
} }
if(formData.company_id){ if (formData.company_id) {
getCompanyInfoFn(); getCompanyInfoFn()
}else{ } else {
loading.value = false; loading.value = false
} }
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
company_name: [ company_name: [
{ required: true, message: t('companyNamePlaceholder'), trigger: 'blur' } { required: true, message: t('companyNamePlaceholder'), trigger: 'blur' },
], ],
exp_type: [ exp_type: [
{ {
trigger: 'blur', trigger: 'blur',
validator: (rule: any, value: any, callback: any) => { validator: (rule: any, value: any, callback: any) => {
if(!value.length){ if (!value.length) {
callback() callback()
return false; return false
} }
let textArr = []; // let textArr = [] //
let valArr = []; // let valArr = [] //
for(let i = 0; i < value.length; i++){ for (let i = 0; i < value.length; i++) {
if(!value[i].text){ if (!value[i].text) {
callback(new Error(t('expTypeTextTips'))) callback(new Error(t('expTypeTextTips')))
break; break
}else if(value[i].text){ } else if (value[i].text) {
textArr.push(value[i].text); textArr.push(value[i].text)
}
if(!value[i].value){
callback(new Error(t('expTypeValueTips')))
break;
}else if(parseFloat(value[i].value) == 0 ){
callback(new Error(t('expTypeValueNullTips')))
break;
}else if(value[i].value){
valArr.push(value[i].value);
}
}
if(new Set(textArr).size !== textArr.length){
callback(new Error(t('expTypeTextRepeatTips')))
}
if(new Set(valArr).size !== valArr.length){
callback(new Error(t('expTypeValueRepeatTips')))
}
callback()
}
} }
], if (!value[i].value) {
print_style: [ callback(new Error(t('expTypeValueTips')))
{ break
trigger: 'blur', } else if (parseFloat(value[i].value) == 0) {
validator: (rule: any, value: any, callback: any) => { callback(new Error(t('expTypeValueNullTips')))
if(!value.length){ break
callback() } else if (value[i].value) {
return false; valArr.push(value[i].value)
}
let nameArr = []; //
let sizeArr = []; //
for(let i = 0; i < value.length; i++){
if(!value[i].template_name){
callback(new Error(t('printStyleNameTips')))
break;
}else if(value[i].template_name){
nameArr.push(value[i].template_name);
}
if(!value[i].template_size){
callback(new Error(t('printStyleSizeTips')))
break;
}else if(value[i].template_size){
sizeArr.push(value[i].template_size);
}
}
if(new Set(nameArr).size !== nameArr.length){
callback(new Error(t('printStyleNameRepeatTips')))
}
if(new Set(sizeArr).size !== sizeArr.length){
callback(new Error(t('printStyleSizeRepeatTips')))
}
callback()
}
} }
] }
} if (new Set(textArr).size !== textArr.length) {
callback(new Error(t('expTypeTextRepeatTips')))
}
if (new Set(valArr).size !== valArr.length) {
callback(new Error(t('expTypeValueRepeatTips')))
}
callback()
},
},
],
print_style: [
{
trigger: 'blur',
validator: (rule: any, value: any, callback: any) => {
if (!value.length) {
callback()
return false
}
let nameArr = [] //
let sizeArr = [] //
for (let i = 0; i < value.length; i++) {
if (!value[i].template_name) {
callback(new Error(t('printStyleNameTips')))
break
} else if (value[i].template_name) {
nameArr.push(value[i].template_name)
}
if (!value[i].template_size) {
callback(new Error(t('printStyleSizeTips')))
break
} else if (value[i].template_size) {
sizeArr.push(value[i].template_size)
}
}
if (new Set(nameArr).size !== nameArr.length) {
callback(new Error(t('printStyleNameRepeatTips')))
}
if (new Set(sizeArr).size !== sizeArr.length) {
callback(new Error(t('printStyleSizeRepeatTips')))
}
callback()
},
},
],
}
}) })
// //
const addPrintStyleValueEvent = ()=>{ const addPrintStyleValueEvent = () => {
formData.print_style.push({ formData.print_style.push({
template_name: '', template_name: '',
template_size: '' template_size: '',
}) })
} }
// //
const addExpTypeValueEvent = ()=>{ const addExpTypeValueEvent = () => {
formData.exp_type.push({ formData.exp_type.push({
text: '', text: '',
value: '' value: '',
}) })
} }
// //
const deletePrintStyleValueEvent = (index:any)=>{ const deletePrintStyleValueEvent = (index: any) => {
formData.print_style.splice(index,1) formData.print_style.splice(index, 1)
} }
// //
const deleteExpTypeValueEvent = (index:any)=>{ const deleteExpTypeValueEvent = (index: any) => {
formData.exp_type.splice(index,1) formData.exp_type.splice(index, 1)
} }
/** /**
* 确认 * 确认
* @param formEl * @param formEl
*/ */
const repeat = ref(false) const repeat = ref(false)
const save = async (formEl: FormInstance | undefined) => { const save = async (formEl: FormInstance | undefined) => {
if (repeat.value || !formEl) return if (repeat.value || !formEl) return
const api = formData.company_id ? editCompany : addCompany const api = formData.company_id ? editCompany : addCompany
await formEl.validate(async (valid) => {
if (valid) {
repeat.value = true
const data = formData await formEl.validate(async (valid) => {
api(data).then(res => { if (valid) {
router.push('/shop/order/delivery/company') repeat.value = true
repeat.value = false
}).catch(() => {
repeat.value = false
})
}
})
}
const data = formData
api(data)
.then((res) => {
router.push('/shop/order/delivery/company')
repeat.value = false
})
.catch(() => {
repeat.value = false
})
}
})
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

171
admin/src/addon/shop/views/delivery/components/delivery-personnel-edit.vue

@ -1,27 +1,64 @@
<template> <template>
<el-dialog v-model="showDialog" :title="formData.deliver_id ? t('updateDeliver') : t('addDeliveryPersonnel')" width="480" class="diy-dialog-wrap" :destroy-on-close="true"> <el-dialog
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading"> v-model="showDialog"
<el-form-item :label="t('deliverName')" prop="deliver_name"> :title="
<el-input v-model.trim="formData.deliver_name" clearable :placeholder="t('deliverNamePlaceholder')" class="input-width" maxlength="10"/> formData.deliver_id ? t('updateDeliver') : t('addDeliveryPersonnel')
</el-form-item> "
<el-form-item :label="t('deliverMobile')" prop="deliver_mobile"> width="480"
<el-input v-model.trim="formData.deliver_mobile" clearable :placeholder="t('deliverMobilePlaceholder')" class="input-width" @keyup="filterNumber($event)" @blur="formData.deliver_mobile = $event.target.value" /> class="diy-dialog-wrap"
</el-form-item> :destroy-on-close="true"
</el-form> >
<template #footer> <el-form
<span class="dialog-footer"> :model="formData"
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button> label-width="120px"
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button> ref="formRef"
</span> :rules="formRules"
</template> class="page-form"
</el-dialog> v-loading="loading"
>
<el-form-item :label="t('deliverName')" prop="deliver_name">
<el-input
v-model.trim="formData.deliver_name"
clearable
:placeholder="t('deliverNamePlaceholder')"
class="input-width"
maxlength="10"
/>
</el-form-item>
<el-form-item :label="t('deliverMobile')" prop="deliver_mobile">
<el-input
v-model.trim="formData.deliver_mobile"
clearable
:placeholder="t('deliverMobilePlaceholder')"
class="input-width"
@keyup="filterNumber($event)"
@blur="formData.deliver_mobile = $event.target.value"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, computed } from 'vue' import { ref, reactive, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { addShopDeliver, editShopDeliver, getShopDeliverInfo } from '@/addon/shop/api/delivery' import {
addShopDeliver,
editShopDeliver,
getShopDeliverInfo,
} from '@/addon/shop/api/delivery'
import { filterNumber } from '@/utils/common' import { filterNumber } from '@/utils/common'
const showDialog = ref(false) const showDialog = ref(false)
@ -31,9 +68,9 @@ const loading = ref(false)
* 表单数据 * 表单数据
*/ */
const initialFormData = { const initialFormData = {
deliver_id: '', deliver_id: '',
deliver_name: '', deliver_name: '',
deliver_mobile: '' deliver_mobile: '',
} }
const formData: Record<string, any> = reactive({ ...initialFormData }) const formData: Record<string, any> = reactive({ ...initialFormData })
@ -41,20 +78,24 @@ const formRef = ref<FormInstance>()
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
deliver_name: [ deliver_name: [
{ required: true, message: t('deliverNamePlaceholder'), trigger: 'blur' } { required: true, message: t('deliverNamePlaceholder'), trigger: 'blur' },
], ],
deliver_mobile: [ deliver_mobile: [
{ required: true, message: t('deliverMobilePlaceholder'), trigger: 'blur' }, {
{ min: 11, max: 11, message: '请输入11位手机号码', trigger: 'blur' }, required: true,
{ message: t('deliverMobilePlaceholder'),
pattern :/^1[23456789]\d{9}$/, trigger: 'blur',
message: '请输入正确的手机号码', },
trigger: 'blur' { min: 11, max: 11, message: '请输入11位手机号码', trigger: 'blur' },
} {
] pattern: /^1[23456789]\d{9}$/,
} message: '请输入正确的手机号码',
trigger: 'blur',
},
],
}
}) })
const emit = defineEmits(['complete']) const emit = defineEmits(['complete'])
@ -64,49 +105,51 @@ const emit = defineEmits(['complete'])
* @param formEl * @param formEl
*/ */
const confirm = async (formEl: FormInstance | undefined) => { const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
const save = formData.deliver_id ? editShopDeliver : addShopDeliver const save = formData.deliver_id ? editShopDeliver : addShopDeliver
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
const data = formData const data = formData
save(data).then(res => { save(data)
loading.value = false .then((res) => {
showDialog.value = false loading.value = false
emit('complete') showDialog.value = false
}).catch(() => { emit('complete')
loading.value = false })
}) .catch(() => {
} loading.value = false
}) })
}
})
} }
const setFormData = async (row: any = null) => { const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData) Object.assign(formData, initialFormData)
loading.value = true loading.value = true
if (row) { if (row) {
const data = await (await getShopDeliverInfo(row.deliver_id)).data const data = await (await getShopDeliverInfo(row.deliver_id)).data
if (data) { if (data) {
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
}
} }
loading.value = false }
loading.value = false
} }
defineExpose({ defineExpose({
showDialog, showDialog,
setFormData setFormData,
}) })
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
<style lang="scss"> <style lang="scss">
.diy-dialog-wrap .el-form-item__label { .diy-dialog-wrap .el-form-item__label {
height: auto !important; height: auto !important;
} }
</style> </style>

248
admin/src/addon/shop/views/delivery/config.vue

@ -1,53 +1,108 @@
<template> <template>
<div class="main-container" v-loading="loading"> <div class="main-container" v-loading="loading">
<div class="flex ml-[18px] justify-between items-center mt-[20px]"> <div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-page-title">{{ pageName }}</span> <span class="text-page-title">{{ pageName }}</span>
</div> </div>
<div class="p-[18px] logistics-body" ref="tableRef" :key="toggleIndex" v-if="!loading"> <div
<template v-for="(item, index) in tableData" :key="item.key"> class="p-[18px] logistics-body"
<div class="mb-[20px] bg-[#fff]"> ref="tableRef"
<el-card shadow="never"> :key="toggleIndex"
<template #header> v-if="!loading"
<div class="flex items-center justify-between"> >
<div class="flex items-center"> <template v-for="(item, index) in tableData" :key="item.key">
<i class="iconfont icontuodong vues-rank mr-[5px]"></i> <div class="mb-[20px] bg-[#fff]">
<el-input v-focus v-if="index === activeIndex" v-model.trim="inputValue" class="w-[120px]" maxlength="10" @blur="inputBlur"/> <el-card shadow="never">
<span v-else class="font-600 text-[14px]">{{ item.name }}</span> <template #header>
<el-icon class="text-color ml-[10px] cursor-pointer" @click="edit(index)"> <div class="flex items-center justify-between">
<EditPen/> <div class="flex items-center">
</el-icon> <i class="iconfont icontuodong vues-rank mr-[5px]"></i>
</div> <el-input
<el-switch v-model="item.status" active-value="1" inactive-value="2" @change="update(item)"/> v-focus
</div> v-if="index === activeIndex"
</template> v-model.trim="inputValue"
<div class="flex items-center justify-between"> class="w-[120px]"
<span class="text-[#666666] text-[14px]">{{ t(item.key) }}</span> maxlength="10"
<div> @blur="inputBlur"
<template v-if="item.key === 'local_delivery'"> />
<el-button type="primary" link @click="goRouter('/shop/order/delivery/staff')">{{ t('deliveryStaff') }}</el-button> <span v-else class="font-600 text-[14px]">{{
<el-button type="primary" link @click="goRouter('/shop/order/delivery/local')">{{ t('localConfig') }}</el-button> item.name
</template> }}</span>
<template v-if="item.key === 'express'"> <el-icon
<el-button type="primary" link @click="goRouter('/shop/order/delivery/company')">{{ t('deliveryCompany') }}</el-button> class="text-color ml-[10px] cursor-pointer"
<el-button type="primary" link @click="goRouter('/shop/order/shipping/template')">{{ t('deliveryTemplate') }}</el-button> @click="edit(index)"
<el-button type="primary" link @click="goRouter('/shop/order/delivery/search')">{{ t('deliverySearch') }}</el-button> >
</template> <EditPen />
<template v-if="item.key === 'store'"> </el-icon>
<el-button type="primary" link @click="goRouter('/shop/order/delivery/store')">{{ t('deliveryStore') }}</el-button> </div>
</template> <el-switch
</div> v-model="item.status"
</div> active-value="1"
</el-card> inactive-value="2"
</div> @change="update(item)"
</template> />
</div> </div>
</div> </template>
<div class="flex items-center justify-between">
<span class="text-[#666666] text-[14px]">{{ t(item.key) }}</span>
<div>
<template v-if="item.key === 'local_delivery'">
<el-button
type="primary"
link
@click="goRouter('/shop/order/delivery/staff')"
>{{ t('deliveryStaff') }}</el-button
>
<el-button
type="primary"
link
@click="goRouter('/shop/order/delivery/local')"
>{{ t('localConfig') }}</el-button
>
</template>
<template v-if="item.key === 'express'">
<el-button
type="primary"
link
@click="goRouter('/shop/order/delivery/company')"
>{{ t('deliveryCompany') }}</el-button
>
<el-button
type="primary"
link
@click="goRouter('/shop/order/shipping/template')"
>{{ t('deliveryTemplate') }}</el-button
>
<el-button
type="primary"
link
@click="goRouter('/shop/order/delivery/search')"
>{{ t('deliverySearch') }}</el-button
>
</template>
<template v-if="item.key === 'store'">
<el-button
type="primary"
link
@click="goRouter('/shop/order/delivery/store')"
>{{ t('deliveryStore') }}</el-button
>
</template>
</div>
</div>
</el-card>
</div>
</template>
</div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, nextTick, ref, toRaw } from 'vue' import { onMounted, nextTick, ref, toRaw } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
import { getShopDeliveryList, setShopDeliveryConfig } from '@/addon/shop/api/delivery' import {
getShopDeliveryList,
setShopDeliveryConfig,
} from '@/addon/shop/api/delivery'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
const route = useRoute() const route = useRoute()
@ -55,82 +110,87 @@ const router = useRouter()
const pageName = route.meta.title const pageName = route.meta.title
const loading = ref(false) const loading = ref(false)
interface TableDataType { interface TableDataType {
key: string key: string
name: string name: string
status: number status: number
} }
const tableData = ref<TableDataType[]>([]) const tableData = ref<TableDataType[]>([])
const getShopDeliveryListFn = () => { const getShopDeliveryListFn = () => {
loading.value = true loading.value = true
getShopDeliveryList().then(res => { getShopDeliveryList()
tableData.value = res.data .then((res) => {
loading.value = false tableData.value = res.data
nextTick(() => { loading.value = false
if(rowDrop) rowDrop() nextTick(() => {
}) if (rowDrop) rowDrop()
}).catch(() => { })
loading.value = false })
.catch(() => {
loading.value = false
}) })
} }
onMounted(() => { onMounted(() => {
getShopDeliveryListFn() getShopDeliveryListFn()
}) })
// //
const toggleIndex = ref(0) const toggleIndex = ref(0)
const tableRef = ref() const tableRef = ref()
const rowDrop = () => { const rowDrop = () => {
Sortable.create(tableRef.value, { Sortable.create(tableRef.value, {
handle: '.vues-rank', handle: '.vues-rank',
animation: 300, animation: 300,
onEnd ({ newIndex, oldIndex }) { onEnd({ newIndex, oldIndex }) {
const currRow = tableData.value.splice(oldIndex, 1)[0] const currRow = tableData.value.splice(oldIndex, 1)[0]
tableData.value.splice(newIndex, 0, currRow) tableData.value.splice(newIndex, 0, currRow)
toggleIndex.value += 1 toggleIndex.value += 1
nextTick(() => { nextTick(() => {
rowDrop() rowDrop()
}) })
update() update()
} },
}) })
} }
// //
const activeIndex = ref<number|null>(null) const activeIndex = ref<number | null>(null)
const inputValue = ref('') const inputValue = ref('')
const edit = (index: number) => { const edit = (index: number) => {
activeIndex.value = index activeIndex.value = index
inputValue.value = toRaw(tableData.value[index].name) inputValue.value = toRaw(tableData.value[index].name)
} }
const inputBlur = () => { const inputBlur = () => {
if (inputValue.value == '' || tableData.value[activeIndex.value].name === inputValue.value) { if (
activeIndex.value = null inputValue.value == '' ||
inputValue.value = '' tableData.value[activeIndex.value].name === inputValue.value
return false ) {
}
tableData.value[activeIndex.value].name = inputValue.value
activeIndex.value = null activeIndex.value = null
update() inputValue.value = ''
return false
}
tableData.value[activeIndex.value].name = inputValue.value
activeIndex.value = null
update()
} }
const update = () => { const update = () => {
setShopDeliveryConfig({ setShopDeliveryConfig({
value: tableData.value value: tableData.value,
}) })
} }
const goRouter = (path: string) => { const goRouter = (path: string) => {
router.push({ path }) router.push({ path })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.main-container { .main-container {
min-height: calc(100vh - 64px); min-height: calc(100vh - 64px);
} }
.text-color { .text-color {
color: var(--el-color-primary); color: var(--el-color-primary);
} }
:deep(.el-card__header) { :deep(.el-card__header) {
padding-top: 5px !important; padding-top: 5px !important;
padding-bottom: 5px !important; padding-bottom: 5px !important;
} }
</style> </style>

350
admin/src/addon/shop/views/delivery/electronic_sheet.vue

@ -1,131 +1,216 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center mb-[5px]">
<div class="flex justify-between items-center mb-[5px]"> <span class="text-lg">{{ pageName }}</span>
<span class="text-lg">{{pageName}}</span> <el-button type="primary" @click="addEvent">
<el-button type="primary" @click="addEvent"> {{ t('addElectronicSheet') }}
{{ t('addElectronicSheet') }} </el-button>
</el-button> </div>
</div>
<el-tabs
<el-tabs model-value="/shop/delivery/electronic_sheet" @tab-change="handleClick"> model-value="/shop/delivery/electronic_sheet"
<el-tab-pane :label="t('tabESTemplate')" name="/shop/delivery/electronic_sheet" /> @tab-change="handleClick"
<el-tab-pane :label="t('tabESConfig')" name="/shop/delivery/electronic_sheet/config" /> >
</el-tabs> <el-tab-pane
:label="t('tabESTemplate')"
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> name="/shop/delivery/electronic_sheet"
<el-form :inline="true" :model="tableData.searchParam" ref="searchFormRef"> />
<el-form-item :label="t('templateName')" prop="template_name"> <el-tab-pane
<el-input v-model.trim="tableData.searchParam.template_name" :placeholder="t('templateNamePlaceholder')" maxlength="30" /> :label="t('tabESConfig')"
</el-form-item> name="/shop/delivery/electronic_sheet/config"
/>
<el-form-item :label="t('expressCompany')" prop="express_company_id"> </el-tabs>
<el-select v-model="tableData.searchParam.express_company_id" :placeholder="t('expressCompanyPlaceholder')" clearable>
<el-option v-for="item in companyList" :key="item.company_id" :label="item.company_name" :value="item.company_id" /> <el-card
</el-select> class="box-card !border-none my-[10px] table-search-wrap"
</el-form-item> shadow="never"
>
<el-form-item> <el-form
<el-button type="primary" @click="loadList()">{{ t('search') }}</el-button> :inline="true"
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> :model="tableData.searchParam"
</el-form-item> ref="searchFormRef"
</el-form> >
</el-card> <el-form-item :label="t('templateName')" prop="template_name">
<el-input
<div class="mt-[10px]"> v-model.trim="tableData.searchParam.template_name"
<el-table :data="tableData.data" size="large" v-loading="tableData.loading"> :placeholder="t('templateNamePlaceholder')"
<template #empty> maxlength="30"
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span> />
</template> </el-form-item>
<el-table-column :label="t('templateName')" min-width="200" :show-overflow-tooltip="true">
<template #default="{ row }"> <el-form-item :label="t('expressCompany')" prop="express_company_id">
<el-tag size="small" v-if="row.is_default">{{ t('isDefault') }}</el-tag> <el-select
<span class="ml-[8px]">{{row.template_name}}</span> v-model="tableData.searchParam.express_company_id"
</template> :placeholder="t('expressCompanyPlaceholder')"
</el-table-column> clearable
>
<el-table-column prop="express_company_id" :label="t('expressCompany')" min-width="120" :show-overflow-tooltip="true"> <el-option
<template #default="{ row }"> v-for="item in companyList"
<div>{{ row.company.company_name }}</div> :key="item.company_id"
</template> :label="item.company_name"
</el-table-column> :value="item.company_id"
<el-table-column prop="pay_type_name" :label="t('payType')" min-width="80" :show-overflow-tooltip="true"/> />
</el-select>
<el-table-column prop="status" :label="t('status')" min-width="80" :show-overflow-tooltip="true" > </el-form-item>
<template #default="{ row }">
<div v-if="row.status == 1">{{ t('statusOn') }}</div> <el-form-item>
<div v-if="row.status == 0">{{ t('statusOff') }}</div> <el-button type="primary" @click="loadList()">{{
</template> t('search')
</el-table-column> }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{
<el-table-column :label="t('operation')" fixed="right" min-width="80" align="right"> t('reset')
<template #default="{ row }"> }}</el-button>
<el-button type="primary" link v-if="!row.is_default" @click="setDefaultEvent(row.id)">{{ t('setDefault') }}</el-button> </el-form-item>
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> </el-form>
<el-button type="primary" link v-if="!row.is_default" @click="deleteEvent(row.id)">{{ t('delete') }}</el-button> </el-card>
</template>
</el-table-column> <div class="mt-[10px]">
<el-table
</el-table> :data="tableData.data"
<div class="mt-[16px] flex justify-end"> size="large"
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.limit" v-loading="tableData.loading"
layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" >
@size-change="loadList()" @current-change="loadList" /> <template #empty>
</div> <span>{{ !tableData.loading ? t('emptyData') : '' }}</span>
</div> </template>
<el-table-column
</el-card> :label="t('templateName')"
</div> min-width="200"
:show-overflow-tooltip="true"
>
<template #default="{ row }">
<el-tag size="small" v-if="row.is_default">{{
t('isDefault')
}}</el-tag>
<span class="ml-[8px]">{{ row.template_name }}</span>
</template>
</el-table-column>
<el-table-column
prop="express_company_id"
:label="t('expressCompany')"
min-width="120"
:show-overflow-tooltip="true"
>
<template #default="{ row }">
<div>{{ row.company.company_name }}</div>
</template>
</el-table-column>
<el-table-column
prop="pay_type_name"
:label="t('payType')"
min-width="80"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="status"
:label="t('status')"
min-width="80"
:show-overflow-tooltip="true"
>
<template #default="{ row }">
<div v-if="row.status == 1">{{ t('statusOn') }}</div>
<div v-if="row.status == 0">{{ t('statusOff') }}</div>
</template>
</el-table-column>
<el-table-column
:label="t('operation')"
fixed="right"
min-width="80"
align="right"
>
<template #default="{ row }">
<el-button
type="primary"
link
v-if="!row.is_default"
@click="setDefaultEvent(row.id)"
>{{ t('setDefault') }}</el-button
>
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button
type="primary"
link
v-if="!row.is_default"
@click="deleteEvent(row.id)"
>{{ t('delete') }}</el-button
>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="tableData.page"
v-model:page-size="tableData.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="tableData.total"
@size-change="loadList()"
@current-change="loadList"
/>
</div>
</div>
</el-card>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getElectronicSheetPageList, deleteElectronicSheet, setDefaultElectronicSheet } from '@/addon/shop/api/electronic_sheet' import {
import { ElMessageBox,FormInstance } from 'element-plus' getElectronicSheetPageList,
import { useRoute,useRouter } from 'vue-router' deleteElectronicSheet,
setDefaultElectronicSheet,
} from '@/addon/shop/api/electronic_sheet'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { getCompanyList } from '@/addon/shop/api/delivery' import { getCompanyList } from '@/addon/shop/api/delivery'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title; const pageName = route.meta.title
const tableData = reactive({ const tableData = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
total: 0, total: 0,
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
template_name: "", template_name: '',
express_company_id: "", express_company_id: '',
} },
}) })
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()
const handleClick = (path: string) => { const handleClick = (path: string) => {
router.push({ path }) router.push({ path })
} }
/** /**
* 获取电子面单列表 * 获取电子面单列表
*/ */
const loadList = (page: number = 1) => { const loadList = (page: number = 1) => {
tableData.loading = true tableData.loading = true
tableData.page = page tableData.page = page
getElectronicSheetPageList({ getElectronicSheetPageList({
page: tableData.page, page: tableData.page,
limit: tableData.limit, limit: tableData.limit,
...tableData.searchParam ...tableData.searchParam,
}).then(res => { })
tableData.loading = false .then((res) => {
tableData.data = res.data.data tableData.loading = false
tableData.total = res.data.total tableData.data = res.data.data
}).catch(() => { tableData.total = res.data.total
tableData.loading = false })
.catch(() => {
tableData.loading = false
}) })
} }
@ -134,16 +219,16 @@ loadList()
const companyList = ref([]) const companyList = ref([])
getCompanyList({ getCompanyList({
electronic_sheet_switch: 1 electronic_sheet_switch: 1,
}).then((res:any)=>{ }).then((res: any) => {
companyList.value = res.data; companyList.value = res.data
}) })
/** /**
* 添加电子面单 * 添加电子面单
*/ */
const addEvent = () => { const addEvent = () => {
router.push('/shop/delivery/electronic_sheet_add') router.push('/shop/delivery/electronic_sheet_add')
} }
/** /**
@ -151,48 +236,43 @@ const addEvent = () => {
* @param data * @param data
*/ */
const editEvent = (data: any) => { const editEvent = (data: any) => {
router.push('/shop/delivery/electronic_sheet_edit?id=' + data.id) router.push('/shop/delivery/electronic_sheet_edit?id=' + data.id)
} }
/** /**
* 删除电子面单 * 删除电子面单
*/ */
const deleteEvent = (id: number) => { const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('electronicSheetDeleteTips'), t('warning'), ElMessageBox.confirm(t('electronicSheetDeleteTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning', }).then(() => {
} deleteElectronicSheet(id).then(() => {
).then(() => { loadList()
deleteElectronicSheet(id).then(() => {
loadList()
})
}) })
})
} }
/** /**
* 设置默认电子面单模版 * 设置默认电子面单模版
*/ */
const setDefaultEvent = (id: number) => { const setDefaultEvent = (id: number) => {
ElMessageBox.confirm(t('electronicSheetSetDefaultTips'), t('warning'), ElMessageBox.confirm(t('electronicSheetSetDefaultTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning', }).then(() => {
} setDefaultElectronicSheet({ id }).then(() => {
).then(() => { loadList()
setDefaultElectronicSheet({id}).then(() => {
loadList()
})
}) })
})
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
loadList() loadList()
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

341
admin/src/addon/shop/views/delivery/electronic_sheet_config.vue

@ -1,184 +1,257 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center mb-[5px] h-[32px]">
<div class="flex justify-between items-center mb-[5px] h-[32px]"> <span class="text-lg">{{ pageName }}</span>
<span class="text-lg">{{pageName}}</span> </div>
</div>
<el-tabs
<el-tabs model-value="/shop/delivery/electronic_sheet/config" @tab-change="handleClick"> model-value="/shop/delivery/electronic_sheet/config"
<el-tab-pane :label="t('tabESTemplate')" name="/shop/delivery/electronic_sheet" /> @tab-change="handleClick"
<el-tab-pane :label="t('tabESConfig')" name="/shop/delivery/electronic_sheet/config" /> >
</el-tabs> <el-tab-pane
:label="t('tabESTemplate')"
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading"> name="/shop/delivery/electronic_sheet"
<el-card class="box-card !border-none" shadow="never"> />
<h3 class="panel-title !text-sm">{{ t('apiSet') }}</h3> <el-tab-pane
:label="t('tabESConfig')"
<el-form-item :label="t('interfaceType')" prop="interface_type"> name="/shop/delivery/electronic_sheet/config"
<div> />
<el-radio-group v-model="formData.interface_type"> </el-tabs>
<el-radio label="kdbird" size="large">{{ t('kdn') }}</el-radio>
</el-radio-group> <el-form
<template v-if="formData.interface_type == 'kdbird'"> class="page-form"
<p class="text-[12px] text-[#b2b2b2]"> :model="formData"
{{ t('promptTips1-1') }}<el-button class="button-size" type="primary" link @click="kdnEvent('https://www.kdniao.com')">https://www.kdniao.com</el-button> :rules="formRules"
</p> label-width="150px"
</template> ref="formRef"
</div> v-loading="loading"
</el-form-item> >
<div v-if="formData.interface_type == 'kdbird'"> <el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ t('apiSet') }}</h3>
<el-form-item :label="t('kdnEBusinessIDLabel')" class="input-item">
<div> <el-form-item :label="t('interfaceType')" prop="interface_type">
<el-input v-model.trim="formData.kdniao_id" :placeholder="t('kdnEBusinessIDPlaceholder')" class="input-width" clearable /> <div>
<p class="text-[12px] text-[#b2b2b2]">{{ t('kdnEBusinessIDTips') }}</p> <el-radio-group v-model="formData.interface_type">
</div> <el-radio label="kdbird" size="large">{{ t('kdn') }}</el-radio>
</el-form-item> </el-radio-group>
<template v-if="formData.interface_type == 'kdbird'">
<el-form-item label="API key" class="input-item"> <p class="text-[12px] text-[#b2b2b2]">
<div> {{ t('promptTips1-1')
<el-input v-model.trim="formData.kdniao_api_key" clearable :placeholder="t('kdnAppKeyPlaceholder')" class="input-width" /> }}<el-button
<p class="text-[12px] text-[#b2b2b2]">{{ t('kdnAppKeyTips') }}</p> class="button-size"
</div> type="primary"
</el-form-item> link
@click="kdnEvent('https://www.kdniao.com')"
</div> >https://www.kdniao.com</el-button
>
</el-card> </p>
</template>
<el-card class="box-card !border-none" shadow="never"> </div>
<h3 class="panel-title !text-sm">{{ t('printerSet') }}</h3> </el-form-item>
<div v-if="formData.interface_type == 'kdbird'">
<el-alert type="warning" :closable="false" class="!mb-[10px]"> <el-form-item :label="t('kdnEBusinessIDLabel')" class="input-item">
<template #default> <div>
<p>用双端口加载主JS文件Lodop.js或CLodopfuncs.js兼容老版本以防其中某端口被占</p> <el-input
<p>HTTP推荐端口8000/18000HTTPS推荐端口8443</p> v-model.trim="formData.kdniao_id"
<p>1. 请将打印机连接至本机 </p> :placeholder="t('kdnEBusinessIDPlaceholder')"
<p>2. 在本机上安装打印控件下载链接<a href="http://www.lodop.net/download.html" target="_blank" class="text-primary">http://www.lodop.net/download.html</a></p> class="input-width"
<p>3. 将打印控件中的打印端口下面的打印端口设为相同</p> clearable
</template> />
</el-alert> <p class="text-[12px] text-[#b2b2b2]">
{{ t('kdnEBusinessIDTips') }}
<el-form-item :label="t('serverPort1')" class="input-item-required" prop="server_port1"> </p>
<div> </div>
<el-input v-model.trim="formData.server_port1" :placeholder="t('serverPort1Placeholder')" class="input-width" clearable /> </el-form-item>
</div>
</el-form-item> <el-form-item label="API key" class="input-item">
<div>
<el-form-item :label="t('serverPort2')" class="input-item-required" prop="server_port2"> <el-input
<div> v-model.trim="formData.kdniao_api_key"
<el-input v-model.trim="formData.server_port2" :placeholder="t('serverPort2Placeholder')" class="input-width" clearable /> clearable
</div> :placeholder="t('kdnAppKeyPlaceholder')"
</el-form-item> class="input-width"
/>
<el-form-item :label="t('httpsPort')" class="input-item-required" prop="https_port"> <p class="text-[12px] text-[#b2b2b2]">
<div> {{ t('kdnAppKeyTips') }}
<el-input v-model.trim="formData.https_port" :placeholder="t('httpsPortPlaceholder')" class="input-width" clearable /> </p>
</div> </div>
</el-form-item> </el-form-item>
</div>
</el-card> </el-card>
</el-form>
<el-card class="box-card !border-none" shadow="never">
<div class="fixed-footer-wrap"> <h3 class="panel-title !text-sm">{{ t('printerSet') }}</h3>
<div class="fixed-footer">
<el-button type="primary" :loading="loading" @click="save(formRef)">{{ t('save') }}</el-button> <el-alert type="warning" :closable="false" class="!mb-[10px]">
</div> <template #default>
</div> <p>
</el-card> 用双端口加载主JS文件Lodop.js或CLodopfuncs.js兼容老版本以防其中某端口被占
</p>
</div> <p>HTTP推荐端口8000/18000HTTPS推荐端口8443</p>
<p>1. 请将打印机连接至本机</p>
<p>
2. 在本机上安装打印控件下载链接<a
href="http://www.lodop.net/download.html"
target="_blank"
class="text-primary"
>http://www.lodop.net/download.html</a
>
</p>
<p>3. 将打印控件中的打印端口下面的打印端口设为相同</p>
</template>
</el-alert>
<el-form-item
:label="t('serverPort1')"
class="input-item-required"
prop="server_port1"
>
<div>
<el-input
v-model.trim="formData.server_port1"
:placeholder="t('serverPort1Placeholder')"
class="input-width"
clearable
/>
</div>
</el-form-item>
<el-form-item
:label="t('serverPort2')"
class="input-item-required"
prop="server_port2"
>
<div>
<el-input
v-model.trim="formData.server_port2"
:placeholder="t('serverPort2Placeholder')"
class="input-width"
clearable
/>
</div>
</el-form-item>
<el-form-item
:label="t('httpsPort')"
class="input-item-required"
prop="https_port"
>
<div>
<el-input
v-model.trim="formData.https_port"
:placeholder="t('httpsPortPlaceholder')"
class="input-width"
clearable
/>
</div>
</el-form-item>
</el-card>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" :loading="loading" @click="save(formRef)">{{
t('save')
}}</el-button>
</div>
</div>
</el-card>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { FormInstance, FormRules } from 'element-plus' import { FormInstance, FormRules } from 'element-plus'
import { useRoute,useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { setElectronicSheetConfig, getElectronicSheetConfig } from '@/addon/shop/api/electronic_sheet' import {
setElectronicSheetConfig,
getElectronicSheetConfig,
} from '@/addon/shop/api/electronic_sheet'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title; const pageName = route.meta.title
const loading = ref(true) const loading = ref(true)
const handleClick = (path: string) => { const handleClick = (path: string) => {
router.push({ path }) router.push({ path })
} }
const formData:any = reactive({ const formData: any = reactive({
interface_type: 'kdbird', interface_type: 'kdbird',
kdniao_id: '', kdniao_id: '',
kdniao_api_key: '', kdniao_api_key: '',
server_port1: '8000', server_port1: '8000',
server_port2: '18000', server_port2: '18000',
https_port: '8443' https_port: '8443',
}) })
const setFormData = async () => { const setFormData = async () => {
const data = await (await getElectronicSheetConfig()).data const data = await (await getElectronicSheetConfig()).data
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
loading.value = false loading.value = false
} }
setFormData() setFormData()
const kdnEvent = (url:any) => { const kdnEvent = (url: any) => {
window.open(url, '_blank') window.open(url, '_blank')
} }
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
// //
const formRules = reactive<FormRules>({ const formRules = reactive<FormRules>({
server_port1: [ server_port1: [
{ required: true, message: t('serverPort1Placeholder'), trigger: 'blur' }, { required: true, message: t('serverPort1Placeholder'), trigger: 'blur' },
], ],
server_port2: [ server_port2: [
{ required: true, message: t('serverPort2Placeholder'), trigger: 'blur' }, { required: true, message: t('serverPort2Placeholder'), trigger: 'blur' },
], ],
https_port: [ https_port: [
{ required: true, message: t('httpsPortPlaceholder'), trigger: 'blur' }, { required: true, message: t('httpsPortPlaceholder'), trigger: 'blur' },
], ],
}) })
/** /**
* 保存 * 保存
*/ */
const save = async (formEl: FormInstance | undefined) => { const save = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
setElectronicSheetConfig(formData).then(() => { setElectronicSheetConfig(formData)
loading.value = false .then(() => {
}).catch(() => { loading.value = false
loading.value = false })
}) .catch(() => {
} loading.value = false
}) })
}
})
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.input-item { .input-item {
margin-bottom: 10px !important margin-bottom: 10px !important;
} }
.input-item-required { .input-item-required {
margin-bottom: 20px !important margin-bottom: 20px !important;
} }
.button-size { .button-size {
font-size: 12px !important; font-size: 12px !important;
} }
.el-radio.el-radio--large { .el-radio.el-radio--large {
height: auto !important height: auto !important;
} }
</style> </style>

626
admin/src/addon/shop/views/delivery/electronic_sheet_edit.vue

@ -1,270 +1,384 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never"> <el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" /> <el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card> </el-card>
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading"> <el-form
<el-card class="box-card !border-none" shadow="never"> class="page-form"
:model="formData"
<h3 class="panel-title !text-sm">{{ t('basicSettings') }}</h3> :rules="formRules"
<el-form-item :label="t('templateName')" prop="template_name"> label-width="150px"
<el-input v-model.trim="formData.template_name" clearable :placeholder="t('templateNamePlaceholder')" class="input-width" maxlength="30" /> ref="formRef"
</el-form-item> v-loading="loading"
>
<el-form-item :label="t('expressCompany')" prop="express_company_id"> <el-card class="box-card !border-none" shadow="never">
<el-select v-model="formData.express_company_id" :placeholder="t('expressCompanyPlaceholder')" clearable @change="handleSelectCompanyChange"> <h3 class="panel-title !text-sm">{{ t('basicSettings') }}</h3>
<el-option v-for="item in companyList" :key="item.company_id" :label="item.company_name" :value="item.company_id" /> <el-form-item :label="t('templateName')" prop="template_name">
</el-select> <el-input
</el-form-item> v-model.trim="formData.template_name"
clearable
<el-form-item :label="t('expType')" prop="exp_type" v-show="expTypeList.length"> :placeholder="t('templateNamePlaceholder')"
<el-radio-group v-model="formData.exp_type"> class="input-width"
<el-radio v-for="(item,index) in expTypeList" :key="index" :value="item.value">{{ item.text }}</el-radio> maxlength="30"
</el-radio-group> />
</el-form-item> </el-form-item>
<el-form-item :label="t('printStyle')" v-show="printStyleList.length"> <el-form-item :label="t('expressCompany')" prop="express_company_id">
<div> <el-select
<el-select v-model="formData.print_style" :placeholder="t('printStylePlaceholder')" clearable> v-model="formData.express_company_id"
<el-option v-for="(item,index) in printStyleList" :key="index" :label="item.template_name" :value="item.template_size" /> :placeholder="t('expressCompanyPlaceholder')"
</el-select> clearable
<div class="text-[12px] text-[#999] mt-[3px] leading-[20px]">{{ t('printStyleTips1') }}</div> @change="handleSelectCompanyChange"
<div class="text-[12px] text-[#999] mt-[3px] leading-[20px]">{{ t('printStyleTips2') }}</div> >
</div> <el-option
</el-form-item> v-for="item in companyList"
:key="item.company_id"
</el-card> :label="item.company_name"
<el-card class="box-card !border-none" shadow="never"> :value="item.company_id"
<h3 class="panel-title !text-sm">{{ t('otherSettings') }}</h3> />
</el-select>
<el-form-item :label="t('customerName')"> </el-form-item>
<div>
<el-input v-model.trim="formData.customer_name" clearable class="input-width" maxlength="20" /> <el-form-item
<div class="flex items-center mt-[5px] text-[12px] text-[#999] leading-[20px]"> :label="t('expType')"
<span>{{ t('customerNameTips') }}</span> prop="exp_type"
<a class="ml-[3px] text-[var(--el-color-primary)]" target="_blank" href="https://www.yuque.com/kdnjishuzhichi/rg4owd">{{t('examine')}}</a> v-show="expTypeList.length"
</div> >
<div class="flex items-center mt-[3px] text-[12px] text-[#999] leading-[20px]"> <el-radio-group v-model="formData.exp_type">
<span>{{ t('customerNameTips1') }}</span> <el-radio
<a class="ml-[3px] text-[var(--el-color-primary)]" target="_blank" href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/hrfw43">{{t('examine')}}</a> v-for="(item, index) in expTypeList"
</div> :key="index"
</div> :value="item.value"
</el-form-item> >{{ item.text }}</el-radio
>
<el-form-item :label="t('customerPwd')"> </el-radio-group>
<div> </el-form-item>
<el-input v-model.trim="formData.customer_pwd" clearable class="input-width" maxlength="20" />
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">{{ t('customerPwdTips') }}</div> <el-form-item :label="t('printStyle')" v-show="printStyleList.length">
</div> <div>
</el-form-item> <el-select
v-model="formData.print_style"
<el-form-item :label="t('sendSite')"> :placeholder="t('printStylePlaceholder')"
<div> clearable
<el-input v-model.trim="formData.send_site" clearable class="input-width" maxlength="20" /> >
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">{{ t('sendSiteTips') }}</div> <el-option
</div> v-for="(item, index) in printStyleList"
</el-form-item> :key="index"
:label="item.template_name"
<el-form-item :label="t('sendStaff')"> :value="item.template_size"
<div> />
<el-input v-model.trim="formData.send_staff" clearable class="input-width" maxlength="20" /> </el-select>
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">{{ t('sendStaffTips') }}</div> <div class="text-[12px] text-[#999] mt-[3px] leading-[20px]">
</div> {{ t('printStyleTips1') }}
</el-form-item> </div>
<div class="text-[12px] text-[#999] mt-[3px] leading-[20px]">
<el-form-item :label="t('monthCode')"> {{ t('printStyleTips2') }}
<div> </div>
<el-input v-model.trim="formData.month_code" clearable class="input-width" maxlength="20" /> </div>
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">{{ t('monthCodeTips') }}</div> </el-form-item>
</div> </el-card>
</el-form-item> <el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ t('otherSettings') }}</h3>
<el-form-item :label="t('payType')">
<el-radio-group v-model="formData.pay_type"> <el-form-item :label="t('customerName')">
<el-radio v-for="(item,index) in payType" :value="parseInt(index)">{{ item }}</el-radio> <div>
</el-radio-group> <el-input
</el-form-item> v-model.trim="formData.customer_name"
clearable
<el-form-item :label="t('isNotice')"> class="input-width"
<div> maxlength="20"
<el-radio-group v-model="formData.is_notice"> />
<el-radio :value="1">{{ t('yes') }}</el-radio> <div
<el-radio :value="0">{{ t('no') }}</el-radio> class="flex items-center mt-[5px] text-[12px] text-[#999] leading-[20px]"
</el-radio-group> >
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">{{ t('isNoticeTips') }}</div> <span>{{ t('customerNameTips') }}</span>
</div> <a
</el-form-item> class="ml-[3px] text-[var(--el-color-primary)]"
target="_blank"
<el-form-item :label="t('status')"> href="https://www.yuque.com/kdnjishuzhichi/rg4owd"
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" /> >{{ t('examine') }}</a
</el-form-item> >
</div>
<el-form-item :label="t('isDefault')"> <div
<el-switch v-model="formData.is_default" :active-value="1" :inactive-value="0" /> class="flex items-center mt-[3px] text-[12px] text-[#999] leading-[20px]"
</el-form-item> >
<span>{{ t('customerNameTips1') }}</span>
</el-card> <a
</el-form> class="ml-[3px] text-[var(--el-color-primary)]"
target="_blank"
<div class="fixed-footer-wrap"> href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/hrfw43"
<div class="fixed-footer"> >{{ t('examine') }}</a
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button> >
<el-button @click="back()">{{ t('cancel') }}</el-button> </div>
</div> </div>
</div> </el-form-item>
</div>
<el-form-item :label="t('customerPwd')">
<div>
<el-input
v-model.trim="formData.customer_pwd"
clearable
class="input-width"
maxlength="20"
/>
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">
{{ t('customerPwdTips') }}
</div>
</div>
</el-form-item>
<el-form-item :label="t('sendSite')">
<div>
<el-input
v-model.trim="formData.send_site"
clearable
class="input-width"
maxlength="20"
/>
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">
{{ t('sendSiteTips') }}
</div>
</div>
</el-form-item>
<el-form-item :label="t('sendStaff')">
<div>
<el-input
v-model.trim="formData.send_staff"
clearable
class="input-width"
maxlength="20"
/>
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">
{{ t('sendStaffTips') }}
</div>
</div>
</el-form-item>
<el-form-item :label="t('monthCode')">
<div>
<el-input
v-model.trim="formData.month_code"
clearable
class="input-width"
maxlength="20"
/>
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">
{{ t('monthCodeTips') }}
</div>
</div>
</el-form-item>
<el-form-item :label="t('payType')">
<el-radio-group v-model="formData.pay_type">
<el-radio
v-for="(item, index) in payType"
:value="parseInt(index)"
>{{ item }}</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('isNotice')">
<div>
<el-radio-group v-model="formData.is_notice">
<el-radio :value="1">{{ t('yes') }}</el-radio>
<el-radio :value="0">{{ t('no') }}</el-radio>
</el-radio-group>
<div class="mt-[5px] text-[12px] text-[#999] leading-[20px]">
{{ t('isNoticeTips') }}
</div>
</div>
</el-form-item>
<el-form-item :label="t('status')">
<el-switch
v-model="formData.status"
:active-value="1"
:inactive-value="0"
/>
</el-form-item>
<el-form-item :label="t('isDefault')">
<el-switch
v-model="formData.is_default"
:active-value="1"
:inactive-value="0"
/>
</el-form-item>
</el-card>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{
t('save')
}}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, computed } from 'vue' import { ref, reactive, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { import {
addElectronicSheet, addElectronicSheet,
editElectronicSheet, editElectronicSheet,
getElectronicSheetInfo, getElectronicSheetInfo,
getElectronicSheetPayType getElectronicSheetPayType,
} from '@/addon/shop/api/electronic_sheet' } from '@/addon/shop/api/electronic_sheet'
import { getCompanyList } from '@/addon/shop/api/delivery' import { getCompanyList } from '@/addon/shop/api/delivery'
const loading = ref(false) const loading = ref(false)
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const repeat = ref(false) const repeat = ref(false)
const pageName = route.meta.title const pageName = route.meta.title
/** /**
* 表单数据 * 表单数据
*/ */
const initialFormData:any = { const initialFormData: any = {
id: route.query.id || 0, id: route.query.id || 0,
template_name: '', template_name: '',
express_company_id: '', express_company_id: '',
customer_name: '', customer_name: '',
customer_pwd: '', customer_pwd: '',
send_site: '', send_site: '',
send_staff: '', send_staff: '',
month_code: '', month_code: '',
pay_type: 1, pay_type: 1,
is_notice: 0, is_notice: 0,
status: 1, status: 1,
exp_type: 1, exp_type: 1,
print_style: '', print_style: '',
is_default: '', is_default: '',
} }
const formData: Record<string, any> = reactive({ ...initialFormData }) const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
template_name: [ template_name: [
{ required: true, message: t('templateNamePlaceholder'), trigger: 'blur' }, {
], required: true,
express_company_id: [ message: t('templateNamePlaceholder'),
{ required: true, message: t('expressCompanyPlaceholder'), trigger: 'blur' }, trigger: 'blur',
] },
} ],
express_company_id: [
{
required: true,
message: t('expressCompanyPlaceholder'),
trigger: 'blur',
},
],
}
})
const companyList: any = ref([]) //
const expTypeList: any = ref([]) //
const printStyleList: any = ref([]) //
const payType = ref([])
const init = async () => {
getElectronicSheetPayType().then((res: any) => {
payType.value = res.data
})
await getCompanyList({ electronic_sheet_switch: 1 }).then((res: any) => {
companyList.value = res.data
})
if (formData.id) {
loading.value = true
getElectronicSheetInfo(formData.id).then((res: any) => {
let data = res.data
if (data)
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
loading.value = false
handleSelectCompanyChange(formData.express_company_id, true)
}) })
}
const companyList: any = ref([]) // }
const expTypeList: any = ref([]) //
const printStyleList: any = ref([]) // init()
const payType = ref([])
const handleSelectCompanyChange = (value: any, load: any = false) => {
const init = async ()=> { if (!value) {
getElectronicSheetPayType().then((res: any) => { expTypeList.value = []
payType.value = res.data; printStyleList.value = []
}) return
}
await getCompanyList({ electronic_sheet_switch: 1 }).then((res: any) => {
companyList.value = res.data; for (let i = 0; i < companyList.value.length; i++) {
}) if (companyList.value[i].company_id == value) {
expTypeList.value = companyList.value[i].exp_type
if (formData.id) { expTypeList.value.forEach((item: any) => {
loading.value = true if (item.value) item.value = parseInt(item.value)
getElectronicSheetInfo(formData.id).then((res: any) => { })
let data = res.data; printStyleList.value = companyList.value[i].print_style
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (!load) {
}) if (expTypeList.value.length) {
loading.value = false formData.exp_type = expTypeList.value[0].value
handleSelectCompanyChange(formData.express_company_id, true) } else {
}) formData.exp_type = 1 // 1
}
}
init();
const handleSelectCompanyChange = (value: any,load: any = false) => {
if (!value) {
expTypeList.value = [];
printStyleList.value = [];
return;
} }
if (printStyleList.value.length) {
for (let i = 0; i < companyList.value.length; i++) { formData.print_style = printStyleList.value[0].value
if (companyList.value[i].company_id == value) { } else {
expTypeList.value = companyList.value[i].exp_type; formData.print_style = '' //
expTypeList.value.forEach((item: any) => {
if (item.value) item.value = parseInt(item.value);
})
printStyleList.value = companyList.value[i].print_style;
if (!load) {
if (expTypeList.value.length) {
formData.exp_type = expTypeList.value[0].value
} else {
formData.exp_type = 1; // 1
}
if (printStyleList.value.length) {
formData.print_style = printStyleList.value[0].value
} else {
formData.print_style = ''; //
}
}
break;
}
} }
}
break
} }
}
/** }
* 确认
* @param formEl /**
*/ * 确认
const confirm = async(formEl: FormInstance | undefined) => { * @param formEl
if (loading.value || !formEl) return */
let save = formData.id ? editElectronicSheet : addElectronicSheet const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async(valid) => { let save = formData.id ? editElectronicSheet : addElectronicSheet
if (valid) {
await formEl.validate(async (valid) => {
if (repeat.value) return if (valid) {
repeat.value = true if (repeat.value) return
repeat.value = true
let data = formData
let data = formData
save(data).then(res => {
repeat.value = false save(data)
if (!formData.id) { .then((res) => {
router.push('/shop/delivery/electronic_sheet') repeat.value = false
} if (!formData.id) {
}).catch(err => { router.push('/shop/delivery/electronic_sheet')
repeat.value = false }
}) })
} .catch((err) => {
repeat.value = false
}) })
} }
})
}
const back = () => { const back = () => {
router.push('/shop/delivery/electronic_sheet') router.push('/shop/delivery/electronic_sheet')
} }
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

773
admin/src/addon/shop/views/delivery/local.vue

@ -1,18 +1,25 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never"> <el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" /> <el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card> </el-card>
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<el-form label-width="120px" ref="formRef" :rules="formRules" :model="formData" class="page-form" v-loading="loading"> <el-form
<!-- <h3 class="panel-title">{{t('basicSettings')}}</h3> --> label-width="120px"
<el-form-item :label="t('deliveryType')" prop="delivery_type"> ref="formRef"
<el-checkbox-group v-model="formData.delivery_type"> :rules="formRules"
<el-checkbox label="business">{{ t('business') }}</el-checkbox> :model="formData"
</el-checkbox-group> class="page-form"
</el-form-item> v-loading="loading"
<!-- <el-form-item :label="t('timeIsOpen')" prop="time_is_open"> >
<!-- <h3 class="panel-title">{{t('basicSettings')}}</h3> -->
<el-form-item :label="t('deliveryType')" prop="delivery_type">
<el-checkbox-group v-model="formData.delivery_type">
<el-checkbox label="business">{{ t('business') }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<!-- <el-form-item :label="t('timeIsOpen')" prop="time_is_open">
<div> <div>
<el-radio-group v-model="formData.time_is_open"> <el-radio-group v-model="formData.time_is_open">
<el-radio :label="1">{{ t('open') }}</el-radio> <el-radio :label="1">{{ t('open') }}</el-radio>
@ -40,116 +47,233 @@
</el-checkbox-group> </el-checkbox-group>
</el-form-item> </el-form-item>
</template> --> </template> -->
<el-form-item :label="t('deliveryAddress')" prop="delivery_address"> <el-form-item :label="t('deliveryAddress')" prop="delivery_address">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="flex"> <div class="flex">
{{ defaultDeliveryAddress ? defaultDeliveryAddress.full_address : t('defaultDeliveryAddressEmpty') }} {{
<el-button type="primary" @click="router.push('/shop/order/address')" link class="ml-[10px]">{{ defaultDeliveryAddress ? t('update') : t('toSetting') }}</el-button> defaultDeliveryAddress
</div> ? defaultDeliveryAddress.full_address
<div class="text-error leading-none" v-if="formData.center.lat && defaultDeliveryAddress && (formData.center.lat != defaultDeliveryAddress.lat || formData.center.lng != defaultDeliveryAddress.lng)"> : t('defaultDeliveryAddressEmpty')
{{ t('deliveryAddressChange') }}</div> }}
</div> <el-button
</el-form-item> type="primary"
<el-form-item :label="t('feeType')"> @click="router.push('/shop/order/address')"
<el-radio-group v-model="formData.fee_type"> link
<el-radio label="region">{{ t('region') }}</el-radio> class="ml-[10px]"
<el-radio label="distance">{{ t('distance') }}</el-radio> >{{
</el-radio-group> defaultDeliveryAddress ? t('update') : t('toSetting')
</el-form-item> }}</el-button
<el-form-item :label="t('feeSetting')" prop="distance" v-show="formData.fee_type == 'distance'"> >
<div class="flex"> </div>
<div class="w-[60px] mx-[5px]"> <div
<el-input v-model.number="formData.base_dist" type="text" @keyup="filterDigit($event)" /> class="text-error leading-none"
</div> v-if="
{{ t('feeSettingTextOne') }} formData.center.lat &&
<div class="w-[60px] mx-[5px]"> defaultDeliveryAddress &&
<el-input v-model.trim="formData.base_price" type="text" @keyup="filterDigit($event)"/> (formData.center.lat != defaultDeliveryAddress.lat ||
</div> formData.center.lng != defaultDeliveryAddress.lng)
{{ t('feeSettingTextTwo') }} "
<div class="w-[60px] mx-[5px]"> >
<el-input v-model.number="formData.grad_dist" type="text" @keyup="filterDigit($event)"/> {{ t('deliveryAddressChange') }}
</div> </div>
{{ t('feeSettingTextThree') }} </div>
<div class="w-[60px] mx-[5px]"> </el-form-item>
<el-input v-model.trim="formData.grad_price" type="text" @keyup="filterDigit($event)"/> <el-form-item :label="t('feeType')">
</div> <el-radio-group v-model="formData.fee_type">
{{ t('priceUnit') }} <el-radio label="region">{{ t('region') }}</el-radio>
<el-radio label="distance">{{ t('distance') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
:label="t('feeSetting')"
prop="distance"
v-show="formData.fee_type == 'distance'"
>
<div class="flex">
<div class="w-[60px] mx-[5px]">
<el-input
v-model.number="formData.base_dist"
type="text"
@keyup="filterDigit($event)"
/>
</div>
{{ t('feeSettingTextOne') }}
<div class="w-[60px] mx-[5px]">
<el-input
v-model.trim="formData.base_price"
type="text"
@keyup="filterDigit($event)"
/>
</div>
{{ t('feeSettingTextTwo') }}
<div class="w-[60px] mx-[5px]">
<el-input
v-model.number="formData.grad_dist"
type="text"
@keyup="filterDigit($event)"
/>
</div>
{{ t('feeSettingTextThree') }}
<div class="w-[60px] mx-[5px]">
<el-input
v-model.trim="formData.grad_price"
type="text"
@keyup="filterDigit($event)"
/>
</div>
{{ t('priceUnit') }}
</div>
</el-form-item>
<el-form-item :label="t('weightFee')" prop="">
<div class="flex">
{{ t('weightFeeTextOne') }}
<div class="w-[60px] mx-[5px]">
<el-input
v-model.trim="formData.weight_start"
type="text"
@keyup="filterDigit($event)"
/>
</div>
{{ t('weightFeeTextTwo') }}
<div class="w-[60px] mx-[5px]">
<el-input
v-model.trim="formData.weight_unit"
type="text"
@keyup="filterDigit($event)"
/>
</div>
{{ t('weightFeeTextThree') }}
<div class="w-[60px] mx-[5px]">
<el-input
v-model.trim="formData.weight_price"
type="text"
@keyup="filterDigit($event)"
/>
</div>
{{ t('priceUnit') }}
</div>
</el-form-item>
<el-form-item prop="area" v-loading="mapLoading">
<div class="relative w-full">
<div id="container" class="w-full h-[520px]"></div>
<div
class="absolute bg-white w-[270px] h-[500px] top-[10px] left-[10px] region-list"
>
<el-scrollbar>
<div
class="p-[10px] region-item pr-[50px] relative"
v-for="(item, index) in formData.area"
:key="index"
:class="{ '!border-primary': index == currArea }"
@click="selectArea(index)"
>
<el-form
label-width="80px"
:model="item"
:rules="formRules"
class="page-form"
ref="areaFromRef"
>
<div class="pb-[18px]">
<el-form-item :label="t('areaName')" prop="area_name">
<el-input
v-model.trim="formData.area[index].area_name"
type="text"
/>
</el-form-item>
</div> </div>
</el-form-item> <div class="pb-[18px]">
<el-form-item :label="t('weightFee')" prop=""> <el-form-item :label="t('startPrice')" prop="start_price">
<div class="flex"> <el-input
{{ t('weightFeeTextOne') }} v-model.trim="formData.area[index].start_price"
<div class="w-[60px] mx-[5px]"> type="text"
<el-input v-model.trim="formData.weight_start" type="text" @keyup="filterDigit($event)"/> @keyup="filterDigit($event)"
</div> />
{{ t('weightFeeTextTwo') }} </el-form-item>
<div class="w-[60px] mx-[5px]">
<el-input v-model.trim="formData.weight_unit" type="text" @keyup="filterDigit($event)"/>
</div>
{{ t('weightFeeTextThree') }}
<div class="w-[60px] mx-[5px]">
<el-input v-model.trim="formData.weight_price" type="text" @keyup="filterDigit($event)" />
</div>
{{ t('priceUnit') }}
</div> </div>
</el-form-item> <div
class="pb-[10px]"
<el-form-item prop="area" v-loading="mapLoading"> v-show="formData.fee_type == 'region'"
<div class="relative w-full"> >
<div id="container" class="w-full h-[520px]"></div> <el-form-item
<div class="absolute bg-white w-[270px] h-[500px] top-[10px] left-[10px] region-list"> :label="t('deliveryPrice')"
<el-scrollbar> prop="delivery_price"
<div class="p-[10px] region-item pr-[50px] relative" v-for="(item, index) in formData.area" :key="index" :class="{ '!border-primary': index == currArea }" @click="selectArea(index)"> >
<el-form label-width="80px" :model="item" :rules="formRules" class="page-form" ref="areaFromRef"> <el-input
<div class="pb-[18px]"> v-model.trim="formData.area[index].delivery_price"
<el-form-item :label="t('areaName')" prop="area_name"> type="text"
<el-input v-model.trim="formData.area[index].area_name" type="text" /> @keyup="filterDigit($event)"
</el-form-item> />
</div> </el-form-item>
<div class="pb-[18px]">
<el-form-item :label="t('startPrice')" prop="start_price">
<el-input v-model.trim="formData.area[index].start_price" type="text" @keyup="filterDigit($event)" />
</el-form-item>
</div>
<div class="pb-[10px]" v-show="formData.fee_type == 'region'">
<el-form-item :label="t('deliveryPrice')" prop="delivery_price">
<el-input v-model.trim="formData.area[index].delivery_price" type="text" @keyup="filterDigit($event)"/>
</el-form-item>
</div>
<el-form-item :label="t('areaType')">
<el-radio-group v-model="formData.area[index].area_type" @click.stop="" @change="areaTypeChange(index)">
<el-radio label="radius" size="large" class="!mr-[10px]">{{ t('radius') }}</el-radio>
<el-radio label="custom" size="large" class="!mr-[0px]">{{ t('custom') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<el-button type="primary" link class="absolute z-1 top-[10px] right-[10px]" @click.stop="deleteArea(index)">{{ t('delete') }}</el-button>
</div>
<div class="p-[10px] text-center">
<el-button type="default" plain @click="addArea">{{ t('addDeliveryArea') }}</el-button>
</div>
</el-scrollbar>
</div>
</div> </div>
</el-form-item> <el-form-item :label="t('areaType')">
</el-form> <el-radio-group
</el-card> v-model="formData.area[index].area_type"
<div class="fixed-footer-wrap"> @click.stop=""
<div class="fixed-footer"> @change="areaTypeChange(index)"
<el-button type="primary" @click="onSave(formRef)" :disabled="loading">{{ t('save') }}</el-button> >
<el-button @click="back()">{{ t('cancel') }}</el-button> <el-radio
label="radius"
size="large"
class="!mr-[10px]"
>{{ t('radius') }}</el-radio
>
<el-radio
label="custom"
size="large"
class="!mr-[0px]"
>{{ t('custom') }}</el-radio
>
</el-radio-group>
</el-form-item>
</el-form>
<el-button
type="primary"
link
class="absolute z-1 top-[10px] right-[10px]"
@click.stop="deleteArea(index)"
>{{ t('delete') }}</el-button
>
</div>
<div class="p-[10px] text-center">
<el-button type="default" plain @click="addArea">{{
t('addDeliveryArea')
}}</el-button>
</div>
</el-scrollbar>
</div> </div>
</div> </div>
</el-form-item>
</el-form>
</el-card>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button
type="primary"
@click="onSave(formRef)"
:disabled="loading"
>{{ t('save') }}</el-button
>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div> </div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, onMounted, onBeforeUnmount,toRaw } from 'vue' import { ref, computed, onMounted, onBeforeUnmount, toRaw } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { getMap } from '@/app/api/sys' import { getMap } from '@/app/api/sys'
import { guid, filterDigit, deepClone } from '@/utils/common' import { guid, filterDigit, deepClone } from '@/utils/common'
import { createCircle, deleteGeometry, createPolygon, selectGeometry, createMarker } from '@/utils/qqmap' import {
createCircle,
deleteGeometry,
createPolygon,
selectGeometry,
createMarker,
} from '@/utils/qqmap'
import { setLocal, getLocal } from '@/addon/shop/api/delivery' import { setLocal, getLocal } from '@/addon/shop/api/delivery'
import { FormInstance } from 'element-plus' import { FormInstance } from 'element-plus'
import Test from '@/utils/test' import Test from '@/utils/test'
@ -161,154 +285,170 @@ const loading = ref(true)
const pageName = route.meta.title const pageName = route.meta.title
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const areaFromRef: any = ref<FormInstance[]>() const areaFromRef: any = ref<FormInstance[]>()
interface addressType{ interface addressType {
full_address:string full_address: string
lat:string lat: string
lng:string lng: string
} }
const defaultDeliveryAddress:any = ref<addressType|null>(null) const defaultDeliveryAddress: any = ref<addressType | null>(null)
const getDefaultDeliveryAddress = async () => { const getDefaultDeliveryAddress = async () => {
await getShopDefaultDeliveryAddressInfo().then(({ data }) => { await getShopDefaultDeliveryAddressInfo()
defaultDeliveryAddress.value = data .then(({ data }) => {
}).catch() defaultDeliveryAddress.value = data
})
.catch()
} }
getDefaultDeliveryAddress() getDefaultDeliveryAddress()
const formData = ref({ const formData = ref({
center: { center: {
lat: '', lat: '',
lng: '' lng: '',
},
delivery_type: ['business'],
fee_type: 'region',
time_is_open: 1,
time_type: 0,
time_week: <any>[],
base_dist: '',
base_price: '',
grad_dist: '',
grad_price: '',
weight_start: 0.0,
weight_unit: 0,
weight_price: 0,
area: [
{
area_name: '',
area_type: 'radius',
start_price: 0,
delivery_price: 0,
area_json: {
key: guid(),
},
}, },
delivery_type: ['business'], ],
fee_type: 'region',
time_is_open:1,
time_type:0,
time_week: <any>[],
base_dist: '',
base_price: '',
grad_dist: '',
grad_price: '',
weight_start: 0.000,
weight_unit: 0,
weight_price: 0,
area: [
{
area_name: '',
area_type: 'radius',
start_price: 0,
delivery_price: 0,
area_json: {
key: guid()
}
}
]
}) })
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
time_week: [{ required: true, message: t('timeWeekRequire'), trigger: 'change' }], time_week: [
delivery_address: [ { required: true, message: t('timeWeekRequire'), trigger: 'change' },
{ ],
validator: (rule: any, value: any, callback: any) => { delivery_address: [
if (!defaultDeliveryAddress.value) { {
callback(new Error(t('defaultDeliveryAddressEmpty'))) validator: (rule: any, value: any, callback: any) => {
} if (!defaultDeliveryAddress.value) {
callback() callback(new Error(t('defaultDeliveryAddressEmpty')))
} }
} callback()
], },
delivery_type: [ },
{ ],
validator: (rule: any, value: any, callback: any) => { delivery_type: [
if (!formData.value.delivery_type.length) { {
callback(new Error(t('deliveryTypeRequire'))) validator: (rule: any, value: any, callback: any) => {
} if (!formData.value.delivery_type.length) {
callback() callback(new Error(t('deliveryTypeRequire')))
} }
callback()
},
},
],
distance: [
{
validator: (rule: any, value: any, callback: any) => {
if (formData.value.fee_type == 'distance') {
if (Test.require(formData.value.base_dist)) {
callback(new Error(t('baseDistRequire')))
} }
], if (Test.require(formData.value.base_price)) {
distance: [ callback(new Error(t('basePriceRequire')))
{
validator: (rule: any, value: any, callback: any) => {
if (formData.value.fee_type == 'distance') {
if (Test.require(formData.value.base_dist)) {
callback(new Error(t('baseDistRequire')))
}
if (Test.require(formData.value.base_price)) {
callback(new Error(t('basePriceRequire')))
}
if (Test.require(formData.value.grad_dist)) {
callback(new Error(t('gradDistRequire')))
}
if (Test.require(formData.value.grad_price)) {
callback(new Error(t('gradPriceRequire')))
}
}
callback()
},
trigger: 'blur'
} }
], if (Test.require(formData.value.grad_dist)) {
area_name: [{ required: true, message: t('areaNameRequire'), trigger: 'blur' }], callback(new Error(t('gradDistRequire')))
start_price: [
{ required: true, message: t('startPriceRequire'), trigger: 'blur' },
{
validator: (rule: any, value: any, callback: any) => {
if (parseInt(value) < 0) {
callback(new Error(t('startPriceMin')))
}
callback()
},
trigger: 'blur'
} }
], if (Test.require(formData.value.grad_price)) {
delivery_price: [ callback(new Error(t('gradPriceRequire')))
{ required: formData.value.fee_type == 'region', message: t('deliveryPriceRequire'), trigger: 'blur' },
{
validator: (rule: any, value: any, callback: any) => {
if (parseInt(value) < 0) {
callback(new Error(t('deliveryPriceMin')))
}
callback()
},
trigger: 'blur'
} }
], }
area: [ callback()
{ },
validator: (rule: any, value: any, callback: any) => { trigger: 'blur',
if (Test.empty(formData.value.area)) { },
callback(new Error(t('areaPlaceholder'))) ],
} area_name: [
callback() { required: true, message: t('areaNameRequire'), trigger: 'blur' },
}, ],
trigger: 'blur' start_price: [
} { required: true, message: t('startPriceRequire'), trigger: 'blur' },
] {
} validator: (rule: any, value: any, callback: any) => {
if (parseInt(value) < 0) {
callback(new Error(t('startPriceMin')))
}
callback()
},
trigger: 'blur',
},
],
delivery_price: [
{
required: formData.value.fee_type == 'region',
message: t('deliveryPriceRequire'),
trigger: 'blur',
},
{
validator: (rule: any, value: any, callback: any) => {
if (parseInt(value) < 0) {
callback(new Error(t('deliveryPriceMin')))
}
callback()
},
trigger: 'blur',
},
],
area: [
{
validator: (rule: any, value: any, callback: any) => {
if (Test.empty(formData.value.area)) {
callback(new Error(t('areaPlaceholder')))
}
callback()
},
trigger: 'blur',
},
],
}
}) })
getLocal().then(({ data }) => { getLocal()
.then(({ data }) => {
loading.value = false loading.value = false
if (data) Object.assign(formData.value, data) if (data) Object.assign(formData.value, data)
formData.value.time_week = formData.value.time_week?formData.value.time_week.split(','):[] formData.value.time_week = formData.value.time_week
}).catch(()=>{ ? formData.value.time_week.split(',')
loading.value = false : []
}) })
.catch(() => {
loading.value = false
})
onMounted(() => { onMounted(() => {
const mapScript = document.createElement('script') const mapScript = document.createElement('script')
getMap().then(res => { getMap().then((res) => {
mapScript.type = 'text/javascript' mapScript.type = 'text/javascript'
mapScript.src = 'https://map.qq.com/api/gljs?libraries=tools,service&v=1.exp&key=' + res.data.key mapScript.src =
document.body.appendChild(mapScript) 'https://map.qq.com/api/gljs?libraries=tools,service&v=1.exp&key=' +
}) res.data.key
mapScript.onload = () => { document.body.appendChild(mapScript)
setTimeout(() => { })
initMap() mapScript.onload = () => {
}, 500) setTimeout(() => {
} initMap()
}, 500)
}
}) })
/** /**
@ -317,23 +457,28 @@ onMounted(() => {
let map: any let map: any
const mapLoading = ref(true) const mapLoading = ref(true)
const initMap = () => { const initMap = () => {
const TMap = (window as any).TMap const TMap = (window as any).TMap
const LatLng = TMap.LatLng const LatLng = TMap.LatLng
const center = new LatLng(defaultDeliveryAddress.value ? defaultDeliveryAddress.value.lat : 39.980619, defaultDeliveryAddress.value ? defaultDeliveryAddress.value.lng : 116.321277) const center = new LatLng(
defaultDeliveryAddress.value ? defaultDeliveryAddress.value.lat : 39.980619,
defaultDeliveryAddress.value ? defaultDeliveryAddress.value.lng : 116.321277
)
map = new TMap.Map('container', { map = new TMap.Map('container', {
center, center,
zoom: 14 zoom: 14,
}) })
createMarker(map) createMarker(map)
map.on('tilesloaded', () => { map.on('tilesloaded', () => {
mapLoading.value = false mapLoading.value = false
}) })
formData.value.area.forEach(item => { formData.value.area.forEach((item) => {
item.area_type == 'radius' ? createCircle(map, item.area_json) : createPolygon(map, item.area_json) item.area_type == 'radius'
}) ? createCircle(map, item.area_json)
: createPolygon(map, item.area_json)
})
} }
const currArea = ref<number>(0) const currArea = ref<number>(0)
@ -342,96 +487,100 @@ const currArea = ref<number>(0)
* 添加配送区域 * 添加配送区域
*/ */
const addArea = () => { const addArea = () => {
formData.value.area.push({ formData.value.area.push({
area_name: '', area_name: '',
area_type: 'radius', area_type: 'radius',
start_price: 0, start_price: 0,
delivery_price: 0, delivery_price: 0,
area_json: { area_json: {
key: guid() key: guid(),
} },
}) })
const index = formData.value.area.length - 1 const index = formData.value.area.length - 1
createCircle(map, formData.value.area[index].area_json) createCircle(map, formData.value.area[index].area_json)
} }
/** /**
* 删除配送区域 * 删除配送区域
*/ */
const deleteArea = (index: number) => { const deleteArea = (index: number) => {
const data = formData.value.area[index] const data = formData.value.area[index]
deleteGeometry(data.area_json.key) deleteGeometry(data.area_json.key)
formData.value.area.splice(index, 1) formData.value.area.splice(index, 1)
} }
const selectArea = (index: number) => { const selectArea = (index: number) => {
currArea.value = index currArea.value = index
const data = formData.value.area[index] const data = formData.value.area[index]
selectGeometry(data.area_json.key) selectGeometry(data.area_json.key)
} }
const areaTypeChange = (index: number) => { const areaTypeChange = (index: number) => {
const data = formData.value.area[index] const data = formData.value.area[index]
deleteGeometry(data.area_json.key) deleteGeometry(data.area_json.key)
data.area_type == 'radius' ? createCircle(map, data.area_json) : createPolygon(map, data.area_json) data.area_type == 'radius'
? createCircle(map, data.area_json)
: createPolygon(map, data.area_json)
} }
onBeforeUnmount(() => { onBeforeUnmount(() => {
map.destroy() map.destroy()
}) })
const onSave = async (formEl: FormInstance | undefined) => { const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
let areaValidate = true
await formEl.validate(async (valid) => { for (let i = 0; i < areaFromRef.value?.length; i++) {
let areaValidate = true const ref = areaFromRef.value[i]
await ref.validate(async (valid) => {
areaValidate = valid
})
if (!areaValidate) break
}
if (!areaValidate) return
for (let i = 0; i < areaFromRef.value?.length; i++) { if (valid) {
const ref = areaFromRef.value[i] loading.value = true
await ref.validate(async (valid) => {
areaValidate = valid
})
if (!areaValidate) break
}
if (!areaValidate) return
if (valid) { formData.value.center = {
loading.value = true lat: defaultDeliveryAddress.value.lat,
lng: defaultDeliveryAddress.value.lng,
formData.value.center = { }
lat: defaultDeliveryAddress.value.lat,
lng: defaultDeliveryAddress.value.lng
}
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
const param = deepClone(toRaw(formData.value)) const param = deepClone(toRaw(formData.value))
param.time_week = param.time_week.toString() param.time_week = param.time_week.toString()
setLocal(param).then(() => { setLocal(param)
loading.value = false .then(() => {
}).catch(() => { loading.value = false
loading.value = false })
}) .catch(() => {
}) loading.value = false
} })
}) })
}
})
} }
const back = () => { const back = () => {
router.push({ path: '/shop/order/delivery' }) router.push({ path: '/shop/order/delivery' })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.region-list { .region-list {
border: 1px solid var(--el-border-color-lighter); border: 1px solid var(--el-border-color-lighter);
z-index: 3; z-index: 3;
.region-item { .region-item {
border: 1px solid transparent; border: 1px solid transparent;
border-bottom-color: var(--el-border-color-lighter); border-bottom-color: var(--el-border-color-lighter);
} }
} }
#container :deep(div){ #container :deep(div) {
z-index: 2 !important; z-index: 2 !important;
} }
</style> </style>

260
admin/src/addon/shop/views/delivery/search.vue

@ -1,76 +1,116 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never"> <el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="router.push({ path: '/shop/order/delivery' })" /> <el-page-header
</el-card> :content="pageName"
<el-form :model="formData" label-width="150px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading"> :icon="ArrowLeft"
<el-card class="box-card !border-none" shadow="never"> @back="router.push({ path: '/shop/order/delivery' })"
<el-form-item :label="t('interfaceType')" prop="interface_type"> />
<div> </el-card>
<el-radio-group v-model="formData.interface_type"> <el-form
<el-radio :label="1" size="large">{{ t('kdn') }}</el-radio> :model="formData"
<!-- <el-radio :label="2" size="large">{{ t('kd100') }}</el-radio>--> label-width="150px"
</el-radio-group> ref="formRef"
<p class="text-[12px] text-[#b2b2b2]" v-if="formData.interface_type == 1"> :rules="formRules"
{{ t('promptTips1-1') }}<el-button class="button-size" type="primary" link @click="openEvent('https://www.kdniao.com')">https://www.kdniao.com</el-button> class="page-form"
</p> v-loading="loading"
<p class="text-[12px] text-[#b2b2b2]" v-if="formData.interface_type == 1"> >
{{ t('promptTips1-2') }} <el-card class="box-card !border-none" shadow="never">
</p> <el-form-item :label="t('interfaceType')" prop="interface_type">
<!-- <p class="text-[12px] text-[#b2b2b2]" v-if="formData.interface_type == 2">--> <div>
<!-- {{ t('promptTips2') }}<el-button class="button-size" type="primary" link @click="openEvent('https://www.kuaidi100.com')">https://www.kuaidi100.com</el-button>--> <el-radio-group v-model="formData.interface_type">
<!-- </p>--> <el-radio :label="1" size="large">{{ t('kdn') }}</el-radio>
</div> <!-- <el-radio :label="2" size="large">{{ t('kd100') }}</el-radio>-->
</el-form-item> </el-radio-group>
<div v-if="formData.interface_type == 1"> <p
<el-form-item :label="t('isPayEdition')" prop="kdn_is_pay" class="items-center"> class="text-[12px] text-[#b2b2b2]"
<el-radio-group v-model="formData.kdniao_is_pay"> v-if="formData.interface_type == 1"
<el-radio :label="1" size="large">{{ t('free') }}</el-radio> >
<el-radio :label="2" size="large">{{ t('pay') }}</el-radio> {{ t('promptTips1-1')
</el-radio-group> }}<el-button
</el-form-item> class="button-size"
type="primary"
<el-form-item label="EBusinessID" class="input-item"> link
<div> @click="openEvent('https://www.kdniao.com')"
<el-input v-model.trim="formData.kdniao_id" :placeholder="t('kdnEBusinessIDPlaceholder')" class="input-width" clearable /> >https://www.kdniao.com</el-button
<p class="text-[12px] text-[#b2b2b2]">{{ t('kdnEBusinessIDTips') }}</p> >
</div> </p>
</el-form-item> <p
class="text-[12px] text-[#b2b2b2]"
<el-form-item label="APPKEY" class="input-item"> v-if="formData.interface_type == 1"
<div> >
<el-input v-model.trim="formData.kdniao_app_key" clearable :placeholder="t('kdnAppKeyPlaceholder')" class="input-width" /> {{ t('promptTips1-2') }}
<p class="text-[12px] text-[#b2b2b2]">{{ t('kdnAppKeyTips') }}</p> </p>
</div> <!-- <p class="text-[12px] text-[#b2b2b2]" v-if="formData.interface_type == 2">-->
</el-form-item> <!-- {{ t('promptTips2') }}<el-button class="button-size" type="primary" link @click="openEvent('https://www.kuaidi100.com')">https://www.kuaidi100.com</el-button>-->
<!-- </p>-->
</div> </div>
</el-form-item>
<!-- <div v-if="formData.interface_type == 2">--> <div v-if="formData.interface_type == 1">
<!-- <el-form-item label="APPKEY" class="input-item">--> <el-form-item
<!-- <div>--> :label="t('isPayEdition')"
<!-- <el-input v-model.trim="formData.kd100_app_key" clearable :placeholder="t('kd100AppKeyPlaceholder')" class="input-width" />--> prop="kdn_is_pay"
<!-- <p class="text-[12px] text-[#b2b2b2]">{{ t('kd100AppKeyTips') }}</p>--> class="items-center"
<!-- </div>--> >
<!-- </el-form-item>--> <el-radio-group v-model="formData.kdniao_is_pay">
<el-radio :label="1" size="large">{{ t('free') }}</el-radio>
<!-- <el-form-item label="CUSTOMER" class="input-item">--> <el-radio :label="2" size="large">{{ t('pay') }}</el-radio>
<!-- <div>--> </el-radio-group>
<!-- <el-input v-model.trim="formData.kd100_customer" :placeholder="t('kd100CustomerPlaceholder')" class="input-width" clearable />--> </el-form-item>
<!-- <p class="text-[12px] text-[#b2b2b2]">{{ t('kd100CustomerTips') }}</p>-->
<!-- </div>--> <el-form-item label="EBusinessID" class="input-item">
<!-- </el-form-item>--> <div>
<!-- </div>--> <el-input
v-model.trim="formData.kdniao_id"
</el-card> :placeholder="t('kdnEBusinessIDPlaceholder')"
</el-form> class="input-width"
clearable
<div class="fixed-footer-wrap"> />
<div class="fixed-footer"> <p class="text-[12px] text-[#b2b2b2]">
<el-button type="primary" :loading="loading" @click="save(formRef)">{{ t('save') }}</el-button> {{ t('kdnEBusinessIDTips') }}
</div> </p>
</div> </div>
</div> </el-form-item>
<el-form-item label="APPKEY" class="input-item">
<div>
<el-input
v-model.trim="formData.kdniao_app_key"
clearable
:placeholder="t('kdnAppKeyPlaceholder')"
class="input-width"
/>
<p class="text-[12px] text-[#b2b2b2]">{{ t('kdnAppKeyTips') }}</p>
</div>
</el-form-item>
</div>
<!-- <div v-if="formData.interface_type == 2">-->
<!-- <el-form-item label="APPKEY" class="input-item">-->
<!-- <div>-->
<!-- <el-input v-model.trim="formData.kd100_app_key" clearable :placeholder="t('kd100AppKeyPlaceholder')" class="input-width" />-->
<!-- <p class="text-[12px] text-[#b2b2b2]">{{ t('kd100AppKeyTips') }}</p>-->
<!-- </div>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="CUSTOMER" class="input-item">-->
<!-- <div>-->
<!-- <el-input v-model.trim="formData.kd100_customer" :placeholder="t('kd100CustomerPlaceholder')" class="input-width" clearable />-->
<!-- <p class="text-[12px] text-[#b2b2b2]">{{ t('kd100CustomerTips') }}</p>-->
<!-- </div>-->
<!-- </el-form-item>-->
<!-- </div>-->
</el-card>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" :loading="loading" @click="save(formRef)">{{
t('save')
}}</el-button>
</div>
</div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -87,72 +127,72 @@ const pageName = route.meta.title
const loading = ref(true) const loading = ref(true)
interface formDataType { interface formDataType {
interface_type: number interface_type: number
kdniao_id: string kdniao_id: string
kdniao_app_key: string kdniao_app_key: string
kdniao_is_pay: number kdniao_is_pay: number
kd100_app_key: string kd100_app_key: string
kd100_customer: string kd100_customer: string
} }
const formData = reactive<formDataType|any>({ const formData = reactive<formDataType | any>({
interface_type: 1, interface_type: 1,
kdniao_id: '', kdniao_id: '',
kdniao_app_key: '', kdniao_app_key: '',
kdniao_is_pay: 1, kdniao_is_pay: 1,
kd100_app_key: '', kd100_app_key: '',
kd100_customer: '' kd100_customer: '',
}) })
const setFormData = async () => { const setFormData = async () => {
const data = await (await getDeliverySearch()).data const data = await (await getDeliverySearch()).data
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
loading.value = false loading.value = false
} }
setFormData() setFormData()
const openEvent = (url:any) => { const openEvent = (url: any) => {
window.open(url, '_blank') window.open(url, '_blank')
} }
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
// //
const formRules = reactive<FormRules>({ const formRules = reactive<FormRules>({})
})
/** /**
* 保存 * 保存
*/ */
const save = async (formEl: FormInstance | undefined) => { const save = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
setDeliverySearch(formData).then(() => { setDeliverySearch(formData)
loading.value = false .then(() => {
}).catch(() => { loading.value = false
loading.value = false })
}) .catch(() => {
} loading.value = false
}) })
}
})
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.input-item { .input-item {
margin-bottom: 10px !important margin-bottom: 10px !important;
} }
.button-size { .button-size {
font-size: 12px !important; font-size: 12px !important;
} }
.el-radio.el-radio--large { .el-radio.el-radio--large {
height: auto !important height: auto !important;
} }
</style> </style>

228
admin/src/addon/shop/views/delivery/staff.vue

@ -1,57 +1,98 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<div class="detail-head !m-0"> <div class="detail-head !m-0">
<div class="left" @click="router.push('/shop/order/delivery')"> <div class="left" @click="router.push('/shop/order/delivery')">
<span class="iconfont iconxiangzuojiantou !text-xs"></span> <span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span> <span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span>
</div> </div>
<span class="adorn">|</span> <span class="adorn">|</span>
<span class="right">{{ pageName }}</span> <span class="right">{{ pageName }}</span>
</div> </div>
<el-button type="primary" @click="addEvent"> <el-button type="primary" @click="addEvent">
{{ t('addDeliveryPersonnel') }} {{ t('addDeliveryPersonnel') }}
</el-button> </el-button>
</div> </div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> <el-card
<el-form :inline="true" :model="tableData.searchParam" ref="searchFormRef"> class="box-card !border-none my-[10px] table-search-wrap"
<el-form-item :label="t('deliverName')" prop="deliver_name"> shadow="never"
<el-input v-model.trim="tableData.searchParam.deliver_name" :placeholder="t('deliverNamePlaceholder')" /> >
</el-form-item> <el-form
<el-form-item :label="t('deliverMobile')" prop="deliver_mobile"> :inline="true"
<el-input v-model.trim="tableData.searchParam.deliver_mobile" :placeholder="t('deliverMobilePlaceholder')" /> :model="tableData.searchParam"
</el-form-item> ref="searchFormRef"
<el-form-item> >
<el-button type="primary" @click="getShopDeliveryFn()">{{ t('search') }}</el-button> <el-form-item :label="t('deliverName')" prop="deliver_name">
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> <el-input
</el-form-item> v-model.trim="tableData.searchParam.deliver_name"
</el-form> :placeholder="t('deliverNamePlaceholder')"
</el-card> />
<div class="mt-[10px]"> </el-form-item>
<el-table :data="tableData.data" ref="tableRef" size="large" v-loading="tableData.loading"> <el-form-item :label="t('deliverMobile')" prop="deliver_mobile">
<template #empty> <el-input
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span> v-model.trim="tableData.searchParam.deliver_mobile"
</template> :placeholder="t('deliverMobilePlaceholder')"
<el-table-column prop="deliver_name" :label="t('deliverName')" /> />
<el-table-column prop="deliver_mobile" :label="t('deliverMobile')" /> </el-form-item>
<el-table-column :label="t('operation')" fixed="right" align="right" width="120"> <el-form-item>
<template #default="{ row }"> <el-button type="primary" @click="getShopDeliveryFn()">{{
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> t('search')
<el-button type="primary" link @click="deleteEvent(row.deliver_id)">{{ t('delete') }}</el-button> }}</el-button>
</template> <el-button @click="resetForm(searchFormRef)">{{
</el-table-column> t('reset')
}}</el-button>
</el-table> </el-form-item>
<div class="mt-[16px] flex justify-end"> </el-form>
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.limit" </el-card>
layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" <div class="mt-[10px]">
@size-change="getShopDeliveryFn()" @current-change="getShopDeliveryFn" /> <el-table
</div> :data="tableData.data"
</div> ref="tableRef"
</el-card> size="large"
<delivery-personnel-edit ref="editCategoryDialog" @complete="getShopDeliveryFn" /> v-loading="tableData.loading"
</div> >
<template #empty>
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="deliver_name" :label="t('deliverName')" />
<el-table-column prop="deliver_mobile" :label="t('deliverMobile')" />
<el-table-column
:label="t('operation')"
fixed="right"
align="right"
width="120"
>
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button
type="primary"
link
@click="deleteEvent(row.deliver_id)"
>{{ t('delete') }}</el-button
>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="tableData.page"
v-model:page-size="tableData.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="tableData.total"
@size-change="getShopDeliveryFn()"
@current-change="getShopDeliveryFn"
/>
</div>
</div>
</el-card>
<delivery-personnel-edit
ref="editCategoryDialog"
@complete="getShopDeliveryFn"
/>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
@ -65,34 +106,36 @@ const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title const pageName = route.meta.title
const tableData = reactive({ const tableData = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
total: 0, total: 0,
loading: false, loading: false,
data: [], data: [],
searchParam: { searchParam: {
deliver_name: '', deliver_name: '',
deliver_mobile: '' deliver_mobile: '',
} },
}) })
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()
/** /**
* 获取配送员列表 * 获取配送员列表
*/ */
const getShopDeliveryFn = (page: number = 1) => { const getShopDeliveryFn = (page: number = 1) => {
tableData.loading = true tableData.loading = true
tableData.page = page tableData.page = page
getShopDelivery({ getShopDelivery({
page: tableData.page, page: tableData.page,
limit: tableData.limit, limit: tableData.limit,
...tableData.searchParam ...tableData.searchParam,
}).then(res => { })
tableData.loading = false .then((res) => {
tableData.data = res.data.data tableData.loading = false
tableData.total = res.data.total tableData.data = res.data.data
}).catch(() => { tableData.total = res.data.total
tableData.loading = false })
.catch(() => {
tableData.loading = false
}) })
} }
getShopDeliveryFn() getShopDeliveryFn()
@ -102,8 +145,8 @@ const editCategoryDialog: Record<string, any> | null = ref(null)
* 添加配送员 * 添加配送员
*/ */
const addEvent = () => { const addEvent = () => {
editCategoryDialog.value.setFormData() editCategoryDialog.value.setFormData()
editCategoryDialog.value.showDialog = true editCategoryDialog.value.showDialog = true
} }
/** /**
@ -111,30 +154,29 @@ const addEvent = () => {
* @param data * @param data
*/ */
const editEvent = (data: any) => { const editEvent = (data: any) => {
editCategoryDialog.value.setFormData(data) editCategoryDialog.value.setFormData(data)
editCategoryDialog.value.showDialog = true editCategoryDialog.value.showDialog = true
} }
/** /**
* 删除配送员 * 删除配送员
*/ */
const deleteEvent = (id: number) => { const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('deliverDeleteTips'), t('warning'), ElMessageBox.confirm(t('deliverDeleteTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning' }).then(() => {
} deleteShopDeliver(id)
).then(() => { .then(() => {
deleteShopDeliver(id).then(() => { getShopDeliveryFn()
getShopDeliveryFn() })
}).catch(() => { .catch(() => {})
}) })
})
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
getShopDeliveryFn() getShopDeliveryFn()
} }
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

288
admin/src/addon/shop/views/delivery/store.vue

@ -1,77 +1,129 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<div class="detail-head !m-0"> <div class="detail-head !m-0">
<div class="left" @click="router.push('/shop/order/delivery')"> <div class="left" @click="router.push('/shop/order/delivery')">
<span class="iconfont iconxiangzuojiantou !text-xs"></span> <span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span> <span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
</div>
<el-button type="primary" @click="addEvent">
{{ t('addStore') }}
</el-button>
</div>
<el-card
class="box-card !border-none my-[10px] table-search-wrap"
shadow="never"
>
<el-form
:inline="true"
:model="storeTable.searchParam"
ref="searchFormRef"
>
<el-form-item :label="t('storeName')" prop="store_name">
<el-input
v-model.trim="storeTable.searchParam.store_name"
:placeholder="t('storeNamePlaceholder')"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadStoreList()">{{
t('search')
}}</el-button>
<el-button @click="resetForm(searchFormRef)">{{
t('reset')
}}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table
:data="storeTable.data"
size="large"
v-loading="storeTable.loading"
>
<template #empty>
<span>{{ !storeTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column :label="t('storeInfo')" min-width="170" align="left">
<template #default="{ row }">
<div class="h-[50px] flex items-center">
<el-image
class="w-[50px] h-[50px]"
:src="img(row.store_logo)"
fit="contain"
>
<template #error>
<div class="image-slot">
<img
class="w-[50px] h-[50px]"
src="@/addon/shop/assets/store_default.png"
/>
</div> </div>
<span class="adorn">|</span> </template>
<span class="right">{{ pageName }}</span> </el-image>
</div> <p class="ml-[10px] text-[14px]">{{ row.store_name }}</p>
<el-button type="primary" @click="addEvent"> </div>
{{ t('addStore') }} </template>
</el-button> </el-table-column>
</div> <el-table-column
prop="store_mobile"
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> :label="t('storeMobile')"
<el-form :inline="true" :model="storeTable.searchParam" ref="searchFormRef"> min-width="120"
<el-form-item :label="t('storeName')" prop="store_name"> />
<el-input v-model.trim="storeTable.searchParam.store_name" :placeholder="t('storeNamePlaceholder')" /> <el-table-column
</el-form-item> prop="full_address"
<el-form-item> :label="t('fullAddress')"
<el-button type="primary" @click="loadStoreList()">{{ t('search') }}</el-button> min-width="180"
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> />
</el-form-item> <el-table-column
</el-form> prop="trade_time"
</el-card> :label="t('tradeTime')"
min-width="120"
<div class="mt-[10px]"> />
<el-table :data="storeTable.data" size="large" v-loading="storeTable.loading"> <el-table-column :label="t('createTime')" min-width="120">
<template #empty> <template #default="{ row }">
<span>{{ !storeTable.loading ? t('emptyData') : '' }}</span> {{ row.create_time || '' }}
</template> </template>
<el-table-column :label="t('storeInfo')" min-width="170" align="left"> </el-table-column>
<template #default="{ row }">
<div class="h-[50px] flex items-center"> <el-table-column
<el-image class="w-[50px] h-[50px] " :src="img(row.store_logo)" fit="contain"> :label="t('operation')"
<template #error> fixed="right"
<div class="image-slot"> align="right"
<img class="w-[50px] h-[50px]" src="@/addon/shop/assets/store_default.png" /> min-width="120"
</div> >
</template> <template #default="{ row }">
</el-image> <el-button type="primary" link @click="editEvent(row)">{{
<p class="ml-[10px] text-[14px]">{{ row.store_name }}</p> t('edit')
</div> }}</el-button>
</template> <el-button
</el-table-column> type="primary"
<el-table-column prop="store_mobile" :label="t('storeMobile')" min-width="120" /> link
<el-table-column prop="full_address" :label="t('fullAddress')" min-width="180" /> @click="deleteEvent(row.store_id)"
<el-table-column prop="trade_time" :label="t('tradeTime')" min-width="120" /> >{{ t('delete') }}</el-button
<el-table-column :label="t('createTime')" min-width="120"> >
<template #default="{ row }"> </template>
{{ row.create_time || '' }} </el-table-column>
</template> </el-table>
</el-table-column> <div class="mt-[16px] flex justify-end">
<el-pagination
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120"> v-model:current-page="storeTable.page"
<template #default="{ row }"> v-model:page-size="storeTable.limit"
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> layout="total, sizes, prev, pager, next, jumper"
<el-button type="primary" link @click="deleteEvent(row.store_id)">{{ t('delete') }}</el-button> :total="storeTable.total"
</template> @size-change="loadStoreList()"
</el-table-column> @current-change="loadStoreList"
/>
</el-table> </div>
<div class="mt-[16px] flex justify-end"> </div>
<el-pagination v-model:current-page="storeTable.page" v-model:page-size="storeTable.limit" </el-card>
layout="total, sizes, prev, pager, next, jumper" :total="storeTable.total" </div>
@size-change="loadStoreList()" @current-change="loadStoreList" />
</div>
</div>
</el-card>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -81,21 +133,21 @@ import { getStoreList, deleteStore } from '@/addon/shop/api/delivery'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus' import { ElMessageBox, FormInstance } from 'element-plus'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { setTablePageStorage,getTablePageStorage } from "@/utils/common"; import { setTablePageStorage, getTablePageStorage } from '@/utils/common'
const route = useRoute() const route = useRoute()
const pageName = route.meta.title const pageName = route.meta.title
const storeTable = reactive({ const storeTable = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
total: 0, total: 0,
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
store_name: '', store_name: '',
create_time: '' create_time: '',
} },
}) })
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()
@ -104,23 +156,29 @@ const searchFormRef = ref<FormInstance>()
* 获取自提门店列表 * 获取自提门店列表
*/ */
const loadStoreList = (page: number = 1) => { const loadStoreList = (page: number = 1) => {
storeTable.loading = true storeTable.loading = true
storeTable.page = page storeTable.page = page
getStoreList({ getStoreList({
page: storeTable.page, page: storeTable.page,
limit: storeTable.limit, limit: storeTable.limit,
...storeTable.searchParam ...storeTable.searchParam,
}).then(res => { })
storeTable.loading = false .then((res) => {
storeTable.data = res.data.data storeTable.loading = false
storeTable.total = res.data.total storeTable.data = res.data.data
setTablePageStorage(storeTable.page, storeTable.limit, storeTable.searchParam); storeTable.total = res.data.total
}).catch(() => { setTablePageStorage(
storeTable.loading = false storeTable.page,
storeTable.limit,
storeTable.searchParam
)
})
.catch(() => {
storeTable.loading = false
}) })
} }
loadStoreList(getTablePageStorage(storeTable.searchParam).page); loadStoreList(getTablePageStorage(storeTable.searchParam).page)
const router = useRouter() const router = useRouter()
@ -128,7 +186,7 @@ const router = useRouter()
* 添加自提门店 * 添加自提门店
*/ */
const addEvent = () => { const addEvent = () => {
router.push('/shop/order/delivery/store/edit') router.push('/shop/order/delivery/store/edit')
} }
/** /**
@ -136,33 +194,31 @@ const addEvent = () => {
* @param data * @param data
*/ */
const editEvent = (data: any) => { const editEvent = (data: any) => {
router.push('/shop/order/delivery/store/edit?id=' + data.store_id) router.push('/shop/order/delivery/store/edit?id=' + data.store_id)
} }
/** /**
* 删除自提门店 * 删除自提门店
*/ */
const deleteEvent = (id: number) => { const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('storeDeleteTips'), t('warning'), ElMessageBox.confirm(t('storeDeleteTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning' }).then(() => {
} deleteStore(id)
).then(() => { .then(() => {
deleteStore(id).then(() => { loadStoreList()
loadStoreList() })
}).catch(() => { .catch(() => {})
}) })
})
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
loadStoreList() loadStoreList()
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

688
admin/src/addon/shop/views/delivery/store_edit.vue

@ -1,63 +1,136 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never"> <el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="id ? t('updateStore') : t('addStore')" :icon="ArrowLeft" @back="back" /> <el-page-header
</el-card> :content="id ? t('updateStore') : t('addStore')"
<el-card class="box-card !border-none" shadow="never" v-loading="loading"> :icon="ArrowLeft"
<el-form :model="formData" label-width="140px" ref="formRef" :rules="formRules" class="page-form"> @back="back"
<el-form-item :label="t('storeName')" prop="store_name"> />
<el-input v-model.trim="formData.store_name" clearable :placeholder="t('storeNamePlaceholder')" </el-card>
class="input-width" /> <el-card class="box-card !border-none" shadow="never" v-loading="loading">
</el-form-item> <el-form
<el-form-item :label="t('storeDesc')"> :model="formData"
<el-input v-model.trim="formData.store_desc" type="textarea" rows="4" clearable label-width="140px"
:placeholder="t('storeDescPlaceholder')" class="input-width" /> ref="formRef"
</el-form-item> :rules="formRules"
<el-form-item :label="t('storeLogo')"> class="page-form"
<upload-image v-model="formData.store_logo" /> >
</el-form-item> <el-form-item :label="t('storeName')" prop="store_name">
<el-form-item :label="t('storeMobile')" prop="store_mobile"> <el-input
<el-input v-model.trim="formData.store_mobile" clearable :placeholder="t('storeMobilePlaceholder')" v-model.trim="formData.store_name"
class="input-width" @keyup="filterNumber($event)" clearable
@blur="formData.store_mobile = $event.target.value" /> :placeholder="t('storeNamePlaceholder')"
</el-form-item> class="input-width"
<el-form-item :label="t('tradeTime')" prop="trade_time"> />
<div> </el-form-item>
<el-input v-model.trim="formData.trade_time" clearable :placeholder="t('tradeTimePlaceholder')" <el-form-item :label="t('storeDesc')">
class="input-width" /> <el-input
<p class="text-[12px] text-[#999]">{{ t('tradeTimeTips') }}</p> v-model.trim="formData.store_desc"
</div> type="textarea"
</el-form-item> rows="4"
<el-form-item :label="t('storeAddress')" prop="address_area"> clearable
<el-select v-model="formData.province_id" value-key="id" clearable class="w-[200px]" ref="provinceRef"> :placeholder="t('storeDescPlaceholder')"
<el-option :label="t('provincePlaceholder')" :value="0"/> class="input-width"
<el-option v-for="(item, index) in areaList.province" :key="index" :label="item.name" :value="item.id"/> />
</el-select> </el-form-item>
<el-select v-model="formData.city_id" value-key="id" clearable class="w-[200px] ml-3" ref="cityRef"> <el-form-item :label="t('storeLogo')">
<el-option :label="t('cityPlaceholder')" :value="0"/> <upload-image v-model="formData.store_logo" />
<el-option v-for="(item, index) in areaList.city " :key="index" :label="item.name" :value="item.id"/> </el-form-item>
</el-select> <el-form-item :label="t('storeMobile')" prop="store_mobile">
<el-select v-model="formData.district_id" value-key="id" clearable class="w-[200px] ml-3" ref="districtRef"> <el-input
<el-option :label="t('districtPlaceholder')" :value="0"/> v-model.trim="formData.store_mobile"
<el-option v-for="(item, index) in areaList.district " :key="index" :label="item.name" :value="item.id"/> clearable
</el-select> :placeholder="t('storeMobilePlaceholder')"
</el-form-item> class="input-width"
<el-form-item prop="address"> @keyup="filterNumber($event)"
<el-input v-model.trim="formData.address" clearable :placeholder="t('addressPlaceholder')" class="input-width"/> @blur="formData.store_mobile = $event.target.value"
</el-form-item> />
</el-form-item>
<el-form-item> <el-form-item :label="t('tradeTime')" prop="trade_time">
<div id="container" class="w-[800px] h-[520px] relative" v-loading="mapLoading"></div> <div>
</el-form-item> <el-input
</el-form> v-model.trim="formData.trade_time"
</el-card> clearable
<div class="fixed-footer-wrap"> :placeholder="t('tradeTimePlaceholder')"
<div class="fixed-footer !z-[9999]"> class="input-width"
<el-button type="primary" @click="onSave(formRef)">{{ t('save') }}</el-button> />
<el-button @click="back()">{{ t('cancel') }}</el-button> <p class="text-[12px] text-[#999]">{{ t('tradeTimeTips') }}</p>
</div> </div>
</div> </el-form-item>
<el-form-item :label="t('storeAddress')" prop="address_area">
<el-select
v-model="formData.province_id"
value-key="id"
clearable
class="w-[200px]"
ref="provinceRef"
>
<el-option :label="t('provincePlaceholder')" :value="0" />
<el-option
v-for="(item, index) in areaList.province"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
<el-select
v-model="formData.city_id"
value-key="id"
clearable
class="w-[200px] ml-3"
ref="cityRef"
>
<el-option :label="t('cityPlaceholder')" :value="0" />
<el-option
v-for="(item, index) in areaList.city"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
<el-select
v-model="formData.district_id"
value-key="id"
clearable
class="w-[200px] ml-3"
ref="districtRef"
>
<el-option :label="t('districtPlaceholder')" :value="0" />
<el-option
v-for="(item, index) in areaList.district"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item prop="address">
<el-input
v-model.trim="formData.address"
clearable
:placeholder="t('addressPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item>
<div
id="container"
class="w-[800px] h-[520px] relative"
v-loading="mapLoading"
></div>
</el-form-item>
</el-form>
</el-card>
<div class="fixed-footer-wrap">
<div class="fixed-footer !z-[9999]">
<el-button type="primary" @click="onSave(formRef)">{{
t('save')
}}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div> </div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -74,15 +147,15 @@ const route = useRoute()
const id: number = parseInt(route.query.id as string) const id: number = parseInt(route.query.id as string)
const loading = ref(false) const loading = ref(false)
const pageName = route.meta.title const pageName = route.meta.title
interface areaType{ interface areaType {
province: any[], province: any[]
city: any[], city: any[]
district: any[] district: any[]
} }
const areaList = reactive<areaType>({ const areaList = reactive<areaType>({
province: [], province: [],
city: [], city: [],
district: [] district: [],
}) })
const provinceRef = ref() const provinceRef = ref()
const cityRef = ref() const cityRef = ref()
@ -91,24 +164,26 @@ const districtRef = ref()
/** /**
* 获取省 * 获取省
*/ */
getAreaListByPid(0).then(res => { getAreaListByPid(0).then((res) => {
areaList.province = res.data areaList.province = res.data
}) })
let mapKey: string = '' let mapKey: string = ''
onMounted(() => { onMounted(() => {
const mapScript = document.createElement('script') const mapScript = document.createElement('script')
getMap().then(res => { getMap().then((res) => {
mapKey = res.data.key mapKey = res.data.key
mapScript.type = 'text/javascript' mapScript.type = 'text/javascript'
mapScript.src = 'https://map.qq.com/api/gljs?libraries=tools,service&v=1.exp&key=' + res.data.key mapScript.src =
document.body.appendChild(mapScript) 'https://map.qq.com/api/gljs?libraries=tools,service&v=1.exp&key=' +
}) res.data.key
mapScript.onload = () => { document.body.appendChild(mapScript)
setTimeout(() => { })
initMap() mapScript.onload = () => {
}, 500) setTimeout(() => {
} initMap()
}, 500)
}
}) })
/** /**
@ -118,56 +193,58 @@ let map: any
let marker: any let marker: any
const mapLoading = ref(true) const mapLoading = ref(true)
const initMap = () => { const initMap = () => {
const TMap = (window as any).TMap const TMap = (window as any).TMap
const LatLng = TMap.LatLng const LatLng = TMap.LatLng
const center = new LatLng(formData.latitude, formData.longitude) const center = new LatLng(formData.latitude, formData.longitude)
map = new TMap.Map('container', { map = new TMap.Map('container', {
center, center,
zoom: 14 zoom: 14,
}) })
map.on('tilesloaded', () => { map.on('tilesloaded', () => {
mapLoading.value = false mapLoading.value = false
})
marker = createMarker(map)
map.on('click', (evt: any) => {
map.setCenter(evt.latLng)
marker.updateGeometries({
id: 'center',
position: evt.latLng,
}) })
latLngChange(evt.latLng.lat, evt.latLng.lng)
})
marker = createMarker(map) latLngChange(center.lat, center.lng)
map.on('click', (evt: any) => {
map.setCenter(evt.latLng)
marker.updateGeometries({
id: 'center',
position: evt.latLng
})
latLngChange(evt.latLng.lat, evt.latLng.lng)
})
latLngChange(center.lat, center.lng)
} }
const storeArea = reactive({ const storeArea = reactive({
province_id: 0, province_id: 0,
city_id: 0, city_id: 0,
district_id: 0 district_id: 0,
}) })
const latLngChange = (lat: number, lng: number) => { const latLngChange = (lat: number, lng: number) => {
latLngToAddress({ mapKey, lat, lng }).then(({ message, result }) => { latLngToAddress({ mapKey, lat, lng })
if (message == 'query ok' || message == 'Success') { .then(({ message, result }) => {
formData.latitude = result.location.lat if (message == 'query ok' || message == 'Success') {
formData.longitude = result.location.lng formData.latitude = result.location.lat
formData.address = result.formatted_addresses.recommend formData.longitude = result.location.lng
formData.address = result.formatted_addresses.recommend
getAreaByCode(result.ad_info.adcode).then(({ data }) => {
storeArea.province_id = data.province ? data.province.id : 0 getAreaByCode(result.ad_info.adcode).then(({ data }) => {
storeArea.city_id = data.city ? data.city.id : 0 storeArea.province_id = data.province ? data.province.id : 0
storeArea.district_id = data.district ? data.district.id : 0 storeArea.city_id = data.city ? data.city.id : 0
}) storeArea.district_id = data.district ? data.district.id : 0
} else { })
console.error(message, result) } else {
} console.error(message, result)
}).catch(err => { }
console.log(err) })
.catch((err) => {
console.log(err)
}) })
} }
@ -175,34 +252,34 @@ const latLngChange = (lat: number, lng: number) => {
* 表单数据 * 表单数据
*/ */
const initialFormData = { const initialFormData = {
store_id: 0, store_id: 0,
store_name: '', store_name: '',
store_desc: '', store_desc: '',
store_logo: '', store_logo: '',
store_mobile: '', store_mobile: '',
province_id: 0, province_id: 0,
province_name: '', province_name: '',
city_id: 0, city_id: 0,
city_name: '', city_name: '',
district_id: 0, district_id: 0,
district_name: '', district_name: '',
address: '', address: '',
full_address: '', full_address: '',
longitude: 116.397190, longitude: 116.39719,
latitude: 39.908626, latitude: 39.908626,
trade_time: '' trade_time: '',
} }
const formData: Record<string, any> = reactive({ ...initialFormData }) const formData: Record<string, any> = reactive({ ...initialFormData })
const setFormData = async (id: number = 0) => { const setFormData = async (id: number = 0) => {
loading.value = true loading.value = true
Object.assign(formData, initialFormData) Object.assign(formData, initialFormData)
const data = await (await getStoreInfo(id)).data const data = await (await getStoreInfo(id)).data
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
loading.value = false loading.value = false
} }
if (id) setFormData(id) if (id) setFormData(id)
@ -210,198 +287,229 @@ const formRef = ref<FormInstance>()
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
store_name: [ store_name: [
{ required: true, message: t('storeNamePlaceholder'), trigger: 'blur' } { required: true, message: t('storeNamePlaceholder'), trigger: 'blur' },
], ],
store_logo: [ store_logo: [
{ required: true, message: t('storeLogoPlaceholder'), trigger: 'blur' } { required: true, message: t('storeLogoPlaceholder'), trigger: 'blur' },
], ],
store_mobile: [ store_mobile: [
{ required: true, message: t('storeMobilePlaceholder'), trigger: 'blur' } { required: true, message: t('storeMobilePlaceholder'), trigger: 'blur' },
], ],
trade_time: [ trade_time: [
{ required: true, message: t('tradeTimePlaceholder'), trigger: 'blur' } { required: true, message: t('tradeTimePlaceholder'), trigger: 'blur' },
], ],
address_area: [ address_area: [
{ {
validator: (rule: any, value: any, callback: any) => { validator: (rule: any, value: any, callback: any) => {
if (!formData.province_id) { if (!formData.province_id) {
callback(new Error(t('provincePlaceholder'))) callback(new Error(t('provincePlaceholder')))
} }
if (!formData.city_id) { if (!formData.city_id) {
callback(new Error(t('cityPlaceholder'))) callback(new Error(t('cityPlaceholder')))
} }
if (areaList.district.length && !formData.district_id) { if (areaList.district.length && !formData.district_id) {
callback(new Error(t('districtPlaceholder'))) callback(new Error(t('districtPlaceholder')))
} }
callback() callback()
} },
} },
], ],
address: [ address: [
{ required: true, message: t('addressPlaceholder'), trigger: 'blur' } { required: true, message: t('addressPlaceholder'), trigger: 'blur' },
] ],
} }
}) })
/** /**
* 获取市 * 获取市
*/ */
watch(() => formData.province_id, (nval) => { watch(
() => formData.province_id,
(nval) => {
if (nval) { if (nval) {
getAreaListByPid(formData.province_id).then(res => { getAreaListByPid(formData.province_id).then((res) => {
areaList.city = res.data areaList.city = res.data
const cityId = formData.city_id const cityId = formData.city_id
if (cityId) { if (cityId) {
let isExist = false let isExist = false
for (let i = 0; i < res.data.length; i++) { for (let i = 0; i < res.data.length; i++) {
if (cityId == res.data[i].id) { if (cityId == res.data[i].id) {
isExist = true isExist = true
break break
}
}
if (isExist) {
formData.city_id = cityId
return
}
} }
formData.city_id = 0 }
areaChange() if (isExist) {
}) formData.city_id = cityId
} else { return
}
}
formData.city_id = 0 formData.city_id = 0
areaChange()
})
} else {
formData.city_id = 0
} }
}) }
)
/** /**
* 获取区 * 获取区
*/ */
watch(() => formData.city_id, (nval) => { watch(
() => formData.city_id,
(nval) => {
if (nval) { if (nval) {
getAreaListByPid(formData.city_id).then(res => { getAreaListByPid(formData.city_id).then((res) => {
areaList.district = res.data areaList.district = res.data
const districtId = formData.district_id const districtId = formData.district_id
if (districtId) { if (districtId) {
let isExist = false let isExist = false
for (let i = 0; i < res.data.length; i++) { for (let i = 0; i < res.data.length; i++) {
if (districtId == res.data[i].id) { if (districtId == res.data[i].id) {
isExist = true isExist = true
break break
}
}
if (isExist) {
formData.district_id = districtId
return
}
} }
areaChange() }
formData.district_id = 0 if (isExist) {
}) formData.district_id = districtId
} else { return
}
}
areaChange()
formData.district_id = 0 formData.district_id = 0
})
} else {
formData.district_id = 0
} }
}) }
)
watch(() => formData.district_id, (nval) => { watch(
() => formData.district_id,
(nval) => {
if (nval) { if (nval) {
areaChange() areaChange()
} }
}) }
)
const areaChange = debounce(() => { const areaChange = debounce(() => {
setTimeout(() => { setTimeout(() => {
const address = [ const address = [
formData.province_id ? provinceRef.value.states.selectedLabel : '', formData.province_id ? provinceRef.value.states.selectedLabel : '',
formData.city_id ? cityRef.value.states.selectedLabel : '', formData.city_id ? cityRef.value.states.selectedLabel : '',
formData.district_id ? districtRef.value.states.selectedLabel : '' formData.district_id ? districtRef.value.states.selectedLabel : '',
] ]
addressToLatLng({ mapKey, address: address.join('') }).then(({ message, result }) => { addressToLatLng({ mapKey, address: address.join('') }).then(
if (message == 'Success' || message == 'query ok') { ({ message, result }) => {
const latLng = new (window as any).TMap.LatLng(result.location.lat, result.location.lng) if (message == 'Success' || message == 'query ok') {
map.setCenter(latLng) const latLng = new (window as any).TMap.LatLng(
marker.updateGeometries({ result.location.lat,
id: 'center', result.location.lng
position: latLng )
}) map.setCenter(latLng)
formData.latitude = result.location.lat marker.updateGeometries({
formData.longitude = result.location.lng id: 'center',
} else { position: latLng,
console.error(message, result) })
} formData.latitude = result.location.lat
}) formData.longitude = result.location.lng
}, 500) } else {
console.error(message, result)
}
}
)
}, 500)
}, 500) }, 500)
/** /**
* 地图点选获取市 * 地图点选获取市
*/ */
watch(() => storeArea.province_id, (nval) => { watch(
() => storeArea.province_id,
(nval) => {
if (nval) { if (nval) {
getAreaListByPid(storeArea.province_id).then(res => { getAreaListByPid(storeArea.province_id).then((res) => {
areaList.city = res.data areaList.city = res.data
formData.province_id = storeArea.province_id formData.province_id = storeArea.province_id
formData.city_id = storeArea.city_id formData.city_id = storeArea.city_id
}) })
} }
}) }
)
/** /**
* 地图点选获取区 * 地图点选获取区
*/ */
watch(() => storeArea.city_id, (nval) => { watch(
() => storeArea.city_id,
(nval) => {
if (nval) { if (nval) {
getAreaListByPid(storeArea.city_id).then(res => { getAreaListByPid(storeArea.city_id).then((res) => {
areaList.district = res.data areaList.district = res.data
formData.city_id = storeArea.city_id formData.city_id = storeArea.city_id
formData.district_id = storeArea.district_id formData.district_id = storeArea.district_id
}) })
} }
}) }
)
/** /**
* 地图点选获取区 * 地图点选获取区
*/ */
watch(() => storeArea.district_id, (nval) => { watch(
() => storeArea.district_id,
(nval) => {
if (nval) { if (nval) {
formData.district_id = storeArea.district_id formData.district_id = storeArea.district_id
} }
}) }
)
const onSave = async (formEl: FormInstance | undefined) => { const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
const data = formData const data = formData
formData.province_name = formData.province_id ? provinceRef.value.states.selectedLabel : '', ;(formData.province_name = formData.province_id
formData.city_name = formData.city_id ? cityRef.value.states.selectedLabel : '', ? provinceRef.value.states.selectedLabel
formData.district_name = formData.district_id ? districtRef.value.states.selectedLabel : '' : ''),
const address = [ (formData.city_name = formData.city_id
data.province_id ? provinceRef.value.states.selectedLabel : '', ? cityRef.value.states.selectedLabel
data.city_id ? cityRef.value.states.selectedLabel : '', : ''),
data.district_id ? districtRef.value.states.selectedLabel : '', (formData.district_name = formData.district_id
data.address ? districtRef.value.states.selectedLabel
] : '')
data.full_address = address.join('') const address = [
data.province_id ? provinceRef.value.states.selectedLabel : '',
const save = id ? editStore : addStore data.city_id ? cityRef.value.states.selectedLabel : '',
save(data).then(res => { data.district_id ? districtRef.value.states.selectedLabel : '',
loading.value = false data.address,
history.back() ]
}).catch(() => { data.full_address = address.join('')
loading.value = false
}) const save = id ? editStore : addStore
} save(data)
}) .then((res) => {
loading.value = false
history.back()
})
.catch(() => {
loading.value = false
})
}
})
} }
const back = () => { const back = () => {
history.back() history.back()
} }
</script> </script>

256
admin/src/addon/shop/views/delivery/template.vue

@ -1,84 +1,137 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<div class="detail-head !m-0">
<div class="left" @click="router.push('/shop/order/delivery')">
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
</div>
<el-button type="primary" @click="addEvent">
{{ t('addTemplate') }}
</el-button>
</div>
<div class="flex justify-between items-center"> <el-card
<div class="detail-head !m-0"> class="box-card !border-none my-[10px] table-search-wrap"
<div class="left" @click="router.push('/shop/order/delivery')"> shadow="never"
<span class="iconfont iconxiangzuojiantou !text-xs"></span> >
<span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span> <el-form
</div> :inline="true"
<span class="adorn">|</span> :model="templateTable.searchParam"
<span class="right">{{ pageName }}</span> ref="searchFormRef"
</div> >
<el-button type="primary" @click="addEvent"> <el-form-item :label="t('templateName')" prop="template_name">
{{ t('addTemplate') }} <el-input
</el-button> v-model.trim="templateTable.searchParam.template_name"
</div> :placeholder="t('templateNamePlaceholder')"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadTemplateList()">{{
t('search')
}}</el-button>
<el-button @click="resetForm(searchFormRef)">{{
t('reset')
}}</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> <div class="mt-[10px]">
<el-form :inline="true" :model="templateTable.searchParam" ref="searchFormRef"> <el-table
<el-form-item :label="t('templateName')" prop="template_name"> :data="templateTable.data"
<el-input v-model.trim="templateTable.searchParam.template_name" :placeholder="t('templateNamePlaceholder')" /> size="large"
</el-form-item> v-loading="templateTable.loading"
<el-form-item> >
<el-button type="primary" @click="loadTemplateList()">{{ t('search') }}</el-button> <template #empty>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> <span>{{ !templateTable.loading ? t('emptyData') : '' }}</span>
</el-form-item> </template>
</el-form> <el-table-column
</el-card> prop="template_name"
:label="t('templateName')"
<div class="mt-[10px]"> min-width="120"
<el-table :data="templateTable.data" size="large" v-loading="templateTable.loading"> />
<template #empty> <el-table-column
<span>{{ !templateTable.loading ? t('emptyData') : '' }}</span> prop="fee_type_name"
</template> :label="t('feeTypeName')"
<el-table-column prop="template_name" :label="t('templateName')" min-width="120" /> min-width="120"
<el-table-column prop="fee_type_name" :label="t('feeTypeName')" min-width="120" /> />
<el-table-column :label="t('freeShipping')" min-width="120" align="center"> <el-table-column
<template #default="{ row }"> :label="t('freeShipping')"
{{ row.is_free_shipping ? t('open') : t('close') }} min-width="120"
</template> align="center"
</el-table-column> >
<el-table-column prop="create_time" :label="t('createTime')" min-width="120" /> <template #default="{ row }">
<el-table-column :label="t('operation')" fixed="right" min-width="120" align="right"> {{ row.is_free_shipping ? t('open') : t('close') }}
<template #default="{ row }"> </template>
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> </el-table-column>
<el-button type="primary" link @click="deleteEvent(row.template_id)">{{ t('delete') }}</el-button> <el-table-column
</template> prop="create_time"
</el-table-column> :label="t('createTime')"
</el-table> min-width="120"
<div class="mt-[16px] flex justify-end"> />
<el-pagination v-model:current-page="templateTable.page" v-model:page-size="templateTable.limit" <el-table-column
layout="total, sizes, prev, pager, next, jumper" :total="templateTable.total" :label="t('operation')"
@size-change="loadTemplateList()" @current-change="loadTemplateList" /> fixed="right"
</div> min-width="120"
</div> align="right"
</el-card> >
</div> <template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button
type="primary"
link
@click="deleteEvent(row.template_id)"
>{{ t('delete') }}</el-button
>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="templateTable.page"
v-model:page-size="templateTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="templateTable.total"
@size-change="loadTemplateList()"
@current-change="loadTemplateList"
/>
</div>
</div>
</el-card>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getShippingTemplatePageList, deleteShippingTemplate } from '@/addon/shop/api/delivery' import {
getShippingTemplatePageList,
deleteShippingTemplate,
} from '@/addon/shop/api/delivery'
import { ElMessageBox, FormInstance } from 'element-plus' import { ElMessageBox, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { setTablePageStorage,getTablePageStorage } from "@/utils/common"; import { setTablePageStorage, getTablePageStorage } from '@/utils/common'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title const pageName = route.meta.title
const templateTable = reactive({ const templateTable = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
total: 0, total: 0,
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
template_name: '' template_name: '',
} },
}) })
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()
@ -87,29 +140,35 @@ const searchFormRef = ref<FormInstance>()
* 获取运费模板列表 * 获取运费模板列表
*/ */
const loadTemplateList = (page: number = 1) => { const loadTemplateList = (page: number = 1) => {
templateTable.loading = true templateTable.loading = true
templateTable.page = page templateTable.page = page
getShippingTemplatePageList({ getShippingTemplatePageList({
page: templateTable.page, page: templateTable.page,
limit: templateTable.limit, limit: templateTable.limit,
...templateTable.searchParam ...templateTable.searchParam,
}).then(res => { })
templateTable.loading = false .then((res) => {
templateTable.data = res.data.data templateTable.loading = false
templateTable.total = res.data.total templateTable.data = res.data.data
setTablePageStorage(templateTable.page, templateTable.limit, templateTable.searchParam); templateTable.total = res.data.total
}).catch(() => { setTablePageStorage(
templateTable.loading = false templateTable.page,
templateTable.limit,
templateTable.searchParam
)
})
.catch(() => {
templateTable.loading = false
}) })
} }
loadTemplateList(getTablePageStorage(templateTable.searchParam).page); loadTemplateList(getTablePageStorage(templateTable.searchParam).page)
/** /**
* 添加运费模板 * 添加运费模板
*/ */
const addEvent = () => { const addEvent = () => {
router.push({ path: '/shop/order/shipping/template_edit' }) router.push({ path: '/shop/order/shipping/template_edit' })
} }
/** /**
@ -117,33 +176,34 @@ const addEvent = () => {
* @param data * @param data
*/ */
const editEvent = (data: any) => { const editEvent = (data: any) => {
router.push({ path: '/shop/order/shipping/template_edit', query: { id: data.template_id } }) router.push({
path: '/shop/order/shipping/template_edit',
query: { id: data.template_id },
})
} }
/** /**
* 删除运费模板 * 删除运费模板
*/ */
const deleteEvent = (id: number) => { const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('templateDeleteTips'), t('warning'), ElMessageBox.confirm(t('templateDeleteTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning' }).then(() => {
} deleteShippingTemplate(id)
).then(() => { .then(() => {
deleteShippingTemplate(id).then(() => { loadTemplateList()
loadTemplateList() })
}).catch(() => { .catch(() => {})
}) })
})
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
loadTemplateList() loadTemplateList()
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

937
admin/src/addon/shop/views/delivery/template_edit.vue

File diff suppressed because it is too large

494
admin/src/addon/shop/views/diy/components/edit-goods-coupon.vue

@ -1,119 +1,203 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<div class="edit-attr-item-wrap"> <h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3> <el-form label-width="80px" class="px-[10px]">
<el-form label-width="80px" class="px-[10px]"> <el-form-item :label="t('selectStyle')" class="flex">
<el-form-item :label="t('selectStyle')" class="flex"> <span
<span class="text-primary flex-1 cursor-pointer" @click="showCouponStyle">{{ diyStore.editComponent.styleName }}</span> class="text-primary flex-1 cursor-pointer"
<el-icon> @click="showCouponStyle"
<ArrowRight /> >{{ diyStore.editComponent.styleName }}</span
</el-icon> >
</el-form-item> <el-icon>
</el-form> <ArrowRight />
</el-icon>
<el-dialog v-model="showCouponDialog" :title="t('selectStyle')" width="500px"> </el-form-item>
<div class="flex flex-wrap"> </el-form>
<template v-for="(item,index) in couponStyleList" :key="index">
<div :class="{ 'border-primary': selectCouponStyle.value == item.value }" @click="changeCouponStyle(item)" class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] m-[6px] cursor-pointer border bg-gray-50"> <el-dialog
<img :src="img(item.url)" /> v-model="showCouponDialog"
</div> :title="t('selectStyle')"
</template> width="500px"
</div> >
<div class="flex flex-wrap">
<template #footer> <template v-for="(item, index) in couponStyleList" :key="index">
<span class="dialog-footer"> <div
<el-button @click="showCouponDialog = false">{{ t('cancel') }}</el-button> :class="{
<el-button type="primary" @click="confirmCouponStyle">{{ t('confirm') }}</el-button> 'border-primary': selectCouponStyle.value == item.value,
</span> }"
</template> @click="changeCouponStyle(item)"
class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] m-[6px] cursor-pointer border bg-gray-50"
</el-dialog> >
</div> <img :src="img(item.url)" />
</div>
<div class="edit-attr-item-wrap"> </template>
<h3 class="mb-[10px]">{{ t('couponContent') }}</h3> </div>
<el-form label-width="90px" class="px-[10px]">
<template #footer>
<el-form-item :label="t('couponTitle')"> <span class="dialog-footer">
<el-input v-model.trim="diyStore.editComponent.couponTitle" clearable :maxlength="diyStore.editComponent.style == 'style-3' ? 4 : 8" show-word-limit/> <el-button @click="showCouponDialog = false">{{
</el-form-item> t('cancel')
}}</el-button>
<el-form-item :label="t('couponSubTitle')"> <el-button type="primary" @click="confirmCouponStyle">{{
<el-input v-model.trim="diyStore.editComponent.couponSubTitle" clearable :maxlength="diyStore.editComponent.style == 'style-3' ? 7 : 10" show-word-limit/> t('confirm')
</el-form-item> }}</el-button>
</span>
</el-form> </template>
</el-dialog>
</div> </div>
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('couponData') }}</h3> <h3 class="mb-[10px]">{{ t('couponContent') }}</h3>
<el-form label-width="90px" class="px-[10px]"> <el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('couponTitle')">
<el-form-item :label="t('selectCoupon')"> <el-input
<el-radio-group v-model="diyStore.editComponent.source" :title="t('goodsSelectPopupSelectGoodsButton')"> v-model.trim="diyStore.editComponent.couponTitle"
<el-radio label="all">{{ t('allSources') }}</el-radio> clearable
<el-radio label="custom">{{ t('manualSelectionSources') }}</el-radio> :maxlength="diyStore.editComponent.style == 'style-3' ? 4 : 8"
</el-radio-group> show-word-limit
</el-form-item> />
<el-form-item :label="t('manualSelectionSources')" v-if="diyStore.editComponent.source == 'custom'"> </el-form-item>
<coupon-select-popup ref="couponSelectPopupRef" v-model="diyStore.editComponent.couponIds" :min="1" :max="20" />
</el-form-item> <el-form-item :label="t('couponSubTitle')">
<el-form-item :label="t('couponNum')" v-if="diyStore.editComponent.source == 'all'"> <el-input
<el-slider show-input v-model="diyStore.editComponent.num" :min="1" max="20" size="small" class="goods-coupon-slider" /> v-model.trim="diyStore.editComponent.couponSubTitle"
</el-form-item> clearable
<el-form-item :label="t('couponBtnText')" v-if="diyStore.editComponent.style != 'style-4'"> :maxlength="diyStore.editComponent.style == 'style-3' ? 7 : 10"
<el-input v-model.trim="diyStore.editComponent.btnText" clearable maxlength="5" show-word-limit/> show-word-limit
</el-form-item> />
</el-form-item>
</el-form> </el-form>
</div>
</div>
<div class="edit-attr-item-wrap">
</div> <h3 class="mb-[10px]">{{ t('couponData') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<!-- 样式 --> <el-form-item :label="t('selectCoupon')">
<div class="style-wrap" v-show="diyStore.editTab == 'style'"> <el-radio-group
v-model="diyStore.editComponent.source"
<div class="edit-attr-item-wrap" v-if="diyStore.editComponent.style == 'style-4'"> :title="t('goodsSelectPopupSelectGoodsButton')"
<h3 class="mb-[10px]">{{ t("couponTitleStyle") }}</h3> >
<el-form label-width="90px" class="px-[10px]"> <el-radio label="all">{{ t('allSources') }}</el-radio>
<el-form-item :label="t('couponTitleColor')"> <el-radio label="custom">{{
<el-color-picker v-model="diyStore.editComponent.titleColor" show-alpha :predefine="diyStore.predefineColors" /> t('manualSelectionSources')
</el-form-item> }}</el-radio>
<el-form-item :label="t('couponSubTitleColor')"> </el-radio-group>
<el-color-picker v-model="diyStore.editComponent.subTitleColor" show-alpha :predefine="diyStore.predefineColors" /> </el-form-item>
</el-form-item> <el-form-item
</el-form> :label="t('manualSelectionSources')"
</div> v-if="diyStore.editComponent.source == 'custom'"
>
<div class="edit-attr-item-wrap" v-if="diyStore.editComponent.style == 'style-4'"> <coupon-select-popup
<h3 class="mb-[10px]">{{ t("couponItemStyle") }}</h3> ref="couponSelectPopupRef"
<el-form label-width="90px" class="px-[10px]"> v-model="diyStore.editComponent.couponIds"
<el-form-item :label="t('couponMoney')"> :min="1"
<el-color-picker v-model="diyStore.editComponent.couponItem.moneyColor" show-alpha :predefine="diyStore.predefineColors" /> :max="20"
</el-form-item> />
<el-form-item :label="t('textColor')"> </el-form-item>
<el-color-picker v-model="diyStore.editComponent.couponItem.textColor" show-alpha :predefine="diyStore.predefineColors" /> <el-form-item
</el-form-item> :label="t('couponNum')"
<el-form-item :label="t('subTextColor')"> v-if="diyStore.editComponent.source == 'all'"
<el-color-picker v-model="diyStore.editComponent.couponItem.subTextColor" show-alpha :predefine="diyStore.predefineColors" /> >
</el-form-item> <el-slider
<el-form-item :label="t('listFrameColor')"> show-input
<el-color-picker v-model="diyStore.editComponent.couponItem.bgColor" show-alpha :predefine="diyStore.predefineColors" /> v-model="diyStore.editComponent.num"
</el-form-item> :min="1"
<el-form-item :label="t('goodsRounded')"> max="20"
<el-slider v-model="diyStore.editComponent.couponItem.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> size="small"
</el-form-item> class="goods-coupon-slider"
</el-form> />
</div> </el-form-item>
<el-form-item
<!-- 组件样式 --> :label="t('couponBtnText')"
<slot name="style"></slot> v-if="diyStore.editComponent.style != 'style-4'"
</div> >
<el-input
v-model.trim="diyStore.editComponent.btnText"
clearable
maxlength="5"
show-word-limit
/>
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div
class="edit-attr-item-wrap"
v-if="diyStore.editComponent.style == 'style-4'"
>
<h3 class="mb-[10px]">{{ t('couponTitleStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('couponTitleColor')">
<el-color-picker
v-model="diyStore.editComponent.titleColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('couponSubTitleColor')">
<el-color-picker
v-model="diyStore.editComponent.subTitleColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
</el-form>
</div>
<div
class="edit-attr-item-wrap"
v-if="diyStore.editComponent.style == 'style-4'"
>
<h3 class="mb-[10px]">{{ t('couponItemStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('couponMoney')">
<el-color-picker
v-model="diyStore.editComponent.couponItem.moneyColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker
v-model="diyStore.editComponent.couponItem.textColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('subTextColor')">
<el-color-picker
v-model="diyStore.editComponent.couponItem.subTextColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('listFrameColor')">
<el-color-picker
v-model="diyStore.editComponent.couponItem.bgColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('goodsRounded')">
<el-slider
v-model="diyStore.editComponent.couponItem.aroundRadius"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -127,126 +211,134 @@ import couponSelectPopup from '@/addon/shop/views/goods/components/coupon-select
import { el } from 'element-plus/es/locale' import { el } from 'element-plus/es/locale'
const diyStore = useDiyStore() const diyStore = useDiyStore()
diyStore.editComponent.ignore = ['componentBgColor','componentBgUrl'] // diyStore.editComponent.ignore = ['componentBgColor', 'componentBgUrl'] //
// //
diyStore.editComponent.verify = (index: number) => { diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' } const res = { code: true, message: '' }
if(diyStore.value[index].source == 'custom'){
if(diyStore.value[index].couponIds.length == 0){
res.code = false
res.message = t('couponPlaceholder')
return res;
}
}
if(diyStore.value[index].btnText == ''){ if (diyStore.value[index].source == 'custom') {
res.code = false if (diyStore.value[index].couponIds.length == 0) {
res.message = t('couponBtnTextPlaceholder') res.code = false
return res; res.message = t('couponPlaceholder')
return res
} }
}
if(diyStore.value[index].couponTitle == ''){ if (diyStore.value[index].btnText == '') {
res.code = false res.code = false
res.message = t('couponTitlePlaceholder') res.message = t('couponBtnTextPlaceholder')
return res; return res
} }
if(diyStore.value[index].couponSubTitle == ''){ if (diyStore.value[index].couponTitle == '') {
res.code = false res.code = false
res.message = t('couponSubTitlePlaceholder') res.message = t('couponTitlePlaceholder')
return res; return res
} }
if (diyStore.value[index].couponSubTitle == '') {
res.code = false
res.message = t('couponSubTitlePlaceholder')
return res return res
}
return res
} }
const selectCouponStyle = reactive({ const selectCouponStyle = reactive({
title: diyStore.editComponent.styleName, title: diyStore.editComponent.styleName,
value: diyStore.editComponent.style value: diyStore.editComponent.style,
}) })
// //
const showCouponDialog = ref(false) const showCouponDialog = ref(false)
const showCouponStyle = () => { const showCouponStyle = () => {
showCouponDialog.value = true showCouponDialog.value = true
selectCouponStyle.title = diyStore.editComponent.styleName; selectCouponStyle.title = diyStore.editComponent.styleName
selectCouponStyle.value = diyStore.editComponent.style; selectCouponStyle.value = diyStore.editComponent.style
} }
const couponStyleList = reactive([ const couponStyleList = reactive([
{ {
url: 'addon/shop/diy/goods_coupon/style-1.png', url: 'addon/shop/diy/goods_coupon/style-1.png',
title: '风格1', title: '风格1',
value: 'style-1' value: 'style-1',
}, },
{ {
url: 'addon/shop/diy/goods_coupon/style-2.png', url: 'addon/shop/diy/goods_coupon/style-2.png',
title: '风格2', title: '风格2',
value: 'style-2' value: 'style-2',
}, },
{ {
url: 'addon/shop/diy/goods_coupon/style-3.png', url: 'addon/shop/diy/goods_coupon/style-3.png',
title: '风格3', title: '风格3',
value: 'style-3' value: 'style-3',
}, },
{ {
url: 'addon/shop/diy/goods_coupon/style-4.png', url: 'addon/shop/diy/goods_coupon/style-4.png',
title: '风格4', title: '风格4',
value: 'style-4' value: 'style-4',
} },
]) ])
const changeCouponStyle = (item:any) => { const changeCouponStyle = (item: any) => {
selectCouponStyle.title = item.title; selectCouponStyle.title = item.title
selectCouponStyle.value = item.value; selectCouponStyle.value = item.value
} }
const confirmCouponStyle = () => { const confirmCouponStyle = () => {
diyStore.editComponent.styleName = selectCouponStyle.title; diyStore.editComponent.styleName = selectCouponStyle.title
diyStore.editComponent.style = selectCouponStyle.value; diyStore.editComponent.style = selectCouponStyle.value
if(diyStore.editComponent.style == 'style-3'){ if (diyStore.editComponent.style == 'style-3') {
if(diyStore.editComponent.couponTitle && diyStore.editComponent.couponTitle.length > 4){diyStore.editComponent.couponTitle = diyStore.editComponent.couponTitle.substring(0,4)} if (
if(diyStore.editComponent.couponSubTitle && diyStore.editComponent.couponSubTitle.length > 7){diyStore.editComponent.couponSubTitle = diyStore.editComponent.couponSubTitle.substring(0,7)} diyStore.editComponent.couponTitle &&
diyStore.editComponent.couponTitle.length > 4
) {
diyStore.editComponent.couponTitle =
diyStore.editComponent.couponTitle.substring(0, 4)
}
if (
diyStore.editComponent.couponSubTitle &&
diyStore.editComponent.couponSubTitle.length > 7
) {
diyStore.editComponent.couponSubTitle =
diyStore.editComponent.couponSubTitle.substring(0, 7)
} }
initStyleFn(); }
showCouponDialog.value = false initStyleFn()
showCouponDialog.value = false
} }
const initStyleFn = ()=>{ const initStyleFn = () => {
let index = diyStore.editComponent.ignore.indexOf('componentBgColor'); let index = diyStore.editComponent.ignore.indexOf('componentBgColor')
if(diyStore.editComponent.style == 'style-4' && index != -1){ if (diyStore.editComponent.style == 'style-4' && index != -1) {
diyStore.editComponent.ignore.splice(index,1); diyStore.editComponent.ignore.splice(index, 1)
diyStore.editComponent.titleColor = "#ffffff"; diyStore.editComponent.titleColor = '#ffffff'
diyStore.editComponent.subTitleColor = "#ffffff"; diyStore.editComponent.subTitleColor = '#ffffff'
diyStore.editComponent.couponItem.moneyColor = "#fa191d"; diyStore.editComponent.couponItem.moneyColor = '#fa191d'
diyStore.editComponent.couponItem.textColor = "#333333"; diyStore.editComponent.couponItem.textColor = '#333333'
diyStore.editComponent.couponItem.subTextColor = "#999999"; diyStore.editComponent.couponItem.subTextColor = '#999999'
diyStore.editComponent.couponItem.bgColor = "#ffffff"; diyStore.editComponent.couponItem.bgColor = '#ffffff'
diyStore.editComponent.couponItem.aroundRadius = 10; diyStore.editComponent.couponItem.aroundRadius = 10
diyStore.editComponent.componentStartBgColor = "#fa191d"; diyStore.editComponent.componentStartBgColor = '#fa191d'
} else if (diyStore.editComponent.style != 'style-4' && index == -1) {
}else if(diyStore.editComponent.style != 'style-4' && index == -1){ diyStore.editComponent.ignore.push('componentBgColor')
diyStore.editComponent.ignore.push('componentBgColor'); }
}
} }
initStyleFn(); initStyleFn()
defineExpose({}) defineExpose({})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>
<style lang="scss"> <style lang="scss">
.goods-coupon-slider { .goods-coupon-slider {
.el-slider__input { .el-slider__input {
width: 100px; width: 100px;
} }
} }
</style> </style>

742
admin/src/addon/shop/views/diy/components/edit-goods-list.vue

@ -1,196 +1,372 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3> <h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
<div class="flex items-center mb-[18px] rounded overflow-hidden"> <div class="flex items-center mb-[18px] rounded overflow-hidden">
<span <span
class="iconfont iconzuoyoutuwenpc border-[1px] border-solid border-[#eee] cursor-pointer flex-1 flex items-center justify-center py-[5px]" class="iconfont iconzuoyoutuwenpc border-[1px] border-solid border-[#eee] cursor-pointer flex-1 flex items-center justify-center py-[5px]"
:class="{ 'border-[var(--el-color-primary)] text-[var(--el-color-primary)]': diyStore.editComponent.style == 'style-1' }" :class="{
@click="styleChangeFn('style-1')"></span> 'border-[var(--el-color-primary)] text-[var(--el-color-primary)]':
diyStore.editComponent.style == 'style-1',
<span }"
class="iconfont iconshangxiatuwenpc border-[1px] border-solid border-[#eee] cursor-pointer flex-1 flex items-center justify-center py-[5px]" @click="styleChangeFn('style-1')"
:class="{ 'border-[var(--el-color-primary)] text-[var(--el-color-primary)]': diyStore.editComponent.style == 'style-2' }" ></span>
@click="styleChangeFn('style-2')"></span>
<span
class="iconfont iconliebiaopc border-[1px] border-solid border-[#eee] cursor-pointer flex-1 flex items-center justify-center py-[5px]"
:class="{ 'border-[var(--el-color-primary)] text-[var(--el-color-primary)]': diyStore.editComponent.style == 'style-3' }"
@click="styleChangeFn('style-3')"></span>
</div>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t("selectSource") }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('sortWay')">
<el-radio-group v-model="diyStore.editComponent.sortWay">
<el-radio label="default">{{ t('default') }}</el-radio>
<el-radio label="sale_num">{{ t('sales') }}</el-radio>
<el-radio label="price">{{ t('price') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('goodsSelectPopupSelectGoodsButton')">
<el-radio-group v-model="diyStore.editComponent.source" :title="t('goodsSelectPopupSelectGoodsButton')">
<el-radio label="all">{{ t('goodsSelectPopupAllGoods') }}</el-radio>
<el-radio label="category">{{ t('selectCategory') }}</el-radio>
<el-radio label="custom">{{ t('manualSelectionSources') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('selectCategory')" v-if="diyStore.editComponent.source == 'category'">
<div class="flex items-center w-full">
<div class="cursor-pointer ml-auto" @click="categoryShowDialogOpen">
<span class="text-[var(--el-color-primary)]">{{ diyStore.editComponent.goods_category_name }}</span>
<span class="iconfont iconxiangyoujiantou"></span>
</div>
</div>
</el-form-item>
<el-form-item :label="t('goodsNum')" v-if="diyStore.editComponent.source == 'all' || diyStore.editComponent.source == 'category'">
<el-slider class="goods-list-slider" show-input v-model="diyStore.editComponent.num" :min="1" max="20" size="small" />
</el-form-item>
<el-form-item :label="t('customGoods')" v-if="diyStore.editComponent.source == 'custom'">
<goods-select-popup ref="goodsSelectPopupRef" v-model="diyStore.editComponent.goods_ids" :min="1" :max="99" />
</el-form-item>
</el-form>
<el-dialog v-model="categoryShowDialog" :title="t('goodsCategoryTitle')" width="750px" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false"> <span
<el-table :data="categoryTable.data" ref="categoryTableRef" size="large" v-loading="categoryTable.loading" class="iconfont iconshangxiatuwenpc border-[1px] border-solid border-[#eee] cursor-pointer flex-1 flex items-center justify-center py-[5px]"
height="450px" @selection-change="handleSelectionChange" row-key="category_id" :class="{
:expand-row-keys="expand_category_ids" 'border-[var(--el-color-primary)] text-[var(--el-color-primary)]':
:tree-props="{ hasChildren: 'hasChildren', children: 'child_list' }"> diyStore.editComponent.style == 'style-2',
<template #empty> }"
<span>{{ !categoryTable.loading ? t('emptyData') : '' }}</span> @click="styleChangeFn('style-2')"
</template> ></span>
<el-table-column type="selection" width="55" /> <span
<el-table-column :label="t('categoryName')" min-width="120"> class="iconfont iconliebiaopc border-[1px] border-solid border-[#eee] cursor-pointer flex-1 flex items-center justify-center py-[5px]"
<template #default="{ row }"> :class="{
<span class="order-2">{{ row.category_name }}</span> 'border-[var(--el-color-primary)] text-[var(--el-color-primary)]':
</template> diyStore.editComponent.style == 'style-3',
</el-table-column> }"
<el-table-column :label="t('categoryImage')" width="170" align="left"> @click="styleChangeFn('style-3')"
<template #default="{ row }"> ></span>
<div class="h-[30px]"> </div>
<el-image class="w-[30px] h-[30px] " :src="img(row.image)" fit="contain"> </div>
<template #error> <div class="edit-attr-item-wrap">
<div class="image-slot"> <h3 class="mb-[10px]">{{ t('selectSource') }}</h3>
<img class="w-[30px] h-[30px]" src="@/addon/shop/assets/category_default.png" /> <el-form label-width="80px" class="px-[10px]">
</div> <el-form-item :label="t('sortWay')">
</template> <el-radio-group v-model="diyStore.editComponent.sortWay">
</el-image> <el-radio label="default">{{ t('default') }}</el-radio>
</div> <el-radio label="sale_num">{{ t('sales') }}</el-radio>
</template> <el-radio label="price">{{ t('price') }}</el-radio>
</el-table-column> </el-radio-group>
</el-table> </el-form-item>
<div class="flex items-center justify-end mt-[15px]"> <el-form-item :label="t('goodsSelectPopupSelectGoodsButton')">
<el-button type="primary" @click="saveCategoryId">{{ t('confirm') }}</el-button> <el-radio-group
<el-button @click="categoryShowDialog = false">{{ t('cancel') }}</el-button> v-model="diyStore.editComponent.source"
</div> :title="t('goodsSelectPopupSelectGoodsButton')"
</el-dialog> >
<el-radio label="all">{{ t('goodsSelectPopupAllGoods') }}</el-radio>
<el-radio label="category">{{ t('selectCategory') }}</el-radio>
<el-radio label="custom">{{
t('manualSelectionSources')
}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
:label="t('selectCategory')"
v-if="diyStore.editComponent.source == 'category'"
>
<div class="flex items-center w-full">
<div class="cursor-pointer ml-auto" @click="categoryShowDialogOpen">
<span class="text-[var(--el-color-primary)]">{{
diyStore.editComponent.goods_category_name
}}</span>
<span class="iconfont iconxiangyoujiantou"></span>
</div>
</div>
</el-form-item>
<el-form-item
:label="t('goodsNum')"
v-if="
diyStore.editComponent.source == 'all' ||
diyStore.editComponent.source == 'category'
"
>
<el-slider
class="goods-list-slider"
show-input
v-model="diyStore.editComponent.num"
:min="1"
max="20"
size="small"
/>
</el-form-item>
<el-form-item
:label="t('customGoods')"
v-if="diyStore.editComponent.source == 'custom'"
>
<goods-select-popup
ref="goodsSelectPopupRef"
v-model="diyStore.editComponent.goods_ids"
:min="1"
:max="99"
/>
</el-form-item>
</el-form>
</div> <el-dialog
v-model="categoryShowDialog"
<div class="edit-attr-item-wrap"> :title="t('goodsCategoryTitle')"
<h3 class="mb-[10px]">{{ t("goodsBuyBtn") }}</h3> width="750px"
<el-form label-width="90px" class="px-[10px]"> :close-on-press-escape="false"
<el-form-item :label="t('goodsBtnIsShow')"> :destroy-on-close="true"
<el-switch v-model="diyStore.editComponent.btnStyle.control" /> :close-on-click-modal="false"
</el-form-item> >
<el-form-item :label="t('goodsCartIncident')" v-if="diyStore.editComponent.btnStyle.control"> <el-table
<el-radio-group v-model="diyStore.editComponent.btnStyle.cartEvent"> :data="categoryTable.data"
<el-radio label="detail">{{ t('goodsDetail') }}</el-radio> ref="categoryTableRef"
</el-radio-group> size="large"
</el-form-item> v-loading="categoryTable.loading"
<el-form-item :label="t('goodsBtnStyle')" class="!items-center" v-if="diyStore.editComponent.btnStyle.control"> height="450px"
<div class="flex"> @selection-change="handleSelectionChange"
<template v-for="(item,index) in btnStyleList"> row-key="category_id"
<div v-if=" item.isShow == true" class="cursor-pointer flex items-center justify-center border-[1px] border-solid border-transparent rounded-[6px] py-[5px] px-[8px] mr-[10px]" :class="{'!border-[var(--el-color-primary)]': diyStore.editComponent.btnStyle.style == item.value}"> :expand-row-keys="expand_category_ids"
<div v-if="item.type == 'icon'" :class="['nc-iconfont !text-[25px] text-[var(--el-color-primary)]', item.title]" @click="changeBtnStyle(item)"></div> :tree-props="{ hasChildren: 'hasChildren', children: 'child_list' }"
<div v-if="item.type == 'button'" class="leading-[1] text-[12px] px-[10px] py-[8px] text-[#fff] rounded-[20px] bg-[var(--el-color-primary)]" @click="changeBtnStyle(item)"> >
{{item.title}} <template #empty>
</div> <span>{{ !categoryTable.loading ? t('emptyData') : '' }}</span>
</div> </template>
</template> <el-table-column type="selection" width="55" />
<el-table-column :label="t('categoryName')" min-width="120">
<template #default="{ row }">
<span class="order-2">{{ row.category_name }}</span>
</template>
</el-table-column>
<el-table-column :label="t('categoryImage')" width="170" align="left">
<template #default="{ row }">
<div class="h-[30px]">
<el-image
class="w-[30px] h-[30px]"
:src="img(row.image)"
fit="contain"
>
<template #error>
<div class="image-slot">
<img
class="w-[30px] h-[30px]"
src="@/addon/shop/assets/category_default.png"
/>
</div> </div>
</el-form-item> </template>
<el-form-item :label="t('goodsBtnText')" v-if="diyStore.editComponent.btnStyle.control && diyStore.editComponent.btnStyle.style == 'button'"> </el-image>
<el-input v-model.trim="diyStore.editComponent.btnStyle.text" :placeholder="t('goodsBtnTextPlaceholder')" clearable maxlength="4" show-word-limit/> </div>
</el-form-item> </template>
</el-form> </el-table-column>
</div> </el-table>
<div class="flex items-center justify-end mt-[15px]">
<el-button type="primary" @click="saveCategoryId">{{
t('confirm')
}}</el-button>
<el-button @click="categoryShowDialog = false">{{
t('cancel')
}}</el-button>
</div>
</el-dialog>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('goodsBuyBtn') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('goodsBtnIsShow')">
<el-switch v-model="diyStore.editComponent.btnStyle.control" />
</el-form-item>
<el-form-item
:label="t('goodsCartIncident')"
v-if="diyStore.editComponent.btnStyle.control"
>
<el-radio-group v-model="diyStore.editComponent.btnStyle.cartEvent">
<el-radio label="detail">{{ t('goodsDetail') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
:label="t('goodsBtnStyle')"
class="!items-center"
v-if="diyStore.editComponent.btnStyle.control"
>
<div class="flex">
<template v-for="(item, index) in btnStyleList">
<div
v-if="item.isShow == true"
class="cursor-pointer flex items-center justify-center border-[1px] border-solid border-transparent rounded-[6px] py-[5px] px-[8px] mr-[10px]"
:class="{
'!border-[var(--el-color-primary)]':
diyStore.editComponent.btnStyle.style == item.value,
}"
>
<div
v-if="item.type == 'icon'"
:class="[
'nc-iconfont !text-[25px] text-[var(--el-color-primary)]',
item.title,
]"
@click="changeBtnStyle(item)"
></div>
<div
v-if="item.type == 'button'"
class="leading-[1] text-[12px] px-[10px] py-[8px] text-[#fff] rounded-[20px] bg-[var(--el-color-primary)]"
@click="changeBtnStyle(item)"
>
{{ item.title }}
</div>
</div>
</template>
</div>
</el-form-item>
<el-form-item
:label="t('goodsBtnText')"
v-if="
diyStore.editComponent.btnStyle.control &&
diyStore.editComponent.btnStyle.style == 'button'
"
>
<el-input
v-model.trim="diyStore.editComponent.btnStyle.text"
:placeholder="t('goodsBtnTextPlaceholder')"
clearable
maxlength="4"
show-word-limit
/>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t("goodsShowContent") }}</h3> <h3 class="mb-[10px]">{{ t('goodsShowContent') }}</h3>
<el-form label-width="90px" class="px-[10px]"> <el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('goodsSelectPopupGoodsName')" v-if="diyStore.editComponent.goodsNameStyle.isShow"> <el-form-item
<el-switch v-model="diyStore.editComponent.goodsNameStyle.control" /> :label="t('goodsSelectPopupGoodsName')"
</el-form-item> v-if="diyStore.editComponent.goodsNameStyle.isShow"
<el-form-item :label="t('goodsPriceColor')" v-if="diyStore.editComponent.priceStyle.isShow"> >
<el-switch v-model="diyStore.editComponent.priceStyle.control" /> <el-switch v-model="diyStore.editComponent.goodsNameStyle.control" />
</el-form-item> </el-form-item>
<el-form-item :label="t('goodsSaleNum')" v-if="diyStore.editComponent.saleStyle.isShow"> <el-form-item
<el-switch v-model="diyStore.editComponent.saleStyle.control" /> :label="t('goodsPriceColor')"
</el-form-item> v-if="diyStore.editComponent.priceStyle.isShow"
<el-form-item :label="t('goodsLabel')" v-if="diyStore.editComponent.labelStyle.isShow"> >
<el-switch v-model="diyStore.editComponent.labelStyle.control" /> <el-switch v-model="diyStore.editComponent.priceStyle.control" />
</el-form-item> </el-form-item>
</el-form> <el-form-item
</div> :label="t('goodsSaleNum')"
</div> v-if="diyStore.editComponent.saleStyle.isShow"
>
<el-switch v-model="diyStore.editComponent.saleStyle.control" />
</el-form-item>
<el-form-item
:label="t('goodsLabel')"
v-if="diyStore.editComponent.labelStyle.isShow"
>
<el-switch v-model="diyStore.editComponent.labelStyle.control" />
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 --> <!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'"> <div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3> <h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('goodsBgColor')"> <el-form-item :label="t('goodsBgColor')">
<el-color-picker v-model="diyStore.editComponent.elementBgColor" show-alpha :predefine="diyStore.predefineColors" /> <el-color-picker
</el-form-item> v-model="diyStore.editComponent.elementBgColor"
<el-form-item :label="t('goodsNameColor')"> show-alpha
<el-color-picker v-model="diyStore.editComponent.goodsNameStyle.color" show-alpha :predefine="diyStore.predefineColors" /> :predefine="diyStore.predefineColors"
<div class="mr-[20px]"></div> />
<el-radio-group v-model="diyStore.editComponent.goodsNameStyle.fontWeight"> </el-form-item>
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio> <el-form-item :label="t('goodsNameColor')">
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio> <el-color-picker
</el-radio-group> v-model="diyStore.editComponent.goodsNameStyle.color"
</el-form-item> show-alpha
<el-form-item :label="t('goodsPriceColor')"> :predefine="diyStore.predefineColors"
<el-color-picker v-model="diyStore.editComponent.priceStyle.color" show-alpha :predefine="diyStore.predefineColors" /> />
</el-form-item> <div class="mr-[20px]"></div>
<el-form-item :label="t('goodsSaleColor')"> <el-radio-group
<el-color-picker v-model="diyStore.editComponent.saleStyle.color" show-alpha :predefine="diyStore.predefineColors" /> v-model="diyStore.editComponent.goodsNameStyle.fontWeight"
</el-form-item> >
<el-form-item :label="t('topRounded')"> <el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> <el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-form-item> </el-radio-group>
<el-form-item :label="t('bottomRounded')"> </el-form-item>
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> <el-form-item :label="t('goodsPriceColor')">
</el-form-item> <el-color-picker
</el-form> v-model="diyStore.editComponent.priceStyle.color"
</div> show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('goodsSaleColor')">
<el-color-picker
v-model="diyStore.editComponent.saleStyle.color"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('topRounded')">
<el-slider
v-model="diyStore.editComponent.topElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider
v-model="diyStore.editComponent.bottomElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-if="diyStore.editComponent.btnStyle.control"> <div
<h3 class="mb-[10px]">{{ t("goodsBuyBtn") }}</h3> class="edit-attr-item-wrap"
<el-form label-width="80px" class="px-[10px]"> v-if="diyStore.editComponent.btnStyle.control"
<el-form-item :label="t('goodsIsBold')" v-if="diyStore.editComponent.btnStyle.style == 'button'"> >
<el-switch v-model="diyStore.editComponent.btnStyle.fontWeight" /> <h3 class="mb-[10px]">{{ t('goodsBuyBtn') }}</h3>
</el-form-item> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('goodsTextColor')"> <el-form-item
<el-color-picker v-model="diyStore.editComponent.btnStyle.textColor" show-alpha :predefine="diyStore.predefineColors" /> :label="t('goodsIsBold')"
</el-form-item> v-if="diyStore.editComponent.btnStyle.style == 'button'"
<el-form-item :label="t('listFrameColor')"> >
<el-color-picker v-model="diyStore.editComponent.btnStyle.startBgColor" show-alpha :predefine="diyStore.predefineColors" /> <el-switch v-model="diyStore.editComponent.btnStyle.fontWeight" />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/> </el-form-item>
<el-color-picker v-model="diyStore.editComponent.btnStyle.endBgColor" show-alpha :predefine="diyStore.predefineColors"/> <el-form-item :label="t('goodsTextColor')">
</el-form-item> <el-color-picker
<el-form-item :label="t('goodsRounded')" v-if="diyStore.editComponent.btnStyle.style == 'button'"> v-model="diyStore.editComponent.btnStyle.textColor"
<el-slider v-model="diyStore.editComponent.btnStyle.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> show-alpha
</el-form-item> :predefine="diyStore.predefineColors"
</el-form> />
</div> </el-form-item>
<el-form-item :label="t('listFrameColor')">
<el-color-picker
v-model="diyStore.editComponent.btnStyle.startBgColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
<icon
name="iconfont iconmap-connect"
size="20px"
class="block !text-gray-400 mx-[5px]"
/>
<el-color-picker
v-model="diyStore.editComponent.btnStyle.endBgColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item
:label="t('goodsRounded')"
v-if="diyStore.editComponent.btnStyle.style == 'button'"
>
<el-slider
v-model="diyStore.editComponent.btnStyle.aroundRadius"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 --> <!-- 组件样式 -->
<slot name="style"></slot> <slot name="style"></slot>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -198,93 +374,92 @@ import { getCategoryTree } from '@/addon/shop/api/goods'
import { t } from '@/lang' import { t } from '@/lang'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import useDiyStore from '@/stores/modules/diy' import useDiyStore from '@/stores/modules/diy'
import { ref, reactive, onMounted,nextTick } from 'vue' import { ref, reactive, onMounted, nextTick } from 'vue'
import { ElTable } from 'element-plus' import { ElTable } from 'element-plus'
import goodsSelectPopup from '@/addon/shop/views/goods/components/goods-select-popup.vue' import goodsSelectPopup from '@/addon/shop/views/goods/components/goods-select-popup.vue'
const diyStore:any = useDiyStore() const diyStore: any = useDiyStore()
diyStore.editComponent.ignore = [] // diyStore.editComponent.ignore = [] //
// //
diyStore.editComponent.verify = (index: number) => { diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' } const res = { code: true, message: '' }
if(diyStore.value[index].source == 'category'){ if (diyStore.value[index].source == 'category') {
if(diyStore.value[index].goods_category == ''){ if (diyStore.value[index].goods_category == '') {
res.code = false res.code = false
res.message = t('goodsCategoryPlaceholder') res.message = t('goodsCategoryPlaceholder')
} }
}else if(diyStore.value[index].source == 'custom'){ } else if (diyStore.value[index].source == 'custom') {
if(diyStore.value[index].goods_ids.length == 0){ if (diyStore.value[index].goods_ids.length == 0) {
res.code = false res.code = false
res.message = t('goodsPlaceholder') res.message = t('goodsPlaceholder')
}
} }
return res }
return res
} }
const categoryShowDialog = ref(false) const categoryShowDialog = ref(false)
const categoryTable = reactive({ const categoryTable = reactive({
loading: true, loading: true,
data: [], data: [],
}) })
onMounted(() => { onMounted(() => {
loadCategoryList() loadCategoryList()
}) })
const styleChangeFn = (style) => {
const styleChangeFn = (style)=>{ btnStyleList.forEach((item, index, arr) => {
btnStyleList.forEach((item,index,arr)=>{ if (item.type == 'button') {
if(item.type == "button"){ if (style == 'style-3') {
if(style == "style-3"){ item.isShow = false
item.isShow = false; } else {
}else{ item.isShow = true
item.isShow = true; }
}
}
})
if(style == "style-3"){
diyStore.editComponent.btnStyle.style = btnStyleList[1].value
}else{
diyStore.editComponent.btnStyle.style = btnStyleList[0].value
} }
})
if(style == "style-3"){ if (style == 'style-3') {
diyStore.editComponent.saleStyle.isShow = false; diyStore.editComponent.btnStyle.style = btnStyleList[1].value
diyStore.editComponent.labelStyle.isShow = false; } else {
}else{ diyStore.editComponent.btnStyle.style = btnStyleList[0].value
diyStore.editComponent.saleStyle.isShow = true; }
diyStore.editComponent.labelStyle.isShow = true;
} if (style == 'style-3') {
diyStore.editComponent.saleStyle.isShow = false
diyStore.editComponent.labelStyle.isShow = false
} else {
diyStore.editComponent.saleStyle.isShow = true
diyStore.editComponent.labelStyle.isShow = true
}
diyStore.editComponent.style = style; diyStore.editComponent.style = style
} }
const btnStyleList = reactive([ const btnStyleList = reactive([
{ {
isShow: true, isShow: true,
type: 'button', type: 'button',
title: diyStore.editComponent.btnStyle.text, title: diyStore.editComponent.btnStyle.text,
value: 'button' value: 'button',
}, },
{ {
isShow: true, isShow: true,
type: 'icon', type: 'icon',
title: 'nc-icon-jiahaoV6xx', title: 'nc-icon-jiahaoV6xx',
value: 'nc-icon-jiahaoV6xx' value: 'nc-icon-jiahaoV6xx',
}, },
{ {
isShow: true, isShow: true,
type: 'icon', type: 'icon',
title: 'nc-icon-gouwuche1', title: 'nc-icon-gouwuche1',
value: 'nc-icon-gouwuche1' value: 'nc-icon-gouwuche1',
} },
]) ])
const changeBtnStyle = (item:any) => { const changeBtnStyle = (item: any) => {
diyStore.editComponent.btnStyle.style = item.value diyStore.editComponent.btnStyle.style = item.value
} }
const categoryTableRef = ref<InstanceType<typeof ElTable>>() const categoryTableRef = ref<InstanceType<typeof ElTable>>()
@ -293,65 +468,66 @@ const categoryTableRef = ref<InstanceType<typeof ElTable>>()
*/ */
let currCategoryData: any = null let currCategoryData: any = null
const loadCategoryList = () => { const loadCategoryList = () => {
categoryTable.loading = true categoryTable.loading = true
getCategoryTree().then(res => { getCategoryTree()
categoryTable.loading = false .then((res) => {
categoryTable.data = res.data categoryTable.loading = false
}).catch(() => { categoryTable.data = res.data
categoryTable.loading = false })
.catch(() => {
categoryTable.loading = false
}) })
} }
// //
const handleSelectionChange = (val: string | any[]) => { const handleSelectionChange = (val: string | any[]) => {
let data = '' let data = ''
if (val) data = val[val.length - 1] if (val) data = val[val.length - 1]
if (val.length > 1) categoryTableRef.value!.clearSelection() if (val.length > 1) categoryTableRef.value!.clearSelection()
if (data) categoryTableRef.value!.toggleRowSelection(data, true) if (data) categoryTableRef.value!.toggleRowSelection(data, true)
currCategoryData = data currCategoryData = data
} }
const saveCategoryId = () => { const saveCategoryId = () => {
diyStore.editComponent.goods_category = currCategoryData.category_id diyStore.editComponent.goods_category = currCategoryData.category_id
diyStore.editComponent.goods_category_name = currCategoryData.category_name; diyStore.editComponent.goods_category_name = currCategoryData.category_name
categoryShowDialog.value = false categoryShowDialog.value = false
} }
const categoryShowDialogOpen = () => { const categoryShowDialogOpen = () => {
categoryShowDialog.value = true categoryShowDialog.value = true
nextTick(()=>{ nextTick(() => {
setRowSelection() setRowSelection()
}) })
} }
//, //,
const expand_category_ids = ref<Array<any>>([]) const expand_category_ids = ref<Array<any>>([])
const setRowSelection = ()=>{ const setRowSelection = () => {
expand_category_ids.value = [] expand_category_ids.value = []
categoryTable.data.forEach((el:any)=>{ categoryTable.data.forEach((el: any) => {
if(diyStore.editComponent.goods_category == el.category_id){ if (diyStore.editComponent.goods_category == el.category_id) {
categoryTableRef.value!.toggleRowSelection(el, true) categoryTableRef.value!.toggleRowSelection(el, true)
}else if(el.child_list&&el.child_list.length){ } else if (el.child_list && el.child_list.length) {
el.child_list.forEach((v:any)=>{ el.child_list.forEach((v: any) => {
if(diyStore.editComponent.goods_category == v.category_id){ if (diyStore.editComponent.goods_category == v.category_id) {
expand_category_ids.value.push(el.category_id.toString()) expand_category_ids.value.push(el.category_id.toString())
categoryTableRef.value!.toggleRowSelection(v, true) categoryTableRef.value!.toggleRowSelection(v, true)
} }
}) })
} }
}) })
} }
defineExpose({}) defineExpose({})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
<style lang="scss"> <style lang="scss">
.goods-list-slider { .goods-list-slider {
.el-slider__input { .el-slider__input {
width: 100px; width: 100px;
} }
} }
</style> </style>

1054
admin/src/addon/shop/views/diy/components/edit-many-goods-list.vue

File diff suppressed because it is too large

211
admin/src/addon/shop/views/diy/components/edit-shop-exchange-goods.vue

@ -1,8 +1,8 @@
<template> <template>
<div> <div>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- <div class="edit-attr-item-wrap"> <!-- <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3> <h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
<div class="flex items-center mb-[18px] rounded overflow-hidden"> <div class="flex items-center mb-[18px] rounded overflow-hidden">
<span <span
@ -19,23 +19,30 @@
@click="diyStore.editComponent.style = 'style-3'"></span> @click="diyStore.editComponent.style = 'style-3'"></span>
</div> </div>
</div> --> </div> -->
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t("selectSource") }}</h3> <h3 class="mb-[10px]">{{ t('selectSource') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('sortWay')"> <el-form-item :label="t('sortWay')">
<el-radio-group v-model="diyStore.editComponent.sortWay"> <el-radio-group v-model="diyStore.editComponent.sortWay">
<el-radio label="total_order_num">{{ t('default') }}</el-radio> <el-radio label="total_order_num">{{ t('default') }}</el-radio>
<el-radio label="total_exchange_num">{{ t('sales') }}</el-radio> <el-radio label="total_exchange_num">{{ t('sales') }}</el-radio>
<el-radio label="price">{{ t('price') }}</el-radio> <el-radio label="price">{{ t('price') }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item :label="t('goodsSelectPopupSelectGoodsButton')"> <el-form-item :label="t('goodsSelectPopupSelectGoodsButton')">
<el-radio-group v-model="diyStore.editComponent.source" :title="t('goodsSelectPopupSelectGoodsButton')"> <el-radio-group
<el-radio label="all">{{ t('goodsSelectPopupAllGoods') }}</el-radio> v-model="diyStore.editComponent.source"
<el-radio label="custom">{{ t('manualSelectionSources') }}</el-radio> :title="t('goodsSelectPopupSelectGoodsButton')"
</el-radio-group> >
</el-form-item> <el-radio label="all">{{
<!-- <el-form-item :label="t('selectCategory')" v-if="diyStore.editComponent.source == 'category'"> t('goodsSelectPopupAllGoods')
}}</el-radio>
<el-radio label="custom">{{
t('manualSelectionSources')
}}</el-radio>
</el-radio-group>
</el-form-item>
<!-- <el-form-item :label="t('selectCategory')" v-if="diyStore.editComponent.source == 'category'">
<div class="flex items-center w-full"> <div class="flex items-center w-full">
<div class="cursor-pointer ml-auto" @click="categoryShowDialogOpen"> <div class="cursor-pointer ml-auto" @click="categoryShowDialogOpen">
<span class="text-[var(--el-color-primary)]">{{ diyStore.editComponent.goods_category_name }}</span> <span class="text-[var(--el-color-primary)]">{{ diyStore.editComponent.goods_category_name }}</span>
@ -49,52 +56,95 @@
<span class="ml-[15px]">{{ diyStore.editComponent.num }}</span> <span class="ml-[15px]">{{ diyStore.editComponent.num }}</span>
</div> </div>
</el-form-item> --> </el-form-item> -->
<el-form-item :label="t('customGoods')" v-if="diyStore.editComponent.source == 'custom'"> <el-form-item
<el-button type="primary" @click="goodsSelectPopupRef.show(diyStore.editComponent.goods_ids)">{{ t('goodsSelectPopupSelectGoodsButton') }}</el-button> :label="t('customGoods')"
<div class="inline-block ml-[10px] text-[14px]" v-show="diyStore.editComponent.goods_ids.length"> v-if="diyStore.editComponent.source == 'custom'"
<span>{{ t('goodsSelectPopupSelect') }}</span> >
<span class="text-primary mx-[2px]">{{ diyStore.editComponent.goods_ids.length }}</span> <el-button
<span>{{ t('goodsSelectPopupPiece') }}</span> type="primary"
</div> @click="
<goods-select-popup ref="goodsSelectPopupRef" :min="1" @select="goodsSelect"/> goodsSelectPopupRef.show(diyStore.editComponent.goods_ids)
</el-form-item> "
</el-form> >{{ t('goodsSelectPopupSelectGoodsButton') }}</el-button
>
</div> <div
</div> class="inline-block ml-[10px] text-[14px]"
v-show="diyStore.editComponent.goods_ids.length"
>
<span>{{ t('goodsSelectPopupSelect') }}</span>
<span class="text-primary mx-[2px]">{{
diyStore.editComponent.goods_ids.length
}}</span>
<span>{{ t('goodsSelectPopupPiece') }}</span>
</div>
<goods-select-popup
ref="goodsSelectPopupRef"
:min="1"
@select="goodsSelect"
/>
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 --> <!-- 样式 -->
<div class="style-wrap" v-if="diyStore.editTab == 'style'"> <div class="style-wrap" v-if="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3> <h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('goodsNameColor')"> <el-form-item :label="t('goodsNameColor')">
<el-color-picker v-model="diyStore.editComponent.goodsNameStyle.color" show-alpha :predefine="diyStore.predefineColors" /> <el-color-picker
<div class="mr-[20px]"></div> v-model="diyStore.editComponent.goodsNameStyle.color"
<el-radio-group v-model="diyStore.editComponent.goodsNameStyle.fontWeight"> show-alpha
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio> :predefine="diyStore.predefineColors"
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio> />
</el-radio-group> <div class="mr-[20px]"></div>
</el-form-item> <el-radio-group
<el-form-item :label="t('goodsNumColor')"> v-model="diyStore.editComponent.goodsNameStyle.fontWeight"
<el-color-picker v-model="diyStore.editComponent.saleStyle.color" show-alpha :predefine="diyStore.predefineColors" /> >
</el-form-item> <el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-form-item :label="t('goodsPriceColor')"> <el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
<el-color-picker v-model="diyStore.editComponent.priceStyle.mainColor" show-alpha :predefine="diyStore.predefineColors" /> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item :label="t('topRounded')"> <el-form-item :label="t('goodsNumColor')">
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> <el-color-picker
</el-form-item> v-model="diyStore.editComponent.saleStyle.color"
<el-form-item :label="t('bottomRounded')"> show-alpha
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> :predefine="diyStore.predefineColors"
</el-form-item> />
</el-form> </el-form-item>
</div> <el-form-item :label="t('goodsPriceColor')">
<el-color-picker
v-model="diyStore.editComponent.priceStyle.mainColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('topRounded')">
<el-slider
v-model="diyStore.editComponent.topElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider
v-model="diyStore.editComponent.bottomElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 --> <!-- 组件样式 -->
<slot name="style"></slot> <slot name="style"></slot>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -104,34 +154,33 @@ import useDiyStore from '@/stores/modules/diy'
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
import goodsSelectPopup from '@/addon/shop/views/marketing/exchange/components/goods-select-popup.vue' import goodsSelectPopup from '@/addon/shop/views/marketing/exchange/components/goods-select-popup.vue'
const diyStore:any = useDiyStore() const diyStore: any = useDiyStore()
diyStore.editComponent.ignore = [] // diyStore.editComponent.ignore = [] //
// //
diyStore.editComponent.verify = (index: number) => { diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' } const res = { code: true, message: '' }
if(diyStore.value[index].source == 'category'){ if (diyStore.value[index].source == 'category') {
if(diyStore.value[index].goods_category == ''){ if (diyStore.value[index].goods_category == '') {
res.code = false res.code = false
res.message = t('goodsCategoryPlaceholder') res.message = t('goodsCategoryPlaceholder')
} }
}else if(diyStore.value[index].source == 'custom'){ } else if (diyStore.value[index].source == 'custom') {
if(diyStore.value[index].goods_ids.length == 0){ if (diyStore.value[index].goods_ids.length == 0) {
res.code = false res.code = false
res.message = t('goodsPlaceholder') res.message = t('goodsPlaceholder')
}
} }
}
return res return res
} }
const goodsSelectPopupRef = ref() const goodsSelectPopupRef = ref()
const goodsSelect = (val:any)=>{ const goodsSelect = (val: any) => {
diyStore.editComponent.goods_ids = val.map((el:any)=>el.id) diyStore.editComponent.goods_ids = val.map((el: any) => el.id)
} }
defineExpose({}) defineExpose({})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

41
admin/src/addon/shop/views/diy/components/edit-shop-exchange-info.vue

@ -1,38 +1,37 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3> <h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('bgUrl')"> <el-form-item :label="t('bgUrl')">
<upload-image v-model="diyStore.editComponent.bgUrl" :limit="1"/> <upload-image v-model="diyStore.editComponent.bgUrl" :limit="1" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
</div> </div>
<!-- 样式 --> <!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'"> <div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 --> <!-- 组件样式 -->
<slot name="style"></slot> <slot name="style"></slot>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { t } from '@/lang' import { t } from '@/lang'
import useDiyStore from '@/stores/modules/diy' import useDiyStore from '@/stores/modules/diy'
const diyStore:any = useDiyStore() const diyStore: any = useDiyStore()
diyStore.editComponent.ignore = ['componentBgColor','componentBgUrl'] // diyStore.editComponent.ignore = ['componentBgColor', 'componentBgUrl'] //
// //
diyStore.editComponent.verify = (index: number) => { diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' } const res = { code: true, message: '' }
return res return res
} }
defineExpose({}) defineExpose({})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

281
admin/src/addon/shop/views/diy/components/edit-shop-goods-ranking.vue

@ -1,83 +1,150 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('activeCubeBlockContent') }}</h3> <h3 class="mb-[10px]">{{ t('activeCubeBlockContent') }}</h3>
<el-form label-width="85px" class="px-[10px]"> <el-form label-width="85px" class="px-[10px]">
<div ref="blockBoxRef">
<div ref="blockBoxRef"> <div
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]"> v-for="(item, index) in diyStore.editComponent.list"
<el-form-item :label="t('bgImage')"> :key="item.id"
<upload-image v-model="item.bgUrl" :limit="1" /> class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]"
</el-form-item> >
<el-form-item :label="t('bgImage')">
<el-form-item :label="t('listFrameColor')"> <upload-image v-model="item.bgUrl" :limit="1" />
<el-color-picker v-model="item.listFrame.startColor" show-alpha :predefine="diyStore.predefineColors" /> </el-form-item>
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
<el-color-picker v-model="item.listFrame.endColor" show-alpha :predefine="diyStore.predefineColors" /> <el-form-item :label="t('listFrameColor')">
</el-form-item> <el-color-picker
v-model="item.listFrame.startColor"
<el-form-item :label="t('rankingTitleIcon')"> show-alpha
<upload-image v-model="item.imgUrl" :limit="1" /> :predefine="diyStore.predefineColors"
</el-form-item> />
<icon
<el-form-item :label="t('rankName')"> name="iconfont iconmap-connect"
<el-input v-model="item.text" clearable :placeholder="t('rankNamePlaceholder')" maxlength="8" show-word-limit /> size="20px"
</el-form-item> class="block !text-gray-400 mx-[5px]"
<el-form-item :label="t('rankTextColor')"> />
<el-color-picker v-model="item.textColor" show-alpha :predefine="diyStore.predefineColors" /> <el-color-picker
</el-form-item> v-model="item.listFrame.endColor"
show-alpha
<el-form-item :label="t('rankingSubTitle')"> :predefine="diyStore.predefineColors"
<el-input v-model.trim="item.subTitle.text" :placeholder="t('activeCubeSubTitlePlaceholder')" clearable maxlength="6" show-word-limit /> />
</el-form-item> </el-form-item>
<el-form-item :label="t('rankingSubTitleTextColor')"> <el-form-item :label="t('rankingTitleIcon')">
<el-color-picker v-model="item.subTitle.textColor" show-alpha :predefine="diyStore.predefineColors" /> <upload-image v-model="item.imgUrl" :limit="1" />
</el-form-item> </el-form-item>
<el-form-item :label="t('rankingSubTitleLink')"> <el-form-item :label="t('rankName')">
<diy-link v-model="item.subTitle.link" /> <el-input
</el-form-item> v-model="item.text"
clearable
<el-form-item :label="t('rankSelectPopupSelectRankButton')"> :placeholder="t('rankNamePlaceholder')"
<el-radio-group v-model="item.source" :title="t('rankSelectPopupSelectRankButton')"> maxlength="8"
<el-radio label="default">{{ t('defaultSources') }}</el-radio> show-word-limit
<el-radio label="custom">{{ t('manualSelectionSources') }}</el-radio> />
</el-radio-group> </el-form-item>
</el-form-item> <el-form-item :label="t('rankTextColor')">
<el-form-item :label="t('customGoods')" v-if="item.source == 'custom'"> <el-color-picker
<rank-select-popup ref="goodsSelectPopupRef" v-model="diyStore.editComponent.list[index].rankIds" :max="1" /> v-model="item.textColor"
</el-form-item> show-alpha
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)"> :predefine="diyStore.predefineColors"
<icon name="element CircleCloseFilled" color="#bbb" size="20px" /> />
</div> </el-form-item>
</div>
</div> <el-form-item :label="t('rankingSubTitle')">
<el-input
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addItem">{{ t('activeCubeAddItem') }}</el-button> v-model.trim="item.subTitle.text"
:placeholder="t('activeCubeSubTitlePlaceholder')"
</el-form> clearable
</div> maxlength="6"
</div> show-word-limit
/>
<!-- 样式 --> </el-form-item>
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap"> <el-form-item :label="t('rankingSubTitleTextColor')">
<h3 class="mb-[10px]">{{ t('rankingStyle') }}</h3> <el-color-picker
<el-form label-width="90px" class="px-[10px]"> v-model="item.subTitle.textColor"
<el-form-item :label="t('topRounded')"> show-alpha
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> :predefine="diyStore.predefineColors"
</el-form-item> />
<el-form-item :label="t('bottomRounded')"> </el-form-item>
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item> <el-form-item :label="t('rankingSubTitleLink')">
</el-form> <diy-link v-model="item.subTitle.link" />
</el-form-item>
<el-form-item :label="t('rankSelectPopupSelectRankButton')">
<el-radio-group
v-model="item.source"
:title="t('rankSelectPopupSelectRankButton')"
>
<el-radio label="default">{{ t('defaultSources') }}</el-radio>
<el-radio label="custom">{{
t('manualSelectionSources')
}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
:label="t('customGoods')"
v-if="item.source == 'custom'"
>
<rank-select-popup
ref="goodsSelectPopupRef"
v-model="diyStore.editComponent.list[index].rankIds"
:max="1"
/>
</el-form-item>
<div
class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
v-show="diyStore.editComponent.list.length > 1"
@click="diyStore.editComponent.list.splice(index, 1)"
>
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
</div>
</div>
</div> </div>
<!-- 组件样式 --> <el-button
<slot name="style"></slot> v-show="diyStore.editComponent.list.length < 10"
class="w-full"
@click="addItem"
>{{ t('activeCubeAddItem') }}</el-button
>
</el-form>
</div> </div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('rankingStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('topRounded')">
<el-slider
v-model="diyStore.editComponent.topElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider
v-model="diyStore.editComponent.bottomElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -87,44 +154,44 @@ import useDiyStore from '@/stores/modules/diy'
import { ref, reactive } from 'vue' import { ref, reactive } from 'vue'
import rankSelectPopup from '@/addon/shop/views/marketing/goods_rank/components/rank-select-popup.vue' import rankSelectPopup from '@/addon/shop/views/marketing/goods_rank/components/rank-select-popup.vue'
const diyStore:any = useDiyStore() const diyStore: any = useDiyStore()
diyStore.editComponent.ignore = ['componentBgUrl'] // diyStore.editComponent.ignore = ['componentBgUrl'] //
// //
diyStore.editComponent.verify = (index: number) => { diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' } const res = { code: true, message: '' }
diyStore.value[index].list.forEach((item: any) => { diyStore.value[index].list.forEach((item: any) => {
if (item.source == 'custom') { if (item.source == 'custom') {
if (item.rankIds.length == 0) { if (item.rankIds.length == 0) {
res.code = false res.code = false
res.message = t('请选择榜单') res.message = t('请选择榜单')
} }
} }
}); })
return res return res
} }
const addItem = () => { const addItem = () => {
diyStore.editComponent.list.push({ diyStore.editComponent.list.push({
id: diyStore.generateRandom(), id: diyStore.generateRandom(),
bgUrl: '', bgUrl: '',
text: '榜单名称', text: '榜单名称',
textColor: "#FFFFFF", textColor: '#FFFFFF',
imgUrl: "", imgUrl: '',
subTitle: { subTitle: {
text: '查看更多', text: '查看更多',
textColor: '#FFFFFF', textColor: '#FFFFFF',
link: { link: {
name: '' name: '',
} },
}, },
listFrame: { listFrame: {
startColor: '#FEA715', startColor: '#FEA715',
endColor: '#FE1E00', endColor: '#FE1E00',
}, },
source: 'default', source: 'default',
rankIds: [] rankIds: [],
}) })
} }
defineExpose({}) defineExpose({})

388
admin/src/addon/shop/views/diy/components/edit-shop-goods-recommend.vue

@ -1,185 +1,281 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t("selectSource") }}</h3> <h3 class="mb-[10px]">{{ t('selectSource') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('goodsSelectPopupSelectGoodsButton')"> <el-form-item :label="t('goodsSelectPopupSelectGoodsButton')">
<el-radio-group v-model="diyStore.editComponent.source" :title="t('goodsSelectPopupSelectGoodsButton')"> <el-radio-group
<el-radio label="all">{{ t('defaultGoodsSelect') }}</el-radio> v-model="diyStore.editComponent.source"
<el-radio label="custom">{{ t('manualSelectionSources') }}</el-radio> :title="t('goodsSelectPopupSelectGoodsButton')"
</el-radio-group> >
</el-form-item> <el-radio label="all">{{ t('defaultGoodsSelect') }}</el-radio>
<el-form-item :label="t('customGoods')" v-if="diyStore.editComponent.source == 'custom'"> <el-radio label="custom">{{
<goods-select-popup ref="goodsSelectPopupRef" v-model="diyStore.editComponent.goods_ids" :min="diyStore.editComponent.list.length" :max="diyStore.editComponent.list.length" /> t('manualSelectionSources')
</el-form-item> }}</el-radio>
</el-form> </el-radio-group>
</div> </el-form-item>
<el-form-item
:label="t('customGoods')"
v-if="diyStore.editComponent.source == 'custom'"
>
<goods-select-popup
ref="goodsSelectPopupRef"
v-model="diyStore.editComponent.goods_ids"
:min="diyStore.editComponent.list.length"
:max="diyStore.editComponent.list.length"
/>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<el-form label-width="120px" class="px-[10px]"> <el-form label-width="120px" class="px-[10px]">
<h3 class="mb-[10px]">{{ t('activeCubeBlockContent') }}</h3> <h3 class="mb-[10px]">{{ t('activeCubeBlockContent') }}</h3>
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p> <p class="text-sm text-gray-400 mb-[10px]">
<div ref="blockBoxRef"> {{ t('dragMouseAdjustOrder') }}
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]"> </p>
<el-form-item :label="t('activeCubeTitle')"> <div ref="blockBoxRef">
<el-input v-model.trim="item.title.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit/> <div
</el-form-item> v-for="(item, index) in diyStore.editComponent.list"
<el-form-item :label="t('shopGoodsRecommendComponentTag')"> :key="item.id"
<el-input v-model.trim="item.moreTitle.text" :placeholder="t('shopGoodsRecommendComponentTagPlaceholder')" clearable maxlength="2" show-word-limit/> class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]"
</el-form-item> >
<el-form-item :label="t('activeCubeButton')"> <el-form-item :label="t('activeCubeTitle')">
<el-input v-model.trim="item.button.text" :placeholder="t('activeCubeButtonPlaceholder')" clearable maxlength="2" show-word-limit/> <el-input
</el-form-item> v-model.trim="item.title.text"
<el-form-item :label="t('activeCubeSubTitleTextColor')"> :placeholder="t('activeCubeTitlePlaceholder')"
<el-color-picker v-model="item.title.textColor" show-alpha :predefine="diyStore.predefineColors" /> clearable
</el-form-item> maxlength="4"
<el-form-item :label="t('shopGoodsRecommendComponentTagcolor')"> show-word-limit
<el-color-picker v-model="item.moreTitle.startColor" show-alpha :predefine="diyStore.predefineColors" /> />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/> </el-form-item>
<el-color-picker v-model="item.moreTitle.endColor" show-alpha :predefine="diyStore.predefineColors"/> <el-form-item :label="t('shopGoodsRecommendComponentTag')">
</el-form-item> <el-input
<el-form-item :label="t('activeCubeButtonColor')"> v-model.trim="item.moreTitle.text"
<el-color-picker v-model="item.button.color" show-alpha :predefine="diyStore.predefineColors" /> :placeholder="t('shopGoodsRecommendComponentTagPlaceholder')"
</el-form-item> clearable
<el-form-item :label="t('activeListFrameColor')"> maxlength="2"
<el-color-picker v-model="item.listFrame.startColor" show-alpha :predefine="diyStore.predefineColors" /> show-word-limit
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/> />
<el-color-picker v-model="item.listFrame.endColor" show-alpha :predefine="diyStore.predefineColors"/> </el-form-item>
</el-form-item> <el-form-item :label="t('activeCubeButton')">
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="deleteTempFn(index)"> <el-input
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/> v-model.trim="item.button.text"
</div> :placeholder="t('activeCubeButtonPlaceholder')"
</div> clearable
</div> maxlength="2"
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addItem">{{ t('activeCubeAddItem') }}</el-button> show-word-limit
</el-form> />
</div> </el-form-item>
</div> <el-form-item :label="t('activeCubeSubTitleTextColor')">
<el-color-picker
v-model="item.title.textColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('shopGoodsRecommendComponentTagcolor')">
<el-color-picker
v-model="item.moreTitle.startColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
<icon
name="iconfont iconmap-connect"
size="20px"
class="block !text-gray-400 mx-[5px]"
/>
<el-color-picker
v-model="item.moreTitle.endColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('activeCubeButtonColor')">
<el-color-picker
v-model="item.button.color"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('activeListFrameColor')">
<el-color-picker
v-model="item.listFrame.startColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
<icon
name="iconfont iconmap-connect"
size="20px"
class="block !text-gray-400 mx-[5px]"
/>
<el-color-picker
v-model="item.listFrame.endColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<div
class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
v-show="diyStore.editComponent.list.length > 1"
@click="deleteTempFn(index)"
>
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
</div>
</div>
</div>
<el-button
v-show="diyStore.editComponent.list.length < 10"
class="w-full"
@click="addItem"
>{{ t('activeCubeAddItem') }}</el-button
>
</el-form>
</div>
</div>
<!-- 样式 --> <!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'"> <div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3> <h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('goodsPriceColor')"> <el-form-item :label="t('goodsPriceColor')">
<el-color-picker v-model="diyStore.editComponent.priceStyle.mainColor" show-alpha :predefine="diyStore.predefineColors" /> <el-color-picker
</el-form-item> v-model="diyStore.editComponent.priceStyle.mainColor"
<el-form-item :label="t('topRounded')"> show-alpha
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> :predefine="diyStore.predefineColors"
</el-form-item> />
<el-form-item :label="t('bottomRounded')"> </el-form-item>
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> <el-form-item :label="t('topRounded')">
</el-form-item> <el-slider
</el-form> v-model="diyStore.editComponent.topElementRounded"
</div> show-input
<!-- 组件样式 --> size="small"
<slot name="style"></slot> class="ml-[10px] diy-nav-slider"
</div> :max="50"
/>
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider
v-model="diyStore.editComponent.bottomElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { t } from '@/lang' import { t } from '@/lang'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import useDiyStore from '@/stores/modules/diy' import useDiyStore from '@/stores/modules/diy'
import { ref, reactive, onMounted,nextTick } from 'vue' import { ref, reactive, onMounted, nextTick } from 'vue'
import goodsSelectPopup from '@/addon/shop/views/goods/components/goods-select-popup.vue' import goodsSelectPopup from '@/addon/shop/views/goods/components/goods-select-popup.vue'
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
import { range } from 'lodash-es' import { range } from 'lodash-es'
const diyStore:any = useDiyStore() const diyStore: any = useDiyStore()
diyStore.editComponent.ignore = ['componentBgUrl'] // diyStore.editComponent.ignore = ['componentBgUrl'] //
// //
diyStore.editComponent.verify = (index: number) => { diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' } const res = { code: true, message: '' }
diyStore.value[index].list.forEach((item: any) => { diyStore.value[index].list.forEach((item: any) => {
if (!item.title.text) { if (!item.title.text) {
res.code = false res.code = false
res.message = t('activeCubeTitlePlaceholder') res.message = t('activeCubeTitlePlaceholder')
return res return res
} }
if (!item.moreTitle.text) { if (!item.moreTitle.text) {
res.code = false res.code = false
res.message = t('shopGoodsRecommendComponentTagPlaceholder') res.message = t('shopGoodsRecommendComponentTagPlaceholder')
return res return res
} }
if (!item.button.text) { if (!item.button.text) {
res.code = false res.code = false
res.message = t('activeCubeButtonPlaceholder') res.message = t('activeCubeButtonPlaceholder')
return res return res
}
})
if (diyStore.value[index].source == 'custom' && diyStore.value[index].goods_ids.length < diyStore.value[index].list.length) {
res.code = false
res.message = t('goodsPlaceholder')
return res
} }
})
if (
diyStore.value[index].source == 'custom' &&
diyStore.value[index].goods_ids.length < diyStore.value[index].list.length
) {
res.code = false
res.message = t('goodsPlaceholder')
return res return res
}
return res
} }
diyStore.editComponent.list.forEach((item: any) => { diyStore.editComponent.list.forEach((item: any) => {
if (!item.id) item.id = diyStore.generateRandom() if (!item.id) item.id = diyStore.generateRandom()
}) })
const blockBoxRef = ref() const blockBoxRef = ref()
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
const sortable = Sortable.create(blockBoxRef.value, { const sortable = Sortable.create(blockBoxRef.value, {
group: 'item-wrap', group: 'item-wrap',
animation: 200, animation: 200,
onEnd: event => { onEnd: (event) => {
const temp = diyStore.editComponent.list[event.oldIndex!] const temp = diyStore.editComponent.list[event.oldIndex!]
diyStore.editComponent.list.splice(event.oldIndex!, 1) diyStore.editComponent.list.splice(event.oldIndex!, 1)
diyStore.editComponent.list.splice(event.newIndex!, 0, temp) diyStore.editComponent.list.splice(event.newIndex!, 0, temp)
sortable.sort( sortable.sort(
range(diyStore.editComponent.list.length).map(value => { range(diyStore.editComponent.list.length).map((value) => {
return value.toString() return value.toString()
}) })
) )
} },
})
let listNum = diyStore.editComponent.list.length;
let goodsIdNum = diyStore.editComponent.goods_ids.length;
diyStore.editComponent.goods_ids.splice(listNum, goodsIdNum);
}) })
let listNum = diyStore.editComponent.list.length
let goodsIdNum = diyStore.editComponent.goods_ids.length
diyStore.editComponent.goods_ids.splice(listNum, goodsIdNum)
})
}) })
const addItem = () => { const addItem = () => {
diyStore.editComponent.list.push({ diyStore.editComponent.list.push({
id: diyStore.generateRandom(), id: diyStore.generateRandom(),
title: { title: {
text: '标题', text: '标题',
textColor: '#303133' textColor: '#303133',
}, },
moreTitle: { moreTitle: {
text: '精选', text: '精选',
startColor: '#FF7234', startColor: '#FF7234',
endColor: '#FF213F' endColor: '#FF213F',
}, },
listFrame: { listFrame: {
startColor: '#FFE5E5', startColor: '#FFE5E5',
endColor: '#FFF5F0' endColor: '#FFF5F0',
}, },
button : { button: {
text: "首单", text: '首单',
textColor: "#FFFFFF", textColor: '#FFFFFF',
color: "#FF1128", color: '#FF1128',
}, },
goodsId: [], goodsId: [],
}) })
} }
const deleteTempFn = (index) =>{ const deleteTempFn = (index) => {
diyStore.editComponent.list.splice(index,1); diyStore.editComponent.list.splice(index, 1)
diyStore.editComponent.goods_ids.splice(index,1); diyStore.editComponent.goods_ids.splice(index, 1)
} }
defineExpose({}) defineExpose({})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

71
admin/src/addon/shop/views/diy/components/edit-shop-member-info.vue

@ -1,41 +1,41 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3> <h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('bgUrl')"> <el-form-item :label="t('bgUrl')">
<upload-image v-model="diyStore.editComponent.bgUrl" :limit="1"/> <upload-image v-model="diyStore.editComponent.bgUrl" :limit="1" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('shopMemberInfoComponentAccount')"> <el-form-item :label="t('shopMemberInfoComponentAccount')">
<el-switch v-model="diyStore.editComponent.isShowAccount" /> <el-switch v-model="diyStore.editComponent.isShowAccount" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
</div> </div>
<!-- 样式 --> <!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'"> <div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3> <h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textColor')"> <el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor"/> <el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('shopMemberInfoComponentUidTextColor')">
<el-color-picker v-model="diyStore.editComponent.uidTextColor"/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 --> <el-form label-width="80px" class="px-[10px]">
<slot name="style"></slot> <el-form-item :label="t('shopMemberInfoComponentUidTextColor')">
</div> <el-color-picker v-model="diyStore.editComponent.uidTextColor" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -46,7 +46,6 @@ const diyStore = useDiyStore()
diyStore.editComponent.ignore = ['componentBgUrl'] // diyStore.editComponent.ignore = ['componentBgUrl'] //
defineExpose({}) defineExpose({})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

609
admin/src/addon/shop/views/diy/components/edit-shop-newcomer.vue

@ -1,116 +1,232 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('styleRecommend') }}</h3> <h3 class="mb-[10px]">{{ t('styleRecommend') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('selectStyle')" class="flex"> <el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer" @click="showTitleStyle">{{ diyStore.editComponent.style.title }}</span> <span
<el-icon> class="text-primary flex-1 cursor-pointer"
<ArrowRight /> @click="showTitleStyle"
</el-icon> >{{ diyStore.editComponent.style.title }}</span
</el-form-item> >
</el-form> <el-icon>
<ArrowRight />
</el-icon>
</el-form-item>
</el-form>
<el-dialog v-model="showTitleDialog" :title="t('selectStyle')" width="460px"> <el-dialog
<div class="flex flex-wrap"> v-model="showTitleDialog"
<template v-for="(item,index) in styleList" :key="index"> :title="t('selectStyle')"
<div :class="{ 'border-primary': selectStyle.value == item.value }" @click="changeTitleStyle(item)" class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] mb-[12px] cursor-pointer border bg-[#eee]"> width="460px"
<img :src="img(item.url)" /> >
</div> <div class="flex flex-wrap">
</template> <template v-for="(item, index) in styleList" :key="index">
</div> <div
<template #footer> :class="{ 'border-primary': selectStyle.value == item.value }"
<span class="dialog-footer"> @click="changeTitleStyle(item)"
<el-button @click="showTitleDialog = false">{{ t('cancel') }}</el-button> class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] mb-[12px] cursor-pointer border bg-[#eee]"
<el-button type="primary" @click="confirmTitleStyle">{{ t('confirm') }}</el-button> >
</span> <img :src="img(item.url)" />
</template> </div>
</template>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="showTitleDialog = false">{{
t('cancel')
}}</el-button>
<el-button type="primary" @click="confirmTitleStyle">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</div>
</el-dialog> <div class="edit-attr-item-wrap">
</div> <h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('image')">
<upload-image v-model="diyStore.editComponent.textImg" :limit="1" />
</el-form-item>
<el-form-item
:label="t('subTitle')"
v-show="
diyStore.editComponent &&
diyStore.editComponent.style &&
diyStore.editComponent.style.value == 'style-3'
"
>
<el-input
v-model.trim="diyStore.editComponent.subTitle.text"
:placeholder="t('subTitlePlaceholder')"
clearable
maxlength="8"
show-word-limit
/>
</el-form-item>
<el-form-item
:label="t('link')"
v-show="
diyStore.editComponent &&
diyStore.editComponent.style &&
diyStore.editComponent.style.value == 'style-3'
"
>
<diy-link v-model="diyStore.editComponent.subTitle.link" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3> <h3 class="mb-[10px]">{{ t('selectSource') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('image')"> <el-form-item :label="t('goodsSelectPopupSelectGoodsButton')">
<upload-image v-model="diyStore.editComponent.textImg" :limit="1"/> <el-radio-group
</el-form-item> v-model="diyStore.editComponent.source"
<el-form-item :label="t('subTitle')" v-show="diyStore.editComponent && diyStore.editComponent.style && diyStore.editComponent.style.value == 'style-3'"> :title="t('goodsSelectPopupSelectGoodsButton')"
<el-input v-model.trim="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit /> >
</el-form-item> <el-radio label="all">{{ t('goodsSelectPopupAllGoods') }}</el-radio>
<el-form-item :label="t('link')" v-show="diyStore.editComponent && diyStore.editComponent.style && diyStore.editComponent.style.value == 'style-3'"> <el-radio label="custom">{{
<diy-link v-model="diyStore.editComponent.subTitle.link"/> t('manualSelectionSources')
</el-form-item> }}</el-radio>
</el-form> </el-radio-group>
</div> </el-form-item>
<el-form-item
:label="t('goodsNum')"
v-if="
diyStore.editComponent.source == 'all' ||
diyStore.editComponent.source == 'category'
"
>
<el-slider
class="goods-list-slider"
show-input
v-model="diyStore.editComponent.num"
:min="1"
max="20"
size="small"
/>
</el-form-item>
<el-form-item
:label="t('customGoods')"
v-if="diyStore.editComponent.source == 'custom'"
>
<newcomer-goods-select-popup
ref="goodsSelectPopupRef"
v-model="diyStore.editComponent.goods_ids"
:min="1"
:max="99"
mode="sku"
/>
</el-form-item>
</el-form>
</div>
</div>
<div class="edit-attr-item-wrap"> <!-- 样式 -->
<h3 class="mb-[10px]">{{ t("selectSource") }}</h3> <div class="style-wrap" v-show="diyStore.editTab == 'style'">
<el-form label-width="80px" class="px-[10px]"> <div class="edit-attr-item-wrap">
<el-form-item :label="t('goodsSelectPopupSelectGoodsButton')"> <h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3>
<el-radio-group v-model="diyStore.editComponent.source" :title="t('goodsSelectPopupSelectGoodsButton')"> <el-form label-width="80px" class="px-[10px]">
<el-radio label="all">{{ t('goodsSelectPopupAllGoods') }}</el-radio> <el-form-item :label="t('topRounded')">
<el-radio label="custom">{{ t('manualSelectionSources') }}</el-radio> <el-slider
</el-radio-group> v-model="diyStore.editComponent.topElementRounded"
</el-form-item> show-input
<el-form-item :label="t('goodsNum')" v-if="diyStore.editComponent.source == 'all' || diyStore.editComponent.source == 'category'"> size="small"
<el-slider class="goods-list-slider" show-input v-model="diyStore.editComponent.num" :min="1" max="20" size="small" /> class="ml-[10px] diy-nav-slider"
</el-form-item> :max="50"
<el-form-item :label="t('customGoods')" v-if="diyStore.editComponent.source == 'custom'"> />
<newcomer-goods-select-popup ref="goodsSelectPopupRef" v-model="diyStore.editComponent.goods_ids" :min="1" :max="99" mode="sku" /> </el-form-item>
</el-form-item> <el-form-item :label="t('bottomRounded')">
</el-form> <el-slider
v-model="diyStore.editComponent.bottomElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
</el-form>
</div>
<div
class="edit-attr-item-wrap"
v-if="
diyStore.editComponent &&
diyStore.editComponent.style &&
diyStore.editComponent.style.value == 'style-3'
"
>
<h3 class="mb-[10px]">{{ t('subTitleStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('textColor')">
<el-color-picker
v-model="diyStore.editComponent.subTitle.textColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('subTextBgColor')">
<el-color-picker
v-model="diyStore.editComponent.subTitle.startColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
<icon
name="iconfont iconmap-connect"
size="20px"
class="block !text-gray-400 mx-[5px]"
/>
<el-color-picker
v-model="diyStore.editComponent.subTitle.endColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('countDownStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('newcomerNumberColor')">
<el-color-picker
v-model="diyStore.editComponent.countDown.numberColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('newcomerNumberBg')">
<el-color-picker
v-model="diyStore.editComponent.countDown.numberBg.startColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
<icon
name="iconfont iconmap-connect"
size="20px"
class="block !text-gray-400 mx-[5px]"
/>
<el-color-picker
v-model="diyStore.editComponent.countDown.numberBg.endColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('newcomerOtherColor')">
<el-color-picker
v-model="diyStore.editComponent.countDown.otherColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
</el-form>
</div>
</div> <!-- 组件样式 -->
</div> <slot name="style"></slot>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('topRounded')">
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-if="diyStore.editComponent && diyStore.editComponent.style && diyStore.editComponent.style.value == 'style-3'">
<h3 class="mb-[10px]">{{ t('subTitleStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.subTitle.textColor" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
<el-form-item :label="t('subTextBgColor')">
<el-color-picker v-model="diyStore.editComponent.subTitle.startColor" show-alpha :predefine="diyStore.predefineColors"/>
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
<el-color-picker v-model="diyStore.editComponent.subTitle.endColor" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('countDownStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('newcomerNumberColor')">
<el-color-picker v-model="diyStore.editComponent.countDown.numberColor" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
<el-form-item :label="t('newcomerNumberBg')">
<el-color-picker v-model="diyStore.editComponent.countDown.numberBg.startColor" show-alpha :predefine="diyStore.predefineColors"/>
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
<el-color-picker v-model="diyStore.editComponent.countDown.numberBg.endColor" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
<el-form-item :label="t('newcomerOtherColor')">
<el-color-picker v-model="diyStore.editComponent.countDown.otherColor" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -120,174 +236,183 @@ import useDiyStore from '@/stores/modules/diy'
import { ref, reactive } from 'vue' import { ref, reactive } from 'vue'
import newcomerGoodsSelectPopup from '@/addon/shop/views/goods/components/newcomer-goods-select-popup.vue' import newcomerGoodsSelectPopup from '@/addon/shop/views/goods/components/newcomer-goods-select-popup.vue'
const diyStore:any = useDiyStore() const diyStore: any = useDiyStore()
diyStore.editComponent.ignore = ['componentBgUrl'] // diyStore.editComponent.ignore = ['componentBgUrl'] //
// //
diyStore.editComponent.verify = (index: number) => { diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' } const res = { code: true, message: '' }
if(diyStore.value[index].source == 'custom'){ if (diyStore.value[index].source == 'custom') {
if(diyStore.value[index].goods_ids.length == 0){ if (diyStore.value[index].goods_ids.length == 0) {
res.code = false res.code = false
res.message = t('goodsPlaceholder') res.message = t('goodsPlaceholder')
}
} }
}
return res return res
} }
// //
const showTitleDialog = ref(false) const showTitleDialog = ref(false)
const showTitleStyle = () => { const showTitleStyle = () => {
selectStyle.title = diyStore.editComponent.style.title; selectStyle.title = diyStore.editComponent.style.title
selectStyle.value = diyStore.editComponent.style.value; selectStyle.value = diyStore.editComponent.style.value
showTitleDialog.value = true showTitleDialog.value = true
} }
const changeTitleStyle = (item:any) => { const changeTitleStyle = (item: any) => {
selectStyle.title = item.title; selectStyle.title = item.title
selectStyle.value = item.value; selectStyle.value = item.value
} }
const confirmTitleStyle = () => { const confirmTitleStyle = () => {
diyStore.editComponent.style.title = selectStyle.title; diyStore.editComponent.style.title = selectStyle.title
diyStore.editComponent.style.value = selectStyle.value; diyStore.editComponent.style.value = selectStyle.value
initStyle(diyStore.editComponent.style.value); initStyle(diyStore.editComponent.style.value)
showTitleDialog.value = false showTitleDialog.value = false
} }
const styleList = reactive([ const styleList = reactive([
{ {
url : 'addon/shop/diy/newcomer/style_01.png', url: 'addon/shop/diy/newcomer/style_01.png',
title:'风格1', title: '风格1',
value:'style-1' value: 'style-1',
},{ },
url : 'addon/shop/diy/newcomer/style_02.png', {
title:'风格2', url: 'addon/shop/diy/newcomer/style_02.png',
value:'style-2' title: '风格2',
},{ value: 'style-2',
url : 'addon/shop/diy/newcomer/style_03.png', },
title:'风格3', {
value:'style-3' url: 'addon/shop/diy/newcomer/style_03.png',
},{ title: '风格3',
url : 'addon/shop/diy/newcomer/style_04.png', value: 'style-3',
title:'风格4', },
value:'style-4' {
} url: 'addon/shop/diy/newcomer/style_04.png',
title: '风格4',
value: 'style-4',
},
]) ])
const initStyle = (style: any) => { const initStyle = (style: any) => {
if (style == 'style-1') { if (style == 'style-1') {
diyStore.editComponent.textImg = "addon/shop/diy/newcomer/style_title_01.png"; diyStore.editComponent.textImg =
diyStore.editComponent.countDown.numberColor = "rgba(255, 0, 0, 1)"; 'addon/shop/diy/newcomer/style_title_01.png'
diyStore.editComponent.countDown.numberBg.startColor = "rgba(255, 255, 255, 1)"; diyStore.editComponent.countDown.numberColor = 'rgba(255, 0, 0, 1)'
diyStore.editComponent.countDown.numberBg.endColor = ""; diyStore.editComponent.countDown.numberBg.startColor =
diyStore.editComponent.countDown.otherColor = "rgba(255, 255, 255, 1)"; 'rgba(255, 255, 255, 1)'
diyStore.editComponent.textColor = "#303133"; diyStore.editComponent.countDown.numberBg.endColor = ''
diyStore.editComponent.pageStartBgColor = ""; diyStore.editComponent.countDown.otherColor = 'rgba(255, 255, 255, 1)'
diyStore.editComponent.pageEndBgColor = ""; diyStore.editComponent.textColor = '#303133'
diyStore.editComponent.pageGradientAngle = "to bottom"; diyStore.editComponent.pageStartBgColor = ''
diyStore.editComponent.componentStartBgColor = "#ff6D1A"; diyStore.editComponent.pageEndBgColor = ''
diyStore.editComponent.componentEndBgColor = "rgba(255, 70, 56, 1)"; diyStore.editComponent.pageGradientAngle = 'to bottom'
diyStore.editComponent.componentGradientAngle = "to right"; diyStore.editComponent.componentStartBgColor = '#ff6D1A'
diyStore.editComponent.bottomRounded = 12; diyStore.editComponent.componentEndBgColor = 'rgba(255, 70, 56, 1)'
diyStore.editComponent.topRounded = 12; diyStore.editComponent.componentGradientAngle = 'to right'
diyStore.editComponent.elementBgColor = ""; diyStore.editComponent.bottomRounded = 12
diyStore.editComponent.bottomElementRounded = 10; diyStore.editComponent.topRounded = 12
diyStore.editComponent.topElementRounded = 10; diyStore.editComponent.elementBgColor = ''
diyStore.editComponent.margin.top = 10; diyStore.editComponent.bottomElementRounded = 10
diyStore.editComponent.margin.bottom = 0; diyStore.editComponent.topElementRounded = 10
diyStore.editComponent.margin.both = 10; diyStore.editComponent.margin.top = 10
} else if (style == 'style-2') { diyStore.editComponent.margin.bottom = 0
diyStore.editComponent.textImg = "addon/shop/diy/newcomer/style_title_02.png"; diyStore.editComponent.margin.both = 10
diyStore.editComponent.countDown.numberColor = "rgba(255, 255, 255, 1)"; } else if (style == 'style-2') {
diyStore.editComponent.countDown.numberBg.startColor = "rgba(255, 44, 54, 1)"; diyStore.editComponent.textImg =
diyStore.editComponent.countDown.numberBg.endColor = ""; 'addon/shop/diy/newcomer/style_title_02.png'
diyStore.editComponent.countDown.otherColor = "rgba(102, 102, 102, 1)"; diyStore.editComponent.countDown.numberColor = 'rgba(255, 255, 255, 1)'
diyStore.editComponent.textColor = "#303133"; diyStore.editComponent.countDown.numberBg.startColor =
diyStore.editComponent.pageStartBgColor = ""; 'rgba(255, 44, 54, 1)'
diyStore.editComponent.pageEndBgColor = ""; diyStore.editComponent.countDown.numberBg.endColor = ''
diyStore.editComponent.pageGradientAngle = "to bottom"; diyStore.editComponent.countDown.otherColor = 'rgba(102, 102, 102, 1)'
diyStore.editComponent.componentStartBgColor = "rgba(255, 255, 255, 1)"; diyStore.editComponent.textColor = '#303133'
diyStore.editComponent.componentEndBgColor = ""; diyStore.editComponent.pageStartBgColor = ''
diyStore.editComponent.componentGradientAngle = "to bottom"; diyStore.editComponent.pageEndBgColor = ''
diyStore.editComponent.bottomRounded = 12; diyStore.editComponent.pageGradientAngle = 'to bottom'
diyStore.editComponent.topRounded = 12; diyStore.editComponent.componentStartBgColor = 'rgba(255, 255, 255, 1)'
diyStore.editComponent.elementBgColor = ""; diyStore.editComponent.componentEndBgColor = ''
diyStore.editComponent.bottomElementRounded = 5; diyStore.editComponent.componentGradientAngle = 'to bottom'
diyStore.editComponent.topElementRounded = 5; diyStore.editComponent.bottomRounded = 12
diyStore.editComponent.margin.top = 10; diyStore.editComponent.topRounded = 12
diyStore.editComponent.margin.bottom = 0; diyStore.editComponent.elementBgColor = ''
diyStore.editComponent.margin.both = 10; diyStore.editComponent.bottomElementRounded = 5
} else if (style == 'style-3') { diyStore.editComponent.topElementRounded = 5
diyStore.editComponent.textImg = "addon/shop/diy/newcomer/style_title_03.png"; diyStore.editComponent.margin.top = 10
diyStore.editComponent.subTitle.text = "查看更多"; diyStore.editComponent.margin.bottom = 0
diyStore.editComponent.subTitle.textColor = "rgba(239, 0, 12, 1)"; diyStore.editComponent.margin.both = 10
diyStore.editComponent.subTitle.startColor = "rgba(255, 248, 217, 1)"; } else if (style == 'style-3') {
diyStore.editComponent.subTitle.endColor = "rgba(255, 254, 251, 1)"; diyStore.editComponent.textImg =
diyStore.editComponent.subTitle.link.name = ""; 'addon/shop/diy/newcomer/style_title_03.png'
diyStore.editComponent.countDown.numberColor = "rgba(239, 0, 12, 1)"; diyStore.editComponent.subTitle.text = '查看更多'
diyStore.editComponent.countDown.numberBg.startColor = "rgba(255, 248, 217, 1)"; diyStore.editComponent.subTitle.textColor = 'rgba(239, 0, 12, 1)'
diyStore.editComponent.countDown.numberBg.endColor = "rgba(255, 253, 246, 1)"; diyStore.editComponent.subTitle.startColor = 'rgba(255, 248, 217, 1)'
diyStore.editComponent.countDown.otherColor = "rgba(255, 253, 246, 1)"; diyStore.editComponent.subTitle.endColor = 'rgba(255, 254, 251, 1)'
diyStore.editComponent.textColor = "#303133"; diyStore.editComponent.subTitle.link.name = ''
diyStore.editComponent.pageStartBgColor = ""; diyStore.editComponent.countDown.numberColor = 'rgba(239, 0, 12, 1)'
diyStore.editComponent.pageEndBgColor = ""; diyStore.editComponent.countDown.numberBg.startColor =
diyStore.editComponent.pageGradientAngle = "to bottom"; 'rgba(255, 248, 217, 1)'
diyStore.editComponent.componentStartBgColor = "rgba(255, 12, 16, 1)"; diyStore.editComponent.countDown.numberBg.endColor =
diyStore.editComponent.componentEndBgColor = "rgba(255, 101, 18, 1)"; 'rgba(255, 253, 246, 1)'
diyStore.editComponent.componentGradientAngle = "to right"; diyStore.editComponent.countDown.otherColor = 'rgba(255, 253, 246, 1)'
diyStore.editComponent.bottomRounded = 12; diyStore.editComponent.textColor = '#303133'
diyStore.editComponent.topRounded = 12; diyStore.editComponent.pageStartBgColor = ''
diyStore.editComponent.elementBgColor = ""; diyStore.editComponent.pageEndBgColor = ''
diyStore.editComponent.bottomElementRounded = 0; diyStore.editComponent.pageGradientAngle = 'to bottom'
diyStore.editComponent.topElementRounded = 0; diyStore.editComponent.componentStartBgColor = 'rgba(255, 12, 16, 1)'
diyStore.editComponent.margin.top = 10; diyStore.editComponent.componentEndBgColor = 'rgba(255, 101, 18, 1)'
diyStore.editComponent.margin.bottom = 0; diyStore.editComponent.componentGradientAngle = 'to right'
diyStore.editComponent.margin.both = 10; diyStore.editComponent.bottomRounded = 12
} else if (style == 'style-4') { diyStore.editComponent.topRounded = 12
diyStore.editComponent.textImg = "addon/shop/diy/newcomer/style_title_02.png"; diyStore.editComponent.elementBgColor = ''
diyStore.editComponent.countDown.numberColor = "rgba(255, 255, 255, 1)"; diyStore.editComponent.bottomElementRounded = 0
diyStore.editComponent.countDown.numberBg.startColor = ""; diyStore.editComponent.topElementRounded = 0
diyStore.editComponent.countDown.numberBg.endColor = ""; diyStore.editComponent.margin.top = 10
diyStore.editComponent.countDown.otherColor = "rgba(255, 253, 253, 1)"; diyStore.editComponent.margin.bottom = 0
diyStore.editComponent.textColor = "#303133"; diyStore.editComponent.margin.both = 10
diyStore.editComponent.pageStartBgColor = ""; } else if (style == 'style-4') {
diyStore.editComponent.pageEndBgColor = ""; diyStore.editComponent.textImg =
diyStore.editComponent.pageGradientAngle = "to bottom"; 'addon/shop/diy/newcomer/style_title_02.png'
diyStore.editComponent.componentStartBgColor = "rgba(255, 255, 255, 1)"; diyStore.editComponent.countDown.numberColor = 'rgba(255, 255, 255, 1)'
diyStore.editComponent.componentEndBgColor = "rgba(255, 255, 255, 1)"; diyStore.editComponent.countDown.numberBg.startColor = ''
diyStore.editComponent.componentGradientAngle = "to bottom"; diyStore.editComponent.countDown.numberBg.endColor = ''
diyStore.editComponent.bottomRounded = 12; diyStore.editComponent.countDown.otherColor = 'rgba(255, 253, 253, 1)'
diyStore.editComponent.topRounded = 12; diyStore.editComponent.textColor = '#303133'
diyStore.editComponent.elementBgColor = ""; diyStore.editComponent.pageStartBgColor = ''
diyStore.editComponent.bottomElementRounded = 10; diyStore.editComponent.pageEndBgColor = ''
diyStore.editComponent.topElementRounded = 10; diyStore.editComponent.pageGradientAngle = 'to bottom'
diyStore.editComponent.margin.top = 10; diyStore.editComponent.componentStartBgColor = 'rgba(255, 255, 255, 1)'
diyStore.editComponent.margin.bottom = 0; diyStore.editComponent.componentEndBgColor = 'rgba(255, 255, 255, 1)'
diyStore.editComponent.margin.both = 10; diyStore.editComponent.componentGradientAngle = 'to bottom'
} diyStore.editComponent.bottomRounded = 12
diyStore.editComponent.topRounded = 12
diyStore.editComponent.elementBgColor = ''
diyStore.editComponent.bottomElementRounded = 10
diyStore.editComponent.topElementRounded = 10
diyStore.editComponent.margin.top = 10
diyStore.editComponent.margin.bottom = 0
diyStore.editComponent.margin.both = 10
}
} }
const selectStyle = reactive({ const selectStyle = reactive({
title: diyStore.editComponent.style.title, title: diyStore.editComponent.style.title,
value: diyStore.editComponent.style.value value: diyStore.editComponent.style.value,
}) })
initStyle(diyStore.editComponent.style.value); initStyle(diyStore.editComponent.style.value)
defineExpose({}) defineExpose({})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
<style lang="scss"> <style lang="scss">
.goods-list-slider { .goods-list-slider {
.el-slider__input { .el-slider__input {
width: 100px; width: 100px;
} }
} }
</style> </style>

205
admin/src/addon/shop/views/diy/components/edit-shop-order-info.vue

@ -1,78 +1,104 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3> <h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('title')"> <el-form-item :label="t('title')">
<el-input v-model.trim="diyStore.editComponent.text" :placeholder="t('titlePlaceholder')" clearable maxlength="6" show-word-limit /> <el-input
</el-form-item> v-model.trim="diyStore.editComponent.text"
</el-form> :placeholder="t('titlePlaceholder')"
</div> clearable
maxlength="6"
<div class="edit-attr-item-wrap"> show-word-limit
<h3 class="mb-[10px]">{{ t('subTitle') }}</h3> />
<el-form label-width="80px" class="px-[10px]"> </el-form-item>
<el-form-item :label="t('more')"> </el-form>
<el-input v-model.trim="diyStore.editComponent.more.text" :placeholder="t('morePlaceholder')" clearable maxlength="8" show-word-limit /> </div>
</el-form-item>
</el-form> <div class="edit-attr-item-wrap">
</div> <h3 class="mb-[10px]">{{ t('subTitle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
</div> <el-form-item :label="t('more')">
<el-input
<!-- 样式 --> v-model.trim="diyStore.editComponent.more.text"
<div class="style-wrap" v-show="diyStore.editTab == 'style'"> :placeholder="t('morePlaceholder')"
clearable
<div class="edit-attr-item-wrap"> maxlength="8"
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3> show-word-limit
<el-form label-width="80px" class="px-[10px]"> />
<el-form-item :label="t('textFontSize')"> </el-form-item>
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="30" /> </el-form>
</el-form-item> </div>
<el-form-item :label="t('textFontWeight')"> </div>
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio> <!-- 样式 -->
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio> <div class="style-wrap" v-show="diyStore.editTab == 'style'">
</el-radio-group> <div class="edit-attr-item-wrap">
</el-form-item> <h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
<el-form-item :label="t('textColor')"> <el-form label-width="80px" class="px-[10px]">
<el-color-picker v-model="diyStore.editComponent.textColor" /> <el-form-item :label="t('textFontSize')">
</el-form-item> <el-slider
</el-form> v-model="diyStore.editComponent.fontSize"
</div> show-input
size="small"
<div class="edit-attr-item-wrap"> class="ml-[10px] diy-nav-slider"
<h3 class="mb-[10px]">{{ t('subTitleStyle') }}</h3> :min="12"
<el-form label-width="80px" class="px-[10px]"> :max="30"
<el-form-item :label="t('textColor')"> />
<el-color-picker v-model="diyStore.editComponent.more.color" /> </el-form-item>
</el-form-item> <el-form-item :label="t('textFontWeight')">
</el-form> <el-radio-group v-model="diyStore.editComponent.fontWeight">
</div> <el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
<div class="edit-attr-item-wrap"> </el-radio-group>
<h3 class="mb-[10px]">{{ t('textSet') }}</h3> </el-form-item>
<el-form label-width="90px" class="px-[10px]"> <el-form-item :label="t('textColor')">
<el-form-item :label="t('textFontSize')"> <el-color-picker v-model="diyStore.editComponent.textColor" />
<el-slider v-model="diyStore.editComponent.item.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16"/> </el-form-item>
</el-form-item> </el-form>
<el-form-item :label="t('textFontWeight')"> </div>
<el-radio-group v-model="diyStore.editComponent.item.fontWeight">
<el-radio :label="'normal'">{{t('fontWeightNormal')}}</el-radio> <div class="edit-attr-item-wrap">
<el-radio :label="'bold'">{{t('fontWeightBold')}}</el-radio> <h3 class="mb-[10px]">{{ t('subTitleStyle') }}</h3>
</el-radio-group> <el-form label-width="80px" class="px-[10px]">
</el-form-item> <el-form-item :label="t('textColor')">
<el-form-item :label="t('textColor')"> <el-color-picker v-model="diyStore.editComponent.more.color" />
<el-color-picker v-model="diyStore.editComponent.item.color" show-alpha :predefine="diyStore.predefineColors"/> </el-form-item>
</el-form-item> </el-form>
</div>
</el-form>
</div> <div class="edit-attr-item-wrap">
<!-- 组件样式 --> <h3 class="mb-[10px]">{{ t('textSet') }}</h3>
<slot name="style"></slot> <el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
</div> <el-slider
v-model="diyStore.editComponent.item.fontSize"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:min="12"
:max="16"
/>
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.item.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker
v-model="diyStore.editComponent.item.color"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -86,30 +112,29 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
const showDialog = ref(false) const showDialog = ref(false)
const showStyle = () => { const showStyle = () => {
showDialog.value = true showDialog.value = true
} }
const selectStyle = ref(diyStore.editComponent.style) const selectStyle = ref(diyStore.editComponent.style)
const changeStyle = () => { const changeStyle = () => {
switch (selectStyle.value) { switch (selectStyle.value) {
case 'style-1': case 'style-1':
diyStore.editComponent.subTitle.control = false diyStore.editComponent.subTitle.control = false
diyStore.editComponent.more.control = false diyStore.editComponent.more.control = false
diyStore.editComponent.styleName = '风格1' diyStore.editComponent.styleName = '风格1'
break break
case 'style-2': case 'style-2':
diyStore.editComponent.subTitle.control = true diyStore.editComponent.subTitle.control = true
diyStore.editComponent.more.control = true diyStore.editComponent.more.control = true
diyStore.editComponent.styleName = '风格2' diyStore.editComponent.styleName = '风格2'
break break
} }
diyStore.editComponent.style = selectStyle.value diyStore.editComponent.style = selectStyle.value
showDialog.value = false showDialog.value = false
} }
defineExpose({}) defineExpose({})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

43
admin/src/addon/shop/views/diy/components/edit-shop-search.vue

@ -1,24 +1,27 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<div class="edit-attr-item-wrap"> <h3 class="mb-[10px]">{{ t('goodsSearchSet') }}</h3>
<h3 class="mb-[10px]">{{ t('goodsSearchSet') }}</h3> <el-form label-width="100px" class="px-[10px]">
<el-form label-width="100px" class="px-[10px]"> <el-form-item :label="t('goodsSearchText')">
<el-form-item :label="t('goodsSearchText')"> <el-input
<el-input v-model.trim="diyStore.editComponent.text" :placeholder="t('goodsSearchTextPlaceholder')" clearable maxlength="20" show-word-limit /> v-model.trim="diyStore.editComponent.text"
</el-form-item> :placeholder="t('goodsSearchTextPlaceholder')"
</el-form> clearable
</div> maxlength="20"
show-word-limit
</div> />
</el-form-item>
<!-- 样式 --> </el-form>
<div class="style-wrap" v-show="diyStore.editTab == 'style'"> </div>
<!-- 组件样式 --> </div>
<slot name="style"></slot>
</div> <!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

639
admin/src/addon/shop/views/diy/components/edit-single-recommend.vue

@ -1,188 +1,313 @@
<template> <template>
<!-- 内容 --> <!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'"> <div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap"> <div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3> <h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
<el-form label-width="80px" class="px-[10px]"> <el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('selectStyle')" class="flex"> <el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer" @click="showTitleStyle">{{ diyStore.editComponent.titleStyle.title }}</span> <span
<el-icon> class="text-primary flex-1 cursor-pointer"
<ArrowRight /> @click="showTitleStyle"
</el-icon> >{{ diyStore.editComponent.titleStyle.title }}</span
</el-form-item> >
<el-form-item :label="t('image')"> <el-icon>
<upload-image v-model="diyStore.editComponent.textImg" :limit="1"/> <ArrowRight />
</el-form-item> </el-icon>
<el-form-item :label="t('link')"> </el-form-item>
<diy-link v-model="diyStore.editComponent.textLink"/> <el-form-item :label="t('image')">
</el-form-item> <upload-image v-model="diyStore.editComponent.textImg" :limit="1" />
<el-form-item :label="t('subTitle')"> </el-form-item>
<el-input v-model.trim="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit /> <el-form-item :label="t('link')">
</el-form-item> <diy-link v-model="diyStore.editComponent.textLink" />
<el-form-item :label="t('link')"> </el-form-item>
<diy-link v-model="diyStore.editComponent.subTitle.link"/> <el-form-item :label="t('subTitle')">
</el-form-item> <el-input
</el-form> v-model.trim="diyStore.editComponent.subTitle.text"
:placeholder="t('subTitlePlaceholder')"
<el-dialog v-model="showTitleDialog" :title="t('selectStyle')" width="460px"> clearable
maxlength="8"
<div class="flex flex-wrap"> show-word-limit
<template v-for="(item,index) in titleStyleList" :key="index"> />
<div :class="{ 'border-primary': selectTitleStyle.value == item.value }" @click="changeTitleStyle(item)" class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] mb-[12px] cursor-pointer border bg-[#eee]"> </el-form-item>
<img :src="img(item.url)" /> <el-form-item :label="t('link')">
</div> <diy-link v-model="diyStore.editComponent.subTitle.link" />
</template> </el-form-item>
</div> </el-form>
<template #footer> <el-dialog
<span class="dialog-footer"> v-model="showTitleDialog"
<el-button @click="showTitleDialog = false">{{ t('cancel') }}</el-button> :title="t('selectStyle')"
<el-button type="primary" @click="confirmTitleStyle">{{ t('confirm') }}</el-button> width="460px"
</span> >
</template> <div class="flex flex-wrap">
<template v-for="(item, index) in titleStyleList" :key="index">
</el-dialog> <div
</div> :class="{
'border-primary': selectTitleStyle.value == item.value,
<div class="edit-attr-item-wrap"> }"
<h3 class="mb-[10px]">{{ t("selectSource") }}</h3> @click="changeTitleStyle(item)"
<el-form label-width="80px" class="px-[10px]"> class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] mb-[12px] cursor-pointer border bg-[#eee]"
<el-form-item :label="t('goodsSelectPopupSelectGoodsButton')"> >
<el-radio-group v-model="diyStore.editComponent.source" :title="t('goodsSelectPopupSelectGoodsButton')"> <img :src="img(item.url)" />
<el-radio label="all">{{ t('defaultGoodsSelect') }}</el-radio> </div>
<el-radio label="custom">{{ t('manualSelectionSources') }}</el-radio> </template>
</el-radio-group> </div>
</el-form-item>
<el-form-item :label="t('customGoods')" v-if="diyStore.editComponent.source == 'custom'"> <template #footer>
<goods-select-popup ref="goodsSelectPopupRef" v-model="diyStore.editComponent.goods_ids" :min="1" :max="1" /> <span class="dialog-footer">
</el-form-item> <el-button @click="showTitleDialog = false">{{
</el-form> t('cancel')
</div> }}</el-button>
<el-button type="primary" @click="confirmTitleStyle">{{
<div class="edit-attr-item-wrap"> t('confirm')
<h3 class="mb-[10px]">{{ t('imageSet') }}</h3> }}</el-button>
<el-form label-width="80px" class="px-[10px]"> </span>
</template>
<div ref="imageBoxRef"> </el-dialog>
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]"> </div>
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1" /> <div class="edit-attr-item-wrap">
</el-form-item> <h3 class="mb-[10px]">{{ t('selectSource') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)"> <el-form-item :label="t('goodsSelectPopupSelectGoodsButton')">
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/> <el-radio-group
</div> v-model="diyStore.editComponent.source"
:title="t('goodsSelectPopupSelectGoodsButton')"
<el-form-item :label="t('link')"> >
<diy-link v-model="item.link"/> <el-radio label="all">{{ t('defaultGoodsSelect') }}</el-radio>
</el-form-item> <el-radio label="custom">{{
</div> t('manualSelectionSources')
</div> }}</el-radio>
</el-radio-group>
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addImageAd">{{ t('addImageAd') }}</el-button> </el-form-item>
<el-form-item
</el-form> :label="t('customGoods')"
</div> v-if="diyStore.editComponent.source == 'custom'"
>
<el-dialog v-model="categoryShowDialog" :title="t('goodsCategoryTitle')" width="750px" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false"> <goods-select-popup
<el-table :data="categoryTable.data" ref="categoryTableRef" size="large" v-loading="categoryTable.loading" ref="goodsSelectPopupRef"
height="450px" @selection-change="handleSelectionChange" row-key="category_id" v-model="diyStore.editComponent.goods_ids"
:expand-row-keys="expand_category_ids" :min="1"
:tree-props="{ hasChildren: 'hasChildren', children: 'child_list' }"> :max="1"
<template #empty> />
<span>{{ !categoryTable.loading ? t('emptyData') : '' }}</span> </el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('imageSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<div ref="imageBoxRef">
<div
v-for="(item, index) in diyStore.editComponent.list"
:key="item.id"
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]"
>
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1" />
</el-form-item>
<div
class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
v-show="diyStore.editComponent.list.length > 1"
@click="diyStore.editComponent.list.splice(index, 1)"
>
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
</div>
<el-form-item :label="t('link')">
<diy-link v-model="item.link" />
</el-form-item>
</div>
</div>
<el-button
v-show="diyStore.editComponent.list.length < 10"
class="w-full"
@click="addImageAd"
>{{ t('addImageAd') }}</el-button
>
</el-form>
</div>
<el-dialog
v-model="categoryShowDialog"
:title="t('goodsCategoryTitle')"
width="750px"
:close-on-press-escape="false"
:destroy-on-close="true"
:close-on-click-modal="false"
>
<el-table
:data="categoryTable.data"
ref="categoryTableRef"
size="large"
v-loading="categoryTable.loading"
height="450px"
@selection-change="handleSelectionChange"
row-key="category_id"
:expand-row-keys="expand_category_ids"
:tree-props="{ hasChildren: 'hasChildren', children: 'child_list' }"
>
<template #empty>
<span>{{ !categoryTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column type="selection" width="55" />
<el-table-column :label="t('categoryName')" min-width="120">
<template #default="{ row }">
<span class="order-2">{{ row.category_name }}</span>
</template>
</el-table-column>
<el-table-column :label="t('categoryImage')" width="170" align="left">
<template #default="{ row }">
<div class="h-[30px]">
<el-image
class="w-[30px] h-[30px]"
:src="img(row.image)"
fit="contain"
>
<template #error>
<div class="image-slot">
<img
class="w-[30px] h-[30px]"
src="@/addon/shop/assets/category_default.png"
/>
</div>
</template> </template>
<el-table-column type="selection" width="55" /> </el-image>
<el-table-column :label="t('categoryName')" min-width="120">
<template #default="{ row }">
<span class="order-2">{{ row.category_name }}</span>
</template>
</el-table-column>
<el-table-column :label="t('categoryImage')" width="170" align="left">
<template #default="{ row }">
<div class="h-[30px]">
<el-image class="w-[30px] h-[30px] " :src="img(row.image)" fit="contain">
<template #error>
<div class="image-slot">
<img class="w-[30px] h-[30px]" src="@/addon/shop/assets/category_default.png" />
</div>
</template>
</el-image>
</div>
</template>
</el-table-column>
</el-table>
<div class="flex items-center justify-end mt-[15px]">
<el-button type="primary" @click="saveCategoryId">{{ t('confirm') }}</el-button>
<el-button @click="categoryShowDialog = false">{{ t('cancel') }}</el-button>
</div> </div>
</el-dialog> </template>
</div> </el-table-column>
</el-table>
<!-- 样式 --> <div class="flex items-center justify-end mt-[15px]">
<div class="style-wrap" v-show="diyStore.editTab == 'style'"> <el-button type="primary" @click="saveCategoryId">{{
<div class="edit-attr-item-wrap"> t('confirm')
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3> }}</el-button>
<el-form label-width="90px" class="px-[10px]"> <el-button @click="categoryShowDialog = false">{{
<el-form-item :label="t('textColor')"> t('cancel')
<el-color-picker v-model="diyStore.editComponent.subTitle.textColor" show-alpha :predefine="diyStore.predefineColors"/> }}</el-button>
</el-form-item> </div>
</el-form> </el-dialog>
</div> </div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('carouselStyle') }}</h3> <!-- 样式 -->
<el-form label-width="90px" class="px-[10px]"> <div class="style-wrap" v-show="diyStore.editTab == 'style'">
<el-form-item :label="t('topRounded')"> <div class="edit-attr-item-wrap">
<el-slider v-model="diyStore.editComponent.topCarouselRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> <h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
</el-form-item> <el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('bottomRounded')"> <el-form-item :label="t('textColor')">
<el-slider v-model="diyStore.editComponent.bottomCarouselRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> <el-color-picker
</el-form-item> v-model="diyStore.editComponent.subTitle.textColor"
</el-form> show-alpha
</div> :predefine="diyStore.predefineColors"
<div class="edit-attr-item-wrap"> />
<h3 class="mb-[10px]">{{ t('recommendIndicatorStyle') }}</h3> </el-form-item>
<el-form label-width="90px" class="px-[10px]"> </el-form>
<el-form-item :label="t('recommendIndicatorColor')"> </div>
<el-color-picker v-model="diyStore.editComponent.indicatorColor" show-alpha :predefine="diyStore.predefineColors" /> <div class="edit-attr-item-wrap">
</el-form-item> <h3 class="mb-[10px]">{{ t('carouselStyle') }}</h3>
<el-form-item :label="t('recommendIndicatorActiveColor')"> <el-form label-width="90px" class="px-[10px]">
<el-color-picker v-model="diyStore.editComponent.indicatorActiveColor" show-alpha :predefine="diyStore.predefineColors" /> <el-form-item :label="t('topRounded')">
</el-form-item> <el-slider
</el-form> v-model="diyStore.editComponent.topCarouselRounded"
</div> show-input
<div class="edit-attr-item-wrap"> size="small"
<h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3> class="ml-[10px] diy-nav-slider"
<el-form label-width="80px" class="px-[10px]"> :max="50"
<el-form-item :label="t('goodsBgColor')"> />
<el-color-picker v-model="diyStore.editComponent.elementBgColor" show-alpha :predefine="diyStore.predefineColors" /> </el-form-item>
</el-form-item> <el-form-item :label="t('bottomRounded')">
<el-form-item :label="t('goodsNameColor')"> <el-slider
<el-color-picker v-model="diyStore.editComponent.goodsNameStyle.color" show-alpha :predefine="diyStore.predefineColors" /> v-model="diyStore.editComponent.bottomCarouselRounded"
<div class="mr-[20px]"></div> show-input
<el-radio-group v-model="diyStore.editComponent.goodsNameStyle.fontWeight"> size="small"
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio> class="ml-[10px] diy-nav-slider"
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio> :max="50"
</el-radio-group> />
</el-form-item> </el-form-item>
<el-form-item :label="t('goodsPriceColor')"> </el-form>
<el-color-picker v-model="diyStore.editComponent.priceStyle.mainColor" show-alpha :predefine="diyStore.predefineColors" /> </div>
</el-form-item> <div class="edit-attr-item-wrap">
<el-form-item :label="t('goodsBtnColor')"> <h3 class="mb-[10px]">{{ t('recommendIndicatorStyle') }}</h3>
<el-color-picker v-model="diyStore.editComponent.saleStyle.color" show-alpha :predefine="diyStore.predefineColors" /> <el-form label-width="90px" class="px-[10px]">
</el-form-item> <el-form-item :label="t('recommendIndicatorColor')">
<el-form-item :label="t('topRounded')"> <el-color-picker
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> v-model="diyStore.editComponent.indicatorColor"
</el-form-item> show-alpha
<el-form-item :label="t('bottomRounded')"> :predefine="diyStore.predefineColors"
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" /> />
</el-form-item> </el-form-item>
</el-form> <el-form-item :label="t('recommendIndicatorActiveColor')">
</div> <el-color-picker
v-model="diyStore.editComponent.indicatorActiveColor"
<!-- 组件样式 --> show-alpha
<slot name="style"></slot> :predefine="diyStore.predefineColors"
</div> />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('goodsStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('goodsBgColor')">
<el-color-picker
v-model="diyStore.editComponent.elementBgColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('goodsNameColor')">
<el-color-picker
v-model="diyStore.editComponent.goodsNameStyle.color"
show-alpha
:predefine="diyStore.predefineColors"
/>
<div class="mr-[20px]"></div>
<el-radio-group
v-model="diyStore.editComponent.goodsNameStyle.fontWeight"
>
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('goodsPriceColor')">
<el-color-picker
v-model="diyStore.editComponent.priceStyle.mainColor"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('goodsBtnColor')">
<el-color-picker
v-model="diyStore.editComponent.saleStyle.color"
show-alpha
:predefine="diyStore.predefineColors"
/>
</el-form-item>
<el-form-item :label="t('topRounded')">
<el-slider
v-model="diyStore.editComponent.topElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider
v-model="diyStore.editComponent.bottomElementRounded"
show-input
size="small"
class="ml-[10px] diy-nav-slider"
:max="50"
/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -190,85 +315,85 @@ import { getCategoryTree } from '@/addon/shop/api/goods'
import { t } from '@/lang' import { t } from '@/lang'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import useDiyStore from '@/stores/modules/diy' import useDiyStore from '@/stores/modules/diy'
import { ref, reactive, onMounted,nextTick } from 'vue' import { ref, reactive, onMounted, nextTick } from 'vue'
import { ElTable } from 'element-plus' import { ElTable } from 'element-plus'
import goodsSelectPopup from '@/addon/shop/views/goods/components/goods-select-popup.vue' import goodsSelectPopup from '@/addon/shop/views/goods/components/goods-select-popup.vue'
const diyStore:any = useDiyStore() const diyStore: any = useDiyStore()
diyStore.editComponent.ignore = ['componentBgUrl'] // diyStore.editComponent.ignore = ['componentBgUrl'] //
const selectTitleStyle = reactive({ const selectTitleStyle = reactive({
title: diyStore.editComponent.titleStyle.title, title: diyStore.editComponent.titleStyle.title,
value: diyStore.editComponent.titleStyle.value value: diyStore.editComponent.titleStyle.value,
}) })
// //
const showTitleDialog = ref(false) const showTitleDialog = ref(false)
const showTitleStyle = () => { const showTitleStyle = () => {
selectTitleStyle.title = diyStore.editComponent.titleStyle.title; selectTitleStyle.title = diyStore.editComponent.titleStyle.title
selectTitleStyle.value = diyStore.editComponent.titleStyle.value; selectTitleStyle.value = diyStore.editComponent.titleStyle.value
showTitleDialog.value = true showTitleDialog.value = true
} }
const changeTitleStyle = (item:any) => { const changeTitleStyle = (item: any) => {
selectTitleStyle.title = item.title; selectTitleStyle.title = item.title
selectTitleStyle.value = item.value; selectTitleStyle.value = item.value
} }
const confirmTitleStyle = () => { const confirmTitleStyle = () => {
diyStore.editComponent.titleStyle.title = selectTitleStyle.title; diyStore.editComponent.titleStyle.title = selectTitleStyle.title
diyStore.editComponent.titleStyle.value = selectTitleStyle.value; diyStore.editComponent.titleStyle.value = selectTitleStyle.value
showTitleDialog.value = false showTitleDialog.value = false
} }
const titleStyleList = reactive([ const titleStyleList = reactive([
{ {
url : 'addon/shop/diy/single_recommend/title_style_01.png', url: 'addon/shop/diy/single_recommend/title_style_01.png',
title:'风格1', title: '风格1',
value:'style-1' value: 'style-1',
} },
]) ])
const addImageAd = () => { const addImageAd = () => {
diyStore.editComponent.list.push({ diyStore.editComponent.list.push({
id: diyStore.generateRandom(), id: diyStore.generateRandom(),
imageUrl: '', imageUrl: '',
imgWidth: 0, imgWidth: 0,
imgHeight: 0, imgHeight: 0,
link: { name: '' } link: { name: '' },
}) })
} }
// //
diyStore.editComponent.verify = (index: number) => { diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' } const res = { code: true, message: '' }
if(diyStore.value[index].source == 'custom'){ if (diyStore.value[index].source == 'custom') {
if(diyStore.value[index].goods_ids.length == 0){ if (diyStore.value[index].goods_ids.length == 0) {
res.code = false res.code = false
res.message = t('goodsPlaceholder') res.message = t('goodsPlaceholder')
}
} }
}
diyStore.value[index].list.forEach((item,index) => { diyStore.value[index].list.forEach((item, index) => {
if (item.imageUrl === '') { if (item.imageUrl === '') {
res.code = false res.code = false
res.message = t('imageUrlTip') res.message = t('imageUrlTip')
return res return res
} }
}); })
return res return res
} }
const categoryShowDialog = ref(false) const categoryShowDialog = ref(false)
const categoryTable = reactive({ const categoryTable = reactive({
loading: true, loading: true,
data: [], data: [],
}) })
onMounted(() => { onMounted(() => {
loadCategoryList() loadCategoryList()
}) })
const categoryTableRef = ref<InstanceType<typeof ElTable>>() const categoryTableRef = ref<InstanceType<typeof ElTable>>()
@ -277,54 +402,56 @@ const categoryTableRef = ref<InstanceType<typeof ElTable>>()
*/ */
let currCategoryData: any = null let currCategoryData: any = null
const loadCategoryList = () => { const loadCategoryList = () => {
categoryTable.loading = true categoryTable.loading = true
getCategoryTree().then(res => { getCategoryTree()
categoryTable.loading = false .then((res) => {
categoryTable.data = res.data categoryTable.loading = false
}).catch(() => { categoryTable.data = res.data
categoryTable.loading = false })
.catch(() => {
categoryTable.loading = false
}) })
} }
// //
const handleSelectionChange = (val: string | any[]) => { const handleSelectionChange = (val: string | any[]) => {
let data = '' let data = ''
if (val) data = val[val.length - 1] if (val) data = val[val.length - 1]
if (val.length > 1) categoryTableRef.value!.clearSelection() if (val.length > 1) categoryTableRef.value!.clearSelection()
if (data) categoryTableRef.value!.toggleRowSelection(data, true) if (data) categoryTableRef.value!.toggleRowSelection(data, true)
currCategoryData = data currCategoryData = data
} }
const saveCategoryId = () => { const saveCategoryId = () => {
diyStore.editComponent.goods_category = currCategoryData.category_id diyStore.editComponent.goods_category = currCategoryData.category_id
diyStore.editComponent.goods_category_name = currCategoryData.category_name; diyStore.editComponent.goods_category_name = currCategoryData.category_name
categoryShowDialog.value = false categoryShowDialog.value = false
} }
const categoryShowDialogOpen = () => { const categoryShowDialogOpen = () => {
categoryShowDialog.value = true categoryShowDialog.value = true
nextTick(()=>{ nextTick(() => {
setRowSelection() setRowSelection()
}) })
} }
//, //,
const expand_category_ids = ref<Array<any>>([]) const expand_category_ids = ref<Array<any>>([])
const setRowSelection = ()=>{ const setRowSelection = () => {
expand_category_ids.value = [] expand_category_ids.value = []
categoryTable.data.forEach((el:any)=>{ categoryTable.data.forEach((el: any) => {
if(diyStore.editComponent.goods_category == el.category_id){ if (diyStore.editComponent.goods_category == el.category_id) {
categoryTableRef.value!.toggleRowSelection(el, true) categoryTableRef.value!.toggleRowSelection(el, true)
}else if(el.child_list&&el.child_list.length){ } else if (el.child_list && el.child_list.length) {
el.child_list.forEach((v:any)=>{ el.child_list.forEach((v: any) => {
if(diyStore.editComponent.goods_category == v.category_id){ if (diyStore.editComponent.goods_category == v.category_id) {
expand_category_ids.value.push(el.category_id.toString()) expand_category_ids.value.push(el.category_id.toString())
categoryTableRef.value!.toggleRowSelection(v, true) categoryTableRef.value!.toggleRowSelection(v, true)
} }
}) })
} }
}) })
} }
defineExpose({}) defineExpose({})

444
admin/src/addon/shop/views/goods/attr.vue

@ -1,104 +1,189 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<div class="flex justify-between items-center"> <span class="text-lg">{{ pageName }}</span>
<span class="text-lg">{{pageName}}</span> <el-button type="primary" @click="addEvent">
<el-button type="primary" @click="addEvent"> {{ t('addShopGoodsAttr') }}
{{ t('addShopGoodsAttr') }} </el-button>
</el-button> </div>
</div>
<el-card
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> class="box-card !border-none my-[10px] table-search-wrap"
<el-form :inline="true" :model="goodsAttrTable.searchParam" ref="searchFormRef"> shadow="never"
<el-form-item :label="t('attrName')" prop="attr_name"> >
<el-input v-model.trim="goodsAttrTable.searchParam.attr_name" :placeholder="t('attrNamePlaceholder')" /> <el-form
</el-form-item> :inline="true"
<el-form-item> :model="goodsAttrTable.searchParam"
<el-button type="primary" @click="loadShopGoodsAttrList()">{{ t('search') }}</el-button> ref="searchFormRef"
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> >
</el-form-item> <el-form-item :label="t('attrName')" prop="attr_name">
</el-form> <el-input
</el-card> v-model.trim="goodsAttrTable.searchParam.attr_name"
:placeholder="t('attrNamePlaceholder')"
<div class="mt-[10px]"> />
<el-table :data="goodsAttrTable.data" size="large" v-loading="goodsAttrTable.loading" @sort-change="sortChange"> </el-form-item>
<template #empty> <el-form-item>
<span>{{ !goodsAttrTable.loading ? t('emptyData') : '' }}</span> <el-button type="primary" @click="loadShopGoodsAttrList()">{{
</template> t('search')
}}</el-button>
<el-table-column prop="attr_name" :label="t('attrName')" min-width="320" :show-overflow-tooltip="true"/> <el-button @click="resetForm(searchFormRef)">{{
t('reset')
<el-table-column prop="sort" :label="t('sort')" min-width="120" sortable="custom"> }}</el-button>
<template #default="{ row }"> </el-form-item>
<el-input v-model.trim="row.sort" class="!w-[100px]" maxlength="8" @blur="sortInputListener(row.sort, row)" /> </el-form>
</template> </el-card>
</el-table-column>
<div class="mt-[10px]">
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120"> <el-table
<template #default="{ row }"> :data="goodsAttrTable.data"
<el-button type="primary" link @click="manageEvent(row)">{{ t('manage') }}</el-button> size="large"
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> v-loading="goodsAttrTable.loading"
<el-button type="primary" link @click="deleteEvent(row.attr_id)">{{ t('delete') }}</el-button> @sort-change="sortChange"
</template> >
</el-table-column> <template #empty>
<span>{{ !goodsAttrTable.loading ? t('emptyData') : '' }}</span>
</el-table> </template>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="goodsAttrTable.page" v-model:page-size="goodsAttrTable.limit" <el-table-column
layout="total, sizes, prev, pager, next, jumper" :total="goodsAttrTable.total" prop="attr_name"
@size-change="loadShopGoodsAttrList()" @current-change="loadShopGoodsAttrList" /> :label="t('attrName')"
</div> min-width="320"
</div> :show-overflow-tooltip="true"
/>
</el-card>
<el-table-column
<el-dialog v-model="showDialog" :title="titleDialog" width="500px" :destroy-on-close="true"> prop="sort"
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading"> :label="t('sort')"
<el-form-item :label="t('attrName')" prop="attr_name"> min-width="120"
<el-input v-model.trim="formData.attr_name" clearable :placeholder="t('attrNamePlaceholder')" class="input-width" maxlength="20" /> sortable="custom"
</el-form-item> >
<template #default="{ row }">
<el-form-item :label="t('sort')" > <el-input
<el-input v-model.trim="formData.sort" maxlength="8" show-word-limit clearable :placeholder="t('sortPlaceholder')" class="input-width" @keyup="filterNumber($event)"/> v-model.trim="row.sort"
</el-form-item> class="!w-[100px]"
maxlength="8"
</el-form> @blur="sortInputListener(row.sort, row)"
/>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
</span>
</template> </template>
</el-dialog> </el-table-column>
</div> <el-table-column
:label="t('operation')"
fixed="right"
align="right"
min-width="120"
>
<template #default="{ row }">
<el-button type="primary" link @click="manageEvent(row)">{{
t('manage')
}}</el-button>
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button
type="primary"
link
@click="deleteEvent(row.attr_id)"
>{{ t('delete') }}</el-button
>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="goodsAttrTable.page"
v-model:page-size="goodsAttrTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="goodsAttrTable.total"
@size-change="loadShopGoodsAttrList()"
@current-change="loadShopGoodsAttrList"
/>
</div>
</div>
</el-card>
<el-dialog
v-model="showDialog"
:title="titleDialog"
width="500px"
:destroy-on-close="true"
>
<el-form
:model="formData"
label-width="120px"
ref="formRef"
:rules="formRules"
class="page-form"
v-loading="loading"
>
<el-form-item :label="t('attrName')" prop="attr_name">
<el-input
v-model.trim="formData.attr_name"
clearable
:placeholder="t('attrNamePlaceholder')"
class="input-width"
maxlength="20"
/>
</el-form-item>
<el-form-item :label="t('sort')">
<el-input
v-model.trim="formData.sort"
maxlength="8"
show-word-limit
clearable
:placeholder="t('sortPlaceholder')"
class="input-width"
@keyup="filterNumber($event)"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref,computed } from 'vue' import { reactive, ref, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { ElMessage,ElMessageBox,FormInstance } from 'element-plus' import { ElMessage, ElMessageBox, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { debounce,filterNumber } from '@/utils/common' import { debounce, filterNumber } from '@/utils/common'
import { getAttrPageList, addAttr, deleteAttr,modifyAttrSort,editAttr} from '@/addon/shop/api/goods' import {
getAttrPageList,
addAttr,
deleteAttr,
modifyAttrSort,
editAttr,
} from '@/addon/shop/api/goods'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title; const pageName = route.meta.title
const goodsAttrTable = reactive({ const goodsAttrTable = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
total: 0, total: 0,
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
attr_name: '', attr_name: '',
order: '', order: '',
sort: '' sort: '',
} },
}) })
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()
@ -108,54 +193,56 @@ const loading = ref(false)
const titleDialog = ref('') const titleDialog = ref('')
const formData = reactive({ const formData = reactive({
attr_id: 0, attr_id: 0,
attr_name: '', attr_name: '',
sort: 0 sort: 0,
}) })
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
attr_name: [ attr_name: [
{ required: true, message: t('attrNamePlaceholder'), trigger: 'blur' } { required: true, message: t('attrNamePlaceholder'), trigger: 'blur' },
] ],
} }
}) })
// //
const sortChange = (event: any) => { const sortChange = (event: any) => {
let sort = '' let sort = ''
if (event.order == 'ascending') { if (event.order == 'ascending') {
sort = 'asc' sort = 'asc'
} else if (event.order == 'descending') { } else if (event.order == 'descending') {
sort = 'desc' sort = 'desc'
} }
if (sort) { if (sort) {
goodsAttrTable.searchParam.order = event.prop goodsAttrTable.searchParam.order = event.prop
goodsAttrTable.searchParam.sort = sort goodsAttrTable.searchParam.sort = sort
} }
loadShopGoodsAttrList() loadShopGoodsAttrList()
} }
/** /**
* 获取商品参数列表 * 获取商品参数列表
*/ */
const loadShopGoodsAttrList = (page: number = 1) => { const loadShopGoodsAttrList = (page: number = 1) => {
goodsAttrTable.loading = true goodsAttrTable.loading = true
goodsAttrTable.page = page goodsAttrTable.page = page
getAttrPageList({ getAttrPageList({
page: goodsAttrTable.page, page: goodsAttrTable.page,
limit: goodsAttrTable.limit, limit: goodsAttrTable.limit,
...goodsAttrTable.searchParam ...goodsAttrTable.searchParam,
}).then(res => { })
goodsAttrTable.loading = false .then((res) => {
goodsAttrTable.data = res.data.data goodsAttrTable.loading = false
goodsAttrTable.total = res.data.total goodsAttrTable.data = res.data.data
}).catch(() => { goodsAttrTable.total = res.data.total
goodsAttrTable.loading = false })
.catch(() => {
goodsAttrTable.loading = false
}) })
} }
@ -165,20 +252,20 @@ loadShopGoodsAttrList()
* 添加商品参数 * 添加商品参数
*/ */
const addEvent = () => { const addEvent = () => {
formData.attr_id = 0; formData.attr_id = 0
formData.attr_name = ''; formData.attr_name = ''
formData.sort = 0; formData.sort = 0
titleDialog.value = t('addShopGoodsAttr'); titleDialog.value = t('addShopGoodsAttr')
showDialog.value = true showDialog.value = true
} }
// //
const editEvent = (data:any)=>{ const editEvent = (data: any) => {
formData.attr_id = data.attr_id; formData.attr_id = data.attr_id
formData.attr_name = data.attr_name; formData.attr_name = data.attr_name
formData.sort = data.sort; formData.sort = data.sort
titleDialog.value = t('updateShopGoodsAttr'); titleDialog.value = t('updateShopGoodsAttr')
showDialog.value = true showDialog.value = true
} }
/** /**
@ -186,21 +273,23 @@ const editEvent = (data:any)=>{
* @param formEl * @param formEl
*/ */
const confirm = async (formEl: FormInstance | undefined) => { const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
const save = formData.attr_id ? editAttr : addAttr const save = formData.attr_id ? editAttr : addAttr
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
save(formData).then(res => { save(formData)
loading.value = false .then((res) => {
showDialog.value = false loading.value = false
loadShopGoodsAttrList() showDialog.value = false
}).catch(err => { loadShopGoodsAttrList()
loading.value = false })
}) .catch((err) => {
} loading.value = false
}) })
}
})
} }
/** /**
@ -208,52 +297,49 @@ const confirm = async (formEl: FormInstance | undefined) => {
* @param data * @param data
*/ */
const manageEvent = (data: any) => { const manageEvent = (data: any) => {
router.push('/shop/goods/attr_edit?attr_id=' + data.attr_id) router.push('/shop/goods/attr_edit?attr_id=' + data.attr_id)
} }
/** /**
* 删除商品参数 * 删除商品参数
*/ */
const deleteEvent = (id: number) => { const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('goodsAttrDeleteTips'), t('warning'), ElMessageBox.confirm(t('goodsAttrDeleteTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning', }).then(() => {
} deleteAttr(id)
).then(() => { .then(() => {
deleteAttr(id).then(() => { loadShopGoodsAttrList()
loadShopGoodsAttrList() })
}).catch(() => { .catch(() => {})
}) })
})
} }
// //
const sortInputListener = debounce((sort, row) => { const sortInputListener = debounce((sort, row) => {
if (isNaN(sort) || !/^\d{0,8}$/.test(sort)) { if (isNaN(sort) || !/^\d{0,8}$/.test(sort)) {
ElMessage({ ElMessage({
type: 'warning', type: 'warning',
message: `${ t('sortTips') }` message: `${t('sortTips')}`,
})
return
}
if (sort > 99999999) {
row.sort = 99999999
}
modifyAttrSort({
attr_id: row.attr_id,
sort
}).then((res) => {
}) })
return
}
if (sort > 99999999) {
row.sort = 99999999
}
modifyAttrSort({
attr_id: row.attr_id,
sort,
}).then((res) => {})
}) })
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
loadShopGoodsAttrList() loadShopGoodsAttrList()
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

862
admin/src/addon/shop/views/goods/attr_edit.vue

@ -1,202 +1,363 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never"> <el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="router.push(`/shop/goods/attr`)" /> <el-page-header
</el-card> :content="pageName"
:icon="ArrowLeft"
<el-card class="box-card !border-none" shadow="never"> @back="router.push(`/shop/goods/attr`)"
/>
<!-- 商品参数基础信息 --> </el-card>
<el-row :gutter="20" class="text-[14px]" v-if="Object.keys(attrInfo).length">
<el-col :span="8"> <el-card class="box-card !border-none" shadow="never">
<label>{{ t('attrName') }}</label> <!-- 商品参数基础信息 -->
<span class="ml-[10px]">{{ attrInfo.attr_name }}</span> <el-row
</el-col> :gutter="20"
<el-col :span="6"> class="text-[14px]"
<label>{{ t('sort') }}</label> v-if="Object.keys(attrInfo).length"
<span class="ml-[10px]">{{ attrInfo.sort }}</span> >
</el-col> <el-col :span="8">
<el-col :span="6"> <label>{{ t('attrName') }}</label>
<el-button type="primary" link @click="editEvent">{{ t('edit') }}</el-button> <span class="ml-[10px]">{{ attrInfo.attr_name }}</span>
</el-col> </el-col>
</el-row> <el-col :span="6">
<label>{{ t('sort') }}</label>
<el-button type="primary" @click="openAttrValueEvent" class="my-[15px]">{{ t('addShopGoodsAttr') }}</el-button> <span class="ml-[10px]">{{ attrInfo.sort }}</span>
</el-col>
<el-table :data="goodsAttrTable.data" size="large" v-loading="goodsAttrTable.loading"> <el-col :span="6">
<template #empty> <el-button type="primary" link @click="editEvent">{{
<span>{{ !goodsAttrTable.loading ? t('emptyData') : '' }}</span> t('edit')
</template> }}</el-button>
</el-col>
<el-table-column prop="attr_value_name" :label="t('attrValueName')" min-width="200" :show-overflow-tooltip="true"/> </el-row>
<el-table-column prop="type" :label="t('attrValueType')" min-width="100" :show-overflow-tooltip="true"> <el-button type="primary" @click="openAttrValueEvent" class="my-[15px]">{{
<template #default="{ row }"> t('addShopGoodsAttr')
<template v-if="row.type == 'radio'"> }}</el-button>
<span>{{ t('attrValueTypeRadio') }}</span>
</template> <el-table
<template v-else-if="row.type == 'checkbox'"> :data="goodsAttrTable.data"
<span>{{ t('attrValueTypeCheckbox') }}</span> size="large"
</template> v-loading="goodsAttrTable.loading"
<template v-if="row.type == 'text'"> >
<span>{{ t('attrValueTypeText') }}</span> <template #empty>
</template> <span>{{ !goodsAttrTable.loading ? t('emptyData') : '' }}</span>
</template> </template>
</el-table-column>
<el-table-column
<el-table-column prop="child" :label="t('attrValueChild')" min-width="320" :show-overflow-tooltip="true"> prop="attr_value_name"
<template #default="{ row }"> :label="t('attrValueName')"
<template v-if="row.type != 'text'"> min-width="200"
<template v-for="(item,index) in row.child"> :show-overflow-tooltip="true"
<span :class="{ 'mr-[5px]' : (index+1) != row.child.length }">{{ item.name }}</span> />
</template>
</template> <el-table-column
<template v-else> prop="type"
<span>-</span> :label="t('attrValueType')"
</template> min-width="100"
</template> :show-overflow-tooltip="true"
</el-table-column> >
<template #default="{ row }">
<el-table-column prop="sort" :label="t('sort')" min-width="120" sortable="custom"> <template v-if="row.type == 'radio'">
<template #default="{ row,$index }"> <span>{{ t('attrValueTypeRadio') }}</span>
<el-input v-model.trim="row.sort" class="w-[70px]" maxlength="8" @input="sortInputListener($event, row)" />
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120">
<template #default="{ row,$index }">
<el-button type="primary" link @click="editAttrValueEvent(row,$index)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent($index)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 编辑商品参数信息 -->
<el-dialog v-model="showDialogByAttr" :title="t('updateAttr')" width="500px" :destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRulesByAttr" class="page-form" v-loading="loadingByAttr">
<el-form-item :label="t('attrName')" prop="attr_name">
<el-input v-model.trim="formData.attr_name" clearable :placeholder="t('attrNamePlaceholder')" class="input-width" maxlength="20" />
</el-form-item>
<el-form-item :label="t('sort')" >
<el-input v-model.trim="formData.sort" maxlength="8" show-word-limit clearable :placeholder="t('sortPlaceholder')" class="input-width" @keyup="filterNumber($event)"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialogByAttr = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loadingByAttr" @click="confirmAttr(formRef)">{{ t('confirm') }}</el-button>
</span>
</template> </template>
</el-dialog> <template v-else-if="row.type == 'checkbox'">
<span>{{ t('attrValueTypeCheckbox') }}</span>
<!-- 编辑商品参数值信息 --> </template>
<el-dialog v-model="showDialogByAttrValue" :title="attrValueTitleDialog" width="700px" :destroy-on-close="true"> <template v-if="row.type == 'text'">
<el-form :model="formAttrValueData" label-width="120px" ref="formAttrValueRef" :rules="formRulesByAttrValue" class="page-form" v-loading="loadingByAttrValue"> <span>{{ t('attrValueTypeText') }}</span>
<el-form-item :label="t('attrValueName')" prop="attr_value_name"> </template>
<el-input v-model.trim="formAttrValueData.attr_value_name" clearable :placeholder="t('attrValueNamePlaceholder')" class="input-width" maxlength="20" show-word-limit /> </template>
</el-form-item> </el-table-column>
<el-form-item :label="t('attrValueType')"> <el-table-column
<el-select v-model="formAttrValueData.type" class="!w-[150px]" :disabled="actionAttrValueIndex > -1"> prop="child"
<el-option v-for="item in attrValueTypeOptions" :label="item.label" :value="item.value" /> :label="t('attrValueChild')"
</el-select> min-width="320"
</el-form-item> :show-overflow-tooltip="true"
>
<el-form-item :label="t('sort')" > <template #default="{ row }">
<el-input v-model.trim="formAttrValueData.sort" maxlength="8" show-word-limit clearable :placeholder="t('sortPlaceholder')" class="!w-[150px]" @keyup="filterNumber($event)"/> <template v-if="row.type != 'text'">
</el-form-item> <template v-for="(item, index) in row.child">
<span :class="{ 'mr-[5px]': index + 1 != row.child.length }">{{
<template v-if="formAttrValueData.type != 'text'"> item.name
<el-table :data="formAttrValueData.child" size="large"> }}</span>
<template #empty> </template>
<span>{{ formAttrValueData.child.length == 0 ? t('emptyData') : '' }}</span> </template>
</template> <template v-else>
<span>-</span>
<el-table-column prop="name" :label="t('attrValueName')" min-width="200"> </template>
<template #default="{ row }"> </template>
<el-input v-model.trim="row.name" class="input-width" maxlength="20" :placeholder="t('attrValueNamePlaceholder')" clearable show-word-limit /> </el-table-column>
</template>
</el-table-column> <el-table-column
prop="sort"
<el-table-column prop="name" :label="t('sort')" min-width="120"> :label="t('sort')"
<template #default="{ row }"> min-width="120"
<el-input v-model.trim="row.sort" class="!w-[150px]" maxlength="8" :placeholder="t('sortPlaceholder')" clearable show-word-limit @keyup="filterNumber($event)" /> sortable="custom"
</template> >
</el-table-column> <template #default="{ row, $index }">
<el-input
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="60"> v-model.trim="row.sort"
<template #default="{ row,$index }"> class="w-[70px]"
<el-button type="primary" link @click="deleteAttrValueEvent(row,$index)">{{ t('delete') }}</el-button> maxlength="8"
</template> @input="sortInputListener($event, row)"
</el-table-column> />
</template>
</el-table> </el-table-column>
<el-button type="primary" plain @click="addAttrValueEvent" class="my-[10px]" v-show="formAttrValueData.child.length < maxLength">{{ t('addAttrValue') }}</el-button> <el-table-column
</template> :label="t('operation')"
fixed="right"
</el-form> align="right"
min-width="120"
<template #footer> >
<span class="dialog-footer"> <template #default="{ row, $index }">
<el-button @click="showDialogByAttrValue = false">{{ t('cancel') }}</el-button> <el-button
<el-button type="primary" :loading="loadingByAttrValue" @click="confirmAttrValue(formAttrValueRef)">{{ t('confirm') }}</el-button> type="primary"
</span> link
@click="editAttrValueEvent(row, $index)"
>{{ t('edit') }}</el-button
>
<el-button type="primary" link @click="deleteEvent($index)">{{
t('delete')
}}</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 编辑商品参数信息 -->
<el-dialog
v-model="showDialogByAttr"
:title="t('updateAttr')"
width="500px"
:destroy-on-close="true"
>
<el-form
:model="formData"
label-width="120px"
ref="formRef"
:rules="formRulesByAttr"
class="page-form"
v-loading="loadingByAttr"
>
<el-form-item :label="t('attrName')" prop="attr_name">
<el-input
v-model.trim="formData.attr_name"
clearable
:placeholder="t('attrNamePlaceholder')"
class="input-width"
maxlength="20"
/>
</el-form-item>
<el-form-item :label="t('sort')">
<el-input
v-model.trim="formData.sort"
maxlength="8"
show-word-limit
clearable
:placeholder="t('sortPlaceholder')"
class="input-width"
@keyup="filterNumber($event)"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialogByAttr = false">{{
t('cancel')
}}</el-button>
<el-button
type="primary"
:loading="loadingByAttr"
@click="confirmAttr(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
<!-- 编辑商品参数值信息 -->
<el-dialog
v-model="showDialogByAttrValue"
:title="attrValueTitleDialog"
width="700px"
:destroy-on-close="true"
>
<el-form
:model="formAttrValueData"
label-width="120px"
ref="formAttrValueRef"
:rules="formRulesByAttrValue"
class="page-form"
v-loading="loadingByAttrValue"
>
<el-form-item :label="t('attrValueName')" prop="attr_value_name">
<el-input
v-model.trim="formAttrValueData.attr_value_name"
clearable
:placeholder="t('attrValueNamePlaceholder')"
class="input-width"
maxlength="20"
show-word-limit
/>
</el-form-item>
<el-form-item :label="t('attrValueType')">
<el-select
v-model="formAttrValueData.type"
class="!w-[150px]"
:disabled="actionAttrValueIndex > -1"
>
<el-option
v-for="item in attrValueTypeOptions"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('sort')">
<el-input
v-model.trim="formAttrValueData.sort"
maxlength="8"
show-word-limit
clearable
:placeholder="t('sortPlaceholder')"
class="!w-[150px]"
@keyup="filterNumber($event)"
/>
</el-form-item>
<template v-if="formAttrValueData.type != 'text'">
<el-table :data="formAttrValueData.child" size="large">
<template #empty>
<span>{{
formAttrValueData.child.length == 0 ? t('emptyData') : ''
}}</span>
</template> </template>
</el-dialog>
</div> <el-table-column
prop="name"
:label="t('attrValueName')"
min-width="200"
>
<template #default="{ row }">
<el-input
v-model.trim="row.name"
class="input-width"
maxlength="20"
:placeholder="t('attrValueNamePlaceholder')"
clearable
show-word-limit
/>
</template>
</el-table-column>
<el-table-column prop="name" :label="t('sort')" min-width="120">
<template #default="{ row }">
<el-input
v-model.trim="row.sort"
class="!w-[150px]"
maxlength="8"
:placeholder="t('sortPlaceholder')"
clearable
show-word-limit
@keyup="filterNumber($event)"
/>
</template>
</el-table-column>
<el-table-column
:label="t('operation')"
fixed="right"
align="right"
min-width="60"
>
<template #default="{ row, $index }">
<el-button
type="primary"
link
@click="deleteAttrValueEvent(row, $index)"
>{{ t('delete') }}</el-button
>
</template>
</el-table-column>
</el-table>
<el-button
type="primary"
plain
@click="addAttrValueEvent"
class="my-[10px]"
v-show="formAttrValueData.child.length < maxLength"
>{{ t('addAttrValue') }}</el-button
>
</template>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialogByAttrValue = false">{{
t('cancel')
}}</el-button>
<el-button
type="primary"
:loading="loadingByAttrValue"
@click="confirmAttrValue(formAttrValueRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref,computed } from 'vue' import { reactive, ref, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { ElMessage,ElMessageBox,FormInstance } from 'element-plus' import { ElMessage, ElMessageBox, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { debounce,filterNumber } from '@/utils/common' import { debounce, filterNumber } from '@/utils/common'
import { getAttrInfo,editAttr, modifyAttrValue } from '@/addon/shop/api/goods' import { getAttrInfo, editAttr, modifyAttrValue } from '@/addon/shop/api/goods'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const pageName = route.meta.title; const pageName = route.meta.title
route.query.attr_id = route.query.attr_id || 0 route.query.attr_id = route.query.attr_id || 0
const attrId:any = ref(route.query.attr_id) const attrId: any = ref(route.query.attr_id)
const attrInfo:any = reactive({}) const attrInfo: any = reactive({})
const maxLength = ref(30) // const maxLength = ref(30) //
const goodsAttrTable = reactive({ const goodsAttrTable = reactive({
loading: true, loading: true,
data: [] data: [],
}) })
const loadAttrInfo = ()=> { const loadAttrInfo = () => {
// //
getAttrInfo(attrId.value).then((res: any) => { getAttrInfo(attrId.value).then((res: any) => {
Object.assign(attrInfo, res.data) Object.assign(attrInfo, res.data)
if (attrInfo.attr_value_format) { if (attrInfo.attr_value_format) {
attrInfo.attr_value_format = JSON.parse(attrInfo.attr_value_format); attrInfo.attr_value_format = JSON.parse(attrInfo.attr_value_format)
} else { } else {
attrInfo.attr_value_format = [] attrInfo.attr_value_format = []
} }
goodsAttrTable.data = cloneDeep(attrInfo.attr_value_format)
goodsAttrTable.data.sort((a: any, b: any) => {
return b.sort - a.sort
});
goodsAttrTable.loading = false goodsAttrTable.data = cloneDeep(attrInfo.attr_value_format)
goodsAttrTable.data.sort((a: any, b: any) => {
return b.sort - a.sort
}) })
goodsAttrTable.loading = false
})
} }
loadAttrInfo() loadAttrInfo()
@ -205,26 +366,26 @@ const showDialogByAttr = ref(false)
const loadingByAttr = ref(false) const loadingByAttr = ref(false)
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const formData = reactive({ const formData = reactive({
attr_id: 0, attr_id: 0,
attr_name: '', attr_name: '',
sort: 0 sort: 0,
}) })
// //
const formRulesByAttr = computed(() => { const formRulesByAttr = computed(() => {
return { return {
attr_name: [ attr_name: [
{ required: true, message: t('attrNamePlaceholder'), trigger: 'blur' } { required: true, message: t('attrNamePlaceholder'), trigger: 'blur' },
] ],
} }
}) })
// //
const editEvent = (data:any)=>{ const editEvent = (data: any) => {
formData.attr_id = attrInfo.attr_id; formData.attr_id = attrInfo.attr_id
formData.attr_name = attrInfo.attr_name; formData.attr_name = attrInfo.attr_name
formData.sort = attrInfo.sort; formData.sort = attrInfo.sort
showDialogByAttr.value = true showDialogByAttr.value = true
} }
/** /**
@ -232,205 +393,228 @@ const editEvent = (data:any)=>{
* @param formEl * @param formEl
*/ */
const confirmAttr = async (formEl: FormInstance | undefined) => { const confirmAttr = async (formEl: FormInstance | undefined) => {
if (loadingByAttr.value || !formEl) return if (loadingByAttr.value || !formEl) return
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loadingByAttr.value = true loadingByAttr.value = true
editAttr(formData).then(res => { editAttr(formData)
loadingByAttr.value = false .then((res) => {
showDialogByAttr.value = false loadingByAttr.value = false
loadAttrInfo() showDialogByAttr.value = false
}).catch(err => { loadAttrInfo()
loadingByAttr.value = false })
}) .catch((err) => {
} loadingByAttr.value = false
}) })
}
})
} }
// //
const deleteEvent = (index: any) => { const deleteEvent = (index: any) => {
ElMessageBox.confirm(t('goodsAttrDeleteTips'), t('warning'), { ElMessageBox.confirm(t('goodsAttrDeleteTips'), t('warning'), {
confirmButtonText: t('confirm'), confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'), cancelButtonText: t('cancel'),
type: 'warning', type: 'warning',
}).then(() => { }).then(() => {
if (repeatAttrValue.value) return if (repeatAttrValue.value) return
repeatAttrValue.value = true repeatAttrValue.value = true
attrInfo.attr_value_format.splice(index, 1); attrInfo.attr_value_format.splice(index, 1)
let data = { let data = {
attr_id: attrId.value, attr_id: attrId.value,
attr_value_format: JSON.stringify(attrInfo.attr_value_format) attr_value_format: JSON.stringify(attrInfo.attr_value_format),
}; }
modifyAttrValue(data).then(res => { modifyAttrValue(data)
repeatAttrValue.value = false .then((res) => {
loadAttrInfo() repeatAttrValue.value = false
}).catch(err => { loadAttrInfo()
repeatAttrValue.value = false })
}) .catch((err) => {
}) repeatAttrValue.value = false
})
})
} }
const showDialogByAttrValue = ref(false) const showDialogByAttrValue = ref(false)
const loadingByAttrValue = ref(false) const loadingByAttrValue = ref(false)
const formAttrValueRef = ref<FormInstance>() const formAttrValueRef = ref<FormInstance>()
const attrValueTitleDialog = ref('') const attrValueTitleDialog = ref('')
const formAttrValueData:any = reactive({ const formAttrValueData: any = reactive({
attr_value_id: 0, attr_value_id: 0,
attr_value_name: '', attr_value_name: '',
type: 'radio', type: 'radio',
sort: 0, sort: 0,
child: <any>[] child: <any>[],
}) })
// //
const attrValueTypeOptions = reactive([ const attrValueTypeOptions = reactive([
{ {
label:'单选', label: '单选',
value:'radio' value: 'radio',
}, },
{ {
label:'多选', label: '多选',
value:'checkbox' value: 'checkbox',
}, },
{ {
label:'输入', label: '输入',
value:'text' value: 'text',
} },
]) ])
// 便 // 便
const generateRandom = () => { const generateRandom = () => {
return (Math.floor(new Date().getSeconds()) + Math.floor(new Date().getMilliseconds())); return (
Math.floor(new Date().getSeconds()) +
Math.floor(new Date().getMilliseconds())
)
} }
// //
const openAttrValueEvent = ()=> { const openAttrValueEvent = () => {
formAttrValueData.attr_value_id = attrInfo.attr_value_format.length + generateRandom(); formAttrValueData.attr_value_id =
formAttrValueData.attr_value_name = ''; attrInfo.attr_value_format.length + generateRandom()
formAttrValueData.type = 'radio'; formAttrValueData.attr_value_name = ''
formAttrValueData.sort = 0; formAttrValueData.type = 'radio'
formAttrValueData.child = []; formAttrValueData.sort = 0
formAttrValueData.child = []
showDialogByAttrValue.value = true;
attrValueTitleDialog.value = t('addShopGoodsAttr'); showDialogByAttrValue.value = true
actionAttrValueId.value = -1 attrValueTitleDialog.value = t('addShopGoodsAttr')
actionAttrValueId.value = -1
} }
// //
const sortInputListener = debounce((sort:any, row:any) => { const sortInputListener = debounce((sort: any, row: any) => {
if (isNaN(sort) || !/^\d{0,10}$/.test(sort)) { if (isNaN(sort) || !/^\d{0,10}$/.test(sort)) {
ElMessage({ ElMessage({
type: 'warning', type: 'warning',
message: `${t('sortTips')}` message: `${t('sortTips')}`,
}) })
return return
} }
for (let i = 0; i < attrInfo.attr_value_format.length; i++) { for (let i = 0; i < attrInfo.attr_value_format.length; i++) {
if (attrInfo.attr_value_format[i].attr_value_id == row.attr_value_id) { if (attrInfo.attr_value_format[i].attr_value_id == row.attr_value_id) {
attrInfo.attr_value_format[i].sort = sort; attrInfo.attr_value_format[i].sort = sort
break; break
}
} }
}
let data = {
attr_id: attrId.value, let data = {
attr_value_format: JSON.stringify(attrInfo.attr_value_format) attr_id: attrId.value,
}; attr_value_format: JSON.stringify(attrInfo.attr_value_format),
modifyAttrValue(data).then(res => { }
loadAttrInfo() modifyAttrValue(data)
}).catch(err => { .then((res) => {
loadAttrInfo()
}) })
.catch((err) => {})
}) })
// //
const addAttrValueEvent = ()=>{ const addAttrValueEvent = () => {
formAttrValueData.child.push({ formAttrValueData.child.push({
id: formAttrValueData.child.length + generateRandom(), id: formAttrValueData.child.length + generateRandom(),
name: '', name: '',
sort: 0 sort: 0,
}); })
} }
// //
const editAttrValueEvent = (data:any,index:any)=> { const editAttrValueEvent = (data: any, index: any) => {
attrValueTitleDialog.value = t('updateShopGoodsAttr'); attrValueTitleDialog.value = t('updateShopGoodsAttr')
actionAttrValueId.value = data.attr_value_id actionAttrValueId.value = data.attr_value_id
Object.assign(formAttrValueData,cloneDeep(data)) Object.assign(formAttrValueData, cloneDeep(data))
showDialogByAttrValue.value = true; showDialogByAttrValue.value = true
} }
// //
const formRulesByAttrValue = computed(() => { const formRulesByAttrValue = computed(() => {
return { return {
attr_value_name: [ attr_value_name: [
{ required: true, message: t('attrValueNamePlaceholder'), trigger: 'blur' } {
] required: true,
} message: t('attrValueNamePlaceholder'),
trigger: 'blur',
},
],
}
}) })
const actionAttrValueId = ref(-1) const actionAttrValueId = ref(-1)
const repeatAttrValue = ref(false) const repeatAttrValue = ref(false)
const confirmAttrValue = async (formEl: FormInstance | undefined) => { const confirmAttrValue = async (formEl: FormInstance | undefined) => {
if (loadingByAttrValue.value || !formEl) return if (loadingByAttrValue.value || !formEl) return
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
if(formAttrValueData.type != 'text'){ if (formAttrValueData.type != 'text') {
if(formAttrValueData.child.length == 0){ if (formAttrValueData.child.length == 0) {
ElMessage({type: 'warning', message: `${t('attrValueNamePlaceholder')}`}) ElMessage({
return; type: 'warning',
} message: `${t('attrValueNamePlaceholder')}`,
for(let i=0;i<formAttrValueData.child.length;i++){ })
if(formAttrValueData.child[i].name == ''){ return
ElMessage({type: 'warning', message: `${t('attrValueNamePlaceholder')}`}) }
break; for (let i = 0; i < formAttrValueData.child.length; i++) {
} if (formAttrValueData.child[i].name == '') {
} ElMessage({
} type: 'warning',
message: `${t('attrValueNamePlaceholder')}`,
if (repeatAttrValue.value) return
repeatAttrValue.value = true
formAttrValueData.child.sort((a: any, b: any) => {
return b.sort - a.sort
});
loadingByAttrValue.value = true
if(actionAttrValueId.value == -1) {
attrInfo.attr_value_format.push(formAttrValueData)
}else{
for (let i = 0; i < attrInfo.attr_value_format.length; i++) {
if (attrInfo.attr_value_format[i].attr_value_id == actionAttrValueId.value) {
attrInfo.attr_value_format[i] = cloneDeep(formAttrValueData)
break;
}
}
}
let data = {
attr_id : attrId.value,
attr_value_format : JSON.stringify(attrInfo.attr_value_format)
};
modifyAttrValue(data).then(res => {
loadingByAttrValue.value = false
showDialogByAttrValue.value = false
repeatAttrValue.value = false
loadAttrInfo()
}).catch(err => {
loadingByAttrValue.value = false
repeatAttrValue.value = false
}) })
break
}
} }
}) }
if (repeatAttrValue.value) return
repeatAttrValue.value = true
formAttrValueData.child.sort((a: any, b: any) => {
return b.sort - a.sort
})
loadingByAttrValue.value = true
if (actionAttrValueId.value == -1) {
attrInfo.attr_value_format.push(formAttrValueData)
} else {
for (let i = 0; i < attrInfo.attr_value_format.length; i++) {
if (
attrInfo.attr_value_format[i].attr_value_id ==
actionAttrValueId.value
) {
attrInfo.attr_value_format[i] = cloneDeep(formAttrValueData)
break
}
}
}
let data = {
attr_id: attrId.value,
attr_value_format: JSON.stringify(attrInfo.attr_value_format),
}
modifyAttrValue(data)
.then((res) => {
loadingByAttrValue.value = false
showDialogByAttrValue.value = false
repeatAttrValue.value = false
loadAttrInfo()
})
.catch((err) => {
loadingByAttrValue.value = false
repeatAttrValue.value = false
})
}
})
} }
// //
const deleteAttrValueEvent = (item:any,index:any)=> { const deleteAttrValueEvent = (item: any, index: any) => {
formAttrValueData.child.splice(index,1); formAttrValueData.child.splice(index, 1)
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

328
admin/src/addon/shop/views/goods/brand_list.vue

@ -1,77 +1,132 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<div class="flex justify-between items-center"> <span class="text-page-title">{{ pageName }}</span>
<span class="text-page-title">{{ pageName }}</span> <el-button type="primary" @click="addEvent">
<el-button type="primary" @click="addEvent"> {{ t('addBrand') }}
{{ t('addBrand') }} </el-button>
</el-button> </div>
</div>
<el-card
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> class="box-card !border-none my-[10px] table-search-wrap"
<el-form :inline="true" :model="brandTable.searchParam" ref="searchFormRef"> shadow="never"
<el-form-item :label="t('brandName')" prop="brand_name"> >
<el-input v-model.trim="brandTable.searchParam.brand_name" :placeholder="t('brandNamePlaceholder')" /> <el-form
</el-form-item> :inline="true"
:model="brandTable.searchParam"
<el-form-item> ref="searchFormRef"
<el-button type="primary" @click="loadBrandList()">{{ t('search') }}</el-button> >
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> <el-form-item :label="t('brandName')" prop="brand_name">
</el-form-item> <el-input
</el-form> v-model.trim="brandTable.searchParam.brand_name"
</el-card> :placeholder="t('brandNamePlaceholder')"
/>
<div class="mt-[10px]"> </el-form-item>
<el-table :data="brandTable.data" size="large" v-loading="brandTable.loading" @sort-change="sortChange">
<template #empty> <el-form-item>
<span>{{ !brandTable.loading ? t('emptyData') : '' }}</span> <el-button type="primary" @click="loadBrandList()">{{
</template> t('search')
<el-table-column prop="brand_name" :label="t('brandName')" min-width="120" /> }}</el-button>
<el-table-column :label="t('logo')" min-width="120"> <el-button @click="resetForm(searchFormRef)">{{
<template #default="{ row }"> t('reset')
<div class="h-[30px]"> }}</el-button>
<el-image class="w-[30px] h-[30px] " :src="img(row.logo)" fit="contain"> </el-form-item>
<template #error> </el-form>
<div class="image-slot"> </el-card>
<img class="w-[30px] h-[30px]" src="@/addon/shop/assets/brand_default.png" />
</div> <div class="mt-[10px]">
</template> <el-table
</el-image> :data="brandTable.data"
</div> size="large"
</template> v-loading="brandTable.loading"
</el-table-column> @sort-change="sortChange"
<el-table-column prop="sort" :label="t('sort')" min-width="120" sortable="custom"> >
<template #default="{ row }"> <template #empty>
<el-input v-model.trim="row.sort" class="!w-[100px]" maxlength="8" @blur="sortInputListener(row.sort, row)" /> <span>{{ !brandTable.loading ? t('emptyData') : '' }}</span>
</template> </template>
</el-table-column> <el-table-column
prop="brand_name"
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120"> :label="t('brandName')"
<template #default="{ row }"> min-width="120"
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> />
<el-button type="primary" link @click="deleteEvent(row.brand_id)">{{ t('delete') }} <el-table-column :label="t('logo')" min-width="120">
</el-button> <template #default="{ row }">
</template> <div class="h-[30px]">
</el-table-column> <el-image
class="w-[30px] h-[30px]"
</el-table> :src="img(row.logo)"
<div class="mt-[16px] flex justify-end"> fit="contain"
<el-pagination v-model:current-page="brandTable.page" v-model:page-size="brandTable.limit" >
layout="total, sizes, prev, pager, next, jumper" :total="brandTable.total" <template #error>
@size-change="loadBrandList()" @current-change="loadBrandList" /> <div class="image-slot">
</div> <img
</div> class="w-[30px] h-[30px]"
src="@/addon/shop/assets/brand_default.png"
<brand-edit ref="editBrandDialog" @complete="loadBrandList" /> />
</el-card> </div>
</div> </template>
</el-image>
</div>
</template>
</el-table-column>
<el-table-column
prop="sort"
:label="t('sort')"
min-width="120"
sortable="custom"
>
<template #default="{ row }">
<el-input
v-model.trim="row.sort"
class="!w-[100px]"
maxlength="8"
@blur="sortInputListener(row.sort, row)"
/>
</template>
</el-table-column>
<el-table-column
:label="t('operation')"
fixed="right"
align="right"
min-width="120"
>
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button type="primary" link @click="deleteEvent(row.brand_id)"
>{{ t('delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="brandTable.page"
v-model:page-size="brandTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="brandTable.total"
@size-change="loadBrandList()"
@current-change="loadBrandList"
/>
</div>
</div>
<brand-edit ref="editBrandDialog" @complete="loadBrandList" />
</el-card>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getBrandPageList, deleteBrand, modifyBrandSort } from '@/addon/shop/api/goods' import {
getBrandPageList,
deleteBrand,
modifyBrandSort,
} from '@/addon/shop/api/goods'
import { img, debounce } from '@/utils/common' import { img, debounce } from '@/utils/common'
import { ElMessageBox, FormInstance, ElMessage } from 'element-plus' import { ElMessageBox, FormInstance, ElMessage } from 'element-plus'
import BrandEdit from '@/addon/shop/views/goods/components/brand-edit.vue' import BrandEdit from '@/addon/shop/views/goods/components/brand-edit.vue'
@ -81,52 +136,54 @@ const route = useRoute()
const pageName = route.meta.title const pageName = route.meta.title
const brandTable = reactive({ const brandTable = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
total: 0, total: 0,
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
brand_name: '', brand_name: '',
order: '', order: '',
sort: '' sort: '',
} },
}) })
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()
// //
const sortChange = (event: any) => { const sortChange = (event: any) => {
let sort = '' let sort = ''
if (event.order == 'ascending') { if (event.order == 'ascending') {
sort = 'asc' sort = 'asc'
} else if (event.order == 'descending') { } else if (event.order == 'descending') {
sort = 'desc' sort = 'desc'
} }
if (sort) { if (sort) {
brandTable.searchParam.order = event.prop brandTable.searchParam.order = event.prop
brandTable.searchParam.sort = sort brandTable.searchParam.sort = sort
} }
loadBrandList() loadBrandList()
} }
/** /**
* 获取商品品牌列表 * 获取商品品牌列表
*/ */
const loadBrandList = (page: number = 1) => { const loadBrandList = (page: number = 1) => {
brandTable.loading = true brandTable.loading = true
brandTable.page = page brandTable.page = page
getBrandPageList({ getBrandPageList({
page: brandTable.page, page: brandTable.page,
limit: brandTable.limit, limit: brandTable.limit,
...brandTable.searchParam ...brandTable.searchParam,
}).then(res => { })
brandTable.loading = false .then((res) => {
brandTable.data = res.data.data brandTable.loading = false
brandTable.total = res.data.total brandTable.data = res.data.data
}).catch(() => { brandTable.total = res.data.total
brandTable.loading = false })
.catch(() => {
brandTable.loading = false
}) })
} }
loadBrandList() loadBrandList()
@ -137,8 +194,8 @@ const editBrandDialog: Record<string, any> | null = ref(null)
* 添加商品品牌 * 添加商品品牌
*/ */
const addEvent = () => { const addEvent = () => {
editBrandDialog.value.setFormData() editBrandDialog.value.setFormData()
editBrandDialog.value.showDialog = true editBrandDialog.value.showDialog = true
} }
/** /**
@ -146,52 +203,49 @@ const addEvent = () => {
* @param data * @param data
*/ */
const editEvent = (data: any) => { const editEvent = (data: any) => {
editBrandDialog.value.setFormData(data) editBrandDialog.value.setFormData(data)
editBrandDialog.value.showDialog = true editBrandDialog.value.showDialog = true
} }
/** /**
* 删除商品品牌 * 删除商品品牌
*/ */
const deleteEvent = (id: number) => { const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('brandDeleteTips'), t('warning'), ElMessageBox.confirm(t('brandDeleteTips'), t('warning'), {
{ confirmButtonText: t('confirm'),
confirmButtonText: t('confirm'), cancelButtonText: t('cancel'),
cancelButtonText: t('cancel'), type: 'warning',
type: 'warning' }).then(() => {
} deleteBrand(id)
).then(() => { .then(() => {
deleteBrand(id).then(() => { loadBrandList()
loadBrandList() })
}).catch(() => { .catch(() => {})
}) })
})
} }
// //
const sortInputListener = debounce((sort, row) => { const sortInputListener = debounce((sort, row) => {
if (isNaN(sort) || !/^\d{0,8}$/.test(sort)) { if (isNaN(sort) || !/^\d{0,8}$/.test(sort)) {
ElMessage({ ElMessage({
type: 'warning', type: 'warning',
message: `${ t('sortTips') }` message: `${t('sortTips')}`,
})
return
}
if (sort > 99999999) {
row.sort = 99999999
}
modifyBrandSort({
brand_id: row.brand_id,
sort
}).then((res) => {
}) })
return
}
if (sort > 99999999) {
row.sort = 99999999
}
modifyBrandSort({
brand_id: row.brand_id,
sort,
}).then((res) => {})
}) })
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
loadBrandList() loadBrandList()
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

399
admin/src/addon/shop/views/goods/category.vue

@ -1,75 +1,118 @@
<template> <template>
<div class="main-container"> <div class="main-container">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center mb-[5px]"> <div class="flex justify-between items-center mb-[5px]">
<span class="text-page-title">{{ pageName }}</span> <span class="text-page-title">{{ pageName }}</span>
<el-button type="primary" @click="addEvent"> <el-button type="primary" @click="addEvent">
{{ t('addCategory') }} {{ t('addCategory') }}
</el-button> </el-button>
</div> </div>
<el-tabs class="demo-tabs" model-value="/shop/goods/category" @tab-change="handleClick"> <el-tabs
<el-tab-pane :label="t('tabGoodsCategory')" name="/shop/goods/category" /> class="demo-tabs"
<el-tab-pane :label="t('tabGoodsCategoryConfig')" name="/shop/goods/category/config" /> model-value="/shop/goods/category"
</el-tabs> @tab-change="handleClick"
<div class="mt-[10px]"> >
<el-table :data="categoryTable.data" ref="tableRef" size="large" v-loading="categoryTable.loading" row-key="category_id" :tree-props="{ hasChildren: 'hasChildren', children: 'child_list' }"> <el-tab-pane
<template #empty> :label="t('tabGoodsCategory')"
<span>{{ !categoryTable.loading ? t('emptyData') : '' }}</span> name="/shop/goods/category"
</template> />
<el-table-column :label="t('categoryName')" min-width="120"> <el-tab-pane
<template #default="{ row }"> :label="t('tabGoodsCategoryConfig')"
<i class="order-0 iconfont icontuodong vues-rank mr-[8px]"></i> name="/shop/goods/category/config"
<span class="order-2">{{ row.category_name }}</span> />
</template> </el-tabs>
</el-table-column> <div class="mt-[10px]">
<el-table-column :label="t('image')" width="170" align="left"> <el-table
<template #default="{ row }"> :data="categoryTable.data"
<div class="h-[30px]"> ref="tableRef"
<el-image class="w-[30px] h-[30px] " :src="img(row.image)" fit="contain"> size="large"
<template #error> v-loading="categoryTable.loading"
<div class="image-slot"> row-key="category_id"
<img class="w-[30px] h-[30px]" src="@/addon/shop/assets/category_default.png" /> :tree-props="{ hasChildren: 'hasChildren', children: 'child_list' }"
</div> >
</template> <template #empty>
</el-image> <span>{{ !categoryTable.loading ? t('emptyData') : '' }}</span>
</div> </template>
</template> <el-table-column :label="t('categoryName')" min-width="120">
</el-table-column> <template #default="{ row }">
<el-table-column prop="is_show" :label="t('isShow')" width="400"> <i class="order-0 iconfont icontuodong vues-rank mr-[8px]"></i>
<template #default="{ row }"> <span class="order-2">{{ row.category_name }}</span>
<el-tag class="cursor-pointer" :type="row.is_show != 2 ? 'success' : 'danger'" @click="showClick(row)">{{ row.is_show != 2 ? '' : '' }}</el-tag> </template>
</template> </el-table-column>
</el-table-column> <el-table-column :label="t('image')" width="170" align="left">
<el-table-column prop="sort" :label="t('sort')" width="120" /> <template #default="{ row }">
<el-table-column :label="t('operation')" fixed="right" align="right" width="200"> <div class="h-[30px]">
<template #default="{ row }"> <el-image
<el-button type="primary" link @click="spreadEvent(row)">{{ t('spreadGoodsCategory') }}</el-button> class="w-[30px] h-[30px]"
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> :src="img(row.image)"
<el-button type="primary" link @click="deleteEvent(row)">{{ t('delete') }}</el-button> fit="contain"
</template> >
</el-table-column> <template #error>
<div class="image-slot">
<img
class="w-[30px] h-[30px]"
src="@/addon/shop/assets/category_default.png"
/>
</div>
</template>
</el-image>
</div>
</template>
</el-table-column>
<el-table-column prop="is_show" :label="t('isShow')" width="400">
<template #default="{ row }">
<el-tag
class="cursor-pointer"
:type="row.is_show != 2 ? 'success' : 'danger'"
@click="showClick(row)"
>{{ row.is_show != 2 ? '是' : '否' }}</el-tag
>
</template>
</el-table-column>
<el-table-column prop="sort" :label="t('sort')" width="120" />
<el-table-column
:label="t('operation')"
fixed="right"
align="right"
width="200"
>
<template #default="{ row }">
<el-button type="primary" link @click="spreadEvent(row)">{{
t('spreadGoodsCategory')
}}</el-button>
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button type="primary" link @click="deleteEvent(row)">{{
t('delete')
}}</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-table> <category-edit ref="editCategoryDialog" @complete="loadCategoryList" />
</div> </el-card>
<category-edit ref="editCategoryDialog" @complete="loadCategoryList" /> <!-- 商品分类推广弹出框 -->
</el-card> <goods-category-spread-popup ref="goodsCategorySpreadPopupRef" />
</div>
<!-- 商品分类推广弹出框 -->
<goods-category-spread-popup ref="goodsCategorySpreadPopupRef" />
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref, onMounted, nextTick } from 'vue' import { reactive, ref, onMounted, nextTick } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getCategoryTree, deleteCategory, updateCategory, editCategory } from '@/addon/shop/api/goods' import {
getCategoryTree,
deleteCategory,
updateCategory,
editCategory,
} from '@/addon/shop/api/goods'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import { ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import categoryEdit from '@/addon/shop/views/goods/components/category-edit.vue' import categoryEdit from '@/addon/shop/views/goods/components/category-edit.vue'
import goodsCategorySpreadPopup from '@/addon/shop/views/goods/components/goods-category-spread-popup.vue' import goodsCategorySpreadPopup from '@/addon/shop/views/goods/components/goods-category-spread-popup.vue'
import { useRoute,useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
import { useTemplateRefsList } from '@vueuse/core' import { useTemplateRefsList } from '@vueuse/core'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
@ -78,114 +121,132 @@ const route = useRoute()
const pageName = route.meta.title const pageName = route.meta.title
const tableRef = useTemplateRefsList<HTMLElement>() const tableRef = useTemplateRefsList<HTMLElement>()
const categoryTable = reactive({ const categoryTable = reactive({
loading: true, loading: true,
data: [] data: [],
}) })
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
rowDrop() rowDrop()
}) })
loadCategoryList() loadCategoryList()
}) })
// //
const activeRows = ref<any[]>([]) const activeRows = ref<any[]>([])
// //
const rowDrop = () => { const rowDrop = () => {
const tbody = tableRef.value.$el.querySelector('.el-table__body-wrapper tbody') const tbody = tableRef.value.$el.querySelector(
Sortable.create(tbody, { '.el-table__body-wrapper tbody'
handle: '.vues-rank', )
animation: 300, Sortable.create(tbody, {
onMove: ({ dragged, related }) => { handle: '.vues-rank',
const oldRow = activeRows.value[dragged.rowIndex] // animation: 300,
const newRow = activeRows.value[related.rowIndex] // onMove: ({ dragged, related }) => {
if (oldRow.pid !== newRow.pid) { // id const oldRow = activeRows.value[dragged.rowIndex] //
return false // const newRow = activeRows.value[related.rowIndex] //
} if (oldRow.pid !== newRow.pid) {
}, // id
onStart: () => { // return false //
activeRows.value = treeToTile(cloneDeep(categoryTable.data)) // }
}, },
onEnd: e => { onStart: () => {
const oldRow = activeRows.value[e.oldIndex] // //
const newRow = activeRows.value[e.newIndex] // activeRows.value = treeToTile(cloneDeep(categoryTable.data)) //
},
onEnd: (e) => {
const oldRow = activeRows.value[e.oldIndex] //
const newRow = activeRows.value[e.newIndex] //
if (e.oldIndex === e.newIndex || oldRow.pid !== newRow.pid) return false if (e.oldIndex === e.newIndex || oldRow.pid !== newRow.pid) return false
const index = activeRows.value.indexOf(oldRow) const index = activeRows.value.indexOf(oldRow)
if (index < 0) return false if (index < 0) return false
const currRow = activeRows.value.splice(e.oldIndex, 1)[0] const currRow = activeRows.value.splice(e.oldIndex, 1)[0]
activeRows.value.splice(e.newIndex, 0, currRow) activeRows.value.splice(e.newIndex, 0, currRow)
const pid = newRow.pid const pid = newRow.pid
const currentRows = activeRows.value.filter(c => c.pid === pid)?.map((item, index) => { const currentRows = activeRows.value
if (item.level === 1 && item.category_id === currRow.category_id) { .filter((c) => c.pid === pid)
categoryTable.data = categoryTable.data.filter(c => c.category_id !== currRow.category_id) ?.map((item, index) => {
categoryTable.data.splice(index, 0, currRow) if (item.level === 1 && item.category_id === currRow.category_id) {
} categoryTable.data = categoryTable.data.filter(
if (item.level === 2 && item.category_id === currRow.category_id) { (c) => c.category_id !== currRow.category_id
const treeIndex = categoryTable.data.findIndex(el => el.category_id === item.pid) )
const obj = cloneDeep(categoryTable.data[treeIndex].child_list.filter(c => c.category_id !== currRow.category_id)) categoryTable.data.splice(index, 0, currRow)
categoryTable.data[treeIndex].child_list = [] }
categoryTable.data[treeIndex].child_list.push(...obj) if (item.level === 2 && item.category_id === currRow.category_id) {
categoryTable.data[treeIndex].child_list.splice(index, 0, currRow) const treeIndex = categoryTable.data.findIndex(
} (el) => el.category_id === item.pid
return { )
category_id: item.category_id, // const obj = cloneDeep(
sort: 9999 - index categoryTable.data[treeIndex].child_list.filter(
} (c) => c.category_id !== currRow.category_id
}) )
updateCategoryFn({ category_sort_array: currentRows }) )
} categoryTable.data[treeIndex].child_list = []
}) categoryTable.data[treeIndex].child_list.push(...obj)
categoryTable.data[treeIndex].child_list.splice(index, 0, currRow)
}
return {
category_id: item.category_id, //
sort: 9999 - index,
}
})
updateCategoryFn({ category_sort_array: currentRows })
},
})
} }
/** /**
* 将树数据转化为平铺数据 * 将树数据转化为平铺数据
* @param <Array> treeData当前要转的id * @param <Array> treeData当前要转的id
* @param <String> childKey 子级字段 * @param <String> childKey 子级字段
* @return <Array> 返回数据 * @return <Array> 返回数据
*/ */
const treeToTile = (treeData:any, childKey = 'child_list') => { const treeToTile = (treeData: any, childKey = 'child_list') => {
const arr:Array<any> = [] const arr: Array<any> = []
const expanded = (data:any) => { const expanded = (data: any) => {
if (data && data.length > 0) { if (data && data.length > 0) {
data.filter((d:any) => d).forEach((e:any) => { data
arr.push(e) .filter((d: any) => d)
expanded(e[childKey] || []) .forEach((e: any) => {
}) arr.push(e)
} expanded(e[childKey] || [])
})
} }
expanded(treeData) }
return arr expanded(treeData)
return arr
} }
/** /**
* 获取商品分类列表 * 获取商品分类列表
*/ */
const loadCategoryList = () => { const loadCategoryList = () => {
categoryTable.loading = true categoryTable.loading = true
getCategoryTree().then(res => { getCategoryTree()
categoryTable.loading = false .then((res) => {
categoryTable.data = res.data categoryTable.loading = false
}).catch(() => { categoryTable.data = res.data
categoryTable.loading = false })
.catch(() => {
categoryTable.loading = false
}) })
} }
const updateCategoryFn = (params: any) => { const updateCategoryFn = (params: any) => {
updateCategory(params).then(res => { updateCategory(params).then((res) => {
loadCategoryList() loadCategoryList()
}) })
} }
const showClick = (row: any) => { const showClick = (row: any) => {
row.is_show = row.is_show === 1 ? 2 : 1 row.is_show = row.is_show === 1 ? 2 : 1
const obj = cloneDeep(row) const obj = cloneDeep(row)
delete obj.child_list delete obj.child_list
editCategory(obj) editCategory(obj)
} }
const editCategoryDialog: Record<string, any> | null = ref(null) const editCategoryDialog: Record<string, any> | null = ref(null)
@ -193,8 +254,8 @@ const editCategoryDialog: Record<string, any> | null = ref(null)
* 添加商品分类 * 添加商品分类
*/ */
const addEvent = () => { const addEvent = () => {
editCategoryDialog.value.setFormData() editCategoryDialog.value.setFormData()
editCategoryDialog.value.showDialog = true editCategoryDialog.value.showDialog = true
} }
/** /**
@ -202,57 +263,59 @@ const addEvent = () => {
* @param data * @param data
*/ */
const editEvent = (data: any) => { const editEvent = (data: any) => {
editCategoryDialog.value.setFormData(data) editCategoryDialog.value.setFormData(data)
editCategoryDialog.value.showDialog = true editCategoryDialog.value.showDialog = true
} }
/** /**
* 删除商品分类 * 删除商品分类
*/ */
const deleteEvent = (row: any) => { const deleteEvent = (row: any) => {
ElMessageBox.confirm(!row.child_list || !row.child_list.length ? t('categoryDeleteTips') : t('categoryDeleteTips1'), t('warning'), ElMessageBox.confirm(
{ !row.child_list || !row.child_list.length
confirmButtonText: t('confirm'), ? t('categoryDeleteTips')
cancelButtonText: t('cancel'), : t('categoryDeleteTips1'),
type: 'warning' t('warning'),
} {
).then(() => { confirmButtonText: t('confirm'),
deleteCategory(row.category_id).then(() => { cancelButtonText: t('cancel'),
loadCategoryList() type: 'warning',
}).catch(() => { }
}) ).then(() => {
}) deleteCategory(row.category_id)
.then(() => {
loadCategoryList()
})
.catch(() => {})
})
} }
// 广 // 广
const goodsCategorySpreadPopupRef: any = ref(null) const goodsCategorySpreadPopupRef: any = ref(null)
const spreadEvent = (data: any) => { const spreadEvent = (data: any) => {
goodsCategorySpreadPopupRef.value.show(data) goodsCategorySpreadPopupRef.value.show(data)
} }
const router = useRouter() const router = useRouter()
const handleClick = (path: string) => { const handleClick = (path: string) => {
router.push({ path }) router.push({ path })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.el-table__row) { :deep(.el-table__row) {
> .el-table__cell:nth-child(1) { > .el-table__cell:nth-child(1) {
.cell { .cell {
display: flex; display: flex;
align-items: center; align-items: center;
.el-table__expand-icon,
.el-table__placeholder {
order: 1;
}
}
.el-table__expand-icon,
.el-table__placeholder {
order: 1;
}
} }
}
} }
</style> </style>

439
admin/src/addon/shop/views/goods/category_config.vue

@ -1,46 +1,109 @@
<template> <template>
<div class="main-container pt-[20px] bg-[#fff]" > <div class="main-container pt-[20px] bg-[#fff]">
<div class="flex ml-[18px] justify-between items-center mb-[5px]"> <div class="flex ml-[18px] justify-between items-center mb-[5px]">
<span class="text-page-title">{{ pageName }}</span> <span class="text-page-title">{{ pageName }}</span>
</div> </div>
<el-tabs class="demo-tabs mx-[18px]" model-value="/shop/goods/category/config" @tab-change="handleClick"> <el-tabs
<el-tab-pane :label="t('tabGoodsCategory')" name="/shop/goods/category" /> class="demo-tabs mx-[18px]"
<el-tab-pane :label="t('tabGoodsCategoryConfig')" name="/shop/goods/category/config" /> model-value="/shop/goods/category/config"
</el-tabs> @tab-change="handleClick"
<el-form v-if="Object.keys(formData).length" :model="formData" label-width="170" ref="formRef" :rules="rules" class="page-form" v-loading="loading"> >
<el-card class="box-card !border-none" shadow="never"> <el-tab-pane :label="t('tabGoodsCategory')" name="/shop/goods/category" />
<h3 class="panel-title !text-[16px] pl-[15px]">{{ t('categoryTemplate') }}</h3> <el-tab-pane
<el-form-item :label="t('categoryType')"> :label="t('tabGoodsCategoryConfig')"
<el-radio-group class="mx-[10px]" v-model="formData.level" @change="formData.template='style-1'"> name="/shop/goods/category/config"
<el-radio :label="1">{{ t('categorystyleOne') }}</el-radio> />
<el-radio :label="2">{{ t('categorystyleTwo') }}</el-radio> </el-tabs>
</el-radio-group> <el-form
</el-form-item> v-if="Object.keys(formData).length"
<el-form-item :label="t('categoryTemplate')"> :model="formData"
<template v-for="(item,index) in config['level_'+formData.level]" :key="index"> label-width="170"
<div :class="['w-[150px] border-[1px] border-[#ededed] border-solid overflow-hidden text-[#ededed] rounded-[4px] mr-[20px] relative', formData.template ===item.template ? 'border-color text-color' : '']" @click="levelChange(item.template)"> ref="formRef"
<img class="w-[100%]" :src="img(item.preview)" fit-object="contain" /> :rules="rules"
<span class="iconfont iconicon-selected absolute right-0 bottom-[-8px]"></span> class="page-form"
</div> v-loading="loading"
</template> >
</el-form-item> <el-card class="box-card !border-none" shadow="never">
</el-card> <h3 class="panel-title !text-[16px] pl-[15px]">
<el-card class="box-card !border-none" shadow="never"> {{ t('categoryTemplate') }}
<h3 class="panel-title !text-[16px] pl-[15px]">{{ t('pageSettings') }}</h3> </h3>
<el-form-item :label="t('pageTitle')" prop="page_title"> <el-form-item :label="t('categoryType')">
<el-input v-model.trim="formData.page_title" clearable :placeholder="t('pageTitlePlaceholder')" class="input-width" maxlength="10" show-word-limit /> <el-radio-group
</el-form-item> class="mx-[10px]"
<el-form-item :label="t('searchControl')"> v-model="formData.level"
<el-radio-group class="mx-[10px]" v-model="formData.search.control"> @change="formData.template = 'style-1'"
<el-radio :label="1">{{ t('open') }}</el-radio> >
<el-radio :label="0">{{ t('close') }}</el-radio> <el-radio :label="1">{{ t('categorystyleOne') }}</el-radio>
</el-radio-group> <el-radio :label="2">{{ t('categorystyleTwo') }}</el-radio>
</el-form-item> </el-radio-group>
<el-form-item v-if="formData.search.control" :label="t('searchTitle')" prop="search.title"> </el-form-item>
<el-input v-model.trim="formData.search.title" clearable :placeholder="t('searchTitlePlaceholder')" class="input-width" maxlength="12" show-word-limit /> <el-form-item :label="t('categoryTemplate')">
</el-form-item> <template
<template v-if="formData.level!=2||(formData.level===2&&formData.template != 'style-1')"> v-for="(item, index) in config['level_' + formData.level]"
<!-- <el-form-item :label="t('sort')" prop="sort"> :key="index"
>
<div
:class="[
'w-[150px] border-[1px] border-[#ededed] border-solid overflow-hidden text-[#ededed] rounded-[4px] mr-[20px] relative',
formData.template === item.template
? 'border-color text-color'
: '',
]"
@click="levelChange(item.template)"
>
<img
class="w-[100%]"
:src="img(item.preview)"
fit-object="contain"
/>
<span
class="iconfont iconicon-selected absolute right-0 bottom-[-8px]"
></span>
</div>
</template>
</el-form-item>
</el-card>
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-[16px] pl-[15px]">
{{ t('pageSettings') }}
</h3>
<el-form-item :label="t('pageTitle')" prop="page_title">
<el-input
v-model.trim="formData.page_title"
clearable
:placeholder="t('pageTitlePlaceholder')"
class="input-width"
maxlength="10"
show-word-limit
/>
</el-form-item>
<el-form-item :label="t('searchControl')">
<el-radio-group class="mx-[10px]" v-model="formData.search.control">
<el-radio :label="1">{{ t('open') }}</el-radio>
<el-radio :label="0">{{ t('close') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="formData.search.control"
:label="t('searchTitle')"
prop="search.title"
>
<el-input
v-model.trim="formData.search.title"
clearable
:placeholder="t('searchTitlePlaceholder')"
class="input-width"
maxlength="12"
show-word-limit
/>
</el-form-item>
<template
v-if="
formData.level != 2 ||
(formData.level === 2 && formData.template != 'style-1')
"
>
<!-- <el-form-item :label="t('sort')" prop="sort">
<el-select v-model="formData.sort" clearable :placeholder="t('sortPlaceholder')" <el-select v-model="formData.sort" clearable :placeholder="t('sortPlaceholder')"
class="input-width"> class="input-width">
<el-option label="综合" value="default" /> <el-option label="综合" value="default" />
@ -48,61 +111,99 @@
<el-option label="价格" value="price" /> <el-option label="价格" value="price" />
</el-select> </el-select>
</el-form-item> --> </el-form-item> -->
<!-- <el-form-item :label="t('goodsStyle')"> <!-- <el-form-item :label="t('goodsStyle')">
<el-radio-group class="mx-[10px]" v-model="formData.goods.style"> <el-radio-group class="mx-[10px]" v-model="formData.goods.style">
<el-radio label="single-cols">{{ t('singleCols') }}</el-radio> <el-radio label="single-cols">{{ t('singleCols') }}</el-radio>
<el-radio label="double-cols">{{ t('doubleCols') }}</el-radio> <el-radio label="double-cols">{{ t('doubleCols') }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> --> </el-form-item> -->
<el-form-item :label="t('cartControl')"> <el-form-item :label="t('cartControl')">
<el-radio-group class="mx-[10px]" v-model="formData.cart.control"> <el-radio-group class="mx-[10px]" v-model="formData.cart.control">
<el-radio :label="1">{{ t('show') }}</el-radio> <el-radio :label="1">{{ t('show') }}</el-radio>
<el-radio :label="0">{{ t('hidden') }}</el-radio> <el-radio :label="0">{{ t('hidden') }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<template v-if="formData.cart.control"> <template v-if="formData.cart.control">
<el-form-item :label="t('cartStyle')" class="carStyle"> <el-form-item :label="t('cartStyle')" class="carStyle">
<div class="flex items-center"> <div class="flex items-center">
<div :class="['flex items-center justify-center w-[65px] h-[65px] border-0 border-color rounded-[4px] border-solid box-border cursor-pointer mr-[15px]', formData.cart.style === 'style-1' ? '!border-[1px]' : '']" @click="carStyleClick(1)"> <div
<div class="text-[#fff] bg-color h-[20px] text-[12px] px-[10px] leading-[20px] rounded-[10px]"> :class="[
{{ formData.cart.text }} 'flex items-center justify-center w-[65px] h-[65px] border-0 border-color rounded-[4px] border-solid box-border cursor-pointer mr-[15px]',
</div> formData.cart.style === 'style-1' ? '!border-[1px]' : '',
</div> ]"
<!-- <div :class="['flex items-center justify-center w-[50px] h-[50px] border-0 border-color rounded-[4px] border-solid box-border cursor-pointer mr-[15px]', formData.cart.style === 'style-2' ? '!border-[1px]' : '']" @click="carStyleClick(1)"
>
<div
class="text-[#fff] bg-color h-[20px] text-[12px] px-[10px] leading-[20px] rounded-[10px]"
>
{{ formData.cart.text }}
</div>
</div>
<!-- <div :class="['flex items-center justify-center w-[50px] h-[50px] border-0 border-color rounded-[4px] border-solid box-border cursor-pointer mr-[15px]', formData.cart.style === 'style-2' ? '!border-[1px]' : '']"
@click="carStyleClick(2)"> @click="carStyleClick(2)">
<el-icon size="30px" class="text-color"> <el-icon size="30px" class="text-color">
<CirclePlusFilled /> <CirclePlusFilled />
</el-icon> </el-icon>
</div> --> </div> -->
<div :class="['flex items-center justify-center w-[65px] h-[65px] border-0 border-color rounded-[4px] border-solid box-border cursor-pointer mr-[15px]', formData.cart.style === 'style-3' ? '!border-[1px]' : '']" @click="carStyleClick(3)"> <div
<span class="text-color nc-iconfont nc-icon-gouwucheV6xx6 !text-[24px]"></span> :class="[
</div> 'flex items-center justify-center w-[65px] h-[65px] border-0 border-color rounded-[4px] border-solid box-border cursor-pointer mr-[15px]',
<div :class="['flex items-center justify-center w-[65px] h-[65px] border-0 border-color rounded-[4px] border-solid box-border cursor-pointer mr-[15px]', formData.cart.style === 'style-4' ? '!border-[1px]' : '']" @click="carStyleClick(4)"> formData.cart.style === 'style-3' ? '!border-[1px]' : '',
<div class="text-[#fff] bg-color h-[30px] w-[30px] leading-[30px] rounded-[30px] text-center"> ]"
<span class="nc-iconfont nc-icon-gouwucheV6xx6 !text-[20px]"></span> @click="carStyleClick(3)"
</div> >
</div> <span
</div> class="text-color nc-iconfont nc-icon-gouwucheV6xx6 !text-[24px]"
</el-form-item> ></span>
<el-form-item v-if="formData.cart.style === 'style-1'" prop="cart.text"> </div>
<el-input v-model.trim="formData.cart.text" clearable :placeholder="t('cartTextPlaceholder')" class="input-width" maxlength="3" show-word-limit /> <div
</el-form-item> :class="[
<el-form-item :label="t('cartEvent')"> 'flex items-center justify-center w-[65px] h-[65px] border-0 border-color rounded-[4px] border-solid box-border cursor-pointer mr-[15px]',
<el-radio-group class="mx-[10px]" v-model="formData.cart.event"> formData.cart.style === 'style-4' ? '!border-[1px]' : '',
<el-radio label="detail">{{ t('detail') }}</el-radio> ]"
<el-radio label="cart">{{ t('cart') }}</el-radio> @click="carStyleClick(4)"
</el-radio-group> >
</el-form-item> <div
</template> class="text-[#fff] bg-color h-[30px] w-[30px] leading-[30px] rounded-[30px] text-center"
</template> >
</el-card> <span
</el-form> class="nc-iconfont nc-icon-gouwucheV6xx6 !text-[20px]"
<div class="fixed-footer-wrap"> ></span>
<div class="fixed-footer"> </div>
<el-button type="primary" @click="onSave(formRef)">{{ t('save') }}</el-button> </div>
</div> </div>
</div> </el-form-item>
<el-form-item
v-if="formData.cart.style === 'style-1'"
prop="cart.text"
>
<el-input
v-model.trim="formData.cart.text"
clearable
:placeholder="t('cartTextPlaceholder')"
class="input-width"
maxlength="3"
show-word-limit
/>
</el-form-item>
<el-form-item :label="t('cartEvent')">
<el-radio-group class="mx-[10px]" v-model="formData.cart.event">
<el-radio label="detail">{{ t('detail') }}</el-radio>
<el-radio label="cart">{{ t('cart') }}</el-radio>
</el-radio-group>
</el-form-item>
</template>
</template>
</el-card>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" @click="onSave(formRef)">{{
t('save')
}}</el-button>
</div>
</div> </div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -110,127 +211,131 @@ import { reactive, ref, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getCategoryConfig, setCategoryConfig } from '@/addon/shop/api/goods' import { getCategoryConfig, setCategoryConfig } from '@/addon/shop/api/goods'
import { img } from '@/utils/common' import { img } from '@/utils/common'
import { useRoute,useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
const route = useRoute() const route = useRoute()
const pageName = route.meta.title const pageName = route.meta.title
interface formDataType { interface formDataType {
level: string|number level: string | number
template: string template: string
page_title: string page_title: string
search: { search: {
title: string title: string
control: number|string control: number | string
} }
sort: string sort: string
cart: { cart: {
control: number control: number
style: string style: string
text: string text: string
event: string event: string
} }
} }
const formData = ref<formDataType|any>({}) const formData = ref<formDataType | any>({})
const loading = ref(false) const loading = ref(false)
const rules = computed(() => { const rules = computed(() => {
return { return {
page_title: [ page_title: [
{ required: true, message: t('pageTitlePlaceholder'), trigger: 'blur' } { required: true, message: t('pageTitlePlaceholder'), trigger: 'blur' },
], ],
'search.title': [ 'search.title': [
{ required: true, message: t('searchTitlePlaceholder'), trigger: 'blur' } { required: true, message: t('searchTitlePlaceholder'), trigger: 'blur' },
], ],
sort: [ sort: [
{ required: true, message: t('sortPlaceholder'), trigger: 'change' } { required: true, message: t('sortPlaceholder'), trigger: 'change' },
], ],
'cart.text': [ 'cart.text': [
{ required: true, message: t('cartTextPlaceholder'), trigger: 'blur' } { required: true, message: t('cartTextPlaceholder'), trigger: 'blur' },
] ],
} }
}) })
interface configType { interface configType {
level_1: { level_1: {
template: string template: string
preview: string preview: string
}[] }[]
level_2: { level_2: {
template: string template: string
preview: string preview: string
}[] }[]
} }
const config = reactive<configType|any>({ const config = reactive<configType | any>({
level_1: [ level_1: [
{ {
template: 'style-1', template: 'style-1',
preview: 'addon/shop/category_style1_1.png' preview: 'addon/shop/category_style1_1.png',
} },
], ],
level_2: [ level_2: [
{ {
template: 'style-1', template: 'style-1',
preview: 'addon/shop/category_style2_1.png' preview: 'addon/shop/category_style2_1.png',
}, },
{ {
template: 'style-2', template: 'style-2',
preview: 'addon/shop/category_style2_2.png' preview: 'addon/shop/category_style2_2.png',
} },
] ],
}) })
const getCategoryConfigFn = () => { const getCategoryConfigFn = () => {
loading.value = true loading.value = true
getCategoryConfig().then(res => { getCategoryConfig()
formData.value = res.data .then((res) => {
loading.value = false formData.value = res.data
}).catch(() => { loading.value = false
loading.value = false })
.catch(() => {
loading.value = false
}) })
} }
getCategoryConfigFn() getCategoryConfigFn()
const levelChange = (value: any) => { const levelChange = (value: any) => {
formData.value.template = value formData.value.template = value
} }
const carStyleClick = (value: any) => { const carStyleClick = (value: any) => {
formData.value.cart.style = 'style-' + value formData.value.cart.style = 'style-' + value
} }
const formRef = ref() const formRef = ref()
const onSave = async (formEl: any) => { const onSave = async (formEl: any) => {
await formEl.validate(async (valid:any) => { await formEl.validate(async (valid: any) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
setCategoryConfig(formData.value).then(res => { setCategoryConfig(formData.value)
getCategoryConfigFn() .then((res) => {
}).catch(() => { getCategoryConfigFn()
loading.value = false })
}) .catch(() => {
} loading.value = false
}) })
}
})
} }
const router = useRouter() const router = useRouter()
const handleClick = (path: string) => { const handleClick = (path: string) => {
router.push({ path }) router.push({ path })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.border-color { .border-color {
border-color: var(--el-color-primary); border-color: var(--el-color-primary);
} }
.text-color { .text-color {
color: var(--el-color-primary); color: var(--el-color-primary);
} }
.bg-color { .bg-color {
background-color: var(--el-color-primary); background-color: var(--el-color-primary);
} }
.carStyle { .carStyle {
:deep(.el-form-item__label) { :deep(.el-form-item__label) {
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
} }
} }
</style> </style>

197
admin/src/addon/shop/views/goods/components/brand-edit.vue

@ -1,30 +1,71 @@
<template> <template>
<el-dialog v-model="showDialog" :title="title" width="500px" class="diy-dialog-wrap" :destroy-on-close="true"> <el-dialog
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading"> v-model="showDialog"
<el-form-item :label="t('brandName')" prop="brand_name"> :title="title"
<el-input v-model.trim="formData.brand_name" clearable :placeholder="t('brandNamePlaceholder')" class="input-width" maxlength="10" @blur="formData.brand_name = $event.target.value"/> width="500px"
</el-form-item> class="diy-dialog-wrap"
:destroy-on-close="true"
<el-form-item :label="t('logo')"> >
<upload-image v-model="formData.logo" /> <el-form
</el-form-item> :model="formData"
label-width="120px"
<el-form-item :label="t('desc')" > ref="formRef"
<el-input v-model.trim="formData.desc" type="textarea" clearable :placeholder="t('descPlaceholder')" class="input-width" maxlength="200"/> :rules="formRules"
</el-form-item> class="page-form"
v-loading="loading"
<el-form-item :label="t('sort')" > >
<el-input v-model.trim="formData.sort" maxlength="8" show-word-limit clearable :placeholder="t('sortPlaceholder')" class="input-width" @keyup="filterNumber($event)" @blur="formData.sort = $event.target.value"/> <el-form-item :label="t('brandName')" prop="brand_name">
</el-form-item> <el-input
</el-form> v-model.trim="formData.brand_name"
clearable
<template #footer> :placeholder="t('brandNamePlaceholder')"
<span class="dialog-footer"> class="input-width"
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button> maxlength="10"
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button> @blur="formData.brand_name = $event.target.value"
</span> />
</template> </el-form-item>
</el-dialog>
<el-form-item :label="t('logo')">
<upload-image v-model="formData.logo" />
</el-form-item>
<el-form-item :label="t('desc')">
<el-input
v-model.trim="formData.desc"
type="textarea"
clearable
:placeholder="t('descPlaceholder')"
class="input-width"
maxlength="200"
/>
</el-form-item>
<el-form-item :label="t('sort')">
<el-input
v-model.trim="formData.sort"
maxlength="8"
show-word-limit
clearable
:placeholder="t('sortPlaceholder')"
class="input-width"
@keyup="filterNumber($event)"
@blur="formData.sort = $event.target.value"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -43,11 +84,11 @@ const title = ref('')
* 表单数据 * 表单数据
*/ */
const initialFormData = { const initialFormData = {
brand_id: '', brand_id: '',
brand_name: '', brand_name: '',
logo: '', logo: '',
desc: '', desc: '',
sort: '' sort: '',
} }
const formData: Record<string, any> = reactive({ ...initialFormData }) const formData: Record<string, any> = reactive({ ...initialFormData })
@ -55,11 +96,11 @@ const formRef = ref<FormInstance>()
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
brand_name: [ brand_name: [
{ required: true, message: t('brandNamePlaceholder'), trigger: 'blur' } { required: true, message: t('brandNamePlaceholder'), trigger: 'blur' },
] ],
} }
}) })
const emit = defineEmits(['complete']) const emit = defineEmits(['complete'])
@ -69,59 +110,67 @@ const emit = defineEmits(['complete'])
* @param formEl * @param formEl
*/ */
const confirm = async (formEl: FormInstance | undefined) => { const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
const save = formData.brand_id ? editBrand : addBrand const save = formData.brand_id ? editBrand : addBrand
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
const data = formData const data = formData
save(data).then(res => { save(data)
loading.value = false .then((res) => {
showDialog.value = false loading.value = false
emit('complete') showDialog.value = false
}).catch(err => { emit('complete')
loading.value = false })
}) .catch((err) => {
} loading.value = false
}) })
}
})
} }
// //
const setFormData = async (row: any = null) => { const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData) Object.assign(formData, initialFormData)
loading.value = true loading.value = true
if (row) { if (row) {
const data = await (await getBrandInfo(row.brand_id)).data const data = await (await getBrandInfo(row.brand_id)).data
title.value = t('updateBrand') title.value = t('updateBrand')
if (data) { if (data) {
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
}
} else {
title.value = t('addBrand')
} }
loading.value = false } else {
title.value = t('addBrand')
}
loading.value = false
} }
const filterSpecial = (event:any) => { const filterSpecial = (event: any) => {
event.target.value = event.target.value.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '') event.target.value = event.target.value.replace(
event.target.value = event.target.value.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g, '') /[^\u4e00-\u9fa5a-zA-Z0-9]/g,
''
)
event.target.value = event.target.value.replace(
/[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g,
''
)
} }
defineExpose({ defineExpose({
showDialog, showDialog,
setFormData setFormData,
}) })
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
<style lang="scss"> <style lang="scss">
.diy-dialog-wrap .el-form-item__label{ .diy-dialog-wrap .el-form-item__label {
height: auto !important; height: auto !important;
} }
</style> </style>

232
admin/src/addon/shop/views/goods/components/category-edit.vue

@ -1,38 +1,84 @@
<template> <template>
<el-dialog v-model="showDialog" :title="title" width="480" class="diy-dialog-wrap" :destroy-on-close="true"> <el-dialog
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading"> v-model="showDialog"
<el-form-item :label="t('categoryName')" prop="category_name"> :title="title"
<el-input v-model.trim="formData.category_name" clearable :placeholder="t('categoryNamePlaceholder')" class="input-width" maxlength="10" show-word-limit /> width="480"
</el-form-item> class="diy-dialog-wrap"
<el-form-item :label="t('pid')" prop="pid"> :destroy-on-close="true"
<el-select v-model="formData.pid" clearable :disabled="formData.child_count" :placeholder="t('pidPlaceholder')" class="input-width"> >
<el-option label="顶级分类" :value="0" /> <el-form
<el-option v-for="(item) in optionList" :key="item.category_id" :label="item.category_name" :value="item.category_id" /> :model="formData"
</el-select> label-width="120px"
</el-form-item> ref="formRef"
<el-form-item :label="t('image')"> :rules="formRules"
<upload-image v-model="formData.image" /> class="page-form"
</el-form-item> v-loading="loading"
>
<el-form-item :label="t('isShow')" prop="is_show"> <el-form-item :label="t('categoryName')" prop="category_name">
<el-switch v-model="formData.is_show" class="input-width" :active-value="1" :inactive-value="2" /> <el-input
</el-form-item> v-model.trim="formData.category_name"
</el-form> clearable
:placeholder="t('categoryNamePlaceholder')"
<template #footer> class="input-width"
<span class="dialog-footer"> maxlength="10"
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button> show-word-limit
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button> />
</span> </el-form-item>
</template> <el-form-item :label="t('pid')" prop="pid">
</el-dialog> <el-select
v-model="formData.pid"
clearable
:disabled="formData.child_count"
:placeholder="t('pidPlaceholder')"
class="input-width"
>
<el-option label="顶级分类" :value="0" />
<el-option
v-for="item in optionList"
:key="item.category_id"
:label="item.category_name"
:value="item.category_id"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('image')">
<upload-image v-model="formData.image" />
</el-form-item>
<el-form-item :label="t('isShow')" prop="is_show">
<el-switch
v-model="formData.is_show"
class="input-width"
:active-value="1"
:inactive-value="2"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, computed } from 'vue' import { ref, reactive, computed } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { addCategory, editCategory, getCategoryInfo, getCategoryList } from '@/addon/shop/api/goods' import {
addCategory,
editCategory,
getCategoryInfo,
getCategoryList,
} from '@/addon/shop/api/goods'
const showDialog = ref(false) const showDialog = ref(false)
const loading = ref(false) const loading = ref(false)
@ -42,14 +88,14 @@ const title = ref('')
* 表单数据 * 表单数据
*/ */
const initialFormData = { const initialFormData = {
category_id: '', category_id: '',
category_name: '', category_name: '',
image: '', image: '',
pid: 0, pid: 0,
is_show: 1, is_show: 1,
child_count: 0, child_count: 0,
// sort: 9999, // sort: 9999,
level: 1 level: 1,
} }
const formData: Record<string, any> = reactive({ ...initialFormData }) const formData: Record<string, any> = reactive({ ...initialFormData })
@ -57,22 +103,24 @@ const formRef = ref<FormInstance>()
// //
const formRules = computed(() => { const formRules = computed(() => {
return { return {
category_id: [ category_id: [
{ required: true, message: t('categoryIdPlaceholder'), trigger: 'blur' } { required: true, message: t('categoryIdPlaceholder'), trigger: 'blur' },
], ],
category_name: [ category_name: [
{ required: true, message: t('categoryNamePlaceholder'), trigger: 'blur' } {
], required: true,
pid: [ message: t('categoryNamePlaceholder'),
{ required: true, message: t('pidPlaceholder'), trigger: 'change' } trigger: 'blur',
] },
} ],
pid: [{ required: true, message: t('pidPlaceholder'), trigger: 'change' }],
}
}) })
interface optionListType { interface optionListType {
category_id: number category_id: number
category_name: string category_name: string
} }
const optionList = ref<optionListType[]>([]) const optionList = ref<optionListType[]>([])
const emit = defineEmits(['complete']) const emit = defineEmits(['complete'])
@ -82,63 +130,67 @@ const emit = defineEmits(['complete'])
* @param formEl * @param formEl
*/ */
const confirm = async (formEl: FormInstance | undefined) => { const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return if (loading.value || !formEl) return
const save = formData.category_id ? editCategory : addCategory const save = formData.category_id ? editCategory : addCategory
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
loading.value = true loading.value = true
const data = formData const data = formData
save(data).then(res => { save(data)
loading.value = false .then((res) => {
showDialog.value = false loading.value = false
emit('complete') showDialog.value = false
}).catch(err => { emit('complete')
loading.value = false })
}) .catch((err) => {
} loading.value = false
}) })
}
})
} }
// //
const getCategoryAllFn = () => { const getCategoryAllFn = () => {
getCategoryList({ getCategoryList({
level: 1 level: 1,
}).then(res => { }).then((res) => {
optionList.value = res.data.filter((el: any) => el.category_id != formData.category_id) optionList.value = res.data.filter(
}) (el: any) => el.category_id != formData.category_id
)
})
} }
const setFormData = async (row: any = null) => { const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData) Object.assign(formData, initialFormData)
loading.value = true loading.value = true
if (row) { if (row) {
title.value = t('updateCategory') title.value = t('updateCategory')
const data = await (await getCategoryInfo(row.category_id)).data const data = await (await getCategoryInfo(row.category_id)).data
if (data) { if (data) {
Object.keys(formData).forEach((key: string) => { Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key] if (data[key] != undefined) formData[key] = data[key]
}) })
}
} else {
title.value = t('addCategory')
} }
getCategoryAllFn() } else {
loading.value = false title.value = t('addCategory')
}
getCategoryAllFn()
loading.value = false
} }
defineExpose({ defineExpose({
showDialog, showDialog,
setFormData setFormData,
}) })
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
<style lang="scss"> <style lang="scss">
.diy-dialog-wrap .el-form-item__label { .diy-dialog-wrap .el-form-item__label {
height: auto !important; height: auto !important;
} }
</style> </style>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save