Browse Source

首次提交

master
liutong 1 year ago
parent
commit
872eab7de8
  1. 23
      .gitignore
  2. 1
      niucloud/.env
  3. 1
      niucloud/.example.env
  4. 4
      niucloud/.gitignore
  5. 0
      niucloud/.htaccess
  6. 42
      niucloud/.travis.yml
  7. 56
      niucloud/README.md
  8. 1265
      niucloud/addon/shop/Addon.php
  9. 268
      niucloud/addon/shop/admin/api/delivery.ts
  10. 116
      niucloud/addon/shop/admin/api/electronic_sheet.ts
  11. 736
      niucloud/addon/shop/admin/api/goods.ts
  12. 590
      niucloud/addon/shop/admin/api/marketing.ts
  13. 250
      niucloud/addon/shop/admin/api/order.ts
  14. 43
      niucloud/addon/shop/admin/api/shop.ts
  15. 62
      niucloud/addon/shop/admin/api/shop_address.ts
  16. 30
      niucloud/addon/shop/admin/api/stat.ts
  17. BIN
      niucloud/addon/shop/admin/assets/brand_default.png
  18. BIN
      niucloud/addon/shop/admin/assets/category_default.png
  19. BIN
      niucloud/addon/shop/admin/assets/category_style2_new.png
  20. BIN
      niucloud/addon/shop/admin/assets/category_style3_new.png
  21. BIN
      niucloud/addon/shop/admin/assets/category_style4_new.png
  22. BIN
      niucloud/addon/shop/admin/assets/discount_banner.png
  23. BIN
      niucloud/addon/shop/admin/assets/discount_config.png
  24. BIN
      niucloud/addon/shop/admin/assets/goods_default.png
  25. BIN
      niucloud/addon/shop/admin/assets/store_default.png
  26. 35
      niucloud/addon/shop/admin/lang/zh-cn/address.edit.json
  27. 25
      niucloud/addon/shop/admin/lang/zh-cn/address.list.json
  28. 128
      niucloud/addon/shop/admin/lang/zh-cn/common.json
  29. 20
      niucloud/addon/shop/admin/lang/zh-cn/delivery.company.json
  30. 44
      niucloud/addon/shop/admin/lang/zh-cn/delivery.company_edit.json
  31. 11
      niucloud/addon/shop/admin/lang/zh-cn/delivery.config.json
  32. 17
      niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet.json
  33. 21
      niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_config.json
  34. 34
      niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_edit.json
  35. 55
      niucloud/addon/shop/admin/lang/zh-cn/delivery.local.json
  36. 20
      niucloud/addon/shop/admin/lang/zh-cn/delivery.search.json
  37. 9
      niucloud/addon/shop/admin/lang/zh-cn/delivery.staff.json
  38. 18
      niucloud/addon/shop/admin/lang/zh-cn/delivery.store.json
  39. 38
      niucloud/addon/shop/admin/lang/zh-cn/delivery.store_edit.json
  40. 12
      niucloud/addon/shop/admin/lang/zh-cn/delivery.template.json
  41. 39
      niucloud/addon/shop/admin/lang/zh-cn/delivery.template_edit.json
  42. 10
      niucloud/addon/shop/admin/lang/zh-cn/goods.attr.json
  43. 18
      niucloud/addon/shop/admin/lang/zh-cn/goods.attr_edit.json
  44. 15
      niucloud/addon/shop/admin/lang/zh-cn/goods.brand_list.json
  45. 26
      niucloud/addon/shop/admin/lang/zh-cn/goods.category.json
  46. 27
      niucloud/addon/shop/admin/lang/zh-cn/goods.category_config.json
  47. 49
      niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate.json
  48. 37
      niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate_edit.json
  49. 12
      niucloud/addon/shop/admin/lang/zh-cn/goods.label_group_list.json
  50. 30
      niucloud/addon/shop/admin/lang/zh-cn/goods.label_list.json
  51. 154
      niucloud/addon/shop/admin/lang/zh-cn/goods.list.json
  52. 174
      niucloud/addon/shop/admin/lang/zh-cn/goods.real_edit.json
  53. 29
      niucloud/addon/shop/admin/lang/zh-cn/goods.recycle.json
  54. 10
      niucloud/addon/shop/admin/lang/zh-cn/goods.service.json
  55. 167
      niucloud/addon/shop/admin/lang/zh-cn/goods.virtual_edit.json
  56. 20
      niucloud/addon/shop/admin/lang/zh-cn/index.index.json
  57. 42
      niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.add.json
  58. 42
      niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.edit.json
  59. 47
      niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.list.json
  60. 38
      niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.add.json
  61. 8
      niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.config.json
  62. 37
      niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.detail.json
  63. 38
      niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.edit.json
  64. 50
      niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.list.json
  65. 66
      niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_add.json
  66. 67
      niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_edit.json
  67. 27
      niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_list.json
  68. 55
      niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.order_list.json
  69. 13
      niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.config.json
  70. 33
      niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.edit.json
  71. 17
      niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.list.json
  72. 37
      niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.detail.json
  73. 88
      niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.edit.json
  74. 58
      niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.list.json
  75. 45
      niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.config.json
  76. 57
      niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.order_list.json
  77. 25
      niucloud/addon/shop/admin/lang/zh-cn/order.batch_delivery.json
  78. 41
      niucloud/addon/shop/admin/lang/zh-cn/order.config.json
  79. 134
      niucloud/addon/shop/admin/lang/zh-cn/order.detail.json
  80. 40
      niucloud/addon/shop/admin/lang/zh-cn/order.invoice.json
  81. 161
      niucloud/addon/shop/admin/lang/zh-cn/order.list.json
  82. 106
      niucloud/addon/shop/admin/lang/zh-cn/order.refund.json
  83. 94
      niucloud/addon/shop/admin/lang/zh-cn/order.refund_detail.json
  84. 37
      niucloud/addon/shop/admin/lang/zh-cn/stat.goods.json
  85. 415
      niucloud/addon/shop/admin/views/address/edit.vue
  86. 156
      niucloud/addon/shop/admin/views/address/list.vue
  87. 161
      niucloud/addon/shop/admin/views/delivery/company.vue
  88. 307
      niucloud/addon/shop/admin/views/delivery/company_edit.vue
  89. 112
      niucloud/addon/shop/admin/views/delivery/components/delivery-personnel-edit.vue
  90. 136
      niucloud/addon/shop/admin/views/delivery/config.vue
  91. 198
      niucloud/addon/shop/admin/views/delivery/electronic_sheet.vue
  92. 184
      niucloud/addon/shop/admin/views/delivery/electronic_sheet_config.vue
  93. 270
      niucloud/addon/shop/admin/views/delivery/electronic_sheet_edit.vue
  94. 437
      niucloud/addon/shop/admin/views/delivery/local.vue
  95. 158
      niucloud/addon/shop/admin/views/delivery/search.vue
  96. 140
      niucloud/addon/shop/admin/views/delivery/staff.vue
  97. 168
      niucloud/addon/shop/admin/views/delivery/store.vue
  98. 408
      niucloud/addon/shop/admin/views/delivery/store_edit.vue
  99. 149
      niucloud/addon/shop/admin/views/delivery/template.vue
  100. 501
      niucloud/addon/shop/admin/views/delivery/template_edit.vue

23
.gitignore

@ -0,0 +1,23 @@
# Build and Release Folders
bin-debug/
bin-release/
[Oo]bj/
[Bb]in/
# Other files and folders
.settings/
# Executables
*.swf
*.air
*.ipa
*.apk
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
# should NOT be excluded as they contain compiler settings and other important
# information for Eclipse / Flash Builder.
/.idea
niucloud/public/.htaccess
#uni-app/*
#web/*

1
niucloud/.env

@ -0,0 +1 @@
APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai AUTH_KEY = ymektwfaxgsdigfpbnjoruhczasdvhql PRODUCT_KEY = {product_key} [DATABASE] TYPE = mysql HOSTNAME = 127.0.0.1 DATABASE = school_oa USERNAME = root PASSWORD = root HOSTPORT = 3306 PREFIX = school_ CHARSET = utf8mb4 DEBUG = false [REDIS] REDIS_HOSTNAME = 127.0.0.1 PORT = 6379 REDIS_PASSWORD = SELECT = 0 [QUEUE] state = false [LANG] default_lang = zh-cn [SYSTEM] ADMIN_TOKEN_NAME = token API_TOKEN_NAME = token ADMIN_TOKEN_EXPIRE_TIME = 604800 API_TOKEN_EXPIRE_TIME = 86400 LANG_NAME = lang CHANNEL_NAME = channel ADMIN_DOMAIN = WAP_DOMAIN = WEB_DOMAIN = [NIUCLOUD] code = secret =

1
niucloud/.example.env

@ -0,0 +1 @@
APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai AUTH_KEY = {auth_key} PRODUCT_KEY = {product_key} [DATABASE] TYPE = mysql HOSTNAME = {dbhost} DATABASE = {dbname} USERNAME = {dbuser} PASSWORD = {dbpwd} HOSTPORT = {dbport} PREFIX = {dbprefix} CHARSET = utf8mb4 DEBUG = false [REDIS] REDIS_HOSTNAME = 127.0.0.1 PORT = 6379 REDIS_PASSWORD = SELECT = 0 [QUEUE] state = false [LANG] default_lang = zh-cn [SYSTEM] ADMIN_TOKEN_NAME = token API_TOKEN_NAME = token ADMIN_TOKEN_EXPIRE_TIME = 604800 API_TOKEN_EXPIRE_TIME = 86400 LANG_NAME = lang CHANNEL_NAME = channel ADMIN_DOMAIN = WAP_DOMAIN = WEB_DOMAIN = [NIUCLOUD] code = secret =

4
niucloud/.gitignore

@ -0,0 +1,4 @@
/.idea
/.vscode
*.log
install.lock

0
niucloud/.htaccess

42
niucloud/.travis.yml

@ -0,0 +1,42 @@
sudo: false
language: php
branches:
only:
- stable
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
install:
- composer install --no-dev --no-interaction --ignore-platform-reqs
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
script:
- php think unit
deploy:
provider: releases
api_key:
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
file:
- ThinkPHP_Core.zip
- ThinkPHP_Full.zip
skip_cleanup: true
on:
tags: true

56
niucloud/README.md

@ -0,0 +1,56 @@
ThinkPHP 6.0
===============
> 运行环境要求PHP7.2+,兼容PHP8.1
[官方应用服务市场](https://market.topthink.com) | [`ThinkAPI`——官方统一API服务](https://docs.topthink.com/think-api)
ThinkPHPV6.0版本由[亿速云](https://www.yisu.com/)独家赞助发布。
## 主要新特性
* 采用`PHP7`强类型(严格模式)
* 支持更多的`PSR`规范
* 原生多应用支持
* 更强大和易用的查询
* 全新的事件系统
* 模型事件和数据库事件统一纳入事件系统
* 模板引擎分离出核心
* 内部功能中间件化
* SESSION/Cookie机制改进
* 对Swoole以及协程支持改进
* 对IDE更加友好
* 统一和精简大量用法
## 安装
~~~
composer create-project topthink/think tp 6.0.*
~~~
如果需要更新框架使用
~~~
composer update topthink/framework
~~~
## 文档
[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
## 参与开发
请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
## 版权信息
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2021 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)

1265
niucloud/addon/shop/Addon.php

File diff suppressed because it is too large

268
niucloud/addon/shop/admin/api/delivery.ts

@ -0,0 +1,268 @@
import request from '@/utils/request'
/********************************* 物流公司 ***************************************/
/**
*
* @param params
* @returns
*/
export function getCompanyPageList(params: Record<string, any>) {
return request.get(`shop/delivery/company`, { params })
}
/**
*
* @param params
* @returns
*/
export function getCompanyList(params: Record<string, any>) {
return request.get(`shop/delivery/company/list`, { params })
}
/**
*
* @param company_id company_id
* @returns
*/
export function getCompanyInfo(company_id: number) {
return request.get(`shop/delivery/company/${ company_id }`);
}
/**
*
* @param params
* @returns
*/
export function addCompany(params: Record<string, any>) {
return request.post('shop/delivery/company', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editCompany(params: Record<string, any>) {
return request.put(`shop/delivery/company/${ params.company_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param company_id
* @returns
*/
export function deleteCompany(company_id: number) {
return request.delete(`shop/delivery/company/${ company_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/********************************* 运费模版 ***************************************/
/**
*
* @param params
* @returns
*/
export function getShippingTemplatePageList(params: Record<string, any>) {
return request.get(`shop/shipping/template`, { params })
}
/**
*
* @param params
* @returns
*/
export function getShippingTemplateList(params: Record<string, any>) {
return request.get(`shop/shipping/template/list`, { params })
}
/**
*
* @param template_id template_id
* @returns
*/
export function getShippingTemplateInfo(template_id: number) {
return request.get(`shop/shipping/template/${ template_id }`);
}
/**
*
* @param params
* @returns
*/
export function addShippingTemplate(params: Record<string, any>) {
return request.post('shop/shipping/template', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editShippingTemplate(params: Record<string, any>) {
return request.put(`shop/shipping/template/${ params.template_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param template_id
* @returns
*/
export function deleteShippingTemplate(template_id: number) {
return request.delete(`shop/shipping/template/${ template_id }`, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/********************************* 自提门店 ***************************************/
/**
*
* @param params
* @returns
*/
export function getStoreList(params: Record<string, any>) {
return request.get(`shop/delivery/store`, { params })
}
/**
*
* @param store_id store_id
* @returns
*/
export function getStoreInfo(store_id: number) {
return request.get(`shop/delivery/store/${ store_id }`);
}
/**
*
* @param params
* @returns
*/
export function addStore(params: Record<string, any>) {
return request.post('shop/delivery/store', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editStore(params: Record<string, any>) {
return request.put(`shop/delivery/store/${ params.store_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param store_id
* @returns
*/
export function deleteStore(store_id: number) {
return request.delete(`shop/delivery/store/${ store_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/********************************* 物流查询 ***************************************/
/**
*
* @param params
* @returns
*/
export function setDeliverySearch(params: Record<string, any>) {
return request.post('shop/delivery/search', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getDeliverySearch() {
return request.get('shop/delivery/search')
}
/**
*
* @returns
*/
export function getShopDeliveryList() {
return request.get('shop/delivery/deliveryList')
}
/**
*
* @param params
* @returns
*/
export function setShopDeliveryConfig(params: Record<string, any>) {
return request.put(`shop/delivery/setConfig`, params)
}
/**
*
* @param params
* @returns
*/
export function getShopDelivery(params: Record<string, any>) {
return request.get('shop/delivery/staff', { params })
}
/**
*
* @param staff_id
* @returns
*/
export function getShopDeliverInfo(staff_id: number) {
return request.get(`shop/delivery/staff/${ staff_id }`);
}
/**
*
* @param params
* @returns
*/
export function addShopDeliver(params: Record<string, any>) {
return request.post('shop/delivery/staff', params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editShopDeliver(params: Record<string, any>) {
return request.put(`shop/delivery/staff/${ params.deliver_id }`, params, { showSuccessMessage: true })
}
/**
*
* @param staff_id
* @returns
*/
export function deleteShopDeliver(staff_id: number) {
return request.delete(`shop/delivery/staff/${ staff_id }`)
}
/**
*
* @returns
*/
export function getLocal() {
return request.get('shop/local');
}
/**
*
* @param params
* @returns
*/
export function setLocal(params: Record<string, any>) {
return request.put('shop/local', params, { showSuccessMessage: true })
}

116
niucloud/addon/shop/admin/api/electronic_sheet.ts

@ -0,0 +1,116 @@
import request from '@/utils/request'
/**
*
* @param params
* @returns
*/
export function getElectronicSheetPageList(params: Record<string, any>) {
return request.get(`shop/electronic_sheet`, { params })
}
/**
*
* @param params
* @returns
*/
export function getElectronicSheetList(params: Record<string, any>) {
return request.get(`shop/electronic_sheet/list`, { params })
}
/**
*
* @param id id
* @returns
*/
export function getElectronicSheetInfo(id: number) {
return request.get(`shop/electronic_sheet/${ id }`);
}
/**
*
* @param params
* @returns
*/
export function addElectronicSheet(params: Record<string, any>) {
return request.post('shop/electronic_sheet', params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function editElectronicSheet(params: Record<string, any>) {
return request.put(`shop/electronic_sheet/${ params.id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param id
* @returns
*/
export function deleteElectronicSheet(id: number) {
return request.delete(`shop/electronic_sheet/${ id }`, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function setDefaultElectronicSheet(params: Record<string, any>) {
return request.put(`shop/electronic_sheet/setDefault/${ params.id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function setElectronicSheetConfig(params: Record<string, any>) {
return request.post('shop/electronic_sheet/config', params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @returns
*/
export function getElectronicSheetConfig() {
return request.get(`shop/electronic_sheet/config`)
}
/**
*
* @returns
*/
export function getElectronicSheetPayType() {
return request.get(`shop/electronic_sheet/paytype`)
}
/**
*
* @param params
* @returns
*/
export function printElectronicSheet(params: Record<string, any>) {
return request.post('shop/electronic_sheet/print', params, {
showErrorMessage: true,
showSuccessMessage: true
})
}

736
niucloud/addon/shop/admin/api/goods.ts

@ -0,0 +1,736 @@
import request from '@/utils/request'
/**
*
* @param params
* @returns
*/
export function getGoodsPageList(params: Record<string, any>) {
return request.get(`shop/goods`, { params })
}
/**
*
* @param goods_id goods_id
* @returns
*/
export function getGoodsInfo(goods_id: number) {
return request.get(`shop/goods/${ goods_id }`);
}
/**
*
* @param params
* @returns
*/
export function addGoods(params: Record<string, any>) {
return request.post('shop/goods', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
*/
export function editGoods(params: Record<string, any>) {
return request.put(`shop/goods/${ params.goods_id }`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
* /
* @param params
*/
export function getGoodsInit(params: Record<string, any>) {
return request.get(`shop/goods/init`, { params });
}
/**
*
* @param params
* @returns
*/
export function addVirtualGoods(params: Record<string, any>) {
return request.post('shop/goods/virtual', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
*/
export function editVirtualGoods(params: Record<string, any>) {
return request.put(`shop/goods/virtual/${ params.goods_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
* /
* @param params
*/
export function getVirtualGoodsInit(params: Record<string, any>) {
return request.get(`shop/goods/virtual/init`, { params });
}
/**
*
* @param params
* @returns
*/
export function deleteGoods(params: Record<string, any>) {
return request.put(`shop/goods/delete`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getRecycleGoodsPageList(params: Record<string, any>) {
return request.get(`shop/goods/recycle`, { params })
}
/**
*
* @param params
* @returns
*/
export function recycleGoods(params: Record<string, any>) {
return request.put(`shop/goods/recycle`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
*/
export function editGoodsSort(params: Record<string, any>) {
return request.put(`shop/goods/sort`, params, { showSuccessMessage: true })
}
/**
*
* @param params
*/
export function editGoodsStatus(params: Record<string, any>) {
return request.put(`shop/goods/status`, params, { showSuccessMessage: true })
}
/**
*
* @param params
*/
export function copyGoods(params: Record<string, any>) {
return request.put(`shop/goods/copy/${ params.goods_id }`, params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getGoodsSelectPageList(params: Record<string, any>) {
return request.get(`shop/goods/select`, { params })
}
/**
* SKU规格列表
* @param params
* @returns
*/
export function getGoodsSkuList(params: Record<string, any>) {
return request.get(`shop/goods/sku`, { params })
}
/**
* SKU规格不分页列表
* @param params
* @returns
*/
export function getGoodsSkuNoPageList(params: Record<string, any>) {
return request.get(`shop/goods/selectgoodssku`, { params })
}
/**
* @param params
* @returns
*/
export function getActiveGoodsCount(params: Record<string, any>) {
return request.get(`shop/goods/active/count`, { params })
}
/**
* SKU规格库存
* @param params
* @returns
*/
export function editGoodsListStock(params: Record<string, any>) {
return request.put(`shop/goods/sku/stock`, params, { showSuccessMessage: true })
}
/**
* SKU规格价格
* @param params
* @returns
*/
export function editGoodsListPrice(params: Record<string, any>) {
return request.put(`shop/goods/sku/price`, params, { showSuccessMessage: true })
}
/**
* SKU规格会员价格
* @param params
* @returns
*/
export function editGoodsListMemberPrice(params: Record<string, any>) {
return request.put(`shop/goods/sku/member_price`, params, { showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getGoodsType() {
return request.get(`shop/goods/type`);
}
/**
*
* @param params
* @returns
*/
export function getLabelPageList(params: Record<string, any>) {
return request.get(`shop/goods/label`, { params })
}
/**
*
* @param params
* @returns
*/
export function getLabelList(params: Record<string, any>) {
return request.get(`shop/goods/label/list`, { params })
}
/**
*
* @param label_id label_id
* @returns
*/
export function getLabelInfo(label_id: number) {
return request.get(`shop/goods/label/${ label_id }`);
}
/**
*
* @param params
* @returns
*/
export function addLabel(params: Record<string, any>) {
return request.post('shop/goods/label', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editLabel(params: Record<string, any>) {
return request.put(`shop/goods/label/${ params.label_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
*/
export function modifyLabelStatus(params: Record<string, any>) {
return request.put(`shop/goods/label/status`, params, { showSuccessMessage: true })
}
/**
*
* @param label_id
* @returns
*/
export function deleteLabel(label_id: number) {
return request.delete(`shop/goods/label/${ label_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
*/
export function modifyLabelSort(params: Record<string, any>) {
return request.put(`shop/goods/label/sort`, params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getLabelGroupPageList(params: Record<string, any>) {
return request.get(`shop/goods/label/group`, { params })
}
/**
*
* @param params
* @returns
*/
export function getLabelGroupList(params: Record<string, any>) {
return request.get(`shop/goods/label/group/list`, { params })
}
/**
*
* @param label_id label_id
* @returns
*/
export function getLabelGroupInfo(label_id: number) {
return request.get(`shop/goods/label/group/${ label_id }`);
}
/**
*
* @param params
* @returns
*/
export function addLabelGroup(params: Record<string, any>) {
return request.post('shop/goods/label/group', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editLabelGroup(params: Record<string, any>) {
return request.put(`shop/goods/label/group/${ params.group_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param group_id
* @returns
*/
export function deleteLabelGroup(group_id: number) {
return request.delete(`shop/goods/label/group/${ group_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
*/
export function modifyLabelGroupSort(params: Record<string, any>) {
return request.put(`shop/goods/label/group/sort`, params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getBrandPageList(params: Record<string, any>) {
return request.get(`shop/goods/brand`, { params })
}
/**
*
* @param params
* @returns
*/
export function getBrandList(params: Record<string, any>) {
return request.get(`shop/goods/brand/list`, { params })
}
/**
*
* @param brand_id brand_id
* @returns
*/
export function getBrandInfo(brand_id: number) {
return request.get(`shop/goods/brand/${ brand_id }`);
}
/**
*
* @param params
* @returns
*/
export function addBrand(params: Record<string, any>) {
return request.post('shop/goods/brand', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editBrand(params: Record<string, any>) {
return request.put(`shop/goods/brand/${ params.brand_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
*/
export function modifyBrandSort(params: Record<string, any>) {
return request.put(`shop/goods/brand/sort`, params, { showSuccessMessage: true })
}
/**
*
* @param brand_id
* @returns
*/
export function deleteBrand(brand_id: number) {
return request.delete(`shop/goods/brand/${ brand_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getServePageList(params: Record<string, any>) {
return request.get(`shop/goods/service`, { params })
}
/**
*
* @param params
* @returns
*/
export function getServeList(params: Record<string, any>) {
return request.get(`shop/goods/service/list`, { params })
}
/**
*
* @param service_id service_id
* @returns
*/
export function getServeInfo(service_id: number) {
return request.get(`shop/goods/service/${ service_id }`);
}
/**
*
* @param params
* @returns
*/
export function addServe(params: Record<string, any>) {
return request.post('shop/goods/service', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editServe(params: Record<string, any>) {
return request.put(`shop/goods/service/${ params.service_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param service_id
* @returns
*/
export function deleteServe(service_id: number) {
return request.delete(`shop/goods/service/${ service_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getCategoryTree() {
return request.get(`shop/goods/tree`)
}
/**
*
* @param params
* @returns
*/
export function getCategoryList(params: Record<string, any>) {
return request.get(`shop/goods/category`, { params })
}
/**
*
* @param category_id category_id
* @returns
*/
export function getCategoryInfo(category_id: number) {
return request.get(`shop/goods/category/${ category_id }`);
}
/**
*
* @param params
* @returns
*/
export function addCategory(params: Record<string, any>) {
return request.post('shop/goods/category', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editCategory(params: Record<string, any>) {
return request.put(`shop/goods/category/${ params.category_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param category_id
* @returns
*/
export function deleteCategory(category_id: number) {
return request.delete(`shop/goods/category/${ category_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function updateCategory(params: Record<string, any>) {
return request.post(`shop/goods/category/update`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function setCategoryConfig(params: Record<string, any>) {
return request.post(`shop/goods/category/config`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getCategoryConfig() {
return request.get(`shop/goods/category/config`);
}
/**
*
* @returns
*/
export function getCategoryTreeComponents() {
return request.get(`shop/goods/category/components`)
}
/**
*
* @param params
* @returns
*/
export function getSupplierList(params: Record<string, any>) {
return request.get(`shop_supplier/supplier/list`, { params })
}
/**
*
* @param params
* @returns
*/
export function getEvaluateList(params: Record<string, any>) {
return request.get(`shop/goods/evaluate`, { params })
}
/**
*
* @param params
* @returns
*/
export function addEvaluate(params: Record<string, any>) {
return request.post('shop/goods/evaluate', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param evaluate_id
* @returns
*/
export function deleteEvaluate(evaluate_id: number) {
return request.delete(`shop/goods/evaluate/${ evaluate_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param evaluate_id
* @returns
*/
export function adoptEvaluate(evaluate_id: number) {
return request.put(`shop/goods/evaluate/adopt/${ evaluate_id }`, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param evaluate_id
* @returns
*/
export function refuseEvaluate(evaluate_id: number) {
return request.put(`shop/goods/evaluate/refuse/${ evaluate_id }`, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function replyEvaluate(params: Record<string, any>) {
return request.put(`shop/goods/evaluate/reply/${ params.evaluate_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param evaluate_id
* @returns
*/
export function toppingEvaluate(evaluate_id: number) {
return request.put(`shop/goods/evaluate/topping/${ evaluate_id }`, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param evaluate_id
* @returns
*/
export function cancelToppingEvaluate(evaluate_id: number) {
return request.put(`shop/goods/evaluate/cancel_topping/${ evaluate_id }`, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function getAttrPageList(params: Record<string, any>) {
return request.get(`shop/goods/attr`, { params })
}
/**
*
* @param params
* @returns
*/
export function getAttrList(params: Record<string, any>) {
return request.get(`shop/goods/attr/list`, { params })
}
/**
*
* @param attr_id attr_id
* @returns
*/
export function getAttrInfo(attr_id: number) {
return request.get(`shop/goods/attr/${ attr_id }`);
}
/**
*
* @param params
* @returns
*/
export function addAttr(params: Record<string, any>) {
return request.post('shop/goods/attr', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editAttr(params: Record<string, any>) {
return request.put(`shop/goods/attr/${ params.attr_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param attr_id
* @returns
*/
export function deleteAttr(attr_id: number) {
return request.delete(`shop/goods/attr/${ attr_id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
*/
export function modifyAttrSort(params: Record<string, any>) {
return request.put(`shop/goods/attr/sort`, params, { showSuccessMessage: true })
}
/**
*
* @param params
*/
export function modifyAttrName(params: Record<string, any>) {
return request.put(`shop/goods/attr/attr_name`, params, { showSuccessMessage: true })
}
/**
*
* @param params
*/
export function modifyAttrValue(params: Record<string, any>) {
return request.put(`shop/goods/attr/attr_value`, params, { showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getGoodsBatchSetDict() {
return request.get(`shop/goods/batchSet/dict`)
}
/**
*
* @param params
*/
export function goodsBatchSet(params: Record<string, any>) {
return request.put(`shop/goods/batchSet`, params, { showSuccessMessage: true })
}

590
niucloud/addon/shop/admin/api/marketing.ts

@ -0,0 +1,590 @@
import request from '@/utils/request'
/**
*
* @param params
* @returns
*/
export function getMarketingIndex(params: Record<string, any>) {
return request.get(`shop/marketing`, { params })
}
/**
*
* @param params
* @returns
*/
export function getGoodsCategoryList(params: Record<string, any>) {
return request.get(`shop/goods/coupon/init`, { params })
}
/**
*
* @param params
* @returns
*/
export function addCoupon(params: Record<string, any>) {
return request.post(`shop/goods/coupon`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getCouponStatusList() {
return request.get(`shop/goods/coupon/status`)
}
/**
*
* @param params
* @returns
*/
export function getCouponList(params: Record<string, any>) {
return request.get(`shop/goods/coupon`, { params })
}
/**
*
* @param params
* @returns
*/
export function getCouponSelectList(params: Record<string, any>) {
return request.get(`shop/goods/coupon/select`, { params })
}
/**
*
* @param params
* @returns
*/
export function getCouponRecords(params: Record<string, any>) {
return request.get(`shop/goods/coupon/records`, { params });
}
/**
*
* @param id
* @returns
*/
export function getCouponInfo(id: number) {
return request.get(`shop/goods/coupon/detail/${ id }`);
}
/**
*
* @param params
* @returns
*/
export function editCouponStatus(params: Record<string, any>) {
return request.put(`shop/goods/coupon/setstatus/${ params.status }`, params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editCoupon(params: Record<string, any>) {
return request.put(`shop/goods/coupon/edit/${ params.id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param id
* @returns
*/
export function deleteCoupon(id: number) {
return request.delete(`shop/goods/coupon/${ id }`, { showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function closeCoupon(id: number) {
return request.put(`shop/goods/coupon/invalid/${ id }`, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getSelectedCouponList(params: Record<string, any>) {
return request.get(`shop/goods/coupon/selected`, { params })
}
/************ 限时折扣 ****************/
/**
*
* @param params
* @returns
*/
export function getActiveDiscountPageList(params: Record<string, any>) {
return request.get(`shop/active/discount`, { params })
}
/**
*
* @returns
*/
export function getActiveDiscountStatusList() {
return request.get(`shop/active/status`)
}
/**
*
* @param active_id
* @returns
*/
export function getActiveDiscountInfo(active_id: number) {
return request.get(`shop/active/discount/${ active_id }`);
}
/**
*
* @param params
* @returns
*/
export function addActiveDiscount(params: Record<string, any>) {
return request.post('shop/active/discount', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editActiveDiscount(params: Record<string, any>) {
return request.put(`shop/active/discount/${ params.active_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param active_id
* @returns
*/
export function closeActiveDiscount(active_id: number) {
return request.put(`shop/active/discount/close/${ active_id }`, {}, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param active_id
* @returns
*/
export function deleteActiveDiscount(active_id: number) {
return request.delete(`shop/active/discount/${ active_id }`, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getActiveDiscountGoodsPageList(params: Record<string, any>) {
return request.get(`shop/active/discount/goods/${ params.active_id }`, { params })
}
/**
*
* @param params
* @returns
*/
export function getActiveDiscountOrderPageList(params: Record<string, any>) {
return request.get(`shop/active/discount/order/${ params.active_id }`, { params })
}
/**
*
* @param params
* @returns
*/
export function getActiveDiscountMemberPageList(params: Record<string, any>) {
return request.get(`shop/active/discount/member/${ params.active_id }`, { params })
}
/**
*
* @returns
*/
export function getActiveDiscountConfig() {
return request.get(`shop/active/discount/config`);
}
/**
*
* @param params
* @returns
*/
export function editActiveDiscountConfig(params: Record<string, any>) {
return request.put(`shop/active/discount/config`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/********** 积分商品 ***********/
/**
*
* @param params
* @returns
*/
export function getActiveExchangePageList(params: Record<string, any>) {
return request.get(`shop/active/exchange`, { params })
}
/**
*
* @param id id
* @returns
*/
export function getActiveExchangeInfo(id: number) {
return request.get(`shop/active/exchange/${ id }`);
}
/**
*
* @param params
* @returns
*/
export function addActiveExchange(params: Record<string, any>) {
return request.post('shop/active/exchange', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editActiveExchange(params: Record<string, any>) {
return request.put(`shop/active/exchange/${ params.id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function editActiveExchangeStatus(params: Record<string, any>) {
return request.put(`shop/active/exchange/status/${ params.id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param id
* @returns
*/
export function deleteActiveExchange(id: number) {
return request.delete(`shop/active/exchange/${ id }`, { showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getActiveExchangeStatus() {
return request.get(`shop/active/exchange/status`)
}
/************ 新人专享 ****************/
/**
*
* @returns
*/
export function getActiveNewcomerConfig() {
return request.get(`shop/active/newcomer/config`);
}
/**
*
* @param params
* @returns
*/
export function editActiveNewcomerConfig(params: Record<string, any>) {
return request.put(`shop/active/newcomer/config`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
* -
* @param params
* @returns
*/
export function getNewcomerGoodsList(params: Record<string, any>) {
return request.get('shop/active/newcomer/goods/select', { params })
}
/**
* -
* @param params
* @returns
*/
export function getNewcomerSelectGoodsList(params: Record<string, any>) {
return request.get('shop/active/newcomer/goods/selectgoodssku', { params })
}
/************ 商品榜单 ****************/
/**
*
* @param params
* @returns
*/
export function setRankConfig(params: Record<string, any>) {
return request.post('shop/good/rank/config', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getRankConfig() {
return request.get(`shop/good/rank/config`)
}
/**
*
* @param params
* @returns
*/
export function getRankPageList(params: Record<string, any>) {
return request.get(`shop/good/rank`, { params })
}
/**
*
* @returns
*/
export function optionData() {
return request.get(`shop/good/rank/dict`)
}
/**
*
* @param rank_id
* @returns
*/
export function getRankInfo(rank_id: number) {
return request.get(`shop/good/rank/${ rank_id }`);
}
/**
*
* @param params
* @returns
*/
export function addGoodRank(params: Record<string, any>) {
return request.post('shop/good/rank', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editGoodRank(params: Record<string, any>) {
return request.put(`shop/good/rank/${ params.id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function editRankStatus(params: Record<string, any>) {
return request.put(`shop/goods/rank/status`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param id
* @returns
*/
export function deleteGoodRank(id: number) {
return request.delete(`shop/good/rank/${ id }`, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function batchDelete(params: Record<string, any>) {
return request.put(`shop/good/rank/batchDelete`, params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function modifyGoodsRankSort(params: Record<string, any>) {
return request.put(`shop/good/rank/sort`, params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getSelectRankPageList(params: Record<string, any>) {
return request.get(`shop/good/rank/select`, { params })
}
/************ 满减 ****************/
/**
*
* @param params
* @returns
*/
export function getManjianList(params: Record<string, any>) {
return request.get(`shop/manjian`, { params })
}
/**
*
* @returns
*/
export function getManjianStatusList() {
return request.get(`shop/manjian/status`)
}
/**
*
* @param params
* @returns
*/
export function addManjian(params: Record<string, any>) {
return request.post('shop/manjian', params)
}
/**
*
* @param params
* @returns
*/
export function editManjian(params: Record<string, any>) {
return request.put(`shop/manjian/${ params.id }`, params)
}
/**
*
* @param params
* @returns
*/
export function getManjianInfo(params: Record<string, any>) {
return request.get(`shop/manjian/init`, { params });
}
/**
*
* @param params
* @returns
*/
export function goodsCheck(params: Record<string, any>) {
return request.post('shop/manjian/goods/check', params)
}
/**
*
* @param params
* @returns
*/
export function getManjianMemberPageList(params: Record<string, any>) {
return request.get(`shop/manjian/member/${ params.id }`, { params })
}
/**
*
* @param manjian_id
* @returns
*/
export function closeManjian(manjian_id: number) {
return request.put(`shop/manjian/close/${ manjian_id }`, {}, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
* ,使
* @param params
* @returns
*/
export function getGoodsSelectByReplaceBuy(params: Record<string, any>) {
return request.get(`shop/goods/buy/goods/select`, { params })
}
/**
* ,使
* @param params
* @returns
*/
export function getGoodsSelectedByReplaceBuy(params: Record<string, any>) {
return request.get(`shop/goods/buy/goods/selected`, { params })
}
/**
*
* @param params
* @returns
*/
export function getGoodsSkuInfo(params: Record<string, any>) {
return request.get(`shop/goods/buy/sku/select`, { params })
}
/*
*
* @param manjian_id
* @returns
*/
export function deleteManjian(manjian_id: number) {
return request.delete(`shop/manjian/${ manjian_id }`, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function batchDeleteManjian(params: Record<string, any>) {
return request.put(`shop/manjian/goods/batchDelete`, params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function batchCloseMajian(params: Record<string, any>) {
return request.put(`shop/manjian/goods/batchClose`, params, { showSuccessMessage: true })
}

250
niucloud/addon/shop/admin/api/order.ts

@ -0,0 +1,250 @@
import request from '@/utils/request'
/**
*
* @returns
*/
export function getConfig() {
return request.get('shop/order/config')
}
/**
*
* @returns
*/
export function setConfig(param: any) {
return request.post('shop/order/config', param, { showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getOrderList(params: Record<string, any>) {
return request.get('shop/order/list', { params })
}
/**
*
* @returns
*/
export function getOrderDetail(order_id: number) {
return request.get(`shop/order/detail/${ order_id }`)
}
/**
*
* @return
*/
export function getOrderStatus() {
return request.get(`shop/order/status`)
}
/**
*
* @return
*/
export function getOrderType() {
return request.get(`shop/order/type`)
}
/**
*
* @return
*/
export function orderClose(order_id: number) {
return request.put(`shop/order/close/${ order_id }`)
}
/**
*
* @return
*/
export function getOrderDeliveryType(params: Record<string, any>) {
return request.get(`shop/order/delivery_type`, { params })
}
/**
*
* @return
*/
export function orderDelivery(params: Record<string, any>) {
return request.put(`shop/order/delivery`, params)
}
/**
*
* @return
*/
export function setShopRemark(params: Record<string, any>) {
return request.put(`shop/order/shop_remark`, params)
}
/**
*
* @return
*/
export function orderFinish(order_id: number) {
return request.put(`shop/order/finish/${ order_id }`)
}
/**
*
* @return
*/
export function deliveryPackage(params: Record<string, any>) {
return request.get(`shop/order/delivery/package`, { params })
}
/**
*
* @return
*/
export function deliveryPackageList(params: Record<string, any>) {
return request.get(`shop/order/delivery/package/list`, { params })
}
/**
* 退
* @param {Record<string, any>} params
* @return
*/
export function orderRefund(params: Record<string, any>) {
return request.get(`shop/order/refund`, { params })
}
/**
* 退
*/
export function orderRefundDetail(refund_id: number) {
return request.get(`shop/order/refund/${ refund_id }`)
}
/**
* 退
* @return
*/
export function auditRefund(params: Record<string, any>) {
return request.put(`shop/order/refund/audit/${ params.order_refund_no }`, params)
}
/**
* 退
* @return
*/
export function refundDelivery(params: Record<string, any>) {
return request.put(`shop/order/refund/delivery/${ params.order_refund_no }`, params)
}
/**
* 退
*/
export function getRefundMoney(params: Record<string, any>) {
return request.get(`shop/order/refund/refund_money`, { params })
}
/**
* 退
*/
export function shopActiveRefund(params: Record<string, any>) {
return request.post(`shop/order/refund/active`, params, { showSuccessMessage: true })
}
/**
*
*/
export function getInvoiceList(params: Record<string, any>) {
return request.get(`shop/invoice`, { params })
}
/**
*
*/
export function getInvoiceDetail(id: number) {
return request.get(`shop/invoice/${ id }`)
}
/**
*
*/
export function setInvoice(id: number, params: Record<string, any>) {
return request.put(`shop/invoice/${ id }`, params, { showSuccessMessage: true })
}
/**
*
*/
export function getOrderPayType() {
return request.get(`shop/order/pay/type`)
}
/**
*
*/
export function getOrderFrom() {
return request.get(`shop/order/from`)
}
/**
*
* @return
*/
export function orderEditPrice(params: Record<string, any>) {
return request.put(`shop/order/edit_price`, params, { showSuccessMessage: true })
}
/**
*
* @return
*/
export function getOrderEditAddress(params: Record<string, any>) {
return request.get(`shop/order/edit_delivery`, { params })
}
/**
*
* @return
*/
export function getDeliveryList() {
return request.get(`shop/delivery/store/list`)
}
/**
*
* @return
*/
export function orderEditAddress(params: Record<string, any>) {
return request.put(`shop/order/edit_delivery`, params)
}
/**
*
* @return
*/
export function getOrderBatchDeliveryList(params: Record<string, any>) {
return request.get(`shop/order_batch_delivery`, { params })
}
/**
*
* @return
*/
export function addBatchOrderDelivery(params: Record<string, any>) {
return request.put(`shop/order_batch_delivery/add_batch_order_delivery`, params)
}
/**
*
* @return
*/
export function getOrderBatchDeliveryState() {
return request.get(`shop/order_batch_delivery/get_status`)
}
/**
*
* @return
*/
export function getOrderBatchDeliveryType() {
return request.get(`shop/order_batch_delivery/get_type`)
}

43
niucloud/addon/shop/admin/api/shop.ts

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

62
niucloud/addon/shop/admin/api/shop_address.ts

@ -0,0 +1,62 @@
import request from '@/utils/request'
/**
*
* @param params
* @returns
*/
export function getShopAddressList(params: Record<string, any>) {
return request.get(`shop/shop_address`, { params })
}
/**
*
* @param id id
* @returns
*/
export function getShopAddressInfo(id: number) {
return request.get(`shop/shop_address/${ id }`);
}
/**
*
* @param params
* @returns
*/
export function addShopAddress(params: Record<string, any>) {
return request.post('shop/shop_address', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editShopAddress(params: Record<string, any>) {
return request.put(`shop/shop_address/${ params.id }`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function deleteShopAddress(id: number) {
return request.delete(`shop/shop_address/${ id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @returns
*/
export function getShopDefaultDeliveryAddressInfo() {
return request.get('shop/shop_address/default/delivery');
}
/**
*
* @returns
*/
export function getOrderRefundAddress() {
return request.get('shop/order/refund/address');
}

30
niucloud/addon/shop/admin/api/stat.ts

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

BIN
niucloud/addon/shop/admin/assets/brand_default.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
niucloud/addon/shop/admin/assets/category_default.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
niucloud/addon/shop/admin/assets/category_style2_new.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 KiB

BIN
niucloud/addon/shop/admin/assets/category_style3_new.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

BIN
niucloud/addon/shop/admin/assets/category_style4_new.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

BIN
niucloud/addon/shop/admin/assets/discount_banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

BIN
niucloud/addon/shop/admin/assets/discount_config.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

BIN
niucloud/addon/shop/admin/assets/goods_default.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
niucloud/addon/shop/admin/assets/store_default.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

35
niucloud/addon/shop/admin/lang/zh-cn/address.edit.json

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

25
niucloud/addon/shop/admin/lang/zh-cn/address.list.json

@ -0,0 +1,25 @@
{
"id": "",
"contactName": "联系人",
"mobile": "联系方式",
"mobilePlaceholder": "请输入联系方式",
"provinceId": "省",
"cityId": "市",
"districtId": "区",
"address": "详细地址",
"fullAddress": "地址",
"fullAddressPlaceholder": "请输入地址",
"lat": "纬度",
"lng": "经度",
"isDeliveryAddress": "是否是发货地址",
"isRefundAddress": "是否是退货地址",
"isDefaultDelivery": "默认发货地址",
"isDefaultRefund": "默认收货地址",
"addShopAddress": "添加商家地址库",
"updateShopAddress": "编辑商家地址库",
"shopAddressDeleteTips": "确定要删除该数据吗?",
"addressType": "地址类型",
"deliveryAddress": "发货地址",
"refundAddress": "收货地址",
"default": "默认"
}

128
niucloud/addon/shop/admin/lang/zh-cn/common.json

@ -0,0 +1,128 @@
{
"goodsSelectPopupSelectGoodsButton": "选择商品",
"rankSelectPopupSelectRankButton": "选择榜单",
"goodsSelectPopupSelect": "已选",
"goodsSelectPopupPiece": "个",
"goodsSelectPopupSelectGoodsDialog": "商品选择",
"goodsSelectPopupAllGoods": "全部商品",
"defaultGoodsSelect": "默认",
"goodsSelectPopupSelectedGoods": "已选商品",
"goodsSelectPopupGoodsName": "商品名称",
"goodsSelectPopupGoodsNamePlaceholder": "请输入商品名称",
"goodsSelectPopupGoodsStatusPlaceholder": "请选择商品状态",
"goodsSelectPopupGoodsCategory": "商品分类",
"goodsSelectPopupGoodsCategoryPlaceholder": "全部",
"goodsSelectPopupGoodsType": "商品类型",
"goodsSelectPopupGoodsTypePlaceholder": "请选择商品类型",
"goodsSelectPopupGoodsInfo": "商品",
"goodsSelectPopupGoodsPointUnit": "积分",
"goodsSelectPopupGoodsPriceUnit": "元",
"goodsSelectPopupPrice": "价格",
"goodsSelectPopupStock": "库存",
"goodsSelectPopupBeforeTip": "已选择",
"goodsSelectPopupAfterTip": "个商品",
"goodsSelectPopupClearGoods": "取消选择",
"goodsSelectPopupGoodsMinTip": "所选商品数量不能少于",
"goodsSelectPopupGoodsMaxTip": "所选商品数量不能超过",
"goodsTextColor": "文字颜色",
"textColor": "标题颜色",
"subTextColor": "副标题颜色",
"wayPlaceholder": "虚拟商品和实物商品只能选择其中一个类型,请重新选择",
"goodsStyle": "商品样式",
"goodsBgColor": "商品背景",
"goodsNameColor": "商品名称",
"goodsPriceColor": "销售价",
"goodsBtnText": "文本",
"goodsBtnTextPlaceholder": "请输入按钮文字",
"goodsSaleColor": "商品销量",
"goodsBtnColor": "按钮背景",
"goodsNumColor": "已兑人数",
"goodsBuyBtn": "购买按钮",
"goodsShowContent": "显示内容",
"goodsBtnResult": "按钮效果",
"goodsBtnIsShow": "是否显示",
"goodsCartIncident": "点击事件",
"goodsBtnStyle": "样式",
"goodsSaleNum": "商品销量",
"goodsDetail": "商品详情",
"goodsRounded": "圆角",
"fenxiaoCommissionPriceColor": "分销佣金",
"goodsCategoryPlaceholder": "请选择商品分类",
"goodsPlaceholder": "请选择商品",
"goodsIsBold": "是否加粗",
"goodsLabel": "商品标签",
"headStyle1": "样式1",
"headStyle2": "样式2",
"headStyle3": "样式3",
"headStyle4": "样式4",
"goodsData": "商品数据",
"sortWay": "排序",
"default": "综合",
"sales": "销量",
"price": "价格",
"manyGoodsListAroundRadius": "图片圆角",
"manyGoodsListCategoryName": "分类名称",
"manyGoodsListSubTitle": "副标题",
"manyGoodsLisAddItem": "添加一个多商品组",
"couponData": "优惠券数据",
"couponContent": "优惠券内容",
"couponTitle": "标题",
"couponTitlePlaceholder": "请输入标题",
"couponSubTitle": "副标题",
"couponSubTitlePlaceholder": "请输入副标题",
"selectCoupon": "选择优惠券",
"allSources": "全部",
"couponNum": "优惠券数量",
"couponPlaceholder": "请选择优惠券",
"couponBtnText": "按钮文字",
"couponBtnTextPlaceholder": "请输入按钮文字",
"couponTitleStyle": "标题样式",
"couponTitleColor": "标题颜色",
"couponSubTitleColor": "副标题颜色",
"couponItemStyle": "优惠券项样式",
"couponMoney": "金额颜色",
"manyGoodsListCategorySet": "分组设置",
"manyGoodsListSourceDiy": "自定义",
"manyGoodsListSourceCategory": "商品分类",
"goodsSet": "商品设置",
"goodsSearchSet": "搜索设置",
"goodsSearchText": "搜索内容",
"goodsSearchTextPlaceholder": "请输入搜索内容",
"shopMemberInfoComponentUidTextColor":"编号颜色",
"shopMemberInfoComponentAccount":"账号信息",
"shopGoodsRecommendComponentTag":"标签",
"shopGoodsRecommendComponentTagcolor":"标签颜色",
"shopGoodsRecommendComponentTagPlaceholder":"请输入标签内容",
"shopGoodsRecommendComponentButtonBorderColor":"按钮边框颜色",
"carouselStyle":"轮播样式",
"recommendIndicatorStyle":"指示器设置",
"recommendIndicatorColor":"常规颜色",
"recommendIndicatorActiveColor":"选中颜色",
"activeCubeBlockContent":"板块内容" ,
"bgImage":"背景图片",
"rankingTitleIcon":"图标" ,
"rankSelect":"榜单选择",
"rankName":"榜单名称",
"rankNamePlaceholder":"请输入榜单名称",
"showGoodsNum":"榜单商品数量",
"goodsSourceName":"商品来源",
"ruleTypeName":"排序规则",
"rankTypeName":"排行周期",
"rankSelectPopupAfterTip": "个榜单",
"rankSelectPopupGoodsMinTip": "所选榜单数量不能少于",
"rankSelectPopupGoodsMaxTip": "所选榜单数量不能超过",
"rankingTitleImage":"头部图片" ,
"rankingSubTitle":"副标题",
"rankingSubTitleTextColor":"副标题颜色",
"rankTextColor":"名称颜色",
"rankingSubTitleLink":"副标题链接",
"listFrameColor":"背景颜色",
"topRounded":"上圆角",
"bottomRounded":"下圆角",
"rankingStyle": "板块样式",
"styleRecommend": "风格推荐",
"countDownStyle": "倒计时样式",
"newcomerNumberColor": "数字颜色",
"newcomerNumberBg": "数字背景色",
"newcomerOtherColor": "文字颜色"
}

20
niucloud/addon/shop/admin/lang/zh-cn/delivery.company.json

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

44
niucloud/addon/shop/admin/lang/zh-cn/delivery.company_edit.json

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

11
niucloud/addon/shop/admin/lang/zh-cn/delivery.config.json

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

17
niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet.json

@ -0,0 +1,17 @@
{
"tabESTemplate": "电子面单模板",
"tabESConfig": "设置",
"templateName": "模板名称",
"templateNamePlaceholder": "请输入模板名称",
"expressCompany": "物流公司",
"expressCompanyPlaceholder": "请选择物流公司",
"status": "状态",
"statusOn": "开启",
"statusOff": "关闭",
"addElectronicSheet": "添加电子面单",
"payType": "邮费支付方式",
"isDefault": "默认",
"setDefault": "设为默认",
"electronicSheetDeleteTips": "确定要删除该数据吗?",
"electronicSheetSetDefaultTips": "确定要设置为默认模版吗?"
}

21
niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_config.json

@ -0,0 +1,21 @@
{
"tabESTemplate": "电子面单模板",
"tabESConfig": "设置",
"apiSet": "接口设置",
"interfaceType": "接口类型",
"prompt": "提示",
"promptTips1-1": "请到快递鸟官网申请",
"kdn": "快递鸟",
"kdnEBusinessIDLabel": "用户ID",
"kdnEBusinessIDPlaceholder": "请输入快递鸟用户ID",
"kdnEBusinessIDTips": "快递鸟用户ID,EBusinessID",
"kdnAppKeyPlaceholder": "请输入快递鸟API key",
"kdnAppKeyTips": "快递鸟分配的API key",
"printerSet": "打印机设置",
"serverPort1": "服务器端口1",
"serverPort1Placeholder": "请输入服务器端口1",
"serverPort2": "服务器端口2",
"serverPort2Placeholder": "请输入服务器端口2",
"httpsPort": "HTTPS端口",
"httpsPortPlaceholder": "请输入HTTPS端口"
}

34
niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_edit.json

@ -0,0 +1,34 @@
{
"basicSettings": "基础设置",
"otherSettings": "其他设置",
"templateName": "模板名称",
"templateNamePlaceholder": "请输入模板名称",
"expressCompany": "物流公司",
"expressCompanyPlaceholder": "请选择物流公司",
"expType": "业务类型",
"status": "状态",
"customerName": "CustomerName",
"customerNamePlaceholder": "请输入电子面单客户账号",
"customerPwd": "CustomerPwd",
"customerPwdTips": "电子面单密码,不同快递叫法不同,例如:密码、密钥、客户编号",
"sendSite": "SendStaff",
"sendSiteTips": "不同快递叫法不同,例如:网点编码、网点编号、网点名称",
"sendStaff": "SendStaff",
"sendStaffTips": "不同快递叫法不同,例如:收件快递员、取件员编号、网点名称",
"monthCode": "MonthCode",
"monthCodeTips": "不同快递叫法不同,例如:月结号、密钥、月结编码",
"payType": "邮费支付方式",
"isNotice": "快递员上门揽件",
"yes": "是",
"no": "否",
"isNoticeTips": "是否通知快递员上门揽件,跨越速运,京东快运必填",
"printStyle": "模板样式",
"printStylePlaceholder": "请选择模板样式",
"printStyleTips": "快递鸟模版规格(常用)",
"printStyleTips1": "主流快递单打印纸尺寸一般为:76*130,100*180(单位mm)",
"printStyleTips2": "不填写则取物流公司的默认模板",
"isDefault": "是否默认",
"examine": "点击查看",
"customerNameTips": "快递鸟电子面单账号申请",
"customerNameTips1": "电子面单账号对照表"
}

55
niucloud/addon/shop/admin/lang/zh-cn/delivery.local.json

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

20
niucloud/addon/shop/admin/lang/zh-cn/delivery.search.json

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

9
niucloud/addon/shop/admin/lang/zh-cn/delivery.staff.json

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

18
niucloud/addon/shop/admin/lang/zh-cn/delivery.store.json

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

38
niucloud/addon/shop/admin/lang/zh-cn/delivery.store_edit.json

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

12
niucloud/addon/shop/admin/lang/zh-cn/delivery.template.json

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

39
niucloud/addon/shop/admin/lang/zh-cn/delivery.template_edit.json

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

10
niucloud/addon/shop/admin/lang/zh-cn/goods.attr.json

@ -0,0 +1,10 @@
{
"attrName": "参数模板名称",
"attrNamePlaceholder": "请输入参数模板名称",
"sortPlaceholder": "请输入排序号",
"addShopGoodsAttr": "添加参数模板",
"updateShopGoodsAttr": "编辑参数模板",
"goodsAttrDeleteTips": "确定要删除该数据吗?",
"sortTips":"排序号格式输入错误",
"manage": "管理"
}

18
niucloud/addon/shop/admin/lang/zh-cn/goods.attr_edit.json

@ -0,0 +1,18 @@
{
"attrName": "参数模板名称",
"attrNamePlaceholder": "请输入参数名称",
"updateAttr": "编辑参数模板",
"sort": "排序号",
"sortPlaceholder": "请输入排序号",
"addShopGoodsAttr": "添加商品参数",
"attrValueType": "参数类型",
"attrValueTypeRadio": "单选",
"attrValueTypeCheckbox": "多选",
"attrValueTypeText": "输入",
"attrValueChild": "参数内容",
"updateShopGoodsAttr": "编辑商品参数",
"goodsAttrDeleteTips": "确定要删除该数据吗?",
"attrValueName": "参数名称",
"addAttrValue": "添加参数",
"attrValueNamePlaceholder": "请输入参数名称"
}

15
niucloud/addon/shop/admin/lang/zh-cn/goods.brand_list.json

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

26
niucloud/addon/shop/admin/lang/zh-cn/goods.category.json

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

27
niucloud/addon/shop/admin/lang/zh-cn/goods.category_config.json

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

49
niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate.json

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

37
niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate_edit.json

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

12
niucloud/addon/shop/admin/lang/zh-cn/goods.label_group_list.json

@ -0,0 +1,12 @@
{
"tabGoodsLabel": "商品标签",
"tabGoodsLabelGroup": "标签分组",
"groupName": "分组名称",
"groupNamePlaceholder": "请输入分组名称",
"sort": "排序",
"sortPlaceholder": "请输入排序",
"addLabelGroup": "添加标签分组",
"updateLabelGroup": "编辑标签分组",
"sortTips": "排序号格式输入错误",
"labelGroupDeleteTips": "确定要删除该数据吗?"
}

30
niucloud/addon/shop/admin/lang/zh-cn/goods.label_list.json

@ -0,0 +1,30 @@
{
"tabGoodsLabel": "商品标签",
"tabGoodsLabelGroup": "标签分组",
"labelName": "标签名称",
"labelNamePlaceholder": "请输入标签名称",
"groupName": "标签分组",
"groupNamePlaceholder": "请选择标签分组",
"styleType": "效果设置",
"styleByDiy": "自定义",
"styleByIcon": "图片",
"textColor": "文字颜色",
"bgColor": "背景颜色",
"borderColor": "边框颜色",
"colorTips": "若未设置颜色,则为默认色",
"icon": "上传图片",
"iconTips": "建议尺寸:80px*30px,若未上传将显示默认",
"memo": "标签说明",
"memoPlaceholder": "请输入标签说明",
"sort": "排序",
"sortPlaceholder": "请输入排序",
"addLabel": "添加商品标签",
"updateLabel": "编辑商品标签",
"sortTips": "排序号格式输入错误",
"labelDeleteTips": "确定要删除该数据吗?",
"statusOn": "开启",
"statusOff": "关闭",
"status": "状态",
"label": "标签",
"createTime": "创建时间"
}

154
niucloud/addon/shop/admin/lang/zh-cn/goods.list.json

@ -0,0 +1,154 @@
{
"goodsName": "商品名称",
"goodsNamePlaceholder": "请输入商品名称",
"goodsCategory": "商品分类",
"goodsCategoryPlaceholder": "全部",
"goodsType": "商品类型",
"goodsTypePlaceholder": "请选择商品类型",
"brand": "商品品牌",
"brandPlaceholder": "请选择商品品牌",
"labelIds": "商品标签",
"labelIdsPlaceholder": "请选择商品标签",
"saleNum": "销量",
"startSaleNumPlaceholder": "最低销量",
"startSaleNumTips": "最低销量输入错误",
"endSaleNumPlaceholder": "最高销量",
"endSaleNumTips": "最高销量输入错误",
"shopSaleNumTips":"最低销量不能大于最高销量",
"skuPrice": "价格",
"startPricePlaceholder": "最低价格",
"startPriceTips": "最低价格输入错误",
"endPricePlaceholder": "最高价格",
"endPriceTips": "最高价格输入错误",
"shopPriceTips":"最低价格不能大于最高价格",
"statusOn": "销售中",
"statusOff": "仓库中",
"statusAll": "全部商品",
"batchOnGoods": "批量上架",
"batchOffGoods": "批量下架",
"batchDeleteGoods": "批量删除",
"batchSetting": "批量设置",
"batchEmptySelectedGoodsTips": "请选择要操作的商品",
"goodsInfo": "商品",
"stock": "库存",
"status": "状态",
"sort": "排序",
"sortTips": "排序号格式输入错误",
"createTime": "创建时间",
"addGoods": "添加商品",
"statusActionOn": "上架",
"statusActionOff": "下架",
"statusChangeTips":"确定要下架该商品吗?",
"spreadGoods": "推广",
"copyGoods": "复制",
"updateGoods": "编辑商品",
"goodsCopyTips": "确定要复制该商品吗?",
"goodsDeleteTips": "确定要删除该商品吗?",
"batchGoodsDeleteTips": "确定要删除这些商品吗",
"batchOperationSku": "批量设置",
"editStockPopupTitle": "编辑商品库存",
"editPricePopupTitle": "编辑商品价格",
"skuName": "规格名称",
"price": "销售价",
"pricePlaceholder": "请输入销售价",
"priceTips": "销售价格式输入错误",
"priceNotZeroTips": "销售价不能小于0",
"marketPrice": "划线价",
"marketPricePlaceholder": "请输入划线价",
"marketPriceTips": "划线价格式输入错误",
"marketPriceNotZeroTips": "划线价不能小于0",
"market_price": "划线价",
"market_pricePlaceholder": "请输入划线价",
"market_priceTips": "划线价格式输入错误",
"market_priceNotZeroTips": "划线价不能小于0",
"costPrice": "成本价",
"costPricePlaceholder": "请输入成本价",
"costPriceTips": "成本价格式输入错误",
"costPriceNotZeroTips": "成本价不能小于0",
"cost_price": "成本价",
"cost_pricePlaceholder": "请输入成本价",
"cost_priceTips": "成本价格式输入错误",
"cost_priceNotZeroTips": "成本价不能小于0",
"stockPlaceholder": "请输入库存",
"stockTips": "库存格式输入错误",
"stockNotZeroTips": "库存不能小于0",
"goodsSpreadTitle": "商品推广",
"spreadLink": "推广链接",
"copy": "复制",
"downloadQrcode": "下载二维码",
"memberPrice": "会员价",
"editMemberPricePopupTitle": "编辑会员价",
"memberDiscount": "会员价优惠方式",
"discount": "会员折扣",
"fixedPrice": "指定会员价",
"nonparticipation": "不参与",
"goodsSku": "商品规格",
"memberEnjoyDiscount": "会员享受折扣",
"discountUnit": "折",
"yuanUnit": "元",
"editMemberPrice": "修改会员价",
"memberLevel": "会员等级",
"memberPricePlaceholder": "请输入会员价",
"discountHint": "会员折扣说明:按照默认会员等级折扣优惠",
"fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准",
"addGoodsLabel": "添加商品标签",
"addGoodsService": "添加商品服务",
"addGoodsCategory": "添加分类",
"addGoodsBrand": "添加品牌",
"addGoodsPoster": "添加海报",
"virtualSaleNumPlaceholder": "请输入虚拟销量",
"posterPlaceholder": "请选择商品海报",
"goodsCategoryPlaceholderTwo": "请选择商品分类",
"virtualSaleNumDesc": "虚拟销量只在前台展示中参与计算",
"virtualSaleNumTips": "虚拟销量格式输入错误",
"virtualSaleNumNotZeroTips": "虚拟销量不能小于0",
"giftTips": "当商品设置为赠品时,该商品仅用于活动赠送,不会在前台展示或出售",
"yes": "是",
"no": "否",
"isFreeShipping": "是否免邮",
"feeType": "运费设置",
"selectTemplate": "选择模板",
"fixedShipping": "统一运费",
"deliveryMoney": "固定运费",
"deliveryMoneyPlaceholder": "请输入固定运费",
"deliveryMoneyTips": "固定运费格式输入错误",
"deliveryMoneyNotZeroTips": "固定运费不能小于0",
"deliveryTemplateId": "运费模板",
"deliveryTemplateIdPlaceholder": "请选择运费模板",
"addDeliveryTemplateId": "添加运费模板",
"deliveryType": "配送方式",
"deliveryTypePlaceholder": "请选择配送方式",
"yuan":"元",
"label":"商品标签",
"service":"商品服务",
"virtualSaleNum": "虚拟销量",
"goodsBrand": "商品品牌",
"goodsPoster": "商品海报",
"isGift": "是否赠品",
"batchSettingTip": "每次仅能设置一项,点击确认成功之后生效",
"setStock": "修改库存",
"addStock": "增加库存",
"reduceStock": "减少库存",
"stockNum": "目标数值",
"stockNumTips": "批量调整商品库存,若商品正在参与营销活动,则不会修改库存",
"confirm": "确认",
"diyForm": "万能表单",
"diyFormPlaceholder": "请选择万能表单",
"addDiyForm": "添加表单"
}

174
niucloud/addon/shop/admin/lang/zh-cn/goods.real_edit.json

@ -0,0 +1,174 @@
{
"addGoods": "添加商品",
"updateGoods": "编辑商品",
"basicInfoTab": "基础信息",
"goodsType": "商品类型",
"goodsName": "商品名称",
"goodsNamePlaceholder": "请输入商品名称",
"goodsNameMaxLengthTips": "商品名称不能超过60个字符",
"subTitle": "副标题",
"subTitlePlaceholder": "请输入副标题",
"subTitleMaxLengthTips": "副标题不能超过80个字符",
"goodsImage": "商品图片",
"goodsImagePlaceholder":"请上传商品图片",
"goodsVideo": "商品视频",
"goodsVideoPlaceholder":"请上传商品视频",
"goodsCategory": "商品分类",
"refresh": "刷新",
"addGoodsCategory": "添加分类",
"goodsCategoryPlaceholder": "请选择商品分类",
"brand": "商品品牌",
"brandPlaceholder": "请选择商品品牌",
"addGoodsBrand": "添加品牌",
"poster": "商品海报",
"posterPlaceholder": "请选择商品海报",
"addGoodsPoster": "添加海报",
"posterTips": "不设置将使用默认海报",
"diyForm": "万能表单",
"diyFormPlaceholder": "请选择万能表单",
"addDiyForm": "添加表单",
"label": "商品标签",
"addGoodsLabel": "添加商品标签",
"goodsService": "商品服务",
"addGoodsService": "添加商品服务",
"supplier": "供应商",
"supplierPlaceholder": "请选择供应商",
"addSupplier": "添加供应商",
"status": "商品状态",
"statusOn": "上架",
"statusOff": "下架",
"isGive": "是否赠品",
"yes": "是",
"no": "否",
"sort": "排序",
"sortPlaceholder": "请输入排序",
"sortTips": "排序号格式输入错误",
"priceStockTab": "价格库存",
"specType": "规格类型",
"singleSpec": "单规格",
"multiSpec": "多规格",
"price": "销售价",
"marketPrice": "划线价",
"costPrice": "成本价",
"weight": "重量",
"volume": "体积",
"goodsStock": "商品库存",
"goodsStockPlaceholder": "请输入商品库存",
"skuNo": "商品编码",
"yuan": "元",
"defaultUnit": "件",
"skuNoPlaceholder": "请输入商品编码",
"goodsSku": "商品规格",
"specNamePlaceholder": "请输入规格项,如颜色、尺码、大小",
"specValueNamePlaceholder": "请输入规格值,如:白色",
"addSpecValue": "+添加规格值",
"addSpec": "添加规格",
"batchOperationSku": "批量设置",
"all": "全部",
"stock": "库存",
"skuWeight": "重量(kg)",
"skuVolume": "体积(m³)",
"confirm": "确定",
"image": "图片",
"defaultSku": "默认规格",
"unit": "单位",
"unitPlaceholder": "请输入单位,默认为:件",
"virtualSaleNum": "虚拟销量",
"virtualSaleNumPlaceholder": "请输入虚拟销量",
"virtualSaleNumDesc": "虚拟销量只在前台展示中参与计算",
"virtualSaleNumTips": "虚拟销量格式输入错误",
"virtualSaleNumNotZeroTips": "虚拟销量不能小于0",
"giftTips": "当商品设置为赠品时,该商品仅用于活动赠送,不会在前台展示或出售",
"maxAddSpecTips": "最多添加5个规格项",
"pleaseEditSpecPlaceholder": "请编辑规格信息",
"refreshSuccess": "刷新成功",
"deliveryTab": "配送设置",
"deliveryType": "配送方式",
"deliveryTypePlaceholder": "请选择配送方式",
"pleaseSelectSku":"请先选择商品规格",
"isLimit":"是否限购",
"isLimitTips":"启用限购后,购买商品时,会对该商品购买量做限制判断。",
"limitType":"限购类型",
"limitTypeTips":"单次限购是针对于每次下单不能超过限购数量,单人限购是针对于会员账号购买这个商品的总数不能超过限购数量。",
"singleTime":"单次限购",
"singlePerson":"单人限购",
"maxBuy":"限购数量",
"maxBuyPlaceholder":"请输入限购数量",
"maxBuyTips": "[限购数量]格式输入错误",
"maxBuyWarnTips":"限购数量超出商品库存时,买家将无法购买该商品",
"maxBuyNotZeroTips": "限购数量不能小于1",
"minBuy":"起购数量",
"minBuyTips":"起购数量超出商品库存时,买家将无法购买该商品",
"minBuyFormatErrorTips":"[起购数量]格式输入错误",
"minBuyNotZeroTips": "起购数量不能小于0",
"minBuyGreaterThanMaxBuyTips": "起购数量不能大于限购数量",
"isFreeShipping": "是否免邮",
"feeType": "运费设置",
"selectTemplate": "选择模板",
"fixedShipping": "统一运费",
"deliveryMoney": "固定运费",
"deliveryMoneyPlaceholder": "请输入固定运费",
"deliveryMoneyTips": "固定运费格式输入错误",
"deliveryMoneyNotZeroTips": "固定运费不能小于0",
"deliveryTemplateId": "运费模板",
"deliveryTemplateIdPlaceholder": "请选择运费模板",
"addDeliveryTemplateId": "添加运费模板",
"goodsDesc": "商品详情",
"goodsDescPlaceholder": "请填写商品详情",
"goodsDescMaxTips": "商品描述字符数应在5~50000之间",
"pricePlaceholder": "请输入销售价",
"priceTips": "[销售价]格式输入错误",
"priceNotZeroTips": "销售价不能小于0",
"marketPricePlaceholder": "请输入划线价",
"marketPriceTips": "[划线价]格式输入错误",
"marketPriceNotZeroTips": "划线价不能小于0",
"costPricePlaceholder": "请输入成本价",
"costPriceTips": "[成本价]格式输入错误",
"costPriceNotZeroTips": "成本价不能小于0",
"weightPlaceholder": "请输入重量",
"weightTips": "[重量(kg)]格式输入错误",
"weightNotZeroTips": "重量(kg)不能小于0",
"volumePlaceholder": "请输入体积",
"volumeTips": "[体积(m³)]格式输入错误",
"volumeNotZeroTips": "体积(m³)不能小于0",
"stockPlaceholder": "请输入库存",
"stockTips": "[库存]格式输入错误",
"stockNotZeroTips": "库存不能小于0",
"specNameRequire": "规格项不能为空",
"specNameRepeat": "规格项不能重复",
"specValueRequire": "规格值不能为空",
"specValueNameRepeat": "规格值不能重复",
"lackDefaultSpec": "商品缺少默认规格",
"goodsArguments": "商品参数",
"goodsArgumentsTemp": "商品参数模板",
"goodsArgumentsTempPlaceholder": "请选择商品参数模板",
"goodsArgumentsTempHint": "商品可以添加自定义商品参数,也可以通过参数模板批量设置商品参数",
"argumentsName": "参数名",
"argumentsValue": "参数值",
"argumentsSortHint": "设置排序,改变商品规格展示顺序",
"operation": "操作",
"delAttr": "删除",
"noData": "无数据",
"addGoodsArguments": "添加商品参数",
"memberDiscount": "会员等级折扣",
"discount": "会员折扣",
"fixedPrice": "指定会员价",
"nonparticipation": "不参与",
"discountHint": "会员折扣说明:按照默认会员等级折扣优惠",
"fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准",
"participateInActiveDisableTips": "商品正在参与营销活动,禁止操作"
}

29
niucloud/addon/shop/admin/lang/zh-cn/goods.recycle.json

@ -0,0 +1,29 @@
{
"goodsName": "商品名称",
"goodsNamePlaceholder": "请输入商品名称",
"goodsCategory": "商品分类",
"goodsCategoryPlaceholder": "全部",
"goodsType": "商品类型",
"goodsTypePlaceholder": "请选择商品类型",
"price": "价格",
"saleNum": "销量",
"statusOn": "销售中",
"statusOff": "仓库中",
"batchRecycle": "批量恢复",
"batchEmptySelectedGoodsTips": "请选择要操作的商品",
"goodsInfo": "商品",
"stock": "库存",
"stockPlaceholder": "请输入商品库存(总和)",
"status": "状态",
"createTime": "创建时间",
"recycle": "恢复",
"goodsRecycleTips": "确定要恢复该商品吗?",
"batchGoodsRecycleTips": "确定要恢复这些商品吗"
}

10
niucloud/addon/shop/admin/lang/zh-cn/goods.service.json

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

167
niucloud/addon/shop/admin/lang/zh-cn/goods.virtual_edit.json

@ -0,0 +1,167 @@
{
"addGoods": "添加商品",
"updateGoods": "编辑商品",
"basicInfoTab": "基础信息",
"goodsType": "商品类型",
"goodsName": "商品名称",
"goodsNamePlaceholder": "请输入商品名称",
"goodsNameMaxLengthTips": "商品名称不能超过60个字符",
"subTitle": "副标题",
"subTitlePlaceholder": "请输入副标题",
"subTitleMaxLengthTips": "副标题不能超过80个字符",
"goodsImage": "商品图片",
"goodsImagePlaceholder":"请上传商品图片",
"goodsVideo": "商品视频",
"goodsVideoPlaceholder":"请上传商品视频",
"goodsCategory": "商品分类",
"refresh": "刷新",
"addGoodsCategory": "添加分类",
"goodsCategoryPlaceholder": "请选择商品分类",
"brand": "商品品牌",
"brandPlaceholder": "请选择商品品牌",
"addGoodsBrand": "添加品牌",
"poster": "商品海报",
"posterPlaceholder": "请选择商品海报",
"addGoodsPoster": "添加海报",
"posterTips": "不设置将使用默认海报",
"diyForm": "万能表单",
"diyFormPlaceholder": "请选择万能表单",
"addDiyForm": "添加表单",
"label": "商品标签",
"addGoodsLabel": "添加商品标签",
"goodsService": "商品服务",
"addGoodsService": "添加商品服务",
"supplier": "供应商",
"supplierPlaceholder": "请选择供应商",
"addSupplier": "添加供应商",
"status": "商品状态",
"statusOn": "上架",
"statusOff": "下架",
"isGive": "是否赠品",
"yes": "是",
"no": "否",
"sort": "排序",
"sortPlaceholder": "请输入排序",
"sortTips": "排序号格式输入错误",
"priceStockTab": "价格库存",
"specType": "规格类型",
"singleSpec": "单规格",
"multiSpec": "多规格",
"price": "销售价",
"marketPrice": "划线价",
"costPrice": "成本价",
"goodsStock": "商品库存",
"goodsStockPlaceholder": "请输入商品库存",
"skuNo": "商品编码",
"yuan": "元",
"defaultUnit": "件",
"skuNoPlaceholder": "请输入商品编码",
"goodsSku": "商品规格",
"specNamePlaceholder": "请输入规格项,如颜色、尺码、大小",
"specValueNamePlaceholder": "请输入规格值,如:白色",
"addSpecValue": "+添加规格值",
"addSpec": "添加规格",
"batchOperationSku": "批量设置",
"all": "全部",
"stock": "库存",
"confirm": "确定",
"image": "图片",
"defaultSku": "默认规格",
"unit": "单位",
"unitPlaceholder": "请输入单位,默认为:件",
"virtualSaleNum": "虚拟销量",
"virtualSaleNumPlaceholder": "请输入虚拟销量",
"virtualSaleNumDesc": "虚拟销量只在前台展示中参与计算",
"virtualSaleNumTips": "虚拟销量格式输入错误",
"virtualSaleNumNotZeroTips": "虚拟销量不能小于0",
"giftTips": "当商品设置为赠品时,该商品仅用于活动赠送,不会在前台展示或出售",
"virtualSetTips": "当设置为店内核销时,若存在未完成的订单,则无法编辑",
"maxAddSpecTips": "最多添加5个规格项",
"pleaseEditSpecPlaceholder": "请编辑规格信息",
"refreshSuccess": "刷新成功",
"isLimit":"是否限购",
"isLimitTips":"启用限购后,购买商品时,会对该商品购买量做限制判断。",
"limitType":"限购类型",
"limitTypeTips":"单次限购是针对于每次下单不能超过限购数量,单人限购是针对于会员账号购买这个商品的总数不能超过限购数量。",
"singleTime":"单次限购",
"singlePerson":"单人限购",
"maxBuy":"限购数量",
"maxBuyPlaceholder":"请输入限购数量",
"maxBuyTips": "[限购数量]格式输入错误",
"maxBuyWarnTips":"限购数量超出商品库存时,买家将无法购买该商品",
"maxBuyNotZeroTips": "限购数量不能小于1",
"minBuy":"起购数量",
"minBuyTips":"起购数量超出商品库存时,买家将无法购买该商品",
"minBuyFormatErrorTips":"[起购数量]格式输入错误",
"minBuyNotZeroTips": "起购数量不能小于0",
"minBuyGreaterThanMaxBuyTips": "起购数量不能大于限购数量",
"goodsDesc": "商品详情",
"goodsDescPlaceholder": "请填写商品详情",
"goodsDescMaxTips": "商品描述字符数应在5~50000之间",
"pricePlaceholder": "请输入销售价",
"priceTips": "[销售价]格式输入错误",
"priceNotZeroTips": "销售价不能小于0",
"marketPricePlaceholder": "请输入划线价",
"marketPriceTips": "[划线价]格式输入错误",
"marketPriceNotZeroTips": "划线价不能小于0",
"costPricePlaceholder": "请输入成本价",
"costPriceTips": "[成本价]格式输入错误",
"costPriceNotZeroTips": "成本价不能小于0",
"stockPlaceholder": "请输入库存",
"stockTips": "[库存]格式输入错误",
"stockNotZeroTips": "库存不能小于0",
"specNameRequire": "规格项不能为空",
"specNameRepeat": "规格项不能重复",
"specValueRequire": "规格值不能为空",
"specValueNameRepeat": "规格值不能重复",
"lackDefaultSpec": "商品缺少默认规格",
"setDeliverGoods": "发货设置",
"autoDeliverGoods": "自动发货",
"handDeliverGoods": "手动发货",
"setTakeGoods": "收货设置",
"autoTakeGoods": "自动收货",
"handTakeGoods": "买家确认收货",
"verifyTakeGoods": "到店核销",
"virtualIndate": "有效期",
"virtualIndatePlaceholder": "请输入有效期",
"verifyVirtualIndate": "核销有效期",
"verifyVirtualIndateOne": "永久",
"verifyVirtualIndateTwo": "购买后几日有效",
"verifyVirtualIndateThree": "指定过期日期",
"verifyHint": "无论何时购买此商品,到达指定时间后都将过期,无法核销。",
"sky": "天",
"virtualIndateErrorHint": "核销有效期不能小于1天",
"virtualIndateErrorOneHint": "核销有效期不能小于等于当前时间",
"goodsArguments": "商品参数",
"goodsArgumentsTemp": "商品参数模板",
"goodsArgumentsTempPlaceholder": "请选择商品参数模板",
"goodsArgumentsTempHint": "商品可以添加自定义商品参数,也可以通过参数模板批量设置商品参数",
"argumentsName": "参数名",
"argumentsValue": "参数值",
"argumentsSortHint": "设置排序,改变商品规格展示顺序",
"operation": "操作",
"delAttr": "删除",
"noData": "无数据",
"addGoodsArguments": "添加商品参数",
"memberDiscount": "会员等级折扣",
"discount": "会员折扣",
"fixedPrice": "指定会员价",
"nonparticipation": "不参与",
"discountHint": "会员折扣说明:按照默认会员等级折扣优惠",
"fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准",
"participateInActiveDisableTips": "商品正在参与营销活动,禁止操作"
}

20
niucloud/addon/shop/admin/lang/zh-cn/index.index.json

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

42
niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.add.json

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

42
niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.edit.json

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

47
niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.list.json

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

38
niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.add.json

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

8
niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.config.json

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

37
niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.detail.json

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

38
niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.edit.json

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

50
niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.list.json

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

66
niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_add.json

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

67
niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_edit.json

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

27
niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_list.json

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

55
niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.order_list.json

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

13
niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.config.json

@ -0,0 +1,13 @@
{
"rankName": "榜单标题",
"rankImages": "榜单图片",
"rankRemark": "榜单说明",
"save": "保存",
"imagePlaceholder": "请上传榜单图片",
"rankNamePlaceholder": "请输入榜单名称",
"rankRemarkPlaceholder": "请输入榜单说明",
"useDefaultRankRemark": "使用默认说明",
"noColor": "常规颜色",
"selectedColor": "选中文字颜色",
"selectedBgColor": "选中背景颜色"
}

33
niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.edit.json

@ -0,0 +1,33 @@
{
"addRanking": "添加榜单",
"updateRanking": "修改榜单",
"rankName": "榜单名称",
"rankBanner": "榜单banner",
"imagePlaceholder": "请上传图片",
"rankNamePlaceholder": "请输入榜单名称",
"rankType": "排行周期",
"rankTypePlaceholder": "请选择榜单周期",
"batchDeletion": "批量删除",
"goodsSource": "商品来源",
"goodsSourcePlaceholder": "请选择商品来源",
"addCategory": "添加分类",
"categoryTips": "商品分类不能为空",
"brand": "商品品牌",
"brandPlaceholder": "请选择商品品牌",
"brandTips": "商品品牌不能为空",
"addBrand": "添加品牌",
"label": "商品标签",
"labelTips": "商品标签不能为空",
"addLabel": "添加商品标签",
"sort": "排序",
"sortPlaceholder": "请输入排序号",
"ruleType": "排序规则",
"ruleTypePlaceholder": "请选择排序规则",
"selectGoods": "选择商品",
"sortTips": "排序号格式输入错误",
"goodsJsonEmpty": "商品数据不能为空",
"limitTips": "输入格式不正确",
"rankTypeTips": "天:1天,周:7天,月:30天,季度:90天",
"sortRules": "从大到小排列,支持手动修改排序号调整排名,以满足特定需求展示效果",
"isShow": "状态"
}

17
niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.list.json

@ -0,0 +1,17 @@
{
"addRanking": "添加榜单",
"rankName": "榜单名称",
"rankType": "排行周期",
"rankNamePlaceholder": "请输入榜单名称",
"batchDeletion": "批量删除",
"showGoodsNum": "榜单商品数量",
"goodsSource": "商品来源",
"ruleType": "排序规则",
"createTime": "创建时间",
"deleteTips": "确定删除该榜单吗?",
"batchEmptySelectedGoodsTips": "请先选择要删除的榜单",
"batchGoodsDeleteTips": "确定删除选中的榜单吗?",
"sortTips": "排序号格式输入错误",
"sortRules": "按照排序号从大到小排序",
"isShow": "状态"
}

37
niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.detail.json

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

88
niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.edit.json

@ -0,0 +1,88 @@
{
"addFullDiscountBonus": "添加满减送",
"editFullDiscountBonus": "修改满减送",
"activeName": "活动名称",
"activityTime": "活动时间",
"namePlaceholder": "请输入活动名称",
"conditionType": "条件类型",
"overNyuan": "满N元",
"overNgoods": "满N件",
"ruleType": "优惠规则",
"ladder": "阶梯优惠",
"cycle": "循环优惠",
"ruleJson": "优惠设置",
"activityLevel": "活动层级",
"addActivityLevel": "添加活动层级",
"discountThreshold": "优惠门槛",
"placeholder": "请输入",
"delete": "删除",
"discountContent": "优惠内容",
"discountMoney": "订单金额优惠",
"reduce": "减价",
"discountRate": "打折",
"freeShipping": "包邮",
"freeTips": "仅参与该活动的商品包邮,非整单包邮",
"givePoint": "送积分",
"giveGrowth": "送成长值",
"giveBalance": "送余额",
"giveCoupon": "送优惠券",
"giveCouponTips": "如果优惠券数量不足、限领数量已达上限或优惠券状态不是“进行中”,都将导致赠送失败。",
"name": "优惠券名称",
"type": "优惠券类型",
"couponPrice": "优惠券面值",
"couponGiveNum": "赠券数",
"giveGoods": "送赠品",
"giveGoodsTips": "当赠品库存不足或下架时则不赠送",
"stock": "库存",
"giveNum": "赠送数量",
"joinMemberType": "活动对象",
"allMember": "所有会员参与",
"selectedMemberLevel": "指定会员等级",
"selectedMemberLabel": "指定会员标签",
"memberLevel": "会员等级",
"memberLevelPlaceholder": "请选择会员等级",
"memberLabel": "会员标签",
"memberLabelPlaceholder": "请选择会员标签",
"goodsType": "参与商品",
"allGoods": "全部商品参与",
"selectedGoods": "指定商品参与",
"selectedGoodsNot": "指定商品不参与",
"selectGoods": "选择商品",
"remark": "备注",
"rankRemarkPlaceholder": "请输入备注",
"selectActivityTime": "请选择活动时间",
"selectActivityStartTime": "请选择活动开始时间",
"selectActivityEndTime": "请选择活动结束时间",
"selectActivityTimeTips": "活动结束时间不能小于等于活动开始时间",
"addLevelLimit": "层级限制最多添加五个",
"labelTips": "请选择会员标签",
"levelTips": "请选择会员等级",
"goodsJsonEmpty": "请选择商品",
"couponPlaceholder": "请选择优惠券",
"limitPlaceholder": "请输入优惠门槛",
"discountsPlaceholder": "请输入折扣或金额",
"growthPlaceholder": "请输入赠送成长值",
"pointPlaceholder": "请输入赠送积分",
"balancePlaceholder": "请输入赠送余额",
"valueMustBeGreaterThanZero": "优惠门槛必须大于0",
"pointMustBeGreaterThanZero": "赠送积分必须大于0",
"balanceMustBeGreaterThanZero": "赠送余额必须大于0",
"growthMustBeGreaterThanZero": "赠送成长值必须大于0",
"discountMustBeGreaterThanZero": "优惠内容必须大于0",
"discountMustBeGreaterThanNine": "范围大于等于0.1且小于等于9.9",
"limitTips": "输入格式不正确",
"limitTipsTwo": "每个层级的门槛金额不能相同",
"addSuccess": "添加成功",
"updateSuccess": "编辑成功",
"addFail": "添加失败",
"updateFail": "编辑失败",
"goodOnlyOne": "同一商品在一个时间段内只能参加一个满减送活动",
"discountLimit": "优惠金额不能大于优惠门槛",
"giveNumPlaceholder": "请输入赠送数量",
"giveNumMustBeGreaterThanZero": "赠送数量必须大于0",
"giveNumMustBeGreaterThanStock": "赠送数量不能大于库存",
"limitTipsThree": "必须大于上一层级的优惠门槛",
"ruleTypeTips": "阶梯优惠根据设定的门槛逐级增加优惠,达到特定层级门槛即可享受对应优惠,最高可设5个层级。",
"ruleTypeTipsTwo": "循环优惠指每次达到门槛即获赠一次优惠,无次数上限,需合理设置门槛。",
"goodsOffTips":"该商品已下架"
}

58
niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.list.json

@ -0,0 +1,58 @@
{
"addFullDiscountBonus": "添加满减送",
"name": "活动名称",
"detailTitle": "满减送活动详情",
"activeDetail": "活动详情",
"namePlaceholder": "请输入活动名称",
"title": "标题",
"status": "状态",
"statusPlaceholder": "请选择状态",
"activityTime": "活动时间",
"detail": "详情",
"close": "关闭",
"closeTips": "活动正在进行中,是否确认关闭当前活动?",
"deleteTips": "是否确认删除当前活动",
"createTime": "创建时间",
"startTime": "活动开始时间",
"endTime": "活动结束时间",
"keywordPlaceholder": "请输入商品名称",
"keyword": "商品名称",
"price": "商品价格",
"activeOrderMoney": "累计订单金额",
"activeOrderNum": "支付订单数",
"activeMemberNum": "参与会员数",
"paymentAmount": "支付金额",
"memberCount": "会员数",
"orderCount": "订单数",
"activeSuccessNum": "支付销量",
"activeName": "活动名称",
"participationMemberCount": "参与会员数",
"startDate": "开始时间",
"endDate": "结束时间",
"all": "全部",
"orderTime": "最后下单时间",
"consumptionMoney": "消费总额",
"memberInfo": "会员信息",
"participationNum": "参与次数",
"goodsInfo": "商品信息",
"discountThreshold": "优惠门槛",
"giveGoods": "送赠品",
"givePoint": "送积分",
"giveBalance": "送余额",
"giveGrowth": "送成长值",
"giveCoupon": "送优惠券",
"discountMoney": "订单优惠",
"freeShipping": "包邮",
"basicInfo": "基本信息",
"totalPoint": "累计赠送积分",
"totalBalance": "累计赠送余额",
"totalCouponNum": "累计赠送优惠券",
"totalGoodsNum": "累计赠送商品数",
"activeMember": "活动会员",
"batchDelete": "批量删除",
"batchClose": "批量关闭",
"batchEmptySelectedActiveDeleteTips": "请先选择要删除的活动",
"batchEmptySelectedActiveCloseTips": "请先选择要关闭的活动",
"batchGoodsDeleteTips": "确定删除选中的活动吗?",
"batchGoodsCloseTips": "确定关闭选中的活动吗?"
}

45
niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.config.json

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

57
niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.order_list.json

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

25
niucloud/addon/shop/admin/lang/zh-cn/order.batch_delivery.json

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

41
niucloud/addon/shop/admin/lang/zh-cn/order.config.json

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

134
niucloud/addon/shop/admin/lang/zh-cn/order.detail.json

@ -0,0 +1,134 @@
{
"orderNo": "订单编号",
"orderInfo": "订单信息",
"outTradeNo": "交易流水号",
"orderType": "订单类型",
"orderForm": "订单来源",
"takerName": "收货人",
"takerMobile": "收货人手机号",
"takerFullAddress": "收货地址",
"goodsDetail": "商品信息",
"goodsName": "商品名称",
"price": "价格",
"num": "数量",
"goodsMoney": "商品总额",
"preferentialMoney": "优惠金额",
"deliveryMoney": "配送金额",
"operateLog": "订单日志",
"orderNoPlaceholder": "请输入订单编号",
"orderStatus": "订单状态",
"orderStatusPlaceholder": "请选择订单状态",
"orderFrom": "订单类型",
"orderFromPlaceholder": "请选择订单类型",
"payTime": "支付时间",
"orderGoods": "商品",
"goodsPriceNumber": "单价(元)/数量",
"orderMoney": "订单金额",
"buyInfo": "买家/收货人",
"deliveryType": "配送方式",
"startDate": "开始时间",
"endDate": "结束时间",
"piece": "件",
"payType": "支付方式",
"notes": "备注",
"editAddress": "修改地址",
"remind": "提醒",
"remindTips1": "买家付款成功后,货款将直接进入您的商户号(微信、支付宝)",
"remindTips2": "请及时关注你发出的包裹状态,确保可以配送至买家手中",
"remindTips3": "如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商",
"close": "关闭订单",
"finish": "确认收货",
"delivery": "订单发货",
"deliveryTypePlaceholder": "请选择配送方式",
"company": "物流公司",
"companyPlaceholder": "请选择物流公司",
"expressNumber": "物流单号",
"expressNumberPlaceholder": "请输入物流单号",
"orderGoodsIdsPlaceholder": "请选择订单项",
"virtualDelivery": "虚拟发货",
"orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
"orderFinishTips": "是否确认用户已经收货?",
"orderGoodsPlaceholder": "请选择要发货的商品",
"memberRemark": "买家留言",
"discountMoney": "总优惠金额",
"couponMoney": "优惠券优惠金额",
"manjianDiscountMoney": "满减优惠金额",
"orderDelivery": "物流信息",
"devliveryTime": "发货时间",
"companyName": "物流公司",
"logisticNo": "物流单号",
"packageInfo": "物流包裹信息",
"deliveryInfo": "发货信息",
"goodsInfo": "商品信息",
"logisticInfo": "物流信息",
"storeName": "自提点名称",
"storeAddress": "自提点地址",
"storeMobile": "自提点电话",
"tradeTime": "营业时间",
"deliveryStatusName": "发货状态",
"package": "包裹",
"noLogisticsRequired": "无需物流",
"notLogistics": "暂无物流信息",
"refundStatusName": "退款状态",
"orderInfoEmpty": "暂无数据",
"editPrice": "修改价格",
"adjustMoneyDialogTitle": "调整价格",
"adjustMoneyUnit": "元",
"adjustMoneyTips": "注意 : 只有订单未付款时才支持改价,改价后请联系买家刷新订单核实订单金额后再支付。当订单总额为0元时,订单将自动支付",
"adjustMoneyDeliveryMoney": "运费",
"adjustMoneyGoodsInfo": "商品信息",
"adjustMoneyPrice": "单价",
"adjustMoneyNum": "数量",
"adjustMoneySubTotal": "小计",
"adjustMoneyDiscountMoney": "优惠金额",
"adjustMoneyLabel": "调整金额",
"adjustMoneyTotal": "总计",
"point": "积分",
"electronicSheetPrintTitle": "打印电子面单",
"electronicSheetTemplate": "面单模板",
"electronicSheetTemplatePlaceholder": "请选择面单模板",
"electronicSheetPrintResult": "打印结果",
"deliveryPackageNo": "包裹编号",
"printStatus": "状态",
"printResultCode": "状态码",
"printRemark": "备注",
"electronicSheetPrintOperation": "打印面单",
"printTicket": "打印小票",
"deliveryWay": "发货方式",
"manualWriteWay": "手动填写",
"electronicSheetWay": "电子面单",
"contacts": "联系人",
"contactsPlaceholder": "请输入联系人",
"ContactInformation": "联系方式",
"ContactInformationPlaceholder": "请输入联系方式",
"selfPickupStores": "自提门店",
"address": "地址",
"province": "请选择省",
"city": "请选择市",
"area": "请选择区/县",
"detailedAddress": "请输入详细地址",
"refundTitle": "商家主动退款",
"refundMoney": "退款金额",
"voluntaryRefund": "主动退款",
"refundState": "完成状态",
"refundType": "退款方式",
"refundInstructions": "退款说明",
"refundInstructionsOne": "1、如果是退部分金额,退款后可以是部分退款状态或退款完成状态",
"refundInstructionsTwo": "2、如果是退全部金额,则退款后一定是退款完成状态",
"refundInstructionsThree": "3、退款完成才会执行相关业务如核销码失效,卡包失效等操作",
"backRefund": "原路退款",
"offlineRefund": "线下退款",
"refundToBalance": "退款到余额",
"partialRefund": "部分退款状态",
"refundFinish": "退款完成状态",
"shopActiveRefundMoneyPlaceholder": "主动退款金额不能为空或为零",
"shopActiveRefundMoneyTwoPlaceholder": "主动退款金额不能大于可退款总额",
"refundGoodsItem": "商品项",
"refundGoodsInfo": "商品信息",
"refundGoodsSku": "规格",
"refundGoodsPrice": "售价",
"refundPayPrice": "实付金额",
"refundGoodsNum": "数量",
"refundGoodsPlaceholder": "请选择退款的商品",
"formDetail": "表单详情"
}

40
niucloud/addon/shop/admin/lang/zh-cn/order.invoice.json

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

161
niucloud/addon/shop/admin/lang/zh-cn/order.list.json

@ -0,0 +1,161 @@
{
"orderNo": "订单编号",
"createTime": "下单时间",
"orderNoPlaceholder": "请输入订单编号",
"memberInfo": "会员信息",
"memberInfoPlaceholder": "请输入会员昵称/账号/手机号/编码搜索",
"orderStatus": "订单状态",
"orderStatusPlaceholder": "请选择订单状态",
"orderFrom": "订单类型",
"orderFromPlaceholder": "请选择订单类型",
"payTime": "支付时间",
"orderGoods": "商品",
"goodsPriceNumber": "单价(元)/数量",
"orderMoney": "实付金额(元)",
"point": "积分",
"buyInfo": "买家/收货人",
"deliveryType": "配送方式",
"startDate": "开始时间",
"endDate": "结束时间",
"piece": "件",
"rightsProtection": "维权",
"activeRefund": "主动退款",
"notes": "备注",
"offlinePayment": "线下支付",
"orderClose": "关闭订单",
"editPrice": "修改价格",
"editAddress": "修改地址",
"sendOutGoods": "发货",
"confirmTakeDelivery": "确认收货",
"all": "全部",
"toBePaid": "待支付",
"toBeShipped": "待发货",
"shipped": "已发货",
"receivedGoods": "已收货",
"completed": "已完成",
"closed": "已关闭",
"refunding": "退款中",
"notesDetail": "备注信息",
"deliveryTypePlaceholder": "请选择配送方式",
"company": "物流公司",
"companyPlaceholder": "请选择物流公司",
"expressNumber": "物流单号",
"expressNumberPlaceholder": "请输入物流单号",
"orderGoodsIdsPlaceholder": "请选择订单项",
"virtualDelivery": "虚拟发货",
"goodsName": "商品名称",
"num": "商品数量",
"orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
"orderFinishTips": "是否确认用户已经收货?",
"orderGoodsPlaceholder": "请选择要发货的商品",
"deliveryStatusName": "发货状态",
"fromType": "订单来源",
"payType": "支付类型",
"orderInfo": "订单信息",
"refundStatusName": "退款状态",
"outTradeNo": "交易流水号",
"exportOrderType": "导出订单类型",
"shopOrder": "订单数据表",
"shopOrderGoods": "订单商品表",
"adjustMoneyDialogTitle": "调整价格",
"adjustMoneyUnit": "元",
"adjustMoneyTips": "注意 : 只有订单未付款时才支持改价,改价后请联系买家刷新订单核实订单金额后再支付。当订单总额为0元时,订单将自动支付",
"adjustMoneyDeliveryMoney": "运费",
"adjustMoneyGoodsInfo": "商品信息",
"adjustMoneyPrice": "单价",
"adjustMoneyNum": "数量",
"adjustMoneySubTotal": "小计",
"adjustMoneyDiscountMoney": "优惠金额",
"adjustMoneyLabel": "调整金额",
"adjustMoneyTotal": "总计",
"contacts": "联系人",
"contactsPlaceholder": "请输入联系人",
"ContactInformation": "联系方式",
"ContactInformationPlaceholder": "请输入联系方式",
"address": "地址",
"province": "请选择省",
"city": "请选择市",
"area": "请选择区/县",
"detailedAddress": "请输入详细地址",
"selfPickupStores": "自提门店",
"electronicSheetPrintTitle": "打印电子面单",
"electronicSheetTemplate": "面单模板",
"electronicSheetTemplatePlaceholder": "请选择面单模板",
"electronicSheetPrintResult": "打印结果",
"deliveryPackageNo": "包裹编号",
"batchPrintElectronicSheet": "批量打印电子面单",
"batchEmptySelectedOrderTips": "请选择要操作的订单",
"notSupportPrintElectronicSheetTips": "当前选择的订单不支持打印电子面单",
"printStatus": "状态",
"printResultCode": "状态码",
"printRemark": "备注",
"electronicSheetPrintOperation": "打印面单",
"printTicket": "打印小票",
"deliveryWay": "发货方式",
"manualWriteWay": "手动填写",
"electronicSheetWay": "电子面单",
"refundTitle": "商家主动退款",
"refundMoney": "退款金额",
"voluntaryRefund": "主动退款",
"refundState": "完成状态",
"refundType": "退款方式",
"refundInstructions": "退款说明",
"refundInstructionsOne": "1、如果是退部分金额,退款后可以是部分退款状态或退款完成状态",
"refundInstructionsTwo": "2、如果是退全部金额,则退款后一定是退款完成状态",
"refundInstructionsThree": "3、退款完成才会执行相关业务如核销码失效,卡包失效等操作",
"backRefund": "原路退款",
"offlineRefund": "线下退款",
"refundToBalance": "退款到余额",
"partialRefund": "部分退款状态",
"refundFinish": "退款完成状态",
"shopActiveRefundMoneyPlaceholder": "主动退款金额不能为空或为零",
"shopActiveRefundMoneyTwoPlaceholder": "主动退款金额不能大于可退款总额",
"refundGoodsItem": "商品项",
"refundGoodsInfo": "商品信息",
"refundGoodsSku": "规格",
"refundGoodsPrice": "售价",
"refundPayPrice": "实付金额",
"refundGoodsNum": "数量",
"refundGoodsPlaceholder": "请选择退款的商品",
"orderType": "订单类型",
"orderForm": "订单来源",
"takerName": "收货人",
"takerMobile": "收货人手机号",
"takerFullAddress": "收货地址",
"goodsDetail": "商品信息",
"price": "价格",
"detailNum": "数量",
"goodsMoney": "商品总额",
"preferentialMoney": "优惠金额",
"deliveryMoney": "配送金额",
"operateLog": "订单日志",
"detailOrderMoney": "订单金额",
"payWay": "支付方式",
"remind": "提醒",
"remindTips1": "买家付款成功后,货款将直接进入您的商户号(微信、支付宝)",
"remindTips2": "请及时关注你发出的包裹状态,确保可以配送至买家手中",
"remindTips3": "如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商",
"close": "关闭订单",
"finish": "确认收货",
"delivery": "订单发货",
"memberRemark": "买家留言",
"discountMoney": "总优惠金额",
"couponMoney": "优惠券优惠金额",
"manjianDiscountMoney": "满减优惠金额",
"orderDelivery": "物流信息",
"devliveryTime": "发货时间",
"companyName": "物流公司",
"logisticNo": "物流单号",
"packageInfo": "物流包裹信息",
"deliveryInfo": "发货信息",
"goodsInfo": "商品信息",
"logisticInfo": "物流信息",
"storeName": "自提点名称",
"storeAddress": "自提点地址",
"storeMobile": "自提点电话",
"tradeTime": "营业时间",
"package": "包裹",
"noLogisticsRequired": "无需物流",
"notLogistics": "暂无物流信息",
"orderInfoEmpty": "暂无数据"
}

106
niucloud/addon/shop/admin/lang/zh-cn/order.refund.json

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

94
niucloud/addon/shop/admin/lang/zh-cn/order.refund_detail.json

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

37
niucloud/addon/shop/admin/lang/zh-cn/stat.goods.json

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

415
niucloud/addon/shop/admin/views/address/edit.vue

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

156
niucloud/addon/shop/admin/views/address/list.vue

@ -0,0 +1,156 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-page-title">{{ pageName }}</span>
<el-button type="primary" @click="addEvent">
{{ t('addShopAddress') }}
</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="shopAddressTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('mobile')" prop="mobile">
<el-input v-model.trim="shopAddressTable.searchParam.mobile" :placeholder="t('mobilePlaceholder')"/>
</el-form-item>
<el-form-item :label="t('fullAddress')" prop="full_address">
<el-input v-model.trim="shopAddressTable.searchParam.full_address" :placeholder="t('fullAddressPlaceholder')"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadShopAddressList()">{{ 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="shopAddressTable.data" size="large" v-loading="shopAddressTable.loading">
<template #empty>
<span>{{ !shopAddressTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="contact_name" :label="t('contactName')" min-width="120"/>
<el-table-column prop="mobile" :label="t('mobile')" min-width="120"/>
<el-table-column prop="full_address" :label="t('fullAddress')" min-width="120" :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>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getShopAddressList, deleteShopAddress } from '@/addon/shop/api/shop_address'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
const route = useRoute()
const pageName = route.meta.title
const shopAddressTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
mobile: '',
full_address: ''
}
})
const searchFormRef = ref<FormInstance>()
/**
* 获取商家地址库列表
*/
const loadShopAddressList = (page: number = 1) => {
shopAddressTable.loading = true
shopAddressTable.page = page
getShopAddressList({
page: shopAddressTable.page,
limit: shopAddressTable.limit,
...shopAddressTable.searchParam
}).then(res => {
shopAddressTable.loading = false
shopAddressTable.data = res.data.data
shopAddressTable.total = res.data.total
setTablePageStorage(shopAddressTable.page, shopAddressTable.limit, shopAddressTable.searchParam);
}).catch(() => {
shopAddressTable.loading = false
})
}
loadShopAddressList(getTablePageStorage(shopAddressTable.searchParam).page);
const router = useRouter()
/**
* 添加商家地址库
*/
const addEvent = () => {
router.push('/shop/order/address/edit')
}
/**
* 编辑商家地址库
* @param data
*/
const editEvent = (data: any) => {
router.push('/shop/order/address/edit?id=' + data.id)
}
/**
* 删除商家地址库
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('shopAddressDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
deleteShopAddress(id).then(() => {
loadShopAddressList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadShopAddressList()
}
</script>
<style lang="scss" scoped>
</style>

161
niucloud/addon/shop/admin/views/delivery/company.vue

@ -0,0 +1,161 @@
<template>
<div class="main-container">
<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('addCompany') }}</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-form-item :label="t('companyName')" prop="company_name">
<el-input v-model.trim="companyTable.searchParam.company_name" :placeholder="t('companyNamePlaceholder')"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadCompanyList()">{{ 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="companyTable.data" size="large" v-loading="companyTable.loading">
<template #empty>
<span>{{ !companyTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="company_name" :label="t('companyName')" min-width="120"/>
<el-table-column prop="logo" :label="t('logo')" min-width="120">
<template #default="{ row }">
<div class="w-[50px] h-[50px] flex items-center justify-center">
<img v-if="row.logo" class="max-w-[100%] max-h-[100%]" :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>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getCompanyPageList, deleteCompany } from '@/addon/shop/api/delivery'
import { img } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const companyTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
company_name: '',
logo: '',
url: '',
create_time: '',
modify_time: ''
}
})
const searchFormRef = ref<FormInstance>()
/**
* 获取物流公司列表
*/
const loadCompanyList = (page: number = 1) => {
companyTable.loading = true
companyTable.page = page
getCompanyPageList({
page: companyTable.page,
limit: companyTable.limit,
...companyTable.searchParam
}).then(res => {
companyTable.loading = false
companyTable.data = res.data.data
companyTable.total = res.data.total
setTablePageStorage(companyTable.page, companyTable.limit, companyTable.searchParam);
}).catch(() => {
companyTable.loading = false
})
}
loadCompanyList(getTablePageStorage(companyTable.searchParam).page);
/**
* 添加物流公司
*/
const addEvent = () => {
router.push('/shop/order/delivery/company_add')
}
/**
* 编辑物流公司
* @param data
*/
const editEvent = (data: any) => {
router.push('/shop/order/delivery/company_edit?company_id=' + data.company_id)
}
/**
* 删除物流公司
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('companyDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
deleteCompany(id).then(() => {
loadCompanyList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadCompanyList()
}
</script>
<style lang="scss" scoped>
</style>

307
niucloud/addon/shop/admin/views/delivery/company_edit.vue

@ -0,0 +1,307 @@
<template>
<div class="main-container">
<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-card>
<el-card class="box-card mt-[15px] !border-none" shadow="never">
<el-form :model="formData" label-width="130px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<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-form-item>
<el-form-item :label="t('logo')">
<upload-image v-model="formData.logo"/>
</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">
<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">
<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">
<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">
<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>
<div class="text-[12px] text-[#999] mt-[5px] leading-[20px]">
<span>{{ t('expTypeTips') }}</span>
<a class="ml-[3px] text-[var(--el-color-primary)]" target="_blank" href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/hgx758hom5p6wz0l">{{t('examine')}}</a>
</div>
<p class="text-[12px] text-[#999] mt-[3px] leading-[20px]">{{ t('expTypeTips1') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('printStyle')" prop="print_style" v-show="formData.electronic_sheet_switch">
<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 prop="name" :label="t('printStyleName')" min-width="200">
<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-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-table-column :label="t('operation')" fixed="right" align="right" min-width="60">
<template #default="{ row,$index }">
<el-button type="primary" link @click="deletePrintStyleValueEvent($index)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<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>
<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>
<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>
</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>
<script lang="ts" setup>
import { reactive, ref, computed } from 'vue'
import { t } from '@/lang'
import { addCompany, editCompany, getCompanyInfo } from '@/addon/shop/api/delivery'
import { FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { filterNumber } from '@/utils/common'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const loading = ref(true)
const back = () => {
router.push('/shop/order/delivery/company')
}
/**
* 表单数据
*/
const initialFormData = {
company_id: '',
company_name: '',
logo: '',
url: '',
express_no: '',
express_no_electronic_sheet: "",
print_style: [],
exp_type: [],
electronic_sheet_switch: 1
}
const printStyleMaxLength = ref(10)
const expTypeMaxLength = ref(10)
const formData: Record<string, any> = reactive({ ...initialFormData })
formData.company_id = ref(route.query.company_id)
const getCompanyInfoFn = ()=>{
getCompanyInfo(formData.company_id).then(res => {
loading.value = false;
let data = res.data;
if (data) {
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
})
}
if(formData.company_id){
getCompanyInfoFn();
}else{
loading.value = false;
}
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
company_name: [
{ required: true, message: t('companyNamePlaceholder'), trigger: 'blur' }
],
exp_type: [
{
trigger: 'blur',
validator: (rule: any, value: any, callback: any) => {
if(!value.length){
callback()
return false;
}
let textArr = []; //
let valArr = []; //
for(let i = 0; i < value.length; i++){
if(!value[i].text){
callback(new Error(t('expTypeTextTips')))
break;
}else if(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()
}
}
],
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 = ()=>{
formData.print_style.push({
template_name: '',
template_size: ''
})
}
//
const addExpTypeValueEvent = ()=>{
formData.exp_type.push({
text: '',
value: ''
})
}
//
const deletePrintStyleValueEvent = (index:any)=>{
formData.print_style.splice(index,1)
}
//
const deleteExpTypeValueEvent = (index:any)=>{
formData.exp_type.splice(index,1)
}
/**
* 确认
* @param formEl
*/
const repeat = ref(false)
const save = async (formEl: FormInstance | undefined) => {
if (repeat.value || !formEl) return
const api = formData.company_id ? editCompany : addCompany
await formEl.validate(async (valid) => {
if (valid) {
repeat.value = true
const data = formData
api(data).then(res => {
router.push('/shop/order/delivery/company')
repeat.value = false
}).catch(() => {
repeat.value = false
})
}
})
}
</script>
<style lang="scss" scoped>
</style>

112
niucloud/addon/shop/admin/views/delivery/components/delivery-personnel-edit.vue

@ -0,0 +1,112 @@
<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-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" 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>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { addShopDeliver, editShopDeliver, getShopDeliverInfo } from '@/addon/shop/api/delivery'
import { filterNumber } from '@/utils/common'
const showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
deliver_id: '',
deliver_name: '',
deliver_mobile: ''
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
deliver_name: [
{ required: true, message: t('deliverNamePlaceholder'), trigger: 'blur' }
],
deliver_mobile: [
{ required: true, message: t('deliverMobilePlaceholder'), trigger: 'blur' },
{ min: 11, max: 11, message: '请输入11位手机号码', trigger: 'blur' },
{
pattern :/^1[23456789]\d{9}$/,
message: '请输入正确的手机号码',
trigger: 'blur'
}
]
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
const save = formData.deliver_id ? editShopDeliver : addShopDeliver
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
const data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(() => {
loading.value = false
})
}
})
}
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getShopDeliverInfo(row.deliver_id)).data
if (data) {
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
}
loading.value = false
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>

136
niucloud/addon/shop/admin/views/delivery/config.vue

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

198
niucloud/addon/shop/admin/views/delivery/electronic_sheet.vue

@ -0,0 +1,198 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center mb-[5px]">
<span class="text-lg">{{pageName}}</span>
<el-button type="primary" @click="addEvent">
{{ t('addElectronicSheet') }}
</el-button>
</div>
<el-tabs model-value="/shop/delivery/electronic_sheet" @tab-change="handleClick">
<el-tab-pane :label="t('tabESTemplate')" name="/shop/delivery/electronic_sheet" />
<el-tab-pane :label="t('tabESConfig')" name="/shop/delivery/electronic_sheet/config" />
</el-tabs>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="tableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model.trim="tableData.searchParam.template_name" :placeholder="t('templateNamePlaceholder')" maxlength="30" />
</el-form-item>
<el-form-item :label="t('expressCompany')" prop="express_company_id">
<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-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadList()">{{ 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="tableData.data" size="large" v-loading="tableData.loading">
<template #empty>
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column :label="t('templateName')" 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>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getElectronicSheetPageList, 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'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title;
const tableData = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
template_name: "",
express_company_id: "",
}
})
const searchFormRef = ref<FormInstance>()
const handleClick = (path: string) => {
router.push({ path })
}
/**
* 获取电子面单列表
*/
const loadList = (page: number = 1) => {
tableData.loading = true
tableData.page = page
getElectronicSheetPageList({
page: tableData.page,
limit: tableData.limit,
...tableData.searchParam
}).then(res => {
tableData.loading = false
tableData.data = res.data.data
tableData.total = res.data.total
}).catch(() => {
tableData.loading = false
})
}
loadList()
const companyList = ref([])
getCompanyList({
electronic_sheet_switch: 1
}).then((res:any)=>{
companyList.value = res.data;
})
/**
* 添加电子面单
*/
const addEvent = () => {
router.push('/shop/delivery/electronic_sheet_add')
}
/**
* 编辑电子面单
* @param data
*/
const editEvent = (data: any) => {
router.push('/shop/delivery/electronic_sheet_edit?id=' + data.id)
}
/**
* 删除电子面单
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('electronicSheetDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteElectronicSheet(id).then(() => {
loadList()
})
})
}
/**
* 设置默认电子面单模版
*/
const setDefaultEvent = (id: number) => {
ElMessageBox.confirm(t('electronicSheetSetDefaultTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
setDefaultElectronicSheet({id}).then(() => {
loadList()
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadList()
}
</script>
<style lang="scss" scoped>
</style>

184
niucloud/addon/shop/admin/views/delivery/electronic_sheet_config.vue

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

270
niucloud/addon/shop/admin/views/delivery/electronic_sheet_edit.vue

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

437
niucloud/addon/shop/admin/views/delivery/local.vue

@ -0,0 +1,437 @@
<template>
<div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card>
<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">
<!-- <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>
<el-radio-group v-model="formData.time_is_open">
<el-radio :label="1">{{ t('open') }}</el-radio>
<el-radio :label="0">{{ t('close') }}</el-radio>
</el-radio-group>
<div class="mt-[10px] text-[12px] text-[#999] leading-[20px]">{{t('timeIsOpenTips')}}</div>
</div>
</el-form-item>
<template v-if="formData.time_is_open === 1">
<el-form-item>
<el-radio-group v-model="formData.time_type">
<el-radio :label="0">{{ t('everyDay') }}</el-radio>
<el-radio :label="1">{{ t('custom') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="time_week" v-if="formData.time_type===1">
<el-checkbox-group v-model="formData.time_week">
<el-checkbox label="1">{{ t('monday') }}</el-checkbox>
<el-checkbox label="2">{{ t('tuesday') }}</el-checkbox>
<el-checkbox label="3">{{ t('wednesday') }}</el-checkbox>
<el-checkbox label="4">{{ t('thursday') }}</el-checkbox>
<el-checkbox label="5">{{ t('friday') }}</el-checkbox>
<el-checkbox label="6">{{ t('saturday') }}</el-checkbox>
<el-checkbox label="7">{{ t('sunday') }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
</template> -->
<el-form-item :label="t('deliveryAddress')" prop="delivery_address">
<div class="flex flex-col">
<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>
</div>
<div class="text-error leading-none" v-if="formData.center.lat && defaultDeliveryAddress && (formData.center.lat != defaultDeliveryAddress.lat || formData.center.lng != defaultDeliveryAddress.lng)">
{{ t('deliveryAddressChange') }}</div>
</div>
</el-form-item>
<el-form-item :label="t('feeType')">
<el-radio-group v-model="formData.fee_type">
<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 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>
</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>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, onBeforeUnmount,toRaw } from 'vue'
import { t } from '@/lang'
import { useRoute, useRouter } from 'vue-router'
import { getMap } from '@/app/api/sys'
import { guid, filterDigit, deepClone } from '@/utils/common'
import { createCircle, deleteGeometry, createPolygon, selectGeometry, createMarker } from '@/utils/qqmap'
import { setLocal, getLocal } from '@/addon/shop/api/delivery'
import { FormInstance } from 'element-plus'
import Test from '@/utils/test'
import { getShopDefaultDeliveryAddressInfo } from '@/addon/shop/api/shop_address'
const route = useRoute()
const router = useRouter()
const loading = ref(true)
const pageName = route.meta.title
const formRef = ref<FormInstance>()
const areaFromRef: any = ref<FormInstance[]>()
interface addressType{
full_address:string
lat:string
lng:string
}
const defaultDeliveryAddress:any = ref<addressType|null>(null)
const getDefaultDeliveryAddress = async () => {
await getShopDefaultDeliveryAddressInfo().then(({ data }) => {
defaultDeliveryAddress.value = data
}).catch()
}
getDefaultDeliveryAddress()
const formData = ref({
center: {
lat: '',
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.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(() => {
return {
time_week: [{ required: true, message: t('timeWeekRequire'), trigger: 'change' }],
delivery_address: [
{
validator: (rule: any, value: any, callback: any) => {
if (!defaultDeliveryAddress.value) {
callback(new Error(t('defaultDeliveryAddressEmpty')))
}
callback()
}
}
],
delivery_type: [
{
validator: (rule: any, value: any, callback: any) => {
if (!formData.value.delivery_type.length) {
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)) {
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'
}
],
area_name: [{ required: true, message: t('areaNameRequire'), 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 }) => {
loading.value = false
if (data) Object.assign(formData.value, data)
formData.value.time_week = formData.value.time_week?formData.value.time_week.split(','):[]
}).catch(()=>{
loading.value = false
})
onMounted(() => {
const mapScript = document.createElement('script')
getMap().then(res => {
mapScript.type = 'text/javascript'
mapScript.src = 'https://map.qq.com/api/gljs?libraries=tools,service&v=1.exp&key=' + res.data.key
document.body.appendChild(mapScript)
})
mapScript.onload = () => {
setTimeout(() => {
initMap()
}, 500)
}
})
/**
* 初始化地图
*/
let map: any
const mapLoading = ref(true)
const initMap = () => {
const TMap = (window as any).TMap
const LatLng = TMap.LatLng
const center = new LatLng(defaultDeliveryAddress.value ? defaultDeliveryAddress.value.lat : 39.980619, defaultDeliveryAddress.value ? defaultDeliveryAddress.value.lng : 116.321277)
map = new TMap.Map('container', {
center,
zoom: 14
})
createMarker(map)
map.on('tilesloaded', () => {
mapLoading.value = false
})
formData.value.area.forEach(item => {
item.area_type == 'radius' ? createCircle(map, item.area_json) : createPolygon(map, item.area_json)
})
}
const currArea = ref<number>(0)
/**
* 添加配送区域
*/
const addArea = () => {
formData.value.area.push({
area_name: '',
area_type: 'radius',
start_price: 0,
delivery_price: 0,
area_json: {
key: guid()
}
})
const index = formData.value.area.length - 1
createCircle(map, formData.value.area[index].area_json)
}
/**
* 删除配送区域
*/
const deleteArea = (index: number) => {
const data = formData.value.area[index]
deleteGeometry(data.area_json.key)
formData.value.area.splice(index, 1)
}
const selectArea = (index: number) => {
currArea.value = index
const data = formData.value.area[index]
selectGeometry(data.area_json.key)
}
const areaTypeChange = (index: number) => {
const data = formData.value.area[index]
deleteGeometry(data.area_json.key)
data.area_type == 'radius' ? createCircle(map, data.area_json) : createPolygon(map, data.area_json)
}
onBeforeUnmount(() => {
map.destroy()
})
const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
let areaValidate = true
for (let i = 0; i < areaFromRef.value?.length; i++) {
const ref = areaFromRef.value[i]
await ref.validate(async (valid) => {
areaValidate = valid
})
if (!areaValidate) break
}
if (!areaValidate) return
if (valid) {
loading.value = true
formData.value.center = {
lat: defaultDeliveryAddress.value.lat,
lng: defaultDeliveryAddress.value.lng
}
await formEl.validate(async (valid) => {
const param = deepClone(toRaw(formData.value))
param.time_week = param.time_week.toString()
setLocal(param).then(() => {
loading.value = false
}).catch(() => {
loading.value = false
})
})
}
})
}
const back = () => {
router.push({ path: '/shop/order/delivery' })
}
</script>
<style lang="scss" scoped>
.region-list {
border: 1px solid var(--el-border-color-lighter);
z-index: 3;
.region-item {
border: 1px solid transparent;
border-bottom-color: var(--el-border-color-lighter);
}
}
#container :deep(div){
z-index: 2 !important;
}
</style>

158
niucloud/addon/shop/admin/views/delivery/search.vue

@ -0,0 +1,158 @@
<template>
<div class="main-container">
<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-card>
<el-form :model="formData" label-width="150px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<el-form-item :label="t('interfaceType')" prop="interface_type">
<div>
<el-radio-group v-model="formData.interface_type">
<el-radio :label="1" size="large">{{ t('kdn') }}</el-radio>
<!-- <el-radio :label="2" size="large">{{ t('kd100') }}</el-radio>-->
</el-radio-group>
<p class="text-[12px] text-[#b2b2b2]" v-if="formData.interface_type == 1">
{{ t('promptTips1-1') }}<el-button class="button-size" type="primary" link @click="openEvent('https://www.kdniao.com')">https://www.kdniao.com</el-button>
</p>
<p class="text-[12px] text-[#b2b2b2]" v-if="formData.interface_type == 1">
{{ t('promptTips1-2') }}
</p>
<!-- <p class="text-[12px] text-[#b2b2b2]" v-if="formData.interface_type == 2">-->
<!-- {{ t('promptTips2') }}<el-button class="button-size" type="primary" link @click="openEvent('https://www.kuaidi100.com')">https://www.kuaidi100.com</el-button>-->
<!-- </p>-->
</div>
</el-form-item>
<div v-if="formData.interface_type == 1">
<el-form-item :label="t('isPayEdition')" prop="kdn_is_pay" class="items-center">
<el-radio-group v-model="formData.kdniao_is_pay">
<el-radio :label="1" size="large">{{ t('free') }}</el-radio>
<el-radio :label="2" size="large">{{ t('pay') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="EBusinessID" class="input-item">
<div>
<el-input v-model.trim="formData.kdniao_id" :placeholder="t('kdnEBusinessIDPlaceholder')" class="input-width" clearable />
<p class="text-[12px] text-[#b2b2b2]">{{ t('kdnEBusinessIDTips') }}</p>
</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>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { ArrowLeft } from '@element-plus/icons-vue'
import { FormInstance, FormRules } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { setDeliverySearch, getDeliverySearch } from '@/addon/shop/api/delivery'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const loading = ref(true)
interface formDataType {
interface_type: number
kdniao_id: string
kdniao_app_key: string
kdniao_is_pay: number
kd100_app_key: string
kd100_customer: string
}
const formData = reactive<formDataType|any>({
interface_type: 1,
kdniao_id: '',
kdniao_app_key: '',
kdniao_is_pay: 1,
kd100_app_key: '',
kd100_customer: ''
})
const setFormData = async () => {
const data = await (await getDeliverySearch()).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
loading.value = false
}
setFormData()
const openEvent = (url:any) => {
window.open(url, '_blank')
}
const formRef = ref<FormInstance>()
//
const formRules = reactive<FormRules>({
})
/**
* 保存
*/
const save = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
setDeliverySearch(formData).then(() => {
loading.value = false
}).catch(() => {
loading.value = false
})
}
})
}
</script>
<style lang="scss" scoped>
.input-item {
margin-bottom: 10px !important
}
.button-size {
font-size: 12px !important;
}
.el-radio.el-radio--large {
height: auto !important
}
</style>

140
niucloud/addon/shop/admin/views/delivery/staff.vue

@ -0,0 +1,140 @@
<template>
<div class="main-container">
<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('addDeliveryPersonnel') }}
</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="tableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('deliverName')" prop="deliver_name">
<el-input v-model.trim="tableData.searchParam.deliver_name" :placeholder="t('deliverNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('deliverMobile')" prop="deliver_mobile">
<el-input v-model.trim="tableData.searchParam.deliver_mobile" :placeholder="t('deliverMobilePlaceholder')" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getShopDeliveryFn()">{{ 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="tableData.data" ref="tableRef" size="large" v-loading="tableData.loading">
<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>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import deliveryPersonnelEdit from '@/addon/shop/views/delivery/components/delivery-personnel-edit.vue'
import { getShopDelivery, deleteShopDeliver } from '@/addon/shop/api/delivery'
import { useRoute, useRouter } from 'vue-router'
import { ElMessageBox, FormInstance } from 'element-plus'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const tableData = reactive({
page: 1,
limit: 10,
total: 0,
loading: false,
data: [],
searchParam: {
deliver_name: '',
deliver_mobile: ''
}
})
const searchFormRef = ref<FormInstance>()
/**
* 获取配送员列表
*/
const getShopDeliveryFn = (page: number = 1) => {
tableData.loading = true
tableData.page = page
getShopDelivery({
page: tableData.page,
limit: tableData.limit,
...tableData.searchParam
}).then(res => {
tableData.loading = false
tableData.data = res.data.data
tableData.total = res.data.total
}).catch(() => {
tableData.loading = false
})
}
getShopDeliveryFn()
const editCategoryDialog: Record<string, any> | null = ref(null)
/**
* 添加配送员
*/
const addEvent = () => {
editCategoryDialog.value.setFormData()
editCategoryDialog.value.showDialog = true
}
/**
* 编辑配送员
* @param data
*/
const editEvent = (data: any) => {
editCategoryDialog.value.setFormData(data)
editCategoryDialog.value.showDialog = true
}
/**
* 删除配送员
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('deliverDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
deleteShopDeliver(id).then(() => {
getShopDeliveryFn()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
getShopDeliveryFn()
}
</script>
<style lang="scss" scoped></style>

168
niucloud/addon/shop/admin/views/delivery/store.vue

@ -0,0 +1,168 @@
<template>
<div class="main-container">
<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('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>
</template>
</el-image>
<p class="ml-[10px] text-[14px]">{{ row.store_name }}</p>
</div>
</template>
</el-table-column>
<el-table-column prop="store_mobile" :label="t('storeMobile')" min-width="120" />
<el-table-column prop="full_address" :label="t('fullAddress')" min-width="180" />
<el-table-column prop="trade_time" :label="t('tradeTime')" min-width="120" />
<el-table-column :label="t('createTime')" min-width="120">
<template #default="{ row }">
{{ row.create_time || '' }}
</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.store_id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="storeTable.page" v-model:page-size="storeTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="storeTable.total"
@size-change="loadStoreList()" @current-change="loadStoreList" />
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getStoreList, deleteStore } from '@/addon/shop/api/delivery'
import { img } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
const route = useRoute()
const pageName = route.meta.title
const storeTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
store_name: '',
create_time: ''
}
})
const searchFormRef = ref<FormInstance>()
/**
* 获取自提门店列表
*/
const loadStoreList = (page: number = 1) => {
storeTable.loading = true
storeTable.page = page
getStoreList({
page: storeTable.page,
limit: storeTable.limit,
...storeTable.searchParam
}).then(res => {
storeTable.loading = false
storeTable.data = res.data.data
storeTable.total = res.data.total
setTablePageStorage(storeTable.page, storeTable.limit, storeTable.searchParam);
}).catch(() => {
storeTable.loading = false
})
}
loadStoreList(getTablePageStorage(storeTable.searchParam).page);
const router = useRouter()
/**
* 添加自提门店
*/
const addEvent = () => {
router.push('/shop/order/delivery/store/edit')
}
/**
* 编辑自提门店
* @param data
*/
const editEvent = (data: any) => {
router.push('/shop/order/delivery/store/edit?id=' + data.store_id)
}
/**
* 删除自提门店
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('storeDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
deleteStore(id).then(() => {
loadStoreList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadStoreList()
}
</script>
<style lang="scss" scoped>
</style>

408
niucloud/addon/shop/admin/views/delivery/store_edit.vue

@ -0,0 +1,408 @@
<template>
<div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="id ? t('updateStore') : t('addStore')" :icon="ArrowLeft" @back="back" />
</el-card>
<el-card class="box-card !border-none" shadow="never" v-loading="loading">
<el-form :model="formData" label-width="140px" ref="formRef" :rules="formRules" class="page-form">
<el-form-item :label="t('storeName')" prop="store_name">
<el-input v-model.trim="formData.store_name" clearable :placeholder="t('storeNamePlaceholder')"
class="input-width" />
</el-form-item>
<el-form-item :label="t('storeDesc')">
<el-input v-model.trim="formData.store_desc" type="textarea" rows="4" clearable
:placeholder="t('storeDescPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('storeLogo')">
<upload-image v-model="formData.store_logo" />
</el-form-item>
<el-form-item :label="t('storeMobile')" prop="store_mobile">
<el-input v-model.trim="formData.store_mobile" clearable :placeholder="t('storeMobilePlaceholder')"
class="input-width" @keyup="filterNumber($event)"
@blur="formData.store_mobile = $event.target.value" />
</el-form-item>
<el-form-item :label="t('tradeTime')" prop="trade_time">
<div>
<el-input v-model.trim="formData.trade_time" clearable :placeholder="t('tradeTimePlaceholder')"
class="input-width" />
<p class="text-[12px] text-[#999]">{{ t('tradeTimeTips') }}</p>
</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>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { getStoreInfo, addStore, editStore } from '@/addon/shop/api/delivery'
import { getMap, getAreaListByPid, getAreaByCode } from '@/app/api/sys'
import { useRoute } from 'vue-router'
import { createMarker, latLngToAddress, addressToLatLng } from '@/utils/qqmap'
import { filterNumber, debounce } from '@/utils/common'
const route = useRoute()
const id: number = parseInt(route.query.id as string)
const loading = ref(false)
const pageName = route.meta.title
interface areaType{
province: any[],
city: any[],
district: any[]
}
const areaList = reactive<areaType>({
province: [],
city: [],
district: []
})
const provinceRef = ref()
const cityRef = ref()
const districtRef = ref()
/**
* 获取省
*/
getAreaListByPid(0).then(res => {
areaList.province = res.data
})
let mapKey: string = ''
onMounted(() => {
const mapScript = document.createElement('script')
getMap().then(res => {
mapKey = res.data.key
mapScript.type = 'text/javascript'
mapScript.src = 'https://map.qq.com/api/gljs?libraries=tools,service&v=1.exp&key=' + res.data.key
document.body.appendChild(mapScript)
})
mapScript.onload = () => {
setTimeout(() => {
initMap()
}, 500)
}
})
/**
* 初始化地图
*/
let map: any
let marker: any
const mapLoading = ref(true)
const initMap = () => {
const TMap = (window as any).TMap
const LatLng = TMap.LatLng
const center = new LatLng(formData.latitude, formData.longitude)
map = new TMap.Map('container', {
center,
zoom: 14
})
map.on('tilesloaded', () => {
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)
})
latLngChange(center.lat, center.lng)
}
const storeArea = reactive({
province_id: 0,
city_id: 0,
district_id: 0
})
const latLngChange = (lat: number, lng: number) => {
latLngToAddress({ mapKey, lat, lng }).then(({ message, result }) => {
if (message == 'query ok' || message == 'Success') {
formData.latitude = result.location.lat
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
storeArea.city_id = data.city ? data.city.id : 0
storeArea.district_id = data.district ? data.district.id : 0
})
} else {
console.error(message, result)
}
}).catch(err => {
console.log(err)
})
}
/**
* 表单数据
*/
const initialFormData = {
store_id: 0,
store_name: '',
store_desc: '',
store_logo: '',
store_mobile: '',
province_id: 0,
province_name: '',
city_id: 0,
city_name: '',
district_id: 0,
district_name: '',
address: '',
full_address: '',
longitude: 116.397190,
latitude: 39.908626,
trade_time: ''
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const setFormData = async (id: number = 0) => {
loading.value = true
Object.assign(formData, initialFormData)
const data = await (await getStoreInfo(id)).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
loading.value = false
}
if (id) setFormData(id)
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
store_name: [
{ required: true, message: t('storeNamePlaceholder'), trigger: 'blur' }
],
store_logo: [
{ required: true, message: t('storeLogoPlaceholder'), trigger: 'blur' }
],
store_mobile: [
{ required: true, message: t('storeMobilePlaceholder'), trigger: 'blur' }
],
trade_time: [
{ required: true, message: t('tradeTimePlaceholder'), trigger: 'blur' }
],
address_area: [
{
validator: (rule: any, value: any, callback: any) => {
if (!formData.province_id) {
callback(new Error(t('provincePlaceholder')))
}
if (!formData.city_id) {
callback(new Error(t('cityPlaceholder')))
}
if (areaList.district.length && !formData.district_id) {
callback(new Error(t('districtPlaceholder')))
}
callback()
}
}
],
address: [
{ required: true, message: t('addressPlaceholder'), trigger: 'blur' }
]
}
})
/**
* 获取市
*/
watch(() => formData.province_id, (nval) => {
if (nval) {
getAreaListByPid(formData.province_id).then(res => {
areaList.city = res.data
const cityId = formData.city_id
if (cityId) {
let isExist = false
for (let i = 0; i < res.data.length; i++) {
if (cityId == res.data[i].id) {
isExist = true
break
}
}
if (isExist) {
formData.city_id = cityId
return
}
}
formData.city_id = 0
areaChange()
})
} else {
formData.city_id = 0
}
})
/**
* 获取区
*/
watch(() => formData.city_id, (nval) => {
if (nval) {
getAreaListByPid(formData.city_id).then(res => {
areaList.district = res.data
const districtId = formData.district_id
if (districtId) {
let isExist = false
for (let i = 0; i < res.data.length; i++) {
if (districtId == res.data[i].id) {
isExist = true
break
}
}
if (isExist) {
formData.district_id = districtId
return
}
}
areaChange()
formData.district_id = 0
})
} else {
formData.district_id = 0
}
})
watch(() => formData.district_id, (nval) => {
if (nval) {
areaChange()
}
})
const areaChange = debounce(() => {
setTimeout(() => {
const address = [
formData.province_id ? provinceRef.value.states.selectedLabel : '',
formData.city_id ? cityRef.value.states.selectedLabel : '',
formData.district_id ? districtRef.value.states.selectedLabel : ''
]
addressToLatLng({ mapKey, address: address.join('') }).then(({ message, result }) => {
if (message == 'Success' || message == 'query ok') {
const latLng = new (window as any).TMap.LatLng(result.location.lat, result.location.lng)
map.setCenter(latLng)
marker.updateGeometries({
id: 'center',
position: latLng
})
formData.latitude = result.location.lat
formData.longitude = result.location.lng
} else {
console.error(message, result)
}
})
}, 500)
}, 500)
/**
* 地图点选获取市
*/
watch(() => storeArea.province_id, (nval) => {
if (nval) {
getAreaListByPid(storeArea.province_id).then(res => {
areaList.city = res.data
formData.province_id = storeArea.province_id
formData.city_id = storeArea.city_id
})
}
})
/**
* 地图点选获取区
*/
watch(() => storeArea.city_id, (nval) => {
if (nval) {
getAreaListByPid(storeArea.city_id).then(res => {
areaList.district = res.data
formData.city_id = storeArea.city_id
formData.district_id = storeArea.district_id
})
}
})
/**
* 地图点选获取区
*/
watch(() => storeArea.district_id, (nval) => {
if (nval) {
formData.district_id = storeArea.district_id
}
})
const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
const data = formData
formData.province_name = formData.province_id ? provinceRef.value.states.selectedLabel : '',
formData.city_name = formData.city_id ? cityRef.value.states.selectedLabel : '',
formData.district_name = formData.district_id ? districtRef.value.states.selectedLabel : ''
const address = [
data.province_id ? provinceRef.value.states.selectedLabel : '',
data.city_id ? cityRef.value.states.selectedLabel : '',
data.district_id ? districtRef.value.states.selectedLabel : '',
data.address
]
data.full_address = address.join('')
const save = id ? editStore : addStore
save(data).then(res => {
loading.value = false
history.back()
}).catch(() => {
loading.value = false
})
}
})
}
const back = () => {
history.back()
}
</script>
<style lang="scss" scoped></style>

149
niucloud/addon/shop/admin/views/delivery/template.vue

@ -0,0 +1,149 @@
<template>
<div class="main-container">
<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>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="templateTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model.trim="templateTable.searchParam.template_name" :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>
<div class="mt-[10px]">
<el-table :data="templateTable.data" size="large" v-loading="templateTable.loading">
<template #empty>
<span>{{ !templateTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="template_name" :label="t('templateName')" 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">
<template #default="{ row }">
{{ row.is_free_shipping ? t('open') : t('close') }}
</template>
</el-table-column>
<el-table-column prop="create_time" :label="t('createTime')" min-width="120" />
<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.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>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getShippingTemplatePageList, deleteShippingTemplate } from '@/addon/shop/api/delivery'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const templateTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
template_name: ''
}
})
const searchFormRef = ref<FormInstance>()
/**
* 获取运费模板列表
*/
const loadTemplateList = (page: number = 1) => {
templateTable.loading = true
templateTable.page = page
getShippingTemplatePageList({
page: templateTable.page,
limit: templateTable.limit,
...templateTable.searchParam
}).then(res => {
templateTable.loading = false
templateTable.data = res.data.data
templateTable.total = res.data.total
setTablePageStorage(templateTable.page, templateTable.limit, templateTable.searchParam);
}).catch(() => {
templateTable.loading = false
})
}
loadTemplateList(getTablePageStorage(templateTable.searchParam).page);
/**
* 添加运费模板
*/
const addEvent = () => {
router.push({ path: '/shop/order/shipping/template_edit' })
}
/**
* 编辑运费模板
* @param data
*/
const editEvent = (data: any) => {
router.push({ path: '/shop/order/shipping/template_edit', query: { id: data.template_id } })
}
/**
* 删除运费模板
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('templateDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
deleteShippingTemplate(id).then(() => {
loadTemplateList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadTemplateList()
}
</script>
<style lang="scss" scoped>
</style>

501
niucloud/addon/shop/admin/views/delivery/template_edit.vue

@ -0,0 +1,501 @@
<template>
<div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card>
<el-card class="box-card !border-none" shadow="never">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model.trim="formData.template_name" clearable :placeholder="t('templateNamePlaceholder')" class="input-width" maxlength="60" />
</el-form-item>
<el-form-item :label="t('feeTypeName')" prop="fee_type">
<el-radio-group v-model="formData.fee_type">
<el-radio label="num" size="large">{{ t('num') }}</el-radio>
<el-radio label="weight" size="large">{{ t('weight') }}</el-radio>
<el-radio label="volume" size="large">{{ t('volume') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('feeSetting')" prop="fee_data">
<el-table :data="feeData" style="width: 100%" size="default">
<el-table-column :label="t('deliveryArea')">
<template #default="{ row, $index }">
<div class="area-input">
<span v-if="$index" @click="selectArea('fee', $index)" class="cursor-pointer">{{ row.fee_area_names ? row.fee_area_names : t('areaPlaceholder') }}</span>
<span v-else>{{ row.fee_area_names ? row.fee_area_names : t('areaPlaceholder') }}</span>
</div>
</template>
</el-table-column>
<el-table-column :label="feeLabel.first">
<template #default="{ $index }">
<el-input v-model.trim="feeData[$index].snum" maxlength="8" @keyup="filterDigit($event)" @blur="feeData[$index].snum = $event.target.value"/>
</template>
</el-table-column>
<el-table-column :label="t('fee')">
<template #default="{ $index }">
<el-input v-model.trim="feeData[$index].sprice" maxlength="8" @keyup="filterDigit($event)" @blur="feeData[$index].sprice = $event.target.value"/>
</template>
</el-table-column>
<el-table-column :label="feeLabel.continue">
<template #default="{ $index }">
<el-input v-model.trim="feeData[$index].xnum" maxlength="8" @keyup="filterDigit($event)" @blur="feeData[$index].xnum = $event.target.value"/>
</template>
</el-table-column>
<el-table-column :label="t('continueFee')">
<template #default="{ $index }">
<el-input v-model.trim="feeData[$index].xprice" @keyup="filterDigit($event)" maxlength="8" @blur="feeData[$index].xprice = $event.target.value"/>
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" width="150">
<template #default="{ $index }">
<el-button type="primary" @click="delArea('fee', $index)" link v-if="$index">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[10px]">
<el-button type="primary" @click="addArea('fee')">{{ t('addDeliveryArea') }}</el-button>
</div>
</el-form-item>
<!-- 指定区域包邮 -->
<el-form-item :label="t('freeShipping')" prop="is_free_shipping">
<el-switch v-model="formData.is_free_shipping" size="small" :inactive-value="0" :active-value="1" />
</el-form-item>
<el-form-item v-show="formData.is_free_shipping" prop="free_shipping_data">
<el-table :data="freeShippingData" style="width: 100%" size="default">
<el-table-column :label="t('freeShippingArea')">
<template #default="{ row, $index }">
<div class="area-input">
<el-input v-model.trim="row.free_shipping_area_names" :placeholder="t('areaPlaceholder')" readonly @click="selectArea('free_shipping', $index)" />
</div>
</template>
</el-table-column>
<el-table-column :label="freeShippingLabel">
<template #default="{ $index }">
<el-input v-model.trim="freeShippingData[$index].free_shipping_num" @keyup="filterDigit($event)" maxlength="8" @blur="freeShippingData[$index].free_shipping_num = $event.target.value"/>
</template>
</el-table-column>
<el-table-column :label="t('freeShippingPrice')">
<template #default="{ $index }">
<el-input v-model.trim="freeShippingData[$index].free_shipping_price" @keyup="filterDigit($event)" maxlength="8" @blur="freeShippingData[$index].free_shipping_price = $event.target.value"/>
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" width="150">
<template #default="{ $index }">
<el-button type="primary" @click="delArea('free_shipping', $index)" link>{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="form-tip">{{ t('freeShippingAreaTips') }}</div>
<div class="mt-[10px]">
<el-button type="primary" @click="addArea('free_shipping')">{{ t('addFreeShippingArea') }}</el-button>
</div>
</el-form-item>
<!-- 指定区域不配送 -->
<el-form-item :label="t('noDelivery')" prop="no_delivery">
<el-switch v-model="formData.no_delivery" size="small" :inactive-value="0" :active-value="1" />
</el-form-item>
<el-form-item v-show="formData.no_delivery" prop="no_delivery_data">
<el-table :data="noDeliveryData" style="width: 100%" size="default">
<el-table-column :label="t('noDelivery')">
<template #default="{ row, $index }">
<div class="area-input">
<el-input v-model.trim="row.no_delivery_area_names" readonly @click="selectArea('no_delivery', $index)" :placeholder="t('areaPlaceholder')" />
</div>
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" width="150">
<template #default="{ $index }">
<el-button type="primary" @click="delArea('no_delivery', $index)" link>{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[10px]">
<el-button type="primary" @click="addArea('no_delivery')">{{ t('addNoDelivery') }}</el-button>
</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>
<!-- 选择地区弹窗 -->
<el-dialog v-model="showSelectAreaDialog" :title="t('selectArea')" width="80%" class="diy-dialog-wrap" :destroy-on-close="true" @opened="showSelectOpened">
<el-scrollbar height="50vh">
<el-tree :data="areaTreeData" :props="{ children: 'child', label: 'name' }" default-expand-all show-checkbox ref="areaTreeRef" :default-checked-keys="selectedArea" node-key="id" />
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button @click="showSelectAreaDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirmSelectArea">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import { ElTree, FormInstance, ElMessage } from 'element-plus'
import { addShippingTemplate, editShippingTemplate, getShippingTemplateInfo } from '@/addon/shop/api/delivery'
import { AnyObject } from '@/types/global'
import { useRoute, useRouter } from 'vue-router'
import { getAreatree } from '@/app/api/sys'
import { filterDigit } from '@/utils/common'
import Test from '@/utils/test'
const showSelectAreaDialog = ref(false)
const route = useRoute()
const router = useRouter()
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
template_id: '',
template_name: '',
fee_type: 'num',
area: [],
no_delivery: 0,
is_free_shipping: 0,
fee_data: [],
free_shipping_data: [],
no_delivery_data: []
}
const pageName = route.meta.title
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
const areaTree = ref<AnyObject[]>([])
if (route.query.id) {
loading.value = true
getShippingTemplateInfo(route.query.id).then(({ data }) => {
if (data) {
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
feeData.value = data.fee_data
noDeliveryData.value = data.no_delivery_data
freeShippingData.value = data.free_shipping_data
}
loading.value = false
}).catch(() => {
loading.value = false
})
}
getAreatree(2).then(res => {
areaTree.value = res.data
}).catch()
//
const formRules = computed(() => {
return {
template_name: [
{ required: true, message: t('templateNamePlaceholder'), trigger: 'blur' }
],
fee_data: [{ validator: feeDataValidate }],
free_shipping_data: [{ validator: freeShippingDataValidate }],
no_delivery_data: [{ validator: noDeliveryDataValidate }]
}
})
/**
* 运费模板运费数据校验
*/
const feeDataValidate = (rule: any, value: any, callback: any) => {
for (let i = 0; i < feeData.value.length; i++) {
const item = feeData.value[i]
if (!item.area_ids.length) {
callback(new Error(t('areaPlaceholder')))
break
}
if (Test.empty(item.snum) || item.snum < 0) {
callback(new Error(feeLabel.value.first + t('notUnderZero')))
break
}
if (Test.empty(item.xnum) || item.snum < 0) {
callback(new Error(feeLabel.value.continue + t('notUnderZero')))
break
}
}
callback()
}
/**
* 运费模板包邮数据校验
*/
const freeShippingDataValidate = (rule: any, value: any, callback: any) => {
if (formData.is_free_shipping) {
for (let i = 0; i < freeShippingData.value.length; i++) {
const item = freeShippingData.value[i]
if (!item.area_ids.length) {
callback(new Error(t('freeShippingPlaceholder')))
break
}
if (Test.empty(item.free_shipping_num) || item.free_shipping_num < 0) {
callback(new Error(freeShippingLabel.value + t('notUnderZero')))
break
}
}
callback()
} else {
callback()
}
}
/**
* 运费模板不配送地区校验
*/
const noDeliveryDataValidate = (rule: any, value: any, callback: any) => {
if (formData.no_delivery) {
for (let i = 0; i < noDeliveryData.value.length; i++) {
const item = noDeliveryData.value[i]
if (!item.area_ids.length) {
callback(new Error(t('noDeliveryPlaceholder')))
break
}
}
callback()
} else {
callback()
}
}
const feeLabel = computed(() => {
const label: AnyObject = {
num: {
first: t('firstNum'),
continue: t('continueNum')
},
weight: {
first: t('firstWeight'),
continue: t('continueWeight')
},
volume: {
first: t('firstVolume'),
continue: t('continueVolume')
}
}
return label[formData.fee_type]
})
const freeShippingLabel = computed(() => {
const label: AnyObject = {
num: t('freeShippingNum'),
weight: t('freeShippingWeight'),
volume: t('freeShippingVolume')
}
return label[formData.fee_type]
})
//
const feeData = ref<AnyObject[]>([
{ area_ids: [0], fee_area_names: '全国', snum: 1, sprice: 0, xnum: 1, xprice: 0 }
])
//
const freeShippingData = ref<AnyObject[]>([])
//
const noDeliveryData = ref<AnyObject[]>([])
/**
* 添加地区
* @param type
*/
const addArea = (type: string) => {
switch (type) {
case 'fee':
feeData.value.push({ area_ids: [], fee_area_names: '', snum: 1, sprice: 0, xnum: 1, xprice: 0 })
break
case 'free_shipping':
freeShippingData.value.push({ area_ids: [], free_shipping_area_names: '', free_shipping_num: 0, free_shipping_price: 0 })
break
case 'no_delivery':
noDeliveryData.value.push({ area_ids: [], no_delivery_area_names: '' })
break
}
}
/**
*删除地区
* @param type
* @param index
*/
const delArea = (type: string, index: number) => {
switch (type) {
case 'fee':
feeData.value.splice(index, 1)
break
case 'free_shipping':
freeShippingData.value.splice(index, 1)
break
case 'no_delivery':
noDeliveryData.value.splice(index, 1)
break
}
}
//
let selectedArea: number[] = []
//
const disabledArea = ref <Array<string|number>>([])
let currSelect = { type: '', index: 0 }
const selectArea = (type: string, index: number) => {
currSelect = { type, index }
let data: AnyObject[] = []
switch (type) {
case 'fee':
data = feeData.value
break
case 'free_shipping':
data = freeShippingData.value
break
case 'no_delivery':
data = noDeliveryData.value
break
}
selectedArea = data[index].area_ids
disabledArea.value = []
data.forEach((item, $index) => {
if (index != $index) disabledArea.value.push(...item.area_ids)
})
showSelectAreaDialog.value = true
}
const areaTreeData = computed(() => {
areaTree.value.forEach(province => {
province.child.forEach((city:any) => {
city.disabled = disabledArea.value.includes(city.id)
})
})
return areaTree.value
})
const areaTreeRef = ref<InstanceType<typeof ElTree>>()
const confirmSelectArea = () => {
const nodes = areaTreeRef.value!.getCheckedNodes(false, false)
const areaIds: number[] = []
const areaNames: string[] = []
nodes.forEach(item => {
if (item.level == 2) {
areaIds.push(item.id)
areaNames.push(item.name)
}
})
switch (currSelect.type) {
case 'fee':
feeData.value[currSelect.index].area_ids = areaIds
feeData.value[currSelect.index].fee_area_names = areaNames.toString()
break
case 'free_shipping':
freeShippingData.value[currSelect.index].area_ids = areaIds
freeShippingData.value[currSelect.index].free_shipping_area_names = areaNames.toString()
break
case 'no_delivery':
noDeliveryData.value[currSelect.index].area_ids = areaIds
noDeliveryData.value[currSelect.index].no_delivery_area_names = areaNames.toString()
break
}
showSelectAreaDialog.value = false
}
const showSelectOpened = () => {
areaTreeRef.value!.setCheckedKeys(selectedArea, false)
}
/**
* 确认
* @param formEl
*/
const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
const save = formData.template_id ? editShippingTemplate : addShippingTemplate
await formEl.validate(async (valid) => {
if (valid) {
if (formData.is_free_shipping && freeShippingData.value.length == 0) {
ElMessage.error(t('freeShippingPlaceholder'))
return
}
if (formData.no_delivery && noDeliveryData.value.length == 0) {
ElMessage.error('noDeliveryPlaceholder')
return
}
loading.value = true
const data:AnyObject = {
template_id: formData.template_id,
template_name: formData.template_name,
fee_type: formData.fee_type,
no_delivery: formData.no_delivery,
is_free_shipping: formData.is_free_shipping
}
const area: AnyObject = {}
feeData.value.forEach(item => {
item.area_ids.forEach((city: number) => {
area['city_' + city] = { city_id: city, fee_area_ids: item.area_ids.toString(), fee_area_names: item.fee_area_names, snum: item.snum, sprice: item.sprice, xnum: item.xnum, xprice: item.xprice }
})
})
freeShippingData.value.forEach(item => {
item.area_ids.forEach((city: number) => {
if (area['city_' + city]) {
Object.assign(area['city_' + city], { free_shipping_area_ids: item.area_ids.toString(), free_shipping_area_names: item.free_shipping_area_names, free_shipping_num: item.free_shipping_num, free_shipping_price: item.free_shipping_price })
} else {
area['city_' + city] = { city_id: city, free_shipping_area_ids: item.area_ids.toString(), free_shipping_area_names: item.free_shipping_area_names, free_shipping_num: item.free_shipping_num, free_shipping_price: item.free_shipping_price }
}
})
})
noDeliveryData.value.forEach(item => {
item.area_ids.forEach((city: number) => {
if (area['city_' + city]) {
Object.assign(area['city_' + city], { no_delivery_area_ids: item.area_ids.toString(), no_delivery_area_names: item.no_delivery_area_names })
} else {
area['city_' + city] = { city_id: city, no_delivery_area_ids: item.area_ids.toString(), no_delivery_area_names: item.no_delivery_area_names }
}
})
})
data.area = Object.values(area)
save(data).then(() => {
loading.value = false
router.push({ path: '/shop/order/shipping/template' })
}).catch(() => {
loading.value = false
})
}
})
}
const back = () => {
router.push({ path: '/shop/order/shipping/template' })
}
</script>
<style lang="scss" scoped>
:deep(.el-tree-node.is-expanded>.el-tree-node__children) {
display: flex !important;
flex-wrap: wrap;
}
:deep(.area-input .el-input__wrapper) {
box-shadow: none !important;
padding: 0 !important;
background: none;
input {
cursor: pointer;
}
}
</style>

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

Loading…
Cancel
Save