From 903506c6fd45e62418c1e9eb6ce085258eacf615 Mon Sep 17 00:00:00 2001 From: wanghai Date: Fri, 6 Feb 2026 20:38:12 +0800 Subject: [PATCH] 4.3.0 --- README_cn.md | 74 +- app/helpers.php | 2 +- bootstrap/app.php | 1 + bootstrap/route.php | 2 + composer.json | 5 +- config/kujiale.php | 28 + config/langue.php | 2 +- database/migrations/Version20250105120000.php | 38 + database/migrations/Version20250126120000.php | 45 + database/migrations/Version20251110125741.php | 49 + database/migrations/Version20251128125742.php | 180 + database/migrations/Version20251210125745.php | 42 + database/migrations/Version20251212151424.php | 42 + database/migrations/Version20251217100000.php | 56 + database/migrations/Version20251219015611.php | 58 + database/migrations/Version20251224100000.php | 58 + database/migrations/Version20251225120000.php | 38 + database/migrations/Version20251226120000.php | 38 + database/migrations/Version20251226130000.php | 32 + database/migrations/Version20251227120000.php | 38 + database/migrations/Version20251228120000.php | 44 + database/migrations/Version20260126175248.php | 31 + database/migrations/Version20260206194056.php | 69 + dev-setup.sh | 2150 ++++++ docker-compose.dev.yml | 64 + docker-dev/Dockerfile | 83 + docker-dev/docker-entrypoint.sh | 281 + docker-dev/mysql.cnf | 22 + docker-dev/nginx.conf | 197 + docker-dev/php-fpm.conf | 15 + docker-dev/supervisord.conf | 81 + resources/lang/en-CN/payment.php | 8 + resources/lang/zh-CN/payment.php | 8 + routes/api/companys.php | 3 + routes/api/goods.php | 2 + routes/api/kujiale.php | 43 + routes/api/member.php | 16 + routes/api/pagestemplate.php | 31 + routes/api/weapp.php | 13 +- routes/frontapi/distributor.php | 6 + routes/frontapi/goods.php | 2 + routes/frontapi/kujiale.php | 17 + routes/frontapi/pagestemplate.php | 7 + .../Console/InitAdminPasswordCommand.php | 153 + .../Http/Api/V1/Action/Setting.php | 61 + .../MultiLang/MultiLangItem.php | 47 +- .../Repositories/RegionauthRepository.php | 2 +- .../Services/CommonLangModService.php | 27 +- .../Services/EmployeeService.php | 31 +- .../Services/RegionauthService.php | 12 + .../Services/RepositoryInterceptor.php | 3 +- .../Entities/Distributor.php | 31 + .../Http/FrontApi/V1/Action/Distributor.php | 408 +- .../Repositories/DistributorRepository.php | 30 +- .../Services/DistributorItemsService.php | 10 +- .../Services/DistributorService.php | 51 +- .../Services/DistributorWhiteListService.php | 2 +- .../Services/PickupLocationService.php | 138 +- .../Commands/InitMultiLangCommand.php | 11 +- src/EspierBundle/Console/Kernel.php | 4 + .../FrontApi/V1/Action/LoginController.php | 3 +- .../Services/Export/TradeExportService.php | 17 +- src/EspierBundle/Services/LoginService.php | 260 +- .../Api/V1/Action/ItemsCategory.php | 21 +- .../ApiServices/ItemsCategoryService.php | 3 + src/GoodsBundle/Entities/ItemsCategory.php | 33 +- src/GoodsBundle/Entities/ItemsGroup.php | 226 + .../Entities/ItemsGroupRelItem.php | 322 + .../Http/AdminApi/V1/Action/Items.php | 6 +- src/GoodsBundle/Http/Api/V1/Action/Items.php | 20 +- .../Http/Api/V1/Action/ItemsCategory.php | 24 +- .../Api/V1/Action/ItemsGroupController.php | 78 + .../Http/Api/V1/Action/ItemsTags.php | 57 +- .../Http/FrontApi/V1/Action/Category.php | 33 +- .../Http/FrontApi/V1/Action/Items.php | 9 +- .../V1/Action/ItemsGroupController.php | 48 + .../FrontApi/V1/Action/SalespersonItems.php | 2 +- .../Http/FrontApi/V2/Action/Items.php | 9 + .../Repositories/ItemsCategoryRepository.php | 6 +- .../ItemsGroupRelItemRepository.php | 63 + .../Repositories/ItemsGroupRepository.php | 35 + .../Repositories/ItemsRepository.php | 12 +- .../Services/ItemsCategoryService.php | 105 +- .../Services/ItemsGroupRelItemService.php | 119 + .../Services/ItemsGroupService.php | 65 + src/GoodsBundle/Services/ItemsService.php | 77 +- .../MultiLang/MultiLangOutsideItemService.php | 21 +- .../Services/MultiLang/MultiLangService.php | 106 +- .../Services/NormalGoodsUploadService.php | 2 +- src/KaquanBundle/Entities/DiscountCards.php | 62 + src/KaquanBundle/Entities/UserDiscount.php | 32 + .../Http/Api/V1/Action/DiscountCard.php | 35 + .../Http/FrontApi/V1/Action/DiscountCard.php | 54 +- .../Http/FrontApi/V1/Action/UserDiscount.php | 8 +- .../Repositories/DiscountCardsRepository.php | 8 + .../Repositories/UserDiscountRepository.php | 1 + .../Services/DiscountCardService.php | 47 +- .../Services/DiscountNewGiftCardService.php | 18 +- .../Services/UserDiscountService.php | 50 +- .../Commands/UpdateDesignerWorksCommand.php | 42 + .../Entities/KujialeDesignerGoods.php | 469 ++ .../Entities/KujialeDesignerGoodsRel.php | 159 + .../Entities/KujialeDesignerTags.php | 314 + .../Entities/KujialeDesignerWorks.php | 746 +++ .../Entities/KujialeDesignerWorksItemRel.php | 196 + .../Entities/KujialeDesignerWorksLevel.php | 314 + .../Entities/KujialeDesignerWorksLike.php | 202 + .../Entities/KujialeDesignerWorksPic.php | 375 ++ .../KujialeDesignerWorksRelCities.php | 189 + .../Entities/KujialeDesignerWorksRelTags.php | 283 + .../Http/Api/V1/Action/KuController.php | 695 ++ .../Http/FrontApi/V1/Action/KuController.php | 255 + .../Interfaces/KujialeInterface.php | 0 .../KujialeDesignerGoodsRelRepository.php | 276 + .../KujialeDesignerGoodsRepository.php | 276 + .../KujialeDesignerTagsRepository.php | 276 + .../KujialeDesignerWorksItemRelRepository.php | 277 + .../KujialeDesignerWorksLevelRepository.php | 276 + .../KujialeDesignerWorksLikeRepository.php | 277 + .../KujialeDesignerWorksPicRepository.php | 277 + ...ujialeDesignerWorksRelCitiesRepository.php | 302 + .../KujialeDesignerWorksRelTagsRepository.php | 276 + .../KujialeDesignerWorksRepository.php | 299 + .../Services/DesignerWorksScriptService.php | 187 + .../KujialeDesignerGoodsRelService.php | 55 + .../Services/KujialeDesignerGoodsService.php | 82 + .../Services/KujialeDesignerTagsService.php | 115 + .../KujialeDesignerWorksLikeService.php | 66 + .../KujialeDesignerWorksPicService.php | 54 + .../Services/KujialeDesignerWorksService.php | 484 ++ src/KujialeBundle/Services/api/ApiService.php | 266 + .../Traits/AbstractApiTraits.php | 227 + .../Entities/MemberSegmentRule.php | 306 + src/MembersBundle/Entities/MemberTagGroup.php | 262 + .../Entities/MemberTagGroupRel.php | 200 + src/MembersBundle/Entities/MemberTags.php | 31 + src/MembersBundle/Entities/Members.php | 186 + .../Http/Api/V1/Action/ExportData.php | 48 + .../Http/Api/V1/Action/MemberTagAction.php | 445 ++ .../Http/Api/V1/Action/MemberTags.php | 183 +- .../Http/Api/V1/Action/Members.php | 625 +- .../Http/FrontApi/V1/Action/Members.php | 5 +- .../Jobs/PushMemberTagRelationJob.php | 109 + .../MemberSegmentRuleRepository.php | 252 + .../MemberTagGroupRelRepository.php | 162 + .../Repositories/MemberTagGroupRepository.php | 207 + .../Repositories/MemberTagsRepository.php | 15 + .../Repositories/MembersRepository.php | 24 + .../MemberSalespersonNotifyService.php | 189 + .../Services/MemberSegmentRuleService.php | 869 +++ src/MembersBundle/Services/MemberService.php | 382 +- .../Services/MemberTagRelationPushService.php | 235 + .../Services/MemberTagsService.php | 638 +- .../Services/TagLibraryPushService.php | 477 ++ .../Traits/MemberSearchFilter.php | 17 +- .../V1/Action/DiscountCardController.php | 2 + .../Http/ThirdApi/V1/Action/Member.php | 1192 ++++ .../Http/ThirdApi/V1/Action/Wxapp.php | 2 +- src/OpenapiBundle/Traits/OpenapiRoutes.php | 9 +- .../Services/Orders/AbstractNormalOrder.php | 46 +- .../Services/Payments/OfflinePayService.php | 19 +- .../Services/Payments/WechatPayService.php | 43 +- .../PointsmallItemsRepository.php | 65 +- .../Services/ItemsService.php | 39 +- .../Services/RecommendLikeService.php | 4 +- .../Repositories/FormSettingRepository.php | 1 + .../Repositories/SupplierItemsRepository.php | 45 +- src/ThemeBundle/Entities/OpenScreenAd.php | 62 + src/ThemeBundle/Entities/PagesAdPlace.php | 612 ++ .../Entities/PagesAdPlaceRelDistributors.php | 110 + .../Entities/PagesAdPlaceRelMemberTags.php | 110 + src/ThemeBundle/Entities/PagesSideBar.php | 276 + src/ThemeBundle/Entities/PagesTemplate.php | 35 +- src/ThemeBundle/Entities/PagesTemplateSet.php | 31 + .../Http/Api/V1/Action/OpenScreenAd.php | 4 +- .../Http/Api/V1/Action/PagesAdPlace.php | 841 +++ .../Http/Api/V1/Action/PagesSideBar.php | 419 ++ .../Http/Api/V1/Action/PagesTemplate.php | 149 +- .../Http/Api/V1/Action/PagesTemplateSet.php | 2 + .../Http/FrontApi/V1/Action/OpenScreenAd.php | 15 +- .../Http/FrontApi/V1/Action/PagesAdPlace.php | 169 + .../Http/FrontApi/V1/Action/PagesSideBar.php | 89 + .../Http/FrontApi/V1/Action/PagesTemplate.php | 116 +- .../Repositories/OpenScreenAdRepository.php | 4 +- .../PagesAdPlaceRelDistributorsRepository.php | 327 + .../PagesAdPlaceRelMemberTagsRepository.php | 327 + .../Repositories/PagesAdPlaceRepository.php | 329 + .../Repositories/PagesSideBarRepository.php | 343 + .../Repositories/PagesTemplateRepository.php | 5 + .../PagesTemplateSetRepository.php | 5 + .../ThemeMemberCenterShareRepository.php | 2 +- .../ThemePcTemplateContentRepository.php | 2 +- .../ThemePcTemplateRepository.php | 2 +- .../Services/OpenScreenAdServices.php | 15 +- .../Services/PagesAdPlaceService.php | 167 + .../Services/PagesSideBarService.php | 26 + .../Services/PagesTemplateServices.php | 432 +- .../Services/PagesTemplateSetServices.php | 6 +- .../ThemePcTemplateContentServices.php | 4 +- .../Entities/WeappCustomizePage.php | 34 +- .../Http/Api/V1/Action/CustomizePage.php | 149 +- src/WechatBundle/Http/Api/V1/Action/Wxa.php | 28 +- .../Http/Controllers/PaymentNotify.php | 7 +- .../Http/FrontApi/V1/Action/Wxapp.php | 56 +- .../WeappCustomizePageRepository.php | 2 +- .../Repositories/WeappSettingRepository.php | 2 +- .../Repositories/WechatAuthRepository.php | 2 +- .../Services/Wxapp/CustomizePageService.php | 5 +- .../Services/Wxapp/TemplateService.php | 8 +- src/WsugcBundle/Services/PostService.php | 2 +- storage/static/dealer_menu.json | 2 +- storage/static/it_menu.json | 2 +- storage/static/merchant_menu.json | 2 +- storage/static/platform_menu.json | 5843 +---------------- storage/static/shop_menu.json | 2 +- storage/static/supplier_menu.json | 2 +- 216 files changed, 28040 insertions(+), 6204 deletions(-) create mode 100644 config/kujiale.php create mode 100644 database/migrations/Version20250105120000.php create mode 100644 database/migrations/Version20250126120000.php create mode 100644 database/migrations/Version20251128125742.php create mode 100644 database/migrations/Version20251210125745.php create mode 100644 database/migrations/Version20251212151424.php create mode 100644 database/migrations/Version20251217100000.php create mode 100644 database/migrations/Version20251219015611.php create mode 100644 database/migrations/Version20251224100000.php create mode 100644 database/migrations/Version20251225120000.php create mode 100644 database/migrations/Version20251226120000.php create mode 100644 database/migrations/Version20251226130000.php create mode 100644 database/migrations/Version20251227120000.php create mode 100644 database/migrations/Version20251228120000.php create mode 100644 database/migrations/Version20260126175248.php create mode 100644 database/migrations/Version20260206194056.php create mode 100755 dev-setup.sh create mode 100644 docker-compose.dev.yml create mode 100644 docker-dev/Dockerfile create mode 100755 docker-dev/docker-entrypoint.sh create mode 100644 docker-dev/mysql.cnf create mode 100644 docker-dev/nginx.conf create mode 100644 docker-dev/php-fpm.conf create mode 100644 docker-dev/supervisord.conf create mode 100644 routes/api/kujiale.php create mode 100644 routes/frontapi/kujiale.php create mode 100644 src/CompanysBundle/Console/InitAdminPasswordCommand.php create mode 100644 src/GoodsBundle/Entities/ItemsGroup.php create mode 100644 src/GoodsBundle/Entities/ItemsGroupRelItem.php create mode 100644 src/GoodsBundle/Http/Api/V1/Action/ItemsGroupController.php create mode 100644 src/GoodsBundle/Http/FrontApi/V1/Action/ItemsGroupController.php create mode 100644 src/GoodsBundle/Repositories/ItemsGroupRelItemRepository.php create mode 100644 src/GoodsBundle/Repositories/ItemsGroupRepository.php create mode 100644 src/GoodsBundle/Services/ItemsGroupRelItemService.php create mode 100644 src/GoodsBundle/Services/ItemsGroupService.php create mode 100644 src/KujialeBundle/Commands/UpdateDesignerWorksCommand.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerGoods.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerGoodsRel.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerTags.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerWorks.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerWorksItemRel.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerWorksLevel.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerWorksLike.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerWorksPic.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerWorksRelCities.php create mode 100644 src/KujialeBundle/Entities/KujialeDesignerWorksRelTags.php create mode 100644 src/KujialeBundle/Http/Api/V1/Action/KuController.php create mode 100644 src/KujialeBundle/Http/FrontApi/V1/Action/KuController.php create mode 100644 src/KujialeBundle/Interfaces/KujialeInterface.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerGoodsRelRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerGoodsRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerTagsRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerWorksItemRelRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerWorksLevelRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerWorksLikeRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerWorksPicRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerWorksRelCitiesRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerWorksRelTagsRepository.php create mode 100644 src/KujialeBundle/Repositories/KujialeDesignerWorksRepository.php create mode 100644 src/KujialeBundle/Services/DesignerWorksScriptService.php create mode 100644 src/KujialeBundle/Services/KujialeDesignerGoodsRelService.php create mode 100644 src/KujialeBundle/Services/KujialeDesignerGoodsService.php create mode 100644 src/KujialeBundle/Services/KujialeDesignerTagsService.php create mode 100644 src/KujialeBundle/Services/KujialeDesignerWorksLikeService.php create mode 100644 src/KujialeBundle/Services/KujialeDesignerWorksPicService.php create mode 100644 src/KujialeBundle/Services/KujialeDesignerWorksService.php create mode 100644 src/KujialeBundle/Services/api/ApiService.php create mode 100644 src/KujialeBundle/Traits/AbstractApiTraits.php create mode 100644 src/MembersBundle/Entities/MemberSegmentRule.php create mode 100644 src/MembersBundle/Entities/MemberTagGroup.php create mode 100644 src/MembersBundle/Entities/MemberTagGroupRel.php create mode 100644 src/MembersBundle/Http/Api/V1/Action/MemberTagAction.php create mode 100644 src/MembersBundle/Jobs/PushMemberTagRelationJob.php create mode 100644 src/MembersBundle/Repositories/MemberSegmentRuleRepository.php create mode 100644 src/MembersBundle/Repositories/MemberTagGroupRelRepository.php create mode 100644 src/MembersBundle/Repositories/MemberTagGroupRepository.php create mode 100644 src/MembersBundle/Services/MemberSalespersonNotifyService.php create mode 100644 src/MembersBundle/Services/MemberSegmentRuleService.php create mode 100644 src/MembersBundle/Services/MemberTagRelationPushService.php create mode 100644 src/MembersBundle/Services/TagLibraryPushService.php create mode 100644 src/ThemeBundle/Entities/PagesAdPlace.php create mode 100644 src/ThemeBundle/Entities/PagesAdPlaceRelDistributors.php create mode 100644 src/ThemeBundle/Entities/PagesAdPlaceRelMemberTags.php create mode 100644 src/ThemeBundle/Entities/PagesSideBar.php create mode 100644 src/ThemeBundle/Http/Api/V1/Action/PagesAdPlace.php create mode 100644 src/ThemeBundle/Http/Api/V1/Action/PagesSideBar.php create mode 100644 src/ThemeBundle/Http/FrontApi/V1/Action/PagesAdPlace.php create mode 100644 src/ThemeBundle/Http/FrontApi/V1/Action/PagesSideBar.php create mode 100644 src/ThemeBundle/Repositories/PagesAdPlaceRelDistributorsRepository.php create mode 100644 src/ThemeBundle/Repositories/PagesAdPlaceRelMemberTagsRepository.php create mode 100644 src/ThemeBundle/Repositories/PagesAdPlaceRepository.php create mode 100644 src/ThemeBundle/Repositories/PagesSideBarRepository.php create mode 100644 src/ThemeBundle/Services/PagesAdPlaceService.php create mode 100644 src/ThemeBundle/Services/PagesSideBarService.php diff --git a/README_cn.md b/README_cn.md index 4bd52b8..d6f02f9 100644 --- a/README_cn.md +++ b/README_cn.md @@ -38,13 +38,81 @@ ECShopX 是商派基于23年服务全球知名品牌企业的经验沉淀,推 * 开放API:提供丰富的RESTful API,便于与ERP、WMS、CRM等第三方系统集成。 * 模块化设计:核心功能高度模块化,便于二次开发与功能扩展。 -## 系统要求 +## Docker 部署方式(推荐) + +使用自动化部署脚本快速搭建开发环境,包含 PHP、Nginx、MySQL、Redis 等服务。 + +### 前置要求 + +- 软件:Docker 和 Docker Compose(macOS 推荐 Docker Desktop) +- 系统:macOS 或 Linux 系统 + +### 快速开始 +- 克隆项目到本地 +- 进入根目录,运行部署脚本: + +```bash +bash dev-setup.sh +``` +- 依据脚本提示部署系统 + +脚本会自动完成: +1. 检测 Docker 环境 +2. 克隆前端项目(如不存在) +3. 启动 Docker 容器(PHP、Nginx、MySQL、Redis) +4. 配置 PHP 应用(安装依赖、数据库迁移、初始化管理员密码) +5. 编译前端项目(管理后台、H5、PC商城) + +### 脚本选项 + +```bash +bash dev-setup.sh --rebuild # 重新构建镜像 +bash dev-setup.sh --skip-admin # 跳过管理后台编译 +bash dev-setup.sh --skip-vshop # 跳过移动商城编译 +bash dev-setup.sh --skip-pc # 跳过PC商城编译 +``` + +### 访问地址 + +- **管理后台**: http://localhost:8080 +- **H5前端**: http://localhost:8081 +- **PC前端**: http://localhost:8082 +- **API接口**: http://localhost:8080/api/ + +### 常用命令 + +```bash +# 查看日志 +docker-compose -f docker-compose.dev.yml logs -f + +# 查看服务状态 +docker exec ecshopx-dev supervisorctl status + +# 进入容器 +docker exec -it ecshopx-dev sh + +# 停止服务 +docker-compose -f docker-compose.dev.yml down + +# 重启服务 +docker-compose -f docker-compose.dev.yml restart +``` + +### 注意事项 + +- 首次部署需要 10-30 分钟(下载镜像、安装依赖、编译前端) +- 前端项目会克隆到与当前项目同级的目录 +- 脚本运行时会提示设置管理员密码 +- 确保端口 8080、8081、8082、3306、6379 未被占用 + +## 自行部署 + +### 系统要求 - php >= 7.4 - lumen = 8.3 - mysql >= 5.7 - redis >= 4.0 - -## 安装指南 + ### 配置 .env 文件 * Update database settings * Update Redis settings diff --git a/app/helpers.php b/app/helpers.php index 727578a..7eab49d 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -29,7 +29,7 @@ if (!function_exists('config_path')) { */ function config_path($path = '') { - return true; + return app()->basePath('config/' . $path); } } diff --git a/bootstrap/app.php b/bootstrap/app.php index 12c4c66..cbe2c08 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -91,6 +91,7 @@ $app->configure('oms'); $app->configure('shopexai'); $app->configure('tbitems'); $app->configure('paypal'); +$app->configure('kujiale'); $app->configure('langue'); /* diff --git a/bootstrap/route.php b/bootstrap/route.php index be75ddc..3d4e1b6 100644 --- a/bootstrap/route.php +++ b/bootstrap/route.php @@ -94,6 +94,7 @@ if ($lumenRoutingKeyOne == 'wechatAuth') { require __DIR__.'/../routes/frontapi/community.php'; require __DIR__.'/../routes/frontapi/employeepurchase.php'; require __DIR__.'/../routes/frontapi/ugc.php'; + require __DIR__.'/../routes/frontapi/kujiale.php'; } break; case ($dingoRoutingKeyOne == 'wxapp' || $dingoRoutingKeyOne == 'wxa') : @@ -145,6 +146,7 @@ if ($lumenRoutingKeyOne == 'wechatAuth') { require __DIR__.'/../routes/api/bspay.php'; require __DIR__.'/../routes/api/employeepurchase.php'; require __DIR__.'/../routes/api/ugc.php'; + require __DIR__.'/../routes/api/kujiale.php'; } } diff --git a/composer.json b/composer.json index 0daf405..263818e 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "laravel/lumen", - "version": "4.2.2", + "version": "4.3.0", "description": "The Laravel Lumen Framework.", "keywords": ["framework", "laravel", "lumen"], "license": "MIT", @@ -46,7 +46,8 @@ "yurunsoft/yurun-oauth-login": "^3.0", "freyo/flysystem-qcloud-cos-v5":"^2.0", "elasticsearch/elasticsearch": "^8.0", - "swiftmailer/swiftmailer": "^6.0" + "swiftmailer/swiftmailer": "^6.0", + "overtrue/pinyin": "^4.1" }, "require-dev": { "brainmaestro/composer-git-hooks": "^2.8", diff --git a/config/kujiale.php b/config/kujiale.php new file mode 100644 index 0000000..0402b65 --- /dev/null +++ b/config/kujiale.php @@ -0,0 +1,28 @@ + env('KUJIALE_APPKEY',''), + 'appSecret' => env('KUJIALE_APPSECRET',''), + 'appUid' => env('KUJIALE_APPUID',''), + 'apiUrl' => [ + 'cat' => 'https://openapi.kujiale.com/v2/commodity/cat', //获取商品类目 + 'tag' => 'https://openapi.kujiale.com/v2/commodity/tag', //获取商品标签 + 'search' => 'https://openapi.kujiale.com/v2/commodity/search', //搜索商品 + 'brand' => 'https://openapi.kujiale.com/v2/commodity/brand', //搜索商品 + 'search' => 'https://openapi.kujiale.com/v2/commodity/search', //搜索商品 + 'detail' => 'https://openapi.kujiale.com/v2/commodity/detail', //商品详情 + 'designer_works' => 'https://openapi.kujiale.com/v2/designeroc/design/excellent/list', //设计师方案作品 + 'designer_works_detail' => 'https://openapi.kujiale.com/v2/design/{designId}/basic/v2', //设计师方案作品详情 + 'designer_works_tag' => 'https://openapi.kujiale.com/v2/design/new-tag', //设计师方案作品标签 + 'designer_tags_list' => 'https://openapi.kujiale.com/v2/design/new-tag/category/list', //方案标签 + 'designer_works_pic' => 'https://openapi.kujiale.com/v2/renderpic/list', //方案全景图 + 'designer_room_brand_goods' => 'https://openapi.kujiale.com/v2/panopic/{picId}/currentroom/brandgoods', //方案全景图 + + 'access_token' => 'https://openapi.kujiale.com/v2/sso/token', //获取一次性access_token + 'register_user' => 'https://openapi.kujiale.com/v2/register', //绑定设计圈账号,通过邮箱 + 'search_account' => 'https://openapi.kujiale.com/v2/account/search', //查找设计师账号 + ], + + 'webViewUrl' => $wap_base.'/pages/commodity/scene-detail' //web-view url +]; \ No newline at end of file diff --git a/config/langue.php b/config/langue.php index 6ac2ded..5c1cda6 100644 --- a/config/langue.php +++ b/config/langue.php @@ -4,5 +4,5 @@ * 此处与多语言关联 */ return [ - 'zh-CN','en-CN','ar-SA' + 'zh-CN', 'en-CN', 'ar-SA' ]; diff --git a/database/migrations/Version20250105120000.php b/database/migrations/Version20250105120000.php new file mode 100644 index 0000000..8d27700 --- /dev/null +++ b/database/migrations/Version20250105120000.php @@ -0,0 +1,38 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE kaquan_user_discount ADD salesperson_code VARCHAR(100) DEFAULT NULL COMMENT \'导购编号(employee_number/work_userid)\' AFTER salesperson_id'); + $this->addSql('CREATE INDEX idx_salesperson_code ON kaquan_user_discount (salesperson_code)'); + } + + public function down(Schema $schema) : void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP INDEX idx_salesperson_code ON kaquan_user_discount'); + $this->addSql('ALTER TABLE kaquan_user_discount DROP salesperson_code'); + } +} + diff --git a/database/migrations/Version20250126120000.php b/database/migrations/Version20250126120000.php new file mode 100644 index 0000000..408c55f --- /dev/null +++ b/database/migrations/Version20250126120000.php @@ -0,0 +1,45 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Add fp_salesperson field (分配的导购ID) + $this->addSql('ALTER TABLE members ADD fp_salesperson INT DEFAULT 0 COMMENT \'分配的导购ID\''); + + // Add has_fp field (是否有分配导购) + $this->addSql('ALTER TABLE members ADD has_fp TINYINT(1) DEFAULT 0 COMMENT \'是否有分配导购。0:否;1:是\''); + + // Add index for better query performance + $this->addSql('CREATE INDEX idx_fp_salesperson ON members (fp_salesperson)'); + $this->addSql('CREATE INDEX idx_has_fp ON members (has_fp)'); + } + + public function down(Schema $schema) : void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Drop indexes + $this->addSql('DROP INDEX idx_fp_salesperson ON members'); + $this->addSql('DROP INDEX idx_has_fp ON members'); + + // Drop columns + $this->addSql('ALTER TABLE members DROP fp_salesperson'); + $this->addSql('ALTER TABLE members DROP has_fp'); + } +} + diff --git a/database/migrations/Version20251110125741.php b/database/migrations/Version20251110125741.php index fccd0df..2651c9b 100644 --- a/database/migrations/Version20251110125741.php +++ b/database/migrations/Version20251110125741.php @@ -39,6 +39,7 @@ class Version20251110125741 extends AbstractMigration ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多语言字典库' "); } + // 创建 item_multi_lang_mod_lang_zhCN 表 $tableExists = $conn->fetchOne( "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'item_multi_lang_mod_lang_zhCN'" @@ -63,6 +64,30 @@ class Version20251110125741 extends AbstractMigration "); } + // 创建 item_multi_lang_mod_lang_arSA 表 + $tableExists = $conn->fetchOne( + "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'item_multi_lang_mod_lang_arSA'" + ); + + if (!$tableExists) { + $conn->executeStatement(" + CREATE TABLE `item_multi_lang_mod_lang_arSA` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `company_id` bigint(20) NOT NULL COMMENT '公司id', + `data_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '业务id字段', + `table_name` varchar(255) NOT NULL DEFAULT '' COMMENT '表名', + `field` varchar(255) NOT NULL DEFAULT '' COMMENT 'field,多语言对应字段', + `module_name` varchar(255) NOT NULL DEFAULT '' COMMENT 'module_name,模块名', + `lang` varchar(255) NOT NULL DEFAULT '' COMMENT '语言', + `attribute_value` text NOT NULL COMMENT '多语言值', + `created` int(11) NOT NULL, + `updated` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `ix_company_id` (`company_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多语言字典库' + "); + } + // outside_item_multi_lang_mod_lang_enCN $tableExists = $conn->fetchOne( "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'outside_item_multi_lang_mod_lang_enCN'" @@ -111,6 +136,30 @@ class Version20251110125741 extends AbstractMigration "); } + //outside_item_multi_lang_mod_lang_arSA + $tableExists = $conn->fetchOne( + "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'outside_item_multi_lang_mod_lang_arSA'" + ); + + if (!$tableExists) { + $conn->executeStatement(" + CREATE TABLE `outside_item_multi_lang_mod_lang_arSA` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `company_id` bigint(20) NOT NULL COMMENT '公司id', + `data_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '业务id字段', + `table_name` varchar(255) NOT NULL DEFAULT '' COMMENT '表名', + `field` varchar(255) NOT NULL DEFAULT '' COMMENT 'field,多语言对应字段', + `module_name` varchar(255) NOT NULL DEFAULT '' COMMENT 'module_name,模块名', + `lang` varchar(255) NOT NULL DEFAULT '' COMMENT '语言', + `attribute_value` text NOT NULL COMMENT '多语言值', + `created` int(11) NOT NULL, + `updated` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `ix_company_id` (`company_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多语言字典库' + "); + } + // multi_lang_mod基表 $tableExists = $conn->fetchOne( "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'multi_lang_mod'" diff --git a/database/migrations/Version20251128125742.php b/database/migrations/Version20251128125742.php new file mode 100644 index 0000000..5e32b6d --- /dev/null +++ b/database/migrations/Version20251128125742.php @@ -0,0 +1,180 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql(" + CREATE TABLE `kujiale_designer_goods` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `good_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渲染图ID', + `dimensions` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '尺寸', + `description` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '描述', + `brand_good_code` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品编码', + `brand_good_name` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品名称', + `brand_id` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '品牌id', + `brand_name` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '品牌名称', + `series_tag_id` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '系列id', + `series_tag_name` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '系列名称', + `product_number` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '型号', + `customer_texture` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '材质', + `buy_link` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '购买链接', + `created` int(11) NOT NULL COMMENT '创建时间', + `updated` int(11) DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_good_id` (`good_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "); + $this->addSql(" + CREATE TABLE `kujiale_designer_goods_rel` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `pic_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渲染图ID', + `obs_brand_good_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品ID', + `created` int(11) NOT NULL COMMENT '创建时间', + `updated` int(11) DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_brand_good_id` (`obs_brand_good_id`), + KEY `idx_pic_id` (`pic_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "); + $this->addSql(" + CREATE TABLE `kujiale_designer_tags` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `tag_category_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '标签类目id', + `tag_category_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标签类目名', + `type` int(11) DEFAULT NULL COMMENT '类型', + `is_multiple_selected` int(11) DEFAULT NULL COMMENT '是否支持多选', + `is_disabled` int(11) DEFAULT NULL COMMENT '是否禁用', + `tag_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标签id', + `tag_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标签名称', + `created` int(11) NOT NULL COMMENT '创建时间', + `updated` int(11) DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_category_id` (`tag_category_id`), + KEY `idx_tag_id` (`tag_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "); + + $this->addSql(" + CREATE TABLE `kujiale_designer_works` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `design_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '方案名称', + `cover_pic` text COLLATE utf8mb4_unicode_ci COMMENT '方案封面', + `is_origin` bigint(20) DEFAULT NULL COMMENT '是否原创', + `is_excellent` bigint(20) DEFAULT NULL COMMENT '是否优秀', + `is_real_excellent` bigint(20) DEFAULT NULL COMMENT '是否优秀', + `is_top` bigint(20) DEFAULT NULL COMMENT '是否置顶', + `design_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '方案ID', + `plan_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型ID', + `comm_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '小区', + `city` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '城市', + `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型名称', + `tag_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '方案分类id', + `design_pano_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '全景漫游url', + `user_avatar` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户头像', + `email` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '邮箱', + `user_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名', + `user_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户id', + `organization_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '组织id', + `created` int(11) NOT NULL COMMENT '创建时间', + `updated` int(11) DEFAULT NULL COMMENT '更新时间', + `view_count` int(11) DEFAULT NULL COMMENT '浏览量', + `like_count` int(11) DEFAULT NULL COMMENT '点赞数', + `ku_created` int(11) DEFAULT NULL COMMENT '方案更新时间', + PRIMARY KEY (`id`), + KEY `idx_design_id` (`design_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_plan_id` (`plan_id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "); + $this->addSql(" + CREATE TABLE `kujiale_designer_works_level` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `design_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '方案id', + `plan_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型ID', + `spec_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型的房型', + `src_area` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型的建筑面积', + `area` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型的套内建筑面积', + `real_area` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型的套内面积', + `plan_pic` text COLLATE utf8mb4_unicode_ci COMMENT '户型图的URL', + `created` int(11) NOT NULL COMMENT '创建时间', + `updated` int(11) DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_design_id` (`design_id`), + KEY `idx_plan_id` (`plan_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "); + + $this->addSql(" + CREATE TABLE `kujiale_designer_works_like` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `design_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '方案id', + `plan_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型ID', + `user_id` int(11) DEFAULT NULL COMMENT '点赞用户id', + `created` int(11) NOT NULL COMMENT '创建时间', + `updated` int(11) DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_design_id` (`design_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_plan_id` (`plan_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "); + $this->addSql(" + CREATE TABLE `kujiale_designer_works_pic` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `pic_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渲染图ID', + `pic_type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渲染图类型。0表示普通渲染图,1表示全景图,3表示俯视图', + `pic_detail_type` bigint(20) DEFAULT NULL COMMENT '渲染图类型细分', + `room_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渲染图所属房间的名字', + `img` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渲染图URL', + `pano_link` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '全景图的链接地址', + `design_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '方案ID', + `plan_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型ID', + `level` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渲染图所在房间的楼层信息,正为地上,负为地下室,不存在0层', + `created` int(11) NOT NULL COMMENT '创建时间', + `updated` int(11) DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_design_id` (`design_id`), + KEY `idx_plan_id` (`plan_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "); + + $this->addSql(" + CREATE TABLE `kujiale_designer_works_rel_tags` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `tag_category_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '标签类目id', + `tag_category_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标签类目名', + `tag_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标签id', + `tag_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标签名称', + `design_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '方案id', + `plan_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '户型ID', + `created` int(11) NOT NULL COMMENT '创建时间', + `updated` int(11) DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_design_id` (`design_id`), + KEY `idx_category_id` (`tag_category_id`), + KEY `idx_plan_id` (`plan_id`), + KEY `idx_tag_id` (`tag_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + } +} diff --git a/database/migrations/Version20251210125745.php b/database/migrations/Version20251210125745.php new file mode 100644 index 0000000..97117ce --- /dev/null +++ b/database/migrations/Version20251210125745.php @@ -0,0 +1,42 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // 创建设计师作品城市关联表 + $this->addSql('CREATE TABLE kujiale_designer_works_rel_cities ( + id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'自增ID\', + design_id VARCHAR(255) NOT NULL COMMENT \'方案ID\', + plan_id VARCHAR(255) DEFAULT NULL COMMENT \'户型ID\', + city_id INT NOT NULL COMMENT \'城市ID\', + created INT NOT NULL COMMENT \'创建时间\', + updated INT DEFAULT NULL COMMENT \'更新时间\', + INDEX idx_design_id (design_id), + INDEX idx_plan_id (plan_id), + INDEX idx_city_id (city_id), + PRIMARY KEY(id) + ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'设计师作品城市关联表\''); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE IF EXISTS kujiale_designer_works_rel_cities'); + } +} + diff --git a/database/migrations/Version20251212151424.php b/database/migrations/Version20251212151424.php new file mode 100644 index 0000000..1e76e12 --- /dev/null +++ b/database/migrations/Version20251212151424.php @@ -0,0 +1,42 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // 创建设计师作品与商品绑定关系表 + $this->addSql('CREATE TABLE kujiale_designer_works_item_rel ( + id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', + item_id BIGINT NOT NULL COMMENT \'商品ID\', + design_id VARCHAR(255) NOT NULL COMMENT \'设计ID\', + goods_bn VARCHAR(255) DEFAULT NULL COMMENT \'SPU货号\', + created INT NOT NULL COMMENT \'创建时间\', + updated INT DEFAULT NULL COMMENT \'更新时间\', + INDEX idx_item_id (item_id), + INDEX idx_design_id (design_id), + INDEX idx_goods_bn (goods_bn), + UNIQUE KEY uk_design_id (design_id), + PRIMARY KEY(id) + ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'设计师作品与商品绑定关系表\''); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE IF EXISTS kujiale_designer_works_item_rel'); + } +} diff --git a/database/migrations/Version20251217100000.php b/database/migrations/Version20251217100000.php new file mode 100644 index 0000000..9c237e8 --- /dev/null +++ b/database/migrations/Version20251217100000.php @@ -0,0 +1,56 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // 会员标签组 + $this->addSql("CREATE TABLE members_tag_groups ( + group_id BIGINT AUTO_INCREMENT NOT NULL COMMENT '标签组ID', + company_id BIGINT NOT NULL COMMENT '公司id', + group_name VARCHAR(100) NOT NULL COMMENT '标签组名称', + description VARCHAR(255) DEFAULT NULL COMMENT '描述', + distributor_id BIGINT UNSIGNED DEFAULT 0 NOT NULL COMMENT '分销商id', + created BIGINT NOT NULL, + updated BIGINT NOT NULL, + INDEX idx_company_id (company_id), + INDEX idx_distributor_id (distributor_id), + PRIMARY KEY(group_id) + ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = '会员标签组'"); + + // 标签组与标签关联 + $this->addSql("CREATE TABLE members_tag_group_rel ( + id BIGINT AUTO_INCREMENT NOT NULL COMMENT '主键ID', + group_id BIGINT NOT NULL COMMENT '标签组ID', + tag_id BIGINT NOT NULL COMMENT '标签ID', + company_id BIGINT NOT NULL COMMENT '公司ID', + distributor_id BIGINT UNSIGNED DEFAULT 0 NOT NULL COMMENT '分销商id', + created BIGINT NOT NULL, + INDEX idx_group_id (group_id), + INDEX idx_tag_id (tag_id), + INDEX idx_company_distributor (company_id, distributor_id), + PRIMARY KEY(id) + ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = '会员标签组与标签关系表'"); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE IF EXISTS members_tag_group_rel'); + $this->addSql('DROP TABLE IF EXISTS members_tag_groups'); + } +} diff --git a/database/migrations/Version20251219015611.php b/database/migrations/Version20251219015611.php new file mode 100644 index 0000000..08de2e1 --- /dev/null +++ b/database/migrations/Version20251219015611.php @@ -0,0 +1,58 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $conn = $this->connection; + + // 创建 member_segment_rules 表 + $tableExists = $conn->fetchOne( + "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'member_segment_rules'" + ); + + if (!$tableExists) { + $conn->executeStatement(" + CREATE TABLE `member_segment_rules` ( + `rule_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '规则id', + `company_id` bigint(20) NOT NULL COMMENT '公司id', + `distributor_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '分销商id', + `rule_name` varchar(100) NOT NULL COMMENT '规则名称(分群标签名称)', + `description` text COMMENT '人群说明', + `rule_config` text NOT NULL COMMENT '规则配置(层级结构,JSON格式存储)', + `tag_ids` text COMMENT '关联的标签ID数组(JSON格式)', + `status` smallint(6) NOT NULL DEFAULT '1' COMMENT '状态:0=禁用,1=启用', + `created` bigint(20) NOT NULL COMMENT '创建时间(时间戳)', + `updated` bigint(20) DEFAULT NULL COMMENT '更新时间(时间戳)', + PRIMARY KEY (`rule_id`), + KEY `idx_company_distributor` (`company_id`, `distributor_id`), + KEY `idx_status` (`status`), + KEY `idx_created` (`created`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='人群规则表' + "); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $conn = $this->connection; + + // 删除表 + $conn->executeStatement("DROP TABLE IF EXISTS `member_segment_rules`"); + } +} diff --git a/database/migrations/Version20251224100000.php b/database/migrations/Version20251224100000.php new file mode 100644 index 0000000..7cfd3c5 --- /dev/null +++ b/database/migrations/Version20251224100000.php @@ -0,0 +1,58 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $conn = $this->connection; + + // 为 member_tag_groups 表添加 wechat_group_id 字段 + $conn->executeStatement(" + ALTER TABLE `members_tag_groups` + ADD COLUMN `wechat_group_id` VARCHAR(100) NULL COMMENT '企业微信标签组ID' AFTER `distributor_id`, + ADD INDEX `idx_wechat_group_id` (`wechat_group_id`) + "); + + // 为 members_tags 表添加 wechat_tag_id 字段 + $conn->executeStatement(" + ALTER TABLE `members_tags` + ADD COLUMN `wechat_tag_id` VARCHAR(100) NULL COMMENT '企业微信标签ID' AFTER `source`, + ADD INDEX `idx_wechat_tag_id` (`wechat_tag_id`) + "); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $conn = $this->connection; + + // 删除 member_tag_groups 表的 wechat_group_id 字段 + $conn->executeStatement(" + ALTER TABLE `member_tag_groups` + DROP INDEX `idx_wechat_group_id`, + DROP COLUMN `wechat_group_id` + "); + + // 删除 members_tags 表的 wechat_tag_id 字段 + $conn->executeStatement(" + ALTER TABLE `members_tags` + DROP INDEX `idx_wechat_tag_id`, + DROP COLUMN `wechat_tag_id` + "); + } +} + diff --git a/database/migrations/Version20251225120000.php b/database/migrations/Version20251225120000.php new file mode 100644 index 0000000..c30ad44 --- /dev/null +++ b/database/migrations/Version20251225120000.php @@ -0,0 +1,38 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Add reg_distributor and reg_salesperson to members table + $this->addSql('ALTER TABLE members ADD reg_distributor INT DEFAULT 0 COMMENT \'注册时的分销商ID\''); + $this->addSql('ALTER TABLE members ADD reg_salesperson VARCHAR(100) DEFAULT NULL COMMENT \'注册时的导购ID\''); + + // Add indexes for better query performance + $this->addSql('CREATE INDEX idx_reg_distributor ON members (reg_distributor)'); + $this->addSql('CREATE INDEX idx_reg_salesperson ON members (reg_salesperson)'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP INDEX idx_reg_distributor ON members'); + $this->addSql('DROP INDEX idx_reg_salesperson ON members'); + $this->addSql('ALTER TABLE members DROP reg_distributor'); + $this->addSql('ALTER TABLE members DROP reg_salesperson'); + } +} + diff --git a/database/migrations/Version20251226120000.php b/database/migrations/Version20251226120000.php new file mode 100644 index 0000000..c11666b --- /dev/null +++ b/database/migrations/Version20251226120000.php @@ -0,0 +1,38 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Add is_become_friend field (是否已加为好友) + $this->addSql('ALTER TABLE members ADD is_become_friend TINYINT(1) DEFAULT 0 COMMENT \'是否已加为好友。0:否;1:是\''); + + // Add index for better query performance + $this->addSql('CREATE INDEX idx_is_become_friend ON members (is_become_friend)'); + } + + public function down(Schema $schema) : void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Drop index + $this->addSql('DROP INDEX idx_is_become_friend ON members'); + + // Drop column + $this->addSql('ALTER TABLE members DROP is_become_friend'); + } +} + diff --git a/database/migrations/Version20251226130000.php b/database/migrations/Version20251226130000.php new file mode 100644 index 0000000..255fe1d --- /dev/null +++ b/database/migrations/Version20251226130000.php @@ -0,0 +1,32 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE kaquan_discount_cards ADD coupon_type VARCHAR(10) DEFAULT \'mall\' NOT NULL COMMENT \'券类型。mall:商城券;guide:导购专属券\''); + $this->addSql('ALTER TABLE kaquan_discount_cards ADD guide_issue_quantity INT DEFAULT 0 NOT NULL COMMENT \'导购发放数量\''); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE kaquan_discount_cards DROP coupon_type'); + $this->addSql('ALTER TABLE kaquan_discount_cards DROP guide_issue_quantity'); + } +} + diff --git a/database/migrations/Version20251227120000.php b/database/migrations/Version20251227120000.php new file mode 100644 index 0000000..c985ee8 --- /dev/null +++ b/database/migrations/Version20251227120000.php @@ -0,0 +1,38 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Add op_distributor field (作为分配的店铺ID) + $this->addSql('ALTER TABLE members ADD op_distributor INT DEFAULT 0 COMMENT \'作为分配的店铺ID\''); + + // Add index for better query performance + $this->addSql('CREATE INDEX idx_op_distributor ON members (op_distributor)'); + } + + public function down(Schema $schema) : void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Drop index + $this->addSql('DROP INDEX idx_op_distributor ON members'); + + // Drop column + $this->addSql('ALTER TABLE members DROP op_distributor'); + } +} + diff --git a/database/migrations/Version20251228120000.php b/database/migrations/Version20251228120000.php new file mode 100644 index 0000000..5eece2f --- /dev/null +++ b/database/migrations/Version20251228120000.php @@ -0,0 +1,44 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Drop index first + $this->addSql('DROP INDEX idx_fp_salesperson ON members'); + + // Change fp_salesperson field type from INT to VARCHAR(100) + $this->addSql('ALTER TABLE members MODIFY fp_salesperson VARCHAR(100) DEFAULT NULL COMMENT \'分配的导购员工编号(employee_number/work_userid)\''); + + // Recreate index for better query performance + $this->addSql('CREATE INDEX idx_fp_salesperson ON members (fp_salesperson)'); + } + + public function down(Schema $schema) : void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // Drop index + $this->addSql('DROP INDEX idx_fp_salesperson ON members'); + + // Change fp_salesperson field type back from VARCHAR to INT + $this->addSql('ALTER TABLE members MODIFY fp_salesperson INT DEFAULT 0 COMMENT \'分配的导购ID\''); + + // Recreate index + $this->addSql('CREATE INDEX idx_fp_salesperson ON members (fp_salesperson)'); + } +} + diff --git a/database/migrations/Version20260126175248.php b/database/migrations/Version20260126175248.php new file mode 100644 index 0000000..a4ead3b --- /dev/null +++ b/database/migrations/Version20260126175248.php @@ -0,0 +1,31 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // 删除 kujiale_designer_works_item_rel 表的唯一索引 uk_design_id + $this->addSql('ALTER TABLE kujiale_designer_works_item_rel DROP INDEX uk_design_id'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + // 恢复唯一索引 uk_design_id + $this->addSql('ALTER TABLE kujiale_designer_works_item_rel ADD UNIQUE KEY uk_design_id (design_id)'); + } +} diff --git a/database/migrations/Version20260206194056.php b/database/migrations/Version20260206194056.php new file mode 100644 index 0000000..26fbb4f --- /dev/null +++ b/database/migrations/Version20260206194056.php @@ -0,0 +1,69 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE items_group (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'ID\', company_id BIGINT DEFAULT 0 NOT NULL COMMENT \'公司ID\', regionauth_id BIGINT DEFAULT 0 NOT NULL COMMENT \'地区ID\', group_key VARCHAR(50) DEFAULT \'\' NOT NULL COMMENT \'分组唯一码\', remark VARCHAR(100) DEFAULT \'\' NOT NULL COMMENT \'备注\', created INT NOT NULL, updated INT DEFAULT NULL, INDEX idx_group_key (group_key), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'商品分组\' '); + $this->addSql('CREATE TABLE items_group_rel_item (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'ID\', company_id BIGINT DEFAULT 0 NOT NULL COMMENT \'公司ID\', regionauth_id BIGINT DEFAULT 0 NOT NULL COMMENT \'地区ID\', group_id BIGINT DEFAULT 0 NOT NULL COMMENT \'分组ID\', group_type VARCHAR(50) DEFAULT \'\' NOT NULL COMMENT \'分组类型(coupon, widget, marketing)\', item_id BIGINT DEFAULT 0 NOT NULL COMMENT \'sku-id\', goods_id BIGINT DEFAULT 0 NOT NULL COMMENT \'spu-id\', is_del BIGINT DEFAULT 0 NOT NULL COMMENT \'是否删除\', created INT NOT NULL, updated INT DEFAULT NULL, INDEX idx_goods_id (goods_id), INDEX idx_group_id (group_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'商品分组关联商品\' '); + $this->addSql('CREATE TABLE kujiale_designer_goods (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', good_id VARCHAR(128) NOT NULL COMMENT \'渲染图ID\', dimensions VARCHAR(32) NOT NULL COMMENT \'尺寸\', description VARCHAR(255) NOT NULL COMMENT \'描述\', brand_good_code VARCHAR(128) NOT NULL COMMENT \'商品编码\', brand_good_name VARCHAR(128) NOT NULL COMMENT \'商品名称\', brand_id VARCHAR(32) NOT NULL COMMENT \'品牌id\', brand_name VARCHAR(128) NOT NULL COMMENT \'品牌名称\', series_tag_id VARCHAR(32) NOT NULL COMMENT \'系列id\', series_tag_name VARCHAR(128) NOT NULL COMMENT \'系列名称\', product_number VARCHAR(32) NOT NULL COMMENT \'型号\', customer_texture VARCHAR(64) NOT NULL COMMENT \'材质\', buy_link VARCHAR(255) NOT NULL COMMENT \'购买链接\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_good_id (good_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE kujiale_designer_goods_rel (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', pic_id VARCHAR(255) NOT NULL COMMENT \'渲染图ID\', obs_brand_good_id VARCHAR(128) NOT NULL COMMENT \'商品ID\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_brand_good_id (obs_brand_good_id), INDEX idx_pic_id (pic_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE kujiale_designer_tags (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', tag_category_id VARCHAR(255) NOT NULL COMMENT \'标签类目id\', tag_category_name VARCHAR(255) DEFAULT NULL COMMENT \'标签类目名\', type INT DEFAULT NULL COMMENT \'类型\', is_multiple_selected INT DEFAULT NULL COMMENT \'是否支持多选\', is_disabled INT DEFAULT NULL COMMENT \'是否禁用\', tag_id VARCHAR(255) DEFAULT NULL COMMENT \'标签id\', tag_name VARCHAR(255) DEFAULT NULL COMMENT \'标签名称\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_category_id (tag_category_id), INDEX idx_tag_id (tag_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE kujiale_designer_works (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', design_name VARCHAR(255) NOT NULL COMMENT \'方案名称\', cover_pic TEXT DEFAULT NULL COMMENT \'方案封面\', is_origin BIGINT DEFAULT NULL COMMENT \'是否原创\', is_excellent BIGINT DEFAULT NULL COMMENT \'是否优秀\', is_real_excellent BIGINT DEFAULT NULL COMMENT \'是否优秀\', is_top BIGINT DEFAULT NULL COMMENT \'是否置顶\', design_id VARCHAR(255) DEFAULT NULL COMMENT \'方案ID\', plan_id VARCHAR(255) DEFAULT NULL COMMENT \'户型ID\', comm_name VARCHAR(255) DEFAULT NULL COMMENT \'小区\', city VARCHAR(255) DEFAULT NULL COMMENT \'城市\', name VARCHAR(255) DEFAULT NULL COMMENT \'户型名称\', tag_id VARCHAR(255) DEFAULT NULL COMMENT \'方案分类id\', design_pano_url VARCHAR(255) DEFAULT NULL COMMENT \'全景漫游url\', user_avatar VARCHAR(255) DEFAULT NULL COMMENT \'用户头像\', email VARCHAR(255) DEFAULT NULL COMMENT \'邮箱\', user_name VARCHAR(255) DEFAULT NULL COMMENT \'用户名\', user_id VARCHAR(255) DEFAULT NULL COMMENT \'用户id\', organization_id VARCHAR(255) DEFAULT NULL COMMENT \'组织id\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', view_count INT DEFAULT NULL COMMENT \'浏览量\', like_count INT DEFAULT NULL COMMENT \'点赞数\', ku_created INT DEFAULT NULL COMMENT \'方案更新时间\', INDEX idx_design_id (design_id), INDEX idx_user_id (user_id), INDEX idx_plan_id (plan_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE kujiale_designer_works_item_rel (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', item_id BIGINT NOT NULL COMMENT \'商品ID\', design_id VARCHAR(255) NOT NULL COMMENT \'设计ID\', goods_bn VARCHAR(255) DEFAULT NULL COMMENT \'SPU货号\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_item_id (item_id), INDEX idx_design_id (design_id), INDEX idx_goods_bn (goods_bn), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'设计师作品与商品绑定关系表\' '); + $this->addSql('CREATE TABLE kujiale_designer_works_level (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', design_id VARCHAR(255) NOT NULL COMMENT \'方案id\', plan_id VARCHAR(255) DEFAULT NULL COMMENT \'户型ID\', spec_name VARCHAR(255) DEFAULT NULL COMMENT \'户型的房型\', src_area VARCHAR(255) DEFAULT NULL COMMENT \'户型的建筑面积\', area VARCHAR(255) DEFAULT NULL COMMENT \'户型的套内建筑面积\', real_area VARCHAR(255) DEFAULT NULL COMMENT \'户型的套内面积\', plan_pic TEXT DEFAULT NULL COMMENT \'户型图的URL\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_design_id (design_id), INDEX idx_plan_id (plan_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE kujiale_designer_works_like (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', design_id VARCHAR(255) NOT NULL COMMENT \'方案id\', plan_id VARCHAR(255) DEFAULT NULL COMMENT \'户型ID\', user_id INT DEFAULT NULL COMMENT \'点赞用户id\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_design_id (design_id), INDEX idx_user_id (user_id), INDEX idx_plan_id (plan_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE kujiale_designer_works_pic (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', pic_id VARCHAR(255) NOT NULL COMMENT \'渲染图ID\', pic_type VARCHAR(255) DEFAULT NULL COMMENT \'渲染图类型。0表示普通渲染图,1表示全景图,3表示俯视图\', pic_detail_type BIGINT DEFAULT NULL COMMENT \'渲染图类型细分\', room_name VARCHAR(255) DEFAULT NULL COMMENT \'渲染图所属房间的名字\', img VARCHAR(255) DEFAULT NULL COMMENT \'渲染图URL\', pano_link VARCHAR(255) DEFAULT NULL COMMENT \'全景图的链接地址\', design_id VARCHAR(255) DEFAULT NULL COMMENT \'方案ID\', plan_id VARCHAR(255) DEFAULT NULL COMMENT \'户型ID\', level VARCHAR(255) DEFAULT NULL COMMENT \'渲染图所在房间的楼层信息,正为地上,负为地下室,不存在0层\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_design_id (design_id), INDEX idx_plan_id (plan_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE kujiale_designer_works_rel_cities (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', design_id VARCHAR(255) NOT NULL COMMENT \'方案id\', plan_id VARCHAR(255) DEFAULT NULL COMMENT \'户型ID\', city_id INT NOT NULL COMMENT \'城市ID\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_design_id (design_id), INDEX idx_plan_id (plan_id), INDEX idx_city_id (city_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE kujiale_designer_works_rel_tags (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'id\', tag_category_id VARCHAR(255) NOT NULL COMMENT \'标签类目id\', tag_category_name VARCHAR(255) DEFAULT NULL COMMENT \'标签类目名\', tag_id VARCHAR(255) DEFAULT NULL COMMENT \'标签id\', tag_name VARCHAR(255) DEFAULT NULL COMMENT \'标签名称\', design_id VARCHAR(255) NOT NULL COMMENT \'方案id\', plan_id VARCHAR(255) DEFAULT NULL COMMENT \'户型ID\', created INT NOT NULL COMMENT \'创建时间\', updated INT DEFAULT NULL COMMENT \'更新时间\', INDEX idx_design_id (design_id), INDEX idx_category_id (tag_category_id), INDEX idx_plan_id (plan_id), INDEX idx_tag_id (tag_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE member_segment_rules (rule_id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'规则id\', company_id BIGINT NOT NULL COMMENT \'公司id\', distributor_id BIGINT UNSIGNED DEFAULT 0 NOT NULL COMMENT \'分销商id\', rule_name VARCHAR(100) NOT NULL COMMENT \'规则名称(分群标签名称)\', description LONGTEXT DEFAULT NULL COMMENT \'人群说明\', rule_config LONGTEXT NOT NULL COMMENT \'规则配置(层级结构,JSON格式存储)\', tag_ids LONGTEXT DEFAULT NULL COMMENT \'关联的标签ID数组(JSON格式)\', status SMALLINT DEFAULT 1 NOT NULL COMMENT \'状态:0=禁用,1=启用\', created bigint NOT NULL, updated bigint NOT NULL, INDEX idx_company_distributor (company_id, distributor_id), INDEX idx_status (status), INDEX idx_created (created), PRIMARY KEY(rule_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'人群规则表\' '); + $this->addSql('CREATE TABLE members_tag_group_rel (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'主键ID\', group_id BIGINT NOT NULL COMMENT \'标签组ID\', tag_id BIGINT NOT NULL COMMENT \'标签ID\', company_id BIGINT NOT NULL COMMENT \'公司ID\', distributor_id BIGINT UNSIGNED DEFAULT 0 NOT NULL COMMENT \'分销商id\', created bigint NOT NULL, INDEX idx_group_id (group_id), INDEX idx_tag_id (tag_id), INDEX idx_company_distributor (company_id, distributor_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'会员标签组与标签关系表\' '); + $this->addSql('CREATE TABLE members_tag_groups (group_id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'标签组ID\', company_id BIGINT NOT NULL COMMENT \'公司id\', group_name VARCHAR(100) NOT NULL COMMENT \'标签组名称\', description VARCHAR(255) DEFAULT NULL COMMENT \'描述\', distributor_id BIGINT UNSIGNED DEFAULT 0 NOT NULL COMMENT \'分销商id\', wechat_group_id VARCHAR(100) DEFAULT NULL COMMENT \'企业微信标签组ID\', created bigint NOT NULL, updated bigint NOT NULL, INDEX idx_company_id (company_id), INDEX idx_distributor_id (distributor_id), PRIMARY KEY(group_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'会员标签组\' '); + $this->addSql('CREATE TABLE pages_ad_place (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'设置id\', company_id BIGINT NOT NULL COMMENT \'公司id\', regionauth_id BIGINT DEFAULT 0 NOT NULL COMMENT \'区域id\', use_bound INT DEFAULT 0 COMMENT \'适用范围: 0:全部,1:指定店铺\', ad_type VARCHAR(20) NOT NULL COMMENT \'广告类型:弹窗=>popup,轮播图=>carousel\', name VARCHAR(100) NOT NULL COMMENT \'广告位名称\', pages VARCHAR(30) NOT NULL COMMENT \'关联页面\', start_time BIGINT NOT NULL COMMENT \'开始时间\', end_time BIGINT NOT NULL COMMENT \'结束时间\', setting LONGTEXT DEFAULT NULL COMMENT \'设置\', auto_play INT DEFAULT 0 NOT NULL COMMENT \'自动播放\', play_interval INT DEFAULT 3 NOT NULL COMMENT \'播放间隔时间\', auto_close INT DEFAULT 0 NOT NULL COMMENT \'自动关闭\', close_delay INT DEFAULT 10 NOT NULL COMMENT \'关闭延迟时间\', source_id BIGINT DEFAULT 0 NOT NULL COMMENT \'添加者ID: 如店铺ID\', created INT NOT NULL, updated INT DEFAULT NULL, audit_status VARCHAR(255) DEFAULT \'submitting\' NOT NULL COMMENT \'审核状态 submitting待提交 processing审核中 approved成功 rejected审核拒绝\', audit_remark VARCHAR(255) DEFAULT NULL COMMENT \'审核备注\', sort INT DEFAULT 0 NOT NULL COMMENT \'排序\', tracking_code VARCHAR(100) DEFAULT NULL COMMENT \'埋点上报参数\', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'广告位设置\' '); + $this->addSql('CREATE TABLE pages_ad_place_rel_distributors (company_id BIGINT NOT NULL COMMENT \'公司id\', ad_place_id BIGINT NOT NULL COMMENT \'广告位id\', distributor_id BIGINT NOT NULL COMMENT \'店铺id\', PRIMARY KEY(company_id, ad_place_id, distributor_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'广告位与店铺关联表\' '); + $this->addSql('CREATE TABLE pages_ad_place_rel_member_tags (company_id BIGINT NOT NULL COMMENT \'公司id\', ad_place_id BIGINT NOT NULL COMMENT \'广告位id\', tag_id BIGINT NOT NULL COMMENT \'人群标签id\', PRIMARY KEY(company_id, ad_place_id, tag_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'广告位与人群标签关联表\' '); + $this->addSql('CREATE TABLE pages_side_bar (id BIGINT AUTO_INCREMENT NOT NULL COMMENT \'设置id\', company_id BIGINT NOT NULL COMMENT \'公司id\', regionauth_id BIGINT DEFAULT 0 NOT NULL COMMENT \'区域id\', name VARCHAR(100) NOT NULL COMMENT \'名称\', pages VARCHAR(100) NOT NULL COMMENT \'关联页面\', disabled TINYINT(1) DEFAULT \'0\' NOT NULL COMMENT \'是否禁用\', setting LONGTEXT DEFAULT NULL COMMENT \'设置\', created INT NOT NULL, updated INT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'侧边栏设置\' '); + $this->addSql('ALTER TABLE aftersales_detail CHANGE refunded_num refunded_num INT UNSIGNED DEFAULT 0 COMMENT \'实际入库数量\''); + $this->addSql('ALTER TABLE aftersales_refund CHANGE freight freight INT UNSIGNED DEFAULT 0 COMMENT \'退款运费,根据freight_type存储现金(分)或积分值\''); + $this->addSql('ALTER TABLE business_rep_user CHANGE create_time create_time bigint NOT NULL'); + $this->addSql('ALTER TABLE common_lang_mod_ar CHANGE data_id data_id BIGINT NOT NULL COMMENT \'业务id字段\''); + $this->addSql('ALTER TABLE common_lang_mod_cn CHANGE data_id data_id BIGINT NOT NULL COMMENT \'业务id字段\''); + $this->addSql('ALTER TABLE common_lang_mod_en CHANGE data_id data_id BIGINT NOT NULL COMMENT \'业务id字段\''); + $this->addSql('ALTER TABLE community_activity CHANGE activity_status activity_status VARCHAR(255) NOT NULL COMMENT \'活动状态 private私有 public公开 protected隐藏 success确认成团 fail成团失败\''); + $this->addSql('ALTER TABLE distribution_distributor ADD first_letter VARCHAR(5) DEFAULT \'\' NOT NULL COMMENT \'店铺名称首字母\''); + $this->addSql('ALTER TABLE items_category ADD regionauth_id BIGINT DEFAULT 0 NOT NULL COMMENT \'地区ID\', CHANGE invoice_tax_rate_id invoice_tax_rate_id BIGINT DEFAULT NULL COMMENT \'发票税率ID\', CHANGE invoice_tax_rate invoice_tax_rate VARCHAR(16) DEFAULT NULL COMMENT \'发票税率\''); + $this->addSql('ALTER TABLE kaquan_discount_cards ADD coupon_type VARCHAR(10) DEFAULT \'mall\' NOT NULL COMMENT \'券类型。mall:商城券;guide:导购专属券\', ADD guide_issue_quantity INT DEFAULT 0 NOT NULL COMMENT \'导购发放数量\''); + $this->addSql('ALTER TABLE kaquan_user_discount ADD salesperson_code VARCHAR(100) DEFAULT NULL COMMENT \'导购编号(employee_number/work_userid)\', CHANGE card_id card_id BIGINT NOT NULL COMMENT \'微信用户领取的卡券 id \''); + $this->addSql('CREATE INDEX idx_salesperson_code ON kaquan_user_discount (salesperson_code)'); + $this->addSql('ALTER TABLE members ADD reg_distributor INT DEFAULT 0 COMMENT \'注册时的分销商ID\', ADD reg_salesperson VARCHAR(100) DEFAULT NULL COMMENT \'注册时的导购ID\', ADD op_distributor INT DEFAULT 0 COMMENT \'作为分配的店铺ID\', ADD fp_salesperson VARCHAR(100) DEFAULT NULL COMMENT \'分配的导购员工编号(employee_number/work_userid)\', ADD has_fp TINYINT(1) DEFAULT \'0\' NOT NULL COMMENT \'是否有分配导购\', ADD is_become_friend TINYINT(1) DEFAULT \'0\' NOT NULL COMMENT \'是否已加为好友。0:否;1:是\', CHANGE created created bigint NOT NULL, CHANGE updated updated bigint NOT NULL'); + $this->addSql('ALTER TABLE members_tags ADD wechat_tag_id VARCHAR(100) DEFAULT NULL COMMENT \'企业微信标签ID\''); + $this->addSql('ALTER TABLE multi_lang_mod CHANGE data_id data_id BIGINT NOT NULL COMMENT \'业务id字段\''); + $this->addSql('ALTER TABLE orders_normal_orders_items CHANGE is_invoice is_invoice INT DEFAULT 0 NOT NULL COMMENT \'是否开票,0否 1已开票 2开票中 3红冲\''); + $this->addSql('ALTER TABLE pages_open_screen_ad ADD start_time BIGINT NOT NULL COMMENT \'开始时间\', ADD end_time BIGINT NOT NULL COMMENT \'结束时间\''); + $this->addSql('ALTER TABLE pages_template ADD regionauth_id BIGINT DEFAULT 0 COMMENT \'区域id\', CHANGE weapp_pages weapp_pages VARCHAR(255) DEFAULT \'index\' COMMENT \'模版页面:index-首页 distributor_index-门店首页\', CHANGE lang lang VARCHAR(255) DEFAULT NULL COMMENT \'模版语言\''); + $this->addSql('ALTER TABLE pages_template_set ADD regionauth_id BIGINT DEFAULT 0 COMMENT \'区域id\''); + $this->addSql('ALTER TABLE popularize_promoter_identity CHANGE is_default is_default INT NOT NULL COMMENT \'是否为默认\''); + $this->addSql('ALTER TABLE promotions_package_item CHANGE is_show is_show TINYINT(1) DEFAULT NULL COMMENT \'列表页是否显示\''); + $this->addSql('ALTER TABLE resources CHANGE eid eid VARCHAR(255) DEFAULT NULL COMMENT \'企业id\', CHANGE passport_uid passport_uid VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE selfservice_registration_activity CHANGE pics pics TEXT'); + $this->addSql('ALTER TABLE user_signin_rules CHANGE days_required days_required BIGINT NOT NULL COMMENT \'需要的天数\''); + $this->addSql('ALTER TABLE wechat_weapp_customize_page ADD regionauth_id BIGINT DEFAULT 0 NOT NULL COMMENT \'区域id\', CHANGE page_type page_type VARCHAR(255) DEFAULT \'normal\' NOT NULL COMMENT \'页面类型 normal:普通页面 salesperson:导购首页 category:分类页 my:我的\''); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema): void + { + } +} diff --git a/dev-setup.sh b/dev-setup.sh new file mode 100755 index 0000000..4841cc0 --- /dev/null +++ b/dev-setup.sh @@ -0,0 +1,2150 @@ +#!/bin/bash + +# ECShopX 开发环境设置脚本(Docker 方式) +# 使用单容器运行所有服务:PHP-FPM、Nginx、MySQL、Redis +# 支持三个项目:ECShopX、ECShopX_admin-frontend、ECShopX_mobile-frontend + +set -e + +# =========================================== +# 配置变量(可根据需要修改) +# =========================================== + +# 脚本目录和项目根目录 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$SCRIPT_DIR" +PARENT_DIR="$(cd "$PROJECT_ROOT/.." && pwd)" + +# 容器配置 +CONTAINER_NAME="ecshopx-dev" +DOCKER_COMPOSE_FILE="$PROJECT_ROOT/docker-compose.dev.yml" + +# 数据库配置 +MYSQL_ROOT_PWD="rootpassword" +MYSQL_DATABASE="ecshopx" +MYSQL_USER="ecshopx" +MYSQL_PASSWORD="ecshopx" + +# Redis 配置 +REDIS_PASSWORD="redispassword" + +# 默认选项 +REBUILD=false +SKIP_ADMIN=false +SKIP_VSHOP=false +SKIP_PC=false + +# 业务模式(全局变量,在 build_admin 中设置,build_vshop 中复用) +SELECTED_PLATFORM="" + +# 默认语言(全局变量,在第一个编译的项目中设置,后续项目复用) +SELECTED_LANG="" + +# 跟踪已安装的前端项目 +INSTALLED_ADMIN=false +INSTALLED_VSHOP=false +INSTALLED_PC=false + +# 记录开始时间 +START_TIME=$(date +%s) + +# Docker Compose 命令(兼容新旧版本) +DOCKER_COMPOSE_CMD="" + +# =========================================== +# 颜色和日志函数 +# =========================================== + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' + +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log_step() { + echo -e "${CYAN}[STEP]${NC} $1" +} + +# =========================================== +# 进度条和动画函数 +# =========================================== + +# Spinner 动画(用于不确定时长的操作) +spinner() { + local pid=$1 + local message=${2:-"处理中"} + local spinstr='|/-\' + local delay=0.1 + + while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} $message ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep $delay + done + printf "\r${CYAN}[INFO]${NC} $message 完成\n" +} + +# 简单的进度条(用于确定时长的操作) +progress_bar() { + local current=$1 + local total=$2 + local width=50 + local percentage=$((current * 100 / total)) + local completed=$((current * width / total)) + local remaining=$((width - completed)) + + printf "\r${CYAN}[INFO]${NC} 进度: [" + printf "%${completed}s" | tr ' ' '=' + printf "%${remaining}s" | tr ' ' '-' + printf "] %d%% (%d/%d)" $percentage $current $total +} + +# 带消息的进度条 +progress_bar_with_message() { + local current=$1 + local total=$2 + local message=$3 + local width=40 + local percentage=$((current * 100 / total)) + local completed=$((current * width / total)) + local remaining=$((width - completed)) + + printf "\r${CYAN}[INFO]${NC} $message [" + printf "%${completed}s" | tr ' ' '=' + printf "%${remaining}s" | tr ' ' '-' + printf "] %d%%" $percentage +} + +# 等待操作完成并显示进度 +wait_with_progress() { + local command=$1 + local message=${2:-"执行中"} + local max_wait=${3:-60} + local interval=${4:-1} + local count=0 + + # 后台执行命令 + eval "$command" > /tmp/progress_output.log 2>&1 & + local pid=$! + + # 显示进度 + while kill -0 $pid 2>/dev/null && [ $count -lt $max_wait ]; do + progress_bar_with_message $count $max_wait "$message" + sleep $interval + count=$((count + interval)) + done + + # 等待命令完成 + wait $pid + local exit_code=$? + + # 清除进度条 + printf "\r${GREEN}[SUCCESS]${NC} $message 完成" + printf "%$((${#message} + 20))s" "" + echo "" + + return $exit_code +} + +# =========================================== +# 检测 Docker Compose 命令 +# =========================================== + +detect_docker_compose() { + # 优先使用 docker compose (v2) + if docker compose version &>/dev/null 2>&1; then + DOCKER_COMPOSE_CMD="docker compose" + log_info "使用 Docker Compose V2 (docker compose)" + # 回退到 docker-compose (v1) + elif command -v docker-compose &>/dev/null; then + DOCKER_COMPOSE_CMD="docker-compose" + log_info "使用 Docker Compose V1 (docker-compose)" + else + log_error "未找到 Docker Compose 命令" + exit 1 + fi +} + +# =========================================== +# 检查容器是否运行 +# =========================================== + +is_container_running() { + docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$" 2>/dev/null +} + +# =========================================== +# 检查容器是否存在(包括已停止的) +# =========================================== + +container_exists() { + docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$" 2>/dev/null +} + +# =========================================== +# 帮助信息 +# =========================================== + +show_help() { + echo "ECShopX 开发环境设置脚本" + echo "" + echo "用法: $0 [选项]" + echo "" + echo "选项:" + echo " --help, -h 显示帮助信息" + echo " --rebuild 强制重新构建镜像(不使用缓存)" + echo " --skip-admin 跳过 ECShopX_admin-frontend 编译" + echo " --skip-vshop 跳过 ECShopX_mobile-frontend 编译" + echo "" + echo "示例:" + echo " $0 # 正常启动(使用缓存)" + echo " $0 --rebuild # 重新构建镜像" + echo " $0 --skip-admin # 跳过管理后台编译" + echo "" + exit 0 +} + +# =========================================== +# 解析命令行参数 +# =========================================== + +parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + --help|-h) + show_help + ;; + --rebuild) + REBUILD=true + shift + ;; + --skip-admin) + SKIP_ADMIN=true + shift + ;; + --skip-vshop) + SKIP_VSHOP=true + shift + ;; + --skip-pc) + SKIP_PC=true + shift + ;; + *) + log_error "未知参数: $1" + echo "使用 --help 查看帮助信息" + exit 1 + ;; + esac + done +} + +# =========================================== +# 检测操作系统 +# =========================================== + +detect_os() { + if [[ "$OSTYPE" == "darwin"* ]]; then + OS="macos" + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + OS="linux" + else + log_error "不支持的操作系统: $OSTYPE" + exit 1 + fi + log_info "检测到操作系统: $OS" +} + +# =========================================== +# 检测 Docker +# =========================================== + +check_docker() { + log_info "检测 Docker 安装状态..." + + if ! command -v docker &> /dev/null; then + log_error "Docker 未安装" + log_info "安装方式:" + log_info " macOS: 下载 Docker Desktop https://www.docker.com/products/docker-desktop" + log_info " Linux: sudo apt-get install docker.io docker-compose (Ubuntu/Debian)" + exit 1 + fi + + # 检测 Docker Compose 命令 + detect_docker_compose + + # 检查 Docker 是否正在运行 + if ! docker info &> /dev/null 2>&1; then + log_warning "Docker 未运行,尝试自动启动..." + + if [ "$OS" = "macos" ]; then + open -a Docker + log_info "正在启动 Docker Desktop,请等待..." + + for i in {1..60}; do + if docker info &> /dev/null 2>&1; then + log_success "Docker 已启动" + break + fi + sleep 2 + if [ $((i % 5)) -eq 0 ]; then + log_info " 等待 Docker 启动... ($i/60)" + fi + done + + if ! docker info &> /dev/null 2>&1; then + log_error "Docker 启动超时,请手动启动 Docker Desktop 后重新运行脚本" + exit 1 + fi + elif [ "$OS" = "linux" ]; then + sudo systemctl start docker || { + log_error "Docker 启动失败,请手动启动" + exit 1 + } + sleep 3 + if ! docker info &> /dev/null 2>&1; then + log_error "Docker 启动失败" + exit 1 + fi + log_success "Docker 已启动" + fi + fi + + log_success "Docker 和 Docker Compose 已就绪" +} + +# =========================================== +# 检查并克隆前端项目 +# =========================================== + +check_and_clone_frontend() { + log_step "检查前端项目目录..." + + # 检查 ECShopX_admin-frontend + ADMIN_DIR="$PARENT_DIR/ECShopX_admin-frontend" + ADMIN_REPO="https://gitee.com/ShopeX/ECShopX_admin-frontend.git" + + if [ ! -d "$ADMIN_DIR" ] || [ ! -f "$ADMIN_DIR/package.json" ]; then + if [ ! -d "$ADMIN_DIR" ]; then + log_warning "ECShopX_admin-frontend 目录不存在" + else + log_warning "ECShopX_admin-frontend 目录存在但缺少 package.json" + fi + + echo "" + echo -n "是否从 Gitee 克隆管理后台(ECShopX_admin-frontend)代码? [Y/n]: " + read -r answer < /dev/tty + + if [ -z "$answer" ] || [ "$answer" = "Y" ] || [ "$answer" = "y" ] || [ "$answer" = "yes" ] || [ "$answer" = "YES" ]; then + if [ -d "$ADMIN_DIR" ]; then + log_info "删除现有目录..." + rm -rf "$ADMIN_DIR" + fi + + log_info "正在从 Gitee 克隆管理后台(ECShopX_admin-frontend)..." + git clone "$ADMIN_REPO" "$ADMIN_DIR" > /tmp/git_clone_admin.log 2>&1 & + local clone_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $clone_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 克隆管理后台(ECShopX_admin-frontend)中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $clone_pid + local clone_exit=$? + + if [ $clone_exit -eq 0 ]; then + printf "\r${GREEN}[SUCCESS]${NC} 管理后台(ECShopX_admin-frontend)克隆成功" + printf "%50s" "" + echo "" + INSTALLED_ADMIN=true + else + printf "\r${RED}[ERROR]${NC} 管理后台(ECShopX_admin-frontend)克隆失败" + printf "%50s" "" + echo "" + cat /tmp/git_clone_admin.log 2>/dev/null | tail -10 + exit 1 + fi + else + log_warning "跳过管理后台(ECShopX_admin-frontend)克隆" + # 如果目录存在但用户选择不安装,删除目录 + if [ -d "$ADMIN_DIR" ]; then + log_info "删除未安装的管理后台目录..." + rm -rf "$ADMIN_DIR" + fi + fi + else + log_info "ECShopX_admin-frontend 目录已存在且包含 package.json,跳过克隆" + INSTALLED_ADMIN=true + fi + # 修复语法错误:注释掉重复的 else...fi 块(原代码第401-403行) + # else + # log_info "ECShopX_admin-frontend 目录已存在且包含 package.json,跳过克隆" + # fi + + # 检查 ECShopX_mobile-frontend + VSHOP_DIR="$PARENT_DIR/ECShopX_mobile-frontend" + VSHOP_REPO="https://gitee.com/ShopeX/ECShopX_mobile-frontend.git" + + if [ ! -d "$VSHOP_DIR" ] || [ ! -f "$VSHOP_DIR/package.json" ]; then + if [ ! -d "$VSHOP_DIR" ]; then + log_warning "ECShopX_mobile-frontend 目录不存在" + else + log_warning "ECShopX_mobile-frontend 目录存在但缺少 package.json" + fi + + echo "" + echo -n "是否从 Gitee 克隆移动商城(ECShopX_mobile-frontend)代码? [Y/n]: " + read -r answer < /dev/tty + + if [ -z "$answer" ] || [ "$answer" = "Y" ] || [ "$answer" = "y" ] || [ "$answer" = "yes" ] || [ "$answer" = "YES" ]; then + if [ -d "$VSHOP_DIR" ]; then + log_info "删除现有目录..." + rm -rf "$VSHOP_DIR" + fi + + log_info "正在从 Gitee 克隆移动商城(ECShopX_mobile-frontend)..." + git clone "$VSHOP_REPO" "$VSHOP_DIR" > /tmp/git_clone_vshop.log 2>&1 & + local clone_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $clone_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 克隆移动商城(ECShopX_mobile-frontend)中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $clone_pid + local clone_exit=$? + + if [ $clone_exit -eq 0 ]; then + printf "\r${GREEN}[SUCCESS]${NC}移动商城(ECShopX_mobile-frontend)克隆成功" + printf "%50s" "" + echo "" + INSTALLED_VSHOP=true + else + printf "\r${RED}[ERROR]${NC}移动商城(ECShopX_mobile-frontend)克隆失败" + printf "%50s" "" + echo "" + cat /tmp/git_clone_vshop.log 2>/dev/null | tail -10 + exit 1 + fi + else + log_warning "跳过移动商城(ECShopX_mobile-frontend)克隆" + # 如果目录存在但用户选择不安装,删除目录 + if [ -d "$VSHOP_DIR" ]; then + log_info "删除未安装的移动商城目录..." + rm -rf "$VSHOP_DIR" + fi + fi + else + log_info "ECShopX_mobile-frontend 目录已存在且包含 package.json,跳过克隆" + INSTALLED_VSHOP=true + fi + + # 检查 ECShopX_desktop-frontend + PC_DIR="$PARENT_DIR/ECShopX_desktop-frontend" + PC_REPO="https://gitee.com/ShopeX/ECShopX_desktop-frontend.git" + + if [ ! -d "$PC_DIR" ] || [ ! -f "$PC_DIR/package.json" ]; then + if [ ! -d "$PC_DIR" ]; then + log_warning "ECShopX_desktop-frontend 目录不存在" + else + log_warning "ECShopX_desktop-frontend 目录存在但缺少 package.json" + fi + + echo "" + echo -n "是否从 Gitee 克隆PC商城(ECShopX_desktop-frontend)代码? [Y/n]: " + read -r answer < /dev/tty + + if [ -z "$answer" ] || [ "$answer" = "Y" ] || [ "$answer" = "y" ] || [ "$answer" = "yes" ] || [ "$answer" = "YES" ]; then + if [ -d "$PC_DIR" ]; then + log_info "删除现有目录..." + rm -rf "$PC_DIR" + fi + + log_info "正在从 Gitee 克隆PC商城(ECShopX_desktop-frontend)..." + git clone "$PC_REPO" "$PC_DIR" > /tmp/git_clone_pc.log 2>&1 & + local clone_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $clone_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 克隆PC商城(ECShopX_desktop-frontend)中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $clone_pid + local clone_exit=$? + + if [ $clone_exit -eq 0 ]; then + printf "\r${GREEN}[SUCCESS]${NC}PC商城(ECShopX_desktop-frontend)克隆成功" + printf "%50s" "" + echo "" + INSTALLED_PC=true + else + printf "\r${RED}[ERROR]${NC}PC商城(ECShopX_desktop-frontend)克隆失败" + printf "%50s" "" + echo "" + cat /tmp/git_clone_pc.log 2>/dev/null | tail -10 + exit 1 + fi + else + log_warning "跳过PC商城(ECShopX_desktop-frontend)克隆" + # 如果目录存在但用户选择不安装,删除目录 + if [ -d "$PC_DIR" ]; then + log_info "删除未安装的PC商城目录..." + rm -rf "$PC_DIR" + fi + fi + else + log_info "ECShopX_desktop-frontend 目录已存在且包含 package.json,跳过克隆" + INSTALLED_PC=true + fi + + echo "" +} + +# =========================================== +# 检查容器状态 +# =========================================== + +check_container_status() { + # 检查容器是否存在(包括已停止的) + if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + # 检查容器是否正在运行 + if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + log_warning "容器 $CONTAINER_NAME 正在运行" + else + log_warning "容器 $CONTAINER_NAME 已存在但未运行" + fi + echo "" + echo -n "请选择操作: [1] 重启容器 [2] 使用现有容器 [3] 退出: " + read -r choice < /dev/tty + + case $choice in + 1) + log_info "停止并删除现有容器..." + $DOCKER_COMPOSE_CMD -f "$DOCKER_COMPOSE_FILE" down + return 0 # 需要重新构建 + ;; + 2) + log_info "使用现有容器..." + # 如果容器未运行,先启动它 + if ! is_container_running; then + log_info "启动现有容器..." + $DOCKER_COMPOSE_CMD -f "$DOCKER_COMPOSE_FILE" up -d + sleep 5 + wait_for_services + fi + return 1 # 跳过构建 + ;; + 3) + log_info "退出脚本" + exit 0 + ;; + *) + log_info "使用现有容器..." + return 1 + ;; + esac + fi + return 0 +} + +# =========================================== +# 配置环境文件 +# =========================================== + +configure_env() { + log_info "配置环境文件..." + cd "$PROJECT_ROOT" + + if [ ! -f ".env" ]; then + for template in ".env.full" ".env.example" ".env.template"; do + if [ -f "$template" ]; then + log_info "从 $template 复制创建 .env 文件..." + cp "$template" .env + break + fi + done + fi +} + +# =========================================== +# 动态修改 docker-compose 文件,移除未安装项目的卷映射 +# =========================================== + +modify_docker_compose() { + log_info "根据安装选择调整 Docker Compose 配置..." + + cd "$PROJECT_ROOT" + + if [ ! -f "$DOCKER_COMPOSE_FILE" ]; then + log_warning "未找到 $DOCKER_COMPOSE_FILE 文件,跳过配置调整" + return 0 + fi + + # 创建临时文件 + local temp_file="${DOCKER_COMPOSE_FILE}.tmp" + cp "$DOCKER_COMPOSE_FILE" "$temp_file" + + # 根据安装标志移除对应的卷映射 + # docker-compose 文件格式: - ../ECShopX_admin-frontend:/data/httpd/ECShopX_admin-frontend + + # 移除管理后台的卷映射(如果未安装) + if [ "$INSTALLED_ADMIN" = false ]; then + log_info "移除 ECShopX_admin-frontend 的卷映射..." + # 直接匹配包含项目名称的行(docker-compose 格式: - ../ECShopX_admin-frontend:...) + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' '/ECShopX_admin-frontend/d' "$temp_file" + else + sed -i '/ECShopX_admin-frontend/d' "$temp_file" + fi + fi + + # 移除移动商城的卷映射(如果未安装) + if [ "$INSTALLED_VSHOP" = false ]; then + log_info "移除 ECShopX_mobile-frontend 的卷映射..." + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' '/ECShopX_mobile-frontend/d' "$temp_file" + else + sed -i '/ECShopX_mobile-frontend/d' "$temp_file" + fi + fi + + # 移除PC商城的卷映射(如果未安装) + if [ "$INSTALLED_PC" = false ]; then + log_info "移除 ECShopX_desktop-frontend 的卷映射..." + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' '/ECShopX_desktop-frontend/d' "$temp_file" + else + sed -i '/ECShopX_desktop-frontend/d' "$temp_file" + fi + fi + + # 清理可能产生的空行(连续两个空行变为一个) + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' '/^$/N;/^\n$/d' "$temp_file" + else + sed -i '/^$/N;/^\n$/d' "$temp_file" + fi + + # 替换原文件 + mv "$temp_file" "$DOCKER_COMPOSE_FILE" + log_success "Docker Compose 配置已调整" + + # 删除未安装项目的目录(如果存在,可能是之前容器创建的) + if [ "$INSTALLED_ADMIN" = false ]; then + ADMIN_DIR="$PARENT_DIR/ECShopX_admin-frontend" + if [ -d "$ADMIN_DIR" ]; then + log_info "删除未安装的管理后台目录: $ADMIN_DIR" + rm -rf "$ADMIN_DIR" + fi + fi + + if [ "$INSTALLED_VSHOP" = false ]; then + VSHOP_DIR="$PARENT_DIR/ECShopX_mobile-frontend" + if [ -d "$VSHOP_DIR" ]; then + log_info "删除未安装的移动商城目录: $VSHOP_DIR" + rm -rf "$VSHOP_DIR" + fi + fi + + if [ "$INSTALLED_PC" = false ]; then + PC_DIR="$PARENT_DIR/ECShopX_desktop-frontend" + if [ -d "$PC_DIR" ]; then + log_info "删除未安装的PC商城目录: $PC_DIR" + rm -rf "$PC_DIR" + fi + fi + + # 如果容器已存在,需要停止并删除,以便重新创建时应用新的配置 + if container_exists; then + log_info "检测到现有容器,需要重启以应用新的卷映射配置..." + if is_container_running; then + log_info "停止现有容器..." + $DOCKER_COMPOSE_CMD -f "$DOCKER_COMPOSE_FILE" down + else + log_info "删除已停止的容器..." + $DOCKER_COMPOSE_CMD -f "$DOCKER_COMPOSE_FILE" rm -f + fi + fi +} + +# =========================================== +# 构建并启动 Docker 容器 +# =========================================== + +run_docker() { + log_step "启动 Docker 容器..." + + cd "$PROJECT_ROOT" + + # 在启动前修改 docker-compose 文件 + modify_docker_compose + + if [ ! -f "$DOCKER_COMPOSE_FILE" ]; then + log_error "未找到 $DOCKER_COMPOSE_FILE 文件" + exit 1 + fi + + # 构建镜像 + if [ "$REBUILD" = true ]; then + log_info "强制重新构建镜像(--no-cache)..." + log_info "这可能需要较长时间,请耐心等待..." + $DOCKER_COMPOSE_CMD -f "$DOCKER_COMPOSE_FILE" build --no-cache > /tmp/docker_build.log 2>&1 & + local build_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $build_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 构建 Docker 镜像中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.3 + done + wait $build_pid + local build_exit=$? + + if [ $build_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} Docker 镜像构建失败" + printf "%50s" "" + echo "" + cat /tmp/docker_build.log 2>/dev/null | tail -30 + exit 1 + else + printf "\r${GREEN}[SUCCESS]${NC} Docker 镜像构建完成" + printf "%50s" "" + echo "" + fi + else + log_info "构建镜像(使用缓存)..." + $DOCKER_COMPOSE_CMD -f "$DOCKER_COMPOSE_FILE" build > /tmp/docker_build.log 2>&1 & + local build_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $build_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 构建 Docker 镜像中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.3 + done + wait $build_pid + local build_exit=$? + + if [ $build_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} Docker 镜像构建失败" + printf "%50s" "" + echo "" + cat /tmp/docker_build.log 2>/dev/null | tail -30 + exit 1 + else + printf "\r${GREEN}[SUCCESS]${NC} Docker 镜像构建完成" + printf "%50s" "" + echo "" + fi + fi + + # 启动容器 + log_info "启动容器..." + $DOCKER_COMPOSE_CMD -f "$DOCKER_COMPOSE_FILE" up -d || { + log_error "Docker 服务启动失败" + exit 1 + } + + log_info "等待服务启动..." + sleep 5 + + # 显示容器状态 + $DOCKER_COMPOSE_CMD -f "$DOCKER_COMPOSE_FILE" ps + + # 等待服务就绪 + wait_for_services +} + +# =========================================== +# 等待服务就绪 +# =========================================== + +wait_for_services() { + # 等待 Supervisor + log_info "等待 Supervisor 启动..." + for i in {1..20}; do + if docker exec "$CONTAINER_NAME" supervisorctl status &>/dev/null 2>&1; then + break + fi + sleep 1 + done + + # 等待 MySQL + log_info "等待 MySQL 服务就绪..." + for i in {1..60}; do + if docker exec "$CONTAINER_NAME" mysqladmin ping --socket=/var/run/mysqld/mysqld.sock -u root -p"$MYSQL_ROOT_PWD" --silent 2>/dev/null || \ + docker exec "$CONTAINER_NAME" mysqladmin ping -h 127.0.0.1 -u root -p"$MYSQL_ROOT_PWD" --silent 2>/dev/null; then + log_success "MySQL 服务已就绪" + break + fi + sleep 2 + if [ $((i % 5)) -eq 0 ]; then + log_info " 等待 MySQL... ($i/60)" + fi + if [ $i -eq 60 ]; then + log_error "MySQL 服务启动超时" + docker exec "$CONTAINER_NAME" tail -n 30 /var/log/supervisor/mysql.log 2>/dev/null || true + exit 1 + fi + done + + # 等待 Redis + log_info "等待 Redis 服务就绪..." + for i in {1..30}; do + if docker exec "$CONTAINER_NAME" redis-cli -a "$REDIS_PASSWORD" ping 2>/dev/null | grep -q "PONG"; then + log_success "Redis 服务已就绪" + break + fi + sleep 2 + if [ $((i % 5)) -eq 0 ]; then + log_info " 等待 Redis... ($i/30)" + fi + if [ $i -eq 30 ]; then + log_error "Redis 服务启动超时" + docker exec "$CONTAINER_NAME" tail -n 30 /var/log/supervisor/redis.log 2>/dev/null || true + exit 1 + fi + done +} + +# =========================================== +# 配置 PHP 应用 +# =========================================== + +configure_application() { + log_info "==========================================" + log_info "开始配置 ECShopX(PHP API)..." + log_info "==========================================" + + # 配置本地 .env 文件 + configure_env + + # 配置容器内 .env 文件 + log_info "配置应用环境..." + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && \ + if [ ! -f .env ]; then \ + cp .env.example .env 2>/dev/null || cp .env.full .env 2>/dev/null || touch .env; \ + fi" || true + + # 更新数据库配置和存储配置 + log_info "更新 .env 配置..." + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && \ + sed -i 's/^DB_HOST=.*/DB_HOST=127.0.0.1/' .env && \ + sed -i 's/^DB_PORT=.*/DB_PORT=3306/' .env && \ + sed -i 's/^DB_DATABASE=.*/DB_DATABASE=$MYSQL_DATABASE/' .env && \ + sed -i 's/^DB_USERNAME=.*/DB_USERNAME=$MYSQL_USER/' .env && \ + sed -i 's/^DB_PASSWORD=.*/DB_PASSWORD=$MYSQL_PASSWORD/' .env && \ + sed -i 's/^REDIS_HOST=.*/REDIS_HOST=127.0.0.1/' .env && \ + sed -i 's/^REDIS_PORT=.*/REDIS_PORT=6379/' .env && \ + sed -i 's/^REDIS_PASSWORD=.*/REDIS_PASSWORD=$REDIS_PASSWORD/' .env && \ + sed -i 's/^REDIS_DATABASE=.*/REDIS_DATABASE=0/' .env && \ + (grep -q '^DISK_DRIVER=' .env && sed -i 's/^DISK_DRIVER=.*/DISK_DRIVER=local/' .env || echo 'DISK_DRIVER=local' >> .env) && \ + (grep -q '^APP_URL=' .env && sed -i 's|^APP_URL=.*|APP_URL=http://localhost:8080|' .env || echo 'APP_URL=http://localhost:8080' >> .env)" 2>/dev/null || true + + # 安装 Composer 依赖 + log_info "检查并安装 Composer 依赖..." + + # 检查是否需要安装依赖 + NEED_INSTALL=$(docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && \ + if [ ! -f composer.phar ]; then \ + echo 'ERROR'; \ + elif [ ! -d vendor ] || [ ! -f vendor/autoload.php ]; then \ + echo 'YES'; \ + else \ + echo 'NO'; \ + fi" 2>/dev/null) + + if [ "$NEED_INSTALL" = "ERROR" ]; then + log_error "composer.phar 文件不存在" + exit 1 + elif [ "$NEED_INSTALL" = "YES" ]; then + log_info "开始安装 Composer 依赖(这可能需要一些时间)..." + # 后台执行并显示进度 + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && \ + php -d memory_limit=-1 composer.phar config repo.packagist composer https://mirrors.aliyun.com/composer/ 2>/dev/null || true && \ + php -d memory_limit=-1 composer.phar install -o --no-interaction --prefer-dist" > /tmp/composer_output.log 2>&1 & + local composer_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $composer_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 安装 Composer 依赖中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $composer_pid + local composer_exit=$? + + if [ $composer_exit -eq 0 ]; then + printf "\r${GREEN}[SUCCESS]${NC} Composer 依赖安装完成" + printf "%50s" "" + echo "" + else + printf "\r${RED}[ERROR]${NC} Composer 依赖安装失败" + printf "%50s" "" + echo "" + cat /tmp/composer_output.log 2>/dev/null | tail -20 + exit 1 + fi + else + log_success "Composer 依赖已存在,跳过安装" + fi + + # 生成应用密钥(仅在不存在时) + APP_KEY=$(docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && grep '^APP_KEY=' .env | cut -d'=' -f2" 2>/dev/null) + if [ -z "$APP_KEY" ] || [ "$APP_KEY" = "" ]; then + log_info "生成应用密钥..." + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && php artisan key:generate --force" 2>/dev/null || { + log_warning "应用密钥生成失败" + } + else + log_info "应用密钥已存在,跳过生成" + fi + + # 执行数据库迁移 + log_info "执行数据库迁移..." + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && php artisan doctrine:migrations:migrate --no-interaction" > /tmp/migration_output.log 2>&1 & + local migration_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $migration_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 执行数据库迁移中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $migration_pid + local migration_exit=$? + + if [ $migration_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} 数据库迁移失败" + printf "%50s" "" + echo "" + cat /tmp/migration_output.log 2>/dev/null | tail -20 + log_info "请手动执行: docker exec $CONTAINER_NAME sh -c 'cd /data/httpd/ECShopX && php artisan doctrine:migrations:migrate --no-interaction'" + exit 1 + else + printf "\r${GREEN}[SUCCESS]${NC} 数据库迁移完成" + printf "%50s" "" + echo "" + fi + + # 创建存储链接(storage:link) + log_info "创建存储目录链接..." + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && \ + if [ ! -L public/storage ] && [ ! -d public/storage ]; then \ + php artisan storage:link 2>/dev/null || true; \ + fi" || { + log_warning "存储链接创建失败,将稍后重试" + } + log_success "存储链接配置完成" + + # 初始化管理员密码 + init_admin_password +} + +# =========================================== +# 初始化管理员密码 +# =========================================== + +init_admin_password() { + echo "" + while true; do + echo -n "请输入管理员密码: " + read -rs admin_password < /dev/tty + echo "" # 换行 + + if [ -z "$admin_password" ]; then + log_warning "密码不能为空,请重新输入" + continue + fi + + echo -n "请再次确认密码: " + read -rs admin_password_confirm < /dev/tty + echo "" # 换行 + + if [ "$admin_password" != "$admin_password_confirm" ]; then + log_warning "两次输入的密码不一致,请重新输入" + continue + fi + break + done + + log_info "初始化管理员密码..." + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX && php artisan account:init-admin-password '$admin_password'" || { + log_warning "管理员密码初始化失败" + } + log_success "管理员密码初始化完成" +} + +# =========================================== +# 检查容器内目录是否存在并挂载正确 +# =========================================== + +check_container_directory() { + local container_path=$1 + local host_path=$2 + local project_name=$3 + local max_retries=2 + local retry_count=0 + + # 首先检查容器是否运行 + if ! is_container_running; then + log_warning "容器未运行,无法检查目录挂载状态" + log_info "目录挂载将在容器启动后自动生效" + # 对于 ECShopX_desktop-frontend,如果容器未运行,也返回成功(允许继续) + if [ "$project_name" = "ECShopX_desktop-frontend" ]; then + return 0 + fi + return 0 # 容器未运行时,假设挂载会在启动后生效 + fi + + while [ $retry_count -lt $max_retries ]; do + # 检查目录是否存在 + if docker exec "$CONTAINER_NAME" sh -c "test -d $container_path" 2>/dev/null; then + # 检查 package.json 是否存在 + if docker exec "$CONTAINER_NAME" sh -c "test -f $container_path/package.json" 2>/dev/null; then + log_success "目录挂载检查通过: $container_path" + return 0 # 目录和文件都存在 + else + if [ $retry_count -eq 0 ]; then + log_warning "容器内 $container_path/package.json 不存在,尝试重启容器以确保目录正确挂载..." + if ! restart_container_for_mount "$project_name"; then + return 1 + fi + retry_count=$((retry_count + 1)) + continue + else + # 对于 ECShopX_desktop-frontend,如果重启后仍然不存在,也允许继续(可能是配置问题) + if [ "$project_name" = "ECShopX_desktop-frontend" ]; then + log_warning "容器内 $container_path/package.json 仍然不存在,但继续执行..." + return 0 + fi + log_error "容器内 $container_path/package.json 仍然不存在" + log_info "请检查主机目录 $host_path 是否存在且包含 package.json" + return 1 + fi + fi + else + if [ $retry_count -eq 0 ]; then + log_warning "容器内 $container_path 目录不存在,尝试重启容器以确保目录正确挂载..." + if ! restart_container_for_mount "$project_name"; then + return 1 + fi + retry_count=$((retry_count + 1)) + continue + else + log_error "容器内 $container_path 目录仍然不存在" + log_info "请检查 docker-compose.dev.yml 中的卷挂载配置是否正确" + log_info "主机目录路径: $host_path" + return 1 + fi + fi + done + + return 1 +} + +# =========================================== +# 重启容器以确保目录挂载 +# =========================================== + +restart_container_for_mount() { + local project_name=$1 + log_warning "检测到 $project_name 目录未正确挂载,正在重启容器..." + + if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$" 2>/dev/null; then + log_info "重启容器 $CONTAINER_NAME..." + docker-compose -f "$DOCKER_COMPOSE_FILE" restart || { + log_error "容器重启失败" + return 1 + } + + log_info "等待容器启动..." + sleep 5 + + # 等待服务就绪 + wait_for_services + + log_success "容器重启完成" + return 0 + else + log_warning "容器未运行,无需重启" + return 0 + fi +} + +# =========================================== +# 配置前端项目的 .env 文件 +# =========================================== + +configure_frontend_env() { + local project_dir=$1 + local project_name=$2 + local api_base_url=${3:-"http://localhost:8080/api/"} + local app_id=${4:-""} + local default_lang=${5:-""} + + # 检查主机目录是否存在 + if [ ! -d "$project_dir" ]; then + log_warning "$project_name 目录不存在,跳过配置" + return 0 + fi + + # 检查容器内目录是否存在 + local container_path="" + if [ "$project_name" = "ECShopX_admin-frontend" ]; then + container_path="/data/httpd/ECShopX_admin-frontend" + elif [ "$project_name" = "ECShopX_mobile-frontend" ]; then + container_path="/data/httpd/ECShopX_mobile-frontend" + elif [ "$project_name" = "ECShopX_desktop-frontend" ]; then + container_path="/data/httpd/ECShopX_desktop-frontend" + else + log_warning "未知的项目名称: $project_name" + return 0 + fi + + # 如果容器未运行,直接配置主机目录 + if ! is_container_running; then + log_info "容器未运行,配置主机目录的 .env 文件..." + local env_file="$project_dir/.env" + + # 如果 .env 不存在,尝试从 .env.example 复制 + if [ ! -f "$env_file" ]; then + if [ -f "$project_dir/.env.example" ]; then + log_info "从 .env.example 创建 .env 文件..." + cp "$project_dir/.env.example" "$env_file" + else + log_info "创建新的 .env 文件..." + touch "$env_file" + fi + fi + + # 配置 ECShopX_admin-frontend + if [ "$project_name" = "ECShopX_admin-frontend" ]; then + # 使用 sed 修改或添加 VUE_APP_BASE_API + if grep -q "^VUE_APP_BASE_API=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^VUE_APP_BASE_API=.*|VUE_APP_BASE_API=$api_base_url|" "$env_file" + else + sed -i "s|^VUE_APP_BASE_API=.*|VUE_APP_BASE_API=$api_base_url|" "$env_file" + fi + else + echo "VUE_APP_BASE_API=$api_base_url" >> "$env_file" + fi + log_success "已配置 VUE_APP_BASE_API=$api_base_url" + + # 配置 VUE_APP_DEFAULT_LANG(如果提供) + if [ -n "$default_lang" ]; then + if grep -q "^VUE_APP_DEFAULT_LANG=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^VUE_APP_DEFAULT_LANG=.*|VUE_APP_DEFAULT_LANG=$default_lang|" "$env_file" + else + sed -i "s|^VUE_APP_DEFAULT_LANG=.*|VUE_APP_DEFAULT_LANG=$default_lang|" "$env_file" + fi + else + echo "VUE_APP_DEFAULT_LANG=$default_lang" >> "$env_file" + fi + log_success "已配置 VUE_APP_DEFAULT_LANG=$default_lang" + fi + + # 配置 VUE_APP_QIANKUN_ENTRY + if grep -q "^VUE_APP_QIANKUN_ENTRY=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^VUE_APP_QIANKUN_ENTRY=.*|VUE_APP_QIANKUN_ENTRY=http://localhost:8080/newpc/|" "$env_file" + else + sed -i "s|^VUE_APP_QIANKUN_ENTRY=.*|VUE_APP_QIANKUN_ENTRY=http://localhost:8080/newpc/|" "$env_file" + fi + else + echo "VUE_APP_QIANKUN_ENTRY=http://localhost:8080/newpc/" >> "$env_file" + fi + log_success "已配置 VUE_APP_QIANKUN_ENTRY=http://localhost:8080/newpc/" + fi + + # 配置 ECShopX_mobile-frontend + if [ "$project_name" = "ECShopX_mobile-frontend" ]; then + # 使用 sed 修改或添加 APP_BASE_URL + if grep -q "^APP_BASE_URL=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^APP_BASE_URL=.*|APP_BASE_URL=$api_base_url|" "$env_file" + else + sed -i "s|^APP_BASE_URL=.*|APP_BASE_URL=$api_base_url|" "$env_file" + fi + else + echo "APP_BASE_URL=$api_base_url" >> "$env_file" + fi + log_success "已配置 APP_BASE_URL=$api_base_url" + + # 配置 APP_PLATFORM(如果提供) + if [ -n "$app_id" ]; then + if grep -q "^APP_PLATFORM=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^APP_PLATFORM=.*|APP_PLATFORM=$app_id|" "$env_file" + else + sed -i "s|^APP_PLATFORM=.*|APP_PLATFORM=$app_id|" "$env_file" + fi + else + echo "APP_PLATFORM=$app_id" >> "$env_file" + fi + log_success "已配置 APP_PLATFORM=$app_id" + fi + + # 配置 APP_I18N_ORIGIN_LANG(如果提供) + if [ -n "$default_lang" ]; then + if grep -q "^APP_I18N_ORIGIN_LANG=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^APP_I18N_ORIGIN_LANG=.*|APP_I18N_ORIGIN_LANG=$default_lang|" "$env_file" + else + sed -i "s|^APP_I18N_ORIGIN_LANG=.*|APP_I18N_ORIGIN_LANG=$default_lang|" "$env_file" + fi + else + echo "APP_I18N_ORIGIN_LANG=$default_lang" >> "$env_file" + fi + log_success "已配置 APP_I18N_ORIGIN_LANG=$default_lang" + fi + fi + + # 配置 ECShopX_desktop-frontend + if [ "$project_name" = "ECShopX_desktop-frontend" ]; then + # 使用 sed 修改或添加 VUE_APP_API_BASE_URL + if grep -q "^VUE_APP_API_BASE_URL=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^VUE_APP_API_BASE_URL=.*|VUE_APP_API_BASE_URL=$api_base_url|" "$env_file" + else + sed -i "s|^VUE_APP_API_BASE_URL=.*|VUE_APP_API_BASE_URL=$api_base_url|" "$env_file" + fi + else + echo "VUE_APP_API_BASE_URL=$api_base_url" >> "$env_file" + fi + log_success "已配置 VUE_APP_API_BASE_URL=$api_base_url" + + # 配置 VUE_APP_COMPANYID(默认值为1) + if grep -q "^VUE_APP_COMPANYID=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^VUE_APP_COMPANYID=.*|VUE_APP_COMPANYID=1|" "$env_file" + else + sed -i "s|^VUE_APP_COMPANYID=.*|VUE_APP_COMPANYID=1|" "$env_file" + fi + else + echo "VUE_APP_COMPANYID=1" >> "$env_file" + fi + log_success "已配置 VUE_APP_COMPANYID=1" + + # 配置 VUE_APP_DEFAULT_LANG(如果提供) + if [ -n "$default_lang" ]; then + if grep -q "^VUE_APP_DEFAULT_LANG=" "$env_file" 2>/dev/null; then + # macOS 和 Linux 兼容的 sed 命令 + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s|^VUE_APP_DEFAULT_LANG=.*|VUE_APP_DEFAULT_LANG=$default_lang|" "$env_file" + else + sed -i "s|^VUE_APP_DEFAULT_LANG=.*|VUE_APP_DEFAULT_LANG=$default_lang|" "$env_file" + fi + else + echo "VUE_APP_DEFAULT_LANG=$default_lang" >> "$env_file" + fi + log_success "已配置 VUE_APP_DEFAULT_LANG=$default_lang" + fi + fi + else + # 容器运行中,配置容器内的 .env 文件 + # 检查容器内目录是否存在 + if ! docker exec "$CONTAINER_NAME" sh -c "test -d $container_path" 2>/dev/null; then + log_warning "容器内 $container_path 目录不存在,跳过配置" + return 0 + fi + + # 在容器内配置 .env 文件 + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if [ ! -f .env ]; then + if [ -f .env.example ]; then + cp .env.example .env + else + touch .env + fi + fi + " 2>/dev/null || true + + # 配置 ECShopX_admin-frontend + if [ "$project_name" = "ECShopX_admin-frontend" ]; then + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^VUE_APP_BASE_API=' .env 2>/dev/null; then + sed -i 's|^VUE_APP_BASE_API=.*|VUE_APP_BASE_API=$api_base_url|' .env + else + echo 'VUE_APP_BASE_API=$api_base_url' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 VUE_APP_BASE_API=$api_base_url" + + # 配置 VUE_APP_DEFAULT_LANG(如果提供) + if [ -n "$default_lang" ]; then + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^VUE_APP_DEFAULT_LANG=' .env 2>/dev/null; then + sed -i 's|^VUE_APP_DEFAULT_LANG=.*|VUE_APP_DEFAULT_LANG=$default_lang|' .env + else + echo 'VUE_APP_DEFAULT_LANG=$default_lang' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 VUE_APP_DEFAULT_LANG=$default_lang" + fi + + # 配置 VUE_APP_QIANKUN_ENTRY + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^VUE_APP_QIANKUN_ENTRY=' .env 2>/dev/null; then + sed -i 's|^VUE_APP_QIANKUN_ENTRY=.*|VUE_APP_QIANKUN_ENTRY=http://localhost:8080/newpc/|' .env + else + echo 'VUE_APP_QIANKUN_ENTRY=http://localhost:8080/newpc/' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 VUE_APP_QIANKUN_ENTRY=http://localhost:8080/newpc/" + fi + + # 配置 ECShopX_mobile-frontend + if [ "$project_name" = "ECShopX_mobile-frontend" ]; then + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^APP_BASE_URL=' .env 2>/dev/null; then + sed -i 's|^APP_BASE_URL=.*|APP_BASE_URL=$api_base_url|' .env + else + echo 'APP_BASE_URL=$api_base_url' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 APP_BASE_URL=$api_base_url" + + # 配置 APP_PLATFORM(如果提供) + if [ -n "$app_id" ]; then + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^APP_PLATFORM=' .env 2>/dev/null; then + sed -i 's|^APP_PLATFORM=.*|APP_PLATFORM=$app_id|' .env + else + echo 'APP_PLATFORM=$app_id' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 APP_PLATFORM=$app_id" + fi + + # 配置 APP_I18N_ORIGIN_LANG(如果提供) + if [ -n "$default_lang" ]; then + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^APP_I18N_ORIGIN_LANG=' .env 2>/dev/null; then + sed -i 's|^APP_I18N_ORIGIN_LANG=.*|APP_I18N_ORIGIN_LANG=$default_lang|' .env + else + echo 'APP_I18N_ORIGIN_LANG=$default_lang' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 APP_I18N_ORIGIN_LANG=$default_lang" + fi + fi + + # 配置 ECShopX_desktop-frontend + if [ "$project_name" = "ECShopX_desktop-frontend" ]; then + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^VUE_APP_API_BASE_URL=' .env 2>/dev/null; then + sed -i 's|^VUE_APP_API_BASE_URL=.*|VUE_APP_API_BASE_URL=$api_base_url|' .env + else + echo 'VUE_APP_API_BASE_URL=$api_base_url' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 VUE_APP_API_BASE_URL=$api_base_url" + + # 配置 VUE_APP_COMPANYID(默认值为1) + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^VUE_APP_COMPANYID=' .env 2>/dev/null; then + sed -i 's|^VUE_APP_COMPANYID=.*|VUE_APP_COMPANYID=1|' .env + else + echo 'VUE_APP_COMPANYID=1' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 VUE_APP_COMPANYID=1" + + # 配置 VUE_APP_DEFAULT_LANG(如果提供) + if [ -n "$default_lang" ]; then + docker exec "$CONTAINER_NAME" sh -c " + cd $container_path && \ + if grep -q '^VUE_APP_DEFAULT_LANG=' .env 2>/dev/null; then + sed -i 's|^VUE_APP_DEFAULT_LANG=.*|VUE_APP_DEFAULT_LANG=$default_lang|' .env + else + echo 'VUE_APP_DEFAULT_LANG=$default_lang' >> .env + fi + " 2>/dev/null || true + log_success "已配置容器内 VUE_APP_DEFAULT_LANG=$default_lang" + fi + fi + fi +} + +# =========================================== +# 编译 ECShopX_admin-frontend +# =========================================== + +build_admin() { + if [ "$SKIP_ADMIN" = true ]; then + log_info "跳过 ECShopX_admin-frontend 编译(--skip-admin)" + return 0 + fi + + ADMIN_DIR="$PARENT_DIR/ECShopX_admin-frontend" + + if [ ! -d "$ADMIN_DIR" ]; then + log_warning "ECShopX_admin-frontend 目录不存在,跳过编译" + return 0 + fi + + log_info "==========================================" + log_info "开始编译 ECShopX_admin-frontend(管理后台)..." + log_info "==========================================" + + if [ ! -f "$ADMIN_DIR/package.json" ]; then + log_error "ECShopX_admin-frontend/package.json 不存在" + return 1 + fi + + # 检查是否已有编译产物 + if [ -d "$ADMIN_DIR/dist" ] && [ -f "$ADMIN_DIR/dist/index.html" ]; then + log_info "检测到已有编译产物,跳过编译" + log_info "如需重新编译,请删除 ECShopX_admin-frontend/dist 目录" + return 0 + fi + + # 检查容器内目录是否存在并确保正确挂载 + log_info "检查容器内目录挂载状态..." + if ! check_container_directory "/data/httpd/ECShopX_admin-frontend" "$ADMIN_DIR" "ECShopX_admin-frontend"; then + return 1 + fi + + # 确认默认语言(如果还未选择) + if [ -z "$SELECTED_LANG" ]; then + echo "" + log_info "请选择默认语言:" + log_info " 1) 中文 (zhcn)" + log_info " 2) 英文 (en)" + echo "" + while true; do + read -p "请输入选项 (1 或 2,默认: 1): " LANG_CHOICE + LANG_CHOICE=${LANG_CHOICE:-1} + if [ "$LANG_CHOICE" = "1" ] || [ "$LANG_CHOICE" = "zhcn" ] || [ "$LANG_CHOICE" = "zh" ]; then + SELECTED_LANG="zhcn" + break + elif [ "$LANG_CHOICE" = "2" ] || [ "$LANG_CHOICE" = "en" ] || [ "$LANG_CHOICE" = "english" ]; then + SELECTED_LANG="en" + break + else + log_error "无效的选项,请输入 1 或 2" + fi + done + echo "" + log_info "已选择默认语言: $SELECTED_LANG" + echo "" + else + log_info "复用已选择的默认语言: $SELECTED_LANG" + fi + + # 配置前端项目的 .env 文件 + log_info "配置 ECShopX_admin-frontend 的 .env 文件..." + configure_frontend_env "$ADMIN_DIR" "ECShopX_admin-frontend" "http://localhost:8080/api/" "" "$SELECTED_LANG" + + log_info "安装 npm 依赖..." + # 使用绝对路径并先验证目录存在 + docker exec "$CONTAINER_NAME" sh -c " + if [ ! -d /data/httpd/ECShopX_admin-frontend ]; then + echo '错误: 目录不存在' + exit 1 + fi + cd /data/httpd/ECShopX_admin-frontend || exit 1 + npm install --legacy-peer-deps + " > /tmp/npm_admin_output.log 2>&1 & + local npm_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $npm_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 安装 ECShopX_admin-frontend npm 依赖中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $npm_pid + local npm_exit=$? + + if [ $npm_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} ECShopX_admin-frontend npm install 失败" + printf "%50s" "" + echo "" + cat /tmp/npm_admin_output.log 2>/dev/null | tail -20 + log_info "请检查容器内目录状态: docker exec $CONTAINER_NAME ls -la /data/httpd/ECShopX_admin-frontend" + return 1 + else + printf "\r${GREEN}[SUCCESS]${NC} ECShopX_admin-frontend npm 依赖安装完成" + printf "%50s" "" + echo "" + fi + + # 提示用户选择业务模式 + echo "" + log_info "请选择业务模式:" + log_info " 1) BBC (多商户入驻电商平台模式)" + log_info " 2) B2C (线上商城、O2O云店、内购商城、供应链线上商城等模式)" + echo "" + while true; do + read -p "请输入选项 (1 或 2,默认: 1): " BUILD_MODE + BUILD_MODE=${BUILD_MODE:-1} + if [ "$BUILD_MODE" = "1" ] || [ "$BUILD_MODE" = "bbc" ]; then + BUILD_CMD="build:bbc" + BUILD_MODE_NAME="BBC (B2B2C)" + SELECTED_PLATFORM="platform" + break + elif [ "$BUILD_MODE" = "2" ] || [ "$BUILD_MODE" = "b2c" ]; then + BUILD_CMD="build:b2c" + BUILD_MODE_NAME="B2C" + SELECTED_PLATFORM="standard" + break + else + log_error "无效的选项,请输入 1 或 2" + fi + done + echo "" + log_info "已选择业务模式: $BUILD_MODE_NAME" + echo "" + + log_info "开始前端环境编译" + log_info "编译时长依赖本地硬件性能,耗时较长请耐心等待" + log_info "举列:Mac M2芯片预计整体耗时15分钟" + echo "" + + log_info "执行编译命令: npm run $BUILD_CMD" + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX_admin-frontend && npm run $BUILD_CMD" > /tmp/build_admin_output.log 2>&1 & + local build_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $build_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 编译 ECShopX_admin-frontend 中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $build_pid + local build_exit=$? + + if [ $build_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} ECShopX_admin-frontend 编译失败" + printf "%50s" "" + echo "" + cat /tmp/build_admin_output.log 2>/dev/null | tail -20 + return 1 + else + printf "\r${GREEN}[SUCCESS]${NC} ECShopX_admin-frontend 编译完成" + printf "%50s" "" + echo "" + fi + + if docker exec "$CONTAINER_NAME" sh -c "[ -f /data/httpd/ECShopX_admin-frontend/dist/index.html ]"; then + log_success "ECShopX_admin-frontend 编译成功" + return 0 + else + log_error "ECShopX_admin-frontend 编译输出不完整" + return 1 + fi +} + +# =========================================== +# 编译 ECShopX_desktop-frontend +# =========================================== + +build_pc() { + if [ "$SKIP_PC" = true ]; then + log_info "跳过 ECShopX_desktop-frontend 编译(--skip-pc)" + return 0 + fi + + PC_DIR="$PARENT_DIR/ECShopX_desktop-frontend" + + if [ ! -d "$PC_DIR" ]; then + log_warning "ECShopX_desktop-frontend 目录不存在,跳过编译" + return 0 + fi + + log_info "==========================================" + log_info "开始编译 ECShopX_desktop-frontend(PC前端)..." + log_info "==========================================" + + if [ ! -f "$PC_DIR/package.json" ]; then + log_error "ECShopX_desktop-frontend/package.json 不存在" + return 1 + fi + + # 检查是否已有编译产物(Nuxt项目编译后生成.nuxt或.output目录) + if docker exec "$CONTAINER_NAME" sh -c "[ -d /data/httpd/ECShopX_desktop-frontend/.nuxt ]" 2>/dev/null || \ + docker exec "$CONTAINER_NAME" sh -c "[ -d /data/httpd/ECShopX_desktop-frontend/.output ]" 2>/dev/null || \ + [ -d "$PC_DIR/.nuxt" ] || [ -d "$PC_DIR/.output" ]; then + log_info "检测到已有编译产物,跳过编译" + log_info "如需重新编译,请删除 ECShopX_desktop-frontend/.nuxt 或 .output 目录" + # 即使跳过编译,也需要启动Nuxt服务 + need_build=false + else + need_build=true + fi + + # 检查容器内目录是否存在并确保正确挂载 + log_info "检查容器内目录挂载状态..." + if ! check_container_directory "/data/httpd/ECShopX_desktop-frontend" "$PC_DIR" "ECShopX_desktop-frontend"; then + return 1 + fi + + # 如果跳过编译,直接启动Nuxt服务,不需要确认语言 + if [ "$need_build" = false ]; then + # 启动 Nuxt 服务 + log_info "启动 Nuxt 服务(监听3000端口)..." + + # 检查是否已有Nuxt进程在运行 + if docker exec "$CONTAINER_NAME" sh -c "pgrep -f 'nuxt.*3000\|node.*nuxt' > /dev/null" 2>/dev/null; then + log_info "Nuxt 服务已在运行" + else + # 启动Nuxt服务 + if docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX_desktop-frontend && npm run | grep -q 'start'" 2>/dev/null; then + docker exec -d "$CONTAINER_NAME" sh -c " + cd /data/httpd/ECShopX_desktop-frontend && \ + PORT=3000 HOST=0.0.0.0 nohup npm run start > /var/log/nuxt.log 2>&1 & + " 2>/dev/null || true + else + docker exec -d "$CONTAINER_NAME" sh -c " + cd /data/httpd/ECShopX_desktop-frontend && \ + PORT=3000 HOST=0.0.0.0 nohup npm run dev > /var/log/nuxt.log 2>&1 & + " 2>/dev/null || true + fi + + # 等待Nuxt服务启动 + sleep 3 + fi + + # 重新加载nginx配置 + docker exec "$CONTAINER_NAME" sh -c "nginx -s reload" 2>/dev/null || true + return 0 + fi + + # 只有在需要编译时才确认默认语言和配置.env + if [ "$need_build" = true ]; then + # 确认默认语言(如果还未选择) + if [ -z "$SELECTED_LANG" ]; then + echo "" + log_info "请选择默认语言:" + log_info " 1) 中文 (zhcn)" + log_info " 2) 英文 (en)" + echo "" + while true; do + read -p "请输入选项 (1 或 2,默认: 1): " LANG_CHOICE + LANG_CHOICE=${LANG_CHOICE:-1} + if [ "$LANG_CHOICE" = "1" ] || [ "$LANG_CHOICE" = "zhcn" ] || [ "$LANG_CHOICE" = "zh" ]; then + SELECTED_LANG="zhcn" + break + elif [ "$LANG_CHOICE" = "2" ] || [ "$LANG_CHOICE" = "en" ] || [ "$LANG_CHOICE" = "english" ]; then + SELECTED_LANG="en" + break + else + log_error "无效的选项,请输入 1 或 2" + fi + done + echo "" + log_info "已选择默认语言: $SELECTED_LANG" + echo "" + else + log_info "复用已选择的默认语言: $SELECTED_LANG" + fi + + # 配置前端项目的 .env 文件 + log_info "配置 ECShopX_desktop-frontend 的 .env 文件..." + configure_frontend_env "$PC_DIR" "ECShopX_desktop-frontend" "http://localhost:8080" "" "$SELECTED_LANG" + + log_info "安装 npm 依赖..." + # 使用绝对路径并先验证目录存在 + docker exec "$CONTAINER_NAME" sh -c " + if [ ! -d /data/httpd/ECShopX_desktop-frontend ]; then + echo '错误: 目录不存在' + exit 1 + fi + cd /data/httpd/ECShopX_desktop-frontend || exit 1 + npm install --legacy-peer-deps + " > /tmp/npm_pc_output.log 2>&1 & + local npm_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $npm_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 安装 ECShopX_desktop-frontend npm 依赖中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $npm_pid + local npm_exit=$? + + if [ $npm_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} ECShopX_desktop-frontend npm install 失败" + printf "%50s" "" + echo "" + cat /tmp/npm_pc_output.log 2>/dev/null | tail -20 + log_info "请检查容器内目录状态: docker exec $CONTAINER_NAME ls -la /data/httpd/ECShopX_desktop-frontend" + return 1 + else + printf "\r${GREEN}[SUCCESS]${NC} ECShopX_desktop-frontend npm 依赖安装完成" + printf "%50s" "" + echo "" + fi + + log_info "执行编译(npm run build)..." + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX_desktop-frontend && npm run build" > /tmp/build_pc_output.log 2>&1 & + local build_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $build_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 编译 ECShopX_desktop-frontend 中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $build_pid + local build_exit=$? + + if [ $build_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} ECShopX_desktop-frontend 编译失败" + printf "%50s" "" + echo "" + cat /tmp/build_pc_output.log 2>/dev/null | tail -20 + return 1 + else + printf "\r${GREEN}[SUCCESS]${NC} ECShopX_desktop-frontend 编译完成" + printf "%50s" "" + echo "" + fi + # 验证编译产物 + if ! docker exec "$CONTAINER_NAME" sh -c "[ -d /data/httpd/ECShopX_desktop-frontend/.nuxt ] || [ -d /data/httpd/ECShopX_desktop-frontend/.output ]" 2>/dev/null; then + log_error "ECShopX_desktop-frontend 编译输出不完整" + return 1 + fi + fi + + # 检查编译产物(Nuxt项目编译后生成.nuxt或.output目录) + if docker exec "$CONTAINER_NAME" sh -c "[ -d /data/httpd/ECShopX_desktop-frontend/.nuxt ] || [ -d /data/httpd/ECShopX_desktop-frontend/.output ]" 2>/dev/null; then + log_success "ECShopX_desktop-frontend 编译成功" + + # 启动 Nuxt 服务 + log_info "启动 Nuxt 服务(监听3000端口)..." + + # 检查是否已有Nuxt进程在运行 + if docker exec "$CONTAINER_NAME" sh -c "pgrep -f 'nuxt.*3000\|node.*nuxt' > /dev/null" 2>/dev/null; then + log_info "Nuxt 服务已在运行,重启服务..." + docker exec "$CONTAINER_NAME" sh -c "pkill -f 'nuxt.*3000\|node.*nuxt'" 2>/dev/null || true + sleep 2 + fi + + # 在后台启动Nuxt服务 + # 优先使用生产模式(npm run start),如果不存在则使用开发模式(npm run dev) + log_info "检查可用的启动命令..." + if docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX_desktop-frontend && npm run | grep -q 'start'" 2>/dev/null; then + log_info "使用生产模式启动(npm run start)..." + docker exec -d "$CONTAINER_NAME" sh -c " + cd /data/httpd/ECShopX_desktop-frontend && \ + PORT=3000 HOST=0.0.0.0 nohup npm run start > /var/log/nuxt.log 2>&1 & + " || { + log_error "Nuxt 服务启动失败" + log_info "请检查日志: docker exec $CONTAINER_NAME tail -f /var/log/nuxt.log" + return 1 + } + else + log_info "使用开发模式启动(npm run dev)..." + docker exec -d "$CONTAINER_NAME" sh -c " + cd /data/httpd/ECShopX_desktop-frontend && \ + PORT=3000 HOST=0.0.0.0 nohup npm run dev > /var/log/nuxt.log 2>&1 & + " || { + log_error "Nuxt 服务启动失败" + log_info "请检查日志: docker exec $CONTAINER_NAME tail -f /var/log/nuxt.log" + return 1 + } + fi + + # 等待Nuxt服务启动 + log_info "等待 Nuxt 服务启动..." + local nuxt_ready=false + for i in {1..30}; do + if docker exec "$CONTAINER_NAME" sh -c "curl -s http://127.0.0.1:3000 > /dev/null" 2>/dev/null; then + nuxt_ready=true + break + fi + sleep 2 + if [ $((i % 5)) -eq 0 ]; then + printf "\r${CYAN}[INFO]${NC} 等待 Nuxt 服务启动... ($i/30)" + fi + done + + if [ "$nuxt_ready" = true ]; then + printf "\r${GREEN}[SUCCESS]${NC} Nuxt 服务已启动并监听3000端口" + printf "%50s" "" + echo "" + if [ "$INSTALLED_VSHOP" = true ]; then + log_info "H5前端访问地址: http://localhost:8081" + fi + if [ "$INSTALLED_PC" = true ]; then + log_info "PC前端访问地址: http://localhost:8082" + fi + else + printf "\r${YELLOW}[WARNING]${NC} Nuxt 服务启动超时,但可能仍在启动中" + printf "%50s" "" + echo "" + log_info "请检查日志: docker exec $CONTAINER_NAME tail -f /var/log/nuxt.log" + if [ "$INSTALLED_VSHOP" = true ]; then + log_info "H5前端访问地址: http://localhost:8081" + fi + if [ "$INSTALLED_PC" = true ]; then + log_info "PC前端访问地址: http://localhost:8082" + fi + fi + + # 重新加载nginx配置以确保8082端口配置生效 + log_info "重新加载 Nginx 配置..." + docker exec "$CONTAINER_NAME" sh -c "nginx -s reload" 2>/dev/null || { + log_warning "Nginx 配置重载失败,可能需要重启容器" + } + else + log_error "ECShopX_desktop-frontend 编译输出不完整" + return 1 + fi +} + +# =========================================== +# 编译 ECShopX_mobile-frontend +# =========================================== + +build_vshop() { + if [ "$SKIP_VSHOP" = true ]; then + log_info "跳过 ECShopX_mobile-frontend 编译(--skip-vshop)" + return 0 + fi + + VSHOP_DIR="$PARENT_DIR/ECShopX_mobile-frontend" + + if [ ! -d "$VSHOP_DIR" ]; then + log_warning "ECShopX_mobile-frontend 目录不存在,跳过编译" + return 0 + fi + + log_info "==========================================" + log_info "开始编译 ECShopX_mobile-frontend(H5前端)..." + log_info "==========================================" + + if [ ! -f "$VSHOP_DIR/package.json" ]; then + log_error "ECShopX_mobile-frontend/package.json 不存在" + return 1 + fi + + # 检查是否已有编译产物 + if [ -d "$VSHOP_DIR/dist" ]; then + log_info "检测到已有编译产物,跳过编译" + log_info "如需重新编译,请删除 ECShopX_mobile-frontend/dist 目录" + return 0 + fi + + # 检查容器内目录是否存在并确保正确挂载 + log_info "检查容器内目录挂载状态..." + if ! check_container_directory "/data/httpd/ECShopX_mobile-frontend" "$VSHOP_DIR" "ECShopX_mobile-frontend"; then + return 1 + fi + + # 确认业务模式(如果 ECShopX_admin-frontend 中已经确认过,则复用;否则重新确认) + if [ -z "$SELECTED_PLATFORM" ]; then + echo "" + log_info "请选择业务模式:" + log_info " 1) BBC (多商户入驻电商平台模式)" + log_info " 2) B2C (线上商城、O2O云店、内购商城、供应链线上商城等模式)" + echo "" + while true; do + read -p "请输入选项 (1 或 2,默认: 1): " BUILD_MODE + BUILD_MODE=${BUILD_MODE:-1} + if [ "$BUILD_MODE" = "1" ] || [ "$BUILD_MODE" = "bbc" ]; then + SELECTED_PLATFORM="platform" + BUILD_MODE_NAME="BBC (B2B2C)" + break + elif [ "$BUILD_MODE" = "2" ] || [ "$BUILD_MODE" = "b2c" ]; then + SELECTED_PLATFORM="standard" + BUILD_MODE_NAME="B2C" + break + else + log_error "无效的选项,请输入 1 或 2" + fi + done + echo "" + log_info "已选择业务模式: $BUILD_MODE_NAME" + echo "" + else + # 复用已选择的业务模式 + if [ "$SELECTED_PLATFORM" = "platform" ]; then + BUILD_MODE_NAME="BBC (B2B2C)" + else + BUILD_MODE_NAME="B2C" + fi + log_info "复用已选择的业务模式: $BUILD_MODE_NAME" + fi + + # 确认默认语言(如果还未选择) + if [ -z "$SELECTED_LANG" ]; then + echo "" + log_info "请选择默认语言:" + log_info " 1) 中文 (zhcn)" + log_info " 2) 英文 (en)" + echo "" + while true; do + read -p "请输入选项 (1 或 2,默认: 1): " LANG_CHOICE + LANG_CHOICE=${LANG_CHOICE:-1} + if [ "$LANG_CHOICE" = "1" ] || [ "$LANG_CHOICE" = "zhcn" ] || [ "$LANG_CHOICE" = "zh" ]; then + SELECTED_LANG="zhcn" + break + elif [ "$LANG_CHOICE" = "2" ] || [ "$LANG_CHOICE" = "en" ] || [ "$LANG_CHOICE" = "english" ]; then + SELECTED_LANG="en" + break + else + log_error "无效的选项,请输入 1 或 2" + fi + done + echo "" + log_info "已选择默认语言: $SELECTED_LANG" + echo "" + else + log_info "复用已选择的默认语言: $SELECTED_LANG" + fi + + # 配置前端项目的 .env 文件 + log_info "配置 ECShopX_mobile-frontend 的 .env 文件..." + configure_frontend_env "$VSHOP_DIR" "ECShopX_mobile-frontend" "http://localhost:8080/api/h5app/wxapp" "$SELECTED_PLATFORM" "$SELECTED_LANG" + + log_info "安装 npm 依赖..." + # 使用绝对路径并先验证目录存在 + docker exec "$CONTAINER_NAME" sh -c " + if [ ! -d /data/httpd/ECShopX_mobile-frontend ]; then + echo '错误: 目录不存在' + exit 1 + fi + cd /data/httpd/ECShopX_mobile-frontend || exit 1 + npm install --legacy-peer-deps + " > /tmp/npm_vshop_output.log 2>&1 & + local npm_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $npm_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 安装 ECShopX_mobile-frontend npm 依赖中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $npm_pid + local npm_exit=$? + + if [ $npm_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} ECShopX_mobile-frontend npm install 失败" + printf "%50s" "" + echo "" + cat /tmp/npm_vshop_output.log 2>/dev/null | tail -20 + log_info "请检查容器内目录状态: docker exec $CONTAINER_NAME ls -la /data/httpd/ECShopX_mobile-frontend" + return 1 + else + printf "\r${GREEN}[SUCCESS]${NC} ECShopX_mobile-frontend npm 依赖安装完成" + printf "%50s" "" + echo "" + fi + + log_info "执行编译(npm run build:h5)..." + docker exec "$CONTAINER_NAME" sh -c "cd /data/httpd/ECShopX_mobile-frontend && npm run build:h5" > /tmp/build_vshop_output.log 2>&1 & + local build_pid=$! + + # 显示进度动画 + local spinstr='|/-\' + while kill -0 $build_pid 2>/dev/null; do + local temp=${spinstr#?} + printf "\r${CYAN}[INFO]${NC} 编译 ECShopX_mobile-frontend 中 ${spinstr:0:1}" + spinstr=$temp${spinstr%"$temp"} + sleep 0.2 + done + wait $build_pid + local build_exit=$? + + if [ $build_exit -ne 0 ]; then + printf "\r${RED}[ERROR]${NC} ECShopX_mobile-frontend 编译失败" + printf "%50s" "" + echo "" + cat /tmp/build_vshop_output.log 2>/dev/null | tail -20 + return 1 + else + printf "\r${GREEN}[SUCCESS]${NC} ECShopX_mobile-frontend 编译完成" + printf "%50s" "" + echo "" + fi + + if docker exec "$CONTAINER_NAME" sh -c "[ -d /data/httpd/ECShopX_mobile-frontend/dist ]"; then + log_success "ECShopX_mobile-frontend 编译成功" + return 0 + else + log_error "ECShopX_mobile-frontend 编译输出目录不存在" + return 1 + fi +} + +# =========================================== +# 显示完成信息 +# =========================================== + +show_success_info() { + # 计算执行时间 + END_TIME=$(date +%s) + DURATION=$((END_TIME - START_TIME)) + MINUTES=$((DURATION / 60)) + SECONDS=$((DURATION % 60)) + + echo "" + log_success "==========================================" + log_success "恭喜你,安装成功" + log_success "温馨提示:移动商城、PC商城前端显示空白,并非系统问题,需前往管理后台配置模板数据。" + + # 根据安装的项目显示温馨提示 + if [ "$INSTALLED_VSHOP" = true ] || [ "$INSTALLED_PC" = true ]; then + local tip_msg="温馨提示:" + if [ "$INSTALLED_VSHOP" = true ] && [ "$INSTALLED_PC" = true ]; then + tip_msg="${tip_msg}移动商城、PC商城前端显示空白,并非系统问题,需前往管理后台配置模板数据。" + elif [ "$INSTALLED_VSHOP" = true ]; then + tip_msg="${tip_msg}移动商城前端显示空白,并非系统问题,需前往管理后台配置模板数据。" + elif [ "$INSTALLED_PC" = true ]; then + tip_msg="${tip_msg}PC商城前端显示空白,并非系统问题,需前往管理后台配置模板数据。" + fi + log_success "$tip_msg" + fi + + log_success "==========================================" + echo "" + log_info "服务信息:" + + if [ "$INSTALLED_ADMIN" = true ]; then + log_info " 管理后台: http://localhost:8080" + fi + + if [ "$INSTALLED_VSHOP" = true ]; then + log_info " H5前端: http://localhost:8081" + fi + + if [ "$INSTALLED_PC" = true ]; then + log_info " PC前端: http://localhost:8082" + fi + + log_info " API 接口: http://localhost:8080/api/" + log_info " MySQL: localhost:3306 (用户: $MYSQL_USER, 密码: $MYSQL_PASSWORD)" + log_info " Redis: localhost:6379 (密码: $REDIS_PASSWORD)" + echo "" + + # 检查微信小程序编译产物(仅在安装了移动商城时显示) + if [ "$INSTALLED_VSHOP" = true ]; then + VSHOP_DIR="$PARENT_DIR/ECShopX_mobile-frontend" + if [ -d "$VSHOP_DIR/dist" ]; then + log_info "微信小程序:" + log_info " 微信开发者工具打开目录: $VSHOP_DIR/dist" + echo "" + fi + fi + log_info "常用命令:" + log_info " 查看日志: $DOCKER_COMPOSE_CMD -f $DOCKER_COMPOSE_FILE logs -f" + log_info " 服务状态: docker exec $CONTAINER_NAME supervisorctl status" + log_info " 进入容器: docker exec -it $CONTAINER_NAME sh" + log_info " 停止服务: $DOCKER_COMPOSE_CMD -f $DOCKER_COMPOSE_FILE down" + log_info " 重启服务: $DOCKER_COMPOSE_CMD -f $DOCKER_COMPOSE_FILE restart" + log_info " 重新构建: $0 --rebuild" + echo "" + log_info "执行时间: ${MINUTES}分${SECONDS}秒" + log_success "==========================================" +} + +# =========================================== +# 主函数 +# =========================================== + +main() { + # 解析命令行参数 + parse_args "$@" + + echo "==========================================" + echo " ECShopX 开发环境设置 (Docker)" + echo " 支持: ECShopX / ECShopX_admin-frontend / ECShopX_mobile-frontend / ECShopX_desktop-frontend" + echo "==========================================" + echo "" + + detect_os + check_docker + + # 检查并克隆前端项目(在启动容器之前) + check_and_clone_frontend + + # 检查容器状态 + if check_container_status; then + run_docker + fi + + # 配置 PHP 应用 + configure_env + configure_application + + # 编译前端项目 + build_admin || log_warning "管理后台(ECShopX_admin-frontend)编译未完成" + build_vshop || log_warning "移动商城(ECShopX_mobile-frontend)编译未完成" + build_pc || log_warning "PC商城(ECShopX_desktop-frontend)编译未完成" + + # Show success info + show_success_info +} + +# 执行主函数 +main "$@" diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..fb86649 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,64 @@ +version: '3.8' + +services: + ecshopx-dev: + build: + context: . + dockerfile: docker-dev/Dockerfile + args: + BUILDKIT_INLINE_CACHE: 1 + image: ecshopx-dev + container_name: ecshopx-dev + restart: unless-stopped + ports: + - "8080:8080" # Nginx (容器8080端口映射到主机8080端口) + - "8081:8081" # Nginx H5前端服务 (容器8081端口映射到主机8081端口) + - "8082:8082" # Nginx PC前端代理 (容器8082端口映射到主机8082端口) + volumes: + # 分别挂载四个项目目录 + - .:/data/httpd/ECShopX + - ../ECShopX_admin-frontend:/data/httpd/ECShopX_admin-frontend + - ../ECShopX_mobile-frontend:/data/httpd/ECShopX_mobile-frontend + - ../ECShopX_desktop-frontend:/data/httpd/ECShopX_desktop-frontend + # 数据持久化 + - mysql_data:/var/lib/mysql + - redis_data:/var/lib/redis + environment: + # PHP-FPM 配置 + - FPM_LISTEN=127.0.0.1:9000 + - FPM_PM=dynamic + - FPM_PM_MAX_CHILDREN=40 + - FPM_PM_MIN_SPARE_SERVERS=5 + - FPM_PM_MAX_SPARE_SERVERS=10 + - FPM_PHP_ADMIN_VALUE_MEMORY_LIMIT=128M + # MySQL 配置 + - MYSQL_ROOT_PASSWORD=rootpassword + - MYSQL_DATABASE=ecshopx + - MYSQL_USER=ecshopx + - MYSQL_PASSWORD=ecshopx + # Redis 配置 + - REDIS_PASSWORD=redispassword + # 应用配置(会写入 .env) + - DB_HOST=127.0.0.1 + - DB_PORT=3306 + - DB_DATABASE=ecshopx + - DB_USERNAME=ecshopx + - DB_PASSWORD=ecshopx + - REDIS_HOST=127.0.0.1 + - REDIS_PORT=6379 + - REDIS_DATABASE=0 + # 时区 + - TZ=Asia/Shanghai + networks: + - ecshopx-dev-network + +volumes: + mysql_data: + name: ecshopx-dev-mysql + redis_data: + name: ecshopx-dev-redis + +networks: + ecshopx-dev-network: + name: ecshopx-dev-net + driver: bridge diff --git a/docker-dev/Dockerfile b/docker-dev/Dockerfile new file mode 100644 index 0000000..d13363e --- /dev/null +++ b/docker-dev/Dockerfile @@ -0,0 +1,83 @@ +FROM registry.cn-hangzhou.aliyuncs.com/shopex_company/ecshopex-php:ecx-7.4.32-fpm-alpine3.16 + +# 安装 MySQL、Redis、Nginx、Supervisor 和 Node.js +# 基础镜像已包含 PHP 7.4.32 和 FPM,只需安装其他服务 +RUN apk add --no-cache \ + # MySQL (MariaDB) + mariadb \ + mariadb-client \ + # Redis + redis \ + # Nginx + nginx \ + # Supervisor + supervisor \ + # Node.js 16.x(从 Alpine 官方源安装) + nodejs=16.20.2-r0 \ + npm \ + # 其他工具 + bash \ + curl \ + tzdata \ + ca-certificates \ + # Node.js 编译依赖 + python3 \ + make \ + g++ \ + && rm -rf /var/cache/apk/* \ + && npm config set registry https://registry.npmmirror.com \ + && node --version && npm --version + +# 设置时区 +ENV TZ=Asia/Shanghai +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# 创建必要的目录和用户 +RUN mkdir -p /var/log/supervisor \ + && mkdir -p /etc/supervisor/conf.d \ + && mkdir -p /var/lib/mysql \ + && mkdir -p /var/run/mysqld \ + && mkdir -p /var/lib/redis \ + && mkdir -p /var/log/redis \ + && mkdir -p /var/run/redis \ + && mkdir -p /var/log/nginx \ + && mkdir -p /var/log/php-fpm \ + && mkdir -p /run/php \ + && mkdir -p /var/lib/nginx/tmp/client_body \ + && mkdir -p /var/lib/nginx/tmp/proxy \ + && mkdir -p /var/lib/nginx/tmp/fastcgi \ + && mkdir -p /var/lib/nginx/tmp/uwsgi \ + && mkdir -p /var/lib/nginx/tmp/scgi \ + && mkdir -p /data/httpd/ECShopX \ + && mkdir -p /data/httpd/ECShopX_admin-frontend \ + && mkdir -p /data/httpd/ECShopX_mobile-frontend \ + && mkdir -p /data/httpd/ECShopX_desktop-frontend \ + && (id -u redis >/dev/null 2>&1 || adduser -D -s /sbin/nologin redis) \ + && (id -u www-data >/dev/null 2>&1 || (addgroup -g 82 www-data && adduser -D -s /sbin/nologin -u 82 -G www-data www-data)) \ + && chown -R redis:redis /var/lib/redis /var/log/redis /var/run/redis \ + && chown -R www-data:www-data /var/log/php-fpm /run/php /var/lib/nginx /var/log/nginx + +# 只复制配置文件(项目代码通过 volumes 挂载) +COPY docker-dev/supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY docker-dev/docker-entrypoint.sh /usr/bin/entrypoint.sh +COPY docker-dev/nginx.conf /etc/nginx/nginx.conf +COPY docker-dev/php-fpm.conf /tmp/php-fpm-custom.conf +COPY docker-dev/mysql.cnf /etc/my.cnf + +# 创建 MySQL 配置链接 +RUN mkdir -p /etc/mysql && \ + (ln -sf /etc/my.cnf /etc/mysql/my.cnf 2>/dev/null || true) + +# 设置权限 +RUN chmod +x /usr/bin/entrypoint.sh \ + && chown -R mysql:mysql /var/lib/mysql \ + && chown -R mysql:mysql /var/run/mysqld + +# 工作目录 +WORKDIR /data/httpd + +# 暴露端口 +EXPOSE 80 3306 6379 + +ENTRYPOINT ["/usr/bin/entrypoint.sh"] +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf", "-n"] diff --git a/docker-dev/docker-entrypoint.sh b/docker-dev/docker-entrypoint.sh new file mode 100755 index 0000000..c7a683e --- /dev/null +++ b/docker-dev/docker-entrypoint.sh @@ -0,0 +1,281 @@ +#!/bin/sh +# ECShopX API Docker 容器启动脚本 +# 负责初始化服务、配置环境和启动 Supervisor +# 注意:某些非关键步骤允许失败(使用 || true),关键步骤失败会退出 + +# 设置时区 +if [ -z "$TZ" ]; then + export TZ="Asia/Shanghai" +fi +if ! ln -snf /usr/share/zoneinfo/$TZ /etc/localtime || ! echo "$TZ" > /etc/timezone; then + echo "警告: 无法设置时区,使用默认值" +fi + +# 配置 PHP-FPM(根据基础镜像的实际路径) +PHP_FPM_CONF_DIR="" +if [ -d "/usr/local/etc/php-fpm.d" ]; then + PHP_FPM_CONF_DIR="/usr/local/etc/php-fpm.d" +elif [ -d "/etc/php7/php-fpm.d" ]; then + PHP_FPM_CONF_DIR="/etc/php7/php-fpm.d" +elif [ -d "/etc/php-fpm.d" ]; then + PHP_FPM_CONF_DIR="/etc/php-fpm.d" +fi + +if [ -n "$PHP_FPM_CONF_DIR" ] && [ -f "/tmp/php-fpm-custom.conf" ]; then + if cp /tmp/php-fpm-custom.conf "$PHP_FPM_CONF_DIR/www.conf"; then + echo "✓ PHP-FPM 配置已复制到: $PHP_FPM_CONF_DIR/www.conf" + else + echo "✗ 错误: 无法复制 PHP-FPM 配置文件" + exit 1 + fi +fi + +# 检测 PHP-FPM 可执行文件路径(用于 supervisor 配置) +PHP_FPM_BIN="" +if [ -f "/usr/local/sbin/php-fpm" ]; then + PHP_FPM_BIN="/usr/local/sbin/php-fpm" +elif [ -f "/usr/sbin/php-fpm7" ]; then + PHP_FPM_BIN="/usr/sbin/php-fpm7" +elif [ -f "/usr/sbin/php-fpm" ]; then + PHP_FPM_BIN="/usr/sbin/php-fpm" +elif command -v php-fpm &> /dev/null; then + PHP_FPM_BIN=$(command -v php-fpm) +fi + +if [ -n "$PHP_FPM_BIN" ]; then + # 更新 supervisor 配置中的 PHP-FPM 路径 + SUPERVISOR_CONF="/etc/supervisor/conf.d/supervisord.conf" + if [ -f "$SUPERVISOR_CONF" ]; then + # 使用 sed 更新配置(Alpine Linux 兼容语法) + if sed -i "s|^command=.*php-fpm.*|command=$PHP_FPM_BIN -F|" "$SUPERVISOR_CONF"; then + echo "✓ PHP-FPM 路径已设置为: $PHP_FPM_BIN -F" + else + echo "警告: 无法更新 supervisord.conf 中的 PHP-FPM 路径,使用默认配置" + fi + else + echo "✗ 错误: $SUPERVISOR_CONF 文件不存在" + echo "检查文件位置..." + find /etc -name "supervisord.conf" 2>/dev/null || echo "未找到 supervisord.conf" + exit 1 + fi +else + echo "警告: 未找到 PHP-FPM 可执行文件,supervisor 配置将使用默认路径" +fi + +# 设置环境变量默认值(使用更简洁的语法) +export FPM_LISTEN="${FPM_LISTEN:-127.0.0.1:9000}" +export FPM_PM="${FPM_PM:-dynamic}" +export FPM_PM_MAX_CHILDREN="${FPM_PM_MAX_CHILDREN:-40}" +export FPM_PM_MIN_SPARE_SERVERS="${FPM_PM_MIN_SPARE_SERVERS:-1}" +export FPM_PM_MAX_SPARE_SERVERS="${FPM_PM_MAX_SPARE_SERVERS:-3}" +export FPM_PHP_ADMIN_VALUE_MEMORY_LIMIT="${FPM_PHP_ADMIN_VALUE_MEMORY_LIMIT:-64M}" + +export MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-rootpassword}" +export MYSQL_DATABASE="${MYSQL_DATABASE:-ecshopx}" +export MYSQL_USER="${MYSQL_USER:-ecshopx}" +export MYSQL_PASSWORD="${MYSQL_PASSWORD:-ecshopx}" + +export REDIS_PASSWORD="${REDIS_PASSWORD:-redispassword}" + +# 初始化 MySQL(如果数据目录为空或没有系统表) +if [ ! -d "/var/lib/mysql/mysql" ] && [ ! -d "/var/lib/mysql/mariadb" ]; then + echo "==========================================" + echo "初始化 MySQL 数据目录..." + echo "==========================================" + + if ! mysql_install_db --user=mysql --datadir=/var/lib/mysql --skip-test-db --auth-root-authentication-method=normal >/dev/null 2>&1; then + echo "✗ 错误: MySQL 数据目录初始化失败" + exit 1 + fi + + # 启动 MySQL 以创建数据库和用户 + echo "启动临时 MySQL 进程..." + mysqld_safe --defaults-file=/etc/my.cnf --user=mysql --datadir=/var/lib/mysql --skip-networking --socket=/var/run/mysqld/mysqld.sock >/dev/null 2>&1 & + MYSQL_PID=$! + + # 等待 MySQL 启动(最多等待 30 秒) + echo "等待 MySQL 启动..." + MYSQL_READY=false + for i in $(seq 1 30); do + if mysqladmin ping --socket=/var/run/mysqld/mysqld.sock --silent 2>/dev/null; then + MYSQL_READY=true + break + fi + sleep 1 + done + + if [ "$MYSQL_READY" = false ]; then + echo "✗ 错误: MySQL 启动超时" + kill $MYSQL_PID 2>/dev/null || true + exit 1 + fi + + echo "✓ MySQL 已启动,创建数据库和用户..." + # 创建数据库和用户 + if ! mysql --socket=/var/run/mysqld/mysqld.sock -uroot </dev/null || true + exit 1 + fi + + # 停止 MySQL(supervisor 会重新启动) + echo "停止临时 MySQL 进程..." + mysqladmin --socket=/var/run/mysqld/mysqld.sock -uroot -p${MYSQL_ROOT_PASSWORD} shutdown 2>/dev/null || kill $MYSQL_PID 2>/dev/null || true + wait $MYSQL_PID 2>/dev/null || true + sleep 2 + echo "✓ MySQL 初始化完成" +fi + +# 配置 Redis +# 确保 Redis 用户和目录存在(Dockerfile 中已创建,这里只是确保) +if ! id -u redis >/dev/null 2>&1; then + echo "警告: Redis 用户不存在,尝试创建..." + adduser -D -s /sbin/nologin redis || { + echo "✗ 错误: 无法创建 Redis 用户" + exit 1 + } +fi +mkdir -p /var/lib/redis /var/log/redis /var/run/redis +chown -R redis:redis /var/lib/redis /var/log/redis /var/run/redis || { + echo "✗ 错误: 无法设置 Redis 目录权限" + exit 1 +} + +# 确保 Nginx 临时目录存在且有正确权限 +mkdir -p /var/lib/nginx/tmp/client_body \ + /var/lib/nginx/tmp/proxy \ + /var/lib/nginx/tmp/fastcgi \ + /var/lib/nginx/tmp/uwsgi \ + /var/lib/nginx/tmp/scgi \ + /var/log/nginx +chown -R www-data:www-data /var/lib/nginx /var/log/nginx || { + echo "警告: 无法设置 Nginx 目录权限,可能影响文件上传" +} + +# 配置 Redis 密码 +if [ -n "$REDIS_PASSWORD" ]; then + # 检查 Redis 配置文件是否存在 + if [ -f "/etc/redis.conf" ]; then + # 如果已有 requirepass 配置,替换它;否则添加 + if grep -q "^requirepass" /etc/redis.conf 2>/dev/null; then + sed -i "s/^requirepass.*/requirepass ${REDIS_PASSWORD}/" /etc/redis.conf + else + echo "requirepass ${REDIS_PASSWORD}" >> /etc/redis.conf + fi + else + # 如果配置文件不存在,创建基本配置 + cat > /etc/redis.conf < /data/httpd/ECShopX/license.zl 2>/dev/null; then + echo "✓ 许可证文件已写入" + else + echo "警告: 许可证文件解码失败" + fi +fi + +# 如果提供了命令参数,直接执行(用于 docker exec 等场景) +if [ -n "$1" ]; then + exec "$@" +fi + +# 先启动 supervisord 在后台(临时修改配置为 daemon 模式) +echo "==========================================" +echo "启动 Supervisor 管理所有服务..." +echo "==========================================" + +# 创建临时配置文件(daemon 模式) +TEMP_SUPERVISOR_CONF="/tmp/supervisord-daemon.conf" +cp /etc/supervisor/conf.d/supervisord.conf "$TEMP_SUPERVISOR_CONF" +# 修改为 daemon 模式 +sed -i 's/nodaemon=true/nodaemon=false/' "$TEMP_SUPERVISOR_CONF" 2>/dev/null || \ + sed -i 's/nodaemon = true/nodaemon = false/' "$TEMP_SUPERVISOR_CONF" 2>/dev/null || true + +# 启动 supervisord 在后台 +echo "启动后台 supervisord..." +if ! /usr/bin/supervisord -c "$TEMP_SUPERVISOR_CONF"; then + echo "✗ 错误: 无法启动 supervisord" + exit 1 +fi +echo "✓ 后台 supervisord 已启动" + +# 等待服务启动 +echo "等待服务启动..." +sleep 5 + +# 检查 supervisord 是否运行(使用临时配置文件启动的进程) +# 等待一下让 supervisord 完全启动 +sleep 2 +if ! supervisorctl -c "$TEMP_SUPERVISOR_CONF" status >/dev/null 2>&1; then + echo "警告: 无法连接到后台 supervisord,尝试继续执行..." + # 不退出,继续执行(composer 和迁移由 dev-setup.sh 处理) +fi + +# 等待 MySQL 和 Redis 就绪 +echo "等待 MySQL 和 Redis 服务就绪..." +MYSQL_READY=false +for i in $(seq 1 60); do + if mysqladmin ping --socket=/var/run/mysqld/mysqld.sock --silent 2>/dev/null || \ + mysqladmin ping -h 127.0.0.1 -u root -p${MYSQL_ROOT_PASSWORD} --silent 2>/dev/null; then + MYSQL_READY=true + echo "✓ MySQL 已就绪" + break + fi + if [ $((i % 5)) -eq 0 ]; then + echo " 等待 MySQL... ($i/60)" + fi + sleep 1 +done + +if [ "$MYSQL_READY" = false ]; then + echo "警告: MySQL 启动超时,继续执行..." +fi + +REDIS_READY=false +for i in $(seq 1 30); do + if redis-cli -a ${REDIS_PASSWORD} ping 2>/dev/null | grep -q "PONG"; then + REDIS_READY=true + echo "✓ Redis 已就绪" + break + fi + if [ $((i % 5)) -eq 0 ]; then + echo " 等待 Redis... ($i/30)" + fi + sleep 1 +done + +if [ "$REDIS_READY" = false ]; then + echo "警告: Redis 启动超时,继续执行..." +fi + +# 注意:Composer 安装和数据库迁移已移到 dev-setup.sh 脚本中执行 +# 这样可以更好地控制执行时机和错误处理 + +# 停止后台 supervisord,然后在前台启动(成为 PID 1) +echo "==========================================" +echo "切换到前台模式运行 Supervisor..." +echo "==========================================" +supervisorctl -c "$TEMP_SUPERVISOR_CONF" shutdown 2>/dev/null || pkill supervisord 2>/dev/null || true +sleep 2 + +# 使用原始配置文件在前台启动(成为 PID 1) +exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf -n diff --git a/docker-dev/mysql.cnf b/docker-dev/mysql.cnf new file mode 100644 index 0000000..4e5228e --- /dev/null +++ b/docker-dev/mysql.cnf @@ -0,0 +1,22 @@ +[mysqld] +user = mysql +pid-file = /var/run/mysqld/mysqld.pid +socket = /var/run/mysqld/mysqld.sock +datadir = /var/lib/mysql +bind-address = 0.0.0.0 +port = 3306 +character-set-server = utf8mb4 +collation-server = utf8mb4_unicode_ci +default-storage-engine = innodb +max_allowed_packet = 64M +innodb_buffer_pool_size = 256M +innodb_log_file_size = 64M +sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION + +[mysql] +default-character-set = utf8mb4 + +[client] +default-character-set = utf8mb4 +port = 3306 +socket = /var/run/mysqld/mysqld.sock diff --git a/docker-dev/nginx.conf b/docker-dev/nginx.conf new file mode 100644 index 0000000..760579b --- /dev/null +++ b/docker-dev/nginx.conf @@ -0,0 +1,197 @@ +user www-data; +worker_processes auto; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + client_max_body_size 50m; + + # 配置临时目录路径(确保目录存在且有权限) + client_body_temp_path /var/lib/nginx/tmp/client_body; + proxy_temp_path /var/lib/nginx/tmp/proxy; + fastcgi_temp_path /var/lib/nginx/tmp/fastcgi; + uwsgi_temp_path /var/lib/nginx/tmp/uwsgi; + scgi_temp_path /var/lib/nginx/tmp/scgi; + + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; + + # 前端服务(管理后台 + API 代理) + server { + listen 8080; + server_name _; + + # API 接口代理 + location /api/ { + proxy_pass http://127.0.0.1:8090; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + client_max_body_size 32m; + client_body_buffer_size 256k; + } + + # 图片资源代理(转发到 PHP 服务处理) + location /storage/ { + proxy_pass http://127.0.0.1:8090; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + client_max_body_size 32m; + client_body_buffer_size 256k; + } + + # 微信授权代理 + location /wechatAuth/ { + proxy_pass http://127.0.0.1:8090; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + client_max_body_size 32m; + client_body_buffer_size 256k; + } + + # 管理后台静态资源 + location / { + root /data/httpd/ECShopX_admin-frontend/dist/; + index index.html index.htm; + try_files $uri $uri/index.html $uri/ /index.html =404; + } + + # 安全配置 + location ~* \.(ini|sql|conf|bak)$ { + return 404; + } + + location ~* ^/(themes|images|logs|data|demo|wap_themes)/.*\.(php|php5)$ { + deny all; + } + + location ~ /\.(svn|git|)/ { + deny all; + } + } + + # PHP API 服务 + server { + listen 8090; + server_name _; + index index.html index.htm index.php; + root /data/httpd/ECShopX/public; + + location / { + try_files $uri $uri/ /index.php$is_args$args; + } + + location ~ \.php$ { + add_header 'Access-Control-Allow-Origin' '*' always; + add_header Access-Control-Allow-Headers "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"; + add_header Access-Control-Expose-Headers "Authorization"; + add_header Access-Control-Allow-Methods "DELETE, GET, HEAD, POST, PUT, OPTIONS, TRACE, PATCH"; + + if ($request_method = OPTIONS ) { + return 200; + } + + fastcgi_pass 127.0.0.1:9000; + fastcgi_read_timeout 150; + fastcgi_index index.php; + fastcgi_buffers 4 128k; + fastcgi_buffer_size 128k; + fastcgi_busy_buffers_size 128k; + fastcgi_temp_file_write_size 256k; + fastcgi_temp_path /dev/shm; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\.ht { + deny all; + } + + location ~* \.(ini|sql|conf|bak)$ { + return 404; + } + + location ~* ^/(themes|images|logs|data|demo|wap_themes)/.*\.(php|php5)$ { + deny all; + } + + location ~ /\.(svn|git|)/ { + deny all; + } + } + + # H5前端服务(微信小程序H5版本) + server { + listen 8081; + server_name _; + + # 静态文件服务 + location / { + root /data/httpd/eECShopX_mobile-frontend/dist/h5; + index index.html index.htm; + try_files $uri $uri/ /index.html =404; + } + + # 安全配置 + location ~* \.(ini|sql|conf|bak)$ { + return 404; + } + + location ~ /\.(svn|git|)/ { + deny all; + } + } + + # PC前端服务代理(Nuxt) + server { + listen 8082; + server_name _; + + # 代理到Nuxt服务(监听3000端口) + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_cache_bypass $http_upgrade; + proxy_read_timeout 300s; + proxy_connect_timeout 75s; + } + + # 安全配置 + location ~* \.(ini|sql|conf|bak)$ { + return 404; + } + + location ~ /\.(svn|git|)/ { + deny all; + } + } +} diff --git a/docker-dev/php-fpm.conf b/docker-dev/php-fpm.conf new file mode 100644 index 0000000..ea8ce23 --- /dev/null +++ b/docker-dev/php-fpm.conf @@ -0,0 +1,15 @@ +[www] +user = www-data +group = www-data +listen = 127.0.0.1:9000 +listen.owner = www-data +listen.group = www-data +pm = dynamic +pm.max_children = 40 +pm.start_servers = 5 +pm.min_spare_servers = 5 +pm.max_spare_servers = 10 +pm.max_requests = 500 +php_admin_value[memory_limit] = 128M +php_admin_value[upload_max_filesize] = 20M +php_admin_value[post_max_size] = 20M diff --git a/docker-dev/supervisord.conf b/docker-dev/supervisord.conf new file mode 100644 index 0000000..b9cebe1 --- /dev/null +++ b/docker-dev/supervisord.conf @@ -0,0 +1,81 @@ +[unix_http_server] +file=/run/supervisord.sock +chmod=0700 + +[supervisord] +logfile=/var/log/supervisord.log +logfile_maxbytes=50MB +logfile_backups=10 +loglevel=info +pidfile=/run/supervisord.pid +nodaemon=true +minfds=1024 +minprocs=200 + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///run/supervisord.sock + +[program:mysql] +command=/usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql --datadir=/var/lib/mysql --bind-address=0.0.0.0 --socket=/var/run/mysqld/mysqld.sock +autostart=true +autorestart=true +startsecs=15 +startretries=5 +stdout_logfile=/var/log/supervisor/mysql.log +stderr_logfile=/var/log/supervisor/mysql.log +user=mysql +priority=100 +environment=HOME="/var/lib/mysql" + +[program:redis] +command=/usr/bin/redis-server /etc/redis.conf --daemonize no +autostart=true +autorestart=true +startsecs=5 +startretries=5 +stdout_logfile=/var/log/supervisor/redis.log +stderr_logfile=/var/log/supervisor/redis.log +user=redis +priority=200 +directory=/var/lib/redis + +[program:php-fpm] +command=/usr/local/sbin/php-fpm -F +autostart=true +autorestart=true +startsecs=3 +startretries=3 +stdout_logfile=/var/log/supervisor/php-fpm.log +stderr_logfile=/var/log/supervisor/php-fpm.log +user=root +priority=300 +# entrypoint 脚本会检测 PHP-FPM 路径并更新此命令 + +[program:nginx] +command=/usr/sbin/nginx -g "daemon off;" +autostart=true +autorestart=true +startsecs=3 +startretries=3 +stdout_logfile=/var/log/supervisor/nginx.log +stderr_logfile=/var/log/supervisor/nginx.log +user=root +priority=400 + +[program:nuxt] +command=/bin/sh -c "sleep 5; cd /data/httpd/ECShopX_desktop-frontend && if [ -d .nuxt ] || [ -d .output ]; then if npm run 2>/dev/null | grep -q 'start'; then PORT=3000 HOST=0.0.0.0 npm run start; else PORT=3000 HOST=0.0.0.0 npm run dev; fi; else exit 0; fi" +autostart=true +autorestart=true +startsecs=10 +startretries=3 +stdout_logfile=/var/log/supervisor/nuxt.log +stderr_logfile=/var/log/supervisor/nuxt.log +user=root +priority=500 +directory=/data/httpd/ECShopX_desktop-frontend + +[include] +files = /etc/supervisor/conf.d/*.conf diff --git a/resources/lang/en-CN/payment.php b/resources/lang/en-CN/payment.php index 5af9340..1381ad5 100644 --- a/resources/lang/en-CN/payment.php +++ b/resources/lang/en-CN/payment.php @@ -9,4 +9,12 @@ return [ 'alipay' => 'Alipay', 'bank_card' => 'Bank Card', 'wechat_pay_hfpay' => 'WeChat Pay (HFPay)', + 'app_id_required' => 'App ID is required', + 'merchant_id_required' => 'Merchant ID is required', + 'key_required' => 'API Key is required', + 'cert_required' => 'Merchant certificate is required', + 'cert_key_required' => 'Merchant certificate key is required', + 'cert_file_name_error' => 'Please upload apiclient_cert.pem', + 'cert_key_file_name_error' => 'Please upload apiclient_key.pem', + 'servicer_info_required' => 'Service provider APPID and merchant ID are required when enabling special merchant service provider', ]; diff --git a/resources/lang/zh-CN/payment.php b/resources/lang/zh-CN/payment.php index b79b63c..42a8161 100644 --- a/resources/lang/zh-CN/payment.php +++ b/resources/lang/zh-CN/payment.php @@ -9,4 +9,12 @@ return [ 'alipay' => '支付宝', 'bank_card' => '银行卡', 'wechat_pay_hfpay' => '微信支付(hfpay)', + 'app_id_required' => '公众账号ID不能为空', + 'merchant_id_required' => '商户号不能为空', + 'key_required' => 'API密钥不能为空', + 'cert_required' => '商户证书不能为空', + 'cert_key_required' => '商户证书秘钥不能为空', + 'cert_file_name_error' => '请上传apiclient_cert.pem', + 'cert_key_file_name_error' => '请上传apiclient_key.pem', + 'servicer_info_required' => '开启特约商户服务商APPID和服务商商户号必填!', ]; diff --git a/routes/api/companys.php b/routes/api/companys.php index 2a8e748..324d24f 100644 --- a/routes/api/companys.php +++ b/routes/api/companys.php @@ -138,6 +138,9 @@ $api->version('v1', function($api) { $api->get('/mail/setting', [ 'name'=>'获取邮件配置','middleware'=>'activated', 'as' => 'mail.setting.get', 'uses'=>'Setting@getMailSetting']); $api->post('/mail/setting', [ 'name'=>'保存邮件配置','middleware'=>'activated', 'as' => 'mail.setting.set', 'uses'=>'Setting@saveMailSetting']); + //酷家乐路由配置 + $api->get('/kujiale/config', [ 'name'=>'获取酷家乐路由配置','middleware'=>'activated', 'as' => 'kujiale.config.get', 'uses'=>'Setting@getKujialeConfig']); + $api->post('/kujiale/config', [ 'name'=>'保存酷家乐路由配置','middleware'=>'activated', 'as' => 'kujiale.config.set', 'uses'=>'Setting@saveKujialeConfig']); }); $api->group(['namespace' => 'CompanysBundle\Http\Api\V1\Action', 'middleware' => ['api.auth', 'activated', 'shoplog'], 'providers' => 'jwt'], function($api) { diff --git a/routes/api/goods.php b/routes/api/goods.php index f702d84..ac1e803 100644 --- a/routes/api/goods.php +++ b/routes/api/goods.php @@ -29,6 +29,8 @@ $api->version('v1', function($api) { $api->post('/goods/setItemsCategory', ['name' => '更新商品分类', 'as' => 'goods.items.category_change', 'uses' => 'Items@setItemsCategory']); $api->get('/goods/items', ['name' => '获取商品列表', 'as' => 'goods.items.lists', 'uses' => 'Items@getItemsList']); $api->get('/goods/items/onsale', ['name' => '获取可销售的商品列表', 'as' => 'goods.items.onsale.lists', 'uses' => 'Items@getOnsaleItemsList']); + $api->post('/goods/save_group_item', ['name' => '保存分组商品', 'as' => 'goods.items.save_group_item', 'uses' => 'ItemsGroupController@saveGroupItem']); + $api->get('/goods/get_group_items', ['name' => '查询分组商品', 'as' => 'goods.items.get_group_items', 'uses' => 'ItemsGroupController@getGroupItems']); $api->get('/goods/sku', ['name' => '获取商品列表', 'as' => 'goods.sku.lists', 'uses' => 'Items@getSkuList']); $api->get('/goods/items/{item_id}', ['name' => '获取商品详情', 'as' => 'goods.items.detail', 'uses' => 'Items@getItemsDetail']); $api->delete('/goods/items/{item_id}', ['name' => '删除商品', 'as' => 'goods.items.delete', 'uses' => 'Items@deleteItems']); diff --git a/routes/api/kujiale.php b/routes/api/kujiale.php new file mode 100644 index 0000000..ec24e39 --- /dev/null +++ b/routes/api/kujiale.php @@ -0,0 +1,43 @@ +version('v1', function($api) { + $api->group([ + 'namespace' => 'KujialeBundle\Http\Api\V1\Action', + 'middleware' => ['api.auth', 'activated', 'shoplog'], + 'providers' => 'jwt' + ], function($api) { + // 设计师作品与商品绑定相关接口 + $api->post('/kujiale/designer-works/bind-item', [ + 'name' => '绑定设计师作品与商品', + 'as' => 'kujiale.designer.works.bind.item', + 'uses' => 'KuController@bindDesignerWorksItem' + ]); + + $api->delete('/kujiale/designer-works/unbind-item', [ + 'name' => '解绑设计师作品与商品', + 'as' => 'kujiale.designer.works.unbind.item', + 'uses' => 'KuController@unbindDesignerWorksItem' + ]); + + $api->get('/kujiale/designer-works/items', [ + 'name' => '查询关联了design的商品列表', + 'as' => 'kujiale.designer.works.items', + 'uses' => 'KuController@getDesignerWorksItems' + ]); + + $api->get('/kujiale/designer-works/list', [ + 'name' => '获取设计师作品列表', + 'as' => 'kujiale.designer.works.list', + 'uses' => 'KuController@getDesignerWorksList' + ]); + }); +}); diff --git a/routes/api/member.php b/routes/api/member.php index 89744c2..d56c2fd 100644 --- a/routes/api/member.php +++ b/routes/api/member.php @@ -45,6 +45,7 @@ $api->version('v1', function($api) { $api->put('/member/salesman', ['name'=>'设置会员的导购员','middleware'=>'activated', 'as' => 'member.upate.salesman', 'uses' =>'Members@setMemberSalesman']); $api->put('/member/grade', ['name'=>'更新会员等级','middleware'=>'activated', 'as' => 'member.upate.grade_id', 'uses' =>'Members@updateGradeById']); $api->patch('/member/grade', ['name'=>'批量更新会员等级','middleware'=>'activated', 'as' => 'member.upate.grade_ids', 'uses' =>'Members@updateGrade']); + $api->put('/member/regDistributor', ['name'=>'批量更新会员注册分销商','middleware'=>'activated', 'as' => 'member.update.reg_distributor', 'uses' =>'Members@reChangeRegDistributor']); $api->get('/operate/loglist', ['name'=>'获取会员操作日志','middleware'=>'activated', 'as' => 'member.operate.logs', 'uses' =>'Members@gerMemberOperateLogList']); @@ -89,5 +90,20 @@ $api->version('v1', function($api) { $api->post('/members/trustlogin/list',['name'=>'获取信任登录列表','middleware'=>'activated', 'as' => 'member.trustlogin.list', 'uses' =>'TrustLogin@getTrustLoginList']); $api->put('/members/trustlogin/setting',['name'=>'保存信任登录状态','middleware'=>'activated', 'as' => 'member.trustlogin.setting', 'uses' =>'TrustLogin@saveStatusSetting']); + + //标签组相关路由 + $api->post('/member/tag-group', ['name' => '新增标签组', 'middleware' => 'activated', 'as' => 'member.taggroup.add', 'uses' => 'MemberTags@createTagGroup']); + $api->delete('/member/tag-group/{group_id}', ['name' => '删除标签组', 'middleware' => 'activated', 'as' => 'member.taggroup.delete', 'uses' => 'MemberTags@deleteTagGroup']); + $api->get('/member/tag-group', ['name' => '标签组列表', 'middleware' => 'activated', 'as' => 'member.taggroup.list', 'uses' => 'MemberTags@getTagGroupList']); + $api->put('/member/tag-group/{group_id}', ['name' => '编辑标签组', 'middleware' => 'activated', 'as' => 'member.taggroup.update', 'uses' => 'MemberTags@updateTagGroup']); + + //人群圈选路由 + $api->get('/member/segment-rule/structure', ['name'=>'获取规则结构配置','middleware'=>'activated', 'as' => 'member.segment.rule.structure', 'uses' =>'MemberTagAction@getRuleStructure']); + $api->post('/member/segment-rule/preview', ['name'=>'预览人群规则(查询匹配的用户ID)','middleware'=>'activated', 'as' => 'member.segment.rule.preview', 'uses' =>'MemberTagAction@previewSegmentRule']); + $api->get('/member/segment-rule', ['name'=>'获取人群规则列表','middleware'=>'activated', 'as' => 'member.segment.rule.list', 'uses' =>'MemberTagAction@getSegmentRuleList']); + $api->post('/member/segment-rule', ['name'=>'创建人群规则','middleware'=>'activated', 'as' => 'member.segment.rule.create', 'uses' =>'MemberTagAction@createSegmentRule']); + $api->get('/member/segment-rule/{rule_id}', ['name'=>'查看人群规则详情','middleware'=>'activated', 'as' => 'member.segment.rule.get', 'uses' =>'MemberTagAction@getSegmentRule']); + $api->put('/member/segment-rule/{rule_id}', ['name'=>'编辑人群规则','middleware'=>'activated', 'as' => 'member.segment.rule.update', 'uses' =>'MemberTagAction@updateSegmentRule']); + }); }); diff --git a/routes/api/pagestemplate.php b/routes/api/pagestemplate.php index 6e4aea3..babd3d6 100644 --- a/routes/api/pagestemplate.php +++ b/routes/api/pagestemplate.php @@ -7,6 +7,7 @@ $api->version('v1', function ($api) { $api->post('/pagestemplate/add', ['name' => '新增模板', 'as' => 'pagestemplate.add', 'uses' => 'PagesTemplate@add']); $api->put('/pagestemplate/edit', ['name' => '编辑模板', 'as' => 'pagestemplate.edit', 'uses' => 'PagesTemplate@edit']); $api->get('/pagestemplate/detail', ['name' => '模板详情', 'as' => 'pagestemplate.detail', 'uses' => 'PagesTemplate@detail']); + $api->get('/pagestemplate/widget/items', ['name' => '获取模板组件商品', 'as' => 'pagestemplate.widget.items', 'uses' => 'PagesTemplate@getWidgetItems']); $api->post('/pagestemplate/copy', ['name' => '复制模板', 'as' => 'pagestemplate.copy', 'uses' => 'PagesTemplate@copy']); $api->delete('/pagestemplate/del/{pages_template_id}', ['name' => '废弃模板', 'as' => 'pagestemplate.delete', 'uses' => 'PagesTemplate@delete']); $api->put('/pagestemplate/modifyStatus', ['name' => '模板状态变更', 'as' => 'pagestemplate.modifyStatus', 'uses' => 'PagesTemplate@modifyStatus']); @@ -40,4 +41,34 @@ $api->version('v1', function ($api) { $api->post('/memberCenterShare/set', ['name' => '设置会员中心分享信息', 'as' => 'memberCenterShare.set', 'uses' => 'MemberCenterShare@set']); $api->get('/memberCenterShare/getInfo', ['name' => '获取会员中心分享信息', 'as' => 'memberCenterShare.getInfo', 'uses' => 'MemberCenterShare@getInfo']); }); + + // 侧边栏设置 + $api->group(['namespace' => 'ThemeBundle\Http\Api\V1\Action', 'middleware' => ['api.auth', 'activated', 'shoplog'], 'providers' => 'jwt'], function ($api) { + $api->get('/sidebar/list', ['name' => '获取侧边栏列表', 'as' => 'pages.sidebar.list', 'uses' => 'PagesSideBar@getList']); + $api->get('/sidebar/{id}', ['name' => '获取侧边栏详情', 'as' => 'pages.sidebar.getInfo', 'uses' => 'PagesSideBar@getInfo']); + $api->post('/sidebar', ['name' => '设置侧边栏设置', 'as' => 'pages.sidebar.create', 'uses' => 'PagesSideBar@create']); + $api->put('/sidebar/{id}', ['name' => '更新侧边栏设置', 'as' => 'pages.sidebar.update', 'uses' => 'PagesSideBar@update']); + $api->delete('/sidebar/{id}', ['name' => '删除侧边栏设置', 'as' => 'pages.sidebar.delete', 'uses' => 'PagesSideBar@delete']); + }); + + // 广告位设置 + $api->group(['namespace' => 'ThemeBundle\Http\Api\V1\Action', 'middleware' => ['api.auth', 'activated', 'shoplog'], 'providers' => 'jwt'], function ($api) { + $api->get('/adplace/popup/list', ['name' => '获取广告位列表', 'as' => 'pages.adplace.popup.list', 'uses' => 'PagesAdPlace@getList']); + $api->get('/adplace/popup/{id}', ['name' => '获取广告位详情', 'as' => 'pages.adplace.popup.getInfo', 'uses' => 'PagesAdPlace@getInfo']); + $api->post('/adplace/popup', ['name' => '设置广告位', 'as' => 'pages.adplace.popup.create', 'uses' => 'PagesAdPlace@create']); + $api->put('/adplace/popup/{id}', ['name' => '更新广告位', 'as' => 'pages.adplace.popup.update', 'uses' => 'PagesAdPlace@update']); + $api->delete('/adplace/popup/{id}', ['name' => '删除广告位', 'as' => 'pages.adplace.popup.delete', 'uses' => 'PagesAdPlace@delete']); + $api->post('/adplace/popup/submit/{id}', ['name' => '提交审核广告位', 'as' => 'pages.adplace.popup.submit', 'uses' => 'PagesAdPlace@submit']); + $api->post('/adplace/popup/audit/{id}', ['name' => '审核广告位', 'as' => 'pages.adplace.popup.audit', 'uses' => 'PagesAdPlace@audit']); + $api->post('/adplace/popup/withdraw/{id}', ['name' => '撤回广告位审核申请', 'as' => 'pages.adplace.popup.withdraw', 'uses' => 'PagesAdPlace@withdraw']); + + $api->get('/adplace/carousel/list', ['name' => '获取广告位列表', 'as' => 'pages.adplace.carousel.list', 'uses' => 'PagesAdPlace@getList']); + $api->get('/adplace/carousel/{id}', ['name' => '获取广告位详情', 'as' => 'pages.adplace.carousel.getInfo', 'uses' => 'PagesAdPlace@getInfo']); + $api->post('/adplace/carousel', ['name' => '设置广告位', 'as' => 'pages.adplace.carousel.create', 'uses' => 'PagesAdPlace@create']); + $api->put('/adplace/carousel/{id}', ['name' => '更新广告位', 'as' => 'pages.adplace.carousel.update', 'uses' => 'PagesAdPlace@update']); + $api->delete('/adplace/carousel/{id}', ['name' => '删除广告位', 'as' => 'pages.adplace.carousel.delete', 'uses' => 'PagesAdPlace@delete']); + $api->post('/adplace/carousel/submit/{id}', ['name' => '提交审核广告位', 'as' => 'pages.adplace.carousel.submit', 'uses' => 'PagesAdPlace@submit']); + $api->post('/adplace/carousel/audit/{id}', ['name' => '审核广告位', 'as' => 'pages.adplace.carousel.audit', 'uses' => 'PagesAdPlace@audit']); + $api->post('/adplace/carousel/withdraw/{id}', ['name' => '撤回广告位审核申请', 'as' => 'pages.adplace.carousel.withdraw', 'uses' => 'PagesAdPlace@withdraw']); + }); }); diff --git a/routes/api/weapp.php b/routes/api/weapp.php index 08898d5..50a8385 100644 --- a/routes/api/weapp.php +++ b/routes/api/weapp.php @@ -48,13 +48,14 @@ $api->version('v1', function($api) { $api->post('/wxa/stats/retaininfo', [ 'name'=>'小程序访问留存','middleware'=>'activated', 'as' => 'wechat.wxa.stats.retaininfo', 'uses'=>'WxappStats@getRetaininfo']); $api->post('/wxa/stats/userportrait', [ 'name'=>'小程序用户画像', 'middleware'=>'activated', 'as' => 'wechat.wxa.stats.userportrait', 'uses'=>'WxappStats@getUserPortrait']); - $api->post('/wxa/customizepage', [ 'name'=>'增加小程序自定义页面','middleware'=>'activated', 'as' => 'wechat.wxa.customizepage.add', 'uses'=>'CustomizePage@createCustomizePage']); - $api->put('/wxa/customizepage/{id}', [ 'name'=>'更新小程序自定义页面', 'middleware'=>'activated', 'as' => 'wechat.wxa.customizepage.update', 'uses'=>'CustomizePage@updateCustomizePage']); - $api->delete('/wxa/customizepage/{id}', [ 'name'=>'删除小程序自定义页面', 'middleware'=>'activated', 'as' => 'wechat.wxa.customizepage.delete', 'uses'=>'CustomizePage@deleteCustomizePage']); - $api->get('/wxa/customizepage/list', ['name'=>'小程序自定义页面列表','middleware'=>'activated','as' => 'wechat.wxa.customizepage.list', 'uses'=>'CustomizePage@getCustomizepageList']); + $api->post('/wxa/customizepage', [ 'name'=>'增加小程序自定义页面', 'as' => 'wechat.wxa.customizepage.add', 'uses'=>'CustomizePage@createCustomizePage']); + $api->put('/wxa/customizepage/{id}', [ 'name'=>'更新小程序自定义页面', 'as' => 'wechat.wxa.customizepage.update', 'uses'=>'CustomizePage@updateCustomizePage']); + $api->delete('/wxa/customizepage/{id}', [ 'name'=>'删除小程序自定义页面', 'as' => 'wechat.wxa.customizepage.delete', 'uses'=>'CustomizePage@deleteCustomizePage']); + $api->get('/wxa/customizepage/list', ['name'=>'小程序自定义页面列表', 'as' => 'wechat.wxa.customizepage.list', 'uses'=>'CustomizePage@getCustomizepageList']); $api->get('/wxa/customizepage/{id}', ['name'=>'获取小程序自定义页面详情','middleware'=>'activated','as' => 'wechat.wxa.customizepage.info', 'uses'=>'CustomizePage@getCustomizePageInfo']); - $api->get('/wxa/salesperson/customizepage', [ 'name'=>'获取导购货架首页','middleware'=>'activated', 'as' => 'wechat.wxa.salesperson.customizepage.get', 'uses'=>'CustomizePage@getSalespersonCustomizePage']); - + $api->get('/wxa/salesperson/customizepage', [ 'name'=>'获取导购货架首页', 'as' => 'wechat.wxa.salesperson.customizepage.get', 'uses'=>'CustomizePage@getSalespersonCustomizePage']); + $api->put('/wxa/customizepage/{id}/bindcategory', [ 'name'=>'自定也页面绑定分类ID', 'as' => 'wechat.wxa.customizepage.category.bind', 'uses'=>'CustomizePage@bindCategoryId']); + $api->post('/wxa/customizepage/copy/{id}', [ 'name'=>'复制自定义页面', 'as' => 'wechat.wxa.customizepage.category.copy', 'uses'=>'CustomizePage@copy']); $api->put('/wxa/config/{wxaAppId}', ['name' => '小程序配置', 'middleware' => 'activated', 'as' => 'wechat.wxa.config', 'uses' => 'Wxa@saveConfig']); $api->put('/wxappTemplate/wxapp', ['name' => '微信模板编辑', 'middleware' => 'activated', 'as' => 'wechat.wxappTemplate.wxapp', 'uses' => 'wxappTemplate@updateWxappTemplate']); diff --git a/routes/frontapi/distributor.php b/routes/frontapi/distributor.php index 68fd76c..70a4d08 100644 --- a/routes/frontapi/distributor.php +++ b/routes/frontapi/distributor.php @@ -47,6 +47,7 @@ $api->version('v1', function ($api) { // 获取店铺列表-已支持h5 $api->get('/wxapp/distributor/list', ['as' => 'front.wxapp.distributor.list', 'uses'=>'Distributor@getDistributorList']); $api->get('/wxapp/distributor/alllist', ['as' => 'front.wxapp.distributor.alllist', 'uses'=>'Distributor@getAllDistributorList']); + $api->get('/wxapp/distributor/get_all_distributor', ['as' => 'front.wxapp.distributor.get_all_distributor', 'uses'=>'Distributor@getAllDistributor']); // 获取总部自提点店铺的详细信息 $api->get('/wxapp/distributor/self', ['as' => 'front.wxapp.distributor.self', 'uses'=>'Distributor@getDistributionSelfDetail']); // 获取默认的店铺详细信息 @@ -85,6 +86,11 @@ $api->version('v1', function ($api) { // 店铺进店规则验证 $api->post('/wxapp/distributor/config/inRule/check', ['name' => '验证店铺进店规则', 'as' => 'front.wxapp.distributor.config.inRule.check', 'uses' => 'Distributor@checkInRule']); + // 根据地址获取地区信息 + $api->get('/wxapp/distributor/getAreaByAddress', ['name' => '根据地址获取地区信息', 'as' => 'front.wxapp.distributor.getAreaByAddress', 'uses' => 'Distributor@getAreaByAddress']); + // 根据地址获取地区信息 + $api->get('/wxapp/distributor/getAreaByJwd', ['name' => '根据地址获取地区信息-逆解析', 'as' => 'front.wxapp.distributor.getAreaByJwd', 'uses' => 'Distributor@getAreaByJwd']); + }); $api->group(['prefix' => 'h5app', 'namespace' => 'SalespersonBundle\Http\FrontApi\V1\Action', 'middleware' => ['dingoguard:h5app', 'api.auth'], 'providers' => 'jwt'], function ($api) { diff --git a/routes/frontapi/goods.php b/routes/frontapi/goods.php index 5a55c26..020cf26 100644 --- a/routes/frontapi/goods.php +++ b/routes/frontapi/goods.php @@ -40,6 +40,8 @@ $api->version('v1', function ($api) { // 商品分类-店铺推广 $api->get('/wxapp/goods/promoter/category', ['as' => 'goods.category.lists', 'uses' => 'Category@getPromoterCategoryList']); + //获取分组商品 + $api->get('/wxapp/goods/get_group_items', ['as' => 'goods.items.get_group_items', 'uses' => 'ItemsGroupController@getGroupItems']); }); $api->group(['namespace' => 'GoodsBundle\Http\FrontApi\V2\Action', 'middleware' => 'frontnoauth:h5app', 'prefix' => 'h5app'], function ($api) { diff --git a/routes/frontapi/kujiale.php b/routes/frontapi/kujiale.php new file mode 100644 index 0000000..9bb75b4 --- /dev/null +++ b/routes/frontapi/kujiale.php @@ -0,0 +1,17 @@ +version('v1', function($api) { + $api->group(['namespace' => 'KujialeBundle\Http\FrontApi\V1\Action', 'middleware' => 'frontnoauth:h5app', 'prefix' => 'h5app', 'providers' => 'jwt'], function($api) { + $api->post('/wxapp/kujiale/desginList', ['name' => '设计师方案列表', 'as' => 'kujiale.desgin.list', 'uses' => 'KuController@desginWorkList']); + $api->get('/wxapp/kujiale/desginTagsList', ['name' => '方案标签列表', 'as' => 'kujiale.tags.list', 'uses' => 'KuController@getDesginTagsList']); + $api->post('/wxapp/kujiale/desginDetail', ['name' => '设计师方案详情', 'as' => 'kujiale.desgin.detail', 'uses' => 'KuController@desginWorkDetail']); + $api->post('/wxapp/kujiale/viewcount', ['name' => '设计师方案详情', 'as' => 'kujiale.desgin.detail', 'uses' => 'KuController@updateDesignViewCount']); + + $api->get('/wxapp/kujiale/getProductList', ['name' => '获取渲染图商品列表', 'as' => 'kujiale.desgin.goods.list', 'uses' => 'KuController@getProductListByPicId']); + $api->get('/wxapp/kujiale/getDesignerDetail', ['name' => '获取渲染图详情', 'as' => 'kujiale.desgin.pic.detail', 'uses' => 'KuController@getDesignerPicById']); + $api->get('/wxapp/kujiale/getLocationList', ['name' => '获取城市列表', 'as' => 'kujiale.location.list', 'uses' => 'KuController@getLocationList']); + }); + + $api->group(['namespace' => 'KujialeBundle\Http\FrontApi\V1\Action', 'middleware' => ['dingoguard:h5app', 'api.auth'], 'prefix' => 'h5app', 'providers' => 'jwt'], function($api) { + $api->post('/wxapp/kujiale/like', ['name' => '设计师方案详情', 'as' => 'kujiale.desgin.detail', 'uses' => 'KuController@updateDesignLikeCount']); + }); +}); \ No newline at end of file diff --git a/routes/frontapi/pagestemplate.php b/routes/frontapi/pagestemplate.php index 5d65842..3ef1919 100644 --- a/routes/frontapi/pagestemplate.php +++ b/routes/frontapi/pagestemplate.php @@ -15,6 +15,7 @@ $api->version('v1', function ($api) { $api->group(['prefix' => 'h5app', 'namespace' => 'ThemeBundle\Http\FrontApi\V1\Action', 'middleware' => ['frontnoauth:h5app']], function ($api) { $api->get('/wxapp/pagestemplate/detail', ['middleware'=>'apicache','name' => '模板详情', 'as' => 'front.pagestemplate.detail', 'uses' => 'PagesTemplate@detail']); + $api->get('/wxapp/pagestemplate/widget/items', ['name' => '获取模板组件商品', 'as' => 'front.pagestemplate.widget.items', 'uses' => 'PagesTemplate@getWidgetItems']); $api->get('/wxapp/pagestemplate/shopDetail', ['name' => '店铺模板详情', 'as' => 'front.pagestemplate.shopDetail', 'uses' => 'PagesTemplate@shopDetail']); $api->get('/wxapp/pagestemplate/setInfo', ['name' => '模板设置信息', 'as' => 'front.pagestemplate.setInfo', 'uses' => 'PagesTemplate@setInfo']); $api->get('/wxapp/pagestemplate/gettdk', ['name' => '获取tdk配置信息', 'as' => 'front.pagestemplate.gettdk', 'uses' => 'PagesTemplate@getTdk']); @@ -26,6 +27,12 @@ $api->version('v1', function ($api) { //会员中心分享设置 $api->get('/wxapp/memberCenterShare/getInfo', ['name' => '获取会员中心分享信息', 'as' => 'front.memberCenterShare.getInfo', 'uses' => 'MemberCenterShare@getInfo']); + + // 侧边栏设置 + $api->get('/wxapp/sidebar/info', ['name' => '获取侧边栏设置', 'as' => 'front.sidebar.info', 'uses' => 'PagesSideBar@getPagesSideBar']); + + // 广告列表 + $api->get('/wxapp/ad/list', ['name' => '获取广告列表', 'as' => 'front.ad.list', 'uses' => 'PagesAdPlace@getAdList']); }); }); /* ↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑↑ taro小程序、h5、app端、pc端 ↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑↑ */ diff --git a/src/CompanysBundle/Console/InitAdminPasswordCommand.php b/src/CompanysBundle/Console/InitAdminPasswordCommand.php new file mode 100644 index 0000000..fb1a32c --- /dev/null +++ b/src/CompanysBundle/Console/InitAdminPasswordCommand.php @@ -0,0 +1,153 @@ +argument('password'); + $companyId = $this->option('company_id'); + + // 如果没有提供 company_id,使用配置文件中的值 + if (empty($companyId)) { + $companyId = config('common.system_companys_id', 1); + $this->info("未指定 company_id,使用配置文件中的值: {$companyId}"); + } else { + $companyId = (int)$companyId; + $this->info("使用指定的 company_id: {$companyId}"); + } + + $this->info("开始初始化 admin 账号密码..."); + + // 获取 Repository + $operatorsRepository = app('registry')->getManager('default')->getRepository(\CompanysBundle\Entities\Operators::class); + + // 获取数据库连接 + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + + try { + // 检查 admin 账号是否已存在 + $operator = $operatorsRepository->getInfo([ + 'login_name' => 'admin', + 'operator_type' => 'admin' + ]); + + if (empty($operator)) { + // 账号不存在,创建新账号 + $this->info("admin 账号不存在,正在创建新账号..."); + + $operatorData = [ + 'login_name' => 'admin', + 'mobile' => 'admin', + 'password' => password_hash($password, PASSWORD_DEFAULT), + 'operator_type' => 'admin', + 'company_id' => $companyId, + 'username' => 'admin', + ]; + + $newOperator = $operatorsRepository->create($operatorData); + $operatorId = $newOperator['operator_id']; + + $this->info("✓ 已创建 admin 账号"); + $this->info(" 账号ID: {$operatorId}"); + $this->info(" 公司ID: {$companyId}"); + + } else { + // 账号已存在,更新密码和 company_id + $operatorId = $operator['operator_id']; + $oldCompanyId = $operator['company_id'] ?? 'null'; + + $this->info("admin 账号已存在,正在更新密码..."); + $this->info(" 账号ID: {$operatorId}"); + $this->info(" 原公司ID: {$oldCompanyId}"); + + $updateData = [ + 'password' => password_hash($password, PASSWORD_DEFAULT), + ]; + + // 如果 company_id 与现有值不同,则更新 + if ($operator['company_id'] != $companyId) { + $updateData['company_id'] = $companyId; + $this->info(" 将更新公司ID为: {$companyId}"); + } + + $operatorsRepository->updateOneBy( + [ + 'login_name' => 'admin', + 'operator_type' => 'admin' + ], + $updateData + ); + + $this->info("✓ 已更新 admin 账号密码"); + if (isset($updateData['company_id'])) { + $this->info("✓ 已更新公司ID为: {$companyId}"); + } + } + + $conn->commit(); + $this->info(""); + $this->info("操作成功完成!"); + $this->info("登录账号: admin"); + $this->info("公司ID: {$companyId}"); + + } catch (\Exception $e) { + $conn->rollback(); + $this->error("操作失败: " . $e->getMessage()); + $this->error("错误详情: " . $e->getTraceAsString()); + return 1; + } + + return 0; + } +} diff --git a/src/CompanysBundle/Http/Api/V1/Action/Setting.php b/src/CompanysBundle/Http/Api/V1/Action/Setting.php index 24b9e12..2961209 100644 --- a/src/CompanysBundle/Http/Api/V1/Action/Setting.php +++ b/src/CompanysBundle/Http/Api/V1/Action/Setting.php @@ -2149,4 +2149,65 @@ class Setting extends BaseController return $this->response->array($result); } + /** + * 获取酷家乐配置 + * @route GET /company/kujiale/config + */ + public function getKujialeConfig(Request $request) + { + $companyId = app('auth')->user()->get('company_id'); + if (!$companyId) { + throw new ResourceException('无法获取公司ID'); + } + + $redis = app('redis')->connection('default'); + $key = 'kujiale:config:' . $companyId; + $raw = $redis->get($key); + $config = $raw ? json_decode($raw, true) : []; + + return $this->response->array([ + 'success' => true, + 'data' => [ + 'appKey' => $config['appKey'] ?? '', + 'appSecret' => $config['appSecret'] ?? '', + ], + ]); + } + + /** + * 保存酷家乐配置 + * @route POST /company/kujiale/config + */ + public function saveKujialeConfig(Request $request) + { + $validator = app('validator')->make($request->all(), [ + 'appKey' => 'required|string', + 'appSecret' => 'required|string', + ]); + + if ($validator->fails()) { + throw new \Dingo\Api\Exception\ValidationHttpException($validator->errors()); + } + + $companyId = app('auth')->user()->get('company_id'); + if (!$companyId) { + throw new ResourceException('无法获取公司ID'); + } + + $config = [ + 'appKey' => $request->input('appKey'), + 'appSecret' => $request->input('appSecret'), + 'updated' => time(), + ]; + + $redis = app('redis')->connection('default'); + $key = 'kujiale:config:' . $companyId; + $redis->set($key, json_encode($config)); + + return $this->response->array([ + 'success' => true, + 'message' => '保存成功', + ]); + } + } diff --git a/src/CompanysBundle/MultiLang/MultiLangItem.php b/src/CompanysBundle/MultiLang/MultiLangItem.php index 8fe94b8..98c9ebf 100644 --- a/src/CompanysBundle/MultiLang/MultiLangItem.php +++ b/src/CompanysBundle/MultiLang/MultiLangItem.php @@ -24,6 +24,7 @@ class MultiLangItem // private $module = 'item'; private $table; + private $moduleNew; public function __construct(string $lang,string $module = 'item') { $this->lang = $lang; @@ -31,6 +32,7 @@ class MultiLangItem if($module != 'item'){ $moduleNew = 'outside_item'; } + $this->moduleNew = $moduleNew; $tableLang = str_replace('-','',$lang); $this->table = $moduleNew."_multi_lang_mod_lang_$tableLang"; } @@ -225,7 +227,7 @@ CREATE TABLE {$table} LIKE `multi_lang_mod`; $params['_offset'] = $offset; } // 添加 LIMIT OFFSET(使用 prepare 绑定) - + $conn = app("registry")->getConnection("default"); $stmt = $conn->prepare($sql); foreach ($params as $key => $val) { @@ -347,4 +349,47 @@ CREATE TABLE {$table} LIKE `multi_lang_mod`; return ['whereClauses' => $whereClauses, 'params' => $params]; } + public function deleteByFilter(array $filter) + { + $conn = app("registry")->getConnection("default"); + $schemaManager = $conn->getSchemaManager(); + + // 获取所有匹配表前缀的语言表 + $tablePrefix = $this->moduleNew . "_multi_lang_mod_lang_"; + $allTables = $schemaManager->listTableNames(); + $langTables = array_filter($allTables, function($tableName) use ($tablePrefix) { + return strpos($tableName, $tablePrefix) === 0; + }); + + if (empty($langTables)) { + return false; + } + + // 构建 WHERE 子句和参数 + $whereClauses = []; + $params = []; + foreach ($filter as $key => $value) { + $whereClauses[] = "`$key` = :$key"; + $params[$key] = $value; + } + + // 如果没有过滤条件,返回 false(防止误删所有数据) + if (empty($whereClauses)) { + return false; + } + + $whereSql = implode(' AND ', $whereClauses); + + // 对每个语言表执行删除操作 + $totalDeleted = 0; + foreach ($langTables as $table) { + $sql = "DELETE FROM `{$table}` WHERE {$whereSql}"; + $deleted = $conn->executeStatement($sql, $params); + $totalDeleted += $deleted; + } + + return $totalDeleted > 0; + } + + } diff --git a/src/CompanysBundle/Repositories/RegionauthRepository.php b/src/CompanysBundle/Repositories/RegionauthRepository.php index b411255..cf56581 100644 --- a/src/CompanysBundle/Repositories/RegionauthRepository.php +++ b/src/CompanysBundle/Repositories/RegionauthRepository.php @@ -174,7 +174,7 @@ class RegionauthRepository extends EntityRepository array_walk($value, function (&$colVal) use ($qb) { $colVal = $qb->expr()->literal($colVal); }); - $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); } else { $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); } diff --git a/src/CompanysBundle/Services/CommonLangModService.php b/src/CompanysBundle/Services/CommonLangModService.php index 9cb6bb1..27dcfa3 100644 --- a/src/CompanysBundle/Services/CommonLangModService.php +++ b/src/CompanysBundle/Services/CommonLangModService.php @@ -276,18 +276,21 @@ class CommonLangModService return true; } - public function filterByLang(string $lang, string $field, string $content, string $tableName) + public function filterByLang(string $lang, string $field, string $content, string $tableName, $companyId = 0) { // 处理带操作符的字段名,如 page_name|contains,只取字段名部分 $fieldParts = explode('|', $field); $fieldName = $fieldParts[0]; $filter = [ - 'lang'=>$lang, + // 'lang'=>$lang, 'field'=>$fieldName, 'table_name'=>$tableName, 'attribute_value|contains'=>$content, ]; + // if ($companyId > 0) { + // $filter['company_id'] = $companyId; + // } $repository = $this->getLangMapRepository($lang); $list = $repository->getListByFilter($filter, -1, -1); if(empty($list)){ @@ -325,7 +328,15 @@ class CommonLangModService $fields = $fieldsArr['fields']; $fieldsOpts = $fieldsArr['fieldOpts']; foreach($totalLang as $lang) { - $filter = ['table_name' => $tableName, 'field' => $fields, 'lang' => $lang, 'data_id'=>$id]; + if ($lang != $langue) { + continue; + } + $filter = [ + 'table_name' => $tableName, + 'field' => $fields, + // 'lang' => $lang, + 'data_id'=>$id + ]; if (!empty($module)) { $filter['module_name'] = $module; } @@ -379,7 +390,15 @@ class CommonLangModService $fields = $fieldsArr['fields']; $fieldsOpts = $fieldsArr['fieldOpts']; foreach($totalLang as $lang) { - $filter = ['table_name' => $tableName, 'field' => $fields, 'lang' => $lang, 'data_id'=>$ids]; + if ($lang != $langue) { + continue; + } + $filter = [ + 'table_name' => $tableName, + 'field' => $fields, + // 'lang' => $lang, + 'data_id'=>$ids + ]; $repository = $this->getLangMapRepository($lang); $listTmp = $repository->getListByFilter($filter, -1, -1); if(empty($listTmp)){ diff --git a/src/CompanysBundle/Services/EmployeeService.php b/src/CompanysBundle/Services/EmployeeService.php index 1ea279d..8747103 100644 --- a/src/CompanysBundle/Services/EmployeeService.php +++ b/src/CompanysBundle/Services/EmployeeService.php @@ -139,16 +139,39 @@ class EmployeeService if (isset($params['password']) && $params['password']) { $operatorParams['password'] = $params['password']; } - // $operatorParams['login_name'] = $params['login_name']; - $operatorParams['mobile'] = $params['mobile']; - $operatorParams['username'] = $params['username']; + // 数据未脱敏处理 + $operatorsService = new OperatorsService(); + $oldOperatorInfo = $operatorsService->getInfo([ + 'operator_id' => $filter['operator_id'], + ]); + // 处理 mobile 字段 + if (strpos($params['mobile'], '*') !== false) { + // 如果存在*,使用oldOperatorInfo数据 + $operatorParams['mobile'] = $oldOperatorInfo['mobile']; + } elseif ($params['mobile'] != $oldOperatorInfo['mobile']) { + // 如果不存在*并且数据不等于oldOperatorInfo数据,存新数据 + $operatorParams['mobile'] = $params['mobile']; + } else { + // 如果不存在*且数据等于oldOperatorInfo数据,保持原值 + $operatorParams['mobile'] = $oldOperatorInfo['mobile']; + } + // 处理 username 字段 + if (strpos($params['username'], '*') !== false) { + // 如果存在*,使用oldOperatorInfo数据 + $operatorParams['username'] = $oldOperatorInfo['username']; + } elseif ($params['username'] != $oldOperatorInfo['username']) { + // 如果不存在*并且数据不等于oldOperatorInfo数据,存新数据 + $operatorParams['username'] = $params['username']; + } else { + // 如果不存在*且数据等于oldOperatorInfo数据,保持原值 + $operatorParams['username'] = $oldOperatorInfo['username']; + } $operatorParams['head_portrait'] = $params['head_portrait']; $operatorParams['regionauth_id'] = $params['regionauth_id'] ?? 0; if (isset($params['distributor_ids'])) { $operatorParams['distributor_ids'] = $params['distributor_ids'] ?: []; } $operatorParams['shop_ids'] = $params['shop_ids'] ?: []; - $operatorsService = new OperatorsService(); $conn = app('registry')->getConnection('default'); $conn->beginTransaction(); try { diff --git a/src/CompanysBundle/Services/RegionauthService.php b/src/CompanysBundle/Services/RegionauthService.php index 709a42a..58aa990 100644 --- a/src/CompanysBundle/Services/RegionauthService.php +++ b/src/CompanysBundle/Services/RegionauthService.php @@ -112,4 +112,16 @@ class RegionauthService return false; } } + + /** + * Dynamically call the shopsservice instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->entityRepository->$method(...$parameters); + } } diff --git a/src/CompanysBundle/Services/RepositoryInterceptor.php b/src/CompanysBundle/Services/RepositoryInterceptor.php index 6c3079f..12fea8f 100644 --- a/src/CompanysBundle/Services/RepositoryInterceptor.php +++ b/src/CompanysBundle/Services/RepositoryInterceptor.php @@ -290,13 +290,14 @@ class RepositoryInterceptor $fieldLangue = $repository->langField; $lang = $ns->getLang(); $prkFilter = $filter[$prk] ?? ''; // 所有过滤字段keys + $companyId = $filter['company_id'] ?? 0; foreach ($filter as $key => $value) { $dataIdArr = ''; // 必须是多语言字段 // 可能存在xx|xx 这种数据, 所以要兼容 $filterkeys = explode('|', $key); if (in_array($filterkeys[0], $fieldLangue)) { - $dataIdArr = $ns->filterByLang($lang, $key, $value, $table); + $dataIdArr = $ns->filterByLang($lang, $key, $value, $table, $companyId); // 如果存在多语言字段主键,说明可能其他地方使用了主键过滤,我们需要合并掉 if (!empty($dataIdArr)) { if (!empty($prkFilter)) { diff --git a/src/DistributionBundle/Entities/Distributor.php b/src/DistributionBundle/Entities/Distributor.php index a5bc7f3..1a652e8 100644 --- a/src/DistributionBundle/Entities/Distributor.php +++ b/src/DistributionBundle/Entities/Distributor.php @@ -90,6 +90,13 @@ class Distributor */ private $name; + /** + * @var string + * + * @ORM\Column(name="first_letter", type="string", length="5", options={"comment":"店铺名称首字母", "default":""}) + */ + private $first_letter = ""; + /** * @var string * @@ -659,6 +666,30 @@ class Distributor return $this->name; } + /** + * Set firstLetter. + * + * @param string $firstLetter + * + * @return Distributor + */ + public function setFirstLetter($firstLetter) + { + $this->first_letter = $firstLetter; + + return $this; + } + + /** + * Get firstLetter. + * + * @return string + */ + public function getFirstLetter() + { + return $this->first_letter; + } + /** * Set created * diff --git a/src/DistributionBundle/Http/FrontApi/V1/Action/Distributor.php b/src/DistributionBundle/Http/FrontApi/V1/Action/Distributor.php index c7fbdfa..0398f99 100644 --- a/src/DistributionBundle/Http/FrontApi/V1/Action/Distributor.php +++ b/src/DistributionBundle/Http/FrontApi/V1/Action/Distributor.php @@ -408,10 +408,46 @@ class Distributor extends BaseController // $result['distributor_id'] = 0; $result['is_valid'] = 'true'; } else {//默认店铺 - $filter['distributor_id'] = 0; - $result = $distributorService->getInfo($filter); + $result = $distributorService->getInfoSimple([ + 'company_id' => $authInfo['company_id'], + 'is_default' => 1, + 'is_valid' => 'true', + ]); + // $filter['distributor_id'] = 0; + // $result = $distributorService->getInfo($filter); } } + if(empty($result['is_valid'])){ + // $result = [ + // 'distributor_id' => 0, + // 'is_delivery' => true, + // 'is_ziti' => false, + // ]; + //这里应该取默认 + $result = $distributorService->getInfoSimple([ + 'company_id' => $authInfo['company_id'], + 'is_default' => 1, + 'is_valid' => 'true', + ]); + if (!$result) { + $result = [ + 'distributor_id' => 0, + 'is_delivery' => true, + 'is_ziti' => false, + ]; + } + return $this->response->array($result); + } + + + if(empty($result['is_valid'])){ + $result = [ + 'distributor_id' => 0, + 'is_delivery' => true, + 'is_ziti' => false, + ]; + return $this->response->array($result); + } if ($result && $result['is_valid'] == 'true') { $result['status'] = false; @@ -449,11 +485,19 @@ class Distributor extends BaseController return $this->response->array($result); } else { - $result = [ - 'distributor_id' => 0, - 'is_delivery' => true, - 'is_ziti' => false, - ]; + //这里应该取默认店铺, + $result = $distributorService->getInfoSimple([ + 'company_id' => $authInfo['company_id'], + 'is_default' => 1, + 'is_valid' => 'true', + ]); + if (!$result) { + $result = [ + 'distributor_id' => 0, + 'is_delivery' => true, + 'is_ziti' => false, + ]; + } return $this->response->array($result); } } @@ -1064,6 +1108,83 @@ class Distributor extends BaseController return $this->response->array($result); } + /** + * 获取所有的店铺 + * path = '/api/h5app/wxapp/distributor/get_all_distributor' + */ + public function getAllDistributor(Request $request) + { + // 获取参数 + $authInfo = $request->get('auth'); + $params = $request->all('regionauth_id', 'category_id', 'first_letter', 'distributor_id'); + $companyId = (int)$authInfo['company_id']; // 企业id + $page = $request->input('page', 1);// 当前页 + $pageSize = $request->input('pageSize', 10); // 每页的数量 + $regionauth_id = $request->input('regionauth_id', 0); // 小镇ID + + // 定义返回响应的结构体 + $result = [ + "total_count" => 0, + "list" => [], + "tagList" => [], + ]; + + // 搜索条件 + $filter = [ + 'company_id' => $companyId, + 'distributor_self' => 0,//默认拿不是总店的店铺 + 'is_valid' => 'true',//必须是显示状态的店铺 + ]; + foreach ($params as $k => $v) { + if (!$v) continue; + switch ($k) { + case 'distributor_id': + case 'category_id': + case 'regionauth_id': + $filter[$k] = intval($v); + break; + + case 'first_letter': + $filter[$k] = trim($v); + break; + } + } + + // 排序方式 + $sortType = $request->input("sort_type", 0); + switch ($sortType) { + case 5: + $orderBy = [ + "first_letter" => "ASC",//字母A-Z排序 + "distributor_id" => "DESC"//按店铺添加时间,新店铺靠前 + ]; + break; + default: // 根据添加时间倒序 + $orderBy = [ + "created" => "DESC", + "distributor_id" => "DESC" + ]; + break; + } + + $cols = 'distributor_id, name, logo, first_letter'; + $distributorService = new DistributorService(); + $rsDistributor = $distributorService->entityRepository->getLists($filter, $cols, $page, $pageSize, $orderBy); + $result['filter'] = $filter; + if ($rsDistributor) { + foreach ($rsDistributor as $k => $v) { + $result["list"][] = [ + 'distributor_id' => $v['distributor_id'], + 'name' => $v['name'], + 'logo' => $v['logo'], + 'first_letter' => $v['first_letter'], + ]; + } + } + + return $this->response->array($result); + } + /** * @SWG\Get( * path="/wxapp/distributor/self", @@ -2111,8 +2232,117 @@ class Distributor extends BaseController ]; $pickupLocationService = new PickupLocationService(); $result = $pickupLocationService->getNearlists($pFilter, $postData['lng'], $postData['lat'], '*', 1, 100); + + // 在列表前面添加店铺地址 + if (!empty($distributorIds) && is_array($distributorIds)) { + // 取第一个店铺ID(通常只有一个) + $distributorId = $distributorIds[0]; + $distributorFilter = [ + 'company_id' => $authInfo['company_id'], + 'distributor_id' => $distributorId, + ]; + $distributor = $distributorService->getInfoSimple($distributorFilter); + + if ($distributor && !empty($distributor['address'])) { + // 转换店铺营业时间格式(调用 Service 的方法) + $hours = $pickupLocationService->formatDistributorHour($distributor['hour'] ?? ''); + // 从营业时间中提取工作日(字符串格式) + $workdaysStr = $pickupLocationService->extractWorkdaysFromHours($hours); + // 转换为数组格式,与 getNearlists 返回的格式保持一致 + $workdays = explode(',', trim($workdaysStr, ',')); + + // 计算距离(如果有经纬度) + $distance = null; + if ($postData['lng'] && $postData['lat'] && $distributor['lng'] && $distributor['lat']) { + $distance = $this->calculateDistance( + $postData['lat'], + $postData['lng'], + $distributor['lat'], + $distributor['lng'] + ); + } + + // 构造店铺地址项(使用负数ID标识) + $storeAddressItem = [ + 'id' => (string)(-$distributorId), // 使用负数ID标识店铺地址,转为字符串与自提点格式一致 + 'company_id' => (string)($distributor['company_id'] ?? ''), + 'distributor_id' => (string)($distributor['distributor_id'] ?? ''), + 'rel_distributor_id' => (string)($distributor['distributor_id'] ?? ''), + 'name' => $distributor['name'] ?? '', + 'lng' => $distributor['lng'] ?? '', + 'lat' => $distributor['lat'] ?? '', + 'province' => $distributor['province'] ?? '', + 'city' => $distributor['city'] ?? '', + 'area' => $distributor['area'] ?? '', + 'address' => $distributor['address'] ?? '', + 'contract_phone' => $distributor['mobile'] ?? '', + 'hours' => $hours, + 'workdays' => $workdays, // 数组格式 + 'wait_pickup_days' => '0', // 转为字符串与自提点格式一致 + 'latest_pickup_time' => null, // 保持 null,与自提点可能为 null 的情况一致 + 'created' => (string)time(), // 转为字符串与自提点格式一致 + 'updated' => (string)time(), // 转为字符串与自提点格式一致 + 'is_store_address' => true, // 标识字段 + ]; + + // 如果有距离,添加到数组中 + if ($distance !== null) { + $storeAddressItem['distance'] = $distance; + } + + // 插入到列表前面 + if (!isset($result['list'])) { + $result['list'] = []; + } + array_unshift($result['list'], $storeAddressItem); + + // 更新总数 + $result['total_count'] = ($result['total_count'] ?? 0) + 1; + + // 如果有距离,需要重新排序(按距离) + if ($distance !== null && !empty($result['list'])) { + usort($result['list'], function($a, $b) { + $distanceA = $a['distance'] ?? PHP_INT_MAX; + $distanceB = $b['distance'] ?? PHP_INT_MAX; + return $distanceA <=> $distanceB; + }); + } + } + } + return $this->response->array($result); } + + /** + * 计算两点之间的距离(公里) + * @param float $lat1 纬度1 + * @param float $lng1 经度1 + * @param float $lat2 纬度2 + * @param float $lng2 经度2 + * @return float 距离(公里) + */ + private function calculateDistance($lat1, $lng1, $lat2, $lng2) + { + $lat1 = floatval($lat1); + $lng1 = floatval($lng1); + $lat2 = floatval($lat2); + $lng2 = floatval($lng2); + + // 使用Haversine公式计算距离 + $earthRadius = 6371; // 地球半径(公里) + + $dLat = deg2rad($lat2 - $lat1); + $dLng = deg2rad($lng2 - $lng1); + + $a = sin($dLat / 2) * sin($dLat / 2) + + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * + sin($dLng / 2) * sin($dLng / 2); + + $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); + $distance = $earthRadius * $c; + + return round($distance, 2); + } /** * @SWG\Get( @@ -2317,49 +2547,86 @@ class Distributor extends BaseController throw new ResourceException('请先登录'); } // 如果用户有专属导购,进行验证店铺或者导购是否有效 - $filter = [ - 'company_id' => $companyId, - 'user_id' => $userId, - 'is_bind' => 1, + // 按照会员列表获取会员归属店铺,按照会员列表查询逻辑,走batchGetBindSalesperson + $memberService = new MemberService(); + $memberList = [ + [ + 'user_id' => $userId, + ] ]; - $result = $workWechatRepositories->getInfo($filter); - if (!empty($result)) { + // 批量查询会员的绑定导购和绑定门店 + $memberService->batchGetBindSalesperson($companyId, $memberList); + app('log')->info('david-batchGetBindSalesperson:'.json_encode($memberList)); + + $memberInfo = $memberList[0] ?? []; + $salespersonInfo = $memberInfo['salesperson_info'] ?? []; + $storeInfo = $memberInfo['store_info'] ?? []; + + // 检查是否有绑定导购信息 + $salespersonId = $salespersonInfo['salesperson_id'] ?? null; + + if ($salespersonId) { + // 有绑定导购,进行验证 + // 验证导购是否有效 $filter = [ 'company_id' => $companyId, - 'salesperson_id' => $result['salesperson_id'], + 'salesperson_id' => $salespersonId, 'salesperson_type' => 'shopping_guide', // 'is_valid' => 'true', ]; - $salespersonInfo = $salespersonService->getSalespersonDetail($filter); - if (empty($salespersonInfo)) { + $salespersonDetail = $salespersonService->getSalespersonDetail($filter); + if (empty($salespersonDetail)) { throw new ResourceException('导购员不存在'); } - if (isset($salespersonInfo['is_valid']) && ($salespersonInfo['is_valid'] != 'true' || $salespersonInfo['is_valid'] != true)) { + if (isset($salespersonDetail['is_valid']) && ($salespersonDetail['is_valid'] != 'true' && $salespersonDetail['is_valid'] != true)) { throw new ResourceException('导购员失效'); } + // 验证店铺是否有效 - $filterDistributor = [ - 'company_id' => $companyId, - 'distributor_id' => $salespersonInfo['distributor_id'], - // 'is_valid' => 'true', - ]; - $info = $distributorService->getInfoSimple($filterDistributor); - if (empty($info)) { + $storeBn = $storeInfo['store_bn'] ?? ''; + $distributorInfo = null; + + if (!empty($storeBn)) { + // 优先根据门店编号(shop_code)查询店铺 + $filterDistributor = [ + 'company_id' => $companyId, + 'shop_code' => $storeBn, + // 'is_valid' => 'true', + ]; + $distributorInfo = $distributorService->getInfoSimple($filterDistributor); + } + + // 如果通过门店编号没找到,使用导购的店铺ID + if (empty($distributorInfo)) { + $distributorId = $salespersonDetail['distributor_id'] ?? null; + if ($distributorId) { + $filterDistributor = [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + // 'is_valid' => 'true', + ]; + $distributorInfo = $distributorService->getInfoSimple($filterDistributor); + } + } + + if (empty($distributorInfo)) { throw new ResourceException('店铺不存在'); } - if (isset($info['is_valid']) && ($info['is_valid'] != 'true' || $info['is_valid'] != true)) { + + if (isset($distributorInfo['is_valid']) && ($distributorInfo['is_valid'] != 'true' && $distributorInfo['is_valid'] != true)) { throw new ResourceException('店铺失效'); } + $result = [ 'status' => true, 'msg' => '成功', 'data' => [ - 'distributor_id' => $salespersonInfo['distributor_id'], - 'distributor_ids' => $salespersonInfo['distributor_ids'], - 'salesperson_id' => $salespersonInfo['salesperson_id'], + 'distributor_id' => $distributorInfo['distributor_id'], + 'distributor_ids' => $salespersonDetail['distributor_ids'] ?? [], + 'salesperson_id' => $salespersonDetail['salesperson_id'], ] ]; - }else { + } else { $result = ['status' => false, 'msg' => '用户没有专属导购', 'data' => []]; } } @@ -2383,4 +2650,87 @@ class Distributor extends BaseController return $this->response->array($data); } + + /** + * @SWG\Get( + * path="/distributor/getAreaByjwd", + * summary="根据地址获取地区信息", + * tags={"店铺"}, + * description="根据地址获取地区信息", + * operationId="getAreaByAddress", + * @SWG\Parameter( + * name="address", + * in="query", + * description="地址", + * required=true, + * type="string", + * ), + * @SWG\Response( + * response=200, + * description="成功返回结构", + * @SWG\Schema( + * @SWG\Property( + * property="data", + * type="array", + * @SWG\Items( + * type="object", + * ) + * ), + * ), + * ), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/DistributionErrorRespones") ) ) + * ) + */ + public function getAreaByJwd(Request $request) + { + $lat = $request->input('lat'); + $lng = $request->input('lng'); + if (!$lat || !$lng) { + throw new ResourceException(trans('DistributionBundle/Controllers/Distributor.address_required'), 400); + } + $area = get_area_by_lat_lng($lat, $lng); + return $this->response->array($area); + } + + + /** + * @SWG\Get( + * path="/distributor/getAreaByAddress", + * summary="根据地址获取地区信息", + * tags={"店铺"}, + * description="根据地址获取地区信息", + * operationId="getAreaByAddress", + * @SWG\Parameter( + * name="address", + * in="query", + * description="地址", + * required=true, + * type="string", + * ), + * @SWG\Response( + * response=200, + * description="成功返回结构", + * @SWG\Schema( + * @SWG\Property( + * property="data", + * type="array", + * @SWG\Items( + * type="object", + * ) + * ), + * ), + * ), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/DistributionErrorRespones") ) ) + * ) + */ + public function getAreaByAddress(Request $request) + { + $address = $request->input('address'); + if (!$address) { + throw new ResourceException(trans('DistributionBundle/Controllers/Distributor.address_required'), 400); + } + $area = get_latlng_by_address($address); + return $this->response->array($area); + } + } diff --git a/src/DistributionBundle/Repositories/DistributorRepository.php b/src/DistributionBundle/Repositories/DistributorRepository.php index 3f539cb..5c4e749 100644 --- a/src/DistributionBundle/Repositories/DistributorRepository.php +++ b/src/DistributionBundle/Repositories/DistributorRepository.php @@ -26,6 +26,7 @@ use EspierBundle\Traits\Repository\FilterRepositoryTrait; use GoodsBundle\Services\MultiLang\MagicLangTrait; use GoodsBundle\Services\MultiLang\MultiLangOutsideItemService; use MerchantBundle\Entities\Merchant; +use Overtrue\Pinyin\Pinyin; class DistributorRepository extends EntityRepository { @@ -55,6 +56,7 @@ class DistributorRepository extends EntityRepository 'address', 'house_number', 'name', + 'first_letter', 'auto_sync_goods', 'logo', 'contract_phone', @@ -469,7 +471,7 @@ class DistributorRepository extends EntityRepository $result = $this->getColumnNamesData($entity); if ($result){ - $this->getLangService()->getOneLangData($result,$this->multiLangField,$this->table,$this->getLang(),$result[$this->prk],$this->table); + $result = $this->getLangService()->getOneLangData($result,$this->multiLangField,$this->table,$this->getLang(),$result[$this->prk],$this->table); } return $result; @@ -681,11 +683,20 @@ class DistributorRepository extends EntityRepository private function setColumnNamesData($entity, $params) { foreach ($this->cols as $col) { + if ($col == 'first_letter') { + continue; + } + if (isset($params[$col])) { $fun = "set" . str_replace(" ", "", ucwords(str_replace("_", " ", $col))); if (method_exists($entity, $fun)) { $entity->$fun($params[$col]); } + + if ($col == 'name') { + $firstLetter = $this->getFirstLetter($params[$col]); + $entity->setFirstLetter($firstLetter); + } } } return $entity; @@ -728,4 +739,21 @@ class DistributorRepository extends EntityRepository } return []; } + + //获取店铺名称的首字母 + public function getFirstLetter($str = '') + { + $first_letter = strtoupper(mb_substr($str, 0, 1, 'utf-8')); + if (preg_match('/^[A-Z]$/', $first_letter)) { + return $first_letter; + } + + $pinyin = new Pinyin(); + $letters = $pinyin->abbr($str); // NHSJ + $first_letter = strtoupper(substr($letters, 0, 1)); + if (!preg_match('/^[A-Z]$/', $first_letter)) { + $first_letter = 'Z#'; + } + return $first_letter; + } } diff --git a/src/DistributionBundle/Services/DistributorItemsService.php b/src/DistributionBundle/Services/DistributorItemsService.php index be59190..828d7c0 100644 --- a/src/DistributionBundle/Services/DistributorItemsService.php +++ b/src/DistributionBundle/Services/DistributorItemsService.php @@ -387,8 +387,16 @@ class DistributorItemsService ->setMaxResults($pageSize); } - if (!$column) { + if (!$column || $column == '*') { $column = 'items.*'; + } else { + if (!is_array($column)) { + $column = explode(',', $column); + } + array_walk($column, function (&$v) { + $v = 'items.'.$v; + }); + $column = implode(',', $column); } $column .= ',(CASE items.store WHEN 0 THEN 0 ELSE 1 END) as v_store'; $result['list'] = $query->select($column)->execute()->fetchAll(); diff --git a/src/DistributionBundle/Services/DistributorService.php b/src/DistributionBundle/Services/DistributorService.php index dc8f7cb..a27d6e2 100644 --- a/src/DistributionBundle/Services/DistributorService.php +++ b/src/DistributionBundle/Services/DistributorService.php @@ -437,10 +437,15 @@ class DistributorService } } $distributorInfo = $this->getDefaultDistributor($filter['company_id']); - if (!$distributorInfo || $distributorInfo['is_valid'] === 'false' || $distributorInfo['is_valid'] === false || $distributorInfo['distributor_self'] === 0 || $distributorInfo['distributor_self'] === '0') { + if(empty($distributorInfo)){ $distributorInfo = $this->getMainDistributor($filter['company_id']); + }else{ + if ($distributorInfo['is_valid'] === 'false' || $distributorInfo['is_valid'] === false || $distributorInfo['distributor_self'] === 0 || $distributorInfo['distributor_self'] === '0') { + $distributorInfo = $this->getMainDistributor($filter['company_id']); + } } - + + return $distributorInfo; } @@ -896,7 +901,7 @@ class DistributorService $fields = 'distributor_id'; return $this->entityRepository->getLists($filter, $fields); } - + /** * 追加店铺列表数据(适用于多个店铺id) * @param int $companyId 公司id @@ -1300,7 +1305,7 @@ class DistributorService /** * 设置店铺收款主体 - * + * * @param int $companyId 公司ID * @param int $distributorId 店铺ID * @param int $paymentSubject 收款主体,0=平台,1=店铺 @@ -1314,11 +1319,11 @@ class DistributorService 'distributor_id' => $distributorId, 'company_id' => $companyId ]); - + if (!$distributorInfo) { throw new ResourceException(trans('DistributionBundle/Services/DistributorService.distributor_not_exists_or_no_permission')); } - + // 检查店铺下是否有未完成的退款单 // 需要检查的退款状态:READY(未审核)、AUDIT_SUCCESS(审核成功待退款)、PROCESSING(已发起退款等待到账)、CHANGE(退款异常) $aftersalesRefundService = new AftersalesRefundService(); @@ -1329,11 +1334,11 @@ class DistributorService ]; // 使用count方法检查是否存在未完成的退款单(性能更好) $refundCount = $aftersalesRefundService->aftersalesRefundRepository->count($refundFilter); - + if ($refundCount > 0) { throw new ResourceException(trans('DistributionBundle/Services/DistributorService.has_unfinished_refund_cannot_switch_payment_subject')); } - + // 支付配置校验 if ($paymentSubject == 1) { // 切换为店铺时,需要校验店铺的支付配置 @@ -1342,20 +1347,20 @@ class DistributorService // 切换为平台时,需要校验平台的支付配置 $this->validatePlatformPaymentConfig($companyId); } - + // 更新收款主体 $updateData = ['payment_subject' => $paymentSubject]; $this->entityRepository->updateBy( ['distributor_id' => $distributorId, 'company_id' => $companyId], $updateData ); - + return true; } /** * 校验店铺支付配置 - * + * * @param int $companyId 公司ID * @param int $distributorId 店铺ID * @throws ResourceException @@ -1367,17 +1372,17 @@ class DistributorService app('log')->debug('validateDistributorPaymentConfig::paymentStatus====>'.json_encode($paymentStatus, 1)); $wxpayOpen = $paymentStatus['wxpay']['is_open'] ?? false; $alipayOpen = $paymentStatus['alipay']['is_open'] ?? false; - + // 检查是否至少有一个支付方式开启 if (!$wxpayOpen && !$alipayOpen) { throw new ResourceException(trans('DistributionBundle/Services/DistributorService.switch_to_distributor_payment_subject_need_at_least_one_payment')); } - + // 检查已开启的支付方式配置是否完整 if ($wxpayOpen) { $this->validateWxpayConfig($companyId, $distributorId); } - + if ($alipayOpen) { $this->validateAlipayConfig($companyId, $distributorId); } @@ -1385,7 +1390,7 @@ class DistributorService /** * 校验平台支付配置 - * + * * @param int $companyId 公司ID * @throws ResourceException */ @@ -1396,12 +1401,12 @@ class DistributorService app('log')->debug('validatePlatformPaymentConfig::paymentStatus====>'.json_encode($paymentStatus)); $wxpayOpen = $paymentStatus['wxpay']['is_open'] ?? false; $alipayOpen = $paymentStatus['alipay']['is_open'] ?? false; - + // 检查已开启的支付方式配置是否完整 if ($wxpayOpen) { $this->validateWxpayConfig($companyId, 0); } - + if ($alipayOpen) { $this->validateAlipayConfig($companyId, 0); } @@ -1409,7 +1414,7 @@ class DistributorService /** * 校验微信支付配置 - * + * * @param int $companyId 公司ID * @param int $distributorId 店铺ID,0表示平台 * @throws ResourceException @@ -1419,9 +1424,9 @@ class DistributorService $wxpayService = new WechatPayService($distributorId, false); $wxpayServiceWrapper = new PaymentsService($wxpayService); $wxpayConfig = $wxpayServiceWrapper->getPaymentSetting($companyId); - + $requiredFields = ['app_id', 'merchant_id', 'key', 'cert', 'cert_key']; - + foreach ($requiredFields as $field) { $value = $wxpayConfig[$field] ?? ''; if (empty($value) && $value !== '0') { @@ -1436,7 +1441,7 @@ class DistributorService /** * 校验支付宝配置 - * + * * @param int $companyId 公司ID * @param int $distributorId 店铺ID,0表示平台 * @throws ResourceException @@ -1446,9 +1451,9 @@ class DistributorService $alipayService = new AlipayService($distributorId, false); $alipayServiceWrapper = new PaymentsService($alipayService); $alipayConfig = $alipayServiceWrapper->getPaymentSetting($companyId); - + $requiredFields = ['app_id', 'ali_public_key', 'private_key']; - + foreach ($requiredFields as $field) { $value = $alipayConfig[$field] ?? ''; if (empty($value) && $value !== '0') { diff --git a/src/DistributionBundle/Services/DistributorWhiteListService.php b/src/DistributionBundle/Services/DistributorWhiteListService.php index 79c764c..8570c9d 100644 --- a/src/DistributionBundle/Services/DistributorWhiteListService.php +++ b/src/DistributionBundle/Services/DistributorWhiteListService.php @@ -179,7 +179,7 @@ class DistributorWhiteListService return []; } $distributor_id = array_column($list,null,'distributor_id'); - $distributorList = $this->distributorRepository->getLists(['distributor_id' => array_keys($distributor_id)], '*', 1, -1); + $distributorList = $this->distributorRepository->getLists(['distributor_id' => array_keys($distributor_id), 'is_valid' => 'true'], '*', 1, -1); if(empty($distributorList)){ return []; } diff --git a/src/DistributionBundle/Services/PickupLocationService.php b/src/DistributionBundle/Services/PickupLocationService.php index e0d9e7d..205d604 100644 --- a/src/DistributionBundle/Services/PickupLocationService.php +++ b/src/DistributionBundle/Services/PickupLocationService.php @@ -31,35 +31,151 @@ class PickupLocationService } public function checkPickupTime($companyId, $id, $pickupDate, $pickupTime) { - $filter = [ - 'company_id' => $companyId, - 'id' => $id, - ]; - $pickupLocation = $this->entityRepository->getInfo($filter); - if (!$pickupLocation) { - throw new ResourceException(trans('DistributionBundle/Services/PickupLocationService.pickup_location_not_exist')); + $pickupLocation = null; + + // 判断是否是店铺地址(负数ID) + if ($id < 0) { + // 从店铺表获取信息 + $distributorId = abs($id); + $distributorService = new DistributorService(); + $distributor = $distributorService->getInfoSimple([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId + ]); + + if (!$distributor) { + throw new ResourceException(trans('DistributionBundle/Services/PickupLocationService.pickup_location_not_exist')); + } + + // 转换店铺营业时间格式 + $hours = $this->formatDistributorHour($distributor['hour'] ?? ''); + // 从营业时间中提取工作日 + $workdays = $this->extractWorkdaysFromHours($hours); + + // 构造自提点格式的数据 + $pickupLocation = [ + 'hours' => $hours, + 'workdays' => $workdays, + ]; + } else { + // 原有逻辑:从自提点表获取 + $filter = [ + 'company_id' => $companyId, + 'id' => $id, + ]; + $pickupLocation = $this->entityRepository->getInfo($filter); + if (!$pickupLocation) { + throw new ResourceException(trans('DistributionBundle/Services/PickupLocationService.pickup_location_not_exist')); + } } + // 验证工作日 $day = date('w', strtotime($pickupDate)); if ($day == '0') { $day = '7'; } - if (!in_array($day, $pickupLocation['workdays'])) { + + // workdays 可能是字符串(逗号分隔)或数组 + $workdaysArray = is_array($pickupLocation['workdays']) + ? $pickupLocation['workdays'] + : explode(',', trim($pickupLocation['workdays'], ',')); + + if (!in_array($day, $workdaysArray)) { throw new ResourceException(trans('DistributionBundle/Services/PickupLocationService.time_slot_unavailable')); } + // 验证营业时间 $ifPickup = false; - foreach ($pickupLocation['hours'] as $val) { - if ($val[0] == $pickupTime[0] && $val[1] == $pickupTime[1]) { - $ifPickup = true; + if (!empty($pickupLocation['hours']) && is_array($pickupLocation['hours'])) { + foreach ($pickupLocation['hours'] as $val) { + if (is_array($val)) { + // 兼容两种格式: + // 1. 4元素数组 [工作日开始, 工作日结束, 时间开始, 时间结束] + // 2. 2元素数组 [时间开始, 时间结束](新格式,与自提点一致) + if (count($val) == 4) { + // 旧格式:检查时间部分(索引2和3) + if ($val[2] == $pickupTime[0] && $val[3] == $pickupTime[1]) { + $ifPickup = true; + break; + } + } elseif (count($val) == 2) { + // 新格式:直接检查时间(索引0和1) + if ($val[0] == $pickupTime[0] && $val[1] == $pickupTime[1]) { + $ifPickup = true; + break; + } + } + } } } + if (!$ifPickup) { throw new ResourceException(trans('DistributionBundle/Services/PickupLocationService.time_slot_unavailable')); } return true; } + + /** + * 转换店铺营业时间格式为自提点格式 + * @param string $hour 店铺营业时间(可能是JSON或字符串格式) + * @return array 自提点格式的营业时间 [["08:00", "23:30"]],与自提点格式保持一致(只有时间,没有工作日) + */ + public function formatDistributorHour($hour) + { + if (!$hour) { + return []; + } + + // 尝试解析为JSON + $decoded = json_decode($hour, true); + if ($decoded && is_array($decoded)) { + // 如果已经是数组格式,检查是否包含工作日信息 + $result = []; + foreach ($decoded as $item) { + if (is_array($item)) { + // 如果是4元素数组 [工作日开始, 工作日结束, 时间开始, 时间结束] + if (count($item) == 4) { + $result[] = [$item[2], $item[3]]; // 只取时间部分 + } + // 如果是2元素数组 [时间开始, 时间结束] + elseif (count($item) == 2) { + $result[] = $item; + } + } + } + if (!empty($result)) { + return $result; + } + } + + // 如果是字符串格式 "08:00-23:30",转换为数组格式(只有时间) + if (strpos($hour, '-') !== false) { + $hourParts = explode('-', $hour); + if (count($hourParts) == 2) { + return [ + [trim($hourParts[0]), trim($hourParts[1])] + ]; + } + } + + return []; + } + + /** + * 从营业时间中提取工作日 + * @param array $hours 营业时间数组(现在只有时间,没有工作日信息) + * @return string 工作日字符串,如 "1,2,3,4,5,6,7" + * + * 注意:由于 hours 格式已改为只有时间(与自提点格式一致),无法从中提取工作日 + * 店铺地址默认每天可用,返回所有工作日 + */ + public function extractWorkdaysFromHours($hours) + { + // 由于 hours 格式已改为只有时间(与自提点格式一致),无法从中提取工作日 + // 店铺地址默认每天可用 + return '1,2,3,4,5,6,7'; + } public function savePickupLocation($params) { // 判断营业时间不能重复 diff --git a/src/EspierBundle/Commands/InitMultiLangCommand.php b/src/EspierBundle/Commands/InitMultiLangCommand.php index 1ee0270..1ee23c1 100644 --- a/src/EspierBundle/Commands/InitMultiLangCommand.php +++ b/src/EspierBundle/Commands/InitMultiLangCommand.php @@ -58,17 +58,20 @@ class InitMultiLangCommand extends Command $moduleArr = ['item','other']; foreach($moduleArr as $module){ (new \CompanysBundle\MultiLang\MultiLangItem($lang,$module))->createTable(); - - $this->writeLangueConfig($lang); } + // 只写入一次配置,避免重复 + $this->writeLangueConfig($lang); // (new \CompanysBundle\MultiLang\MultiLangItem('zh-CN','other'))->createTable();dd(11); } // 写入config/langue.php private function writeLangueConfig($lang){ $config = config('langue'); - $config[] = $lang; - file_put_contents(config_path('langue.php'),'all('auth_type', 'appid', 'code', 'iv', 'encryptedData', 'signature', 'rawData', 'uid', 'source_id', 'monitor_id', 'inviter_id', 'source_from', 'distributor_id', 'salesperson_id', 'invite_code', 'employee_auth', 'purchanse_share_code', 'puid'); + $params = $request->all('auth_type', 'appid', 'code', 'iv', 'encryptedData', 'signature', 'rawData', 'uid', 'source_id', 'monitor_id', 'inviter_id', 'source_from', 'distributor_id', 'salesperson_id', 'invite_code', 'employee_auth', 'purchanse_share_code', 'puid','gu_user_id','dtid','work_userid','channel'); + app('log')->info('david----file:'.__FILE__.',line:'.__LINE__.'----params:'.json_encode($params)); $params['company_id'] = $companyId; $params['wxa_appid'] = $authInfo['wxapp_appid']; $params['authorizer_appid'] = $authInfo['woa_appid']; diff --git a/src/EspierBundle/Services/Export/TradeExportService.php b/src/EspierBundle/Services/Export/TradeExportService.php index 1e14634..308fdc4 100644 --- a/src/EspierBundle/Services/Export/TradeExportService.php +++ b/src/EspierBundle/Services/Export/TradeExportService.php @@ -58,6 +58,7 @@ class TradeExportService implements ExportFileInterface 'user_name' => '会员名称', 'totalFee' => '订单总金额', 'payFee' => '订单实付金额', + 'payPoint' => '订单实付积分', 'discountFee' => '订单优惠金额', 'transactionId' => '支付流水号', 'payDate' => '支付时间', @@ -169,7 +170,21 @@ class TradeExportService implements ExportFileInterface // 直接赋值,不再添加引号,由 ExportFileService 统一处理 $orderList[$key][$k] = $value[$k]; } elseif (in_array($k, ['totalFee', 'payFee', 'discountFee']) && isset($value[$k])) { - $orderList[$key][$k] = $value[$k] / 100; + // 如果是积分支付,订单实付金额显示为0 + if ($k == 'payFee' && isset($value['payType']) && $value['payType'] == 'point') { + $orderList[$key][$k] = 0; + } else { + $orderList[$key][$k] = $value[$k] / 100; + } + } elseif ($k == 'payPoint') { + // 新增:处理订单实付积分 + if (isset($value['payType']) && $value['payType'] == 'point') { + // 积分支付时,订单实付积分 = payFee 的值(积分无需除以100) + $orderList[$key][$k] = isset($value['payFee']) ? $value['payFee'] : 0; + } else { + // 非积分支付时,订单实付积分为0 + $orderList[$key][$k] = 0; + } } elseif (in_array($k, ['timeStart', 'timeExpire']) && isset($value[$k]) && $value[$k]) { $orderList[$key][$k] = date('Y-m-d H:i:s', $value[$k]); } elseif ($k == "tradeSourceType" && isset($value[$k])) { diff --git a/src/EspierBundle/Services/LoginService.php b/src/EspierBundle/Services/LoginService.php index 310d2ad..ce86261 100644 --- a/src/EspierBundle/Services/LoginService.php +++ b/src/EspierBundle/Services/LoginService.php @@ -35,6 +35,8 @@ use AliBundle\Factory\MiniAppFactory; use EmployeePurchaseBundle\Services\RelativesService; use ShuyunBundle\Jobs\MemberRegisterJob; use ShuyunBundle\Services\MembersService as ShuyunMembersService; +use ThirdPartyBundle\Services\MarketingCenter\Request as MarketingCenterRequest; +use DistributionBundle\Services\DistributorService; class LoginService { @@ -107,7 +109,6 @@ class LoginService // 创建/更新微信用户 $weChatUserData = [ - 'company_id' => $params['company_id'], 'company_id' => $params['company_id'], 'open_id' => $openId, 'unionid' => $unionId, @@ -131,6 +132,8 @@ class LoginService app('log')->info('wxappPreLogin member====>'.var_export($member, true)); if (!$member) { $member = $this->register($params); + // register push dg - 推送会员基础信息到导购端 + // $this->pushMemberBasicInfoToSalesperson($params['company_id'], $member['user_id']); } else { // 数云模式 if (config('common.oem-shuyun')) { @@ -162,6 +165,8 @@ class LoginService } } + + if (isset($params['salesperson_id']) && $params['salesperson_id']) { // 用户和导购的关联绑定 @@ -288,6 +293,31 @@ class LoginService $params['source_from'] = $wechatUser['source_from'] ?? 'default'; } + // 记录注册时的分销商和导购信息 + if (isset($params['distributor_id']) && !empty($params['distributor_id'])) { + // 如果是字符串(门店编号),转换为门店ID + $distributorService = new DistributorService(); + $distributorId = $distributorService->getShopIdByShopCode($params['distributor_id']); + if ($distributorId !== false) { + $params['reg_distributor'] = (int)$distributorId; + } else { + $params['reg_distributor'] = 0; + } + }else { + $params['reg_distributor'] = 0; + } + + //op_distributor start + // op_distributor: 注册时默认与reg_distributor保持一致 + $params['op_distributor'] = $params['reg_distributor']; + //op_distributor end + + // reg_salesperson: 取 gu_user_id,否则为空字符串 + $params['reg_salesperson'] = ''; + if (!empty($params['work_userid'])) { + $params['reg_salesperson'] = (string)$params['work_userid']; + } + // 创建用户 $result = $memberService->createMember($params); @@ -312,6 +342,10 @@ class LoginService $relativesService->bindRelative($relativeBindParams); $employeesService->delInviteCode($params['company_id'], $inviteCode); } + + // 检测导购好友关系 + $this->checkSalespersonFriendStatus($result['user_id'], $params, $params['company_id']); + $conn->commit(); return $result; @@ -454,4 +488,228 @@ class LoginService return false; } } + + /** + * 推送会员基础信息到导购端 + * @param int $companyId 企业ID + * @param int $userId 会员ID + * @return void + */ + public function pushMemberBasicInfoToSalesperson($companyId, $userId) + { + try { + $memberService = new MemberService(); + + // 获取会员完整信息(包括 members 和 members_info) + $memberInfo = $memberService->getMemberInfo([ + 'user_id' => $userId, + 'company_id' => $companyId + ], true); + + if (!$memberInfo || !isset($memberInfo['user_id'])) { + app('log')->warning('推送会员基础信息到导购端:未找到会员信息', [ + 'company_id' => $companyId, + 'user_id' => $userId + ]); + return; + } + + // 获取 unionid + $wechatUserService = new WechatUserService(); + $wechatUserInfo = $wechatUserService->getUserInfo([ + 'user_id' => $userId, + 'company_id' => $companyId + ]); + $unionid = $wechatUserInfo['unionid'] ?? ''; + + // 准备推送数据 + $pushData = [ + 'user_id' => (string)$memberInfo['user_id'], + ]; + + // unionid + if ($unionid) { + $pushData['unionid'] = $unionid; + } + + // birthday (格式:YYYY-MM-DD) + if (!empty($memberInfo['birthday'])) { + $birthday = $memberInfo['birthday']; + // 如果是时间戳,转换为日期格式 + if (is_numeric($birthday)) { + $pushData['birthday'] = date('Y-m-d', $birthday); + } else { + $pushData['birthday'] = $birthday; + } + } + + // reg_distributor (注册时的分销商编号 shop_code) + if (isset($memberInfo['reg_distributor']) && $memberInfo['reg_distributor'] > 0) { + $distributorService = new DistributorService(); + $distributorInfo = $distributorService->getInfoSimple([ + 'company_id' => $companyId, + 'distributor_id' => $memberInfo['reg_distributor'] + ]); + if ($distributorInfo && !empty($distributorInfo['shop_code'])) { + $pushData['reg_distributor'] = $distributorInfo['shop_code']; + } + } + + // reg_salesperson (注册时的导购ID) + if (isset($memberInfo['reg_salesperson']) && !empty($memberInfo['reg_salesperson'])) { + $pushData['reg_salesperson'] = (string)$memberInfo['reg_salesperson']; + } + + // fp_salesperson (分配的导购ID) + if (isset($memberInfo['fp_salesperson']) && $memberInfo['fp_salesperson'] > 0) { + $pushData['fp_salesperson'] = (int)$memberInfo['fp_salesperson']; + } + + // has_fp (是否有分配导购。0:否;1:是) + if (isset($memberInfo['has_fp'])) { + $pushData['has_fp'] = (int)$memberInfo['has_fp']; + } + + // grade_id (会员等级ID) + if (!empty($memberInfo['grade_id'])) { + $pushData['grade_id'] = (int)$memberInfo['grade_id']; + } + + // mobile (手机号) + if (!empty($memberInfo['mobile'])) { + $pushData['mobile'] = $memberInfo['mobile']; + } + + // username (用户名) + if (!empty($memberInfo['username'])) { + $pushData['username'] = $memberInfo['username']; + } + + // avatar (头像URL) + if (!empty($memberInfo['avatar'])) { + $pushData['avatar'] = $memberInfo['avatar']; + } + + // 调用导购端接口推送数据 + $marketingCenterRequest = new MarketingCenterRequest(); + $result = $marketingCenterRequest->call($companyId, 'basics.member.syncBasicInfo', $pushData); + + app('log')->info('推送会员基础信息到导购端', [ + 'company_id' => $companyId, + 'user_id' => $userId, + 'push_data' => $pushData, + 'result' => $result + ]); + + } catch (\Exception $e) { + // 推送失败不影响注册流程,只记录日志 + app('log')->error('推送会员基础信息到导购端失败', [ + 'company_id' => $companyId, + 'user_id' => $userId, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString() + ]); + } + } + + /** + * 检测导购好友关系并更新会员信息 + * @param int $userId 会员ID + * @param array $params 注册参数 + * @param int $companyId 公司ID + */ + public function checkSalespersonFriendStatus($userId, $params, $companyId) + { + try { + // 检查是否有unionid和门店信息 + $unionid = $params['unionid'] ?? ''; + if (empty($unionid)) { + app('log')->info('注册时检测导购好友关系:缺少unionid,跳过检测', [ + 'user_id' => $userId, + 'company_id' => $companyId + ]); + return; + } + + // 获取门店编号(shop_code) + $shopCode = ''; + $distributorId = $params['reg_distributor'] ?? $params['op_distributor'] ?? 0; + + if ($distributorId > 0) { + $distributorService = new DistributorService(); + $distributorInfo = $distributorService->getInfoSimple([ + 'distributor_id' => $distributorId, + 'company_id' => $companyId + ]); + $shopCode = $distributorInfo['shop_code'] ?? ''; + } + + if (empty($shopCode)) { + app('log')->info('注册时检测导购好友关系:缺少门店编号,跳过检测', [ + 'user_id' => $userId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId + ]); + return; + } + + // 调用接口查询导购好友关系 + $marketingCenterRequest = new MarketingCenterRequest(); + $apiParams = [ + 'shop_code' => $shopCode, + 'unionid' => $unionid + ]; + + app('log')->info('注册时检测导购好友关系:开始查询', [ + 'user_id' => $userId, + 'company_id' => $companyId, + 'shop_code' => $shopCode, + 'unionid' => $unionid + ]); + + $result = $marketingCenterRequest->call($companyId, 'members.getFriendWorkUserid', $apiParams); + + app('log')->info('注册时检测导购好友关系:接口返回', [ + 'user_id' => $userId, + 'company_id' => $companyId, + 'result' => $result + ]); + + // 检查返回结果 + if (!empty($result['data']['work_userid'])) { + $workUserid = $result['data']['work_userid']; + + // 如果有work_userid(已加好友),更新会员信息 + if (!empty($workUserid)) { + $memberService = new MemberService(); + $updateParams = [ + 'has_fp' => 1, + 'is_become_friend' => 1, + 'fp_salesperson' => $workUserid + ]; + $filter = [ + 'user_id' => $userId, + 'company_id' => $companyId + ]; + + $memberService->updateMemberInfo($updateParams, $filter); + + app('log')->info('注册时检测导购好友关系:已更新会员信息', [ + 'user_id' => $userId, + 'company_id' => $companyId, + 'work_userid' => $workUserid, + 'update_params' => $updateParams + ]); + } + } + } catch (\Exception $e) { + // 检测失败不影响注册流程,只记录日志 + app('log')->error('注册时检测导购好友关系失败', [ + 'user_id' => $userId, + 'company_id' => $companyId, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString() + ]); + } + } } diff --git a/src/GoodsBundle/Api/V1/Action/ItemsCategory.php b/src/GoodsBundle/Api/V1/Action/ItemsCategory.php index ecc36c2..22b2212 100644 --- a/src/GoodsBundle/Api/V1/Action/ItemsCategory.php +++ b/src/GoodsBundle/Api/V1/Action/ItemsCategory.php @@ -300,6 +300,20 @@ class ItemsCategory extends BaseController * required=true, * type="integer" * ), + * @SWG\Parameter( + * name="item_id", + * in="query", + * description="商品ID", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="is_point", + * in="query", + * description="是否积分商品,1=积分商品,0=普通商品", + * required=false, + * type="integer" + * ), * @SWG\Response( * response=200, * description="成功返回结构", @@ -327,10 +341,11 @@ class ItemsCategory extends BaseController * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/ServiceErrorRespones") ) ) * ) */ - public function getCategoryInfo(request $request, $company_id, $category_id) + public function getCategoryInfo($company_id, $category_id) { $filter['category_id'] = $category_id; $filter['company_id'] = $company_id; + $validator = app('validator')->make($filter, [ 'category_id' => 'required|integer|min:1', 'company_id' => 'required|integer|min:1', @@ -338,6 +353,7 @@ class ItemsCategory extends BaseController if ($validator->fails()) { throw new ResourceException('删除分类出错.', $validator->errors()); } + $itemsCategoryService = new ItemsCategoryService(); $result = $itemsCategoryService->getCategoryInfo($filter); return $this->response->array($result); @@ -418,6 +434,9 @@ class ItemsCategory extends BaseController throw new ResourceException('分类名称不能重复'); } } + if (empty($data['customize_page_id'])) { + $data['customize_page_id'] = 0; + } $result = $itemsCategoryService->updateOneBy(['category_id' => $category_id, 'company_id' => $company_id], $data); diff --git a/src/GoodsBundle/ApiServices/ItemsCategoryService.php b/src/GoodsBundle/ApiServices/ItemsCategoryService.php index 8b5ac09..49b3822 100644 --- a/src/GoodsBundle/ApiServices/ItemsCategoryService.php +++ b/src/GoodsBundle/ApiServices/ItemsCategoryService.php @@ -18,6 +18,8 @@ namespace GoodsBundle\ApiServices; use GoodsBundle\Entities\ItemsCategory; +use GoodsBundle\Entities\ItemRelAttributes; +use PointsmallBundle\Entities\PointsmallItemRelAttributes; use Dingo\Api\Exception\ResourceException; use GoodsBundle\Events\ItemCategoryAddEvent; use GoodsBundle\Services\ItemsRelCatsService; @@ -135,6 +137,7 @@ class ItemsCategoryService $itemsAttributesService = new ItemsAttributesService(); $attrList = $itemsAttributesService->getAttrList(['attribute_id' => $attributeIds], 1, 100); + $itemInfo['goods_params'] = []; $itemInfo['goods_spec'] = []; foreach ($attrList['list'] as $row) { diff --git a/src/GoodsBundle/Entities/ItemsCategory.php b/src/GoodsBundle/Entities/ItemsCategory.php index 36933a9..742e599 100644 --- a/src/GoodsBundle/Entities/ItemsCategory.php +++ b/src/GoodsBundle/Entities/ItemsCategory.php @@ -49,6 +49,13 @@ class ItemsCategory */ private $company_id; + /** + * @var integer + * + * @ORM\Column(name="regionauth_id", type="bigint", options={"comment":"地区ID", "default":0}) + */ + private $regionauth_id = 0; + /** * @var string * @@ -174,7 +181,7 @@ class ItemsCategory * * @ORM\Column(name="customize_page_id", type="bigint", nullable=true, options={"comment":"自定义模板id", "default":"0"}) */ - private $customize_page_id; + private $customize_page_id = 0; /** * @var integer @@ -232,6 +239,30 @@ class ItemsCategory return $this->company_id; } + /** + * Set regionauthId + * + * @param integer $regionauthId + * + * @return ItemsCategory + */ + public function setRegionauthId($regionauthId) + { + $this->regionauth_id = $regionauthId; + + return $this; + } + + /** + * Get regionauthId + * + * @return integer + */ + public function getRegionauthId() + { + return $this->regionauth_id; + } + /** * Set categoryName * diff --git a/src/GoodsBundle/Entities/ItemsGroup.php b/src/GoodsBundle/Entities/ItemsGroup.php new file mode 100644 index 0000000..74f643e --- /dev/null +++ b/src/GoodsBundle/Entities/ItemsGroup.php @@ -0,0 +1,226 @@ +id; + } + + /** + * Set companyId. + * + * @param int $companyId + * + * @return ItemsGroup + */ + public function setCompanyId($companyId) + { + $this->company_id = $companyId; + + return $this; + } + + /** + * Get companyId. + * + * @return int + */ + public function getCompanyId() + { + return $this->company_id; + } + + /** + * Set regionauthId. + * + * @param int $regionauthId + * + * @return ItemsGroup + */ + public function setRegionauthId($regionauthId) + { + $this->regionauth_id = $regionauthId; + + return $this; + } + + /** + * Get regionauthId. + * + * @return int + */ + public function getRegionauthId() + { + return $this->regionauth_id; + } + + /** + * Set groupKey. + * + * @param string $groupKey + * + * @return ItemsGroup + */ + public function setGroupKey($groupKey) + { + $this->group_key = $groupKey; + + return $this; + } + + /** + * Get groupKey. + * + * @return string + */ + public function getGroupKey() + { + return $this->group_key; + } + + /** + * Set remark. + * + * @param string $remark + * + * @return ItemsGroup + */ + public function setRemark($remark) + { + $this->remark = $remark; + + return $this; + } + + /** + * Get remark. + * + * @return string + */ + public function getRemark() + { + return $this->remark; + } + + /** + * Set created. + * + * @param int $created + * + * @return ItemsGroup + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return ItemsGroup + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} + diff --git a/src/GoodsBundle/Entities/ItemsGroupRelItem.php b/src/GoodsBundle/Entities/ItemsGroupRelItem.php new file mode 100644 index 0000000..314eb63 --- /dev/null +++ b/src/GoodsBundle/Entities/ItemsGroupRelItem.php @@ -0,0 +1,322 @@ +id; + } + + /** + * Set companyId. + * + * @param int $companyId + * + * @return ItemsGroupRelItem + */ + public function setCompanyId($companyId) + { + $this->company_id = $companyId; + + return $this; + } + + /** + * Get companyId. + * + * @return int + */ + public function getCompanyId() + { + return $this->company_id; + } + + /** + * Set regionauthId. + * + * @param int $regionauthId + * + * @return ItemsGroupRelItem + */ + public function setRegionauthId($regionauthId) + { + $this->regionauth_id = $regionauthId; + + return $this; + } + + /** + * Get regionauthId. + * + * @return int + */ + public function getRegionauthId() + { + return $this->regionauth_id; + } + + /** + * Set groupId. + * + * @param int $groupId + * + * @return ItemsGroupRelItem + */ + public function setGroupId($groupId) + { + $this->group_id = $groupId; + + return $this; + } + + /** + * Get groupId. + * + * @return int + */ + public function getGroupId() + { + return $this->group_id; + } + + /** + * Set itemId. + * + * @param int $itemId + * + * @return ItemsGroupRelItem + */ + public function setItemId($itemId) + { + $this->item_id = $itemId; + + return $this; + } + + /** + * Get itemId. + * + * @return int + */ + public function getItemId() + { + return $this->item_id; + } + + /** + * Set goodsId. + * + * @param int $goodsId + * + * @return ItemsGroupRelItem + */ + public function setGoodsId($goodsId) + { + $this->goods_id = $goodsId; + + return $this; + } + + /** + * Get goodsId. + * + * @return int + */ + public function getGoodsId() + { + return $this->goods_id; + } + + /** + * Set isDel. + * + * @param int $isDel + * + * @return ItemsGroupRelItem + */ + public function setIsDel($isDel) + { + $this->is_del = $isDel; + + return $this; + } + + /** + * Get isDel. + * + * @return int + */ + public function getIsDel() + { + return $this->is_del; + } + + /** + * Set created. + * + * @param int $created + * + * @return ItemsGroupRelItem + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return ItemsGroupRelItem + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } + + /** + * Set groupType. + * + * @param string $groupType + * + * @return ItemsGroupRelItem + */ + public function setGroupType($groupType) + { + $this->group_type = $groupType; + + return $this; + } + + /** + * Get groupType. + * + * @return string + */ + public function getGroupType() + { + return $this->group_type; + } +} + diff --git a/src/GoodsBundle/Http/AdminApi/V1/Action/Items.php b/src/GoodsBundle/Http/AdminApi/V1/Action/Items.php index 8e40c1a..1027261 100644 --- a/src/GoodsBundle/Http/AdminApi/V1/Action/Items.php +++ b/src/GoodsBundle/Http/AdminApi/V1/Action/Items.php @@ -115,7 +115,7 @@ class Items extends BaseController $userId = $request->get('user_id', 0); if ($result['list']) { // 计算会员价 - $result = $itemsService->getItemsListMemberPrice($result, $userId, $params['company_id']); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], $userId, $params['company_id']); } $result = $itemsService->getItemsListActityTag($result, $params['company_id']); $result['cur'] = $this->getCur($params['company_id']); @@ -230,7 +230,7 @@ class Items extends BaseController //营销标签 $itemsService = new ItemsService(); $itemList['list'][0] = $result; - $itemList = $itemsService->getItemsListActityTag($itemList, $authInfo['company_id']); + $itemList['list'] = $itemsService->getItemsListActityTag($itemList['list'], $authInfo['company_id']); $result = $itemList['list'][0]; if ($result['promotion_activity'] ?? 0) { @@ -335,7 +335,7 @@ class Items extends BaseController } $result = $itemsService->getItemListData($params, $page, $pageSize, $orderBy, false); } - $result = $itemsService->getItemsListActityTag($result, $authInfo['company_id']); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $authInfo['company_id']); return $this->response->array($result); } } diff --git a/src/GoodsBundle/Http/Api/V1/Action/Items.php b/src/GoodsBundle/Http/Api/V1/Action/Items.php index c6b2a19..52618b0 100644 --- a/src/GoodsBundle/Http/Api/V1/Action/Items.php +++ b/src/GoodsBundle/Http/Api/V1/Action/Items.php @@ -743,7 +743,11 @@ class Items extends BaseController //获取translation // $result['translation'] = (new MultiLangService())->getTranslation($result['item_id'],'items'); //后台也改成替换 - $result = (new MultiLangService())->getTranslationByLang($result,$result['item_id'],'items'); + if ($operate_source == 'supplier' && !$page_from){ + $result = (new MultiLangService())->getTranslationByLang($result,$result['item_id'],'supplier_items'); + }else { + $result = (new MultiLangService())->getTranslationByLang($result,$result['item_id'],'items'); + } if (!is_array($result['intro'])) { json_decode($result['intro']); @@ -1380,6 +1384,10 @@ class Items extends BaseController if (isset($inputData['item_name']) && $inputData['item_name']) { $params['item_name|contains'] = $request->input('item_name'); } + if(!empty($inputData['created_time_start']) && !empty($inputData['created_time_end'])){ + $params['created|gte'] = $inputData['created_time_start']; + $params['created|lte'] = $inputData['created_time_end']; + } if (isset($inputData['consume_type']) && $inputData['consume_type']) { $params['consume_type'] = $request->input('consume_type'); } @@ -1746,7 +1754,7 @@ class Items extends BaseController $pageSize = ($pageSize <= 0) ? 10 : $pageSize; $result = $itemsService->getItemsList($params, $page, $pageSize); } - $result = $itemsService->dealListStore($result); + $result = $itemsService->dealListStore($result,$isGetSkuList); $result['warning_store'] = $warningStore; $result['filter'] = $params; @@ -1754,7 +1762,7 @@ class Items extends BaseController if ($result['list']) { //营销标签 if (method_exists($itemsService, 'getItemsListActityTag')) { - $result = $itemsService->getItemsListActityTag($result, $params['company_id']); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $params['company_id']); } $itemIds = array_column($result['list'], 'item_id'); @@ -2159,7 +2167,7 @@ class Items extends BaseController if ($result['list']) { //营销标签 - $result = $itemsService->getItemsListActityTag($result, $params['company_id']); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $params['company_id']); //获取商品标签 $itemIds = array_column($result['list'], 'item_id'); $tagFilter = [ @@ -2640,10 +2648,10 @@ class Items extends BaseController // 如果是推广员不需要计算会员价 if ($result['list']) { // 计算会员价 - $result = $itemsService->getItemsListMemberPrice($result, 0, $filter['company_id']); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], 0, $filter['company_id']); } //营销标签 - $result = $itemsService->getItemsListActityTag($result, $filter['company_id']); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $filter['company_id']); return $this->response->array($result); } diff --git a/src/GoodsBundle/Http/Api/V1/Action/ItemsCategory.php b/src/GoodsBundle/Http/Api/V1/Action/ItemsCategory.php index c43c008..2a301a4 100644 --- a/src/GoodsBundle/Http/Api/V1/Action/ItemsCategory.php +++ b/src/GoodsBundle/Http/Api/V1/Action/ItemsCategory.php @@ -409,11 +409,27 @@ class ItemsCategory extends BaseController public function getCategoryInfo($category_id, request $request) { $filter['company_id'] = app('auth')->user()->get('company_id'); - $itemsCategoryService = new ItemsCategoryService(); - $filter['category_id'] = $category_id; - - $result = $itemsCategoryService->getCategoryInfo($filter); + $item_id = $request->input('item_id'); + $is_point = $request->input('is_point', 0); + $otherParmas = []; + if ($item_id) { + $validator = app('validator')->make([ + 'item_id' => $item_id, + 'is_point' => $is_point, + ], [ + 'item_id' => 'required|integer|min:1', + 'is_point' => 'in:0,1', + ]); + if ($validator->fails()) { + throw new ResourceException('参数错误.', $validator->errors()); + } + $otherParmas['item_id'] = $item_id; + $otherParmas['is_point'] = $is_point; + } + $itemsCategoryService = new ItemsCategoryService(); + $result = $itemsCategoryService->getCategoryInfo($filter, $otherParmas); + return $this->response->array($result); } diff --git a/src/GoodsBundle/Http/Api/V1/Action/ItemsGroupController.php b/src/GoodsBundle/Http/Api/V1/Action/ItemsGroupController.php new file mode 100644 index 0000000..6308cd8 --- /dev/null +++ b/src/GoodsBundle/Http/Api/V1/Action/ItemsGroupController.php @@ -0,0 +1,78 @@ +all('rel_goods_ids', 'group_id', 'regionauth_id', 'pages_template_id'); + $rules = [ + 'rel_goods_ids' => ['required','商品ID不能为空'], + // 'group_id' => ['required','分组ID不能为空'], + 'regionauth_id' => ['required','区域ID不能为空'], + ]; + $error = validator_params($params, $rules); + if ($error) { + throw new ResourceException($error); + } + $params['company_id'] = app('auth')->user()->get('company_id'); + $itemsGroupService = new ItemsGroupService(); + if (empty($params['group_id'])) { + $group_key = 'widget-' . ($params['pages_template_id'] ?? date('Ymd-Hi')); + $group_data = [ + 'company_id' => $params['company_id'], + 'regionauth_id' => $params['regionauth_id'], + 'group_key' => $group_key, + 'remark' => '', + ]; + $itemsGroup = $itemsGroupService->repository->create($group_data); + if (!$itemsGroup) { + throw new ResourceException('分组创建失败,请稍后重试'); + } + $params['group_id'] = $itemsGroup['id']; + } else { + $itemsGroup = $itemsGroupService->repository->getInfoById($params['group_id']); + if (!$itemsGroup) { + throw new ResourceException('group_id错误'); + } + } + + $itemsGroupRelItemService = new ItemsGroupRelItemService(); + $itemsGroupRelItemService->createRelItem($params['group_id'], 'widget', $params); + return $this->response->array(['items_group' => $itemsGroup]); + } + + /** + * path="/goods/get_group_items", + * summary="获取分组商品", + */ + public function getGroupItems(Request $request) + { + $params = $request->all('page', 'pageSize', 'group_id'); + $params['page'] = $params['page'] ?? 1; + $params['pageSize'] = $params['pageSize'] ?? 100; + $filter = [ + 'group_id' => $params['group_id'], + ]; + $orderBy = [ + 'id' => 'DESC' + ]; + $itemsGroupRelItemService = new ItemsGroupRelItemService(); + $rs = $itemsGroupRelItemService->repository->getLists($filter, 'goods_id', $params['page'], $params['pageSize'], $orderBy); + $result = array_column($rs, 'goods_id'); + return $this->response->array(['goods_id' => $result]); + } + +} + diff --git a/src/GoodsBundle/Http/Api/V1/Action/ItemsTags.php b/src/GoodsBundle/Http/Api/V1/Action/ItemsTags.php index db9ba5a..e87d882 100644 --- a/src/GoodsBundle/Http/Api/V1/Action/ItemsTags.php +++ b/src/GoodsBundle/Http/Api/V1/Action/ItemsTags.php @@ -21,6 +21,7 @@ use Illuminate\Http\Request; use Dingo\Api\Exception\StoreResourceFailedException; use App\Http\Controllers\Controller as Controller; use GoodsBundle\Services\ItemsTagsService; +use CompanysBundle\MultiLang\MultiLangItem; class ItemsTags extends Controller { @@ -198,7 +199,61 @@ class ItemsTags extends Controller $filter['company_id'] = $companyId; if (isset($params['tag_name']) && $params['tag_name']) { - $filter['tag_name|contains'] = $params['tag_name']; + // tag_name是多语言字段,需要同时查询主表和多语言表,然后合并结果 + // 使用完整的语言代码(如 zh-CN),MultiLangItem 会自动处理 + $lang = $request->input('country_code', 'zh-CN'); + if (empty($lang)) { + $lang = 'zh-CN'; + } + + $tagIds = []; + + // 1. 在多语言表中查询,同时考虑company_id条件 + $multiLangItem = new MultiLangItem($lang); + $langFilter = [ + 'table_name' => 'items_tags', + 'field' => 'tag_name', + 'attribute_value|contains' => $params['tag_name'], + 'company_id' => $companyId, + ]; + $langList = $multiLangItem->getListByFilter($langFilter, -1); + if (!empty($langList)) { + $langIds = array_column($langList, 'data_id'); + $langIds = array_unique($langIds); + $tagIds = array_merge($tagIds, $langIds); + } + + // 2. 同时也在主表中查询(兼容没有多语言记录的数据) + // 直接查询主表,只考虑company_id和tag_name条件 + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('tag_id') + ->from('items_tags') + ->where('company_id = :company_id') + ->andWhere('tag_name LIKE :tag_name'); + $qb->setParameter('company_id', $companyId); + $qb->setParameter('tag_name', '%' . $params['tag_name'] . '%'); + $mainTableResult = $qb->execute()->fetchAll(\PDO::FETCH_COLUMN); + if (!empty($mainTableResult)) { + $mainTableIds = array_unique($mainTableResult); + $tagIds = array_merge($tagIds, $mainTableIds); + } + + // 3. 合并去重后的tag_id列表 + $tagIds = array_unique($tagIds); + + if (!empty($tagIds)) { + // 如果找到了匹配的tag_id,则使用tag_id查询 + if (isset($filter['tag_id'])) { + $filter['tag_id'] = array_intersect((array)$filter['tag_id'], $tagIds); + } else { + $filter['tag_id'] = $tagIds; + } + // 移除tag_name条件,因为已经通过tag_id查询了 + } else { + // 如果都没有找到,使用tag_name条件查询(虽然不太可能) + $filter['tag_name|contains'] = $params['tag_name']; + } } if($request->has('tag_source') && $tag_source = $request->input('tag_source','')){ if($tag_source == 'distributor'){ diff --git a/src/GoodsBundle/Http/FrontApi/V1/Action/Category.php b/src/GoodsBundle/Http/FrontApi/V1/Action/Category.php index 54abe0d..f876b0a 100644 --- a/src/GoodsBundle/Http/FrontApi/V1/Action/Category.php +++ b/src/GoodsBundle/Http/FrontApi/V1/Action/Category.php @@ -29,6 +29,7 @@ use PopularizeBundle\Services\PromoterGoodsService; use PopularizeBundle\Services\SettingService; use Dingo\Api\Exception\ResourceException; use SalespersonBundle\Services\SalespersonService; +use WechatBundle\Services\Wxapp\CustomizePageService; class Category extends BaseController { @@ -138,16 +139,44 @@ class Category extends BaseController $filter['is_main_category'] = $request->input('is_main_category', false); + $onlyTop = $request->input('only_top', false); + if ($onlyTop) { + $filter['parent_id'] = 0; + $filter['category_level'] = 1; + } + $itemsCategoryService = new ItemsCategoryService(); - $result = $itemsCategoryService->getItemsCategory($filter, true, 1, -1, ['sort' => 'DESC', 'created' => 'ASC'], 'category_id,category_name,category_level,parent_id,image_url'); + $result = $itemsCategoryService->getItemsCategory($filter, true, 1, -1, ['sort' => 'DESC', 'created' => 'ASC'], 'category_id,category_name,category_level,parent_id,image_url,customize_page_id'); + // 分类获取不到获取商城主类目 if (false == $filter['is_main_category'] && !$result) { $filter['is_main_category'] = true; if (isset($filter['distributor_id'])) { unset($filter['distributor_id']); } - $result = $itemsCategoryService->getItemsCategory($filter, true, 1, -1, ['sort' => 'DESC', 'created' => 'ASC'], 'category_id,category_name,category_level,parent_id,image_url'); + $result = $itemsCategoryService->getItemsCategory($filter, true, 1, -1, ['sort' => 'DESC', 'created' => 'ASC'], 'category_id,category_name,category_level,parent_id,image_url,customize_page_id'); } + + if ($result) { + $pageIds = array_filter(array_column($result, 'customize_page_id')); + if ($pageIds) { + $pageFilter = [ + 'company_id' => $company_id, + 'is_open' => 1, + 'page_type' => 'category', + 'id' => $pageIds, + ]; + $customizePageService = new CustomizePageService(); + $pageList = $customizePageService->lists($pageFilter, 'id'); + $validPageIds = array_column($pageList['list'], 'id'); + foreach ($result as $key => $value) { + if ($value['customize_page_id'] && !in_array($value['customize_page_id'], $validPageIds)) { + $result[$key]['customize_page_id'] = 0; + } + } + } + } + return $this->response->array($result); } /** diff --git a/src/GoodsBundle/Http/FrontApi/V1/Action/Items.php b/src/GoodsBundle/Http/FrontApi/V1/Action/Items.php index 9411d25..62ae699 100644 --- a/src/GoodsBundle/Http/FrontApi/V1/Action/Items.php +++ b/src/GoodsBundle/Http/FrontApi/V1/Action/Items.php @@ -431,10 +431,10 @@ class Items extends BaseController $itemsService = new ItemsService(); $result = $itemsService->getItemListData($params, $page, $pageSize, $orderBy, false); - $result = $itemsService->getItemsListMemberPrice($result, $authInfo['user_id'], $params['company_id']); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], $authInfo['user_id'], $params['company_id']); //营销标签 - $result = $itemsService->getItemsListActityTag($result, $params['company_id']); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $params['company_id']); $result['goods_total'] = $result['total_count'];//兼容前端 @@ -761,6 +761,7 @@ class Items extends BaseController $params['or']['item_id'] = $itemIds; } } + $params['keywords'] = $keywords; } if ($request->input('item_name')) { @@ -996,10 +997,10 @@ class Items extends BaseController // 如果是推广员不需要计算会员价 if ($result['list']) { // 计算会员价 - $result = $itemsService->getItemsListMemberPrice($result, $authInfo['user_id'], $params['company_id']); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], $authInfo['user_id'], $params['company_id']); } //营销标签 - $result = $itemsService->getItemsListActityTag($result, $params['company_id']); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $params['company_id']); } $memberFavItemsId = []; diff --git a/src/GoodsBundle/Http/FrontApi/V1/Action/ItemsGroupController.php b/src/GoodsBundle/Http/FrontApi/V1/Action/ItemsGroupController.php new file mode 100644 index 0000000..17689df --- /dev/null +++ b/src/GoodsBundle/Http/FrontApi/V1/Action/ItemsGroupController.php @@ -0,0 +1,48 @@ + []]; + // $authInfo = $request->get('auth'); + // + // $filter['company_id'] = $authInfo['company_id']; + // $filter['regionauth_id'] = $request->get('regionauth_id', 0); + // $filter['group_id'] = intval($request->get('group_id', 0)); + // if (!$filter['group_id']) { + // return $this->response->array($result); + // } + // + // $page = intval($request->input('page', 1)); + // $pageSize = min(intval($request->input('pageSize', 10)), 20); + // + // $params = $request->all('page', 'pageSize', 'group_id'); + // $filter = [ + // 'group_id' => $params['group_id'], + // ]; + // $itemsGroupRelItemService = new ItemsGroupRelItemService(); + // $rs = $itemsGroupRelItemService->getWxappGroupItems($filter, $page, $pageSize); + // if ($rs) { + // $goods_id = array_column($rs, 'goods_id'); + // //处理商品促销标签等 + // foreach ($rs as $v) { + // $result['items'][] = $v; + // } + // } + return $this->response->array($result); + } + +} + + diff --git a/src/GoodsBundle/Http/FrontApi/V1/Action/SalespersonItems.php b/src/GoodsBundle/Http/FrontApi/V1/Action/SalespersonItems.php index b8ca46b..04ad6ee 100644 --- a/src/GoodsBundle/Http/FrontApi/V1/Action/SalespersonItems.php +++ b/src/GoodsBundle/Http/FrontApi/V1/Action/SalespersonItems.php @@ -484,7 +484,7 @@ class SalespersonItems extends BaseController //营销标签 $itemsService = new ItemsService(); $itemList['list'][0] = $result; - $itemList = $itemsService->getItemsListActityTag($itemList, $authInfo['company_id']); + $itemList['list'] = $itemsService->getItemsListActityTag($itemList['list'], $authInfo['company_id']); $result = $itemList['list'][0]; if ($result['promotion_activity'] ?? 0) { diff --git a/src/GoodsBundle/Http/FrontApi/V2/Action/Items.php b/src/GoodsBundle/Http/FrontApi/V2/Action/Items.php index 8708e17..eebc80e 100644 --- a/src/GoodsBundle/Http/FrontApi/V2/Action/Items.php +++ b/src/GoodsBundle/Http/FrontApi/V2/Action/Items.php @@ -36,6 +36,7 @@ use OrdersBundle\Services\CartService; use GoodsBundle\Services\ItemsRecommendService; use CompanysBundle\Services\SettingService as ItemSettingService; use TdksetBundle\Services\TdkGivenService; +use KujialeBundle\Services\KujialeDesignerWorksService; class Items extends BaseController { @@ -624,6 +625,14 @@ class Items extends BaseController } $result['itemName'] = $result['item_name']; + // 获取商品关联的设计作品 + try { + $designerWorksService = new KujialeDesignerWorksService(); + $result['design_works'] = $designerWorksService->getDesignerWorksByItemId($item_id); + } catch (\Exception $e) { + // 如果查询失败,返回空数组 + $result['design_works'] = []; + } return $this->response->array($result); } diff --git a/src/GoodsBundle/Repositories/ItemsCategoryRepository.php b/src/GoodsBundle/Repositories/ItemsCategoryRepository.php index 9801964..1870ab5 100644 --- a/src/GoodsBundle/Repositories/ItemsCategoryRepository.php +++ b/src/GoodsBundle/Repositories/ItemsCategoryRepository.php @@ -624,6 +624,9 @@ class ItemsCategoryRepository extends EntityRepository if (isset($data["company_id"]) && $data["company_id"]) { $entity->setCompanyId($data["company_id"]); } + if (isset($data["regionauth_id"]) && $data["regionauth_id"]) { + $entity->setRegionauthId($data["regionauth_id"]); + } if (isset($data["category_name"]) && $data["category_name"]) { $entity->setCategoryName($data["category_name"]); } @@ -676,7 +679,7 @@ class ItemsCategoryRepository extends EntityRepository $entity->setCategoryCode($data['category_code']); } - if (isset($data["customize_page_id"]) && $data['customize_page_id']) { + if (isset($data["customize_page_id"])) { $entity->setCustomizePageId($data['customize_page_id']); } if (isset($data["category_id_taobao"]) && $data['category_id_taobao']) { @@ -707,6 +710,7 @@ class ItemsCategoryRepository extends EntityRepository return [ 'id' => $entity->getCategoryId(), 'category_id' => $entity->getCategoryId(), + 'regionauth_id' => $entity->getRegionauthId(), 'company_id' => $entity->getCompanyId(), 'category_name' => $entity->getCategoryName(), 'label' => $entity->getCategoryName(), diff --git a/src/GoodsBundle/Repositories/ItemsGroupRelItemRepository.php b/src/GoodsBundle/Repositories/ItemsGroupRelItemRepository.php new file mode 100644 index 0000000..6b93e04 --- /dev/null +++ b/src/GoodsBundle/Repositories/ItemsGroupRelItemRepository.php @@ -0,0 +1,63 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + public function createQuick($data = []) + { + if (!$data) { + return false; + } + + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder(); + + $columns = array(); + foreach ($data[0] as $columnName => $value) { + $columns[] = $columnName; + } + + $sql = 'INSERT INTO '.$this->table. ' (' . implode(', ', $columns) . ') VALUES '; + + $insertValue = []; + foreach($data as $value) { + foreach($value as &$v) { + $v = $qb->expr()->literal($v); + } + $insertValue[] = '(' . implode(', ', $value) . ')'; + } + + $sql .= implode(',',$insertValue); + return $conn->executeUpdate($sql); + } + +} + diff --git a/src/GoodsBundle/Repositories/ItemsGroupRepository.php b/src/GoodsBundle/Repositories/ItemsGroupRepository.php new file mode 100644 index 0000000..8e3ae3d --- /dev/null +++ b/src/GoodsBundle/Repositories/ItemsGroupRepository.php @@ -0,0 +1,35 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + +} + diff --git a/src/GoodsBundle/Repositories/ItemsRepository.php b/src/GoodsBundle/Repositories/ItemsRepository.php index 22d0c4f..d52c81d 100644 --- a/src/GoodsBundle/Repositories/ItemsRepository.php +++ b/src/GoodsBundle/Repositories/ItemsRepository.php @@ -448,7 +448,12 @@ class ItemsRepository extends EntityRepository return []; } - return $this->getColumnNamesData($entity); + $result = $this->getColumnNamesData($entity); + //替换语言 + $service = new MultiLangService(); + $lang = $this->getLang(); + $result = $service->getOneLangData($result,$this->multiLangField,$this->table,$lang,$result['item_id'],$this->table); + return $result; } /** @@ -731,11 +736,15 @@ class ItemsRepository extends EntityRepository foreach ($businessLogicFields as $field) { unset($dbFilter[$field]); } + // 多语言处理filter + $service = new MultiLangService(); + $dbFilter = $service->filterLang($dbFilter, $this->multiLangField, $this->table, $this->prk); $conn = app('registry')->getConnection('default'); $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); $qb = $this->_filter($dbFilter, $qb); $lists = $qb->execute()->fetchAll(); + $lists = $service->getListAddLang($lists,$this->multiLangField,$this->table,$this->getLang(),$this->prk); return $lists; } @@ -864,7 +873,6 @@ class ItemsRepository extends EntityRepository 'distributor_ids' => $distributorIds, 'item_params' => $itemParams, 'item_spec' => $itemSpec, - 'discount_rate' => $discountRate, ]; } diff --git a/src/GoodsBundle/Services/ItemsCategoryService.php b/src/GoodsBundle/Services/ItemsCategoryService.php index 983847e..44a8a30 100644 --- a/src/GoodsBundle/Services/ItemsCategoryService.php +++ b/src/GoodsBundle/Services/ItemsCategoryService.php @@ -17,10 +17,14 @@ namespace GoodsBundle\Services; +use GoodsBundle\Entities\Items; +use EspierBundle\Services\BusService; use GoodsBundle\Entities\ItemsCategory; use Dingo\Api\Exception\ResourceException; -use EspierBundle\Services\BusService; +use GoodsBundle\Entities\ItemRelAttributes; use GoodsBundle\Services\MultiLang\MagicLangTrait; +use PointsmallBundle\Entities\PointsmallItemRelAttributes; +use PointsmallBundle\Entities\PointsmallItems; class ItemsCategoryService { @@ -261,7 +265,7 @@ class ItemsCategoryService /** * 获取单个分类信息 */ - public function getCategoryInfo($filter) + public function getCategoryInfo($filter, $otherParams = []) { $itemInfo = $this->itemsCategoryRepository->getInfo($filter); if (!$itemInfo) { @@ -274,12 +278,49 @@ class ItemsCategoryService $itemsAttributesService = new ItemsAttributesService(); $attrList = $itemsAttributesService->getAttrList(['attribute_id' => $attributeIds], 1, 100, ['attribute_sort' => 'asc']); + + // 如果提供了item_id,获取商品的自定义属性值 + $customAttributeValues = []; + if (isset($otherParams['item_id']) && $otherParams['item_id']) { + $isPoint = isset($otherParams['is_point']) ? $otherParams['is_point'] : 0; + $customAttributeValues = $this->getItemCustomAttributeValues($otherParams['item_id'], $filter['company_id'], $isPoint, $attributeIds); + } + $itemInfo['goods_params'] = []; $itemInfo['goods_spec'] = []; foreach ($attrList['list'] as $row) { if ($row['attribute_type'] == 'item_params') { + // 处理商品参数的自定义属性值 + // 如果有attribute_values列表,需要在对应的属性值上显示自定义值 + if (isset($row['attribute_values']['list']) && is_array($row['attribute_values']['list'])) { + foreach ($row['attribute_values']['list'] as &$attrValue) { + // 先检查是否有针对该attribute_value_id的自定义值 + $key = $row['attribute_id'] . '_' . $attrValue['attribute_value_id']; + if (isset($customAttributeValues[$key])) { + $attrValue['custom_attribute_value'] = $customAttributeValues[$key]; + $attrValue['attribute_value'] = $customAttributeValues[$key]; + } + } + unset($attrValue); + } + // 如果attribute_id级别有自定义值,也添加到属性中 + if (isset($customAttributeValues[$row['attribute_id']])) { + $row['custom_attribute_value'] = $customAttributeValues[$row['attribute_id']]; + $row['attribute_value'] = $customAttributeValues[$row['attribute_id']]; + } $itemInfo['goods_params'][] = $row; } else { + // 处理规格属性,如果有自定义属性值,合并到属性值列表中 + if (isset($row['attribute_values']['list']) && is_array($row['attribute_values']['list'])) { + foreach ($row['attribute_values']['list'] as &$attrValue) { + $key = $row['attribute_id'] . '_' . $attrValue['attribute_value_id']; + if (isset($customAttributeValues[$key])) { + $attrValue['custom_attribute_value'] = $customAttributeValues[$key]; + $attrValue['attribute_value'] = $customAttributeValues[$key]; + } + } + unset($attrValue); + } $itemInfo['goods_spec'][] = $row; } } @@ -291,6 +332,66 @@ class ItemsCategoryService return $itemInfo; } + /** + * 获取商品的自定义属性值 + * @param int $itemId 商品ID + * @param int $companyId 公司ID + * @param int $isPoint 是否积分商品,1=积分商品,0=普通商品 + * @param array $attributeIds 属性ID列表 + * @return array 自定义属性值数组,key为attribute_id或attribute_id_attribute_value_id + */ + private function getItemCustomAttributeValues($itemId, $companyId, $isPoint, $attributeIds) + { + $customValues = []; + + // 传入的是多规格默认的default_item_id + // 获取所有多规格的item_id + if ($isPoint == 1) { + // 积分商品,使用PointsmallItemRelAttributes表 + $itemRelAttributesRepository = app('registry')->getManager('default')->getRepository(PointsmallItemRelAttributes::class); + $itemsRepository = app('registry')->getManager('default')->getRepository(PointsmallItems::class); + } else { + // 普通商品,使用ItemRelAttributes表 + $itemRelAttributesRepository = app('registry')->getManager('default')->getRepository(ItemRelAttributes::class); + $itemsRepository = app('registry')->getManager('default')->getRepository(Items::class); + } + $items = $itemsRepository->list([ + 'default_item_id' => $itemId, + 'company_id' => $companyId, + ],[], 100, 1); + $itemIds = array_column($items['list'], 'item_id'); + + $relAttributes = $itemRelAttributesRepository->lists([ + 'item_id' => $itemIds, + 'company_id' => $companyId, + 'attribute_id' => $attributeIds + ], 1, 100); + + if ($relAttributes['total_count'] > 0) { + foreach ($relAttributes['list'] as $relAttr) { + if (!empty($relAttr['custom_attribute_value'])) { + if ($relAttr['attribute_type'] == 'item_params') { + // 商品参数类型 + if ($relAttr['attribute_value_id']) { + // 如果有attribute_value_id,key为attribute_id_attribute_value_id + $key = $relAttr['attribute_id'] . '_' . $relAttr['attribute_value_id']; + $customValues[$key] = $relAttr['custom_attribute_value']; + } else { + // 如果没有attribute_value_id,key为attribute_id + $customValues[$relAttr['attribute_id']] = $relAttr['custom_attribute_value']; + } + } else if ($relAttr['attribute_type'] == 'item_spec' && $relAttr['attribute_value_id']) { + // 规格类型,key为attribute_id_attribute_value_id + $key = $relAttr['attribute_id'] . '_' . $relAttr['attribute_value_id']; + $customValues[$key] = $relAttr['custom_attribute_value']; + } + } + } + } + + return $customValues; + } + public function getItemsCategoryIds($categoryId, $companyId) { if (is_array($categoryId)) { diff --git a/src/GoodsBundle/Services/ItemsGroupRelItemService.php b/src/GoodsBundle/Services/ItemsGroupRelItemService.php new file mode 100644 index 0000000..3d19242 --- /dev/null +++ b/src/GoodsBundle/Services/ItemsGroupRelItemService.php @@ -0,0 +1,119 @@ +repository = app('registry')->getManager('default')->getRepository(ItemsGroupRelItem::class); + } + + /** + * 获取商品分组下的商品 goods_id + */ + public function getGroupItemsById($group_id, $data_type = 'string') + { + $rsRelItems = $this->repository->getLists(['group_id' => $group_id], 'goods_id'); + if (!$rsRelItems) { + return false; + } + if ($data_type == 'string') { + return implode(',', array_column($rsRelItems, 'goods_id')); + } + return array_column($rsRelItems, 'goods_id'); + } + + /** + * 获取商品分组下的商品 goods_id + */ + public function getGroupItems($group_key, $data_type = 'string') + { + $itemsGroupService = new ItemsGroupService(); + $itemsGroup = $itemsGroupService->repository->getInfo(['group_key' => $group_key]); + if (!$itemsGroup) { + return ''; + } + + $rsRelItems = $this->repository->getLists(['group_id' => $itemsGroup['id']], 'goods_id'); + if ($data_type == 'string') { + return implode(',', array_column($rsRelItems, 'goods_id')); + } + return array_column($rsRelItems, 'goods_id'); + } + + /** + * 写入分组商品数据 + */ + public function createRelItem($group_id, $group_type, $dataInfo) + { + if (is_string($dataInfo['rel_goods_ids'])) { + $dataInfo['rel_goods_ids'] = explode(',', $dataInfo['rel_goods_ids']); + } + $dataInfo['rel_goods_ids'] = array_filter(array_unique($dataInfo['rel_goods_ids'])); + if (!$dataInfo['rel_goods_ids']) { + return false; + } + + $delGoodsIds = [];//需要删除的 + $newGoodsIds = $dataInfo['rel_goods_ids'];//需要新写入的 + $filter = [ + 'group_id' => $group_id, + ]; + $rs = $this->repository->getLists($filter, 'goods_id'); + if ($rs) { + $oldGoodsIds = array_column($rs, 'goods_id'); + $delGoodsIds = array_diff($oldGoodsIds, $dataInfo['rel_goods_ids']); + $newGoodsIds = array_diff($dataInfo['rel_goods_ids'], $oldGoodsIds); + $rs = null; + $oldGoodsIds = null; + } + if ($delGoodsIds) { + $filter = [ + 'group_id' => $group_id, + 'goods_id' => $delGoodsIds, + ]; + $this->repository->deleteBy($filter); + $delGoodsIds = null; + } + + $batchSize = 500; + $batchData = []; + $count = 0; + foreach ($newGoodsIds as $goods_id) { + $batchData[] = [ + 'company_id' => $dataInfo['company_id'], + 'regionauth_id' => $dataInfo['regionauth_id'], + 'group_id' => $group_id, + 'group_type' => $group_type, + 'goods_id' => $goods_id, + 'created' => time(), + 'updated' => time(), + ]; + $count++; + // 每500条数据执行一次插入 + if ($count % $batchSize === 0) { + $this->repository->createQuick($batchData); + $batchData = []; // 清空批次数据 + } + } + + // 插入剩余不足500条的数据 + if (!empty($batchData)) { + $this->repository->createQuick($batchData); + } + + $newGoodsIds = null; + $batchData = null; + return true; + } +} + diff --git a/src/GoodsBundle/Services/ItemsGroupService.php b/src/GoodsBundle/Services/ItemsGroupService.php new file mode 100644 index 0000000..6bb8b78 --- /dev/null +++ b/src/GoodsBundle/Services/ItemsGroupService.php @@ -0,0 +1,65 @@ +repository = app('registry')->getManager('default')->getRepository(ItemsGroup::class); + } + + //自动创建商品分组 + public function getGroupId($group_type = '', $dataInfo = []) + { + if ($group_type == 'coupon') { + $group_key = $group_type . '-' . $dataInfo['card_id']; + } elseif ($group_type == 'marketing') { + $group_key = $group_type . '-' . $dataInfo['marketing_id']; + } + //查询分组是否存在 + $group_data = [ + 'company_id' => $dataInfo['company_id'], + 'regionauth_id' => $dataInfo['regionauth_id'], + 'group_key' => $group_key, + ]; + $itemsGroupService = new ItemsGroupService(); + $itemsGroup = $itemsGroupService->repository->getInfo($group_data); + if ($itemsGroup) { + return $itemsGroup['id']; + } + //新增商品分组 + $group_data['remark'] = $dataInfo['remark'] ?? date('Y-m-d H:i:s'); + $itemsGroup = $itemsGroupService->repository->create($group_data); + if (!$itemsGroup) { + throw new ResourceException('商品分组创建失败,请稍后重试'); + } + return $itemsGroup['id']; + } + + public function delGroupData($group_key) + { + $itemsGroupService = new ItemsGroupService(); + $itemsGroup = $itemsGroupService->repository->getLists(['group_key' => $group_key]); + if ($itemsGroup) { + foreach ($itemsGroup as $v) { + $group_id = $v['id']; + $itemsGroupRelItemService = new ItemsGroupRelItemService(); + if ($itemsGroupRelItemService->repository->getInfo(['group_id' => $group_id])) { + $itemsGroupRelItemService->repository->deleteBy(['group_id' => $group_id]); + } + $itemsGroupService->repository->deleteById($group_id); + } + } + } +} + diff --git a/src/GoodsBundle/Services/ItemsService.php b/src/GoodsBundle/Services/ItemsService.php index 195636e..31b7777 100644 --- a/src/GoodsBundle/Services/ItemsService.php +++ b/src/GoodsBundle/Services/ItemsService.php @@ -623,9 +623,19 @@ class ItemsService app('log')->debug('debug:create:item_spec:'.__FUNCTION__.':'.__LINE__.':'.json_encode($params['spec_pics'])); $paramsData['image_url'] = $params['spec_pics'] ? explode(',', $params['spec_pics']) : []; } - $sort++; - $this->itemRelAttributesRepository->create($paramsData); + // 如果商品关联规格存在更新,不存在新增 + $itemRelParamsData = [ + 'company_id' => $data['company_id'], + 'item_id' => $itemsResult['item_id'], + 'attribute_id' => $row['spec_id'], + ]; + $itemRelParamsInfo = $this->itemRelAttributesRepository->getInfo($itemRelParamsData); + if (!empty($itemRelParamsInfo)) { + $this->itemRelAttributesRepository->updateOneBy($itemRelParamsData, $paramsData); + }else { + $this->itemRelAttributesRepository->create($paramsData); + } } } @@ -818,6 +828,11 @@ class ItemsService 'item_bn' => $data['item_bn'], ]; $item = $this->itemsRepository->getInfo($_filter); + // if(!isset($params['item_id'])){ + // if(!empty($item)){ + // $params['item_id'] = $item['item_id']; + // } + // } if ($item && isset($params['item_id']) && $params['item_id'] != $item['item_id']) { throw new ResourceException(trans('GoodsBundle/Controllers/Items.item_bn_exists') . $data['item_bn']); }else if ($item && !isset($params['item_id'])) { @@ -2015,6 +2030,19 @@ class ItemsService $categoryId = $filter['category_id']; unset($filter['category_id']); } + // 根据商品主类目id,获取到对应的子类目id + if (isset($filter['item_category']) && $filter['item_category']) { + $itemsCategoryService = new ItemsCategoryService(); + $mainCatIds = []; + if (is_array($filter['item_category'])) { + foreach ($filter['item_category'] as $mainCatId) { + $mainCatIds += $itemsCategoryService->getMainCatChildIdsBy($mainCatId, $filter['company_id']); + } + } else { + $mainCatIds = $itemsCategoryService->getMainCatChildIdsBy($filter['item_category'], $filter['company_id']); + } + $filter['item_category'] = $mainCatIds; + } // 根据商品参数刷选商品ID if (isset($filter['item_params']) && $filter['item_params']) { $itemIds = $this->getItemIdsByItemParamsId($filter, $itemIds); @@ -2238,7 +2266,7 @@ class ItemsService */ public function getItemsListMemberPrice($itemList, $userId, $companyId) { - $itemIds = array_column($itemList['list'], 'item_id'); + $itemIds = array_column($itemList, 'item_id'); $memberPriceService = new MemberPriceService(); $filter = ['company_id' => $companyId, 'item_id' => $itemIds]; $priceList = $memberPriceService->lists($filter); @@ -2284,7 +2312,7 @@ class ItemsService } } - foreach ($itemList['list'] as &$item) { + foreach ($itemList as &$item) { $item['member_grade_name'] = $gradeName; $itemId = $item['item_id']; if (isset($newPrice[$itemId]) && $newPrice[$itemId] > 0) { @@ -2463,16 +2491,22 @@ class ItemsService unset($newfilter['item_name'],$filter['item_name']); } + // 处理关键字,并提供多语言 if(!empty($filter['keywords'])){ - $listBn = $itemsRepository->getItemsLists(['or'=>[ - ['item_bn|contains'=>$filter['keywords']], - ['item_name|contains'=>$filter['keywords']], - ]]); - $idsBn = array_column($listBn,'default_item_id'); - unset($filter['keywords']); $lang = $itemsRepository->getLang(); $langIds = $multiLangService->filterByLang($lang,'item_name',$filter['keywords'],'items'); - $totalIds = array_merge($idsBn,$langIds); + $or = [ + 'or'=>[ + 'item_bn|contains'=> $filter['keywords'], + // ['item_name|contains'=> $filter['keywords']], + ] + ]; + if (!empty($langIds)) { + $or['or']['item_id'] = $langIds; + } + $listBn = $itemsRepository->getItemsLists($or); + $idsBn = array_column($listBn,'default_item_id'); + $totalIds = array_merge($idsBn, $langIds); $totalIds = array_unique($totalIds); if(!empty($newfilter['item_id'])){ $newfilter['item_id'] = array_merge($newfilter['item_id'],$totalIds); @@ -2488,6 +2522,11 @@ class ItemsService // ]; // unset($newfilter['keywords']); // } + + // or 已经处理,如果存在unset + if (isset($newfilter['or'])) { + unset($newfilter['or']); + } return $newfilter; } @@ -2807,10 +2846,10 @@ class ItemsService public function getItemsListActityTag($itemList, $companyId) { - $goodsIds = array_column($itemList['list'], 'goods_id'); + $goodsIds = array_column($itemList, 'goods_id'); if ($goodsIds) { $promotionItemTagService = new PromotionItemTagService(); - $list = $promotionItemTagService->getPromotions($itemList['list'], $companyId, ['activity_price' => 'desc']); + $list = $promotionItemTagService->getPromotions($itemList, $companyId, ['activity_price' => 'desc']); foreach ($list as $value) { if ($value['is_all_items'] == '2') {//指定商品适用 $newTags[$value['goods_id']][$value['promotion_id']] = [ @@ -2843,7 +2882,7 @@ class ItemsService ]; $marketingService = new MarketingActivityService(); - foreach ($itemList['list'] as &$items) { + foreach ($itemList as &$items) { if (!isset($items['goods_id'])) { continue; } @@ -2898,9 +2937,9 @@ class ItemsService /*if ($itemIds ?? null) { $datalists = $this->itemsRepository->getItemsLists(['item_id' => $itemIds], 'market_price,price,goods_id'); $datalists = array_column($datalists, null, 'goods_id'); - foreach ($itemList['list'] as $k => $items_info) { + foreach ($itemList as $k => $items_info) { if (isset($datalists[$items_info['goods_id']])) { - $itemList['list'][$k] = array_merge($datalists[$items_info['goods_id']], $itemList['list'][$k]); + $itemList[$k] = array_merge($datalists[$items_info['goods_id']], $itemList[$k]); } } }*/ @@ -3117,8 +3156,11 @@ class ItemsService * @param $result * @return mixed */ - public function dealListStore($result) + public function dealListStore($result, $isGetSkuList = false) { + if($isGetSkuList){ + return $result; + } if (!$result['list']) { return $result; } @@ -3236,7 +3278,6 @@ class ItemsService return $itemsList; } - /** * Dynamically call the KaquanService instance. * diff --git a/src/GoodsBundle/Services/MultiLang/MultiLangOutsideItemService.php b/src/GoodsBundle/Services/MultiLang/MultiLangOutsideItemService.php index 5f3b409..63fb073 100644 --- a/src/GoodsBundle/Services/MultiLang/MultiLangOutsideItemService.php +++ b/src/GoodsBundle/Services/MultiLang/MultiLangOutsideItemService.php @@ -98,7 +98,7 @@ class MultiLangOutsideItemService foreach ($langBag as $k => $v) { $field = str_replace("_lang", "", $k); foreach ($v as $lang => $vv) { - $service = new MultiLangItem($lang); + $service = new MultiLangItem($lang,'MultiLangItem'); $insertData = $baseInsertData; $insertData['lang'] = $lang; $insertData['attribute_value'] = $vv; @@ -123,7 +123,11 @@ class MultiLangOutsideItemService public function getOneLangData(array $body, array $field, string $tableName, string $lang, int $id = 0, string $module = '') { $fieldStruct = $field; - $filter = ['table_name' => $tableName, 'field' => $fieldStruct, 'lang' => $lang]; + $filter = [ + 'table_name' => $tableName, + 'field' => $fieldStruct, + // 'lang' => $lang + ]; if (!empty($id)) { $filter['data_id'] = $id; } @@ -131,9 +135,9 @@ class MultiLangOutsideItemService $filter['module_name'] = $module; } - $content = (new MultiLangItem($lang))->getListByFilter($filter, -1); + $content = (new MultiLangItem($lang, 'outside_item'))->getListByFilter($filter, -1); if (empty($content)) { - return []; + return $body; } $structContent = []; foreach ($content as $v) { @@ -163,7 +167,11 @@ class MultiLangOutsideItemService if (empty($ids)) { return $dataList; } - $filter = ['table_name' => $tableName, 'field' => $field, 'data_id' => $ids]; + $filter = [ + 'table_name' => $tableName, + 'field' => $field, + 'data_id' => $ids + ]; $service = new MultiLangItem($lang,$tableName); $listTmp = $service->getListByFilter($filter, -1); if (empty($listTmp)) { @@ -204,6 +212,7 @@ class MultiLangOutsideItemService $dataField[$field] = $langBag[$field]; } } + if(empty($dataField)){ return; } @@ -218,7 +227,7 @@ class MultiLangOutsideItemService 'table_name' => $tableName, 'field' => $k, 'data_id' => $dataId, - 'lang' => '', + // 'lang' => '', ]; $service->updateOrInsert($filter, $updateData); } diff --git a/src/GoodsBundle/Services/MultiLang/MultiLangService.php b/src/GoodsBundle/Services/MultiLang/MultiLangService.php index 18d65b5..827ba42 100644 --- a/src/GoodsBundle/Services/MultiLang/MultiLangService.php +++ b/src/GoodsBundle/Services/MultiLang/MultiLangService.php @@ -50,7 +50,7 @@ class MultiLangService 'tag_name' ], 'membercard_grade'=>[ - 'grade_name','description' + 'grade_name','description', 'background_pic_url', 'grade_background' ], 'config_request_fields'=>[ 'label','validate_condition','alert_required_message' @@ -159,6 +159,9 @@ class MultiLangService if (!empty($module)) { $filter['module_name'] = $module; } + // if (isset($body['company_id'])) { + // $filter['company_id'] = $body['company_id']; + // } $content = (new MultiLangItem($lang))->getListByFilter($filter, -1); // $content = $this->multiLangModRepository->getLists($filter, '*', 1, -1); @@ -188,8 +191,12 @@ class MultiLangService $newField = $this->multiLangAttr[$tableName]; } $filter = ['table_name' => $tableName, 'field' => $newField, 'data_id' => $ids]; + // if (isset($dataList['company_id'])) { + // $filter['company_id'] = $dataList['company_id']; + // } $service = new MultiLangItem($lang); $listTmp = $service->getListByFilter($filter, -1); + if (empty($listTmp)) { return $dataList; } @@ -213,7 +220,7 @@ class MultiLangService return $dataList; } - public function updateLangData(array $langBag, string $tableName, int $dataId) + public function updateLangData(array $langBag, string $tableName, int $dataId, $company_id = 0) { $dataField = []; if(empty($this->multiLangAttr[$tableName])){ @@ -228,24 +235,58 @@ class MultiLangService return; } $service = new MultiLangItem($this->getLang()); - foreach ($dataField as $k => $vv){ - - + foreach ($dataField as $k => $vv) { // $field = str_replace("_lang", "", $k); $updateData = [ 'attribute_value' => $vv, ]; + // if ($company_id > 0) { + // $updateData['company_id'] = $company_id; + // } $filter = [ 'table_name' => $tableName, 'field' => $k, 'data_id' => $dataId, - 'lang' => '', + // 'lang' => '', ]; $service->updateOrInsert($filter, $updateData); } } + public function updateLangDataNew(array $langBag, string $tableName, int $dataId, $multiLangAttr = [], $company_id = 0) + { + $dataField = []; + if(empty($multiLangAttr)){ + return; + } + foreach ($multiLangAttr as $field) { + if(isset($langBag[$field])){ + $dataField[$field] = $langBag[$field]; + } + } + if(empty($dataField)){ + return; + } + $service = new MultiLangItem($this->getLang()); + foreach ($dataField as $k => $vv) { +// $field = str_replace("_lang", "", $k); + $updateData = [ + 'attribute_value' => $vv, + ]; + // if ($company_id > 0) { + // $updateData['company_id'] = $company_id; + // } + $filter = [ + 'table_name' => $tableName, + 'field' => $k, + 'data_id' => $dataId, + // 'lang' => '', + ]; + $service->updateOrInsert($filter, $updateData); + } + } + public function updateLangDataParams(array $langBag, string $tableName, int $dataId) { $lang = $this->getLang(); @@ -259,21 +300,24 @@ class MultiLangService 'table_name' => $tableName, 'field' => $key, 'data_id' => $dataId, - 'lang' => $lang, + // 'lang' => $lang, ]; $service->updateByFilter($filter, $updateData); } } //搜索用 - public function filterByLang(string $lang, string $field, string $content, string $tableName) + public function filterByLang(string $lang, string $field, string $content, string $tableName, $companyId = 0) { $filter = [ - 'lang' => $lang, + // 'lang' => $lang, 'field' => $field, 'table_name' => $tableName, 'attribute_value|contains' => $content, ]; + // if ($companyId > 0) { + // $filter['company_id'] = $companyId; + // } $service = new MultiLangItem($lang); $list = $service->getListByFilter($filter, -1); if (empty($list)) { @@ -282,6 +326,34 @@ class MultiLangService return array_column($list, 'data_id'); } + public function filterLang($filter, $multiLangField, $table, $prk) + { + $lang = $this->getLang(); + $prkFilter = $filter[$prk] ?? ''; // 所有过滤字段keys + // 优化字段查询加入company_id + $companyId = $filter['company_id'] ?? 0; + foreach ($filter as $key => $value) { + $dataIdArr = ''; + // 必须是多语言字段 + // 可能存在xx|xx 这种数据, 所以要兼容 + $filterkeys = explode('|', $key); + if (in_array($filterkeys[0], $multiLangField)) { + $dataIdArr = $this->filterByLang($lang, $filterkeys[0], $value, $table, $companyId); + // 如果存在多语言字段主键,说明可能其他地方使用了主键过滤,我们需要合并掉 + if (!empty($dataIdArr)) { + if (!empty($prkFilter)) { + $filter[$prk] = array_merge((array)$prkFilter, $dataIdArr); + }else{ + $filter[$prk] = $dataIdArr; + } + // 移除多语言字段的原始过滤条件,因为已经转换为按主键过滤 + unset($filter[$key]); + } + } + } + + return $filter; + } public function getItemSpec(array $itemId) //这里是sku级别啊!!!!拿规格值得 { @@ -405,10 +477,15 @@ class MultiLangService return $outPutData; } - public function addMultiLangByParams($id, array $params, string $module) + public function addMultiLangByParams($id, array $params, string $module , $multiLangAttr = []) { $lang = $this->getLang(); - $multiLang = $this->multiLangAttr[$module] ?? []; + // 兼容商品多表,多语言字段,首先使用传入的多语言字段 + if (!empty($multiLangAttr)) { + $multiLang = $multiLangAttr; + }else { + $multiLang = $this->multiLangAttr[$module] ?? []; + } $langBag = []; if (!empty($multiLang)) { foreach ($multiLang as $vv) { @@ -481,4 +558,11 @@ class MultiLangService // // } + public function deleteMultiLangByParams(int $id, string $module) + { + $service = new MultiLangItem($this->getLang()); + $filter['table_name'] = $module; + $filter['data_id'] = $id; + $service->deleteByFilter($filter); + } } diff --git a/src/GoodsBundle/Services/NormalGoodsUploadService.php b/src/GoodsBundle/Services/NormalGoodsUploadService.php index 7b17cb4..9e2803e 100644 --- a/src/GoodsBundle/Services/NormalGoodsUploadService.php +++ b/src/GoodsBundle/Services/NormalGoodsUploadService.php @@ -276,7 +276,7 @@ class NormalGoodsUploadService $row['goods_id'] = false; $row['item_id'] = false; if ($row['item_bn']) { - $filter = ['item_bn' => $row['item_bn'], 'company_id' => $companyId]; + $filter = ['item_bn' => trim($row['item_bn']), 'company_id' => $companyId]; $itemsService = new ItemsService(); $oldItemInfo = $itemsService->getItem($filter); if ($oldItemInfo) { diff --git a/src/KaquanBundle/Entities/DiscountCards.php b/src/KaquanBundle/Entities/DiscountCards.php index 6a0408d..cb19a76 100644 --- a/src/KaquanBundle/Entities/DiscountCards.php +++ b/src/KaquanBundle/Entities/DiscountCards.php @@ -515,6 +515,20 @@ class DiscountCards */ private $dm_use_channel; + /** + * @var string + * + * @ORM\Column(name="coupon_type", type="string", length=10, options={"comment":"券类型。mall:商城券;guide:导购专属券", "default": "mall"}) + */ + private $coupon_type = 'mall'; + + /** + * @var integer + * + * @ORM\Column(name="guide_issue_quantity", type="integer", options={"comment":"导购发放数量", "default": 0}) + */ + private $guide_issue_quantity = 0; + /** * Get cardId * @@ -2132,4 +2146,52 @@ class DiscountCards { return $this->dm_use_channel; } + + /** + * Set couponType. + * + * @param string $couponType + * + * @return DiscountCards + */ + public function setCouponType($couponType = 'mall') + { + $this->coupon_type = $couponType; + + return $this; + } + + /** + * Get couponType. + * + * @return string + */ + public function getCouponType() + { + return $this->coupon_type; + } + + /** + * Set guideIssueQuantity. + * + * @param integer $guideIssueQuantity + * + * @return DiscountCards + */ + public function setGuideIssueQuantity($guideIssueQuantity = 0) + { + $this->guide_issue_quantity = $guideIssueQuantity; + + return $this; + } + + /** + * Get guideIssueQuantity. + * + * @return integer + */ + public function getGuideIssueQuantity() + { + return $this->guide_issue_quantity; + } } diff --git a/src/KaquanBundle/Entities/UserDiscount.php b/src/KaquanBundle/Entities/UserDiscount.php index 9cf788c..ade655a 100644 --- a/src/KaquanBundle/Entities/UserDiscount.php +++ b/src/KaquanBundle/Entities/UserDiscount.php @@ -31,6 +31,7 @@ use Doctrine\ORM\Mapping as ORM; * @ORM\Index(name="idx_status_expiredtime", columns={"status", "expired_time"}), * @ORM\Index(name="idx_cardid_companyid_userid", columns={"card_id", "company_id", "user_id"}), * @ORM\Index(name="idx_dm_card_code", columns={"dm_card_code"}), + * @ORM\Index(name="idx_salesperson_code", columns={"salesperson_code"}), * }) * @ORM\Entity(repositoryClass="KaquanBundle\Repositories\UserDiscountRepository") */ @@ -323,6 +324,13 @@ class UserDiscount */ private $salesperson_id; + /** + * @var string + * + * @ORM\Column(name="salesperson_code", type="string", length=100, nullable=true, options={"comment":"导购编号(employee_number/work_userid)"}) + */ + private $salesperson_code; + /** * @var integer * @@ -1332,6 +1340,30 @@ class UserDiscount return $this->salesperson_id; } + /** + * Set salespersonCode. + * + * @param string|null $salespersonCode + * + * @return UserDiscount + */ + public function setSalespersonCode($salespersonCode = null) + { + $this->salesperson_code = $salespersonCode; + + return $this; + } + + /** + * Get salespersonCode. + * + * @return string|null + */ + public function getSalespersonCode() + { + return $this->salesperson_code; + } + /** * Set relCategoryIds. * diff --git a/src/KaquanBundle/Http/Api/V1/Action/DiscountCard.php b/src/KaquanBundle/Http/Api/V1/Action/DiscountCard.php index 2c019f1..f23923f 100644 --- a/src/KaquanBundle/Http/Api/V1/Action/DiscountCard.php +++ b/src/KaquanBundle/Http/Api/V1/Action/DiscountCard.php @@ -59,6 +59,8 @@ class DiscountCard extends BaseController * @SWG\Parameter(name="kq_status", in="query", description="卡券状态 0:正常 1:暂停 2:关闭", type="integer"), * @SWG\Parameter(name="distributor_ids", in="query", description="指定店铺id列表 [1, 2]", type="string"), * @SWG\Parameter(name="items", in="query", description="指定可兑换商品信息 [{'id': 1, 'limit': 3}, {'id': 2, 'limit': 4}]", type="string"), + * @SWG\Parameter(name="coupon_type", in="query", description="券类型。mall:商城券;guide:导购专属券", type="string", default="mall"), + * @SWG\Parameter(name="guide_issue_quantity", in="query", description="导购发放数量", type="integer", default=0), * @SWG\Response( * response=200, * description="成功返回结构", @@ -170,6 +172,12 @@ class DiscountCard extends BaseController * @SWG\Parameter( * name="store_self", in="query", description="平台版仅支持自营商品【总店】", type="string" * ), + * @SWG\Parameter( + * name="coupon_type", in="query", description="券类型。mall:商城券;guide:导购专属券", type="string", default="mall" + * ), + * @SWG\Parameter( + * name="guide_issue_quantity", in="query", description="导购发放数量", type="integer", default=0 + * ), * @SWG\Response( * response=200, * description="成功返回结构", @@ -219,6 +227,15 @@ class DiscountCard extends BaseController // 活动类型 长期/短期 $data = $request->input(); $data['company_id'] = $companyId; + + // 处理券类型字段,默认为 mall + $data['coupon_type'] = $request->input('coupon_type', 'mall'); + if (!in_array($data['coupon_type'], ['mall', 'guide'])) { + $data['coupon_type'] = 'mall'; + } + + // 处理导购发放数量字段,默认为 0 + $data['guide_issue_quantity'] = intval($request->input('guide_issue_quantity', 0)); $dateType = $request->input('date_type'); if ($dateType == DiscountNewGiftCardService::DATE_TYPE_LONG) { if (app('validator')->make($request->all(), [ @@ -256,6 +273,15 @@ class DiscountCard extends BaseController $postdata = $this->__doParams($request->input(), $companyId); $postdata['company_id'] = $companyId; + // 处理券类型字段,默认为 mall + $postdata['coupon_type'] = $request->input('coupon_type', 'mall'); + if (!in_array($postdata['coupon_type'], ['mall', 'guide'])) { + $postdata['coupon_type'] = 'mall'; + } + + // 处理导购发放数量字段,默认为 0 + $postdata['guide_issue_quantity'] = intval($request->input('guide_issue_quantity', 0)); + $postdata['source_id'] = app('auth')->user()->get('distributor_id');//如果是平台,这里是0 $postdata['source_type'] = app('auth')->user()->get('operator_type');//如果是平台,这里是admin @@ -620,6 +646,15 @@ class DiscountCard extends BaseController if ($request->input('title')) { $filter['title|like'] = $request->input('title'); } + $isGuide = $request->input('is_guide',100); + if((int)$isGuide !== 100){ + if ((int)$isGuide === 1) { + $filter['coupon_type'] = 'guide'; + }else{ + $filter['coupon_type'] = 'mall'; + } + } + $store_self = $request->input('store_self'); $sourceId = floatval($request->get('distributor_id', 0));//如果是平台,这里是0 if ($store_self == "true") {//平台版仅支持自营商品【总店】 diff --git a/src/KaquanBundle/Http/FrontApi/V1/Action/DiscountCard.php b/src/KaquanBundle/Http/FrontApi/V1/Action/DiscountCard.php index bc9c874..1d5493a 100644 --- a/src/KaquanBundle/Http/FrontApi/V1/Action/DiscountCard.php +++ b/src/KaquanBundle/Http/FrontApi/V1/Action/DiscountCard.php @@ -59,6 +59,9 @@ class DiscountCard extends BaseController * @SWG\Parameter( * name="card_id", in="query", description="卡券id", required=false, type="integer", * ), + * @SWG\Parameter( + * name="userWorkId", in="query", description="导购员工编号(work_userid)", required=false, type="string", + * ), * @SWG\Response( * response=200, * description="成功返回结构", @@ -93,6 +96,8 @@ class DiscountCard extends BaseController $offset = ($page - 1) * $count; $filter = []; + $userWorkId = $request->input('work_userid', ''); + // if ($request->input('use_platform')) { // $filter['use_platform'] = $request->input('use_platform'); // } @@ -117,6 +122,12 @@ class DiscountCard extends BaseController unset($filter['distributor_id']); } $filter['receive'] = '1'; + + if(!empty($userWorkId)){ + $filter['coupon_type'] = 'guide'; + }else{ + $filter['coupon_type'] = 'mall'; + } $filter['company_id'] = $authInfo['company_id']; $discountCardService = new KaquanService(new DiscountCardService()); @@ -134,7 +145,7 @@ class DiscountCard extends BaseController if ($request->input('card_id')) { $cardId = $request->input('card_id'); - $filter['card_id'] = (int)$cardId; + $filter['card_id'] = explode(',', $cardId); unset($filter['receive']); // 如果指定ID,则不判断是否只能前台直接领取 } @@ -142,12 +153,22 @@ class DiscountCard extends BaseController //获取用户领取的优惠券 $userDiscountService = new UserDiscountService(); + foreach ($result['list'] as $k => $v) { + $result['list'][$k]['button_status'] = [ + 'label' => 'get', //get/exchange/buy/get_invalid + 'text' => '领取', //领取/兑换/购买/已领取 + ]; + } if (isset($authInfo['user_id'])) { foreach ($result['list'] as &$value) { $value['user_get_num'] = $userDiscountService->getUserGetNum($authInfo['user_id'], $value['card_id'], $value['company_id']); - if ($value['get_limit'] <= $value['user_get_num']) { + if ($value['get_limit'] && $value['get_limit'] <= $value['user_get_num']) { $value['ifget'] = 1; + $value['button_status'] = [ + 'label' => 'get_invalid', //get/exchange/buy/get_invalid + 'text' => '已领取', //领取/兑换/购买/已领取 + ]; } if ($value['end_date'] && $value['end_date'] <= time()) { $value['gameOver'] = 1; @@ -170,6 +191,35 @@ class DiscountCard extends BaseController // 追加优惠券的店铺信息 (new DistributorService())->appendDistributorInfo((int)$authInfo['company_id'], $result["list"]); + // 如果存在 userWorkId,查询当前导购在每个券下的领券数量 + if (!empty($userWorkId) && !empty($result['list'])) { + $cardIds = array_column($result['list'], 'card_id'); + if (!empty($cardIds)) { + $userDiscountRepository = app('registry')->getManager('default')->getRepository(\KaquanBundle\Entities\UserDiscount::class); + $salespersonCountFilter = [ + 'company_id' => $authInfo['company_id'], + 'card_id' => $cardIds, + 'salesperson_code' => $userWorkId, + ]; + $salespersonCounts = $userDiscountRepository->getTotalNumGroupBy( + $salespersonCountFilter, + 'count(*) as total_num, card_id', + 'card_id' + ); + + // 将查询结果转换为以 card_id 为键的数组 + $salespersonCountMap = []; + foreach ($salespersonCounts as $item) { + $salespersonCountMap[$item['card_id']] = intval($item['total_num']); + } + + // 为每个券添加导购领券数量 + foreach ($result['list'] as &$card) { + $card['salesperson_get_num'] = $salespersonCountMap[$card['card_id']] ?? 0; + } + } + } + return $this->response->array($result); } diff --git a/src/KaquanBundle/Http/FrontApi/V1/Action/UserDiscount.php b/src/KaquanBundle/Http/FrontApi/V1/Action/UserDiscount.php index 0153a9e..1007a88 100644 --- a/src/KaquanBundle/Http/FrontApi/V1/Action/UserDiscount.php +++ b/src/KaquanBundle/Http/FrontApi/V1/Action/UserDiscount.php @@ -38,6 +38,7 @@ class UserDiscount extends BaseController * operationId="receiveCard", * @SWG\Parameter( name="card_id", in="query", description="指定优惠券card_id", required=false, type="string"), * @SWG\Parameter( name="salesperson_id", in="query", description="导购id", required=false, type="string"), + * @SWG\Parameter( name="salesperson_code", in="query", description="导购编号(employee_number/work_userid)", required=false, type="string"), * @SWG\Response( * response=200, * description="成功返回结构", @@ -63,11 +64,16 @@ class UserDiscount extends BaseController $companyId = $user['company_id']; $cardId = $request->input('card_id'); $salespersonId = $request->input('salesperson_id', 0); + $salespersonCode = $request->input('work_userid', ''); $userId = $user['user_id']; if (!$user['user_id'] || !$user['mobile']) { throw new ResourceException('您还不是会员,无法领取优惠券'); } - $result = $userDiscountService->userGetCard($companyId, $cardId, $userId, "商城本地领取", $salespersonId); + // 导购券领取数量限制检查(使用 salesperson_code) + if (!empty($salespersonCode)) { + $userDiscountService->checkGuideCouponLimit($companyId, $cardId, $salespersonCode); + } + $result = $userDiscountService->userGetCard($companyId, $cardId, $userId, "商城本地领取", $salespersonId, '', '', '', $salespersonCode); return $this->response->array(['status' => $result]); } diff --git a/src/KaquanBundle/Repositories/DiscountCardsRepository.php b/src/KaquanBundle/Repositories/DiscountCardsRepository.php index 9a09cec..aa507d7 100644 --- a/src/KaquanBundle/Repositories/DiscountCardsRepository.php +++ b/src/KaquanBundle/Repositories/DiscountCardsRepository.php @@ -567,6 +567,10 @@ class DiscountCardsRepository extends EntityRepository if (isset($data["card_type"]) && $data["card_type"]) { $entity->setCardType($data["card_type"]); } + //当前字段非必填 + if (isset($data["coupon_type"])) { + $entity->setCouponType($data["coupon_type"]); + } if (isset($data["title"]) && $data["title"]) { $entity->setTitle($data["title"]); } @@ -689,6 +693,10 @@ class DiscountCardsRepository extends EntityRepository $entity->setQuantity($data["quantity"]); } //当前字段非必填 + if (isset($data["guide_issue_quantity"])) { + $entity->setGuideIssueQuantity($data["guide_issue_quantity"]); + } + //当前字段非必填 if (isset($data['use_all_shops'])) { if ($data['use_all_shops'] == 'true') { $entity->setUseAllShops(true); diff --git a/src/KaquanBundle/Repositories/UserDiscountRepository.php b/src/KaquanBundle/Repositories/UserDiscountRepository.php index df4ad59..c93e57e 100644 --- a/src/KaquanBundle/Repositories/UserDiscountRepository.php +++ b/src/KaquanBundle/Repositories/UserDiscountRepository.php @@ -68,6 +68,7 @@ class UserDiscountRepository extends EntityRepository $userCardData->setMostCost($cardInfo['most_cost']); $userCardData->setGetDate(time()); $userCardData->setSalespersonId($params['salesperson_id'] ?? 0); + $userCardData->setSalespersonCode($params['salesperson_code'] ?? ''); $userCardData->setApplyScope($cardInfo["apply_scope"] ?? ''); if (isset($params['dm_card_code'])) { $userCardData->setDmCardCode($params['dm_card_code']); diff --git a/src/KaquanBundle/Services/DiscountCardService.php b/src/KaquanBundle/Services/DiscountCardService.php index eb815b6..fa9ee9c 100644 --- a/src/KaquanBundle/Services/DiscountCardService.php +++ b/src/KaquanBundle/Services/DiscountCardService.php @@ -491,7 +491,7 @@ class DiscountCardService implements KaquanInterface array_map(function ($item) { return Arr::only($item, ['item_id', 'use_limit']); }, $relItem); - if(!empty($itemIds)){ + if(!empty($itemIds)){ $filter = ['company_id' => $detail['company_id'], 'item_id' => $itemIds]; $itemService = new ItemsService(); $itemsList = $itemService->getSkuItemsList($filter); @@ -519,7 +519,7 @@ class DiscountCardService implements KaquanInterface $detail['rel_category_ids'] = $categoryIds; $detail['item_category'] = $categoryIds; } - $detail['use_all_items'] = $categoryIds ? 'category' : $detail['use_all_items']; + $detail['use_all_items'] = $categoryIds ? 'category' : $detail['use_all_items'] ?? []; //获取标签 $detail['use_all_items'] = $detail['use_bound'] == self::FOR_TAG_ITEMS ? 'tag' : $detail['use_all_items']; @@ -1060,7 +1060,15 @@ class DiscountCardService implements KaquanInterface } // 根据card_id查询 if (isset($filter['card_id']) && $filter['card_id']) { - $criteria->andWhere($criteria->expr()->eq('kdc.card_id', $filter['card_id'])); + if (is_array($filter['card_id'])) { + $criteria->andWhere($criteria->expr()->in('kdc.card_id', $filter['card_id'])); + } else { + $criteria->andWhere($criteria->expr()->eq('kdc.card_id', $filter['card_id'])); + } + } + // 根据coupon_type查询 + if (isset($filter['coupon_type']) && $filter['coupon_type']) { + $criteria->andWhere($criteria->expr()->eq('kdc.coupon_type', $criteria->expr()->literal($filter['coupon_type']))); } //dd($criteria->getSQL()); @@ -1144,15 +1152,30 @@ class DiscountCardService implements KaquanInterface $criteria->expr()->andX( $criteria->expr()->eq('kdc.card_type', $criteria->expr()->literal('new_gift')), $criteria->expr()->eq('kdc.kq_status', DiscountNewGiftCardService::STATUS_NORMAL), - $criteria->expr()->gte('kdc.send_end_time', time()), + $criteria->expr()->orX( + $criteria->expr()->andX( + $criteria->expr()->isNotNull('kdc.send_end_time'), + $criteria->expr()->gte('kdc.send_end_time', time()) + ), + $criteria->expr()->isNull('kdc.send_end_time') + ), $criteria->expr()->lte('kdc.send_begin_time', time()) ), $criteria->expr()->andX( $criteria->expr()->eq('kdc.card_type', $criteria->expr()->literal('new_gift')), $criteria->expr()->lte('kdc.send_begin_time', time()), $criteria->expr()->gt('kdc.fixed_term', 0), - $criteria->expr()->eq('kdc.send_end_time', 0), - $criteria->expr()->eq('kdc.end_date', 0), + $criteria->expr()->orX( + $criteria->expr()->eq('kdc.send_end_time', 0), + $criteria->expr()->isNull('kdc.send_end_time') + ), + $criteria->expr()->orX( + $criteria->expr()->eq('kdc.end_date', 0), + $criteria->expr()->andX( + $criteria->expr()->neq('kdc.end_date', 0), + $criteria->expr()->gte('kdc.end_date', $criteria->expr()->literal(time())) + ) + ), $criteria->expr()->eq('kdc.kq_status', DiscountNewGiftCardService::STATUS_NORMAL) ), $criteria->expr()->andX( @@ -1357,6 +1380,18 @@ class DiscountCardService implements KaquanInterface private function __setParams(&$dataInfo) { + // 设置券类型默认值 + if (!isset($dataInfo['coupon_type']) || !in_array($dataInfo['coupon_type'], ['mall', 'guide'])) { + $dataInfo['coupon_type'] = 'mall'; + } + + // 设置导购发放数量默认值 + if (!isset($dataInfo['guide_issue_quantity'])) { + $dataInfo['guide_issue_quantity'] = 0; + } else { + $dataInfo['guide_issue_quantity'] = intval($dataInfo['guide_issue_quantity']); + } + //时间戳为标准0点时间 if ($dataInfo['date_type'] == "DATE_TYPE_FIX_TERM") { $dataInfo['fixed_term'] = $dataInfo['days']; diff --git a/src/KaquanBundle/Services/DiscountNewGiftCardService.php b/src/KaquanBundle/Services/DiscountNewGiftCardService.php index 9168304..9f902c0 100644 --- a/src/KaquanBundle/Services/DiscountNewGiftCardService.php +++ b/src/KaquanBundle/Services/DiscountNewGiftCardService.php @@ -167,6 +167,10 @@ class DiscountNewGiftCardService implements KaquanInterface } } if (isset($dataInfo['vip_grade_ids'])) { + if(!is_array($dataInfo['vip_grade_ids'])){ + $dataInfo['vip_grade_ids'] = json_decode($dataInfo['vip_grade_ids'], true); + } + foreach ($detail['vip_grade_ids'] as $vgid) { if (!in_array($vgid, $dataInfo['vip_grade_ids'])) { throw new ResourceException(trans('KaquanBundle.members_only_expand_not_reduce_scope')); @@ -262,6 +266,18 @@ class DiscountNewGiftCardService implements KaquanInterface public function __setParams(&$params, $is_create = false) { + // 设置券类型默认值 + if (!isset($params['coupon_type']) || !in_array($params['coupon_type'], ['mall', 'guide'])) { + $params['coupon_type'] = 'mall'; + } + + // 设置导购发放数量默认值 + if (!isset($params['guide_issue_quantity'])) { + $params['guide_issue_quantity'] = 0; + } else { + $params['guide_issue_quantity'] = intval($params['guide_issue_quantity']); + } + if (isset($params['date_type'])) { switch ($params['date_type']) { case self::DATE_TYPE_LONG: @@ -318,7 +334,7 @@ class DiscountNewGiftCardService implements KaquanInterface $params['grade_ids'] = $ids; } - if (isset($params['vip_grade_ids']) && !empty($params['grade_ids'])) { + if (isset($params['vip_grade_ids']) && !empty($params['vip_grade_ids'])) { $ids = json_decode($params['vip_grade_ids'], true); $params['vip_grade_ids'] = $ids; } diff --git a/src/KaquanBundle/Services/UserDiscountService.php b/src/KaquanBundle/Services/UserDiscountService.php index 3ebe1ec..54d4c9f 100644 --- a/src/KaquanBundle/Services/UserDiscountService.php +++ b/src/KaquanBundle/Services/UserDiscountService.php @@ -314,19 +314,66 @@ class UserDiscountService implements UserDiscountInterface return $result; } + /** + * 检查导购券领取数量限制 + * @param int $companyId + * @param int $cardId + * @param int $salespersonId + * @throws ResourceException + */ + public function checkGuideCouponLimit($companyId, $cardId, $salespersonCode) + { + if (empty($salespersonCode) || !$cardId) { + return; + } + + // 获取券信息 + $discountCardService = new KaquanService(new DiscountCardService()); + $filter = [ + 'card_id' => $cardId, + 'company_id' => $companyId, + ]; + $cardInfo = $discountCardService->getKaquanDetail($filter, false, false); + + // 判断是否为导购券 + if (isset($cardInfo['coupon_type']) && $cardInfo['coupon_type'] == 'guide') { + // 查询该导购已经领取该券的数量(使用 salesperson_code) + $countFilter = [ + 'company_id' => $companyId, + 'card_id' => $cardId, + 'salesperson_code' => $salespersonCode, + ]; + $receivedCount = $this->userDiscountRepository->getTotalNum($countFilter); + + // 获取券的导购发放数量限制 + $guideIssueQuantity = isset($cardInfo['guide_issue_quantity']) ? intval($cardInfo['guide_issue_quantity']) : 0; + + // 如果设置了限制且已领取数量超过限制,则提示错误 + if ($guideIssueQuantity > 0 && $receivedCount >= $guideIssueQuantity) { + throw new ResourceException('超过该券导购可领取的最大数量'); + } + } + } + /** * [userGetCard 用户领取优惠券] * @param int $companyId * @param int $cardId * @param int $userId * @param string $sourceFrom + * @param int $salespersonId + * @param string $activityName + * @param string $dmCardCode + * @param string $mobile + * @param string $salespersonCode * @return array */ - public function userGetCard($companyId, $cardId, $userId, $sourceFrom = "商城本地领取", $salespersonId = 0, $activityName = '' , $dmCardCode = '', $mobile = '') + public function userGetCard($companyId, $cardId, $userId, $sourceFrom = "商城本地领取", $salespersonId = 0, $activityName = '' , $dmCardCode = '', $mobile = '', $salespersonCode = '') { if (!$companyId) { throw new ResourceException(trans('KaquanBundle.coupon_record_add_failed')); } + $postdata['status'] = 1; // 校验优惠券是否能领取 $cardInfo = $this->__getCardInfo($cardId, $companyId, $userId); @@ -412,6 +459,7 @@ class UserDiscountService implements UserDiscountInterface $postdata['user_id'] = $userId; $postdata['code'] = $this->getCode($companyId, $cardId, $userId); $postdata['salesperson_id'] = $salespersonId; + $postdata['salesperson_code'] = $salespersonCode; $postdata['activity_name'] = $activityName; $status = $this->userDiscountRepository->userGetCard($postdata, $cardInfo); $salespersonTaskRecordService = new SalespersonTaskRecordService(); diff --git a/src/KujialeBundle/Commands/UpdateDesignerWorksCommand.php b/src/KujialeBundle/Commands/UpdateDesignerWorksCommand.php new file mode 100644 index 0000000..d8e20cc --- /dev/null +++ b/src/KujialeBundle/Commands/UpdateDesignerWorksCommand.php @@ -0,0 +1,42 @@ +scheduleUpdateDesigner(); + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerGoods.php b/src/KujialeBundle/Entities/KujialeDesignerGoods.php new file mode 100644 index 0000000..3d6df4f --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerGoods.php @@ -0,0 +1,469 @@ +id; + } + + /** + * Set goodId. + * + * @param string $goodId + * + * @return KujialeDesignerGoods + */ + public function setGoodId($goodId) + { + $this->good_id = $goodId; + + return $this; + } + + /** + * Get goodId. + * + * @return string + */ + public function getGoodId() + { + return $this->good_id; + } + + /** + * Set dimensions. + * + * @param string $dimensions + * + * @return KujialeDesignerGoods + */ + public function setDimensions($dimensions) + { + $this->dimensions = $dimensions; + + return $this; + } + + /** + * Get dimensions. + * + * @return string + */ + public function getDimensions() + { + return $this->dimensions; + } + + /** + * Set description. + * + * @param string $description + * + * @return KujialeDesignerGoods + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * Get description. + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * Set brandGoodCode. + * + * @param string $brandGoodCode + * + * @return KujialeDesignerGoods + */ + public function setBrandGoodCode($brandGoodCode) + { + $this->brand_good_code = $brandGoodCode; + + return $this; + } + + /** + * Get brandGoodCode. + * + * @return string + */ + public function getBrandGoodCode() + { + return $this->brand_good_code; + } + + /** + * Set brandGoodName. + * + * @param string $brandGoodName + * + * @return KujialeDesignerGoods + */ + public function setBrandGoodName($brandGoodName) + { + $this->brand_good_name = $brandGoodName; + + return $this; + } + + /** + * Get brandGoodName. + * + * @return string + */ + public function getBrandGoodName() + { + return $this->brand_good_name; + } + + /** + * Set brandId. + * + * @param string $brandId + * + * @return KujialeDesignerGoods + */ + public function setBrandId($brandId) + { + $this->brand_id = $brandId; + + return $this; + } + + /** + * Get brandId. + * + * @return string + */ + public function getBrandId() + { + return $this->brand_id; + } + + /** + * Set brandName. + * + * @param string $brandName + * + * @return KujialeDesignerGoods + */ + public function setBrandName($brandName) + { + $this->brand_name = $brandName; + + return $this; + } + + /** + * Get brandName. + * + * @return string + */ + public function getBrandName() + { + return $this->brand_name; + } + + /** + * Set seriesTagId. + * + * @param string $seriesTagId + * + * @return KujialeDesignerGoods + */ + public function setSeriesTagId($seriesTagId) + { + $this->series_tag_id = $seriesTagId; + + return $this; + } + + /** + * Get seriesTagId. + * + * @return string + */ + public function getSeriesTagId() + { + return $this->series_tag_id; + } + + /** + * Set seriesTagName. + * + * @param string $seriesTagName + * + * @return KujialeDesignerGoods + */ + public function setSeriesTagName($seriesTagName) + { + $this->series_tag_name = $seriesTagName; + + return $this; + } + + /** + * Get seriesTagName. + * + * @return string + */ + public function getSeriesTagName() + { + return $this->series_tag_name; + } + + /** + * Set productNumber. + * + * @param string $productNumber + * + * @return KujialeDesignerGoods + */ + public function setProductNumber($productNumber) + { + $this->product_number = $productNumber; + + return $this; + } + + /** + * Get productNumber. + * + * @return string + */ + public function getProductNumber() + { + return $this->product_number; + } + + /** + * Set customerTexture. + * + * @param string $customerTexture + * + * @return KujialeDesignerGoods + */ + public function setCustomerTexture($customerTexture) + { + $this->customer_texture = $customerTexture; + + return $this; + } + + /** + * Get customerTexture. + * + * @return string + */ + public function getCustomerTexture() + { + return $this->customer_texture; + } + + /** + * Set buyLink. + * + * @param string $buyLink + * + * @return KujialeDesignerGoods + */ + public function setBuyLink($buyLink) + { + $this->buy_link = $buyLink; + + return $this; + } + + /** + * Get buyLink. + * + * @return string + */ + public function getBuyLink() + { + return $this->buy_link; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerGoods + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerGoods + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerGoodsRel.php b/src/KujialeBundle/Entities/KujialeDesignerGoodsRel.php new file mode 100644 index 0000000..56098ff --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerGoodsRel.php @@ -0,0 +1,159 @@ +id; + } + + /** + * Set picId. + * + * @param string $picId + * + * @return KujialeDesignerGoodsRel + */ + public function setPicId($picId) + { + $this->pic_id = $picId; + + return $this; + } + + /** + * Get picId. + * + * @return string + */ + public function getPicId() + { + return $this->pic_id; + } + + /** + * Set obsBrandGoodId. + * + * @param string $obsBrandGoodId + * + * @return KujialeDesignerGoodsRel + */ + public function setObsBrandGoodId($obsBrandGoodId) + { + $this->obs_brand_good_id = $obsBrandGoodId; + + return $this; + } + + /** + * Get obsBrandGoodId. + * + * @return string + */ + public function getObsBrandGoodId() + { + return $this->obs_brand_good_id; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerGoodsRel + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerGoodsRel + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerTags.php b/src/KujialeBundle/Entities/KujialeDesignerTags.php new file mode 100644 index 0000000..bb04d14 --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerTags.php @@ -0,0 +1,314 @@ +id; + } + + /** + * Set tagCategoryId. + * + * @param string $tagCategoryId + * + * @return KujialeDesignerTags + */ + public function setTagCategoryId($tagCategoryId) + { + $this->tag_category_id = $tagCategoryId; + + return $this; + } + + /** + * Get tagCategoryId. + * + * @return string + */ + public function getTagCategoryId() + { + return $this->tag_category_id; + } + + /** + * Set tagCategoryName. + * + * @param string|null $tagCategoryName + * + * @return KujialeDesignerTags + */ + public function setTagCategoryName($tagCategoryName = null) + { + $this->tag_category_name = $tagCategoryName; + + return $this; + } + + /** + * Get tagCategoryName. + * + * @return string|null + */ + public function getTagCategoryName() + { + return $this->tag_category_name; + } + + /** + * Set type. + * + * @param int|null $type + * + * @return KujialeDesignerTags + */ + public function setType($type = null) + { + $this->type = $type; + + return $this; + } + + /** + * Get type. + * + * @return int|null + */ + public function getType() + { + return $this->type; + } + + /** + * Set isMultipleSelected. + * + * @param int|null $isMultipleSelected + * + * @return KujialeDesignerTags + */ + public function setIsMultipleSelected($isMultipleSelected = null) + { + $this->is_multiple_selected = $isMultipleSelected; + + return $this; + } + + /** + * Get isMultipleSelected. + * + * @return int|null + */ + public function getIsMultipleSelected() + { + return $this->is_multiple_selected; + } + + /** + * Set isDisabled. + * + * @param int|null $isDisabled + * + * @return KujialeDesignerTags + */ + public function setIsDisabled($isDisabled = null) + { + $this->is_disabled = $isDisabled; + + return $this; + } + + /** + * Get isDisabled. + * + * @return int|null + */ + public function getIsDisabled() + { + return $this->is_disabled; + } + + /** + * Set tagId. + * + * @param string|null $tagId + * + * @return KujialeDesignerTags + */ + public function setTagId($tagId = null) + { + $this->tag_id = $tagId; + + return $this; + } + + /** + * Get tagId. + * + * @return string|null + */ + public function getTagId() + { + return $this->tag_id; + } + + /** + * Set tagName. + * + * @param string|null $tagName + * + * @return KujialeDesignerTags + */ + public function setTagName($tagName = null) + { + $this->tag_name = $tagName; + + return $this; + } + + /** + * Get tagName. + * + * @return string|null + */ + public function getTagName() + { + return $this->tag_name; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerTags + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerTags + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerWorks.php b/src/KujialeBundle/Entities/KujialeDesignerWorks.php new file mode 100644 index 0000000..66846df --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerWorks.php @@ -0,0 +1,746 @@ +id; + } + + /** + * Set designName. + * + * @param string $designName + * + * @return KujialeDesignerWorks + */ + public function setDesignName($designName) + { + $this->design_name = $designName; + + return $this; + } + + /** + * Get designName. + * + * @return string + */ + public function getDesignName() + { + return $this->design_name; + } + + /** + * Set coverPic. + * + * @param string|null $coverPic + * + * @return KujialeDesignerWorks + */ + public function setCoverPic($coverPic = null) + { + $this->cover_pic = $coverPic; + + return $this; + } + + /** + * Get coverPic. + * + * @return string|null + */ + public function getCoverPic() + { + return $this->cover_pic; + } + + /** + * Set isOrigin. + * + * @param int|null $isOrigin + * + * @return KujialeDesignerWorks + */ + public function setIsOrigin($isOrigin = null) + { + $this->is_origin = $isOrigin; + + return $this; + } + + /** + * Get isOrigin. + * + * @return int|null + */ + public function getIsOrigin() + { + return $this->is_origin; + } + + /** + * Set isExcellent. + * + * @param int|null $isExcellent + * + * @return KujialeDesignerWorks + */ + public function setIsExcellent($isExcellent = null) + { + $this->is_excellent = $isExcellent; + + return $this; + } + + /** + * Get isExcellent. + * + * @return int|null + */ + public function getIsExcellent() + { + return $this->is_excellent; + } + + /** + * Set isRealExcellent. + * + * @param int|null $isRealExcellent + * + * @return KujialeDesignerWorks + */ + public function setIsRealExcellent($isRealExcellent = null) + { + $this->is_real_excellent = $isRealExcellent; + + return $this; + } + + /** + * Get isRealExcellent. + * + * @return int|null + */ + public function getIsRealExcellent() + { + return $this->is_real_excellent; + } + + /** + * Set isTop. + * + * @param int|null $isTop + * + * @return KujialeDesignerWorks + */ + public function setIsTop($isTop = null) + { + $this->is_top = $isTop; + + return $this; + } + + /** + * Get isTop. + * + * @return int|null + */ + public function getIsTop() + { + return $this->is_top; + } + + /** + * Set designId. + * + * @param string|null $designId + * + * @return KujialeDesignerWorks + */ + public function setDesignId($designId = null) + { + $this->design_id = $designId; + + return $this; + } + + /** + * Get designId. + * + * @return string|null + */ + public function getDesignId() + { + return $this->design_id; + } + + /** + * Set planId. + * + * @param string|null $planId + * + * @return KujialeDesignerWorks + */ + public function setPlanId($planId = null) + { + $this->plan_id = $planId; + + return $this; + } + + /** + * Get planId. + * + * @return string|null + */ + public function getPlanId() + { + return $this->plan_id; + } + + /** + * Set commName. + * + * @param string|null $commName + * + * @return KujialeDesignerWorks + */ + public function setCommName($commName = null) + { + $this->comm_name = $commName; + + return $this; + } + + /** + * Get commName. + * + * @return string|null + */ + public function getCommName() + { + return $this->comm_name; + } + + /** + * Set city. + * + * @param string|null $city + * + * @return KujialeDesignerWorks + */ + public function setCity($city = null) + { + $this->city = $city; + + return $this; + } + + /** + * Get city. + * + * @return string|null + */ + public function getCity() + { + return $this->city; + } + + /** + * Set name. + * + * @param string|null $name + * + * @return KujialeDesignerWorks + */ + public function setName($name = null) + { + $this->name = $name; + + return $this; + } + + /** + * Get name. + * + * @return string|null + */ + public function getName() + { + return $this->name; + } + + /** + * Set tagId. + * + * @param string|null $tagId + * + * @return KujialeDesignerWorks + */ + public function setTagId($tagId = null) + { + $this->tag_id = $tagId; + + return $this; + } + + /** + * Get tagId. + * + * @return string|null + */ + public function getTagId() + { + return $this->tag_id; + } + + /** + * Set designPanoUrl. + * + * @param string|null $designPanoUrl + * + * @return KujialeDesignerWorks + */ + public function setDesignPanoUrl($designPanoUrl = null) + { + $this->design_pano_url = $designPanoUrl; + + return $this; + } + + /** + * Get designPanoUrl. + * + * @return string|null + */ + public function getDesignPanoUrl() + { + return $this->design_pano_url; + } + + /** + * Set userAvatar. + * + * @param string|null $userAvatar + * + * @return KujialeDesignerWorks + */ + public function setUserAvatar($userAvatar = null) + { + $this->userAvatar = $userAvatar; + + return $this; + } + + /** + * Get userAvatar. + * + * @return string|null + */ + public function getUserAvatar() + { + return $this->userAvatar; + } + + /** + * Set email. + * + * @param string|null $email + * + * @return KujialeDesignerWorks + */ + public function setEmail($email = null) + { + $this->email = $email; + + return $this; + } + + /** + * Get email. + * + * @return string|null + */ + public function getEmail() + { + return $this->email; + } + + /** + * Set userName. + * + * @param string|null $userName + * + * @return KujialeDesignerWorks + */ + public function setUserName($userName = null) + { + $this->user_name = $userName; + + return $this; + } + + /** + * Get userName. + * + * @return string|null + */ + public function getUserName() + { + return $this->user_name; + } + + /** + * Set userId. + * + * @param string|null $userId + * + * @return KujialeDesignerWorks + */ + public function setUserId($userId = null) + { + $this->userId = $userId; + + return $this; + } + + /** + * Get userId. + * + * @return string|null + */ + public function getUserId() + { + return $this->userId; + } + + /** + * Set organizationId. + * + * @param string|null $organizationId + * + * @return KujialeDesignerWorks + */ + public function setOrganizationId($organizationId = null) + { + $this->organization_id = $organizationId; + + return $this; + } + + /** + * Get organizationId. + * + * @return string|null + */ + public function getOrganizationId() + { + return $this->organization_id; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerWorks + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerWorks + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } + + /** + * Set ViewCount. + * + * @param int|null $viewCount + * + * @return KujialeDesignerWorks + */ + public function setViewCount($viewCount = null) + { + $this->view_count = $viewCount; + + return $this; + } + + /** + * Get ViewCount. + * + * @return int|null + */ + public function getViewCount() + { + return $this->view_count; + } + + /** + * Set LikeCount. + * + * @param int|null $likeCount + * + * @return KujialeDesignerWorks + */ + public function setLikeCount($likeCount = null) + { + $this->like_count = $likeCount; + + return $this; + } + + /** + * Get LikeCount. + * + * @return int|null + */ + public function getLikeCount() + { + return $this->like_count; + } + + /** + * Set KuCreated. + * + * @param int|null $kuCreated + * + * @return KujialeDesignerWorks + */ + public function setKuCreated($kuCreated = null) + { + $this->ku_created = $kuCreated; + + return $this; + } + + /** + * Get KuCreated. + * + * @return int|null + */ + public function getKuCreated() + { + return $this->ku_created; + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerWorksItemRel.php b/src/KujialeBundle/Entities/KujialeDesignerWorksItemRel.php new file mode 100644 index 0000000..d35a649 --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerWorksItemRel.php @@ -0,0 +1,196 @@ +id; + } + + /** + * Set itemId. + * + * @param int $itemId + * + * @return KujialeDesignerWorksItemRel + */ + public function setItemId($itemId) + { + $this->item_id = $itemId; + + return $this; + } + + /** + * Get itemId. + * + * @return int + */ + public function getItemId() + { + return $this->item_id; + } + + /** + * Set designId. + * + * @param string $designId + * + * @return KujialeDesignerWorksItemRel + */ + public function setDesignId($designId) + { + $this->design_id = $designId; + + return $this; + } + + /** + * Get designId. + * + * @return string + */ + public function getDesignId() + { + return $this->design_id; + } + + /** + * Set goodsBn. + * + * @param string|null $goodsBn + * + * @return KujialeDesignerWorksItemRel + */ + public function setGoodsBn($goodsBn = null) + { + $this->goods_bn = $goodsBn; + + return $this; + } + + /** + * Get goodsBn. + * + * @return string|null + */ + public function getGoodsBn() + { + return $this->goods_bn; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerWorksItemRel + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerWorksItemRel + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerWorksLevel.php b/src/KujialeBundle/Entities/KujialeDesignerWorksLevel.php new file mode 100644 index 0000000..f53f3c4 --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerWorksLevel.php @@ -0,0 +1,314 @@ +id; + } + + /** + * Set designId. + * + * @param string $designId + * + * @return KujialeDesignerWorksLevel + */ + public function setDesignId($designId) + { + $this->design_id = $designId; + + return $this; + } + + /** + * Get designId. + * + * @return string + */ + public function getDesignId() + { + return $this->design_id; + } + + /** + * Set planId. + * + * @param string|null $planId + * + * @return KujialeDesignerWorksLevel + */ + public function setPlanId($planId = null) + { + $this->plan_id = $planId; + + return $this; + } + + /** + * Get planId. + * + * @return string|null + */ + public function getPlanId() + { + return $this->plan_id; + } + + /** + * Set specName. + * + * @param string|null $specName + * + * @return KujialeDesignerWorksLevel + */ + public function setSpecName($specName = null) + { + $this->spec_name = $specName; + + return $this; + } + + /** + * Get specName. + * + * @return string|null + */ + public function getSpecName() + { + return $this->spec_name; + } + + /** + * Set srcArea. + * + * @param string|null $srcArea + * + * @return KujialeDesignerWorksLevel + */ + public function setSrcArea($srcArea = null) + { + $this->src_area = $srcArea; + + return $this; + } + + /** + * Get srcArea. + * + * @return string|null + */ + public function getSrcArea() + { + return $this->src_area; + } + + /** + * Set area. + * + * @param string|null $area + * + * @return KujialeDesignerWorksLevel + */ + public function setArea($area = null) + { + $this->area = $area; + + return $this; + } + + /** + * Get area. + * + * @return string|null + */ + public function getArea() + { + return $this->area; + } + + /** + * Set realArea. + * + * @param string|null $realArea + * + * @return KujialeDesignerWorksLevel + */ + public function setRealArea($realArea = null) + { + $this->real_area = $realArea; + + return $this; + } + + /** + * Get realArea. + * + * @return string|null + */ + public function getRealArea() + { + return $this->real_area; + } + + /** + * Set planPic. + * + * @param string|null $planPic + * + * @return KujialeDesignerWorksLevel + */ + public function setPlanPic($planPic = null) + { + $this->planPic = $planPic; + + return $this; + } + + /** + * Get planPic. + * + * @return string|null + */ + public function getPlanPic() + { + return $this->planPic; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerWorksLevel + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerWorksLevel + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerWorksLike.php b/src/KujialeBundle/Entities/KujialeDesignerWorksLike.php new file mode 100644 index 0000000..518092e --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerWorksLike.php @@ -0,0 +1,202 @@ +id; + } + + /** + * Set PicId. + * + * @param string $picId + * + * @return KujialeDesignerWorksPic + */ + public function setPicId($picId) + { + $this->pic_id = $picId; + + return $this; + } + + /** + * Set designId. + * + * @param string|null $designId + * + * @return KujialeDesignerWorksPic + */ + public function setDesignId($designId = null) + { + $this->design_id = $designId; + + return $this; + } + + /** + * Get designId. + * + * @return string|null + */ + public function getDesignId() + { + return $this->design_id; + } + + /** + * Set planId. + * + * @param string|null $planId + * + * @return KujialeDesignerWorksPic + */ + public function setPlanId($planId = null) + { + $this->plan_id = $planId; + + return $this; + } + + /** + * Get planId. + * + * @return string|null + */ + public function getPlanId() + { + return $this->plan_id; + } + + /** + * Set UserId. + * + * @param string|null $userId + * + * @return KujialeDesignerWorksPic + */ + public function setUserId($userId = null) + { + $this->user_id = $userId; + + return $this; + } + + /** + * Get UserId. + * + * @return string|null + */ + public function getUserId() + { + return $this->user_id; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerWorksPic + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerWorksPic + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerWorksPic.php b/src/KujialeBundle/Entities/KujialeDesignerWorksPic.php new file mode 100644 index 0000000..e6b6802 --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerWorksPic.php @@ -0,0 +1,375 @@ +id; + } + + /** + * Set PicId. + * + * @param string $picId + * + * @return KujialeDesignerWorksPic + */ + public function setPicId($picId) + { + $this->pic_id = $picId; + + return $this; + } + + /** + * Get PicId. + * + * @return string + */ + public function getPicId() + { + return $this->pic_id; + } + + /** + * Set PicType. + * + * @param string|null $picType + * + * @return KujialeDesignerWorksPic + */ + public function setPicType($picType = null) + { + $this->pic_type = $picType; + + return $this; + } + + /** + * Get PicType. + * + * @return string|null + */ + public function getPicType() + { + return $this->pic_type; + } + + /** + * Set PicDetailType. + * + * @param int|null $picDetailType + * + * @return KujialeDesignerWorksPic + */ + public function setPicDetailType($picDetailType = null) + { + $this->pic_detail_type = $picDetailType; + + return $this; + } + + /** + * Get PicDetailType. + * + * @return int|null + */ + public function getPicDetailType() + { + return $this->pic_detail_type; + } + + /** + * Set RoomName. + * + * @param int|null $roomName + * + * @return KujialeDesignerWorksPic + */ + public function setRoomName($roomName = null) + { + $this->room_name = $roomName; + + return $this; + } + + /** + * Get RoomName. + * + * @return int|null + */ + public function getRoomName() + { + return $this->room_name; + } + + /** + * Set img. + * + * @param int|null $img + * + * @return KujialeDesignerWorksPic + */ + public function setImg($img = null) + { + $this->img = $img; + + return $this; + } + + /** + * Get img. + * + * @return int|null + */ + public function getImg() + { + return $this->img; + } + + /** + * Set panoLink. + * + * @param int|null $panoLink + * + * @return KujialeDesignerWorksPic + */ + public function setPanoLink($PanoLink = null) + { + $this->pano_link = $PanoLink; + + return $this; + } + + /** + * Get panoLink. + * + * @return int|null + */ + public function getPanoLink() + { + return $this->pano_link; + } + + /** + * Set designId. + * + * @param string|null $designId + * + * @return KujialeDesignerWorksPic + */ + public function setDesignId($designId = null) + { + $this->design_id = $designId; + + return $this; + } + + /** + * Get designId. + * + * @return string|null + */ + public function getDesignId() + { + return $this->design_id; + } + + /** + * Set planId. + * + * @param string|null $planId + * + * @return KujialeDesignerWorksPic + */ + public function setPlanId($planId = null) + { + $this->plan_id = $planId; + + return $this; + } + + /** + * Get planId. + * + * @return string|null + */ + public function getPlanId() + { + return $this->plan_id; + } + + /** + * Set commName. + * + * @param string|null $level + * + * @return KujialeDesignerWorksPic + */ + public function setLevel($level = null) + { + $this->level = $level; + + return $this; + } + + /** + * Get commName. + * + * @return string|null + */ + public function getLevel() + { + return $this->level; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerWorksPic + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerWorksPic + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/KujialeBundle/Entities/KujialeDesignerWorksRelCities.php b/src/KujialeBundle/Entities/KujialeDesignerWorksRelCities.php new file mode 100644 index 0000000..8b4ed55 --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerWorksRelCities.php @@ -0,0 +1,189 @@ +id; + } + + /** + * Set designId. + * + * @param string $designId + * + * @return KujialeDesignerWorksRelCities + */ + public function setDesignId($designId) + { + $this->design_id = $designId; + + return $this; + } + + /** + * Get designId. + * + * @return string + */ + public function getDesignId() + { + return $this->design_id; + } + + /** + * Set planId. + * + * @param string|null $planId + * + * @return KujialeDesignerWorksRelCities + */ + public function setPlanId($planId = null) + { + $this->plan_id = $planId; + + return $this; + } + + /** + * Get planId. + * + * @return string|null + */ + public function getPlanId() + { + return $this->plan_id; + } + + /** + * Set cityId. + * + * @param int $cityId + * + * @return KujialeDesignerWorksRelCities + */ + public function setCityId($cityId) + { + $this->city_id = $cityId; + + return $this; + } + + /** + * Get cityId. + * + * @return int + */ + public function getCityId() + { + return $this->city_id; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerWorksRelCities + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerWorksRelCities + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} + diff --git a/src/KujialeBundle/Entities/KujialeDesignerWorksRelTags.php b/src/KujialeBundle/Entities/KujialeDesignerWorksRelTags.php new file mode 100644 index 0000000..8822b94 --- /dev/null +++ b/src/KujialeBundle/Entities/KujialeDesignerWorksRelTags.php @@ -0,0 +1,283 @@ +id; + } + + /** + * Set tagCategoryId. + * + * @param string $tagCategoryId + * + * @return KujialeDesignerWorksRelTags + */ + public function setTagCategoryId($tagCategoryId) + { + $this->tag_category_id = $tagCategoryId; + + return $this; + } + + /** + * Get tagCategoryId. + * + * @return string + */ + public function getTagCategoryId() + { + return $this->tag_category_id; + } + + /** + * Set tagCategoryName. + * + * @param string|null $tagCategoryName + * + * @return KujialeDesignerWorksRelTags + */ + public function setTagCategoryName($tagCategoryName = null) + { + $this->tag_category_name = $tagCategoryName; + + return $this; + } + + /** + * Get tagCategoryName. + * + * @return string|null + */ + public function getTagCategoryName() + { + return $this->tag_category_name; + } + + /** + * Set tagId. + * + * @param string|null $tagId + * + * @return KujialeDesignerWorksRelTags + */ + public function setTagId($tagId = null) + { + $this->tag_id = $tagId; + + return $this; + } + + /** + * Get tagId. + * + * @return string|null + */ + public function getTagId() + { + return $this->tag_id; + } + + /** + * Set tagName. + * + * @param string|null $tagName + * + * @return KujialeDesignerWorksRelTags + */ + public function setTagName($tagName = null) + { + $this->tag_name = $tagName; + + return $this; + } + + /** + * Get tagName. + * + * @return string|null + */ + public function getTagName() + { + return $this->tag_name; + } + + /** + * Set designId. + * + * @param string $designId + * + * @return KujialeDesignerWorksRelTags + */ + public function setDesignId($designId) + { + $this->design_id = $designId; + + return $this; + } + + /** + * Get designId. + * + * @return string + */ + public function getDesignId() + { + return $this->design_id; + } + + /** + * Set planId. + * + * @param string|null $planId + * + * @return KujialeDesignerWorksRelTags + */ + public function setPlanId($planId = null) + { + $this->plan_id = $planId; + + return $this; + } + + /** + * Get planId. + * + * @return string|null + */ + public function getPlanId() + { + return $this->plan_id; + } + + /** + * Set created. + * + * @param int $created + * + * @return KujialeDesignerWorksRelTags + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int|null $updated + * + * @return KujialeDesignerWorksRelTags + */ + public function setUpdated($updated = null) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/KujialeBundle/Http/Api/V1/Action/KuController.php b/src/KujialeBundle/Http/Api/V1/Action/KuController.php new file mode 100644 index 0000000..f16a1c1 --- /dev/null +++ b/src/KujialeBundle/Http/Api/V1/Action/KuController.php @@ -0,0 +1,695 @@ +worksItemRelRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorksItemRel::class); + $this->itemsRepository = app('registry')->getManager('default')->getRepository(Items::class); + $this->desginService = new KujialeDesignerWorksService(); + $this->designerWorksRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorks::class); + } + + /** + * 测试方法 + * @param Request $request + * @route 未配置路由 + */ + public function onTest(Request $request) + { + $itemService = new DesignerWorksScriptService(); + $itemService->updateDesignerWorksPic(); + } + + /** + * 设计师方案列表 + * @param Request $request + * @route 未配置路由(可能在其他路由文件中) + */ + public function desginWorkList(Request $request){ + + $validator = app('validator')->make($request->all(), [ + 'page' => 'required|integer|min:1', + 'pageSize' => 'required|integer|min:1|max:50', + ]); + + $filter = []; + + $keyword = $request->input('keywords'); + if(isset($keyword) && !empty($keyword)){ + $filter['keyword'] = $keyword; + } + + $tags = $request->input('tags_params'); + if(isset($tags) && !empty($tags)){ + if(!is_array($tags)){ + throw new ResourceException('参数无效'); + } + $filter['tags'] = $tags; + } + + $filter['normal'] = $request->input('normal') ?? ''; + $filter['new'] = $request->input('new') ?? ''; + $filter['viewcount'] = $request->input('viewcount') ?? ''; + $filter['likecount'] = $request->input('likecount') ?? ''; + + $page = $request->input('page', 1); + $limit = $request->input('pageSize', 50); + + $result = $this->desginService->getDesignerWorksList($filter,$page,$limit); + return $this->response->array($result); + } + + /** + * 新增设计师作品与商品绑定 + * @route POST /kujiale/designer-works/bind-item + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function bindDesignerWorksItem(Request $request) + { + $validator = app('validator')->make($request->all(), [ + 'item_id' => 'required', + 'design_id' => 'required|string', + ]); + + if ($validator->fails()) { + throw new ValidationHttpException($validator->errors()); + } + + // item_id 支持数组 + $itemIds = $request->input('item_id'); + if (!is_array($itemIds)) { + $itemIds = [$itemIds]; + } + // 去重并过滤非法值 + $itemIds = array_values(array_unique(array_filter($itemIds, function ($id) { + return is_numeric($id) && $id > 0; + }))); + + if (empty($itemIds)) { + throw new ResourceException('item_id 参数无效'); + } + + $designId = $request->input('design_id'); + + // 检查该 design_id 是否已经绑定过商品(一个 design 只能绑定一个商品) + // $existingRel = $this->worksItemRelRepository->getInfo(['design_id' => $designId]); + // if (!empty($existingRel)) { + // // 如果已存在绑定关系,先删除旧的 + // $this->worksItemRelRepository->deleteBy(['design_id' => $designId]); + // } + + $success = 0; + $skipped = 0; + $errors = []; + $createdData = []; + + foreach ($itemIds as $itemId) { + // 验证商品是否存在 + $item = $this->itemsRepository->getInfo(['item_id' => $itemId]); + if (empty($item)) { + $errors[] = "商品不存在: {$itemId}"; + continue; + } + + // 如果该商品已存在绑定关系则跳过 + $existingItemRel = $this->worksItemRelRepository->getInfo([ + 'item_id' => $itemId, + 'design_id'=>$designId + ]); + if (!empty($existingItemRel)) { + $skipped++; + continue; + } + + // 获取商品的 goods_bn(SPU货号) + $goodsBn = isset($item['goods_bn']) ? $item['goods_bn'] : null; + + // 创建新的绑定关系 + $data = [ + 'item_id' => $itemId, + 'design_id' => $designId, + 'goods_bn' => $goodsBn, + 'created' => time(), + 'updated' => time(), + ]; + + try { + $result = $this->worksItemRelRepository->create($data); + $createdData[] = $result; + $success++; + } catch (\Exception $e) { + $errors[] = "商品 {$itemId} 绑定失败:" . $e->getMessage(); + } + } + + return $this->response->array([ + 'success' => empty($errors), + 'message' => '绑定完成', + 'success_count' => $success, + 'skipped_count' => $skipped, + 'data' => $createdData, + 'errors' => $errors, + ]); + } + + /** + * 删除设计师作品与商品绑定(支持批量) + * @route DELETE /kujiale/designer-works/unbind-item + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function unbindDesignerWorksItem(Request $request) + { + $data = $request->input(); + + // 如果传入的是数组格式 [{"design_id":xx,"item_id":xxx}] + if (isset($data[0]) && is_array($data[0])) { + $bindings = $data; + } else { + // 兼容单个对象格式 {"design_id":xx,"item_id":xxx} + $bindings = [$data]; + } + + // 验证数据结构 + if (empty($bindings) || !is_array($bindings)) { + throw new ValidationHttpException(['message' => '参数格式错误,需要传入数组格式']); + } + + $successCount = 0; + $failCount = 0; + $errors = []; + + try { + foreach ($bindings as $index => $binding) { + // 验证每个绑定关系的数据 + if (!isset($binding['design_id']) || !isset($binding['item_id'])) { + $failCount++; + $errors[] = "第" . ($index + 1) . "条数据缺少 design_id 或 item_id"; + continue; + } + + $designId = $binding['design_id']; + $itemId = $binding['item_id']; + + // 验证 item_id 格式 + if (!is_numeric($itemId) || $itemId < 1) { + $failCount++; + $errors[] = "第" . ($index + 1) . "条数据的 item_id 格式错误"; + continue; + } + + // 验证 design_id 格式 + if (empty($designId)) { + $failCount++; + $errors[] = "第" . ($index + 1) . "条数据的 design_id 不能为空"; + continue; + } + + // 检查绑定关系是否存在 + $existingRel = $this->worksItemRelRepository->getInfo([ + 'design_id' => $designId, + 'item_id' => $itemId + ]); + + if (empty($existingRel)) { + $failCount++; + $errors[] = "第" . ($index + 1) . "条数据的绑定关系不存在"; + continue; + } + + // 删除绑定关系 + $this->worksItemRelRepository->deleteBy([ + 'design_id' => $designId, + 'item_id' => $itemId + ]); + $successCount++; + } + + $result = [ + 'success' => true, + 'message' => '批量解绑完成', + 'total' => count($bindings), + 'success_count' => $successCount, + 'fail_count' => $failCount + ]; + + if (!empty($errors)) { + $result['errors'] = $errors; + } + + return $this->response->array($result); + } catch (\Exception $e) { + throw new ResourceException('解绑失败:' . $e->getMessage()); + } + } + + /** + * 查询关联了design的商品列表 + * @route GET /kujiale/designer-works/items + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function getDesignerWorksItems(Request $request) + { + $validator = app('validator')->make($request->all(), [ + 'page' => 'integer|min:1', + 'pageSize' => 'integer|min:1|max:100', + ]); + + if ($validator->fails()) { + throw new ValidationHttpException($validator->errors()); + } + + $page = $request->input('page', 1); + $pageSize = $request->input('pageSize', 20); + + // 获取当前用户的公司ID + $auth = (array)app("request")->attributes->get("auth"); + $companyId = app('auth')->user()->get('company_id'); + if (!$companyId) { + throw new ResourceException('无法获取公司ID'); + } + + // 获取筛选条件 + $itemName = $request->input('item_name'); // 商品名称搜索 + $itemBn = $request->input('item_bn'); // 商品编号搜索 + $goodsBn = $request->input('goods_bn'); // SPU货号搜索 + $designId = $request->input('design_id'); // 方案ID搜索 + $designName = $request->input('design_name'); // 方案名称搜索 + $approveStatus = $request->input('approve_status'); // 商品状态筛选 + $itemCategory = $request->input('item_category'); // 管理分类筛选 + + $conn = app('registry')->getConnection('default'); + + // 构建查询 + $qb = $conn->createQueryBuilder(); + $qb->select([ + 'i.item_id', + 'i.item_name', + 'i.item_bn', + 'i.goods_bn as item_goods_bn', + 'i.approve_status', + 'i.item_category', + 'i.store', + 'i.price', + 'i.market_price', + 'i.pics', + 'i.created', + 'i.updated', + 'rel.design_id', + 'rel.goods_bn', + 'w.design_name', + 'w.cover_pic', + 'rel.id as rel_id', + 'rel.created as bind_created' + ]) + ->from('kujiale_designer_works_item_rel', 'rel') + ->innerJoin('rel', 'items', 'i', 'rel.item_id = i.item_id') + ->leftJoin('rel', 'kujiale_designer_works', 'w', 'rel.design_id = w.design_id') + ->where($qb->expr()->eq('i.company_id', $qb->expr()->literal($companyId))); + + // 商品名称搜索 + if (!empty($itemName)) { + $qb->andWhere($qb->expr()->like('i.item_name', $qb->expr()->literal('%' . $itemName . '%'))); + } + + // 商品编号搜索 + if (!empty($itemBn)) { + $qb->andWhere($qb->expr()->like('i.item_bn', $qb->expr()->literal('%' . $itemBn . '%'))); + } + + // SPU货号搜索(支持在绑定表和商品表中搜索) + if (!empty($goodsBn)) { + $qb->andWhere($qb->expr()->orX( + $qb->expr()->like('rel.goods_bn', $qb->expr()->literal('%' . $goodsBn . '%')), + $qb->expr()->like('i.goods_bn', $qb->expr()->literal('%' . $goodsBn . '%')) + )); + } + + // 方案ID搜索 + if (!empty($designId)) { + $qb->andWhere($qb->expr()->eq('rel.design_id', $qb->expr()->literal($designId))); + } + + // 方案名称搜索 + if (!empty($designName)) { + $qb->andWhere($qb->expr()->like('w.design_name', $qb->expr()->literal('%' . $designName . '%'))); + } + + // 商品状态筛选 + if (!empty($approveStatus)) { + if (is_array($approveStatus)) { + $placeholders = []; + foreach ($approveStatus as $index => $status) { + $placeholders[] = ':status_' . $index; + $qb->setParameter('status_' . $index, $status); + } + $qb->andWhere($qb->expr()->in('i.approve_status', $placeholders)); + } else { + $qb->andWhere($qb->expr()->eq('i.approve_status', $qb->expr()->literal($approveStatus))); + } + } + + // 管理分类筛选 + if (!empty($itemCategory)) { + if (is_array($itemCategory)) { + $placeholders = []; + foreach ($itemCategory as $index => $category) { + $placeholders[] = ':category_' . $index; + $qb->setParameter('category_' . $index, $category); + } + $qb->andWhere($qb->expr()->in('i.item_category', $placeholders)); + } else { + $qb->andWhere($qb->expr()->eq('i.item_category', $qb->expr()->literal($itemCategory))); + } + } + + // 获取总数 + $countQb = clone $qb; + $countQb->select('COUNT(DISTINCT rel.id) as total'); + $total = $countQb->execute()->fetchColumn(); + $total = intval($total); + + // 排序 + $qb->orderBy('rel.created', 'DESC'); + + // 分页 + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + + // 执行查询 + $list = $qb->execute()->fetchAll(); + + // 收集 item_id 和 design_id,便于批量查询销售分类和标签 + $itemIds = array_column($list, 'item_id'); + $designIds = array_column($list, 'design_id'); + + // 批量查询销售分类(items_rel_cats + items_category,is_main_category=0) + $salesCateMap = []; + if (!empty($itemIds)) { + $cateQb = $conn->createQueryBuilder(); + $cateQb->select(['irc.item_id', 'ic.category_name']) + ->from('goods_items_rel_cats', 'irc') + ->innerJoin('irc', 'items_category', 'ic', 'irc.category_id = ic.category_id') + ->where($cateQb->expr()->in('irc.item_id', $itemIds)) + ->andWhere('ic.is_main_category = 0'); + $cateRows = $cateQb->execute()->fetchAll(); + foreach ($cateRows as $row) { + $salesCateMap[$row['item_id']][] = $row['category_name']; + } + } + + // 批量查询商品标签(items_rel_tags + items_tags) + $itemTagsMap = []; + if (!empty($itemIds)) { + $itemTagQb = $conn->createQueryBuilder(); + $itemTagQb->select(['irt.item_id', 'it.tag_id', 'it.tag_name', 'it.tag_color', 'it.font_color']) + ->from('items_rel_tags', 'irt') + ->innerJoin('irt', 'items_tags', 'it', 'irt.tag_id = it.tag_id') + ->where($itemTagQb->expr()->in('irt.item_id', $itemIds)) + ->andWhere($itemTagQb->expr()->eq('irt.company_id', $itemTagQb->expr()->literal($companyId))) + ->andWhere($itemTagQb->expr()->eq('it.company_id', $itemTagQb->expr()->literal($companyId))); + + $itemTagRows = $itemTagQb->execute()->fetchAll(); + foreach ($itemTagRows as $row) { + $itemTagsMap[$row['item_id']][] = [ + 'tag_id' => $row['tag_id'], + 'tag_name' => $row['tag_name'], + 'tag_color' => $row['tag_color'], + 'font_color' => $row['font_color'], + ]; + } + } + + // 批量查询设计标签(kujiale_designer_works_rel_tags) + $designTagsMap = []; + if (!empty($designIds)) { + $tagQb = $conn->createQueryBuilder(); + // 使用占位符避免字符串未加引号导致的 SQL 错误 + $placeholders = []; + foreach ($designIds as $idx => $dId) { + $ph = ':design_id_' . $idx; + $placeholders[] = $ph; + $tagQb->setParameter('design_id_' . $idx, $dId); + } + + $tagQb->select(['design_id', 'tag_name']) + ->from('kujiale_designer_works_rel_tags') + ->where($tagQb->expr()->in('design_id', $placeholders)); + + $tagRows = $tagQb->execute()->fetchAll(); + foreach ($tagRows as $row) { + $designTagsMap[$row['design_id']][] = $row['tag_name']; + } + } + + // 处理结果 + $resultList = []; + foreach ($list as $row) { + $salesCategories = $salesCateMap[$row['item_id']] ?? []; + $itemTags = $itemTagsMap[$row['item_id']] ?? []; + $designTags = $designTagsMap[$row['design_id']] ?? []; + + // 将销售分类数组转换为字符串(用逗号分隔) + $itemCatName = !empty($salesCategories) ? implode(',', $salesCategories) : ''; + + $item = [ + 'item_id' => $row['item_id'], + 'item_name' => $row['item_name'], + 'item_bn' => $row['item_bn'], + 'goods_bn' => $row['goods_bn'] ?: $row['item_goods_bn'], // 优先使用绑定表中的goods_bn + 'approve_status' => $row['approve_status'], + 'item_category' => $row['item_category'], + 'stock' => isset($row['store']) ? (int)$row['store'] : null, + 'itemCatName' => $itemCatName, // 销售分类名称(字符串格式) + 'tagList' => $itemTags, // 商品标签列表 + 'price' => $row['price'], + 'market_price' => $row['market_price'], + 'pics' => $row['pics'] ? json_decode($row['pics'], true) : [], + 'created' => $row['created'], + 'updated' => $row['updated'], + 'design' => [ + 'design_id' => $row['design_id'], + 'design_name' => $row['design_name'], + 'cover_pic' => $row['cover_pic'], + 'tags' => $designTags ? implode(',', $designTags) : '', + ], + 'bind_info' => [ + 'rel_id' => $row['rel_id'], + 'bind_created' => $row['bind_created'], + ] + ]; + $resultList[] = $item; + } + + return $this->response->array([ + 'success' => true, + 'total_count' => $total, + 'page' => $page, + 'pageSize' => $pageSize, + 'list' => $resultList + ]); + } + + /** + * 获取设计师作品列表(用于前端选择设计并绑定商品) + * @route GET /kujiale/designer-works/list + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function getDesignerWorksList(Request $request) + { + $validator = app('validator')->make($request->all(), [ + 'page' => 'integer|min:1', + 'pageSize' => 'integer|min:1|max:100', + ]); + + if ($validator->fails()) { + throw new ValidationHttpException($validator->errors()); + } + + $page = $request->input('page', 1); + $pageSize = $request->input('pageSize', 20); + + // 获取筛选条件 + $designName = $request->input('design_name'); // 设计名称搜索 + $designId = $request->input('design_id'); // 设计ID搜索 + $keyword = $request->input('keyword'); // 关键词搜索(设计名称或设计ID) + + // 构建查询条件 + $filter = []; + + // 设计名称搜索 + if (!empty($designName)) { + $filter['design_name|like'] = $designName; + } + + // 设计ID搜索 + if (!empty($designId)) { + $filter['design_id'] = $designId; + } + + // 关键词搜索(同时搜索设计名称和设计ID) + if (!empty($keyword)) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('*') + ->from('kujiale_designer_works') + ->where($qb->expr()->orX( + $qb->expr()->like('design_name', $qb->expr()->literal('%' . $keyword . '%')), + $qb->expr()->like('design_id', $qb->expr()->literal('%' . $keyword . '%')) + )); + + // 获取总数 + $countQb = clone $qb; + $countQb->select('COUNT(*) as total'); + $total = $countQb->execute()->fetchColumn(); + $total = intval($total); + + // 排序和分页 + $qb->orderBy('created', 'DESC'); + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + + $list = $qb->execute()->fetchAll(); + } else { + // 使用 Repository 的 lists 方法 + $orderBy = ['created' => 'DESC']; + $result = $this->designerWorksRepository->lists($filter, $page, $pageSize, $orderBy); + $total = $result['total_count']; + $list = $result['list']; + } + + // 批量获取所有已绑定的设计信息(用于标记是否已绑定) + $boundDesignMap = []; // key: design_id, value: boundRel info + $boundItemMap = []; // key: item_id, value: item info + if (!empty($list)) { + $designIds = array_column($list, 'design_id'); + $boundRels = $this->worksItemRelRepository->getLists(['design_id' => $designIds]); + + // 构建绑定关系映射 + foreach ($boundRels as $boundRel) { + $boundDesignMap[$boundRel['design_id']] = $boundRel; + // 收集需要查询的商品ID + if (!empty($boundRel['item_id'])) { + $boundItemMap[$boundRel['item_id']] = null; // 先占位 + } + } + + // 批量查询商品信息 + if (!empty($boundItemMap)) { + $itemIds = array_keys($boundItemMap); + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('item_id', 'item_name', 'item_bn', 'goods_bn') + ->from('items') + ->where($qb->expr()->in('item_id', $itemIds)); + $items = $qb->execute()->fetchAll(); + + foreach ($items as $item) { + $boundItemMap[$item['item_id']] = $item; + } + } + } + + // 处理结果 + $resultList = []; + foreach ($list as $row) { + $designId = $row['design_id']; + $isBound = isset($boundDesignMap[$designId]); + + // 如果已绑定,获取绑定的商品信息 + $boundItemInfo = null; + if ($isBound) { + $boundRel = $boundDesignMap[$designId]; + if (!empty($boundRel['item_id']) && isset($boundItemMap[$boundRel['item_id']])) { + $item = $boundItemMap[$boundRel['item_id']]; + if (!empty($item)) { + $boundItemInfo = [ + 'item_id' => $item['item_id'], + 'item_name' => $item['item_name'], + 'item_bn' => $item['item_bn'], + 'goods_bn' => $boundRel['goods_bn'] ?: $item['goods_bn'], + ]; + } + } + } + + $design = [ + 'id' => $row['id'], + 'design_id' => $designId, + 'design_name' => $row['design_name'], + 'cover_pic' => $row['cover_pic'], + 'plan_id' => $row['plan_id'], + 'comm_name' => $row['comm_name'], + 'city' => $row['city'], + 'name' => $row['name'], + 'view_count' => $row['view_count'] ?? 0, + 'like_count' => $row['like_count'] ?? 0, + 'created' => $row['created'], + 'updated' => $row['updated'], + 'is_bound' => $isBound, // 是否已绑定商品 + 'bound_item' => $boundItemInfo, // 绑定的商品信息(如果已绑定) + ]; + $resultList[] = $design; + } + + return $this->response->array([ + 'success' => true, + 'total_count' => $total, + 'page' => $page, + 'pageSize' => $pageSize, + 'list' => $resultList + ]); + } +} diff --git a/src/KujialeBundle/Http/FrontApi/V1/Action/KuController.php b/src/KujialeBundle/Http/FrontApi/V1/Action/KuController.php new file mode 100644 index 0000000..8846ea8 --- /dev/null +++ b/src/KujialeBundle/Http/FrontApi/V1/Action/KuController.php @@ -0,0 +1,255 @@ +desginService = new KujialeDesignerWorksService(); + $this->tagsService = new KujialeDesignerTagsService(); + $this->likeService = new KujialeDesignerWorksLikeService(); + } + + public function desginWorkList(Request $request){ + + $validator = app('validator')->make($request->all(), [ + 'page' => 'required|integer|min:1', + 'pageSize' => 'required|integer|min:1|max:50', + ]); + + $filter = []; + + $keyword = $request->input('keywords'); + if(isset($keyword) && !empty($keyword)){ + $filter['keyword'] = $keyword; + } + + $tags = $request->input('tags_params'); + if(isset($tags) && !empty($tags)){ + if(!is_array($tags)){ + throw new ResourceException('参数无效'); + } + $filter['tags'] = $tags; + } + $cityIds = $request->input('city_id'); + if(isset($cityIds) && !empty($cityIds)){ + // if(!is_array($cityIds)){ + // throw new ResourceException('参数无效'); + // } + $filter['cityIds'] = $cityIds; + } + + $page = $request->input('page', 1); + $limit = $request->input('pageSize', 50); + $sort = $request->input('sort', ''); + $filter['page'] = $page; + $filter['pageSize'] = $limit; + $filter['sort'] = $sort; + + //直接打接口 + // $result = (new ApiService)->getDesignerWorks($filter); + $result = $this->desginService->getDesignerWorksList($filter,$page,$limit); + return $this->response->array($result); + } + + public function desginWorkDetail(Request $request){ + + $validator = app('validator')->make($request->all(), [ + 'design_id' => 'required|string', + 'plan_id' => 'required|string', + ]); + + if ($validator->fails()) { + throw new ResourceException('参数错误'); + } + + $design_id = $request->input('design_id'); + $plan_id = $request->input('plan_id'); + + $filter['design_id'] = $design_id; + $filter['plan_id'] = $plan_id; + $authInfo = $request->get('auth'); + // $userId = $authInfo['user_id']; + // if (!empty($userId)){ + // $filter['user_id'] = $userId; + // } + + $result = $this->desginService->getDesignerWorksDetail($filter); + return $this->response->array($result); + + } + + public function getDesginTagsList(Request $request){ + $filter = ['is_disabled' => 0]; + $result = $this->tagsService->getTagsList($filter); + // $result =(new ApiService)->getDesignerTags(); + return $this->response->array($result); + } + + public function updateDesignViewCount(Request $request){ + + $validator = app('validator')->make($request->all(), [ + 'design_id' => 'required|string', + 'plan_id' => 'required|string', + ]); + + if ($validator->fails()) { + throw new ResourceException('参数错误'); + } + + $design_id = $request->input('design_id'); + $plan_id = $request->input('plan_id'); + + $result = $this->desginService->updateViewCount($design_id,$plan_id); + return $this->response->array($result); + } + + public function updateDesignLikeCount(Request $request){ + + $authInfo = $request->get('auth'); + $userId = $authInfo['user_id']; + //$userId = 20; + + $validator = app('validator')->make($request->all(), [ + 'design_id' => 'required|string', + 'plan_id' => 'required|string', + 'is_like' => 'required|string', + ]); + + if ($validator->fails()) { + throw new ResourceException('参数错误'); + } + + $design_id = $request->input('design_id'); + $plan_id = $request->input('plan_id'); + $isLike = $request->input('is_like'); + + $this->likeService->saveLike($design_id,$plan_id,$userId, $isLike == 'true' ? 'like' : 'unlike'); + return $this->response->array(['status' => true]); + } + + public function getProductListByPicId(Request $request) { + $pic_id = $request->input('pic_id'); + $company_id = $request->input('company_id'); + $authInfo = $request->get('auth'); + + $kujialeDesignerGoodsRelService = new KujialeDesignerGoodsRelService(); + $kujialeDesignerGoodsService = new KujialeDesignerGoodsService(); + $kujialeDesignerWorksPicService = new KujialeDesignerWorksPicService(); + + $filter['pic_id'] = $pic_id; + $goods_rel = $kujialeDesignerGoodsRelService->lists($filter); + $goods = []; + $limitItemIds = []; + $itemsService = new ItemsService(); + if (!empty($goods_rel['list'])){ + foreach ($goods_rel['list'] as $rel){ + $filter_goods['good_id'] = $rel['obs_brand_good_id']; + $tempGoods = $kujialeDesignerGoodsService->lists($filter_goods); + if ($tempGoods['total_count'] > 0){ + foreach ($tempGoods['list'] as $item){ + $tempItemInfo = $itemsService->getInfo(['item_bn'=>$item['brand_good_code'], 'audit_status'=>'approved', 'company_id'=>$company_id]); + if (empty($tempItemInfo) || !$item['brand_good_code'] ) { + continue; + } + $item_id = $tempItemInfo['item_id']; + $goods[] = $itemsService->getItemsDetail($item_id, '', $limitItemIds, $company_id); + } + } + } + } + $picInfo = $kujialeDesignerWorksPicService->getInfo(['pic_id' => $pic_id]); + + $kujiale_pano53 = "pano53.p.kujiale.com"; + $kujiale_www = "www.kujiale.com"; + if(!empty($picInfo['pano_link'])){ + $picInfo['pano_link'] = str_replace($kujiale_www, $kujiale_pano53, $picInfo['pano_link']); + } + $result = [ + 'goods_list' => $goods, + 'pic_info' => $picInfo + ]; + + return $this->response->array($result); + } + + public function getDesignerPicById(Request $request) { + $pic_id = $request->input('pic_id'); + $kujialeDesignerWorksPicService = new KujialeDesignerWorksPicService(); + $picInfo = $kujialeDesignerWorksPicService->getInfo(['pic_id' => $pic_id]); + + return $this->response->array($picInfo); + } + + /** + * 获取城市列表 + * 转调酷家乐API获取城市数据 + * + * @param Request $request + * @return \Dingo\Api\Http\Response + */ + public function getLocationList(Request $request) + { + $apiUrl = 'https://qhstatic-cos.kujiale.com/openapi/cities.json'; + + try { + $client = new Client([ + 'timeout' => 10, + 'verify' => false + ]); + + $response = $client->request('GET', $apiUrl); + + if ($response->getStatusCode() == 200) { + $body = $response->getBody()->getContents(); + $data = json_decode($body, true); + + if (json_last_error() === JSON_ERROR_NONE) { + return $this->response->array($data); + } else { + throw new ResourceException('解析JSON数据失败'); + } + } else { + throw new ResourceException('获取城市列表失败'); + } + } catch (GuzzleException $e) { + app('log')->error('获取城市列表API失败: ' . $e->getMessage()); + throw new ResourceException('获取城市列表失败: ' . $e->getMessage()); + } catch (\Exception $e) { + app('log')->error('获取城市列表失败: ' . $e->getMessage()); + throw new ResourceException('获取城市列表失败'); + } + } + +} diff --git a/src/KujialeBundle/Interfaces/KujialeInterface.php b/src/KujialeBundle/Interfaces/KujialeInterface.php new file mode 100644 index 0000000..e69de29 diff --git a/src/KujialeBundle/Repositories/KujialeDesignerGoodsRelRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerGoodsRelRepository.php new file mode 100644 index 0000000..6372b4e --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerGoodsRelRepository.php @@ -0,0 +1,276 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $cols='*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $cols='*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} diff --git a/src/KujialeBundle/Repositories/KujialeDesignerGoodsRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerGoodsRepository.php new file mode 100644 index 0000000..6aa1ad8 --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerGoodsRepository.php @@ -0,0 +1,276 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $cols='*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $cols='*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} diff --git a/src/KujialeBundle/Repositories/KujialeDesignerTagsRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerTagsRepository.php new file mode 100644 index 0000000..e163db3 --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerTagsRepository.php @@ -0,0 +1,276 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} diff --git a/src/KujialeBundle/Repositories/KujialeDesignerWorksItemRelRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerWorksItemRelRepository.php new file mode 100644 index 0000000..932c9b2 --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerWorksItemRelRepository.php @@ -0,0 +1,277 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach ($data as $key => $val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if (!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if (!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach ($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach ($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set" . str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols = [], $ignore = []) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach ($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get" . str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach ($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v, $k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%' . $value . '%'; + } + if (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} diff --git a/src/KujialeBundle/Repositories/KujialeDesignerWorksLevelRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerWorksLevelRepository.php new file mode 100644 index 0000000..2445eeb --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerWorksLevelRepository.php @@ -0,0 +1,276 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} diff --git a/src/KujialeBundle/Repositories/KujialeDesignerWorksLikeRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerWorksLikeRepository.php new file mode 100644 index 0000000..dfbfe1f --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerWorksLikeRepository.php @@ -0,0 +1,277 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} diff --git a/src/KujialeBundle/Repositories/KujialeDesignerWorksPicRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerWorksPicRepository.php new file mode 100644 index 0000000..e3d1849 --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerWorksPicRepository.php @@ -0,0 +1,277 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} diff --git a/src/KujialeBundle/Repositories/KujialeDesignerWorksRelCitiesRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerWorksRelCitiesRepository.php new file mode 100644 index 0000000..a2b65b6 --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerWorksRelCitiesRepository.php @@ -0,0 +1,302 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + /** + * 根据design_id和plan_id删除所有关联的城市记录 + * + * @param string $designId + * @param string $planId + */ + public function deleteByDesignAndPlan($designId, $planId) + { + $filter = [ + 'design_id' => $designId, + 'plan_id' => $planId, + ]; + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + } + $em->flush(); + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} + diff --git a/src/KujialeBundle/Repositories/KujialeDesignerWorksRelTagsRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerWorksRelTagsRepository.php new file mode 100644 index 0000000..db07908 --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerWorksRelTagsRepository.php @@ -0,0 +1,276 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} diff --git a/src/KujialeBundle/Repositories/KujialeDesignerWorksRepository.php b/src/KujialeBundle/Repositories/KujialeDesignerWorksRepository.php new file mode 100644 index 0000000..f063a9a --- /dev/null +++ b/src/KujialeBundle/Repositories/KujialeDesignerWorksRepository.php @@ -0,0 +1,299 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多条数数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach($data as $key=>$val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if(!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if(!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + private function setColumnNamesData($entity, $params) + { + foreach($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols=[], $ignore=[]) + { + if (!$cols) $cols = $this->cols; + + $values = []; + foreach($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $values[$col] = $entity->$fun(); + } + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v,$k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + } else { + $qb =$qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function(&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 更新的条件 + */ + public function getLists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + /** + * 根据条件获取列表数据,包含数据总数条数 + * + * @param $filter 更新的条件 + */ + public function lists($filter, $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($this->cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page-1)*$pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + } + $result['list'] = $lists ?? []; + return $result; + } + + /** + * 根据主键获取数据 + * + * @param $id + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if( !$entity ) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } + + /** + * 更新浏览量 + * @param $filter + */ + public function countView($filter){ + $entity = $this->findOneBy($filter); + if( !$entity ) { + throw new ResourceException("未查询到更新数据"); + } + + $count = $this->getColumnNamesData($entity)['view_count']; + $data['view_count'] = $count + 1; + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + + } +} diff --git a/src/KujialeBundle/Services/DesignerWorksScriptService.php b/src/KujialeBundle/Services/DesignerWorksScriptService.php new file mode 100644 index 0000000..a45f5bc --- /dev/null +++ b/src/KujialeBundle/Services/DesignerWorksScriptService.php @@ -0,0 +1,187 @@ +apiService = new ApiService(); + } + + public function preProcDesignerWorks($worksList){ + $worksInfoList = []; + $workService = new KujialeDesignerWorksService(); + foreach($worksList['result'] as $result){ + if (empty($result['obsDesignId'])){ + continue; + } + + $tmp = []; + $tmp['coverPic'] = $result['coverPic']; + $tmp['designName'] = $result['designName']; + $tmp['isOrigin'] = (isset($result['isOrigin']) && $result['isOrigin']) == true ? 1 : 0; + $tmp['isExcellent'] = (isset($result['isExcellent']) && $result['isExcellent'] == true) ? 1 : 0; + $tmp['isRealExcellent'] = (isset($result['isRealExcellent']) && $result['isRealExcellent'] == true) ? 1 : 0; + $tmp['isTop'] = (isset($result['isTop']) && $result['isTop'] == true) ? 1 : 0; + $tmp['submitSampleRoom'] = (isset($result['submitSampleRoom']) && $result['submitSampleRoom'] == true) ? 1 : 0; + $tmp['designId'] = $result['obsDesignId']; + // $tmp['city_id_list'] = $result['cityIdList']; + $tmp['planId'] = !empty($result['obsPlanId'])?$result['obsPlanId']:$result['obsDesignId']; + $tmp['ku_created'] = $result['created'] *0.001; + // 获取方案信息 + $detail = $this->apiService->getDesignerWorksDetail($result['obsDesignId']); + if($detail && $detail['basicInfo']){ + $tmp['commName'] = $detail['basicInfo']['commName']; + $tmp['city'] = $detail['basicInfo']['city']; + $tmp['name'] = $detail['basicInfo']['name']; + $tmp['coverPic'] = $detail['basicInfo']['coverPic']; + } + // 楼层信息 + if($detail && $detail['levelInfos']){ + $tmp['level'] = $detail['levelInfos']; + } + + // 标签信息 + $tags = $this->apiService->getDesignerWorksRelTag($result['obsDesignId']); + if($tags){ + $tmp['tags'] = $tags; + } + + $tmp = array_merge($tmp,$result['authorVo']); + $worksInfoList[] = $tmp; + } + $workService->saveDesignerWorks($worksInfoList); + } + + /** + * 更新设计师方案作品 + */ + public function updateDesignerWorks(){ + + try{ + // 更新标签列表 + $tagsList = $this->apiService->getDesignerTags(); + if($tagsList){ + $tagsService = new KujialeDesignerTagsService(); + $tagsService->saveTags($tagsList); + } + + // 获取设计师方案 + $start = 0; + $num = 50; + $worksList = $this->apiService->getDesignerWorks($start,$num); + app('log')->info('当前处理设计师方案 第 '.($start + 1).' - '.($start + $num).' 条数据。共有:'.$worksList['count'].'条数据'); + if($worksList) { + // 如果有更多数据的话 + $this->preProcDesignerWorks($worksList); + // 如果还有数据,继续抓取 + while ($worksList['hasMore']) { + $start += $num; + $worksList = $this->apiService->getDesignerWorks($start,$num); + app('log')->info('当前处理设计师方案 第 '.($start + 1).' - '.($start + $num).' 条数据。共有:'.$worksList['count'].'条数据'); + if ($worksList) { + // 如果有更多数据的话 + $this->preProcDesignerWorks($worksList); + } + } + } + }catch(\Exception $e){ + throw $e; + } + } + + public function updateDesignerWorksPic(){ + + try{ + $worksService = new KujialeDesignerWorksService(); + $worksList = $worksService->getLists([]); + if($worksList){ + $picService = new KujialeDesignerWorksPicService(); + foreach($worksList as $work){ + $picList = $this->apiService->getDesignerWorksPicList($work['design_id']); + if($picList && $picList['totalCount'] > 0){ + foreach($picList['result'] as $pic){ + $pic['design_id'] = $work['design_id']; + $pic['plan_id'] = $work['plan_id']; + $result = $picService->savePic($pic); + } + } + } + } + + }catch(\Exception $e){ + throw $e; + } + + } + + public function updateDesignerPicAndGoods(){ + + try{ + $worksService = new KujialeDesignerWorksPicService(); + $worksList = $worksService->getLists([]); + if($worksList){ + $picService = new KujialeDesignerGoodsRelService(); + foreach($worksList as $work){ + $picList = $this->apiService->getDesignerWorksRoomBrandGoods($work['pic_id']); + if (!empty($picList['obsBrandGoodIdList'])){ + foreach ($picList['obsBrandGoodIdList'] as $godds){ + $goods_rel = [ + 'picId' => $work['pic_id'], + 'obsBrandGoodId' => $godds + ]; + $picService->saveGoodsRel($goods_rel); + } + } + //处理完,在获取商品 + } + } + + }catch(\Exception $e){ + throw $e; + } + + } + + public function updateDesignerGoods(){ + + try{ + $worksService = new KujialeDesignerGoodsRelService(); + $worksList = $worksService->getLists([]); + if($worksList){ + $picService = new KujialeDesignerGoodsService(); + foreach($worksList as $work){ + $goodsDetail = $this->apiService->getDetail($work['obs_brand_good_id']); + if (!empty($goodsDetail['brandGoodName'])){ + $goodsDetail['goodsId'] = $work['obs_brand_good_id']; + $picService->saveGoods($goodsDetail); + } + //处理完,在获取商品 + } + } + + }catch(\Exception $e){ + throw $e; + } + + } + + /** + * 定时执行获取设计师方案等数据 + */ + public function scheduleUpdateDesigner() + { + $this->updateDesignerWorks(); + $this->updateDesignerWorksPic(); + $this->updateDesignerPicAndGoods(); + $this->updateDesignerGoods(); + return true; + } +} \ No newline at end of file diff --git a/src/KujialeBundle/Services/KujialeDesignerGoodsRelService.php b/src/KujialeBundle/Services/KujialeDesignerGoodsRelService.php new file mode 100644 index 0000000..7290bb4 --- /dev/null +++ b/src/KujialeBundle/Services/KujialeDesignerGoodsRelService.php @@ -0,0 +1,55 @@ +likeRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerGoodsRel::class); + } + + public function saveGoodsRel($params){ + $conn = app('registry')->getConnection('default'); + try{ + $conn->beginTransaction(); + $filter['pic_id'] = $params['picId']; + $filter['obs_brand_good_id'] = $params['obsBrandGoodId']; + + $save['pic_id'] = $params['picId']; + $save['obs_brand_good_id'] = $params['obsBrandGoodId']; + if($this->likeRepository->count($filter)){ + $save['updated'] = time(); + $this->likeRepository->updateOneBy($filter, $save); + }else{ + $save['created'] = time(); + $this->likeRepository->create($save); + } + $conn->commit(); + }catch(\Exception $e){ + $conn->rollback(); + throw $e; + } + + } + + /** + * Dynamically call the shopsservice instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->likeRepository->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/KujialeBundle/Services/KujialeDesignerGoodsService.php b/src/KujialeBundle/Services/KujialeDesignerGoodsService.php new file mode 100644 index 0000000..25bb35c --- /dev/null +++ b/src/KujialeBundle/Services/KujialeDesignerGoodsService.php @@ -0,0 +1,82 @@ +likeRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerGoods::class); + } + + public function saveGoods($params){ + $conn = app('registry')->getConnection('default'); + try{ + $conn->beginTransaction(); + $filter['good_id'] = $params['goodsId']; + + $save['good_id'] = $params['goodsId']; + $save['dimensions'] = $params['dimensions']; + if (!empty($save['description'])){ + $save['description'] = $params['description']; + } + if (!empty($params['brandGoodCode'])){ + $save['brand_good_code'] = $params['brandGoodCode']; + } + $save['brand_good_name'] = $params['brandGoodName']; + if (!empty($params['obsBrandId'])){ + $save['brand_id'] = $params['obsBrandId']; + } + if (!empty($params['brandName'])){ + $save['brand_name'] = $params['brandName']; + } + if (!empty($params['obsSeriesTagId'])){ + $save['series_tag_id'] = $params['obsSeriesTagId']; + } + if (!empty($params['seriesTagName'])){ + $save['series_tag_name'] = $params['seriesTagName']; + } + if (!empty($params['productNumber'])){ + $save['product_number'] = $params['productNumber']; + } + if (!empty($params['customerTexture'])){ + $save['customer_texture'] = $params['customerTexture']; + } + if (!empty($params['buyLink'])){ + $save['buy_link'] = $params['buyLink']; + } + if($this->likeRepository->count($filter)){ + $save['updated'] = time(); + $this->likeRepository->updateOneBy($filter, $save); + }else{ + $save['created'] = time(); + $this->likeRepository->create($save); + } + $conn->commit(); + }catch(\Exception $e){ + $conn->rollback(); + throw $e; + } + + } + + /** + * Dynamically call the shopsservice instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->likeRepository->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/KujialeBundle/Services/KujialeDesignerTagsService.php b/src/KujialeBundle/Services/KujialeDesignerTagsService.php new file mode 100644 index 0000000..fa8efd7 --- /dev/null +++ b/src/KujialeBundle/Services/KujialeDesignerTagsService.php @@ -0,0 +1,115 @@ +tagsRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerTags::class); + } + + /** + * 保存tags内容 + * @param $tagParams + */ + public function saveTags($tagParams){ + $saveParams = []; + + foreach($tagParams as $tag){ + $tmp = []; + $tmp['tag_category_id'] = $tag['tagCategoryId']; + $tmp['tag_category_name'] = $tag['tagCategoryName']; + $tmp['type'] = $tag['type']; + $tmp['is_multiple_selected'] = $tag['isMultipleSelected'] == true ? 1 : 0; + $tmp['is_disabled'] = $tag['isDisabled'] == true ? 1 : 0; + if(isset($tag['tags']) && !empty($tag['tags'])){ + foreach($tag['tags'] as $t){ + $tmp['tag_id'] = $t['id']; + $tmp['tag_name'] = $t['name']; + $saveParams[] = $tmp; + } + } + } + if(!empty($saveParams)){ + try{ + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + + foreach($saveParams as $save){ + $filter['tag_category_id'] = $save['tag_category_id']; + $filter['tag_id'] = $save['tag_id']; + if($this->tagsRepository->count($filter)){ + $save['updated'] = time(); + $this->tagsRepository->updateOneBy($filter,$save); + }else{ + $save['created'] = time(); + $this->tagsRepository->create($save); + } + } + $conn->commit(); + }catch(\Exception $e){ + $conn->rollback(); + throw $e; + } + } + return true; + } + + public function getTagsList($filter){ + $result = $this->tagsRepository->getLists($filter); + if($result){ + return $this->packageTreeData($result); + } + return []; + } + + /** + * 组装树形结构体 + * @param $resultData + * @return array + */ + private function packageTreeData($resultData){ + $newPackageTree = []; + foreach($resultData as $data){ + if(isset($newPackageTree[$data['tag_category_id']]) && !empty($newPackageTree[$data['tag_category_id']])){ + $tags['tag_id'] = $data['tag_id']; + $tags['tag_name'] = $data['tag_name']; + unset($data['tag_id']); + unset($data['tag_name']); + + $newPackageTree[$data['tag_category_id']]['tags'][] = $tags; + }else{ + $tags['tag_id'] = $data['tag_id']; + $tags['tag_name'] = $data['tag_name']; + unset($data['tag_id']); + unset($data['tag_name']); + $newPackageTree[$data['tag_category_id']] = $data; + $newPackageTree[$data['tag_category_id']]['tags'][] = $tags; + } + } + return array_values($newPackageTree); + } + + /** + * Dynamically call the shopsservice instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->tagsRepository->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/KujialeBundle/Services/KujialeDesignerWorksLikeService.php b/src/KujialeBundle/Services/KujialeDesignerWorksLikeService.php new file mode 100644 index 0000000..4d1d09e --- /dev/null +++ b/src/KujialeBundle/Services/KujialeDesignerWorksLikeService.php @@ -0,0 +1,66 @@ +likeRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorksLike::class); + } + + public function saveLike($designId, $planId, $userId, $type){ + + $filter['design_id'] = $designId; + $filter['plan_id'] = $planId; + $filter['user_id'] = $userId; + $like = $this->likeRepository->getInfo($filter); + + try{ + $saveParams = $filter; + if($like && $type == 'like'){ + throw new ResourceException('已经点赞过'); + } + if(!$like && $type == 'like'){ + $saveParams['created'] = time(); + $this->likeRepository->create($saveParams); + //更新对应的设计方案的点赞量 + $conn = app("registry")->getConnection("default"); + + $sql = "UPDATE kujiale_designer_works SET `like_count`=`like_count`+1 WHERE `design_id`='".$designId."' AND `plan_id`='".$planId."'"; + $conn->executeUpdate($sql); + } + if($like && $type == 'unlike'){ + $this->likeRepository->deleteBy($filter); + //更新对应的设计方案的点赞量 + $conn = app("registry")->getConnection("default"); + + $sql = "UPDATE kujiale_designer_works SET `like_count`=`like_count`-1 WHERE `design_id`='".$designId."' AND `plan_id`='".$planId."'"; + $conn->executeUpdate($sql); + } + return true; + }catch(\Exception $e){ + throw new ResourceException('点赞异常'); + } + } + + /** + * Dynamically call the shopsservice instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->likeRepository->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/KujialeBundle/Services/KujialeDesignerWorksPicService.php b/src/KujialeBundle/Services/KujialeDesignerWorksPicService.php new file mode 100644 index 0000000..2ef84b0 --- /dev/null +++ b/src/KujialeBundle/Services/KujialeDesignerWorksPicService.php @@ -0,0 +1,54 @@ +picRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorksPic::class); + } + + public function savePic($params){ + + $saveParams = []; + $saveParams['img'] = $params['img']; + $saveParams['pic_id'] = $params['picId']; + $saveParams['pic_type'] = $params['picType']; + $saveParams['pic_detail_type'] = $params['picDetailType']; + $saveParams['room_name'] = $params['roomName']; + $saveParams['pano_link'] = isset($params['panoLink']) && !empty($params['panoLink']) ? $params['panoLink'] : ''; + $saveParams['design_id'] = $params['design_id']; + $saveParams['plan_id'] = $params['plan_id']; + + $filter['pic_id'] = $params['picId']; + // $filter['design_id'] = $params['design_id']; + // $filter['plan_id'] = $params['plan_id']; + if($this->picRepository->count($filter)){ + $saveParams['updated'] = time(); + return $this->picRepository->updateBy($filter,$saveParams); + }else{ + $saveParams['created'] = time(); + return $this->picRepository->create($saveParams); + } + } + + /** + * Dynamically call the shopsservice instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->picRepository->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/KujialeBundle/Services/KujialeDesignerWorksService.php b/src/KujialeBundle/Services/KujialeDesignerWorksService.php new file mode 100644 index 0000000..d024f2c --- /dev/null +++ b/src/KujialeBundle/Services/KujialeDesignerWorksService.php @@ -0,0 +1,484 @@ +designerRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorks::class); + $this->levelRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorksLevel::class); + $this->relTagRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorksRelTags::class); + $this->tagRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerTags::class); + $this->picRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorksPic::class); + $this->likeRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorksLike::class); + $this->relCitiesRepository = app('registry')->getManager('default')->getRepository(\KujialeBundle\Entities\KujialeDesignerWorksRelCities::class); + $this->worksItemRelRepository = app('registry')->getManager('default')->getRepository(KujialeDesignerWorksItemRel::class); + } + + /** + * 保存设计师作品内容 + * @param $tagParams + */ + public function saveDesignerWorks($params){ + + $designerWorks = []; + $designerTags = []; + $designerLevel = []; + $designerCities = []; + + foreach($params as $param){ + $tmp = []; + $tmp['design_name'] = $param['designName']; + $tmp['cover_pic'] = $param['coverPic']; + $tmp['is_origin'] = $param['isOrigin']; + $tmp['is_excellent'] = $param['isExcellent']; + $tmp['is_real_excellent'] = $param['isRealExcellent']; + $tmp['is_top'] = $param['isTop']; + $tmp['design_id'] = $param['designId']; + $tmp['plan_id'] = $param['planId']; + $tmp['comm_name'] = $param['commName']; + $tmp['city'] = $param['city']; + $tmp['name'] = $param['name']; + $tmp['tag_id'] = isset($param['tagId']) && !empty($param['tagId']) ? $param['tagId'] : ''; + $tmp['design_pano_url'] = isset($param['designPanoUrl']) && !empty($param['designPanoUrl']) ? $param['designPanoUrl'] : ''; + $tmp['user_avatar'] = $param['userAvatar'] ?? ''; + $tmp['email'] = $param['email'] ?? ''; + $tmp['user_name'] = $param['userName']; + $tmp['user_id'] = $param['obsUserId']; + $tmp['organization_id'] = $param['obsOrganizationId'] ?? ''; + $tmp['ku_created'] = $param['ku_created']; + $designerWorks[] = $tmp; + + // 处理城市ID列表 + if(isset($param['city_id_list']) && !empty($param['city_id_list']) && is_array($param['city_id_list'])){ + foreach($param['city_id_list'] as $cityId){ + $cityTmp = []; + $cityTmp['design_id'] = $tmp['design_id']; + $cityTmp['plan_id'] = $tmp['plan_id']; + $cityTmp['city_id'] = $cityId; + $designerCities[] = $cityTmp; + } + } + + // 是否有楼层信息 + if(isset($param['level']) && !empty($param['level'])){ + foreach($param['level'] as $t){ + $levelTmp = []; + $levelTmp['design_id'] = $tmp['design_id']; + $levelTmp['plan_id'] = $tmp['plan_id']; + $levelTmp['src_area'] = $t['srcArea'] ?? ''; + $levelTmp['area'] = $t['area'] ?? ''; + $levelTmp['real_area'] = $t['realArea'] ?? ''; + $levelTmp['spec_name'] = $t['specName']; + $levelTmp['plan_pic'] = $t['planPic'] ?? ''; + $levelTmp['level'] = $t['level']; + $designerLevel[] = $levelTmp; + } + } + + // 是否有标签信息 + if(isset($param['tags']) && !empty($param['tags'])){ + $tagsList = $this->tagRepository->lists(['tag_id' => $param['tags']]); + if($tagsList['total_count'] == 0){ + throw new \Exception('标签不存在'); + } + $newTagsList = []; + foreach($tagsList['list'] as $tag){ + $newTagsList[$tag['tag_id']] = $tag; + } + foreach($param['tags'] as $t){ + $tagsTmp = []; + $tagsTmp['tag_category_id'] = $newTagsList[$t]['tag_category_id']; + $tagsTmp['tag_category_name'] = $newTagsList[$t]['tag_category_name']; + $tagsTmp['tag_id'] = $t; + $tagsTmp['tag_name'] = $newTagsList[$t]['tag_name']; + $tagsTmp['design_id'] = $tmp['design_id']; + $tagsTmp['plan_id'] = $tmp['plan_id']; + $designerTags[] = $tagsTmp; + } + } + } + if(!empty($designerWorks)){ + $conn = app('registry')->getConnection('default'); + try{ + $conn->beginTransaction(); + foreach($designerWorks as $save){ + $filter['design_id'] = $save['design_id']; + $filter['plan_id'] = $save['plan_id']; + if($this->designerRepository->count($filter)){ + $save['updated'] = time(); + app('log')->info('方案重复的数据: '.json_encode($filter)); + $this->designerRepository->updateOneBy($filter,$save); + }else{ + $save['created'] = time(); + $this->designerRepository->create($save); + } + } + // 处理楼层数据 + foreach($designerLevel as $save){ + $filter['design_id'] = $save['design_id']; + $filter['plan_id'] = $save['plan_id']; + $filter['plan_id'] = $save['plan_id']; + if($this->levelRepository->count($filter)){ + $save['updated'] = time(); + $this->levelRepository->updateOneBy($filter,$save); + }else{ + $save['created'] = time(); + $this->levelRepository->create($save); + } + } + + //标签处理 + foreach($designerTags as $save){ + $filter['design_id'] = $save['design_id']; + $filter['plan_id'] = $save['plan_id']; + $filter['tag_category_id'] = $save['tag_category_id']; + $filter['tag_id'] = $save['tag_id']; + if($this->relTagRepository->count($filter)){ + $save['updated'] = time(); + $this->relTagRepository->updateOneBy($filter,$save); + }else{ + $save['created'] = time(); + $this->relTagRepository->create($save); + } + } + + // 城市关联处理 + // 先删除该方案和户型的所有城市关联记录 + foreach($designerWorks as $work){ + $this->relCitiesRepository->deleteByDesignAndPlan($work['design_id'], $work['plan_id']); + } + // 然后插入新的城市关联记录 + foreach($designerCities as $save){ + $save['created'] = time(); + $this->relCitiesRepository->create($save); + } + + $conn->commit(); + }catch(\Exception $e){ + $conn->rollback(); + throw $e; + } + } + return true; + } + + /** + * 获取设计师方案列表 + * @param $filter + * @param int $page + * @param int $pageSize + * @return mixed + */ + public function getDesignerWorksList($filter,$page = 1, $pageSize = 20){ + + $newFilter = []; + $sort = $filter['sort'] ?? ''; + unset($filter['sort']); + + $userId = null; + if(isset($filter['user_id']) && !empty($filter['user_id'])){ + $userId = $filter['user_id']; + unset($filter['user_id']); + } + + $orderBy = [ + // 'ku_created' => 'desc' + ]; + if($sort === 'hot') + { + $orderBy = ['view_count' => 'desc']; + } + if($sort === 'latest'){ + $orderBy = ['ku_created' => 'desc']; + } + if(isset($filter['new']) && $filter['new'] != ''){ + $orderBy['ku_created'] = $filter['new'] == 0 ? 'asc' : 'desc'; + unset($filter['new']); + } + if(isset($filter['viewcount']) && $filter['viewcount'] != ''){ + $orderBy['view_count'] = $filter['viewcount'] == 0 ? 'asc' : 'desc'; + unset($filter['viewcount']); + } + if(isset($filter['likecount']) && $filter['likecount'] != ''){ + $orderBy['like_count'] = $filter['likecount'] == 0 ? 'asc' : 'desc'; + unset($filter['likecount']); + } + + // 如果是关键字搜索 支持户型、产品、风格 + if(isset($filter['keyword']) && !empty($filter['keyword'])){ + $newFilter['design_name|contains'] = $filter['keyword']; + // 查询户型 + // $planList = $this->levelRepository->lists(['spec_name|contains' => $filter['keyword']]); + // $designIds = array_column($planList,'design_id'); + + // if(!empty($designIds)){ + // $newFilter['design_id'] = $designIds; + // }else{ + // $newFilter['design_name|contains'] = $filter['keyword']; + // } + } + + // 如果存在标签搜索 + if(isset($filter['tags']) && !empty($filter['tags'])){ + $tagFilter = []; + $conn = app('registry')->getConnection('default'); + $designerIds = []; + foreach($filter['tags'] as $k=>$tag){ + // $tagFilter['tag_category_id'][] = $tag['tag_category_id']; + // $tagFilter['tag_id'][] = $tag['tag_id']; + $qb = $conn->createQueryBuilder(); + $qb->select('design_id') + ->from('`kujiale_designer_works_rel_tags`') + ->where($qb->expr()->eq('tag_category_id', $qb->expr()->literal($tag['tag_category_id']))) + ->andWhere($qb->expr()->eq('tag_id', $qb->expr()->literal($tag['tag_id']))); + $tagsList = $qb->execute()->fetchAll(); + foreach($tagsList as $tag1){ + $designerIds[$k][] = $tag1['design_id']; + } + } + $newFilter['design_id'] = []; + foreach ($designerIds as $k=>$ids){ + if ($k==0){ + $newFilter['design_id'] = $ids; + }else{ + $newFilter['design_id'] = array_intersect($ids, $newFilter['design_id']); + } + } + } + if (isset($filter['tags']) && !empty($filter['tags']) && empty($newFilter['design_id'])){ + $newFilter['design_id'] = ''; + } + if(!empty($filter['cityIds'])){ + $newFilter['city|contains'] = $filter['cityIds']; + } + // 查询产品 + $result = $this->designerRepository->lists($newFilter,$page,$pageSize,$orderBy); + if(empty($result['list'])){ + return $result; + } + $newLikeList = []; + if(!is_null($userId)){ + // 获取用户对应的点赞记录 + unset($filter); + $filter['user_id'] = $userId; + $likeList = $this->likeRepository->lists($filter); + if($likeList['total_count'] > 0){ + foreach($likeList['list'] as $like){ + $newLikeList[$userId.'_'.$like['design_id'].'_'.$like['plan_id']] = true; + } + } + } + foreach($result['list'] as &$res){ + $res['is_like'] = false; + if(!empty($userId) && isset($newLikeList[$userId.'_'.$res['design_id'].'_'.$res['plan_id']]) && !empty($newLikeList[$userId.'_'.$res['design_id'].'_'.$res['plan_id']])){ + $res['is_like'] = true; + } + } + + //获取标签 + $designIds = array_column($result['list'], 'design_id'); + $tagList = $this->relTagRepository->lists(['design_id' => $designIds]); + $newTagList = []; + if(!empty($tagList['list'])){ + foreach($tagList['list'] as $tag){ + $newTagList[$tag['design_id']][] = $tag; + } + } + foreach($result['list'] as &$resPassBy){ + $resPassBy['taginfo'] = $newTagList[$resPassBy['design_id']] ?? []; + } + return $result; + } + + /** + * 获取方案详情 + * @param $filter + */ + public function getDesignerWorksDetail($filter){ + $returnValue = [ + 'basicInfo' => [], + 'levelinfo' => [], + 'picinfo' => [] + ]; + $info = $this->designerRepository->getInfo($filter); + if($info){ + + $returnValue['basicInfo'] = $info; + // 查询楼层信息 + $levelInfo = $this->levelRepository->lists($filter); + if($levelInfo['total_count'] > 0){ + $returnValue['levelinfo'] = $levelInfo['list']; + } + //查询全景图信息 + $picList = $this->picRepository->lists($filter); + if($picList['total_count'] > 0){ + $returnValue['picinfo'] = $picList['list']; + + $returnValue['web_view_url'] = false; + + foreach ($picList['list'] as $key => $v) { + if (!empty($v['pano_link']) && $v['pic_type'] && !$returnValue['web_view_url'] ){ + $kujiale_pano53 = "pano53.p.kujiale.com"; + $kujiale_www = "www.kujiale.com"; + $pano_link = str_replace($kujiale_www, $kujiale_pano53, $v['pano_link']); + $returnValue['picinfo'][0]['pano_link'] = $pano_link; + $returnValue['basicInfo']['design_pano_url'] = $pano_link; + + // $returnValue['web_view_url'] = config('kujiale.webViewUrl').'?pic_id='.$v['pic_id']; + } + + } + } + + $returnValue['basicInfo']['design_mesh_url'] = ""; + if(!empty($returnValue['basicInfo']['design_pano_url'])){ + $returnValue['basicInfo']['design_mesh_url'] = "https://pano572.p.kujiale.com/design/".$returnValue['basicInfo']['design_id']."/show"; + } + + $tagList = $this->relTagRepository->lists(['design_id' => $info['design_id']]); + $returnValue['taginfo'] = []; + if($tagList['total_count'] > 0){ + $returnValue['taginfo'] = $tagList['list']; + } + } + //更新viewcount + if($info && !empty($filter)){ + try { + $this->designerRepository->countView($filter); + } catch (\Exception $e) { + // 更新失败不影响主流程,记录日志即可 + app('log')->error('更新view_count失败: ' . $e->getMessage()); + } + } + //更新viewcount end + + return $returnValue; + } + + public function getDesignerWorksDetailByApi(array $params){ + $roomList = (new ApiService())->getDesignerWorksPicList($params['design_id']); + return ['roomList'=>$roomList['result']]; + } + + public function updateViewCount($designId, $plan_id){ + + $filter['design_id'] = $designId; + $filter['plan_id'] = $plan_id; + + return $this->designerRepository->countView($filter); + } + + /** + * 根据商品ID获取关联的设计作品列表 + * 只返回 design_id, design_name, cover_pic 三个字段 + * + * @param int $itemId 商品ID + * @return array 设计作品列表 + */ + public function getDesignerWorksByItemId($itemId) + { + if (empty($itemId)) { + return []; + } + + // 查询商品关联的设计作品绑定关系 + $boundRels = $this->worksItemRelRepository->getLists(['item_id' => $itemId]); + + if (empty($boundRels)) { + return []; + } + + // 获取所有关联的 design_id + $designIds = array_column($boundRels, 'design_id'); + if (empty($designIds)) { + return []; + } + + // 查询设计作品信息 + $designerWorks = $this->designerRepository->getLists(['design_id' => $designIds]); + + // 只返回需要的字段 + $result = []; + foreach ($designerWorks as $work) { + $result[] = [ + 'design_id' => $work['design_id'], + 'design_name' => $work['design_name'], + 'cover_pic' => $work['cover_pic'], + 'plan_id' => $work['plan_id'], + ]; + } + + return $result; + } + + /** + * Dynamically call the shopsservice instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->designerRepository->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/KujialeBundle/Services/api/ApiService.php b/src/KujialeBundle/Services/api/ApiService.php new file mode 100644 index 0000000..e0c1003 --- /dev/null +++ b/src/KujialeBundle/Services/api/ApiService.php @@ -0,0 +1,266 @@ +getData(['index'=>$index],$apiUrl,'get'); + } + + /** + * 获取商品标签列表 + * @return bool|mixed + */ + public function getTag() + { + $apiUrl = config('kujiale.apiUrl.tag'); + return $this->getData([],$apiUrl,'get'); + } + + /** + * 商品搜索 + * @return bool|mixed + */ + public function search($params) + { + $apiUrl = config('kujiale.apiUrl.search'); + return $this->getData($params,$apiUrl,'post'); + } + + /** + * 获取品牌 + * @return bool|mixed + */ + public function getBrand() + { + $apiUrl = config('kujiale.apiUrl.brand'); + return $this->getData([],$apiUrl,'get'); + } + + /** + * 获取商品详情 + * @param $obsbgid + * @return bool|mixed + */ + public function getDetail($obsbgid) + { + $apiUrl = config('kujiale.apiUrl.detail'); + return $this->getData(['obsbgid'=>$obsbgid],$apiUrl,'get'); + } + + /** + * 获取设计师方案作品 + */ + public function getDesignerWorks($start, $num){ + $apiUrl = config('kujiale.apiUrl.designer_works'); + // $tmp = $this->getData(['page' =>$start, 'pageSize' => $num],$apiUrl,'post'); + return $this->getData(['page' => $start, 'pageSize' => $num],$apiUrl,'get'); + // return $this->getData($params,$apiUrl,'post'); + } + + /** + * 获取设计师方案作品详情 + * @param $designId + * @return bool|mixed + */ + public function getDesignerWorksDetail($designId){ + $apiUrl = config('kujiale.apiUrl.designer_works_detail'); + $apiUrl = str_replace('{designId}',$designId,$apiUrl); + return $this->getData(['designId' => $designId],$apiUrl,'get'); + } + + /** + * 获取指定渲染图所在空间商品id + * @param $designId + * @return bool|mixed + */ + public function getDesignerWorksRoomBrandGoods($picId){ + $apiUrl = config('kujiale.apiUrl.designer_room_brand_goods'); + $apiUrl = str_replace('{picId}',$picId,$apiUrl); + return $this->getData([],$apiUrl,'get'); + } + + /** + * 获取设计师方案作品绑定的标签类型 + * @param $designId + * @return bool|mixed + */ + public function getDesignerWorksRelTag($designId){ + $apiUrl = config('kujiale.apiUrl.designer_works_tag'); + return $this->getData(['design_id' => $designId , 'appuid' => config('kujiale.appUid')],$apiUrl,'get'); + } + + public function getDesignerWorksPicList($designId, $start = 0, $num = 50){ + $apiUrl = config('kujiale.apiUrl.designer_works_pic'); + return $this->getData(['design_id' => $designId , 'start' => $start, 'num' => $num],$apiUrl,'get'); + } + + /** + * 获取方案标签列表 + * @return bool|mixed + */ + public function getDesignerTags(){ + $apiUrl = config('kujiale.apiUrl.designer_tags_list'); + return $this->getData(['is_disabled'=>false],$apiUrl,'get'); + } + + /** + * 绑定设计师邮箱 + * @param $params + * @return bool|mixed + */ + public function register($params) + { + try{ + $bodyParams = array_merge($params, [ + 'type' => 0, + 'maxChildrenCount' => 0, + 'defaultPassword' => '123456', + 'creator' => config('kujiale.appUid'), + ]); + $apiUrl = config('kujiale.apiUrl.register_user'); + $this->setApiUrl($apiUrl); + $this->setApiParams($bodyParams); + $this->setAppUid($bodyParams['email']); + $res = $this->post_new([],true); + if ($res['c'] == 0 || ($res['c'] == -1 && $res['m'] == 'appuid has register or bind to a user')) + { + //绑定成功或已经绑定都返回成功 + return true; + } + return false; + }catch (\Exception $e) + { + app('log')->info('获取接口数据失败'.$e->getMessage()); + return false; + } + } + /** + * 获取一次性token + * @param $email + * @return bool|mixed + */ + + public function accessToken($appUid, $dest) + { + try{ + $bodyParams = [ + ]; + $apiUrl = config('kujiale.apiUrl.access_token'); + $this->setApiUrl($apiUrl); + $this->setApiParams($bodyParams); + $this->setAppUid($appUid); + $res = $this->post_new(['dest' => $dest], true); + if ($res['c'] == 0) + { + if (isset($res['d'])) { + return $res['d']; + } + } + return false; + }catch (\Exception $e) + { + app('log')->info('获取接口数据失败'.$e->getMessage()); + return false; + } + } + + /** + * 查找设计师账号-通过邮箱 + * @param $email + * @return bool|mixed + */ + public function getAccountByEmail($email) + { + try{ + $bodyParams = [ + 'email' => $email, + 'start' => 0, + 'num' => 1000, + ]; + $apiUrl = config('kujiale.apiUrl.search_account'); + $this->setApiUrl($apiUrl); + $this->setApiParams($bodyParams); + $res = $this->post_new([],false); + if ($res['c'] == 0) + { + if (isset($res['d'])) { + return $res['d']; + } + } + return false; + }catch (\Exception $e) + { + app('log')->info('获取接口数据失败'.$e->getMessage()); + return false; + } + } + + private function getData($params,$url,$method) + { + try{ + $this->setApiUrl($url); + $this->setApiParams($params); + $appuid = false; + if(isset($params['appuid']) && !empty($params['appuid'])){ + $appuid = true; + } + if ($method == 'get') { + $res = $this->get($appuid); + }else{ + $res = $this->post($appuid); + } + if ($res) { + return $res; + } + return false; + }catch (\Exception $e) + { + app('log')->info('获取接口数据失败'.$e->getMessage()); + return false; + } + } +} \ No newline at end of file diff --git a/src/KujialeBundle/Traits/AbstractApiTraits.php b/src/KujialeBundle/Traits/AbstractApiTraits.php new file mode 100644 index 0000000..a4c34a7 --- /dev/null +++ b/src/KujialeBundle/Traits/AbstractApiTraits.php @@ -0,0 +1,227 @@ +setAppKey(); + $this->setAppSecret(); + $this->setAppUid(); + $this->client = new Client(); + } + + public function setApiParams($params) + { + $this->apiParams = $params; + } + + public function getApiParams() + { + return $this->apiParams; + } + + public function setAppKey() + { + $config = $this->getKujialeConfig(); + $this->appKey = $config['appKey'] ?? ''; + } + + public function getAppKey() + { + return $this->appKey; + } + + public function setAppSecret() + { + $config = $this->getKujialeConfig(); + $this->appSecret = $config['appSecret'] ?? ''; + } + + public function getAppSecret() + { + return $this->appSecret; + } + + public function setAppUid($appUid='') + { + if ($appUid != '') { + $this->appUid = $appUid; + } else { + $this->appUid = config('kujiale.appUid'); + } + } + + public function getAppUid() + { + return $this->appUid; + } + + public function setApiUrl($params) + { + $this->apiUrl= $params; + } + + public function getApiUrl() + { + return $this->apiUrl; + } + + /**获取签名 + * @param $appUid + * @return string + * @throws \ExceptioTraitsn + */ + private function genSign($appUid) + { + if (empty($this->getAppKey()) || empty($this->getAppSecret())) + { + throw new \Exception('未配置相应的appKey或appSecret'); + } + if ($appUid) + { + if (empty($this->appUid)) + { + throw new \Exception('未配置相应的appKey或appSecret'); + } + return md5($this->getAppSecret().$this->getAppKey().$this->getAppUid().(time()*1000)); + } + + return md5($this->getAppSecret().$this->getAppKey().time()*1000); + } + + /**post方法获取接口数据 + * @param bool $appUid + * @return bool + * @throws \Exception + */ + public function post_new($postParams, $appUid = false) + { + if (!$this->canCallApi($appUid)) { + return []; + } + $postParams = array_merge($postParams, [ + 'appkey' => $this->getAppKey(), + 'timestamp' => time()*1000, + ]); + $bodyParams = $this->getApiParams(); + if ($appUid){ + $postParams['appuid'] = $this->getAppUid(); + $postParams['sign'] = $this->genSign(true); + }else{ + $postParams['sign'] = $this->genSign(false); + } + $url = $this->getApiUrl().'?'.http_build_query($postParams); + //app('log')->info('post请求'.$url.'的参数是'.var_export($bodyParams,1)); + $response = $this->client->request('POST',$url,['headers' => ['Content-Type'=>'application/json;charset=utf-8'],'json'=>$bodyParams]); + $res = json_decode($response->getBody(),1); + //app('log')->info('post请求'.$url.'的返回结果是'.var_export($res,1)); + return $res; + } + + /**post方法获取接口数据 + * @param bool $appUid + * @return bool + * @throws \Exception + */ + public function post($appUid = false) + { + if (!$this->canCallApi($appUid)) { + return false; + } + $postParams = [ + 'appkey' => $this->getAppKey(), + 'timestamp' => time()*1000, + ]; + if ($appUid){ + $postParams['appuid'] = $this->getAppUid(); + $postParams['sign'] = $this->genSign(true); + }else{ + $postParams['sign'] = $this->genSign(false); + } + $url = $this->getApiUrl().'?'.http_build_query($postParams); + //app('log')->info('post请求'.$url.'的参数是'.var_export($this->getApiParams(),1)); + $response = $this->client->request('POST',$url,['headers' => ['Content-Type'=>'application/json;charset=utf-8'],'json'=>$this->getApiParams()]); + $res = json_decode($response->getBody(),1); + //app('log')->info('post请求'.$url.'的返回结果是'.var_export($res,1)); + if ($res['c'] == 0) + { + return $res['d']; + } + return false; + } + + /** + * get方法获取接口数据 + * @param bool $appUid + * @return mixed + * @throws \Exception + */ + public function get($appUid = false) + { + if (!$this->canCallApi($appUid)) { + return false; + } + $postParams = [ + 'appkey' => $this->getAppKey(), + 'timestamp' => time()*1000, + ]; + if($appUid) { + $postParams['appuid'] = $this->getAppUid(); + $postParams['sign'] = $this->genSign(true); + }else{ + $postParams['sign'] = $this->genSign(false); + } + $fromParams = array_merge($postParams,$this->getApiParams()); + $url = $this->getApiUrl().'?'.http_build_query($fromParams); + //app('log')->info('get请求'.$url.'的参数是'.var_export($fromParams,1)); + $response = $this->client->request('GET',$url,['headers' => ['Content-Type'=>'text/plain;charset=utf-8']]); + $res = json_decode($response->getBody(),1); + //app('log')->info('get请求'.$url.'的返回结果是'.var_export($res,1)); + if ($res['c'] == 0) + { + return $res['d']; + } + return false; + } + + private function canCallApi(bool $requireAppUid = false): bool + { + if (empty($this->getAppKey()) || empty($this->getAppSecret())) { + return false; + } + if ($requireAppUid && empty($this->getAppUid())) { + return false; + } + return true; + } + + private function getKujialeConfig(): array + { + $redis = app('redis')->connection('default'); + $keys = $redis->keys('kujiale:config:*'); + if (empty($keys)) { + return []; + } + $raw = $redis->get($keys[0]); + return $raw ? json_decode($raw, true) : []; + } +} + + + diff --git a/src/MembersBundle/Entities/MemberSegmentRule.php b/src/MembersBundle/Entities/MemberSegmentRule.php new file mode 100644 index 0000000..4406d78 --- /dev/null +++ b/src/MembersBundle/Entities/MemberSegmentRule.php @@ -0,0 +1,306 @@ +rule_id; + } + + /** + * Set companyId. + * + * @param int $companyId + * + * @return MemberSegmentRule + */ + public function setCompanyId($companyId) + { + $this->company_id = $companyId; + + return $this; + } + + /** + * Get companyId. + * + * @return int + */ + public function getCompanyId() + { + return $this->company_id; + } + + /** + * Set distributorId. + * + * @param int $distributorId + * + * @return MemberSegmentRule + */ + public function setDistributorId($distributorId) + { + $this->distributor_id = $distributorId; + + return $this; + } + + /** + * Get distributorId. + * + * @return int + */ + public function getDistributorId() + { + return $this->distributor_id; + } + + /** + * Set ruleName. + * + * @param string $ruleName + * + * @return MemberSegmentRule + */ + public function setRuleName($ruleName) + { + $this->rule_name = $ruleName; + + return $this; + } + + /** + * Get ruleName. + * + * @return string + */ + public function getRuleName() + { + return $this->rule_name; + } + + /** + * Set description. + * + * @param string|null $description + * + * @return MemberSegmentRule + */ + public function setDescription($description = null) + { + $this->description = $description; + + return $this; + } + + /** + * Get description. + * + * @return string|null + */ + public function getDescription() + { + return $this->description; + } + + /** + * Set ruleConfig. + * + * @param string|array $ruleConfig + * + * @return MemberSegmentRule + */ + public function setRuleConfig($ruleConfig) + { + if (is_array($ruleConfig)) { + $this->rule_config = json_encode($ruleConfig, JSON_UNESCAPED_UNICODE); + } else { + $this->rule_config = $ruleConfig; + } + + return $this; + } + + /** + * Get ruleConfig. + * + * @return array + */ + public function getRuleConfig() + { + return json_decode($this->rule_config, true) ?: []; + } + + /** + * Set tagIds. + * + * @param array|string|null $tagIds + * + * @return MemberSegmentRule + */ + public function setTagIds($tagIds) + { + if (is_array($tagIds)) { + $this->tag_ids = json_encode($tagIds, JSON_UNESCAPED_UNICODE); + } else { + $this->tag_ids = $tagIds; + } + + return $this; + } + + /** + * Get tagIds. + * + * @return array + */ + public function getTagIds() + { + if (empty($this->tag_ids)) { + return []; + } + return json_decode($this->tag_ids, true) ?: []; + } + + /** + * Set status. + * + * @param int $status + * + * @return MemberSegmentRule + */ + public function setStatus($status) + { + $this->status = $status; + + return $this; + } + + /** + * Get status. + * + * @return int + */ + public function getStatus() + { + return $this->status; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Get updated. + * + * @return int|null + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/MembersBundle/Entities/MemberTagGroup.php b/src/MembersBundle/Entities/MemberTagGroup.php new file mode 100644 index 0000000..3fc7582 --- /dev/null +++ b/src/MembersBundle/Entities/MemberTagGroup.php @@ -0,0 +1,262 @@ +group_id; + } + + /** + * Set companyId. + * + * @param int $companyId + * + * @return MemberTagGroup + */ + public function setCompanyId($companyId) + { + $this->company_id = $companyId; + + return $this; + } + + /** + * Get companyId. + * + * @return int + */ + public function getCompanyId() + { + return $this->company_id; + } + + /** + * Set groupName. + * + * @param string $groupName + * + * @return MemberTagGroup + */ + public function setGroupName($groupName) + { + $this->group_name = $groupName; + + return $this; + } + + /** + * Get groupName. + * + * @return string + */ + public function getGroupName() + { + return $this->group_name; + } + + /** + * Set description. + * + * @param string|null $description + * + * @return MemberTagGroup + */ + public function setDescription($description = null) + { + $this->description = $description; + + return $this; + } + + /** + * Get description. + * + * @return string|null + */ + public function getDescription() + { + return $this->description; + } + + /** + * Set distributorId. + * + * @param int $distributorId + * + * @return MemberTagGroup + */ + public function setDistributorId($distributorId) + { + $this->distributor_id = $distributorId; + + return $this; + } + + /** + * Get distributorId. + * + * @return int + */ + public function getDistributorId() + { + return $this->distributor_id; + } + + /** + * Set wechatGroupId. + * + * @param string|null $wechatGroupId + * + * @return MemberTagGroup + */ + public function setWechatGroupId($wechatGroupId = null) + { + $this->wechat_group_id = $wechatGroupId; + + return $this; + } + + /** + * Get wechatGroupId. + * + * @return string|null + */ + public function getWechatGroupId() + { + return $this->wechat_group_id; + } + + /** + * Set created. + * + * @param int $created + * + * @return MemberTagGroup + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated. + * + * @param int $updated + * + * @return MemberTagGroup + */ + public function setUpdated($updated) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated. + * + * @return int + */ + public function getUpdated() + { + return $this->updated; + } +} diff --git a/src/MembersBundle/Entities/MemberTagGroupRel.php b/src/MembersBundle/Entities/MemberTagGroupRel.php new file mode 100644 index 0000000..3672d9c --- /dev/null +++ b/src/MembersBundle/Entities/MemberTagGroupRel.php @@ -0,0 +1,200 @@ +id; + } + + /** + * Set groupId. + * + * @param int $groupId + * + * @return MemberTagGroupRel + */ + public function setGroupId($groupId) + { + $this->group_id = $groupId; + + return $this; + } + + /** + * Get groupId. + * + * @return int + */ + public function getGroupId() + { + return $this->group_id; + } + + /** + * Set tagId. + * + * @param int $tagId + * + * @return MemberTagGroupRel + */ + public function setTagId($tagId) + { + $this->tag_id = $tagId; + + return $this; + } + + /** + * Get tagId. + * + * @return int + */ + public function getTagId() + { + return $this->tag_id; + } + + /** + * Set companyId. + * + * @param int $companyId + * + * @return MemberTagGroupRel + */ + public function setCompanyId($companyId) + { + $this->company_id = $companyId; + + return $this; + } + + /** + * Get companyId. + * + * @return int + */ + public function getCompanyId() + { + return $this->company_id; + } + + /** + * Set distributorId. + * + * @param int $distributorId + * + * @return MemberTagGroupRel + */ + public function setDistributorId($distributorId) + { + $this->distributor_id = $distributorId; + + return $this; + } + + /** + * Get distributorId. + * + * @return int + */ + public function getDistributorId() + { + return $this->distributor_id; + } + + /** + * Set created. + * + * @param int $created + * + * @return MemberTagGroupRel + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created. + * + * @return int + */ + public function getCreated() + { + return $this->created; + } +} diff --git a/src/MembersBundle/Entities/MemberTags.php b/src/MembersBundle/Entities/MemberTags.php index 26a39d7..6bea1f3 100644 --- a/src/MembersBundle/Entities/MemberTags.php +++ b/src/MembersBundle/Entities/MemberTags.php @@ -141,6 +141,13 @@ class MemberTags */ private $source = 'self'; + /** + * @var string|null + * + * @ORM\Column(name="wechat_tag_id", type="string", length=100, nullable=true, options={"comment"="企业微信标签ID"}) + */ + private $wechat_tag_id; + /** * Get tagId. * @@ -486,4 +493,28 @@ class MemberTags { return $this->source; } + + /** + * Set wechatTagId. + * + * @param string|null $wechatTagId + * + * @return MemberTags + */ + public function setWechatTagId($wechatTagId = null) + { + $this->wechat_tag_id = $wechatTagId; + + return $this; + } + + /** + * Get wechatTagId. + * + * @return string|null + */ + public function getWechatTagId() + { + return $this->wechat_tag_id; + } } diff --git a/src/MembersBundle/Entities/Members.php b/src/MembersBundle/Entities/Members.php index e05f2e2..efa429b 100644 --- a/src/MembersBundle/Entities/Members.php +++ b/src/MembersBundle/Entities/Members.php @@ -228,6 +228,48 @@ class Members */ private $third_data; + /** + * @var integer + * + * @ORM\Column(name="reg_distributor", type="integer", nullable=true, options={"comment":"注册时的分销商ID", "default": 0}) + */ + private $reg_distributor = 0; + + /** + * @var string + * + * @ORM\Column(name="reg_salesperson", type="string", length=100, nullable=true, options={"comment":"注册时的导购ID"}) + */ + private $reg_salesperson; + + /** + * @var integer + * + * @ORM\Column(name="op_distributor", type="integer", nullable=true, options={"comment":"作为分配的店铺ID", "default": 0}) + */ + private $op_distributor = 0; + + /** + * @var string + * + * @ORM\Column(name="fp_salesperson", type="string", length=100, nullable=true, options={"comment":"分配的导购员工编号(employee_number/work_userid)"}) + */ + private $fp_salesperson; + + /** + * @var boolean + * + * @ORM\Column(name="has_fp", type="boolean", options={"comment":"是否有分配导购", "default": 0}) + */ + private $has_fp = 0; + + /** + * @var boolean + * + * @ORM\Column(name="is_become_friend", type="boolean", options={"comment":"是否已加为好友。0:否;1:是", "default": 0}) + */ + private $is_become_friend = 0; + /** * Get userId * @@ -815,6 +857,78 @@ class Members return $this->third_data; } + /** + * Set regDistributor. + * + * @param integer $regDistributor + * + * @return Members + */ + public function setRegDistributor($regDistributor = 0) + { + $this->reg_distributor = (int)$regDistributor; + + return $this; + } + + /** + * Get regDistributor. + * + * @return integer + */ + public function getRegDistributor() + { + return $this->reg_distributor; + } + + /** + * Set regSalesperson. + * + * @param string|null $regSalesperson + * + * @return Members + */ + public function setRegSalesperson($regSalesperson = null) + { + $this->reg_salesperson = $regSalesperson; + + return $this; + } + + /** + * Get regSalesperson. + * + * @return string|null + */ + public function getRegSalesperson() + { + return $this->reg_salesperson; + } + + /** + * Set opDistributor. + * + * @param integer $opDistributor + * + * @return Members + */ + public function setOpDistributor($opDistributor = 0) + { + $this->op_distributor = (int)$opDistributor; + + return $this; + } + + /** + * Get opDistributor. + * + * @return integer + */ + public function getOpDistributor() + { + return $this->op_distributor; + } + /** * Set regionMobile. * @@ -862,4 +976,76 @@ class Members { return $this->mobile_country_code; } + + /** + * Set fpSalesperson. + * + * @param string|null $fpSalesperson + * + * @return Members + */ + public function setFpSalesperson($fpSalesperson = null) + { + $this->fp_salesperson = $fpSalesperson; + + return $this; + } + + /** + * Get fpSalesperson. + * + * @return string|null + */ + public function getFpSalesperson() + { + return $this->fp_salesperson; + } + + /** + * Set hasFp. + * + * @param boolean $hasFp + * + * @return Members + */ + public function setHasFp($hasFp = 0) + { + $this->has_fp = (bool)$hasFp; + + return $this; + } + + /** + * Get hasFp. + * + * @return boolean + */ + public function getHasFp() + { + return $this->has_fp; + } + + /** + * Set isBecomeFriend. + * + * @param boolean $isBecomeFriend + * + * @return Members + */ + public function setIsBecomeFriend($isBecomeFriend = 0) + { + $this->is_become_friend = (bool)$isBecomeFriend; + + return $this; + } + + /** + * Get isBecomeFriend. + * + * @return boolean + */ + public function getIsBecomeFriend() + { + return $this->is_become_friend; + } } diff --git a/src/MembersBundle/Http/Api/V1/Action/ExportData.php b/src/MembersBundle/Http/Api/V1/Action/ExportData.php index 944d4b3..c369eab 100644 --- a/src/MembersBundle/Http/Api/V1/Action/ExportData.php +++ b/src/MembersBundle/Http/Api/V1/Action/ExportData.php @@ -23,6 +23,7 @@ use Dingo\Api\Exception\ResourceException; use App\Http\Controllers\Controller as Controller; use MembersBundle\Services\MemberService; +use MembersBundle\Services\MemberTagsService; use MembersBundle\Traits\MemberSearchFilter; use EspierBundle\Traits\GetExportServiceTraits; use EspierBundle\Jobs\ExportFileJob; @@ -152,6 +153,53 @@ class ExportData extends Controller $params['source_from'] = '商城后台发放'; $params['trigger_time'] = time(); + // 如果传了 tag_ids,根据标签筛选会员 + $tagIds = $request->get('tag_ids'); + if (!empty($tagIds)) { + // 将 tag_ids 转换为数组 + if (!is_array($tagIds)) { + $tagIds = explode(',', $tagIds); + } + $tagIds = array_filter(array_map('intval', $tagIds)); + + if (!empty($tagIds)) { + app('log')->info('[ExportData][give_coupon] 根据标签筛选会员', [ + 'company_id' => $companyId, + 'tag_ids' => $tagIds, + ]); + + // 根据标签获取会员ID列表(取并集:拥有任意一个标签的会员) + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('DISTINCT user_id') + ->from('members_rel_tags') + ->where($qb->expr()->eq('company_id', $qb->expr()->literal($companyId))) + ->andWhere($qb->expr()->in('tag_id', $tagIds)); + + $result = $qb->execute()->fetchAll(); + $tagUserIds = array_column($result, 'user_id'); + + app('log')->info('[ExportData][give_coupon] 根据标签获取到的会员数量', [ + 'company_id' => $companyId, + 'tag_ids' => $tagIds, + 'member_count' => count($tagUserIds), + ]); + + // 如果原来 filter 中已经有 user_id,取交集;否则直接使用标签筛选的会员ID + if (!empty($filter['user_id'])) { + $existingUserIds = is_array($filter['user_id']) ? $filter['user_id'] : [$filter['user_id']]; + $filter['user_id'] = array_intersect($existingUserIds, $tagUserIds); + } else { + $filter['user_id'] = $tagUserIds; + } + + // 如果没有匹配的会员,直接返回 + if (empty($filter['user_id'])) { + return $this->response->array(['status' => true, 'msg' => '根据标签未找到符合条件的会员']); + } + } + } + app('log')->debug(":user-number:couponsids: " . json_encode($params['couponsids'])); $discountCardService = new DiscountCardService(); $cardList = $discountCardService->getKaquanList($page = 0, $limit = 500, ['company_id' => $companyId,'card_id|in' => $params['couponsids']]); diff --git a/src/MembersBundle/Http/Api/V1/Action/MemberTagAction.php b/src/MembersBundle/Http/Api/V1/Action/MemberTagAction.php new file mode 100644 index 0000000..8a9ef79 --- /dev/null +++ b/src/MembersBundle/Http/Api/V1/Action/MemberTagAction.php @@ -0,0 +1,445 @@ +memberTagService = new MemberTagsService(); + $this->limit = 20; + $this->segmentRuleRepository = app('registry')->getManager('default')->getRepository(MemberSegmentRule::class); + $this->segmentRuleService = new MemberSegmentRuleService(); + } + + /** + * 创建人群规则 + * 路由: POST /member/segment-rule + * 路由名称: member.segment.rule.create + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function createSegmentRule(Request $request) + { + $params = $request->all(); + if(!empty($params['condition'])){ + if(!is_array($params['condition'])){ + $params['condition'] = json_decode($params['condition'], true); + } + + } + // 参数验证 + $rules = [ + 'rule_name' => ['required|string|max:100', '规则名称必填且不能超过100个字符'], + 'description' => ['string|max:255', '人群说明不能超过255个字符'], + 'condition' => ['required|array', '规则配置必填且必须是数组'], + 'tag_ids' => ['required|array', '标签ID数组必填且必须是数组'], + ]; + + $errorMessage = validator_params($params, $rules); + if ($errorMessage) { + throw new ResourceException($errorMessage); + } + + // 验证 condition 结构 + if (empty($params['condition']) || !is_array($params['condition'])) { + throw new ResourceException('规则配置不能为空'); + } + + // 获取当前用户信息 + $user = app('auth')->user(); + $data = [ + 'company_id' => $user->get('company_id'), + 'distributor_id' => 0, + 'rule_name' => $params['rule_name'], + 'description' => $params['description'] ?? '', + 'rule_config' => $params['condition'], // 前端传的 condition 就是 rule_config + 'tag_ids' => $params['tag_ids'], + 'status' => isset($params['status']) ? (int)$params['status'] : 1, + ]; + + // 如果是分销商,设置分销商ID + $operatorType = $user->get('operator_type'); + if ($operatorType == 'distributor') { + $data['distributor_id'] = $user->get('distributor_id') ?: 0; + } elseif (isset($params['distributor_id'])) { + $data['distributor_id'] = (int)$params['distributor_id']; + } + + // 创建规则 + try { + $result = $this->segmentRuleRepository->create($data); + + // 获取匹配的用户ID并打标签 + $matchedUserIds = []; + $taggedCount = 0; + + try { + // 查询匹配的用户ID + $matchedUserIds = $this->segmentRuleService->queryMatchedUserIds( + $params['condition'], + $data['company_id'], + $data['distributor_id'] + ); + + // 如果有匹配的用户且有标签,则打标签 + if (!empty($matchedUserIds) && !empty($params['tag_ids'])) { + $this->memberTagService->createRelTags( + $matchedUserIds, + $params['tag_ids'], + $data['company_id'] + ); + $taggedCount = count($matchedUserIds); + + app('log')->info('[createSegmentRule] 圈选规则创建并打标签成功', [ + 'rule_id' => $result['rule_id'], + 'rule_name' => $result['rule_name'], + 'matched_count' => count($matchedUserIds), + 'tagged_count' => $taggedCount, + 'tag_ids' => $params['tag_ids'], + ]); + } + } catch (\Exception $e) { + // 打标签失败不影响规则创建,只记录日志 + app('log')->error('[createSegmentRule] 打标签失败', [ + 'rule_id' => $result['rule_id'], + 'error' => $e->getMessage(), + ]); + } + + return $this->response->array([ + 'rule_id' => $result['rule_id'], + 'rule_name' => $result['rule_name'], + 'description' => $result['description'] ?? '', + 'matched_count' => count($matchedUserIds), + 'tagged_count' => $taggedCount, + 'status' => 'success' + ]); + } catch (\Exception $e) { + throw new ResourceException('创建规则失败:' . $e->getMessage()); + } + } + + /** + * 获取人群规则列表 + * 路由: GET /member/segment-rule + * 路由名称: member.segment.rule.list + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function getSegmentRuleList(Request $request) + { + // 获取当前用户信息 + $user = app('auth')->user(); + $companyId = $user->get('company_id'); + $operatorType = $user->get('operator_type'); + $distributorId = $user->get('distributor_id'); + + // 准备参数 + $params = [ + 'company_id' => $companyId, + 'operator_type' => $operatorType, + 'distributor_id' => $distributorId, + 'page' => $request->get('page', 1), + 'page_size' => $request->get('page_size', 20), + 'status' => $request->get('status'), + 'rule_name' => $request->get('rule_name'), + 'tag_name' => $request->get('tag_name'), + 'created_start' => $request->get('created_start'), + 'created_end' => $request->get('created_end'), + 'request_distributor_id' => $request->get('distributor_id'), + ]; + + try { + // 调用 Service 获取列表 + $result = $this->segmentRuleService->getSegmentRuleList($params); + + return $this->response->array($result); + } catch (\Exception $e) { + throw new ResourceException('获取规则列表失败:' . $e->getMessage()); + } + } + + /** + * 编辑人群规则 + * 路由: PUT /member/segment-rule/{rule_id} + * 路由名称: member.segment.rule.update + * + * @param Request $request + * @param int $rule_id + * @return \Illuminate\Http\JsonResponse + */ + public function updateSegmentRule(Request $request, $rule_id) + { + $params = $request->all(); + + // 参数验证 + $rules = [ + 'rule_name' => ['string|max:100', '规则名称不能超过100个字符'], + 'description' => ['string|max:255', '人群说明不能超过255个字符'], + 'condition' => ['array', '规则配置必须是数组'], + 'tag_ids' => ['array', '标签ID数组必须是数组'], + ]; + + $errorMessage = validator_params($params, $rules); + if ($errorMessage) { + throw new ResourceException($errorMessage); + } + + // 获取当前用户信息 + $user = app('auth')->user(); + $companyId = $user->get('company_id'); + $operatorType = $user->get('operator_type'); + + // 构建查询条件 + $filter = [ + 'rule_id' => (int)$rule_id, + 'company_id' => $companyId, + ]; + + // 如果是分销商,只能编辑自己的规则 + if ($operatorType == 'distributor') { + $distributorId = $user->get('distributor_id'); + if ($distributorId) { + $filter['distributor_id'] = $distributorId; + } + } else { + $requestDistributorId = $request->get('distributor_id'); + if ($requestDistributorId !== null) { + $filter['distributor_id'] = (int)$requestDistributorId; + } + } + + // 验证规则是否存在 + $rule = $this->segmentRuleRepository->getOneBy($filter); + if (!$rule) { + throw new ResourceException('规则不存在或无权限编辑'); + } + + // 准备更新数据 + $updateData = []; + + if (isset($params['rule_name'])) { + $updateData['rule_name'] = $params['rule_name']; + } + + if (isset($params['description'])) { + $updateData['description'] = $params['description']; + } + + if (isset($params['condition'])) { + if (empty($params['condition']) || !is_array($params['condition'])) { + throw new ResourceException('规则配置不能为空'); + } + $updateData['rule_config'] = $params['condition']; + } + + if (isset($params['tag_ids'])) { + $updateData['tag_ids'] = $params['tag_ids']; + } + + if (isset($params['status'])) { + $updateData['status'] = (int)$params['status']; + } + + if (empty($updateData)) { + throw new ResourceException('没有需要更新的数据'); + } + + // 更新规则 + try { + $result = $this->segmentRuleRepository->updateOneBy($filter, $updateData); + return $this->response->array([ + 'rule_id' => $result['rule_id'], + 'rule_name' => $result['rule_name'], + 'description' => $result['description'] ?? '', + 'status' => 'success' + ]); + } catch (\Exception $e) { + throw new ResourceException('更新规则失败:' . $e->getMessage()); + } + } + + /** + * 查看人群规则详情 + * 路由: GET /member/segment-rule/{rule_id} + * 路由名称: member.segment.rule.get + * + * @param Request $request + * @param int $rule_id + * @return \Illuminate\Http\JsonResponse + */ + public function getSegmentRule(Request $request, $rule_id) + { + // 获取当前用户信息 + $user = app('auth')->user(); + $companyId = $user->get('company_id'); + $operatorType = $user->get('operator_type'); + + // 构建查询条件 + $filter = [ + 'rule_id' => (int)$rule_id, + 'company_id' => $companyId, + ]; + + // 如果是分销商,只能查看自己的规则 + if ($operatorType == 'distributor') { + $distributorId = $user->get('distributor_id'); + if ($distributorId) { + $filter['distributor_id'] = $distributorId; + } + } else { + $requestDistributorId = $request->get('distributor_id'); + if ($requestDistributorId !== null) { + $filter['distributor_id'] = (int)$requestDistributorId; + } + } + + // 查询规则 + $rule = $this->segmentRuleRepository->getOneBy($filter); + + if (!$rule) { + throw new ResourceException('规则不存在或无权限查看'); + } + + // 查询关联的标签信息 + $tagList = []; + $tagIds = $rule['tag_ids'] ?? []; + if (!empty($tagIds) && is_array($tagIds)) { + // 使用查询构建器直接查询,避免空数组导致的 SQL 语法错误 + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + + // 将数组值转换为 literal(项目标准方式) + array_walk($tagIds, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + + $qb->select('tag_id', 'tag_name') + ->from('members_tags') + ->where($qb->expr()->eq('company_id', $companyId)) + ->andWhere($qb->expr()->in('tag_id', $tagIds)); + + $tags = $qb->execute()->fetchAll(); + + foreach ($tags as $tag) { + $tagList[] = [ + 'tag_id' => $tag['tag_id'], + 'tag_name' => $tag['tag_name'], + ]; + } + } + + // 格式化返回数据 + return $this->response->array([ + 'rule_id' => $rule['rule_id'], + 'rule_name' => $rule['rule_name'], + 'description' => $rule['description'] ?? '', + 'condition' => $rule['rule_config'], // 返回时使用 condition 字段名 + 'tag_ids' => $rule['tag_ids'], + 'tags' => $tagList, // 标签详细信息 + 'status' => $rule['status'], + 'created' => $rule['created'], + 'updated' => $rule['updated'], + ]); + } + + /** + * 预览人群规则(查询匹配的用户ID) + * 路由: POST /member/segment-rule/preview + * 路由名称: member.segment.rule.preview + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function previewSegmentRule(Request $request) + { + $params = $request->all(); + + // 参数验证 + $rules = [ + 'condition' => ['required|array', '规则配置必填且必须是数组'], + ]; + + $errorMessage = validator_params($params, $rules); + if ($errorMessage) { + throw new ResourceException($errorMessage); + } + + // 验证 condition 结构 + if (empty($params['condition']) || !is_array($params['condition'])) { + throw new ResourceException('规则配置不能为空'); + } + + // 获取当前用户信息 + $user = app('auth')->user(); + $companyId = $user->get('company_id'); + $operatorType = $user->get('operator_type'); + + $distributorId = 0; + if ($operatorType == 'distributor') { + $distributorId = $user->get('distributor_id') ?: 0; + } elseif (isset($params['distributor_id'])) { + $distributorId = (int)$params['distributor_id']; + } + + try { + // 调用 Service 查询匹配的用户ID + $userIds = $this->segmentRuleService->queryMatchedUserIds( + $params['condition'], + $companyId, + $distributorId + ); + + return $this->response->array([ + 'matched_count' => count($userIds), + 'user_ids' => $userIds, + ]); + } catch (\Exception $e) { + throw new ResourceException('查询失败:' . $e->getMessage()); + } + } + + /** + * 获取规则结构配置(给前端使用) + * 路由: GET /member/segment-rule/structure + * 路由名称: member.segment.rule.structure + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function getRuleStructure(Request $request) + { + // 获取当前用户信息 + $user = app('auth')->user(); + $companyId = $user->get('company_id'); + + try { + // 调用 Service 获取规则结构 + $structure = $this->segmentRuleService->getRuleStructure($companyId); + + return $this->response->array($structure); + } catch (\Exception $e) { + throw new ResourceException('获取规则结构失败:' . $e->getMessage()); + } + } +} diff --git a/src/MembersBundle/Http/Api/V1/Action/MemberTags.php b/src/MembersBundle/Http/Api/V1/Action/MemberTags.php index 9dc813a..f15319d 100644 --- a/src/MembersBundle/Http/Api/V1/Action/MemberTags.php +++ b/src/MembersBundle/Http/Api/V1/Action/MemberTags.php @@ -57,12 +57,12 @@ class MemberTags extends Controller public function createTags(Request $request) { - $params = $request->all('category_id', 'tag_name', 'description', 'tag_color', 'font_color'); + $params = $request->all('category_id', 'tag_name', 'description', 'tag_color', 'font_color', 'group_id'); $rules = [ 'tag_name' => ['required', '标签名称不能为空'], - 'tag_color' => ['required', '标签颜色'], - 'font_color' => ['required', '标签字体颜色'], + // 'tag_color' => ['required', '标签颜色'], + // 'font_color' => ['required', '标签字体颜色'], ]; $error = validator_params($params, $rules); if ($error) { @@ -83,10 +83,185 @@ class MemberTags extends Controller throw new StoreResourceFailedException('标签名称不能重复'); } - $result = $this->memberTagService->create($params); + try { + $result = $this->memberTagService->createTagWithGroup($params); + } catch (\Exception $e) { + throw new StoreResourceFailedException($e->getMessage()); + } return $this->response->array($result); } + /** + * @SWG\Post( + * path="/member/tag-group", + * summary="新增标签组并关联标签", + * tags={"会员"}, + * description="新增标签组,首次创建会自动生成默认组并关联现有标签", + * operationId="createTagGroup", + * @SWG\Parameter( name="Authorization", in="header", description="JWT验证token", required=true, type="string"), + * @SWG\Parameter( name="group_name", in="query", description="标签组名称", required=true, type="string"), + * @SWG\Parameter( name="description", in="query", description="标签组描述", required=false, type="string"), + * @SWG\Parameter( name="tag_ids", in="query", description="要关联的标签ID数组", required=false, type="array", @SWG\Items(type="integer")), + * @SWG\Parameter( name="tags", in="query", description="需要创建并关联的标签列表", required=false, type="array", @SWG\Items( + * @SWG\Property(property="tag_name", type="string"), + * @SWG\Property(property="tag_color", type="string"), + * @SWG\Property(property="font_color", type="string"), + * @SWG\Property(property="description", type="string"), + * @SWG\Property(property="category_id", type="integer") + * )), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="data", + * type="object" + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/MembersErrorRespones") ) ) + * ) + */ + public function createTagGroup(Request $request) + { + $params = $request->all('group_name', 'description', 'tag_ids', 'tags'); + $rules = [ + 'group_name' => ['required', '标签组名称不能为空'], + ]; + $error = validator_params($params, $rules); + if ($error) { + throw new StoreResourceFailedException($error); + } + + $params['company_id'] = app('auth')->user()->get('company_id'); + $params['distributor_id'] = app('auth')->user()->get('distributor_id'); + + // 支持逗号字符串或数组格式的标签ID + if (isset($params['tag_ids']) && $params['tag_ids'] && !is_array($params['tag_ids'])) { + $params['tag_ids'] = array_filter(explode(',', $params['tag_ids'])); + } + + $result = $this->memberTagService->createTagGroup($params); + return $this->response->array($result); + } + + /** + * @SWG\Get( + * path="/member/tag-group", + * summary="获取标签组列表(含组内标签)", + * tags={"会员"}, + * description="按标签组维度分页返回,并附带组内标签列表", + * operationId="getTagGroupList", + * @SWG\Parameter( name="Authorization", in="header", description="JWT验证token", required=true, type="string"), + * @SWG\Parameter( name="page", in="query", description="页码", required=false, type="integer"), + * @SWG\Parameter( name="page_size", in="query", description="每页数量", required=false, type="integer"), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="data", + * type="object" + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/MembersErrorRespones") ) ) + * ) + */ + public function getTagGroupList(Request $request) + { + $page = (int)$request->get('page', 1); + $pageSize = (int)$request->get('pageSize', 20); + $groupName = $request->get('group_name', ''); + $user = app('auth')->user()->get(); + $filter = [ + 'company_id' => $user['company_id'], + // 'distributor_id' => $user['distributor_id'] ?? 0, + ]; + // 如果传了group_name,添加到过滤条件中 + if (!empty($groupName)) { + $filter['group_name'] = $groupName; + } + $result = $this->memberTagService->getTagGroupList($filter, $page, $pageSize); + return $this->response->array($result); + } + + /** + * @SWG\Put( + * path="/member/tag-group/{group_id}", + * summary="编辑标签组及标签", + * tags={"会员"}, + * description="可修改标签组名称/描述,新增或更新标签,删除指定标签并清理会员关联", + * operationId="updateTagGroup", + * @SWG\Parameter( name="Authorization", in="header", description="JWT验证token", required=true, type="string"), + * @SWG\Parameter( name="group_id", in="path", description="标签组ID", required=true, type="integer"), + * @SWG\Parameter( name="group_name", in="query", description="标签组名称", required=true, type="string"), + * @SWG\Parameter( name="description", in="query", description="标签组描述", required=false, type="string"), + * @SWG\Parameter( name="deleteids", in="query", description="需要删除的标签ID数组", required=false, type="array", @SWG\Items(type="integer")), + * @SWG\Parameter( name="tags", in="query", description="需创建/更新的标签列表", required=false, type="array", @SWG\Items( + * @SWG\Property(property="tag_id", type="integer", description="0表示新增"), + * @SWG\Property(property="tag_name", type="string"), + * @SWG\Property(property="tag_color", type="string"), + * @SWG\Property(property="font_color", type="string"), + * @SWG\Property(property="description", type="string"), + * @SWG\Property(property="category_id", type="integer") + * )), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="data", + * type="object" + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/MembersErrorRespones") ) ) + * ) + */ + public function updateTagGroup(Request $request, $group_id) + { + $params = $request->all('group_name', 'description', 'deleteids', 'tags'); + $params['group_id'] = (int)$group_id; + + $rules = [ + 'group_name' => ['required', '标签组名称不能为空'], + ]; + $error = validator_params($params, $rules); + if ($error) { + throw new StoreResourceFailedException($error); + } + + $params['company_id'] = app('auth')->user()->get('company_id'); + $params['distributor_id'] = app('auth')->user()->get('distributor_id'); + + // deleteids 支持逗号分隔 + if (isset($params['deleteids']) && $params['deleteids'] && !is_array($params['deleteids'])) { + $params['deleteids'] = array_filter(explode(',', $params['deleteids'])); + } + + try { + $result = $this->memberTagService->updateTagGroup($params); + } catch (\Exception $e) { + throw new StoreResourceFailedException($e->getMessage().'---'.$e->getFile().'---'.$e->getLine()); + } + return $this->response->array($result); + } + + /** + * @SWG\Delete( + * path="/member/tag-group/{group_id}", + * summary="删除标签组(仅支持无标签关联的组)", + * tags={"会员"}, + * description="删除标签组,若已关联标签则不允许删除", + * operationId="deleteTagGroup", + * @SWG\Parameter( name="Authorization", in="header", description="JWT验证token", required=true, type="string"), + * @SWG\Parameter( name="group_id", in="path", description="标签组ID", required=true, type="integer"), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="data", + * type="object" + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/MembersErrorRespones") ) ) + * ) + */ + public function deleteTagGroup($group_id) + { + $companyId = app('auth')->user()->get('company_id'); + $distributorId = app('auth')->user()->get('distributor_id'); + try { + $result = $this->memberTagService->deleteTagGroup((int)$group_id, $companyId, $distributorId); + } catch (\Exception $e) { + throw new StoreResourceFailedException($e->getMessage()); + } + return $this->response->array(['status' => $result]); + } + /** * @SWG\Put( * path="/member/tag", diff --git a/src/MembersBundle/Http/Api/V1/Action/Members.php b/src/MembersBundle/Http/Api/V1/Action/Members.php index a066b60..a4f5e33 100644 --- a/src/MembersBundle/Http/Api/V1/Action/Members.php +++ b/src/MembersBundle/Http/Api/V1/Action/Members.php @@ -33,11 +33,15 @@ use MembersBundle\Services\MemberOperateLogService; use KaquanBundle\Services\VipGradeOrderService; use MembersBundle\Traits\MemberSearchFilter; use DistributionBundle\Services\DistributorUserService; +use DistributionBundle\Services\DistributorService; +use DistributionBundle\Entities\Distributor; use SalespersonBundle\Services\SalespersonService; +use MembersBundle\Entities\MembersAssociations; use Dingo\Api\Exception\ResourceException; use PointBundle\Services\PointMemberService; use ThirdPartyBundle\Services\ShopexCrm\GetMemberListService; +use ThirdPartyBundle\Services\MarketingCenter\Request as MarketingCenterRequest; use WorkWechatBundle\Services\WorkWechatRelService; use CommunityBundle\Services\CommunityChiefService; use CommunityBundle\Services\CommunityChiefDistributorService; @@ -46,8 +50,9 @@ use PopularizeBundle\Services\PromoterService; use MembersBundle\Events\CreateMemberSuccessEvent; use KaquanBundle\Services\UserDiscountService; use MembersBundle\Entities\MembersDeleteRecord; +use MembersBundle\Services\MemberSalespersonNotifyService; -use ThirdPartyBundle\Services\MarketingCenter\Request as MarketingCenterRequest; +use EspierBundle\Services\Config\ConfigRequestFieldsService; class Members extends Controller { @@ -254,6 +259,10 @@ class Members extends Controller * @SWG\Parameter( in="query", type="string", required=false, name="vip_grade", description="付费会员类型" ), * @SWG\Parameter( in="query", type="string", required=false, name="remarks", description="备注" ), * @SWG\Parameter( in="query", type="string", required=false, name="username", description="姓名" ), + * @SWG\Parameter( in="query", type="string", required=false, name="employee_number", description="绑定导购编号" ), + * @SWG\Parameter( in="query", type="string", required=false, name="store_bn", description="绑定门店编号" ), + * @SWG\Parameter( in="query", type="string", required=false, name="birthday_start", description="生日开始日期,格式:Y-m-d" ), + * @SWG\Parameter( in="query", type="string", required=false, name="birthday_end", description="生日结束日期,格式:Y-m-d" ), * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( * @SWG\Property( property="data", type="object", * @SWG\Property( property="list", type="array", @@ -329,10 +338,14 @@ class Members extends Controller 'have_consume' => ['sometimes|' . Rule::in(['true', 'false']), '有无购买记录参数不正确'], 'distributor_id' => ['sometimes|integer|min:1', '请确认您选择的店铺是否存在'], 'shop_id' => ['sometimes|integer|min:1', '请确认您选择的门店是否存在'], - 'tag_id' => ['sometimes|integer|min:1', '请确认您选择的会员标签是否存在'], + 'tag_id' => ['sometimes', '请确认您选择的会员标签是否存在'], 'grade_id' => ['sometimes', '请确认您选择的会员等级是否存在'], 'vip_grade' => ['sometimes|' . Rule::in(['notvip', 'svip', 'vip', 'vip,svip']), '付费会员类型参数不正确'], 'promoter_mobile' => ['sometimes|regex:/^1[3456789][0-9]{9}$/', '来源推广员请填写正确的手机号'], + 'employee_number' => ['sometimes|string', '导购编号'], + 'store_bn' => ['sometimes|string', '门店编号'], + 'birthday_start' => ['sometimes|date_format:Y-m-d', '请填写正确的生日开始日期'], + 'birthday_end' => ['sometimes|date_format:Y-m-d', '请填写正确的生日结束日期'], //'inviter_id' =>[], //'user_card_code' =>[], //'user_id' => [], @@ -342,6 +355,10 @@ class Members extends Controller throw new ResourceException($error); } $filter = $this->dataFilter($postdata, $authdata); + $user = app('auth')->user(); + if ($user->get('operator_type') == 'distributor') { //店铺端 + $filter['op_distributor'] = $user->get('distributor_id'); + } if (isset($postdata['inviter_mobile']) && $postdata['inviter_mobile']) { $inviterId = $this->memberService->getUserIdByMobile($postdata['inviter_mobile'], $authdata['company_id']); $filter['inviter_id'] = $inviterId ?: '-1'; @@ -373,6 +390,68 @@ class Members extends Controller $filter['user_id'] = $promoterUserIds; } } + + // 绑定导购编号或绑定门店编号查询 + if ((isset($postdata['store_name']) && $postdata['store_name']) || + (isset($postdata['employee_number']) && $postdata['employee_number'])) { + + $bindMemberIds = $this->memberService->getBindMemberIdsBySalesperson( + $authdata['company_id'], + $postdata['employee_number'] ?? null, + $postdata['store_name'] ?? null + ); + + if (!empty($bindMemberIds)) { + // 如果已有 user_id 条件,取交集;否则直接设置 + $existingUserIds = null; + // 处理 user_id|in 的情况(优先级最高) + if (isset($filter['user_id|in'])) { + $existingUserIds = is_array($filter['user_id|in']) ? $filter['user_id|in'] : [$filter['user_id|in']]; + unset($filter['user_id|in']); + } elseif (isset($filter['user_id']) && $filter['user_id']) { + $existingUserIds = is_array($filter['user_id']) ? $filter['user_id'] : [$filter['user_id']]; + unset($filter['user_id']); + } + + // 处理 user_id|notIn 的情况:需要排除 notIn 中的ID,然后取交集 + if (isset($filter['user_id|notIn'])) { + $notInIds = is_array($filter['user_id|notIn']) ? $filter['user_id|notIn'] : [$filter['user_id|notIn']]; + $bindMemberIds = array_diff($bindMemberIds, $notInIds); + // 如果排除后没有剩余ID,设置为空结果 + if (empty($bindMemberIds)) { + unset($filter['user_id|notIn']); + $filter['user_id|in'] = [-1]; + } else { + unset($filter['user_id|notIn']); + if ($existingUserIds !== null) { + $filter['user_id|in'] = array_intersect($existingUserIds, $bindMemberIds); + if (empty($filter['user_id|in'])) { + $filter['user_id|in'] = [-1]; + } + } else { + $filter['user_id|in'] = $bindMemberIds; + } + } + } else { + if ($existingUserIds !== null) { + $filter['user_id|in'] = array_intersect($existingUserIds, $bindMemberIds); + // 如果交集为空,设置为不存在的ID,确保查询结果为空 + if (empty($filter['user_id|in'])) { + $filter['user_id|in'] = [-1]; + } + } else { + $filter['user_id|in'] = $bindMemberIds; + } + } + } else { + // 如果没有找到绑定的会员,设置为不存在的ID,确保查询结果为空 + // 如果已有 user_id 条件,也需要清空并设置为空结果 + unset($filter['user_id'], $filter['user_id|in'], $filter['user_id|notIn']); + $filter['user_id|in'] = [-1]; + } + } + + unset($filter['distributor_id']); $result['list'] = $this->memberService->getMemberList($filter, $page, $limit); $result['total_count'] = $this->memberService->getMemberCount($filter); @@ -420,7 +499,7 @@ class Members extends Controller // 是否可调整上级(非推广员、有上级推广员) $isCanChangepid = $promoterService->getMemberIsCanChangepid($companyId, $userIds); } - + $allMobile = []; foreach ($result['list'] as &$value) { $value['habbit'] = json_decode($value['habbit'], true); @@ -455,7 +534,7 @@ class Members extends Controller $value['mobile'] = data_masking('mobile', (string) $value['mobile']); $value['username'] = data_masking('truename', (string) $value['username']); $value['inviter'] = $value['inviter'] == '-' ? $value['inviter'] : data_masking('mobile', (string) $value['inviter']); - $value['sex'] = $value['sex'] == '0' ? '-' : data_masking('sex', (string) $value['sex']); + // $value['sex'] = $value['sex'] == '0' ? '-' : data_masking('sex', (string) $value['sex']); } } @@ -480,7 +559,131 @@ class Members extends Controller } } } - + + // 为每个成员添加 requestFields + if ($result['list']) { + $userIds = array_column($result['list'], 'user_id'); + $membersInfoFilter = [ + 'user_id' => $userIds, + 'company_id' => $companyId, + ]; + // 批量获取所有成员的 members_info 数据 + $membersInfoList = $this->memberService->membersInfoRepository->getListNotPagination($membersInfoFilter, '*'); + $membersInfoIndex = []; + foreach ($membersInfoList as $info) { + $membersInfoIndex[$info['user_id']] = $info; + } + + // 获取验证字段配置 + $requestValidateList = (new ConfigRequestFieldsService())->getListAndHandleSettingFormat($companyId, ConfigRequestFieldsService::MODULE_TYPE_MEMBER_INFO); + + // 为每个成员生成 requestFields + foreach ($result['list'] as &$member) { + $requestFields = []; + $datapassRequestFields = []; + + if (isset($membersInfoIndex[$member['user_id']])) { + $info = $membersInfoIndex[$member['user_id']]; + $info["other_params"] = (array)jsonDecode($info["other_params"] ?? null); + + foreach ($requestValidateList as $keyName => $item) { + // 根据数据库中定义的字段名去member和info里获取实际的值,如果都拿不到,则去info的other_params.custom_data里去取 + if (isset($member[$keyName])) { + $requestFields[$keyName] = $member[$keyName]; + } elseif (isset($info[$keyName])) { + $requestFields[$keyName] = $info[$keyName]; + } else { + $requestFields[$keyName] = $info["other_params"]["custom_data"][$keyName] ?? null; + } + + $fieldType = $item["field_type"] ?? null; + // 如果字段是checkbox则只把选中的值拼接成字符串 + if ($fieldType == ConfigRequestFieldsService::FIELD_TYPE_CHECKBOX && !empty($requestFields[$keyName])) { + // 获取已经选中的选项 + $checkedItemList = []; + $requestFields[$keyName] = (array)jsonDecode($requestFields[$keyName]); + foreach ($requestFields[$keyName] as &$checkboxItem) { + if (!empty($checkboxItem["ischecked"]) && ($checkboxItem["ischecked"] === "true" || $checkboxItem["ischecked"] === true)) { + $checkboxItem["ischecked"] = true; + $checkedItemList[] = $checkboxItem["name"] ?? ""; + } else { + $checkboxItem["ischecked"] = false; + } + } + unset($checkboxItem); + } + if ($item['field_type'] == ConfigRequestFieldsService::FIELD_TYPE_MOBILE) { + $datapassRequestFields['mobile'][] = $keyName; + } + } + + // 转换字段值为描述 + (new ConfigRequestFieldsService())->transformGetDescByValue($companyId, ConfigRequestFieldsService::MODULE_TYPE_MEMBER_INFO, $requestFields); + } + + $member["requestFields"] = $requestFields; + $member['datapassRequestFields'] = $datapassRequestFields; + } + } + + + // 批量查询会员的绑定导购和绑定门店 + $this->memberService->batchGetBindSalesperson($companyId, $result['list']); + + // 批量查询注册分销商名称 + $regDistributorIds = array_filter(array_unique(array_column($result['list'], 'reg_distributor')), function($id) { + return $id > 0; + }); + $regDistributorNames = []; + if (!empty($regDistributorIds)) { + $distributorRepository = app('registry')->getManager('default')->getRepository(Distributor::class); + $distributorFilter = [ + 'distributor_id' => $regDistributorIds, + 'company_id' => $companyId, + ]; + $distributorList = $distributorRepository->getLists($distributorFilter, 'distributor_id,name'); + + if (!empty($distributorList)) { + foreach ($distributorList as $distributor) { + $regDistributorNames[$distributor['distributor_id']] = $distributor['name'] ?? ''; + } + } + } + + // 将分销商名称添加到会员列表中 + foreach ($result['list'] as &$member) { + $regDistributorId = $member['reg_distributor'] ?? 0; + $member['reg_distributor_name'] = $regDistributorNames[$regDistributorId] ?? ''; + } + unset($member); + + // 批量查询分配的店铺(op_distributor)对应的门店名称 + $opDistributorIds = array_filter(array_unique(array_column($result['list'], 'op_distributor')), function($id) { + return $id > 0; + }); + $opDistributorNames = []; + if (!empty($opDistributorIds)) { + $distributorRepository = app('registry')->getManager('default')->getRepository(Distributor::class); + $distributorFilter = [ + 'distributor_id' => $opDistributorIds, + 'company_id' => $companyId, + ]; + $distributorList = $distributorRepository->getLists($distributorFilter, 'distributor_id,name'); + + if (!empty($distributorList)) { + foreach ($distributorList as $distributor) { + $opDistributorNames[$distributor['distributor_id']] = $distributor['name'] ?? ''; + } + } + } + + // 将门店名称添加到会员列表中,字段名为 maintain_store + foreach ($result['list'] as &$member) { + $opDistributorId = $member['op_distributor'] ?? 0; + $member['maintain_store'] = $opDistributorNames[$opDistributorId] ?? ''; + } + unset($member); + } return $this->response->array($result); } @@ -568,11 +771,50 @@ class Members extends Controller ]; $result['wechatUserInfo'] = $wechatUserService->getUserInfo($filter); $unionid = $result['wechatUserInfo']['unionid'] ?? ''; + + // 绑定导购和绑定门店信息(通过 unionid 查询) if($unionid){ $requestSalesperson = new MarketingCenterRequest(); - $resultSalesperson = $requestSalesperson->call($companyId, 'basics.member.getBindSalesperson', ['unionid' => $unionid]); + $resultSalesperson = $requestSalesperson->call($companyId, 'basics.member.getBindSalesperson', ['external_member_id' => $result['user_id']]); // [2025-08-01 17:09:24] production.DEBUG: MarketingCenter:result===>{"status":"success","code":"200","message":"success","data":{"salesperson_id":8,"work_userid":"18964058319","member_id":"8","external_member_type":1,"external_userid":"wmZ_c_cQAAZ8RAXTS1EZbpCv0TASdw1A","suite_external_userid":"","unionid":"oFvDQ69HXH8Wcbw19tE9h0RM4MvY","member_status":1,"bind_status":1,"bind_time":1753949254,"bind_cancel_time":1754063999,"friend_status":1,"become_friend_time":1753949070,"employee_number":"18964058319","store_bn":"09876555","store_name":"桂林路店"}} - $result['salesperson_info'] = $resultSalesperson['data'] ?? []; + $salespersonData = $resultSalesperson['data'] ?? []; + $result['salesperson_info'] = $salespersonData; + + // 绑定门店信息 + if (!empty($salespersonData)) { + $result['store_info'] = [ + 'store_bn' => $salespersonData['store_bn'] ?? '', + 'store_name' => $salespersonData['store_name'] ?? '', + ]; + } else { + $result['store_info'] = [ + 'store_bn' => '', + 'store_name' => '', + ]; + } + } else { + $result['salesperson_info'] = []; + $result['store_info'] = [ + 'store_bn' => '', + 'store_name' => '', + ]; + } + + + // 注册门店信息(根据 reg_distributor 查询) + if (!empty($result['reg_distributor']) && $result['reg_distributor'] > 0) { + $distributorRepository = app('registry')->getManager('default')->getRepository(Distributor::class); + $distributorInfo = $distributorRepository->getInfo([ + 'distributor_id' => $result['reg_distributor'], + 'company_id' => $companyId, + ]); + if ($distributorInfo) { + $result['reg_distributor'] = $distributorInfo['name'] ?? ''; + } else { + $result['reg_distributor'] = ''; + } + } else { + $result['reg_distributor'] = ''; } $depositTrade = new DepositTrade(); @@ -1373,4 +1615,373 @@ class Members extends Controller return $this->response->array($result); } + + + /** + * @SWG\Put( + * path="/member/regDistributor", + * summary="批量更新会员注册分销商", + * tags={"会员"}, + * description="批量更新会员的注册分销商ID(reg_distributor字段)", + * operationId="reChangeRegDistributor", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * required=true, + * type="string", + * ), + * @SWG\Parameter( + * name="user_id", + * in="query", + * description="会员ID数组,支持数组格式或JSON字符串格式,如:[1,2,3] 或 \"[1,2,3]\"", + * required=true, + * type="array", + * @SWG\Items(type="integer") + * ), + * @SWG\Parameter( + * name="distributor_id", + * in="query", + * description="分销商ID", + * required=true, + * type="integer", + * ), + * @SWG\Response( + * response=200, + * description="成功返回结构", + * @SWG\Schema( + * @SWG\Property( + * property="data", + * type="object", + * @SWG\Property(property="status", type="boolean", example=true, description="操作状态"), + * @SWG\Property(property="message", type="string", example="更新成功", description="提示信息"), + * @SWG\Property(property="affected_rows", type="integer", example=5, description="受影响的行数"), + * ), + * ), + * ), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/MembersErrorRespones") ) ) + * ) + */ + public function reChangeRegDistributor(Request $request){ + $companyId = app('auth')->user()->get('company_id'); + $inputData = $request->input(); + + // 参数验证 + $rules = [ + 'user_id' => ['required', '会员ID必填'], + 'distributor_id' => ['required|integer', '分销商ID必填'], + ]; + $errorMessage = validator_params($inputData, $rules); + if ($errorMessage) { + throw new ResourceException($errorMessage); + } + + $userIds = $inputData['user_id']; + $distributorId = intval($inputData['distributor_id']); + + // 确保 user_id 是数组 + if (!is_array($userIds)) { + if (is_string($userIds)) { + $userIds = json_decode($userIds, true); + } else { + $userIds = [$userIds]; + } + } + + if (empty($userIds)) { + throw new ResourceException('会员ID不能为空'); + } + + // 过滤掉无效的 user_id + $userIds = array_filter(array_map('intval', $userIds), function($id) { + return $id > 0; + }); + + if (empty($userIds)) { + throw new ResourceException('有效的会员ID不能为空'); + } + + // 查询当前会员的门店信息,过滤掉门店一致的会员 + $membersRepository = app('registry')->getManager('default')->getRepository(\MembersBundle\Entities\Members::class); + $currentMembers = $membersRepository->lists([ + 'company_id' => $companyId, + 'user_id' => $userIds, + ],["created" => "DESC"],1000,1,false); + + // 如果查询不到会员信息,则报错 + if (empty($currentMembers['list'])) { + throw new ResourceException('未找到指定的会员信息'); + } + + // 过滤出需要更新的会员(门店不一致的) + $needUpdateUserIds = []; + foreach ($currentMembers['list'] as $member) { + $currentDistributorId = intval($member['op_distributor'] ?? 0); + // 如果当前门店和提交的门店不一致,则需要更新 + if ($currentDistributorId != $distributorId) { + $needUpdateUserIds[] = intval($member['user_id']); + } + } + + // 如果所有会员的门店都一致,则不做处理 + if (empty($needUpdateUserIds)) { + app('log')->info('批量更新会员注册分销商:所有会员门店已一致,无需更新', [ + 'company_id' => $companyId, + 'user_ids' => $userIds, + 'distributor_id' => $distributorId, + ]); + + return $this->response->array([ + 'status' => true, + 'message' => '所有会员门店已一致,无需更新', + 'affected_rows' => 0, + ]); + } + + // 通知导购端批量解绑会员(在更新前先通知,只通知需要更新的会员) + try { + $notifyService = new MemberSalespersonNotifyService(); + $notifyResult = $notifyService->notifyUnbindMembers($companyId, $needUpdateUserIds); + + app('log')->info('批量更新会员注册分销商:通知导购端解绑结果', [ + 'company_id' => $companyId, + 'user_ids' => $needUpdateUserIds, + 'notify_result' => $notifyResult, + ]); + } catch (\Exception $e) { + // 通知失败不影响主流程,只记录日志 + app('log')->error('批量更新会员注册分销商:通知导购端解绑失败', [ + 'company_id' => $companyId, + 'user_ids' => $needUpdateUserIds, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + } + + // 批量更新 reg_distributor 和 op_distributor(只更新需要更新的会员) + $filter = [ + 'company_id' => $companyId, + 'user_id' => $needUpdateUserIds, + ]; + $updateData = [ + // 'reg_distributor' => $distributorId, + 'op_distributor' => $distributorId, + ]; + + $result = $membersRepository->updateBy($filter, $updateData); + + app('log')->info('批量更新会员注册分销商', [ + 'company_id' => $companyId, + 'original_user_ids' => $userIds, + 'need_update_user_ids' => $needUpdateUserIds, + 'skipped_count' => count($userIds) - count($needUpdateUserIds), + 'distributor_id' => $distributorId, + 'affected_rows' => $result, + ]); + + // 更新门店后,查询这批会员在当前门店下是否有好友关系的导购(只查询需要更新的会员) + try { + // 1. 获取门店的 shop_code(store_bn) + $distributorService = new DistributorService(); + $distributorInfo = $distributorService->getInfoSimple([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId + ]); + + if (empty($distributorInfo) || empty($distributorInfo['shop_code'])) { + app('log')->warning('批量更新会员注册分销商:未找到门店信息或门店编号', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + } else { + $storeBn = $distributorInfo['shop_code']; + + // 2. 获取会员的 unionid 列表(只查询需要更新的会员) + $membersAssociationsRepository = app('registry')->getManager('default')->getRepository(MembersAssociations::class); + $associations = $membersAssociationsRepository->lists([ + 'user_id' => $needUpdateUserIds, + 'company_id' => $companyId, + 'user_type' => 'wechat' + ], 'user_id,unionid', 1, -1); + + if (!empty($associations)) { + $unionids = array_filter(array_column($associations, 'unionid')); + + if (!empty($unionids)) { + // 3. 调用导购接口查询好友关系 + $marketingCenterRequest = new MarketingCenterRequest(); + $requestData = [ + 'store_bn' => $storeBn, + 'unionids' => $unionids, + ]; + + app('log')->info('批量更新会员注册分销商:查询门店导购好友关系', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'store_bn' => $storeBn, + 'unionids_count' => count($unionids), + ]); + + $friendCheckResult = $marketingCenterRequest->call($companyId, 'members.store.friend.check', $requestData); + + app('log')->info('批量更新会员注册分销商:查询门店导购好友关系结果', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'store_bn' => $storeBn, + 'result' => $friendCheckResult, + ]); + + // 4. 构建 unionid => user_id 的映射(无论是否有返回数据都需要) + $unionidToUserIdMap = []; + foreach ($associations as $assoc) { + if (!empty($assoc['unionid']) && !empty($assoc['user_id'])) { + $unionidToUserIdMap[$assoc['unionid']] = $assoc['user_id']; + } + } + + // 记录有好友关系的 unionid + $hasFriendUnionids = []; + + // 5. 如果查询到好友关系,更新对应会员信息 + if (!empty($friendCheckResult) && + !empty($friendCheckResult['data']) && + is_array($friendCheckResult['data'])) { + + // 收集需要更新的会员信息(有好友关系的) + $updateMembers = []; + foreach ($friendCheckResult['data'] as $friendData) { + $unionid = $friendData['unionid'] ?? ''; + $workUserid = $friendData['work_userid'] ?? ''; + + if (!empty($unionid) && !empty($workUserid) && isset($unionidToUserIdMap[$unionid])) { + $hasFriendUnionids[] = $unionid; // 记录有好友关系的 unionid + $updateMembers[] = [ + 'user_id' => $unionidToUserIdMap[$unionid], + 'work_userid' => $workUserid, + 'unionid' => $unionid, + ]; + } + } + + // 批量更新有好友关系的会员信息 + if (!empty($updateMembers)) { + $updateUserIds = array_column($updateMembers, 'user_id'); + + // 按 work_userid 分组,因为每个会员可能对应不同的导购 + foreach ($updateMembers as $memberInfo) { + $updateFilter = [ + 'company_id' => $companyId, + 'user_id' => $memberInfo['user_id'], + ]; + + $updateData = [ + 'is_become_friend' => 1, + 'has_fp' => 1, + 'fp_salesperson' => $memberInfo['work_userid'], + ]; + + $membersRepository->updateBy($updateFilter, $updateData); + } + + app('log')->info('批量更新会员注册分销商:更新会员好友关系成功', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'store_bn' => $storeBn, + 'updated_count' => count($updateMembers), + 'updated_user_ids' => $updateUserIds, + ]); + } else { + app('log')->warning('批量更新会员注册分销商:查询到好友关系但无法匹配到会员', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'store_bn' => $storeBn, + 'friend_data' => $friendCheckResult['data'], + ]); + } + } else { + app('log')->info('批量更新会员注册分销商:未查询到好友关系或接口返回异常', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'store_bn' => $storeBn, + 'result' => $friendCheckResult, + ]); + } + + // 6. 更新没有好友关系的会员(has_fp = 0) + // 只有当导购接口成功返回数据时,才计算差集并更新 + // 计算没有好友关系的 unionid(本次需要更新的 unionid - 导购返回的有好友关系的 unionid) + if (!empty($friendCheckResult) ) { + + // 只有导购接口成功返回时,才计算差集 + $noFriendUnionids = array_diff($unionids, $hasFriendUnionids); + + if (!empty($noFriendUnionids)) { + $noFriendUserIds = []; + foreach ($noFriendUnionids as $unionid) { + if (isset($unionidToUserIdMap[$unionid])) { + $noFriendUserIds[] = $unionidToUserIdMap[$unionid]; + } + } + + if (!empty($noFriendUserIds)) { + // 批量更新没有好友关系的会员 has_fp = 0 + $updateFilter = [ + 'company_id' => $companyId, + 'user_id' => $noFriendUserIds, + ]; + + $updateData = [ + 'has_fp' => 0, + ]; + + $noFriendResult = $membersRepository->updateBy($updateFilter, $updateData); + + app('log')->info('批量更新会员注册分销商:更新无好友关系会员', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'store_bn' => $storeBn, + 'updated_count' => count($noFriendUserIds), + 'updated_user_ids' => $noFriendUserIds, + 'affected_rows' => $noFriendResult, + ]); + } + } + } else { + app('log')->info('批量更新会员注册分销商:导购接口返回异常,不更新无好友关系会员', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'store_bn' => $storeBn, + 'result' => $friendCheckResult, + ]); + } + } else { + app('log')->warning('批量更新会员注册分销商:未找到会员unionid', [ + 'company_id' => $companyId, + 'user_ids' => $userIds, + ]); + } + } else { + app('log')->warning('批量更新会员注册分销商:未找到会员关联信息', [ + 'company_id' => $companyId, + 'user_ids' => $userIds, + ]); + } + } + } catch (\Exception $e) { + // 查询好友关系失败不影响主流程,只记录日志 + app('log')->error('批量更新会员注册分销商:查询门店导购好友关系失败', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'user_ids' => $userIds, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + } + + return $this->response->array([ + 'status' => true, + 'message' => '更新成功', + 'affected_rows' => $result, + ]); + } } diff --git a/src/MembersBundle/Http/FrontApi/V1/Action/Members.php b/src/MembersBundle/Http/FrontApi/V1/Action/Members.php index cca8871..c9c55a4 100644 --- a/src/MembersBundle/Http/FrontApi/V1/Action/Members.php +++ b/src/MembersBundle/Http/FrontApi/V1/Action/Members.php @@ -66,6 +66,7 @@ use PromotionsBundle\Services\SpecificCrowdDiscountService; use EspierBundle\Services\Config\ConfigRequestFieldsService; use ThirdPartyBundle\Services\DmCrm\MemberService as DmMemberService; use CompanysBundle\Services\SettingService as SelfdeliveryAddressService; +use WorkWechatBundle\Entities\WorkWechatRel; class Members extends Controller { @@ -1632,9 +1633,9 @@ class Members extends Controller $params['item_id'] = array_column($result['list'], 'item_id'); $itemsService = new ItemsService(); $itemList = $itemsService->getItemListData($params, 1, $pageSize); - $itemList = $itemsService->getItemsListMemberPrice($itemList, $authInfo['user_id'], $authInfo['company_id']); + $itemList['list'] = $itemsService->getItemsListMemberPrice($itemList['list'], $authInfo['user_id'], $authInfo['company_id']); //营销标签 - $itemList = $itemsService->getItemsListActityTag($itemList, $authInfo['company_id']); + $itemList['list'] = $itemsService->getItemsListActityTag($itemList['list'], $authInfo['company_id']); $itemList = array_column($itemList['list'], null, 'item_id'); foreach ($result['list'] as $key => $value) { if (isset($itemList[$value['item_id']])) { diff --git a/src/MembersBundle/Jobs/PushMemberTagRelationJob.php b/src/MembersBundle/Jobs/PushMemberTagRelationJob.php new file mode 100644 index 0000000..daa4c59 --- /dev/null +++ b/src/MembersBundle/Jobs/PushMemberTagRelationJob.php @@ -0,0 +1,109 @@ +companyId = $companyId; + $this->action = $action; + $this->relations = $relations; + } + + /** + * 执行任务 + */ + public function handle() + { + try { + app('log')->info('[PushMemberTagRelationJob] 开始推送', [ + 'company_id' => $this->companyId, + 'action' => $this->action, + 'total_count' => count($this->relations), + ]); + + // 分批推送(每批200条,避免单次请求数据过大) + $batches = array_chunk($this->relations, 200); + $totalBatches = count($batches); + + foreach ($batches as $index => $batch) { + $params = [ + 'company_id' => (string)$this->companyId, + 'action' => $this->action, + 'timestamp' => date('Y-m-d H:i:s'), + 'relations' => $batch, + ]; + + app('log')->info('[PushMemberTagRelationJob] 推送批次', [ + 'company_id' => $this->companyId, + 'batch' => $index + 1, + 'total_batches' => $totalBatches, + 'count' => count($batch), + ]); + + $request = new Request(); + $result = $request->call( + $this->companyId, + 'members.tag.relation.sync', + [$params] + ); + + app('log')->info('[PushMemberTagRelationJob] 批次推送完成', [ + 'company_id' => $this->companyId, + 'batch' => $index + 1, + 'total_batches' => $totalBatches, + 'count' => count($batch), + 'result' => $result, + ]); + + // 避免请求过快,批次之间间隔100ms + if ($totalBatches > 1 && $index < $totalBatches - 1) { + usleep(100000); // 100ms + } + } + + app('log')->info('[PushMemberTagRelationJob] 全部推送完成', [ + 'company_id' => $this->companyId, + 'action' => $this->action, + 'total_count' => count($this->relations), + 'batches' => $totalBatches, + ]); + + return true; + + } catch (\Exception $e) { + app('log')->error('[PushMemberTagRelationJob] 推送失败', [ + 'company_id' => $this->companyId, + 'action' => $this->action, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + + // 抛出异常,触发队列重试机制 + throw $e; + } + } +} + diff --git a/src/MembersBundle/Repositories/MemberSegmentRuleRepository.php b/src/MembersBundle/Repositories/MemberSegmentRuleRepository.php new file mode 100644 index 0000000..972fd34 --- /dev/null +++ b/src/MembersBundle/Repositories/MemberSegmentRuleRepository.php @@ -0,0 +1,252 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if (!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 查询条件 + */ + public function getOneBy($filter) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + return null; + } + return $this->getColumnNamesData($entity); + } + + /** + * 根据主键获取单条数据 + * + * @param $id + */ + public function getById($id) + { + $entity = $this->find($id); + if (!$entity) { + return null; + } + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + * + * @param $filter 查询条件 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count('.$this->prk.')') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } + + /** + * 根据条件获取列表数据 + * + * @param $filter 查询条件 + * @param $cols 查询字段 + * @param $page 页码 + * @param $pageSize 每页数量 + * @param $orderBy 排序 + */ + public function getLists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } else { + $qb->addOrderBy('created', 'DESC'); + } + if ($pageSize > 0) { + $offset = ($page - 1) * $pageSize; + $qb->setFirstResult($offset); + $qb->setMaxResults($pageSize); + } + return $qb->execute()->fetchAll(); + } + + /** + * 根据条件获取列表数据(带分页信息) + * + * @param $filter 查询条件 + * @param $cols 查询字段 + * @param $page 页码 + * @param $pageSize 每页数量 + * @param $orderBy 排序 + */ + public function lists($filter, $cols = '*', $page = 1, $pageSize = 20, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + $result['list'] = []; + if ($result['total_count'] > 0) { + $result['list'] = $this->getLists($filter, $cols, $page, $pageSize, $orderBy); + } + return $result; + } + + /** + * 设置实体字段数据 + * + * @param $entity + * @param $params + */ + private function setColumnNamesData($entity, $params) + { + foreach ($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + /** + * 获取实体字段数据 + * + * @param $entity + * @param $cols + * @param $ignore + */ + private function getColumnNamesData($entity, $cols = [], $ignore = []) + { + if (!$cols) { + $cols = $this->cols; + } + + $values = []; + foreach ($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + $value = $entity->$fun(); + + // 特殊处理 JSON 字段 + if ($col === 'rule_config' || $col === 'tag_ids') { + if (is_string($value)) { + $value = json_decode($value, true) ?: ($col === 'tag_ids' ? [] : []); + } + } + + $values[$col] = $value; + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param $filter + * @param $qb + */ + private function _filter($filter, $qb) + { + foreach ($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v, $k) = $list; + if ($k == 'contains') { + $k = 'like'; + $value = '%'.$value.'%'; + } + $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + continue; + } elseif (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } +} diff --git a/src/MembersBundle/Repositories/MemberTagGroupRelRepository.php b/src/MembersBundle/Repositories/MemberTagGroupRelRepository.php new file mode 100644 index 0000000..f6f9030 --- /dev/null +++ b/src/MembersBundle/Repositories/MemberTagGroupRelRepository.php @@ -0,0 +1,162 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if (!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach ($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(id)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } + + /** + * 根据条件获取列表数据 + */ + public function getLists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array('created' => 'DESC')) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + return $lists; + } + + private function setColumnNamesData($entity, $params) + { + foreach ($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols = [], $ignore = []) + { + if (!$cols) { + $cols = $this->cols; + } + + $values = []; + foreach ($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + $values[$col] = $entity->$fun(); + } + return $values; + } + + /** + * 筛选条件格式化 + */ + private function _filter($filter, $qb) + { + foreach ($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v, $k) = $list; + if ($k == 'contains') { + $k = 'like'; + $value = '%'.$value.'%'; + } + $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + continue; + } elseif (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } +} diff --git a/src/MembersBundle/Repositories/MemberTagGroupRepository.php b/src/MembersBundle/Repositories/MemberTagGroupRepository.php new file mode 100644 index 0000000..d98b451 --- /dev/null +++ b/src/MembersBundle/Repositories/MemberTagGroupRepository.php @@ -0,0 +1,207 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新数据表字段数据 + * + * @param $filter 更新的条件 + * @param $data 更新的内容 + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 根据主键删除指定数据 + * + * @param $id + */ + public function deleteById($id) + { + $entity = $this->find($id); + if (!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除指定数据 + * + * @param $filter 删除的条件 + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if (!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach ($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + /** + * 根据条件获取单条数据 + * + * @param $filter 更新的条件 + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计数量 + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count('.$this->prk.')') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } + + /** + * 根据条件获取列表数据 + */ + public function lists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array('created' => 'DESC')) + { + $result['total_count'] = $this->count($filter); + $result['list'] = []; + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + $result['list'] = $lists ?? []; + } + return $result; + } + + private function setColumnNamesData($entity, $params) + { + foreach ($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (method_exists($entity, $fun)) { + $entity->$fun($params[$col]); + } + } + } + return $entity; + } + + private function getColumnNamesData($entity, $cols = [], $ignore = []) + { + if (!$cols) { + $cols = $this->cols; + } + + $values = []; + foreach ($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + $values[$col] = $entity->$fun(); + } + return $values; + } + + /** + * 筛选条件格式化 + */ + private function _filter($filter, $qb) + { + foreach ($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v, $k) = $list; + if ($k == 'contains') { + $k = 'like'; + $value = '%'.$value.'%'; + } + $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + continue; + } elseif (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } +} diff --git a/src/MembersBundle/Repositories/MemberTagsRepository.php b/src/MembersBundle/Repositories/MemberTagsRepository.php index b7077d7..db8435f 100644 --- a/src/MembersBundle/Repositories/MemberTagsRepository.php +++ b/src/MembersBundle/Repositories/MemberTagsRepository.php @@ -90,6 +90,19 @@ class MemberTagsRepository extends EntityRepository $qb = $qb->set($key, $qb->expr()->literal($val)); } + if(isset($filter[$this->prk])){ + if(is_array($filter[$this->prk])){ + foreach ($filter[$this->prk] as $pprk){ + //更新数据 + $service = new MultiLangService(); + $service->updateLangData($data,$this->table,$pprk); + } + }else{ + $service = new MultiLangService(); + $service->updateLangData($data,$this->table,$filter[$this->prk]); + } + } + $qb = $this->_filter($filter, $qb); return $qb->execute(); @@ -124,8 +137,10 @@ class MemberTagsRepository extends EntityRepository return true; } $em = $this->getEntityManager(); + $service = new MultiLangService(); foreach ($entityList as $entityProp) { $em->remove($entityProp); + $service->deleteMultiLangByParams($entityProp->getTagId(),$this->table); $em->flush(); } return true; diff --git a/src/MembersBundle/Repositories/MembersRepository.php b/src/MembersBundle/Repositories/MembersRepository.php index 6520c7d..b2849a6 100644 --- a/src/MembersBundle/Repositories/MembersRepository.php +++ b/src/MembersBundle/Repositories/MembersRepository.php @@ -237,6 +237,12 @@ class MembersRepository extends EntityRepository 'disabled' => $userEntity->getDisabled(), 'remarks' => $userEntity->getRemarks(), 'third_data' => $userEntity->getThirdData(), + 'reg_distributor' => $userEntity->getRegDistributor(), + 'reg_salesperson' => $userEntity->getRegSalesperson(), + 'fp_salesperson' => $userEntity->getFpSalesperson(), + 'has_fp' => $userEntity->getHasFp(), + 'is_become_friend' => $userEntity->getIsBecomeFriend(), + 'op_distributor' => $userEntity->getOpDistributor(), ]; return $result; @@ -310,6 +316,24 @@ class MembersRepository extends EntityRepository if (isset($userData['third_data'])) { $userEntity->setThirdData($userData['third_data']); } + if (isset($userData['reg_distributor'])) { + $userEntity->setRegDistributor($userData['reg_distributor']); + } + if (isset($userData['reg_salesperson'])) { + $userEntity->setRegSalesperson($userData['reg_salesperson']); + } + if (isset($userData['fp_salesperson'])) { + $userEntity->setFpSalesperson($userData['fp_salesperson']); + } + if (isset($userData['has_fp'])) { + $userEntity->setHasFp($userData['has_fp']); + } + if (isset($userData['is_become_friend'])) { + $userEntity->setIsBecomeFriend($userData['is_become_friend']); + } + if (isset($userData['op_distributor'])) { + $userEntity->setOpDistributor($userData['op_distributor']); + } return $userEntity; } diff --git a/src/MembersBundle/Services/MemberSalespersonNotifyService.php b/src/MembersBundle/Services/MemberSalespersonNotifyService.php new file mode 100644 index 0000000..e0d6e57 --- /dev/null +++ b/src/MembersBundle/Services/MemberSalespersonNotifyService.php @@ -0,0 +1,189 @@ + true, + 'total_count' => 0, + 'success_count' => 0, + 'fail_count' => 0, + 'results' => [], + ]; + } + + // 获取会员信息,包括 op_distributor 和 unionid + $membersRepository = app('registry')->getManager('default')->getRepository(\MembersBundle\Entities\Members::class); + $members = $membersRepository->getList([ + 'company_id' => $companyId, + 'user_id' => $userIds, + ], 'user_id,op_distributor'); + + if (empty($members)) { + return [ + 'success' => true, + 'total_count' => 0, + 'success_count' => 0, + 'fail_count' => 0, + 'results' => [], + ]; + } + + // 获取会员的 unionid + $wechatUserService = new WechatUserService(); + $memberUnionids = []; + foreach ($members['list'] as $member) { + $unionid = $wechatUserService->getUnionidByUserId($member['user_id'], $companyId); + if ($unionid) { + $memberUnionids[$member['user_id']] = [ + 'unionid' => $unionid, + 'op_distributor' => $member['op_distributor'] ?? 0, + ]; + } + } + + if (empty($memberUnionids)) { + app('log')->info('通知导购端解绑会员:没有找到有效的unionid', [ + 'company_id' => $companyId, + 'user_ids' => $userIds, + ]); + return [ + 'success' => true, + 'total_count' => count($userIds), + 'success_count' => 0, + 'fail_count' => 0, + 'results' => [], + ]; + } + + // 按照 op_distributor 分组 + $groupedByDistributor = []; + foreach ($memberUnionids as $userId => $data) { + $distributorId = $data['op_distributor'] ?: 0; + if (!isset($groupedByDistributor[$distributorId])) { + $groupedByDistributor[$distributorId] = []; + } + $groupedByDistributor[$distributorId][] = $data['unionid']; + } + + // 使用统一的导购端接口调用方式 + $marketingCenterRequest = new MarketingCenterRequest(); + + // 获取门店信息 + $distributorService = new DistributorService(); + $allResults = []; + $totalSuccess = 0; + $totalFail = 0; + + // 按门店分组调用接口 + foreach ($groupedByDistributor as $distributorId => $unionids) { + if (empty($unionids)) { + continue; + } + + // 获取门店编号 + $storeBn = ''; + if ($distributorId > 0) { + $distributorInfo = $distributorService->getData([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + $storeBn = $distributorInfo['shop_code'] ?? ''; + } + + if (empty($storeBn) && $distributorId > 0) { + app('log')->warning('通知导购端解绑会员:门店编号不存在', [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + // 记录失败 + foreach ($unionids as $unionid) { + $allResults[] = [ + 'unionid' => $unionid, + 'success' => false, + 'error' => '门店编号不存在', + ]; + $totalFail++; + } + continue; + } + + // 调用导购端接口(使用统一的方式) + $params = [ + 'store_bn' => $storeBn, + 'unionids' => $unionids, + ]; + + $result = $marketingCenterRequest->call($companyId, 'members.unbindMembers', $params); + + // 处理结果 + if (!empty($result) && isset($result['errcode']) && $result['errcode'] == 0) { + $responseData = $result['data'] ?? []; + $responseResults = $responseData['results'] ?? []; + + foreach ($responseResults as $item) { + $allResults[] = [ + 'unionid' => $item['unionid'] ?? '', + 'success' => $item['success'] ?? false, + 'error' => $item['error'] ?? null, + ]; + if ($item['success'] ?? false) { + $totalSuccess++; + } else { + $totalFail++; + } + } + } else { + // 接口调用失败,记录所有 unionid 为失败 + $errorMsg = $result['errmsg'] ?? '接口调用失败'; + app('log')->warning('通知导购端解绑会员:接口调用失败', [ + 'company_id' => $companyId, + 'store_bn' => $storeBn, + 'unionids' => $unionids, + 'result' => $result, + ]); + foreach ($unionids as $unionid) { + $allResults[] = [ + 'unionid' => $unionid, + 'success' => false, + 'error' => $errorMsg, + ]; + $totalFail++; + } + } + } + + return [ + 'success' => $totalFail === 0, + 'total_count' => count($memberUnionids), + 'success_count' => $totalSuccess, + 'fail_count' => $totalFail, + 'results' => $allResults, + ]; + } + +} + diff --git a/src/MembersBundle/Services/MemberSegmentRuleService.php b/src/MembersBundle/Services/MemberSegmentRuleService.php new file mode 100644 index 0000000..ce2cd05 --- /dev/null +++ b/src/MembersBundle/Services/MemberSegmentRuleService.php @@ -0,0 +1,869 @@ +queryMemberType($subConditions, $totalCondition, $companyId, $distributorId); + break; + case 'order': + $userIds = $this->queryOrderType($subConditions, $totalCondition, $companyId, $distributorId); + break; + default: + throw new ResourceException("不支持的规则类型: {$type}"); + } + + $topTypeResults[] = $userIds; + } + + // 所有顶层类型的结果取交集(AND逻辑) + if (empty($topTypeResults)) { + return []; + } + + $result = $topTypeResults[0]; + for ($i = 1; $i < count($topTypeResults); $i++) { + $result = array_intersect($result, $topTypeResults[$i]); + } + + return array_values(array_unique($result)); + } + + /** + * 查询 member 类型 + * + * @param array $subConditions 子条件数组 + * @param array $totalCondition 总条件 + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function queryMemberType(array $subConditions, array $totalCondition, int $companyId, int $distributorId): array + { + $allUserIds = null; // 初始化为null,表示还没有处理任何条件 + + // 遍历子条件,每个子条件的结果取交集(AND逻辑) + foreach ($subConditions as $subCondition) { + $subType = $subCondition['type'] ?? ''; + $params = $subCondition['params'] ?? []; + + $userIds = []; + switch ($subType) { + case 'birthday': + $userIds = $this->queryBirthday($params, $companyId, $distributorId); + break; + case 'grade': + $userIds = $this->queryGrade($params, $companyId, $distributorId); + break; + case 'point': + $userIds = $this->queryPoint($params, $companyId, $distributorId); + break; + default: + continue 2; // 跳过不支持的子类型 + } + + // 第一个条件:直接赋值 + if ($allUserIds === null) { + $allUserIds = $userIds; + } else { + // 后续条件:与之前的结果取交集 + if (empty($userIds)) { + // 如果当前条件没有结果,交集为空 + $allUserIds = []; + } else { + // 取交集 + $allUserIds = array_intersect($allUserIds, $userIds); + } + } + } + + // 如果没有处理任何条件,返回空数组 + if ($allUserIds === null) { + return []; + } + + return array_values(array_unique($allUserIds)); + } + + /** + * 查询 order 类型 + * + * @param array $subConditions 子条件数组 + * @param array $totalCondition 总条件(订单时间范围) + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function queryOrderType(array $subConditions, array $totalCondition, int $companyId, int $distributorId): array + { + // 提取总条件中的时间范围 + $timeRange = []; + if (!empty($totalCondition) && isset($totalCondition[0])) { + $totalConditionItem = $totalCondition[0]; + if (isset($totalConditionItem['condition_type']) && $totalConditionItem['condition_type'] === 'timeRange') { + $timeRange = $totalConditionItem['params'] ?? []; + } + } + + if (empty($timeRange) || count($timeRange) < 2) { + throw new ResourceException('订单类型必须设置时间范围总条件'); + } + + $startTime = (int)$timeRange[0]; + $endTime = (int)$timeRange[1]; + + $allUserIds = null; // 初始化为null,表示还没有处理任何条件 + + // 遍历子条件,每个子条件的结果取交集(AND逻辑) + foreach ($subConditions as $subCondition) { + $subType = $subCondition['type'] ?? ''; + $params = $subCondition['params'] ?? []; + + $userIds = []; + switch ($subType) { + case 'perOrder': + $userIds = $this->queryPerOrder($params, $startTime, $endTime, $companyId, $distributorId); + break; + case 'sumaryOrder': + $userIds = $this->querySumaryOrder($params, $startTime, $endTime, $companyId, $distributorId); + break; + case 'orderItem': + $userIds = $this->queryOrderItem($params, $startTime, $endTime, $companyId, $distributorId); + break; + case 'hasOrder': + $userIds = $this->queryHasOrder($params, $startTime, $endTime, $companyId, $distributorId); + break; + default: + continue 2; // 跳过不支持的子类型 + } + + // 第一个条件:直接赋值 + if ($allUserIds === null) { + $allUserIds = $userIds; + } else { + // 后续条件:与之前的结果取交集 + if (empty($userIds)) { + // 如果当前条件没有结果,交集为空 + $allUserIds = []; + } else { + // 取交集 + $allUserIds = array_intersect($allUserIds, $userIds); + } + } + } + + // 如果没有处理任何条件,返回空数组 + if ($allUserIds === null) { + return []; + } + + return array_values(array_unique($allUserIds)); + } + + /** + * 查询生日条件 + * params: [start_timestamp, end_timestamp] + * + * @param array $params 参数:[开始时间戳, 结束时间戳] + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function queryBirthday(array $params, int $companyId, int $distributorId): array + { + if (count($params) < 2) { + return []; + } + + $startTimestamp = (int)$params[0]; + $endTimestamp = (int)$params[1]; + + // 将时间戳转换为日期格式(仅取月日) + $startDate = date('m-d', $startTimestamp); + $endDate = date('m-d', $endTimestamp); + + $conn = app('registry')->getConnection('default'); + + $sql = " + SELECT DISTINCT mi.user_id + FROM members_info mi + INNER JOIN members m ON mi.user_id = m.user_id + WHERE mi.company_id = :company_id + AND m.company_id = :company_id2 + "; + + $bindParams = [ + 'company_id' => $companyId, + 'company_id2' => $companyId, + ]; + + // 如果有分销商ID,需要关联分销商表 + if ($distributorId > 0) { + $sql .= " AND EXISTS ( + SELECT 1 FROM distribution_distributor_user ddu + WHERE ddu.user_id = m.user_id AND ddu.distributor_id = :distributor_id + )"; + $bindParams['distributor_id'] = $distributorId; + } + + // 生日范围查询(仅比较月日) + // birthday 字段格式可能是 "2020-09-10" 或 "09-10" + if ($startDate <= $endDate) { + // 正常范围,如 01-01 到 12-31 + $sql .= " AND ( + CASE + WHEN mi.birthday LIKE '%-%-%' THEN DATE_FORMAT(STR_TO_DATE(mi.birthday, '%Y-%m-%d'), '%m-%d') + ELSE mi.birthday + END BETWEEN :start_date AND :end_date + )"; + } else { + // 跨年范围,如 12-01 到 01-31 + $sql .= " AND ( + CASE + WHEN mi.birthday LIKE '%-%-%' THEN DATE_FORMAT(STR_TO_DATE(mi.birthday, '%Y-%m-%d'), '%m-%d') + ELSE mi.birthday + END >= :start_date + OR CASE + WHEN mi.birthday LIKE '%-%-%' THEN DATE_FORMAT(STR_TO_DATE(mi.birthday, '%Y-%m-%d'), '%m-%d') + ELSE mi.birthday + END <= :end_date + )"; + } + + $bindParams['start_date'] = $startDate; + $bindParams['end_date'] = $endDate; + + $stmt = $conn->prepare($sql); + foreach ($bindParams as $key => $value) { + $stmt->bindValue($key, $value); + } + + $result = $stmt->executeQuery()->fetchAllAssociative(); + return array_column($result, 'user_id'); + } + + /** + * 查询会员等级条件 + * params: [grade_id1, grade_id2, ...] + * + * @param array $params 参数:等级ID数组 + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function queryGrade(array $params, int $companyId, int $distributorId): array + { + if (empty($params) || !is_array($params)) { + return []; + } + + $gradeIds = array_map('intval', $params); + + $conn = app('registry')->getConnection('default'); + + $sql = " + SELECT DISTINCT m.user_id + FROM members m + WHERE m.company_id = :company_id + AND m.grade_id IN (:grade_ids) + "; + + $bindParams = [ + 'company_id' => $companyId, + ]; + + // 如果有分销商ID,需要关联分销商表 + if ($distributorId > 0) { + $sql .= " AND EXISTS ( + SELECT 1 FROM distribution_distributor_user ddu + WHERE ddu.user_id = m.user_id AND ddu.distributor_id = :distributor_id + )"; + $bindParams['distributor_id'] = $distributorId; + } + + $placeholders = []; + foreach ($gradeIds as $index => $gradeId) { + $key = 'grade_id_' . $index; + $placeholders[] = ':' . $key; + $bindParams[$key] = $gradeId; + } + $sql = str_replace(':grade_ids', implode(', ', $placeholders), $sql); + + $stmt = $conn->prepare($sql); + foreach ($bindParams as $key => $value) { + $stmt->bindValue($key, $value); + } + + $result = $stmt->executeQuery()->fetchAllAssociative(); + return array_column($result, 'user_id'); + } + + /** + * 查询积分条件 + * params: [min_point, max_point] + * + * @param array $params 参数:[最小积分, 最大积分] + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function queryPoint(array $params, int $companyId, int $distributorId): array + { + if (count($params) < 2) { + return []; + } + + $minPoint = (int)$params[0]; + $maxPoint = (int)$params[1]; + + $conn = app('registry')->getConnection('default'); + + // 直接拼接SQL,方便调试 + $companyId = (int)$companyId; + $minPoint = (int)$minPoint; + $maxPoint = (int)$maxPoint; + + $sql = " + SELECT DISTINCT pm.user_id + FROM point_member pm + INNER JOIN members m ON pm.user_id = m.user_id AND pm.company_id = m.company_id + WHERE pm.company_id = {$companyId} + AND pm.point >= {$minPoint} + AND pm.point <= {$maxPoint} + "; + + if ($distributorId > 0) { + $distributorId = (int)$distributorId; + $sql .= " AND EXISTS ( + SELECT 1 FROM distribution_distributor_user ddu + WHERE ddu.user_id = m.user_id AND ddu.distributor_id = {$distributorId} + )"; + } + + // 记录完整SQL,方便调试和直接执行 + app('log')->debug('queryPoint SQL (原生拼接)', [ + 'sql' => $sql, + ]); + + $result = $conn->fetchAllAssociative($sql); + return array_column($result, 'user_id'); + } + + /** + * 查询单笔金额条件 + * params: [min_amount, max_amount] (单位:分) + * + * @param array $params 参数:[最小金额, 最大金额](单位:分) + * @param int $startTime 开始时间戳 + * @param int $endTime 结束时间戳 + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function queryPerOrder(array $params, int $startTime, int $endTime, int $companyId, int $distributorId): array + { + if (count($params) < 2) { + return []; + } + + $minAmount = (int)$params[0] * 100; // 单位:分 + $maxAmount = (int)$params[1] * 100; // 单位:分 + + $conn = app('registry')->getConnection('default'); + + // 直接拼接SQL,方便调试 + $companyId = (int)$companyId; + $startTime = (int)$startTime; + $endTime = (int)$endTime; + $minAmount = (int)$minAmount; + $maxAmount = (int)$maxAmount; + + $sql = " + SELECT DISTINCT o.user_id + FROM orders_normal_orders o + WHERE o.company_id = {$companyId} + AND o.create_time >= {$startTime} + AND o.create_time <= {$endTime} + AND o.total_fee >= {$minAmount} + AND o.total_fee <= {$maxAmount} + AND o.pay_status = 'PAYED' + "; + + if ($distributorId > 0) { + $distributorId = (int)$distributorId; + $sql .= " AND o.distributor_id = {$distributorId}"; + } + + // 记录完整SQL,方便调试和直接执行 + app('log')->debug('queryPerOrder SQL (原生拼接)', [ + 'sql' => $sql, + + ]); + + $result = $conn->fetchAllAssociative($sql); + return array_column($result, 'user_id'); + } + + /** + * 查询累计金额条件 + * params: [min_amount, max_amount] (单位:分) + * + * @param array $params 参数:[最小金额, 最大金额](单位:分) + * @param int $startTime 开始时间戳 + * @param int $endTime 结束时间戳 + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function querySumaryOrder(array $params, int $startTime, int $endTime, int $companyId, int $distributorId): array + { + if (count($params) < 2) { + return []; + } + + $minAmount = (int)$params[0] * 100; // 单位:分 + $maxAmount = (int)$params[1] * 100; // 单位:分 + + $conn = app('registry')->getConnection('default'); + + $sql = " + SELECT o.user_id, SUM(CAST(o.total_fee AS UNSIGNED)) as total_amount + FROM orders_normal_orders o + WHERE o.company_id = :company_id + AND o.create_time >= :start_time + AND o.create_time <= :end_time + AND o.pay_status = 'PAYED' + "; + + $bindParams = [ + 'company_id' => $companyId, + 'start_time' => $startTime, + 'end_time' => $endTime, + ]; + + if ($distributorId > 0) { + $sql .= " AND o.distributor_id = :distributor_id"; + $bindParams['distributor_id'] = $distributorId; + } + + $sql .= " GROUP BY o.user_id + HAVING total_amount >= :min_amount AND total_amount <= :max_amount"; + + $bindParams['min_amount'] = $minAmount; + $bindParams['max_amount'] = $maxAmount; + + $stmt = $conn->prepare($sql); + foreach ($bindParams as $key => $value) { + $stmt->bindValue($key, $value); + } + + $result = $stmt->executeQuery()->fetchAllAssociative(); + return array_column($result, 'user_id'); + } + + /** + * 查询下单商品条件 + * params: [item_id1, item_id2, ...] + * + * @param array $params 参数:商品ID数组 + * @param int $startTime 开始时间戳 + * @param int $endTime 结束时间戳 + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function queryOrderItem(array $params, int $startTime, int $endTime, int $companyId, int $distributorId): array + { + if (empty($params) || !is_array($params)) { + return []; + } + + $itemIds = array_map('intval', $params); + + $conn = app('registry')->getConnection('default'); + + $sql = " + SELECT DISTINCT o.user_id + FROM orders_normal_orders o + INNER JOIN orders_normal_orders_items oi ON o.order_id = oi.order_id + WHERE o.company_id = :company_id + AND o.create_time >= :start_time + AND o.create_time <= :end_time + AND o.pay_status = 'PAYED' + "; + + $bindParams = [ + 'company_id' => $companyId, + 'start_time' => $startTime, + 'end_time' => $endTime, + ]; + + if ($distributorId > 0) { + $sql .= " AND o.distributor_id = :distributor_id"; + $bindParams['distributor_id'] = $distributorId; + } + + $placeholders = []; + foreach ($itemIds as $index => $itemId) { + $key = 'item_id_' . $index; + $placeholders[] = ':' . $key; + $bindParams[$key] = $itemId; + } + $sql .= " AND oi.item_id IN (" . implode(', ', $placeholders) . ")"; + + $stmt = $conn->prepare($sql); + foreach ($bindParams as $key => $value) { + $stmt->bindValue($key, $value); + } + + $result = $stmt->executeQuery()->fetchAllAssociative(); + return array_column($result, 'user_id'); + } + + /** + * 查询是否有下单条件 + * params: [1] 表示有下单,[0] 表示没下单 + * + * @param array $params 参数:[1] 有下单,[0] 没下单 + * @param int $startTime 开始时间戳 + * @param int $endTime 结束时间戳 + * @param int $companyId 公司ID + * @param int $distributorId 分销商ID + * @return array 用户ID数组 + */ + private function queryHasOrder(array $params, int $startTime, int $endTime, int $companyId, int $distributorId): array + { + if (empty($params) || !isset($params[0])) { + return []; + } + + $hasOrder = (int)$params[0]; // 1=有下单,0=没下单 + + $conn = app('registry')->getConnection('default'); + + if ($hasOrder == 1) { + // 有下单 + $sql = " + SELECT DISTINCT o.user_id + FROM orders_normal_orders o + WHERE o.company_id = :company_id + AND o.create_time >= :start_time + AND o.create_time <= :end_time + AND o.pay_status = 'PAYED' + "; + + $bindParams = [ + 'company_id' => $companyId, + 'start_time' => $startTime, + 'end_time' => $endTime, + ]; + + if ($distributorId > 0) { + $sql .= " AND o.distributor_id = :distributor_id"; + $bindParams['distributor_id'] = $distributorId; + } + } else { + // 没下单:所有会员减去有下单的会员 + $sql = " + SELECT DISTINCT m.user_id + FROM members m + WHERE m.company_id = :company_id + AND NOT EXISTS ( + SELECT 1 FROM orders_normal_orders o + WHERE o.user_id = m.user_id + AND o.company_id = :company_id2 + AND o.create_time >= :start_time + AND o.create_time <= :end_time + AND o.pay_status = 'PAYED' + "; + + $bindParams = [ + 'company_id' => $companyId, + 'company_id2' => $companyId, + 'start_time' => $startTime, + 'end_time' => $endTime, + ]; + + if ($distributorId > 0) { + $sql .= " AND o.distributor_id = :distributor_id"; + $bindParams['distributor_id'] = $distributorId; + } + + $sql .= " )"; + + if ($distributorId > 0) { + $sql .= " AND EXISTS ( + SELECT 1 FROM distribution_distributor_user ddu + WHERE ddu.user_id = m.user_id AND ddu.distributor_id = :distributor_id2 + )"; + $bindParams['distributor_id2'] = $distributorId; + } + } + + $stmt = $conn->prepare($sql); + foreach ($bindParams as $key => $value) { + $stmt->bindValue($key, $value); + } + + $result = $stmt->executeQuery()->fetchAllAssociative(); + return array_column($result, 'user_id'); + } + + /** + * 获取规则结构配置(给前端使用) + * + * @param int $companyId 公司ID + * @return array 规则结构配置 + */ + public function getRuleStructure(int $companyId): array + { + // 查询会员等级列表 + $gradeList = $this->getGradeList($companyId); + // 格式化为 {grade_id: 1, grade_name: "xxx"} 格式的数组 + $gradeMapValue = array_map(function($grade) { + return [ + 'id' => $grade['grade_id'], + 'name' => $grade['grade_name'] + ]; + }, $gradeList); + + return [ + [ + 'type' => 'member', + 'total_condition' => [], + 'sub' => [ + [ + 'type' => 'birthday', + 'lebel' => '生日', + 'condition_type' => 'timeRange' + ], + [ + 'type' => 'grade', + 'lebel' => '会员等级', + 'condition_type' => 'mapping', + 'map_value' => $gradeMapValue + ], + [ + 'type' => 'point', + 'lebel' => '会员积分', + 'condition_type' => 'number_rang', + 'unit' => '积分' + ] + ] + ], + [ + 'type' => 'order', + 'total_condition' => [ + [ + 'condition_type' => 'timeRange', + 'lebel' => '订单时间范围', + 'unit' => '' + ] + ], + 'sub' => [ + [ + 'type' => 'perOrder', + 'lebel' => '单笔金额', + 'condition_type' => 'number_rang', + 'unit' => '元' + ], + [ + 'type' => 'sumaryOrder', + 'lebel' => '累计金额', + 'condition_type' => 'number_rang', + 'map_value' => '元' + ], + [ + 'type' => 'orderItem', + 'lebel' => '下单商品', + 'condition_type' => 'number_items', + 'map_value' => '' + ], + [ + 'type' => 'hasOrder', + 'lebel' => '商城有下单', + 'condition_type' => 'radio', + 'map_value'=>[ + ['id'=>0,'name'=>'否','is_default'=>1], + ['id'=>1,'name'=>'是','is_default'=>0] + ] + ] + ] + ] + ]; + } + + /** + * 获取会员等级列表 + * + * @param int $companyId 公司ID + * @return array 会员等级列表,包含 grade_id 和 grade_name + */ + private function getGradeList(int $companyId): array + { + $memberCardGradeRepository = app('registry')->getManager('default')->getRepository(MemberCardGrade::class); + + // 使用 Repository 的方法获取等级列表(会自动处理多语言) + $gradeList = $memberCardGradeRepository->getListByCompanyId($companyId); + + // 提取 grade_id 和 grade_name + $result = []; + foreach ($gradeList as $grade) { + $result[] = [ + 'grade_id' => $grade['grade_id'] ?? $grade['gradeId'] ?? 0, + 'grade_name' => $grade['grade_name'] ?? $grade['gradeName'] ?? '' + ]; + } + + return $result; + } + + /** + * 获取人群圈选规则列表 + * + * @param array $params 查询参数 + * @return array 返回包含分页信息的规则列表 + */ + public function getSegmentRuleList(array $params): array + { + $companyId = $params['company_id'] ?? 0; + $operatorType = $params['operator_type'] ?? ''; + $distributorId = $params['distributor_id'] ?? 0; + + // 获取分页参数 + $page = (int)($params['page'] ?? 1); + $pageSize = (int)($params['page_size'] ?? 20); + + // 验证分页参数 + if ($page < 1) { + $page = 1; + } + if ($pageSize < 1 || $pageSize > 100) { + $pageSize = 20; + } + + // 构建查询条件 + $filter = [ + 'company_id' => $companyId, + ]; + + // 如果是分销商,只能查看自己的规则 + if ($operatorType == 'distributor') { + if ($distributorId) { + $filter['distributor_id'] = $distributorId; + } + } else { + // 如果传了 distributor_id,按 distributor_id 过滤 + $requestDistributorId = $params['request_distributor_id'] ?? null; + if ($requestDistributorId !== null && $requestDistributorId !== '') { + $filter['distributor_id'] = (int)$requestDistributorId; + } + } + + // 状态过滤 + if (isset($params['status']) && $params['status'] !== null && $params['status'] !== '') { + $filter['status'] = (int)$params['status']; + } + + // 规则名称模糊搜索(支持 rule_name 或 tag_name 参数) + if (!empty($params['tag_name'])) { + // 如果传了 tag_name,用它来搜索 rule_name + $filter['rule_name|contains'] = $params['tag_name']; + } elseif (!empty($params['rule_name'])) { + // 如果传了 rule_name,用它来搜索 rule_name + $filter['rule_name|contains'] = $params['rule_name']; + } + + // 创建时间范围查询 + if (!empty($params['created_start']) || !empty($params['created_end'])) { + if (!empty($params['created_start'])) { + // 将时间字符串转换为时间戳 + $createdStart = is_numeric($params['created_start']) ? (int)$params['created_start'] : strtotime($params['created_start']); + if ($createdStart) { + $filter['created|gte'] = $createdStart; + } + } + if (!empty($params['created_end'])) { + // 将时间字符串转换为时间戳 + $createdEnd = is_numeric($params['created_end']) ? (int)$params['created_end'] : strtotime($params['created_end']); + if ($createdEnd) { + // 如果是日期格式,设置为当天的23:59:59 + if (!is_numeric($params['created_end'])) { + $createdEnd = strtotime(date('Y-m-d', $createdEnd) . ' 23:59:59'); + } + $filter['created|lte'] = $createdEnd; + } + } + } + + // 排序:按创建时间倒序 + $orderBy = ['created' => 'DESC']; + + // 获取 Repository + $segmentRuleRepository = app('registry')->getManager('default')->getRepository(\MembersBundle\Entities\MemberSegmentRule::class); + + // 查询列表 + $result = $segmentRuleRepository->lists($filter, '*', $page, $pageSize, $orderBy); + + // 格式化返回数据 + $list = []; + foreach ($result['list'] as $item) { + $list[] = [ + 'rule_id' => $item['rule_id'], + 'rule_name' => $item['rule_name'], + 'description' => $item['description'] ?? '', + 'status' => $item['status'], + 'distributor_id' => $item['distributor_id'], + 'created' => date('Y-m-d H:i:s', $item['created']), + 'updated' => $item['updated'] ? date('Y-m-d H:i:s', $item['updated']) : '', + ]; + } + + return [ + 'total_count' => $result['total_count'], + 'page' => $page, + 'page_size' => $pageSize, + 'list' => $list, + ]; + } +} diff --git a/src/MembersBundle/Services/MemberService.php b/src/MembersBundle/Services/MemberService.php index dc27ef5..3101d53 100644 --- a/src/MembersBundle/Services/MemberService.php +++ b/src/MembersBundle/Services/MemberService.php @@ -148,6 +148,9 @@ class MemberService 'industry' => isset($params['industry']) ? $params['industry'] : null, 'birthday' => isset($params['birthday']) ? $params['birthday'] : null, 'edu_background' => isset($params['edu_background']) ? $params['edu_background'] : null, + 'reg_distributor' => isset($params['reg_distributor']) ? (int)$params['reg_distributor'] : 0, + 'reg_salesperson' => $params['reg_salesperson'] ?? '', + 'op_distributor' => isset($params['op_distributor']) ? (int)$params['op_distributor'] : 0, ]; if ($isUpdatePassword) { @@ -245,8 +248,8 @@ class MemberService $params['distributor_id'] = $shopRelSalesperson['shop_id']; app('log')->info('导购员信息 shopRelSalesperson===>'.json_encode($shopRelSalesperson) .':salesperson_id===>'.$salesperson['salesperson_id'] ); } - } - app('log')->info('导购员信息 salesperson===>'.json_encode($salesperson) .':work_userid===>'.$params['work_userid'] ); + } + app('log')->info('导购员信息 salesperson===>'.json_encode($salesperson) .':work_userid===>'.$params['work_userid'] ); } // 创建分销员数据 $promoterService = new PromoterService(); @@ -396,7 +399,7 @@ class MemberService if (!$dmMemberInfo) { throw new ResourceException('操作失败,请联系客服'); } - + $memberInfo = [ 'mobile' => $params['mobile'], 'region_mobile' => $params['region_mobile'] ?? '', @@ -619,7 +622,7 @@ class MemberService // 绑定达摩CRM会员 $dmMemberService->memberBind(['mobile' => $params['mobile']]); return $result; - + } /** @@ -744,7 +747,7 @@ class MemberService // 会员的等级变更使用数云,这里不做处理 return true; } - + // 达摩crm, 等级不处理 $ns = new DmCrmSettingService(); if ($ns->getDmCrmSetting($companyId)['is_open'] ?? '') { @@ -1199,7 +1202,7 @@ class MemberService $conn = app('registry')->getConnection('default'); - $mFields = "DISTINCT m.user_id,m.company_id,m.grade_id,m.mobile,m.user_card_code,m.authorizer_appid,m.wxa_appid,m.source_id,m.monitor_id,m.latest_source_id,m.latest_monitor_id,m.created,m.updated,m.created_year,m.created_month,m.created_day,m.offline_card_code,m.inviter_id,m.source_from,m.password,m.disabled,m.use_point,m.remarks,m.third_data,m.region_mobile,m.mobile_country_code,"; + $mFields = "DISTINCT m.user_id,m.company_id,m.grade_id,m.mobile,m.user_card_code,m.authorizer_appid,m.wxa_appid,m.source_id,m.monitor_id,m.latest_source_id,m.latest_monitor_id,m.created,m.updated,m.created_year,m.created_month,m.created_day,m.offline_card_code,m.inviter_id,m.source_from,m.password,m.disabled,m.use_point,m.remarks,m.third_data,m.region_mobile,m.mobile_country_code,m.reg_distributor,m.reg_salesperson,m.fp_salesperson,m.has_fp,m.op_distributor,"; $row = $mFields . 'info.username,info.name,info.sex,info.birthday,info.address,info.email,info.industry,info.income,info.edu_background,info.habbit,info.avatar'; $criteria = $conn->createQueryBuilder(); @@ -1220,6 +1223,11 @@ class MemberService $criteria->leftJoin('m', 'members_rel_tags', 'reltags', 'reltags.user_id = m.user_id'); } + // 积分查询需要关联 point_member 表 + if (isset($filter['point|gte']) || isset($filter['point|lte']) || isset($filter['point'])) { + $criteria->leftJoin('m', 'point_member', 'pm', 'pm.user_id = m.user_id AND pm.company_id = m.company_id'); + } + $this->_filter($filter, $criteria); $commonKey = ['company_id', 'user_id', 'created', 'updated', 'created_month', 'created_day', 'created_year']; @@ -1346,7 +1354,7 @@ class MemberService ->from('members', 'm'); //判断是否存在 members_info 的搜索条件 - if (isset($filter['have_consume']) or isset($filter['username'])) { + if (isset($filter['have_consume']) or isset($filter['username']) or isset($filter['birthday|gte']) or isset($filter['birthday|lte']) or isset($filter['birthday'])) { $criteria->leftJoin('m', 'members_info', 'info', 'info.user_id = m.user_id'); } @@ -1495,23 +1503,39 @@ class MemberService **/ if (isset($filter['tag_id']) && $filter['tag_id']) { - $criteria->andWhere($criteria->expr()->eq('reltags.tag_id', $criteria->expr()->literal($filter['tag_id']))); + // 如果 tag_id 是数组,使用 in 查询;否则使用 eq 查询 + if (is_array($filter['tag_id'])) { + $tagIds = array_map(function($id) use ($criteria) { + return $criteria->expr()->literal($id); + }, $filter['tag_id']); + $criteria->andWhere($criteria->expr()->in('reltags.tag_id', $tagIds)); + } else { + $criteria->andWhere($criteria->expr()->eq('reltags.tag_id', $criteria->expr()->literal($filter['tag_id']))); + } + unset($filter['tag_id']); } unset($filter['distributor_id']); unset($filter['shop_id']); - unset($filter['tag_id']); //好像没什么用? //$criteria->andWhere($criteria->expr()->isNotNull('m.mobile')); //$criteria->andWhere($criteria->expr()->isNotNull('m.user_card_code')); if ($filter) { - $commonKey = ['company_id', 'user_id', 'created', 'updated', 'created_month', 'created_day', 'created_year', 'remarks', 'mobile']; + $commonKey = ['company_id', 'user_id', 'created', 'updated', 'created_month', 'created_day', 'created_year', 'remarks', 'mobile', 'birthday', 'fp_salesperson', 'has_fp', 'grade_id', 'op_distributor']; foreach ($filter as $field => $value) { $list = explode('|', $field); if (count($list) > 1) { list($v, $k) = $list; - $v = in_array($v, $commonKey) ? 'm.' . $v : $v; + // birthday 字段在 members_info 表中,使用 info.birthday + if ($v == 'birthday') { + $v = 'info.' . $v; + } elseif ($v == 'point') { + // point 字段在 point_member 表中,使用 pm.point + $v = 'pm.' . $v; + } else { + $v = in_array($v, $commonKey) ? 'm.' . $v : $v; + } if (in_array($k, ['like', 'notlike'])) { $criteria->andWhere($criteria->expr()->$k($v, $criteria->expr()->literal('%' . $value . '%'))); } elseif (in_array($k, ['in', 'notIn'])) { @@ -1521,10 +1545,19 @@ class MemberService } continue; } elseif (in_array($field, $commonKey)) { - if (is_array($value)) { - $criteria->andWhere($criteria->expr()->in('m.' . $field, $value)); + // birthday 字段在 members_info 表中,使用 info.birthday + if ($field == 'birthday') { + if (is_array($value)) { + $criteria->andWhere($criteria->expr()->in('info.' . $field, $value)); + } else { + $criteria->andWhere($criteria->expr()->eq('info.' . $field, $criteria->expr()->literal($value))); + } } else { - $criteria->andWhere($criteria->expr()->eq('m.' . $field, $criteria->expr()->literal($value))); + if (is_array($value)) { + $criteria->andWhere($criteria->expr()->in('m.' . $field, $value)); + } else { + $criteria->andWhere($criteria->expr()->eq('m.' . $field, $criteria->expr()->literal($value))); + } } } else { $criteria->andWhere($criteria->expr()->eq('m.' . $field, $criteria->expr()->literal($value))); @@ -1570,7 +1603,23 @@ class MemberService if (isset($filter['tag_id']) && $filter['tag_id']) { $criteria->leftJoin('m', 'members_rel_tags', 'reltags', 'reltags.user_id = m.user_id'); + // 如果 tag_id 是数组,使用 in 查询;否则使用 eq 查询 + if (is_array($filter['tag_id'])) { + $tagIds = array_map(function($id) use ($criteria) { + return $criteria->expr()->literal($id); + }, $filter['tag_id']); + $criteria->andWhere($criteria->expr()->in('reltags.tag_id', $tagIds)); + } else { + $criteria->andWhere($criteria->expr()->eq('reltags.tag_id', $criteria->expr()->literal($filter['tag_id']))); + } + unset($filter['tag_id']); } + + // 积分查询需要关联 point_member 表 + if (isset($filter['point|gte']) || isset($filter['point|lte']) || isset($filter['point'])) { + $criteria->leftJoin('m', 'point_member', 'pm', 'pm.user_id = m.user_id AND pm.company_id = m.company_id'); + } + $this->_filter($filter, $criteria); $count = $criteria->execute()->fetchColumn(); @@ -2371,4 +2420,309 @@ class MemberService throw new ResourceException(trans('MembersBundle/Members.logout_failed')); } } + + /** + * 批量查询会员的绑定导购和绑定门店 + * + * @param int $companyId 公司ID + * @param array &$memberList 会员列表(引用传递,会直接修改数组) + * @return array 返回查询结果 + */ + public function batchGetBindSalesperson($companyId, &$memberList) + { + if (empty($memberList)) { + return []; + } + + try { + // 获取会员的 user_id 列表 + $userIds = array_column($memberList, 'user_id'); + + // 批量获取会员的 unionid + $unionidMap = []; // user_id => unionid + $membersAssocRepository = app('registry')->getManager('default')->getRepository(MembersAssociations::class); + $filter = [ + 'user_id' => $userIds, + 'company_id' => $companyId, + 'user_type' => 'wechat', + ]; + $associations = $membersAssocRepository->lists($filter, 'user_id,unionid'); + if (!empty($associations['list'])) { + foreach ($associations['list'] as $assoc) { + if (!empty($assoc['unionid'])) { + $unionidMap[$assoc['user_id']] = $assoc['unionid']; + } + } + } + + // 构建批量请求数据 + $batchData = []; + foreach ($memberList as $index => $member) { + $requestItem = []; + $userId = $member['user_id']; + + // 优先使用 unionid,如果没有则使用 external_member_id (user_id) + if (!empty($unionidMap[$userId])) { + $requestItem['unionid'] = $unionidMap[$userId]; + } else { + $requestItem['external_member_id'] = (string)$userId; + } + + $batchData[] = $requestItem; + } + + if (empty($batchData)) { + app('log')->info('[MemberService] 批量查询绑定导购:无有效数据', [ + 'company_id' => $companyId, + 'member_count' => count($memberList), + ]); + return []; + } + + // 调用导购平台批量查询接口 + $request = new MarketingCenterRequest(); + + app('log')->info('[MemberService] 批量查询绑定导购:开始请求', [ + 'company_id' => $companyId, + 'batch_count' => count($batchData), + 'request_data' => $batchData, + ]); + + // call 方法会自动将 $batchData 放到 data 字段,method 会作为第二个参数传入 + $result = $request->call($companyId, 'basics.member.getBindSalespersonBatch', $batchData); + + app('log')->info('[MemberService] 批量查询绑定导购:返回结果', [ + 'company_id' => $companyId, + 'result' => $result, + 'result_structure' => [ + 'errcode' => $result['errcode'] ?? null, + 'errmsg' => $result['errmsg'] ?? null, + 'data' => [ + 'success' => $result['data']['success'] ?? null, + 'total' => $result['data']['total'] ?? null, + 'success_count' => $result['data']['success_count'] ?? null, + 'fail_count' => $result['data']['fail_count'] ?? null, + 'results_count' => isset($result['data']['results']) ? count($result['data']['results']) : 0, + ], + ], + ]); + + // 将结果匹配到会员列表上 + if (!empty($result['data']['results']) && is_array($result['data']['results'])) { + $matchedCount = 0; + foreach ($result['data']['results'] as $item) { + $requestIndex = $item['request_index'] ?? null; + + // 根据 request_index 匹配到对应的会员 + if ($requestIndex !== null && isset($memberList[$requestIndex])) { + $salespersonData = $item['data'] ?? []; + + // 添加绑定导购信息 + $memberList[$requestIndex]['salesperson_info'] = [ + 'salesperson_id' => $salespersonData['salesperson_id'] ?? null, + 'work_userid' => $salespersonData['work_userid'] ?? '', + 'member_id' => $salespersonData['member_id'] ?? null, + 'external_member_type' => $salespersonData['external_member_type'] ?? null, + 'external_userid' => $salespersonData['external_userid'] ?? '', + 'suite_external_userid' => $salespersonData['suite_external_userid'] ?? '', + 'unionid' => $salespersonData['unionid'] ?? '', + 'member_status' => $salespersonData['member_status'] ?? null, + 'bind_status' => $salespersonData['bind_status'] ?? null, + 'bind_time' => $salespersonData['bind_time'] ?? null, + 'bind_cancel_time' => $salespersonData['bind_cancel_time'] ?? null, + 'friend_status' => $salespersonData['friend_status'] ?? null, + 'become_friend_time' => $salespersonData['become_friend_time'] ?? null, + 'employee_number' => $salespersonData['employee_number'] ?? '', + ]; + + // 添加绑定门店信息 + $memberList[$requestIndex]['store_info'] = [ + 'store_bn' => $salespersonData['store_bn'] ?? '', + 'store_name' => $salespersonData['store_name'] ?? '', + ]; + + $matchedCount++; + } else { + app('log')->warning('[MemberService] 批量查询绑定导购:无法匹配会员', [ + 'company_id' => $companyId, + 'request_index' => $requestIndex, + 'member_list_count' => count($memberList), + ]); + } + } + + app('log')->info('[MemberService] 批量查询绑定导购:匹配完成', [ + 'company_id' => $companyId, + 'matched_count' => $matchedCount, + 'total_results' => count($result['data']['results']), + ]); + } else { + app('log')->info('[MemberService] 批量查询绑定导购:无返回结果', [ + 'company_id' => $companyId, + ]); + } + + return $result; + + } catch (\Exception $e) { + app('log')->error('[MemberService] 批量查询绑定导购失败', [ + 'company_id' => $companyId, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + return []; + } + } + + /** + * 根据导购编号或门店编号获取绑定的会员ID列表 + * + * @param int $companyId 公司ID + * @param string|null $employeeNumber 导购编号(与storeBn二选一) + * @param string|null $storeBn 门店编号(与employeeNumber二选一) + * @return array 返回会员ID数组(user_id),如果查询失败或没有结果返回空数组 + */ + public function getBindMemberIdsBySalesperson(int $companyId, ?string $employeeNumber = null, ?string $storeBn = null): array + { + // 参数验证:必须提供 employee_number 或 store_bn 之一 + if (empty($employeeNumber) && empty($storeBn)) { + app('log')->warning('[MemberService] 获取绑定会员ID:参数错误,必须提供employee_number或store_bn', [ + 'company_id' => $companyId, + ]); + return []; + } + + $requestData = []; + if (!empty($employeeNumber)) { + $requestData['employee_number'] = $employeeNumber; + } + if (!empty($storeBn)) { + $requestData['store_bn'] = $storeBn; + } + + try { + $marketingCenterRequest = new MarketingCenterRequest(); + + app('log')->info('[MemberService] 获取绑定会员ID:开始请求', [ + 'company_id' => $companyId, + 'request_data' => $requestData, + ]); + + $bindResult = $marketingCenterRequest->call($companyId, 'basics.salesperson.getBindMembers', $requestData); + + app('log')->info('[MemberService] 获取绑定会员ID:返回结果', [ + 'company_id' => $companyId, + 'result' => [ + 'errcode' => $bindResult['errcode'] ?? null, + 'errmsg' => $bindResult['errmsg'] ?? null, + 'member_count' => isset($bindResult['data']['member_ids']) ? count($bindResult['data']['member_ids']) : 0, + ], + ]); + + $bindMemberIds = []; + if (isset($bindResult['data']['member_ids']) && is_array($bindResult['data']['member_ids'])) { + // 将字符串类型的 member_id 转换为整数类型的 user_id + $bindMemberIds = array_map('intval', $bindResult['data']['member_ids']); + $bindMemberIds = array_filter($bindMemberIds); // 过滤掉0值 + $bindMemberIds = array_values($bindMemberIds); // 重新索引数组 + } + + return $bindMemberIds; + + } catch (\Exception $e) { + app('log')->error('[MemberService] 获取绑定会员ID失败', [ + 'company_id' => $companyId, + 'request_data' => $requestData, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + return []; + } + } + + /** + * 导购通知加好友 + * 当导购端通知云店,已分配的客户已经加导购为好友时,更新会员的 is_become_friend 状态 + * + * @param int $companyId 公司ID + * @param string $unionid 会员unionid + * @param string $salespersonCode 导购编号(employee_number) + * @return array 返回结果 ['success' => bool, 'message' => string, 'is_already_friend' => bool] + * @throws Exception + */ + public function notifyBecomeFriend(int $companyId, string $unionid, string $salespersonCode): array + { + app('log')->info('[MemberService] 导购通知加好友:开始处理', [ + 'company_id' => $companyId, + 'unionid' => $unionid, + 'salesperson_code' => $salespersonCode, + ]); + + // 1. 根据 unionid 查找会员关联信息 + $membersAssociationsRepository = app('registry')->getManager('default')->getRepository(MembersAssociations::class); + $association = $membersAssociationsRepository->get([ + 'unionid' => $unionid, + 'company_id' => $companyId, + 'user_type' => 'wechat' + ]); + + if (!$association) { + app('log')->warning('[MemberService] 导购通知加好友:未找到会员 unionid=' . $unionid . ':companyId=' . $companyId); + throw new Exception('会员不存在'); + } + + $userId = $association['user_id']; + + // 2. 获取会员信息 + $member = $this->membersRepository->find($userId); + + if (!$member) { + app('log')->warning('[MemberService] 导购通知加好友:未找到会员记录 user_id=' . $userId); + throw new Exception('会员不存在'); + } + + // 3. 验证会员是否已分配给该导购(bind_status = 1) + // fp_salesperson 存储的是 employee_number(导购编号),类型为字符串 + // 检查会员是否已分配给该导购 + if ($member->getHasFp() != 1 || (string)$member->getFpSalesperson() != (string)$salespersonCode) { + app('log')->warning('[MemberService] 导购通知加好友:会员未分配给该导购', [ + 'user_id' => $userId, + 'salesperson_code' => $salespersonCode, + 'has_fp' => $member->getHasFp(), + 'fp_salesperson' => $member->getFpSalesperson(), + ]); + throw new Exception('该会员未分配给该导购'); + } + + // 4. 幂等性检查:如果已经是好友状态,直接返回成功 + if ($member->getIsBecomeFriend() == 1) { + app('log')->info('[MemberService] 导购通知加好友:幂等性检查通过,已是好友状态', [ + 'user_id' => $userId, + 'salesperson_code' => $salespersonCode, + ]); + return [ + 'success' => true, + 'message' => '已是好友状态', + 'is_already_friend' => true, + ]; + } + + // 5. 更新 is_become_friend = 1 + $member->setIsBecomeFriend(1); + + $em = app('registry')->getManager('default'); + $em->persist($member); + $em->flush(); + + app('log')->info('[MemberService] 导购通知加好友:更新成功', [ + 'user_id' => $userId, + 'salesperson_code' => $salespersonCode, + ]); + + return [ + 'success' => true, + 'message' => '更新成功', + 'is_already_friend' => false, + ]; + } } diff --git a/src/MembersBundle/Services/MemberTagRelationPushService.php b/src/MembersBundle/Services/MemberTagRelationPushService.php new file mode 100644 index 0000000..1d8b02f --- /dev/null +++ b/src/MembersBundle/Services/MemberTagRelationPushService.php @@ -0,0 +1,235 @@ +getMemberInfo($companyId, $userIds); + + if (empty($members)) { + app('log')->warning('[MemberTagRelationPush] 未找到会员信息', [ + 'company_id' => $companyId, + 'user_ids' => $userIds, + ]); + return ['success' => true, 'message' => '未找到会员信息']; + } + + // 2. 获取标签信息 + $tags = $this->getTagInfo($companyId, $tagIds); + + if (empty($tags)) { + app('log')->warning('[MemberTagRelationPush] 未找到标签信息', [ + 'company_id' => $companyId, + 'tag_ids' => $tagIds, + ]); + return ['success' => true, 'message' => '未找到标签信息']; + } + + // 3. 构建推送数据 + $relations = []; + + foreach ($members as $member) { + foreach ($tags as $tag) { + $relations[] = [ + 'user_id' => (string)$member['user_id'], + 'mobile' => $member['mobile'] ?? '', + 'tag_id' => (string)$tag['tag_id'], + 'tag_name' => $tag['tag_name'], + 'tag_type' => $this->getTagType($tag['source']), + 'wechat_tag_id' => $tag['wechat_tag_id'] ?? null, + ]; + } + } + + + if (empty($relations)) { + app('log')->warning('[MemberTagRelationPush] 没有需要推送的数据', [ + 'company_id' => $companyId, + 'user_ids' => $userIds, + 'tag_ids' => $tagIds, + ]); + return ['success' => true, 'message' => '没有需要推送的数据']; + } + + // 4. 判断推送方式:≤50条同步,>50条异步 + $totalCount = count($relations); + if ($totalCount <= 50) { + // 同步推送 + return $this->syncPush($companyId, $action, $relations); + } else { + // 异步推送 + return $this->asyncPush($companyId, $action, $relations); + } + + } catch (\Exception $e) { + app('log')->error('[MemberTagRelationPush] 推送失败', [ + 'company_id' => $companyId, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + return ['success' => false, 'message' => $e->getMessage()]; + } + } + + /** + * 同步推送 + * + * @param int $companyId 公司ID + * @param string $action 操作类型 + * @param array $relations 标签关系数据 + * @return array + */ + private function syncPush(int $companyId, string $action, array $relations): array + { + $params = [ + 'company_id' => (string)$companyId, + 'action' => $action, + 'timestamp' => date('Y-m-d H:i:s'), + 'relations' => $relations, + ]; + + app('log')->info('[MemberTagRelationPush] 同步推送', [ + 'company_id' => $companyId, + 'action' => $action, + 'count' => count($relations), + ]); + + $request = new Request(); + $result = $request->call($companyId, 'members.tag.relation.sync', [$params]); + + app('log')->info('[MemberTagRelationPush] 同步推送完成', [ + 'company_id' => $companyId, + 'result' => $result, + ]); + + return [ + 'success' => true, + 'mode' => 'sync', + 'result' => $result, + ]; + } + + /** + * 异步推送 + * + * @param int $companyId 公司ID + * @param string $action 操作类型 + * @param array $relations 标签关系数据 + * @return array + */ + private function asyncPush(int $companyId, string $action, array $relations): array + { + app('log')->info('[MemberTagRelationPush] 异步推送', [ + 'company_id' => $companyId, + 'action' => $action, + 'count' => count($relations), + ]); + + // 推入队列 + $job = new PushMemberTagRelationJob( + $companyId, + $action, + $relations + ); + $job->onQueue('marketing'); + app('Illuminate\Contracts\Bus\Dispatcher')->dispatch($job); + + return [ + 'success' => true, + 'mode' => 'async', + 'message' => '已加入推送队列', + ]; + } + + /** + * 获取会员信息 + * + * @param int $companyId 公司ID + * @param array $userIds 会员ID列表 + * @return array + */ + private function getMemberInfo(int $companyId, array $userIds): array + { + $em = app('registry')->getManager('default'); + $qb = $em->createQueryBuilder(); + + // 转换为 literal 防止SQL注入 + array_walk($userIds, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + + $qb->select('m.user_id', 'm.mobile') + ->from('MembersBundle\Entities\Members', 'm') + ->where('m.company_id = :company_id') + ->andWhere($qb->expr()->in('m.user_id', $userIds)) + ->setParameter('company_id', $companyId); + + return $qb->getQuery()->getResult(); + } + + /** + * 获取标签信息(过滤掉企业微信标签) + * + * @param int $companyId 公司ID + * @param array $tagIds 标签ID列表 + * @return array + */ + private function getTagInfo(int $companyId, array $tagIds): array + { + $em = app('registry')->getManager('default'); + $qb = $em->createQueryBuilder(); + + // 转换为 literal 防止SQL注入 + array_walk($tagIds, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + + $qb->select('t.tag_id', 't.tag_name', 't.source', 't.wechat_tag_id') + ->from(MemberTags::class, 't') + ->where('t.company_id = :company_id') + ->andWhere($qb->expr()->in('t.tag_id', $tagIds)) + ->setParameter('company_id', $companyId); + + + return $qb->getQuery()->getResult(); + } + + /** + * 转换标签类型 + * + * @param string $source 标签来源 + * @return string 标签类型 + */ + private function getTagType(string $source): string + { + $typeMap = [ + 'self' => 'self', // 自定义标签 + 'wechat' => 'wechat', // 企业微信标签 + 'staff' => 'staff', // 员工标签 + ]; + + return $typeMap[$source] ?? 'self'; + } +} + diff --git a/src/MembersBundle/Services/MemberTagsService.php b/src/MembersBundle/Services/MemberTagsService.php index 47af900..6e10ba3 100644 --- a/src/MembersBundle/Services/MemberTagsService.php +++ b/src/MembersBundle/Services/MemberTagsService.php @@ -19,6 +19,8 @@ namespace MembersBundle\Services; use MembersBundle\Entities\MemberTags; use MembersBundle\Entities\MemberRelTags; +use MembersBundle\Entities\MemberTagGroup; +use MembersBundle\Entities\MemberTagGroupRel; use Dingo\Api\Exception\ResourceException; use MembersBundle\Services\MemberService; @@ -28,6 +30,8 @@ class MemberTagsService { public $entityRepository; public $memberRelTags; + public $tagGroupRepository; + public $tagGroupRelRepository; /** * MemberService 构造函数. */ @@ -35,6 +39,8 @@ class MemberTagsService { $this->entityRepository = app('registry')->getManager('default')->getRepository(MemberTags::class); $this->memberRelTags = app('registry')->getManager('default')->getRepository(MemberRelTags::class); + $this->tagGroupRepository = app('registry')->getManager('default')->getRepository(MemberTagGroup::class); + $this->tagGroupRelRepository = app('registry')->getManager('default')->getRepository(MemberTagGroupRel::class); } public function getListTags($filter, $page = 1, $limit = 100, $orderBy = ['created' => 'DESC']) @@ -128,10 +134,11 @@ class MemberTagsService * @param $tagIds * @param $companyId * @param bool $forceCreate true表示强制创建 + * @param bool $skipPush true表示跳过推送到导购平台(用于导购同步标签到本地时避免循环) * @return bool * @throws Exception */ - public function createRelTags($userIds, $tagIds, $companyId, $forceCreate = false) + public function createRelTags($userIds, $tagIds, $companyId, $forceCreate = false, $skipPush = false) { $conn = app('registry')->getConnection('default'); $conn->beginTransaction(); @@ -150,6 +157,29 @@ class MemberTagsService } } $conn->commit(); + + // 推送标签关系到导购平台(如果不需要跳过推送) + if (!$skipPush) { + try { + $pushService = new MemberTagRelationPushService(); + $pushService->pushTagRelations($companyId, $userIds, $tagIds, 'add'); + } catch (\Exception $e) { + // 推送失败不影响主流程,只记录日志 + app('log')->warning('[createRelTags] 推送导购平台失败', [ + 'company_id' => $companyId, + 'user_ids' => $userIds, + 'tag_ids' => $tagIds, + 'error' => $e->getMessage(), + ]); + } + } else { + app('log')->info('[createRelTags] 跳过推送到导购平台', [ + 'company_id' => $companyId, + 'user_ids' => $userIds, + 'tag_ids' => $tagIds, + ]); + } + return true; } catch (\Exception $e) { $conn->rollback(); @@ -212,6 +242,43 @@ class MemberTagsService } } + /** + * 删除指定会员的所有标签 + * + * @param int $userId 会员ID + * @param int $companyId 公司ID + * @return bool + * @throws \Exception + */ + public function deleteRelTagsByUserId($userId, $companyId) + { + $savedata['user_id'] = $userId; + $savedata['company_id'] = $companyId; + + try { + // 查找该会员的所有标签关系 + $relations = $this->memberRelTags->lists($savedata); + + if (isset($relations['list']) && !empty($relations['list'])) { + foreach ($relations['list'] as $relation) { + $tagData = [ + 'tag_id' => $relation['tag_id'], + 'company_id' => $companyId, + ]; + // 标签数量-1 + $this->tagCountReduce($tagData); + } + + // 删除所有标签关系 + $this->memberRelTags->deleteBy($savedata); + } + + return true; + } catch (\Exception $e) { + throw $e; + } + } + /** * 单一标签关联多会员 */ @@ -249,7 +316,25 @@ class MemberTagsService $savedata['user_id'] = $userId; // 标签数量-1 $this->tagCountReduce($savedata); - return $this->memberRelTags->deleteBy($savedata); + $result = $this->memberRelTags->deleteBy($savedata); + + // 推送标签删除关系到导购平台 + if ($result) { + try { + $pushService = new MemberTagRelationPushService(); + $pushService->pushTagRelations($companyId, [$userId], [$tagId], 'remove'); + } catch (\Exception $e) { + // 推送失败不影响主流程,只记录日志 + app('log')->warning('[delRelMemberTag] 推送导购平台失败', [ + 'company_id' => $companyId, + 'user_id' => $userId, + 'tag_id' => $tagId, + 'error' => $e->getMessage(), + ]); + } + } + + return $result; } @@ -414,6 +499,555 @@ class MemberTagsService return array_values($result); } + /** + * 创建标签组并关联标签。 + * - 首次创建标签组时,如果已有标签则先自动生成一个默认组并关联所有现有标签 + * - 然后再创建本次提交的标签组并绑定传入的标签 + * + * @param array $params + * @return array + * @throws \Exception + */ + public function createTagGroup(array $params) + { + if (empty($params['group_name'])) { + throw new ResourceException('标签组名称不能为空'); + } + $companyId = $params['company_id'] ?? 0; + $distributorId = $params['distributor_id'] ?? 0; + $tagIds = isset($params['tag_ids']) ? (array)$params['tag_ids'] : []; + $tagIds = array_values(array_unique(array_filter($tagIds))); + + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + try { + // 首次创建时,如果已有标签则自动创建默认分组并关联现有标签 + $existingGroupCount = $this->tagGroupRepository->count([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + if ($existingGroupCount === 0) { + $allTags = $this->entityRepository->getLists([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ], 'tag_id'); + if ($allTags) { + $defaultTagIds = array_column($allTags, 'tag_id'); + if ($defaultTagIds) { + $defaultGroup = $this->tagGroupRepository->create([ + 'group_name' => '默认标签组', + 'description' => '系统自动创建,包含当前全部标签', + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + $this->bindTagsToGroup($defaultGroup['group_id'], $defaultTagIds, $companyId, $distributorId); + } + } + } + + // 创建本次提交的标签组 + $group = $this->tagGroupRepository->create([ + 'group_name' => $params['group_name'], + 'description' => $params['description'] ?? '', + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + + if ($tagIds) { + // 只绑定当前企业下存在的标签 + $validTags = $this->entityRepository->getLists([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_id' => $tagIds, + ], 'tag_id'); + $validTagIds = array_column($validTags, 'tag_id'); + if ($validTagIds) { + $this->bindTagsToGroup($group['group_id'], $validTagIds, $companyId, $distributorId); + } + } + + // 可选:创建新标签并自动归属到当前标签组 + if (!empty($params['tags']) && is_array($params['tags'])) { + foreach ($params['tags'] as $tagData) { + if (empty($tagData['tag_name'])) { + throw new ResourceException('标签名称不能为空'); + } + $tagData['company_id'] = $companyId; + $tagData['distributor_id'] = $distributorId; + $tagData['group_id'] = $group['group_id']; + $this->createTagWithGroup($tagData); + } + } + + $conn->commit(); + return $group; + } catch (\Exception $e) { + $conn->rollback(); + throw $e; + } + } + + /** + * 删除标签组,只有当组内无标签关联时才允许删除 + * + * @param int $groupId + * @param int $companyId + * @param int $distributorId + * @return bool + */ + public function deleteTagGroup(int $groupId, int $companyId, int $distributorId = 0) + { + $groupInfo = $this->tagGroupRepository->getInfo([ + 'group_id' => $groupId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + if (!$groupInfo) { + return true; + } + + // 获取该组下的所有标签ID + $tagRelList = $this->tagGroupRelRepository->getLists([ + 'group_id' => $groupId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ], 'tag_id'); + + $tagIds = array_column($tagRelList, 'tag_id'); + + // 如果有标签,检查是否有标签绑定了会员 + if (!empty($tagIds)) { + // 检查这些标签是否有绑定会员 + $memberRelCount = $this->memberRelTags->count([ + 'company_id' => $companyId, + 'tag_id' => $tagIds, + ]); + + if ($memberRelCount > 0) { + throw new ResourceException('该标签组下的标签已绑定会员,无法删除'); + } + } + + // 使用事务确保数据一致性 + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + try { + // 删除所有标签(先删除标签与会员的关联,再删除标签本身) + if (!empty($tagIds)) { + foreach ($tagIds as $tagId) { + // 删除标签与会员的关联(虽然上面已经检查过没有绑定,但为了安全还是执行一次) + $this->memberRelTags->deleteBy([ + 'company_id' => $companyId, + 'tag_id' => $tagId, + ]); + + // 删除标签与标签组的关联 + $this->tagGroupRelRepository->deleteBy([ + 'group_id' => $groupId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_id' => $tagId, + ]); + + // 检查标签是否还被其他标签组使用 + $otherGroupCount = $this->tagGroupRelRepository->count([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_id' => $tagId, + ]); + + // 如果没有被其他标签组使用,则删除标签本身 + if ($otherGroupCount === 0) { + $this->entityRepository->deleteBy([ + 'tag_id' => $tagId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + } + } + } + + // 删除标签组 + $result = $this->tagGroupRepository->deleteById($groupId); + + $conn->commit(); + return $result; + } catch (\Exception $e) { + $conn->rollback(); + throw $e; + } + } + + /** + * 创建标签并可选关联到标签组 + * + * @param array $params + * @return array + * @throws \Exception + */ + public function createTagWithGroup(array $params) + { + $companyId = $params['company_id'] ?? 0; + $distributorId = $params['distributor_id'] ?? 0; + $groupId = $params['group_id'] ?? 0; + + if (empty($params['tag_name'])) { + throw new ResourceException('标签名称不能为空'); + } + // 同企业同分销商下的标签名唯一性校验 + $exists = $this->entityRepository->getInfo([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_name' => $params['tag_name'], + ]); + if ($exists) { + throw new ResourceException('标签名称不能重复'); + } + // 默认颜色兜底 + $params['tag_color'] = $params['tag_color'] ?? '#ff1939'; + $params['font_color'] = $params['font_color'] ?? '#ffffff'; + + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + try { + $tag = $this->entityRepository->create($params); + if ($groupId) { + $groupInfo = $this->tagGroupRepository->getInfo([ + 'group_id' => $groupId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + if (!$groupInfo) { + throw new ResourceException('标签组不存在或不属于当前公司'); + } + $this->bindTagsToGroup($groupId, [$tag['tag_id']], $companyId, $distributorId); + } + $conn->commit(); + return $tag; + } catch (\Exception $e) { + $conn->rollback(); + throw $e; + } + } + + /** + * 获取标签组列表,附带组内标签,支持分页 + * + * @param array $filter 必须包含 company_id / distributor_id,可选 group_name 用于搜索 + * @param int $page + * @param int $pageSize + * @return array + */ + public function getTagGroupList(array $filter, int $page = 1, int $pageSize = 20) + { + $companyId = $filter['company_id'] ?? 0; + $distributorId = $filter['distributor_id'] ?? 0; + $groupName = $filter['group_name'] ?? ''; + $orderBy = ['created' => 'DESC']; + + // 如果传了group_name,需要搜索标签组名称或标签名称包含该关键词的标签组 + $targetGroupIds = null; + if (!empty($groupName)) { + $targetGroupIds = []; + + // 1. 搜索标签组名称包含该关键词的标签组 + $groupFilter = [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'group_name|contains' => $groupName, + ]; + $matchedGroups = $this->tagGroupRepository->lists($groupFilter, '*', 1, -1, $orderBy); + if (!empty($matchedGroups['list'])) { + $targetGroupIds = array_merge($targetGroupIds, array_column($matchedGroups['list'], 'group_id')); + } + + // 2. 搜索标签名称包含该关键词的标签,然后找到这些标签所属的标签组 + $tagFilter = [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_name|contains' => $groupName, + ]; + $matchedTags = $this->entityRepository->getLists($tagFilter, 'tag_id'); + if (!empty($matchedTags)) { + $matchedTagIds = array_column($matchedTags, 'tag_id'); + // 查找这些标签所属的标签组 + $tagGroupRels = $this->tagGroupRelRepository->getLists([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_id' => $matchedTagIds, + ], 'group_id'); + if (!empty($tagGroupRels)) { + $groupIdsFromTags = array_unique(array_column($tagGroupRels, 'group_id')); + $targetGroupIds = array_merge($targetGroupIds, $groupIdsFromTags); + } + } + + // 去重 + $targetGroupIds = array_values(array_unique(array_filter($targetGroupIds))); + + // 如果没有匹配的标签组,直接返回空结果 + if (empty($targetGroupIds)) { + return ['total_count' => 0, 'list' => []]; + } + } + + // 构建查询条件 + $queryFilter = [ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]; + // 如果指定了标签组ID列表,添加过滤条件 + if ($targetGroupIds !== null) { + $queryFilter['group_id'] = $targetGroupIds; + } + + $groups = $this->tagGroupRepository->lists($queryFilter, '*', $page, $pageSize, $orderBy); + + if (empty($groups['list'])) { + return ['total_count' => 0, 'list' => []]; + } + + $groupIds = array_column($groups['list'], 'group_id'); + $relList = $this->tagGroupRelRepository->getLists([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'group_id' => $groupIds, + ], 'group_id, tag_id'); + + $groupTagMap = []; + $tagIds = []; + foreach ($relList as $rel) { + $groupTagMap[$rel['group_id']][] = $rel['tag_id']; + $tagIds[] = $rel['tag_id']; + } + $tagIds = array_values(array_unique(array_filter($tagIds))); + + $tagInfoMap = []; + if ($tagIds) { + $tags = $this->entityRepository->getLists([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_id' => $tagIds, + ]); + foreach ($tags as $tag) { + $tagInfoMap[$tag['tag_id']] = $tag; + } + } + + foreach ($groups['list'] as &$group) { + $ids = $groupTagMap[$group['group_id']] ?? []; + $group['tags'] = []; + foreach ($ids as $tid) { + if (isset($tagInfoMap[$tid])) { + $group['tags'][] = $tagInfoMap[$tid]; + } + } + } + + return $groups; + } + + /** + * 编辑标签组:更新组信息、标签、删除指定标签及其会员关联 + * + * @param array $params 需要包含 group_id, group_name, company_id, distributor_id + * @return array + * @throws \Exception + */ + public function updateTagGroup(array $params) + { + $groupId = (int)($params['group_id'] ?? 0); + if (!$groupId) { + throw new ResourceException('标签组ID不能为空'); + } + if (empty($params['group_name'])) { + throw new ResourceException('标签组名称不能为空'); + } + $companyId = $params['company_id'] ?? 0; + $distributorId = $params['distributor_id'] ?? 0; + + $group = $this->tagGroupRepository->getInfo([ + 'group_id' => $groupId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + if (!$group) { + throw new ResourceException('标签组不存在'); + } + + $deleteIds = isset($params['deleteids']) ? (array)$params['deleteids'] : []; + $deleteIds = array_values(array_unique(array_filter($deleteIds, function ($v) { + return (int)$v > 0; + }))); + + $tags = isset($params['tags']) && is_array($params['tags']) ? $params['tags'] : []; + + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + try { + // 更新标签组信息 + $updateData = [ + 'group_name' => $params['group_name'], + ]; + if (isset($params['description'])) { + $updateData['description'] = $params['description']; + } + $this->tagGroupRepository->updateOneBy([ + 'group_id' => $groupId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ], $updateData); + + // 删除指定标签的关联(组关联 + 会员关联),如果标签未被其他标签组使用则删除标签本身 + foreach ($deleteIds as $tagId) { + $tagId = (int)$tagId; + if (!$tagId) { + continue; + } + // 删除标签与会员的关联 + $relCount = $this->memberRelTags->count([ + 'company_id' => $companyId, + 'tag_id' => $tagId, + ]); + if ($relCount > 0) { + $this->memberRelTags->deleteBy([ + 'company_id' => $companyId, + 'tag_id' => $tagId, + ]); + $this->tagCountReduce([ + 'company_id' => $companyId, + 'tag_id' => $tagId, + ], $relCount); + } + // 删除标签与当前标签组的关联 + $this->tagGroupRelRepository->deleteBy([ + 'group_id' => $groupId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_id' => $tagId, + ]); + // 检查标签是否还被其他标签组使用 + $otherGroupCount = $this->tagGroupRelRepository->count([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_id' => $tagId, + ]); + // 如果没有被其他标签组使用,则删除标签本身 + if ($otherGroupCount === 0) { + $this->entityRepository->deleteBy([ + 'tag_id' => $tagId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + } + } + + // 处理标签(新增或更新并确保关联) + foreach ($tags as $tag) { + $tagId = (int)($tag['tag_id'] ?? 0); + $tagName = $tag['tag_name'] ?? ''; + if (!$tagName) { + throw new ResourceException('标签名称不能为空'); + } + + // 新增标签 + if ($tagId === 0) { + $tag['company_id'] = $companyId; + $tag['distributor_id'] = $distributorId; + $tag['group_id'] = $groupId; + $this->createTagWithGroup($tag); + continue; + } + + // 校验标签归属 + $tagInfo = $this->entityRepository->getInfo([ + 'tag_id' => $tagId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + if (!$tagInfo) { + throw new ResourceException('标签不存在或不属于当前公司'); + } + + // 重名校验(排除自身) + $dupList = $this->entityRepository->getLists([ + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + 'tag_name' => $tagName, + ], 'tag_id'); + if ($dupList) { + foreach ($dupList as $dup) { + if (!empty($dup['tag_id']) && (int)$dup['tag_id'] !== $tagId) { + throw new ResourceException('标签名称不能重复'); + } + } + } + + $updateTagData = [ + 'tag_name' => $tagName, + ]; + if (isset($tag['tag_color'])) { + $updateTagData['tag_color'] = $tag['tag_color']; + } + if (isset($tag['font_color'])) { + $updateTagData['font_color'] = $tag['font_color']; + } + if (isset($tag['description'])) { + $updateTagData['description'] = $tag['description']; + } + if (isset($tag['category_id'])) { + $updateTagData['category_id'] = $tag['category_id']; + } + + $this->entityRepository->updateBy([ + 'tag_id' => $tagId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ], $updateTagData); + + // 确保关联存在 + $this->bindTagsToGroup($groupId, [$tagId], $companyId, $distributorId); + } + + $conn->commit(); + return [ + 'group_id' => $groupId, + 'group_name' => $params['group_name'], + ]; + } catch (\Exception $e) { + $conn->rollback(); + throw $e; + } + } + + + /** + * 为指定标签组绑定标签(去重) + */ + private function bindTagsToGroup(int $groupId, array $tagIds, int $companyId, int $distributorId = 0) + { + foreach ($tagIds as $tagId) { + if (!$tagId) { + continue; + } + $exists = $this->tagGroupRelRepository->getInfo([ + 'group_id' => $groupId, + 'tag_id' => $tagId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + if ($exists) { + continue; + } + $this->tagGroupRelRepository->create([ + 'group_id' => $groupId, + 'tag_id' => $tagId, + 'company_id' => $companyId, + 'distributor_id' => $distributorId, + ]); + } + } + // 如果可以直接调取Repositories中的方法,则直接调用 public function __call($method, $parameters) { diff --git a/src/MembersBundle/Services/TagLibraryPushService.php b/src/MembersBundle/Services/TagLibraryPushService.php new file mode 100644 index 0000000..5baf4bb --- /dev/null +++ b/src/MembersBundle/Services/TagLibraryPushService.php @@ -0,0 +1,477 @@ +em = app('registry')->getManager('default'); + $this->tagRepository = $this->em->getRepository(MemberTags::class); + $this->tagGroupRepository = $this->em->getRepository(MemberTagGroup::class); + $this->tagGroupRelRepository = $this->em->getRepository(MemberTagGroupRel::class); + } + + /** + * 推送标签库数据到云店 + * + * @param int $companyId 公司ID + * @param array $tagLibrary 标签库数据 + * @return array 返回统计信息 + * @throws Exception + */ + public function pushTagLibrary(int $companyId, array $tagLibrary): array + { + // 统计信息 + $stats = [ + 'success_count' => 0, + 'fail_count' => 0, + 'created_groups' => 0, + 'updated_groups' => 0, + 'created_tags' => 0, + 'updated_tags' => 0, + 'deleted_groups' => 0, + 'deleted_tags' => 0, + ]; + + try { + $this->em->beginTransaction(); + + // 收集本次推送的所有 wechat_group_id 和 wechat_tag_id + $pushedWechatGroupIds = []; + $pushedWechatTagIds = []; + + foreach ($tagLibrary as $groupData) { + try { + if (!empty($groupData['wechat_group_id'])) { + $pushedWechatGroupIds[] = $groupData['wechat_group_id']; + } + + // 收集标签的 wechat_tag_id + if (!empty($groupData['taglist'])) { + foreach ($groupData['taglist'] as $tagData) { + if (!empty($tagData['wechat_tag_id'])) { + $pushedWechatTagIds[] = $tagData['wechat_tag_id']; + } + } + } + + $this->processTagGroup($companyId, $groupData, $stats); + } catch (Exception $e) { + app('log')->error('[TagLibraryPushService] 处理标签组失败', [ + 'group_data' => $groupData, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + $stats['fail_count']++; + } + } + + // 删除本地多余的企微标签组(本地有但导购没传的) + if (!empty($pushedWechatGroupIds)) { + $deletedGroups = $this->deleteObsoleteGroups($companyId, $pushedWechatGroupIds); + $stats['deleted_groups'] = $deletedGroups; + } + + // 删除本地多余的企微标签(本地有但导购没传的) + if (!empty($pushedWechatTagIds)) { + $deletedTags = $this->deleteObsoleteTags($companyId, $pushedWechatTagIds); + $stats['deleted_tags'] = $deletedTags; + } + + $this->em->flush(); + $this->em->commit(); + + app('log')->info('[TagLibraryPushService] 标签库推送成功', [ + 'company_id' => $companyId, + 'stats' => $stats, + ]); + + return $stats; + + } catch (Exception $e) { + $this->em->rollback(); + app('log')->error('[TagLibraryPushService] 标签库推送失败', [ + 'company_id' => $companyId, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + throw $e; + } + } + + /** + * 处理单个标签组 + * + * @param int $companyId 公司ID + * @param array $groupData 标签组数据 + * @param array &$stats 统计信息(引用传递) + * @throws Exception + */ + private function processTagGroup(int $companyId, array $groupData, array &$stats): void + { + // 验证标签组数据 + if (empty($groupData['group_name'])) { + app('log')->warning('[TagLibraryPushService] 标签组名称为空,跳过', ['data' => $groupData]); + $stats['fail_count']++; + return; + } + + $groupName = $groupData['group_name']; + $description = $groupData['description'] ?? ''; + $wechatGroupId = $groupData['wechat_group_id'] ?? null; + $taglist = $groupData['taglist'] ?? []; + + // 查找或创建标签组 + $groupId = $this->findOrCreateTagGroup($companyId, $groupName, $description, $wechatGroupId, $stats); + + // 处理标签列表 + $processedTagIds = []; + foreach ($taglist as $tagData) { + $tagId = $this->processTag($companyId, $tagData, $stats); + if ($tagId) { + $processedTagIds[] = $tagId; + // 创建或更新标签组与标签的关联关系 + $this->createTagGroupRelation($companyId, $groupId, $tagId); + } + } + + // 清理该标签组下已经不存在的标签关联 + if (!empty($processedTagIds)) { + $this->cleanOldRelations($companyId, $groupId, $processedTagIds); + } + + $stats['success_count']++; + } + + /** + * 查找或创建标签组 + * + * @param int $companyId 公司ID + * @param string $groupName 标签组名称 + * @param string $description 描述 + * @param string|null $wechatGroupId 企微标签组ID + * @param array &$stats 统计信息 + * @return int 标签组ID + * @throws Exception + */ + private function findOrCreateTagGroup(int $companyId, string $groupName, string $description, ?string $wechatGroupId, array &$stats): int + { + $existingGroup = null; + + // 优先根据 wechat_group_id 查找 + if (!empty($wechatGroupId)) { + $qb = $this->em->createQueryBuilder(); + $qb->select('g') + ->from(MemberTagGroup::class, 'g') + ->where('g.company_id = :company_id') + ->andWhere('g.wechat_group_id = :wechat_group_id') + ->setParameter('company_id', $companyId) + ->setParameter('wechat_group_id', $wechatGroupId); + $existingGroup = $qb->getQuery()->getOneOrNullResult(); + } + + if ($existingGroup) { + // 更新现有标签组(ID重复,名字可能变了) + $existingGroup->setGroupName($groupName); + $existingGroup->setDescription($description); + $stats['updated_groups']++; + return $existingGroup->getGroupId(); + } else { + // 创建新标签组 + $newGroup = new MemberTagGroup(); + $newGroup->setCompanyId($companyId); + $newGroup->setGroupName($groupName); + $newGroup->setDescription($description); + if (!empty($wechatGroupId)) { + $newGroup->setWechatGroupId($wechatGroupId); + } + $this->em->persist($newGroup); + $this->em->flush(); // 立即刷新以获取 group_id + $stats['created_groups']++; + return $newGroup->getGroupId(); + } + } + + /** + * 处理单个标签 + * + * @param int $companyId 公司ID + * @param array $tagData 标签数据 + * @param array &$stats 统计信息 + * @return int|null 标签ID,失败返回null + */ + private function processTag(int $companyId, array $tagData, array &$stats): ?int + { + if (empty($tagData['tag_name'])) { + app('log')->warning('[TagLibraryPushService] 标签名称为空,跳过', ['data' => $tagData]); + return null; + } + + $tagName = $tagData['tag_name']; + $tagDescription = $tagData['description'] ?? ''; + $wechatTagId = $tagData['wechat_tag_id'] ?? null; + $tagColor = $tagData['tag_color'] ?? '#3e7bff'; + $fontColor = $tagData['font_color'] ?? '#ffffff'; + $tagIcon = $tagData['tag_icon'] ?? ''; + $tagStatus = $tagData['tag_status'] ?? 'online'; + $source = $tagData['source'] ?? 'wechat'; + + // 查找或创建标签 + return $this->findOrCreateTag( + $companyId, + $tagName, + $tagDescription, + $wechatTagId, + $tagColor, + $fontColor, + $tagIcon, + $tagStatus, + $source, + $stats + ); + } + + /** + * 查找或创建标签 + * + * @param int $companyId 公司ID + * @param string $tagName 标签名称 + * @param string $tagDescription 标签描述 + * @param string|null $wechatTagId 企微标签ID + * @param string $tagColor 标签颜色 + * @param string $fontColor 字体颜色 + * @param string $tagIcon 标签图标 + * @param string $tagStatus 标签状态 + * @param string $source 来源 + * @param array &$stats 统计信息 + * @return int 标签ID + * @throws Exception + */ + private function findOrCreateTag( + int $companyId, + string $tagName, + string $tagDescription, + ?string $wechatTagId, + string $tagColor, + string $fontColor, + string $tagIcon, + string $tagStatus, + string $source, + array &$stats + ): int { + $existingTag = null; + + // 优先根据 wechat_tag_id 查找 + if (!empty($wechatTagId)) { + $qb = $this->em->createQueryBuilder(); + $qb->select('t') + ->from(MemberTags::class, 't') + ->where('t.company_id = :company_id') + ->andWhere('t.wechat_tag_id = :wechat_tag_id') + ->setParameter('company_id', $companyId) + ->setParameter('wechat_tag_id', $wechatTagId); + $existingTag = $qb->getQuery()->getOneOrNullResult(); + } + + if ($existingTag) { + // 更新现有标签(ID重复,名字可能变了) + $existingTag->setTagName($tagName); + $existingTag->setDescription($tagDescription); + $existingTag->setTagColor($tagColor); + $existingTag->setFontColor($fontColor); + $existingTag->setTagIcon($tagIcon); + $existingTag->setTagStatus($tagStatus); + $existingTag->setSource($source); + $stats['updated_tags']++; + return $existingTag->getTagId(); + } else { + // 创建新标签 + $newTag = new MemberTags(); + $newTag->setCompanyId($companyId); + $newTag->setTagName($tagName); + $newTag->setDescription($tagDescription); + $newTag->setTagColor($tagColor); + $newTag->setFontColor($fontColor); + $newTag->setTagIcon($tagIcon); + $newTag->setTagStatus($tagStatus); + $newTag->setSource($source); + if (!empty($wechatTagId)) { + $newTag->setWechatTagId($wechatTagId); + } + $this->em->persist($newTag); + $this->em->flush(); // 立即刷新以获取 tag_id + $stats['created_tags']++; + return $newTag->getTagId(); + } + } + + /** + * 创建标签组与标签的关联关系 + * + * @param int $companyId 公司ID + * @param int $groupId 标签组ID + * @param int $tagId 标签ID + */ + private function createTagGroupRelation(int $companyId, int $groupId, int $tagId): void + { + // 查找是否已存在关联 + $qb = $this->em->createQueryBuilder(); + $qb->select('r') + ->from(MemberTagGroupRel::class, 'r') + ->where('r.company_id = :company_id') + ->andWhere('r.group_id = :group_id') + ->andWhere('r.tag_id = :tag_id') + ->setParameter('company_id', $companyId) + ->setParameter('group_id', $groupId) + ->setParameter('tag_id', $tagId); + $existingRel = $qb->getQuery()->getOneOrNullResult(); + + if (!$existingRel) { + $newRel = new MemberTagGroupRel(); + $newRel->setCompanyId($companyId); + $newRel->setGroupId($groupId); + $newRel->setTagId($tagId); + $this->em->persist($newRel); + } + } + + /** + * 清理标签组下不在本次推送中的标签关联 + * + * @param int $companyId 公司ID + * @param int $groupId 标签组ID + * @param array $processedTagIds 本次推送的标签ID列表 + */ + private function cleanOldRelations(int $companyId, int $groupId, array $processedTagIds): void + { + $qb = $this->em->createQueryBuilder(); + $qb->delete(MemberTagGroupRel::class, 'r') + ->where('r.company_id = :company_id') + ->andWhere('r.group_id = :group_id') + ->andWhere($qb->expr()->notIn('r.tag_id', ':tag_ids')) + ->setParameter('company_id', $companyId) + ->setParameter('group_id', $groupId) + ->setParameter('tag_ids', $processedTagIds); + $qb->getQuery()->execute(); + } + + /** + * 删除本地多余的企微标签组(本地有但导购没传的) + * + * @param int $companyId 公司ID + * @param array $pushedWechatGroupIds 本次推送的所有 wechat_group_id + * @return int 删除的标签组数量 + */ + private function deleteObsoleteGroups(int $companyId, array $pushedWechatGroupIds): int + { + // 查找所有有 wechat_group_id 但不在本次推送列表中的标签组 + $qb = $this->em->createQueryBuilder(); + $qb->select('g') + ->from(MemberTagGroup::class, 'g') + ->where('g.company_id = :company_id') + ->andWhere('g.wechat_group_id IS NOT NULL') + ->andWhere($qb->expr()->notIn('g.wechat_group_id', ':wechat_group_ids')) + ->setParameter('company_id', $companyId) + ->setParameter('wechat_group_ids', $pushedWechatGroupIds); + + $obsoleteGroups = $qb->getQuery()->getResult(); + $deletedCount = 0; + + foreach ($obsoleteGroups as $group) { + // 先删除关联关系 + $relQb = $this->em->createQueryBuilder(); + $relQb->delete(MemberTagGroupRel::class, 'r') + ->where('r.company_id = :company_id') + ->andWhere('r.group_id = :group_id') + ->setParameter('company_id', $companyId) + ->setParameter('group_id', $group->getGroupId()); + $relQb->getQuery()->execute(); + + // 删除标签组 + $this->em->remove($group); + $deletedCount++; + + app('log')->info('[TagLibraryPushService] 删除多余标签组', [ + 'company_id' => $companyId, + 'group_id' => $group->getGroupId(), + 'group_name' => $group->getGroupName(), + 'wechat_group_id' => $group->getWechatGroupId(), + ]); + } + + return $deletedCount; + } + + /** + * 删除本地多余的企微标签(本地有但导购没传的) + * + * @param int $companyId 公司ID + * @param array $pushedWechatTagIds 本次推送的所有 wechat_tag_id + * @return int 删除的标签数量 + */ + private function deleteObsoleteTags(int $companyId, array $pushedWechatTagIds): int + { + // 查找所有有 wechat_tag_id 但不在本次推送列表中的标签 + $qb = $this->em->createQueryBuilder(); + $qb->select('t') + ->from(MemberTags::class, 't') + ->where('t.company_id = :company_id') + ->andWhere('t.wechat_tag_id IS NOT NULL') + ->andWhere($qb->expr()->notIn('t.wechat_tag_id', ':wechat_tag_ids')) + ->setParameter('company_id', $companyId) + ->setParameter('wechat_tag_ids', $pushedWechatTagIds); + + $obsoleteTags = $qb->getQuery()->getResult(); + $deletedCount = 0; + + foreach ($obsoleteTags as $tag) { + // 先删除标签组关联关系 + $relQb = $this->em->createQueryBuilder(); + $relQb->delete(MemberTagGroupRel::class, 'r') + ->where('r.company_id = :company_id') + ->andWhere('r.tag_id = :tag_id') + ->setParameter('company_id', $companyId) + ->setParameter('tag_id', $tag->getTagId()); + $relQb->getQuery()->execute(); + + // 删除会员标签关联(如果有的话) + $memberRelQb = $this->em->createQueryBuilder(); + $memberRelQb->delete('MembersBundle\Entities\MemberRelTags', 'mrt') + ->where('mrt.tag_id = :tag_id') + ->setParameter('tag_id', $tag->getTagId()); + $memberRelQb->getQuery()->execute(); + + // 删除标签 + $this->em->remove($tag); + $deletedCount++; + + app('log')->info('[TagLibraryPushService] 删除多余标签', [ + 'company_id' => $companyId, + 'tag_id' => $tag->getTagId(), + 'tag_name' => $tag->getTagName(), + 'wechat_tag_id' => $tag->getWechatTagId(), + ]); + } + + return $deletedCount; + } +} + diff --git a/src/MembersBundle/Traits/MemberSearchFilter.php b/src/MembersBundle/Traits/MemberSearchFilter.php index 8d6c27c..d1effc8 100644 --- a/src/MembersBundle/Traits/MemberSearchFilter.php +++ b/src/MembersBundle/Traits/MemberSearchFilter.php @@ -57,6 +57,13 @@ trait MemberSearchFilter $filter['created|lte'] = $postdata['time_start_end']; } + if (isset($postdata['birthday_start']) && $postdata['birthday_start']) { + $filter['birthday|gte'] = date('Y-m-d', strtotime($postdata['birthday_start'])); + } + if (isset($postdata['birthday_end']) && $postdata['birthday_end']) { + $filter['birthday|lte'] = date('Y-m-d', strtotime($postdata['birthday_end'])); + } + if (isset($postdata['user_id']) && $postdata['user_id']) { $userIds = is_array($postdata['user_id']) ? $postdata['user_id'] : [$postdata['user_id']]; } @@ -108,7 +115,15 @@ trait MemberSearchFilter } if (isset($postdata['tag_id']) && $postdata['tag_id']) { - $filter['tag_id'] = $postdata['tag_id']; + // 如果 tag_id 包含逗号,则分割成数组 + if (is_string($postdata['tag_id']) && strpos($postdata['tag_id'], ',') !== false) { + $tagIds = explode(',', $postdata['tag_id']); + $tagIds = array_map('trim', $tagIds); + $tagIds = array_filter($tagIds); + $filter['tag_id'] = !empty($tagIds) ? $tagIds : $postdata['tag_id']; + } else { + $filter['tag_id'] = $postdata['tag_id']; + } } if ($postdata['vip_grade'] == 'notvip') { diff --git a/src/OpenapiBundle/Http/ThirdApi/V1/Action/DiscountCardController.php b/src/OpenapiBundle/Http/ThirdApi/V1/Action/DiscountCardController.php index 3e3d45a..cf037dc 100644 --- a/src/OpenapiBundle/Http/ThirdApi/V1/Action/DiscountCardController.php +++ b/src/OpenapiBundle/Http/ThirdApi/V1/Action/DiscountCardController.php @@ -307,6 +307,8 @@ class DiscountCardController extends Controller if ($request->input('title')) { $filter['title|like'] = $request->input('title'); } + + $filter['coupon_type'] = ['guide']; // if ($request->input('card_source')) { // $filter['card_source'] = $request->input('card_source'); // } diff --git a/src/OpenapiBundle/Http/ThirdApi/V1/Action/Member.php b/src/OpenapiBundle/Http/ThirdApi/V1/Action/Member.php index 1574a3e..7a9cf0f 100644 --- a/src/OpenapiBundle/Http/ThirdApi/V1/Action/Member.php +++ b/src/OpenapiBundle/Http/ThirdApi/V1/Action/Member.php @@ -33,9 +33,18 @@ use KaquanBundle\Services\VipGradeOrderService; use MembersBundle\Entities\MembersAssociations; use OrdersBundle\Traits\GetOrderServiceTrait; use MembersBundle\Services\MemberBrowseHistoryService; +use MembersBundle\Services\MemberTagsService; use GoodsBundle\Services\ItemsService; use OrdersBundle\Services\TradeService; use ThirdPartyBundle\Services\DmCrm\MemberService as DmMemberService; +use DistributionBundle\Services\DistributorService; +use DistributionBundle\Entities\Distributor; +use SalespersonBundle\Services\SalespersonService; +use ThirdPartyBundle\Services\MarketingCenter\Request as MarketingCenterRequest; +use MembersBundle\Services\TagLibraryPushService; +use MembersBundle\Entities\MemberTagGroup; +use MembersBundle\Entities\MemberTagGroupRel; +use MembersBundle\Entities\MemberTags; class Member extends Controller { @@ -687,4 +696,1187 @@ class Member extends Controller } $this->api_response('true', '操作成功', null, 'E0000'); } + + /** + * @SWG\Get( + * path="/ecx.member.tagLibrary", + * summary="获取标签库(标签和标签组)", + * tags={"会员"}, + * description="获取标签库,包括所有标签组及其下的标签列表", + * @SWG\Parameter( in="query", type="string", required=true, name="method", description="方法名称 ecx.member.tagLibrary" ), + * @SWG\Parameter( in="query", type="string", required=true, name="app_key", description="app_key" ), + * @SWG\Parameter( in="query", type="string", required=true, name="version", description="版本号" ), + * @SWG\Parameter( in="query", type="string", required=true, name="timestamp", description="请求时间" ), + * @SWG\Parameter( in="query", type="string", required=true, name="sign", description="签名" ), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="status", type="string", example="true", description="接口状态"), + * @SWG\Property( property="code", type="string", example="E0000", description="错误码"), + * @SWG\Property( property="message", type="string", example="操作成功", description="提示信息"), + * @SWG\Property( property="data", type="array", + * @SWG\Items( type="object", + * @SWG\Property( property="group_id", type="integer", example=1, description="标签组ID"), + * @SWG\Property( property="group_name", type="string", example="促销标签", description="标签组名称"), + * @SWG\Property( property="description", type="string", example="促销相关的标签", description="标签组描述"), + * @SWG\Property( property="created", type="string", example="2021-06-28 15:28:14", description="创建时间"), + * @SWG\Property( property="updated", type="string", example="2021-06-28 15:28:14", description="更新时间"), + * @SWG\Property( property="taglist", type="array", description="标签列表", + * @SWG\Items( type="object", + * @SWG\Property( property="tag_id", type="integer", example=1, description="标签ID"), + * @SWG\Property( property="tag_name", type="string", example="VIP会员", description="标签名称"), + * @SWG\Property( property="description", type="string", example="VIP会员标签", description="标签描述"), + * @SWG\Property( property="tag_color", type="string", example="#ff1939", description="标签颜色"), + * @SWG\Property( property="font_color", type="string", example="#ffffff", description="字体颜色"), + * @SWG\Property( property="tag_icon", type="string", example="", description="标签图标"), + * @SWG\Property( property="tag_status", type="string", example="online", description="标签状态"), + * @SWG\Property( property="source", type="string", example="self", description="标签来源"), + * @SWG\Property( property="self_tag_count", type="integer", example=10, description="标签下会员数量"), + * @SWG\Property( property="created", type="string", example="2021-06-29 10:35:13", description="创建时间"), + * @SWG\Property( property="updated", type="string", example="2021-06-29 10:35:13", description="更新时间"), + * ), + * ), + * ), + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/OpenapiErrorRespones"))) + * ) + */ + public function tagLibrary(Request $request) + { + $companyId = $request->get('auth')['company_id']; + $em = app('registry')->getManager('default'); + + // 获取标签组列表(过滤掉企业微信标签组) + $qb = $em->createQueryBuilder(); + $qb->select('g.group_id', 'g.group_name', 'g.description', 'g.created', 'g.updated') + ->from(MemberTagGroup::class, 'g') + ->where('g.company_id = :company_id') + ->setParameter('company_id', $companyId); + + // 过滤掉企业微信标签组(wechat_group_id 不为空的) + $qb->andWhere($qb->expr()->orX( + $qb->expr()->isNull('g.wechat_group_id'), + $qb->expr()->eq('g.wechat_group_id', $qb->expr()->literal('')) + )); + + $groupList = $qb->getQuery()->getResult(); + + // 获取标签组与标签的关系 + $tagGroupRelRepository = app('registry')->getManager('default')->getRepository(MemberTagGroupRel::class); + $groupRelList = $tagGroupRelRepository->getLists(['company_id' => $companyId], 'group_id,tag_id'); + + // 构建 group_id => tag_ids 的映射 + $groupTagsMap = []; + foreach ($groupRelList as $rel) { + $groupId = $rel['group_id']; + if (!isset($groupTagsMap[$groupId])) { + $groupTagsMap[$groupId] = []; + } + $groupTagsMap[$groupId][] = $rel['tag_id']; + } + + // 获取所有标签(过滤掉企业微信标签) + $qb2 = $em->createQueryBuilder(); + $qb2->select('t') + ->from(MemberTags::class, 't') + ->where('t.company_id = :company_id') + ->setParameter('company_id', $companyId) + ->orderBy('t.created', 'DESC'); + + // 过滤掉企业微信标签(wechat_tag_id 不为空的) + $qb2->andWhere($qb2->expr()->orX( + $qb2->expr()->isNull('t.wechat_tag_id'), + $qb2->expr()->eq('t.wechat_tag_id', $qb2->expr()->literal('')) + )); + + $tagListEntities = $qb2->getQuery()->getResult(); + + // 转换为数组格式 + $tagList = ['list' => []]; + foreach ($tagListEntities as $entity) { + $tagList['list'][] = [ + 'tag_id' => $entity->getTagId(), + 'tag_name' => $entity->getTagName(), + 'description' => $entity->getDescription(), + 'tag_color' => $entity->getTagColor(), + 'font_color' => $entity->getFontColor(), + 'tag_icon' => $entity->getTagIcon(), + 'tag_status' => $entity->getTagStatus(), + 'source' => $entity->getSource(), + 'created' => $entity->getCreated(), + 'updated' => $entity->getUpdated(), + ]; + } + + // 构建 tag_id => tag_data 的映射 + $tagsMap = []; + foreach ($tagList['list'] as $tag) { + $tagsMap[$tag['tag_id']] = $tag; + } + + // 获取标签会员数量统计 + $tagIds = array_column($tagList['list'], 'tag_id'); + $countList = []; + if ($tagIds) { + $memberTagsService = new MemberTagsService(); + $countFilter = [ + 'company_id' => $companyId, + 'tag_id' => $tagIds, + ]; + $countList = $memberTagsService->entityRepository->getCountList($countFilter); + $countList = array_column($countList, 'num', 'tag_id'); + } + + app('log')->info('[tagLibrary] 已过滤企业微信标签和标签组', [ + 'company_id' => $companyId, + 'group_count' => count($groupList), + 'tag_count' => count($tagList['list']), + ]); + + // 组装返回数据 + $return = []; + foreach ($groupList as $group) { + $groupId = $group['group_id']; + $taglist = []; + + // 获取该标签组下的所有标签 + if (isset($groupTagsMap[$groupId])) { + foreach ($groupTagsMap[$groupId] as $tagId) { + if (isset($tagsMap[$tagId])) { + $tag = $tagsMap[$tagId]; + $taglist[] = [ + 'tag_id' => $tag['tag_id'], + 'tag_name' => $tag['tag_name'], + 'description' => $tag['description'] ?? '', + 'tag_color' => $tag['tag_color'] ?? '#ff1939', + 'font_color' => $tag['font_color'] ?? '#ffffff', + 'tag_icon' => $tag['tag_icon'] ?? '', + 'tag_status' => $tag['tag_status'] ?? 'online', + 'source' => $tag['source'] ?? 'self', + 'self_tag_count' => $countList[$tag['tag_id']] ?? 0, + 'created' => isset($tag['created']) ? date('Y-m-d H:i:s', $tag['created']) : '', + 'updated' => isset($tag['updated']) ? date('Y-m-d H:i:s', $tag['updated']) : '', + ]; + } + } + } + + $return[] = [ + 'group_id' => $groupId, + 'group_name' => $group['group_name'], + 'description' => $group['description'] ?? '', + 'created' => isset($group['created']) ? date('Y-m-d H:i:s', $group['created']) : '', + 'updated' => isset($group['updated']) ? date('Y-m-d H:i:s', $group['updated']) : '', + 'taglist' => $taglist, + ]; + } + + // 处理未分组的标签 + $groupedTagIds = []; + foreach ($groupTagsMap as $tagIds) { + $groupedTagIds = array_merge($groupedTagIds, $tagIds); + } + $groupedTagIds = array_unique($groupedTagIds); + + $ungroupedTags = []; + foreach ($tagsMap as $tagId => $tag) { + if (!in_array($tagId, $groupedTagIds)) { + $ungroupedTags[] = [ + 'tag_id' => $tag['tag_id'], + 'tag_name' => $tag['tag_name'], + 'description' => $tag['description'] ?? '', + 'tag_color' => $tag['tag_color'] ?? '#ff1939', + 'font_color' => $tag['font_color'] ?? '#ffffff', + 'tag_icon' => $tag['tag_icon'] ?? '', + 'tag_status' => $tag['tag_status'] ?? 'online', + 'source' => $tag['source'] ?? 'self', + 'self_tag_count' => $countList[$tag['tag_id']] ?? 0, + 'created' => isset($tag['created']) ? date('Y-m-d H:i:s', $tag['created']) : '', + 'updated' => isset($tag['updated']) ? date('Y-m-d H:i:s', $tag['updated']) : '', + ]; + } + } + + // 如果有未分组的标签,添加到返回数据中 + if (!empty($ungroupedTags)) { + $return[] = [ + 'group_id' => 0, + 'group_name' => '未分组', + 'description' => '未分配到任何标签组的标签', + 'created' => '', + 'updated' => '', + 'taglist' => $ungroupedTags, + ]; + } + + $this->api_response('true', '操作成功', $return, 'E0000'); + } + + /** + * @SWG\Post( + * path="/ecx.member.tagLibrary.push", + * summary="推送标签库到云店", + * tags={"会员"}, + * description="从企业微信等第三方系统推送标签库数据到云店,支持标签组和标签的创建/更新", + * @SWG\Parameter( in="query", type="string", required=true, name="method", description="方法名称 ecx.member.tagLibrary.push" ), + * @SWG\Parameter( in="query", type="string", required=true, name="app_key", description="app_key" ), + * @SWG\Parameter( in="query", type="string", required=true, name="version", description="版本号" ), + * @SWG\Parameter( in="query", type="string", required=true, name="timestamp", description="请求时间" ), + * @SWG\Parameter( in="query", type="string", required=true, name="sign", description="签名" ), + * @SWG\Parameter( in="body", name="tag_library", required=true, @SWG\Schema(type="array", + * description="标签库数据数组", + * @SWG\Items(type="object", + * @SWG\Property(property="group_id", type="string", description="标签组ID"), + * @SWG\Property(property="group_name", type="string", description="标签组名称"), + * @SWG\Property(property="wechat_group_id", type="string", description="企微标签组ID(用于去重)"), + * @SWG\Property(property="ori_source", type="string", description="来源标识(wechat)"), + * @SWG\Property(property="description", type="string", description="标签组说明"), + * @SWG\Property(property="created", type="string", description="创建时间"), + * @SWG\Property(property="updated", type="string", description="更新时间"), + * @SWG\Property(property="taglist", type="array", description="标签列表", + * @SWG\Items(type="object", + * @SWG\Property(property="tag_id", type="string", description="标签ID"), + * @SWG\Property(property="tag_name", type="string", description="标签名称"), + * @SWG\Property(property="wechat_tag_id", type="string", description="企微标签ID(用于去重)"), + * @SWG\Property(property="ori_source", type="string", description="来源标识(wechat)"), + * @SWG\Property(property="description", type="string", description="标签说明"), + * @SWG\Property(property="tag_color", type="string", description="标签颜色"), + * @SWG\Property(property="font_color", type="string", description="字体颜色"), + * @SWG\Property(property="tag_icon", type="string", description="标签图标"), + * @SWG\Property(property="tag_status", type="string", description="标签状态"), + * @SWG\Property(property="source", type="string", description="来源(wechat)"), + * ), + * ), + * ), + * )), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="status", type="string", example="succ", description="接口状态"), + * @SWG\Property( property="code", type="string", example="E0000", description="错误码"), + * @SWG\Property( property="message", type="string", example="操作成功", description="提示信息"), + * @SWG\Property( property="data", type="object", + * @SWG\Property( property="success_count", type="integer", description="成功处理的标签组数量"), + * @SWG\Property( property="fail_count", type="integer", description="失败的标签组数量"), + * @SWG\Property( property="created_groups", type="integer", description="新建的标签组数量"), + * @SWG\Property( property="updated_groups", type="integer", description="更新的标签组数量"), + * @SWG\Property( property="created_tags", type="integer", description="新建的标签数量"), + * @SWG\Property( property="updated_tags", type="integer", description="更新的标签数量"), + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/OpenapiErrorRespones"))) + * ) + */ + public function tagLibraryPush(Request $request) + { + $params = $request->all(); + $companyId = $request->get('auth')['company_id']; + + // 验证必填参数 + if (empty($params['tag_library']) || !is_array($params['tag_library'])) { + $this->api_response('fail', '标签库数据不能为空', [], 'E1001'); + return; + } + + try { + // 调用 Service 处理业务逻辑 + $tagLibraryPushService = new TagLibraryPushService(); + $stats = $tagLibraryPushService->pushTagLibrary($companyId, $params['tag_library']); + + $this->api_response('true', '操作成功', $stats, 'E0000'); + + } catch (\Exception $e) { + $this->api_response('fail', '标签库推送失败:' . $e->getMessage(), [], 'E9999'); + } + } + + /** + * @SWG\Post( + * path="/ecx.member.tag.relation.push", + * summary="导购平台推送会员标签关系到云店", + * tags={"会员"}, + * description="导购平台推送会员标签关系到云店,支持两种模式:1. 正常模式:先删除会员所有标签,再重新打标签;2. 清空模式:仅删除会员所有标签", + * @SWG\Parameter( in="query", type="string", required=true, name="method", description="方法名称 ecx.member.tag.relation.push" ), + * @SWG\Parameter( in="query", type="string", required=true, name="app_key", description="app_key" ), + * @SWG\Parameter( in="query", type="string", required=true, name="version", description="版本号" ), + * @SWG\Parameter( in="query", type="string", required=true, name="timestamp", description="请求时间" ), + * @SWG\Parameter( in="query", type="string", required=true, name="sign", description="签名" ), + * @SWG\Parameter( in="body", name="action", required=false, @SWG\Schema(type="string", description="操作类型:clear=清空会员所有标签(此时relations可为空)") ), + * @SWG\Parameter( in="body", name="user_id", required=false, @SWG\Schema(type="string", description="会员ID(清空模式必填)") ), + * @SWG\Parameter( in="body", name="mobile", required=false, @SWG\Schema(type="string", description="会员手机号(清空模式备用查找)") ), + * @SWG\Parameter( in="body", name="relations", required=false, @SWG\Schema(type="array", + * description="标签关系数据数组(正常模式必填,清空模式可为空)", + * @SWG\Items(type="object", + * @SWG\Property(property="user_id", type="string", description="会员ID"), + * @SWG\Property(property="mobile", type="string", description="会员手机号"), + * @SWG\Property(property="tag_id", type="string", description="标签ID(导购平台的)"), + * @SWG\Property(property="tag_name", type="string", description="标签名称"), + * @SWG\Property(property="tag_type", type="string", description="标签类型:self/wechat/staff"), + * @SWG\Property(property="wechat_tag_id", type="string", description="企微标签ID(可选)"), + * ) + * )), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="status", type="string", example="succ", description="接口状态"), + * @SWG\Property( property="code", type="string", example="E0000", description="错误码"), + * @SWG\Property( property="message", type="string", example="操作成功", description="提示信息"), + * @SWG\Property( property="data", type="object", + * @SWG\Property( property="success_count", type="integer", description="成功处理的会员数量"), + * @SWG\Property( property="fail_count", type="integer", description="失败的会员数量"), + * @SWG\Property( property="processed_members", type="integer", description="处理的会员总数"), + * @SWG\Property( property="processed_tags", type="integer", description="处理的标签总数"), + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/OpenapiErrorRespones"))) + * ) + */ + public function tagRelationPush(Request $request) + { + $params = $request->all(); + $companyId = $request->get('auth')['company_id']; + + // 特殊处理:清空会员标签 + if ((empty($params['relations']) || !is_array($params['relations'])) && + isset($params['action']) && $params['action'] === 'clear') { + + return $this->handleClearMode($request, $params, $companyId); + } + + // 验证必填参数(正常模式) + if (empty($params['relations']) || !is_array($params['relations'])) { + app('log')->warning('[tagRelationPush] 标签关系数据不能为空', ['company_id' => $companyId, 'params' => $params]); + $this->api_response('fail', '标签关系数据不能为空', [], 'E1001'); + } + + return $this->handleNormalMode($request, $params, $companyId); + } + + /** + * 处理清空模式 + */ + private function handleClearMode(Request $request, array $params, int $companyId) + { + app('log')->info('[tagRelationPush] 清空会员标签模式', [ + 'company_id' => $companyId, + 'user_id' => $params['user_id'] ?? null, + ]); + + // 验证 user_id + if (empty($params['user_id'])) { + app('log')->warning('[tagRelationPush] 清空模式需要提供 user_id', ['company_id' => $companyId, 'params' => $params]); + $this->api_response('fail', '清空模式需要提供 user_id', [], 'E1001'); + } + $stats = [ + 'success_count' => 0, + 'fail_count' => 0, + 'processed_members' => 0, + 'processed_tags' => 0, + ]; + + try { + $memberService = new MemberService(); + $memberTagsService = new MemberTagsService(); + + // 查找会员 + $filter = ['company_id' => $companyId, 'user_id' => $params['user_id']]; + $member = $memberService->getMemberInfo($filter); + + // 如果没找到,尝试用手机号查找 + if (empty($member) && !empty($params['mobile'])) { + $filter = ['company_id' => $companyId, 'mobile' => $params['mobile']]; + $member = $memberService->getMemberInfo($filter); + } + + if (empty($member)) { + app('log')->warning('[tagRelationPush] 未找到会员', [ + 'company_id' => $companyId, + 'user_id' => $params['user_id'], + 'mobile' => $params['mobile'] ?? null, + ]); + $this->api_response('fail', '未找到会员', [], 'E1001'); + } + + $actualUserId = $member['user_id']; + + // 删除该会员的所有标签 + $memberTagsService->deleteRelTagsByUserId($actualUserId, $companyId); + + app('log')->info('[tagRelationPush] 清空会员标签成功', [ + 'company_id' => $companyId, + 'user_id' => $actualUserId, + ]); + + $stats = [ + 'success_count' => 1, + 'fail_count' => 0, + 'processed_members' => 1, + 'processed_tags' => 0, + ]; + } catch (\Exception $e) { + app('log')->error('[tagRelationPush] 清空会员标签失败', [ + 'company_id' => $companyId, + 'user_id' => $params['user_id'] ?? null, + 'error' => $e->getMessage(), + ]); + $this->api_response('fail', '清空会员标签失败:' . $e->getMessage(), [], 'E9999'); + } + $this->api_response('true', '操作成功', $stats, 'E0000'); + } + + /** + * 处理正常模式 + */ + private function handleNormalMode(Request $request, array $params, int $companyId) + { + $memberService = new MemberService(); + $memberTagsService = new MemberTagsService(); + $em = app('registry')->getManager('default'); + + $stats = [ + 'success_count' => 0, + 'fail_count' => 0, + 'processed_members' => 0, + 'processed_tags' => 0, + ]; + + try { + app('log')->info('[tagRelationPush] 开始处理(正常模式)', [ + 'company_id' => $companyId, + 'count' => count($params['relations']), + ]); + + // 按会员分组处理 + $memberRelations = []; + foreach ($params['relations'] as $relation) { + $userId = $relation['user_id'] ?? ''; + if (!$userId) { + continue; + } + + if (!isset($memberRelations[$userId])) { + $memberRelations[$userId] = [ + 'mobile' => $relation['mobile'] ?? '', + 'tags' => [], + ]; + } + + $memberRelations[$userId]['tags'][] = $relation; + } + + $stats['processed_members'] = count($memberRelations); + + // 处理每个会员的标签 + foreach ($memberRelations as $userId => $data) { + try { + // 1. 查找会员 + $filter = ['company_id' => $companyId]; + + // 优先用 user_id 查找 + if ($userId) { + $filter['user_id'] = $userId; + $member = $memberService->getMemberInfo($filter); + } + + // 如果没找到,用手机号查找 + if (empty($member) && !empty($data['mobile'])) { + $filter = ['company_id' => $companyId, 'mobile' => $data['mobile']]; + $member = $memberService->getMemberInfo($filter); + } + + if (empty($member)) { + app('log')->warning('[tagRelationPush] 未找到会员', [ + 'company_id' => $companyId, + 'user_id' => $userId, + 'mobile' => $data['mobile'], + ]); + $stats['fail_count']++; + continue; + } + + $actualUserId = $member['user_id']; + + // 2. 先删除该会员的所有标签 + $deleteFilter = [ + 'company_id' => $companyId, + 'user_id' => $actualUserId, + ]; + + $conn = $em->getConnection(); + $conn->beginTransaction(); + + try { + // 删除所有标签关系 + $memberTagsService->deleteRelTagsByUserId($actualUserId, $companyId); + + // 3. 查找并打上新标签 + $tagIds = []; + foreach ($data['tags'] as $tagRelation) { + $wechatTagId = $tagRelation['wechat_tag_id'] ?? null; + $tagId = $tagRelation['tag_id'] ?? null; + + // 查找云店的标签 + $tagFilter = ['company_id' => $companyId]; + + // 优先根据 wechat_tag_id 查找 + if (!empty($wechatTagId)) { + $tagFilter['wechat_tag_id'] = $wechatTagId; + } else if (!empty($tagId)) { + // 否则根据 tag_id 查找 + $tagFilter['tag_id'] = $tagId; + } else { + continue; + } + + $qb = $em->createQueryBuilder(); + $qb->select('t.tag_id') + ->from(MemberTags::class, 't') + ->where('t.company_id = :company_id') + ->setParameter('company_id', $companyId); + + if (!empty($wechatTagId)) { + $qb->andWhere('t.wechat_tag_id = :wechat_tag_id') + ->setParameter('wechat_tag_id', $wechatTagId); + } else { + $qb->andWhere('t.tag_id = :tag_id') + ->setParameter('tag_id', $tagId); + } + + $tag = $qb->getQuery()->getOneOrNullResult(); + + if ($tag) { + $tagIds[] = $tag['tag_id']; + $stats['processed_tags']++; + } else { + app('log')->warning('[tagRelationPush] 未找到标签', [ + 'company_id' => $companyId, + 'wechat_tag_id' => $wechatTagId, + 'tag_id' => $tagId, + ]); + } + } + + // 4. 给会员打上标签(跳过推送到导购平台,避免循环同步) + if (!empty($tagIds)) { + $memberTagsService->createRelTags([$actualUserId], $tagIds, $companyId, true, true); + } + + $conn->commit(); + $stats['success_count']++; + + app('log')->info('[tagRelationPush] 会员标签处理成功', [ + 'company_id' => $companyId, + 'user_id' => $actualUserId, + 'tag_count' => count($tagIds), + ]); + + } catch (\Exception $e) { + $conn->rollback(); + throw $e; + } + + } catch (\Exception $e) { + $stats['fail_count']++; + app('log')->error('[tagRelationPush] 会员标签处理失败', [ + 'company_id' => $companyId, + 'user_id' => $userId, + 'error' => $e->getMessage(), + ]); + } + } + + app('log')->info('[tagRelationPush] 处理完成', [ + 'company_id' => $companyId, + 'stats' => $stats, + ]); + + } catch (\Exception $e) { + app('log')->error('[tagRelationPush] 处理失败', [ + 'company_id' => $companyId, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + $this->api_response('fail', '标签关系推送失败:' . $e->getMessage(), [], 'E9999'); + } + + $this->api_response('true', '操作成功', $stats, 'E0000'); + } + + /** + * @SWG\Post( + * path="/ecx.member.assignMemberToSalesperson", + * summary="分配客户回调通知", + * tags={"会员"}, + * description="导购端分配会员给导购后,通知云店系统更新分配关系", + * @SWG\Parameter( in="query", type="string", required=true, name="method", description="方法名称 ecx.member.assignMemberToSalesperson" ), + * @SWG\Parameter( in="query", type="string", required=true, name="employee_number", description="导购员工编号" ), + * @SWG\Parameter( in="query", type="string", required=true, name="unionid", description="会员unionid" ), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="status", type="string", example="success", description="接口状态"), + * @SWG\Property( property="code", type="string", example="0", description="错误码"), + * @SWG\Property( property="message", type="string", example="分配成功", description="提示信息"), + * @SWG\Property( property="data", type="object", + * @SWG\Property( property="employee_number", type="string", example="SP001", description="导购员工编号"), + * @SWG\Property( property="unionid", type="string", example="unionid_123456", description="会员unionid"), + * @SWG\Property( property="assign_time", type="string", example="2025-12-25 15:30:00", description="分配时间"), + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/OpenapiErrorRespones"))) + * ) + */ + public function assignMemberToSalesperson(Request $request) + { + $companyId = $request->get('auth')['company_id']; + $params = $request->all(); + + // 参数验证 + $rules = [ + 'employee_number' => ['required|string', '请填写导购员工编号'], + 'unionid' => ['required|string', '请填写会员unionid'], + ]; + $error = validator_params($params, $rules); + if ($error) { + $this->api_response('fail', $error, null, 'E4003'); + } + + app('log')->info('分配客户回调通知::params=' . json_encode($params).':companyId='.$companyId); + + try { + + // 2. 根据 unionid 查找会员 + $membersAssociationsRepository = app('registry')->getManager('default')->getRepository(MembersAssociations::class); + $association = $membersAssociationsRepository->get([ + 'unionid' => $params['unionid'], + 'company_id' => $companyId, + 'user_type' => 'wechat' + ]); + + if (!$association) { + app('log')->warning('分配客户回调通知::未找到会员 unionid='.$params['unionid'].':companyId='.$companyId); + $this->api_response('fail', '会员不存在', null, 'E4002'); + } + + $userId = $association['user_id']; + + // 3. 更新会员的分配导购信息(支持幂等性) + $membersRepository = app('registry')->getManager('default')->getRepository(Members::class); + $member = $membersRepository->find($userId); + + if (!$member) { + app('log')->warning('分配客户回调通知::未找到会员记录 user_id='.$userId); + $this->api_response('fail', '会员不存在', null, 'E4002'); + } + + // 幂等性检查:如果已经是分配的同一个导购,直接返回成功 + if ($member->getFpSalesperson() == $params['employee_number'] && $member->getHasFp() == 1) { + app('log')->info('分配客户回调通知::幂等性检查通过,已分配相同导购 user_id='.$userId.',employee_number='.$params['employee_number']); + $assignTime = date('Y-m-d H:i:s'); + $this->api_response('true', '分配成功', [ + 'employee_number' => $params['employee_number'], + 'unionid' => $params['unionid'], + 'assign_time' => $assignTime, + ], '0'); + } + + // 更新分配关系 + $member->setFpSalesperson($params['employee_number']); + $member->setHasFp(1); + + $em = app('registry')->getManager('default'); + $em->persist($member); + $em->flush(); + + app('log')->info('分配客户回调通知::更新成功 user_id='.$userId.',employee_number='.$params['employee_number']); + + // 5. 同步达摩CRM(如果开启) + $dmMemberService = new DmMemberService($companyId); + + // 6. 返回成功响应 + $assignTime = date('Y-m-d H:i:s'); + } catch (\Exception $e) { + app('log')->error('分配客户回调通知::异常::'.$e->getMessage().'::params='.json_encode($params).'::trace='.$e->getTraceAsString()); + $this->api_response('fail', '系统错误:'.$e->getMessage(), null, 'E5001'); + } + $this->api_response('true', '分配成功', [ + 'employee_number' => $params['employee_number'], + 'unionid' => $params['unionid'], + 'assign_time' => $assignTime, + ], '0'); + } + + /** + * @SWG\Post( + * path="/ecx.member.notifyBecomeFriend", + * summary="导购通知加好友", + * tags={"会员"}, + * description="导购端通知云店,已分配的客户已经加导购为好友", + * @SWG\Parameter( in="query", type="string", required=true, name="method", description="方法名称 ecx.member.notifyBecomeFriend" ), + * @SWG\Parameter( in="query", type="string", required=true, name="app_key", description="app_key" ), + * @SWG\Parameter( in="query", type="string", required=true, name="version", description="版本号" ), + * @SWG\Parameter( in="query", type="string", required=true, name="timestamp", description="请求时间" ), + * @SWG\Parameter( in="query", type="string", required=true, name="sign", description="签名" ), + * @SWG\Parameter( in="query", type="string", required=true, name="unionid", description="会员unionid" ), + * @SWG\Parameter( in="query", type="string", required=true, name="salesperson_code", description="导购编号(导购的employee_number)" ), + * @SWG\Parameter( in="query", type="integer", required=true, name="is_become_friend", description="是否已加为好友,固定值:1" ), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="status", type="string", example="success", description="接口状态"), + * @SWG\Property( property="code", type="string", example="0", description="错误码"), + * @SWG\Property( property="message", type="string", example="success", description="提示信息"), + * @SWG\Property( property="data", type="object", description="返回数据"), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/OpenapiErrorRespones"))) + * ) + */ + public function notifyBecomeFriend(Request $request) + { + $companyId = $request->get('auth')['company_id']; + $params = $request->all(); + + // 参数验证 + $rules = [ + 'unionid' => ['required|string', '请填写会员unionid'], + 'salesperson_code' => ['required|string', '请填写导购编号'], + 'is_become_friend' => ['required|integer|in:1', 'is_become_friend必须为1'], + ]; + $error = validator_params($params, $rules); + if ($error) { + $this->api_response('fail', $error, null, 'E0001'); + } + + app('log')->info('导购通知加好友::params=' . json_encode($params) . ':companyId=' . $companyId); + + try { + // 调用 Service 处理核心业务逻辑 + $memberService = new MemberService(); + $result = $memberService->notifyBecomeFriend( + $companyId, + $params['unionid'], + $params['salesperson_code'] + ); + + // 返回成功响应 + $this->api_response('success', 'success', [], '0'); + + } catch (\Exception $e) { + app('log')->error('导购通知加好友::异常::' . $e->getMessage() . '::params=' . json_encode($params) . '::trace=' . $e->getTraceAsString()); + + // 根据异常消息返回相应的错误码 + $errorCode = 'E5001'; + $errorMessage = '系统错误:' . $e->getMessage(); + + if (strpos($e->getMessage(), '会员不存在') !== false) { + $errorCode = 'E4002'; + $errorMessage = $e->getMessage(); + } elseif (strpos($e->getMessage(), '未分配给该导购') !== false) { + $errorCode = 'E4004'; + $errorMessage = $e->getMessage(); + } + + $this->api_response('fail', $errorMessage, null, $errorCode); + } + } + + /** + * @SWG\Get( + * path="/ecx.member.listFp", + * summary="会员列表查询(增强版)", + * tags={"会员"}, + * description="会员列表查询,支持分页、生日范围、标签、分配状态、导购编号等筛选", + * @SWG\Parameter( in="query", type="string", required=true, name="method", description="方法名称 ecx.member.listFp" ), + * @SWG\Parameter( in="query", type="string", required=true, name="app_key", description="app_key" ), + * @SWG\Parameter( in="query", type="string", required=true, name="version", description="版本号" ), + * @SWG\Parameter( in="query", type="string", required=true, name="timestamp", description="请求时间" ), + * @SWG\Parameter( in="query", type="string", required=true, name="sign", description="签名" ), + * @SWG\Parameter( in="query", type="integer", required=false, name="page", description="页码,默认1" ), + * @SWG\Parameter( in="query", type="integer", required=false, name="page_size", description="每页数量,默认10" ), + * @SWG\Parameter( in="query", type="string", required=false, name="birthday_start", description="生日开始日期,格式:YYYY-MM-DD" ), + * @SWG\Parameter( in="query", type="string", required=false, name="birthday_end", description="生日结束日期,格式:YYYY-MM-DD" ), + * @SWG\Parameter( in="query", type="array", required=false, name="tag_id", description="标签ID,支持多个,格式:tag_id[]=1&tag_id[]=2" ), + * @SWG\Parameter( in="query", type="string", required=false, name="type", description="分配状态:noassign=未分配,assign=已分配" ), + * @SWG\Parameter( in="query", type="string", required=false, name="salesperson_code", description="导购编号(work_userid)" ), + * @SWG\Parameter( in="query", type="string", required=false, name="keyword", description="关键词(用于按手机号模糊查询)" ), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="status", type="string", example="success", description="接口状态"), + * @SWG\Property( property="code", type="string", example="E0000", description="错误码"), + * @SWG\Property( property="message", type="string", example="操作成功", description="提示信息"), + * @SWG\Property( property="data", type="object", + * @SWG\Property( property="count", type="integer", example=100, description="总数量"), + * @SWG\Property( property="list", type="array", description="会员列表", + * @SWG\Items(type="object") + * ), + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/OpenapiErrorRespones"))) + * ) + */ + public function memberList(Request $request) + { + $companyId = $request->get('auth')['company_id']; + $params = $request->all(); + + // 参数验证 + $rules = [ + 'scope' => ['sometimes|in:fp,customer', 'scope参数错误,应为fp或customer'], + 'page' => ['sometimes|integer|min:1', '页码必须为正整数'], + 'page_size' => ['sometimes|integer', '每页数量必须在1-500之间'], + 'birthday_start' => ['sometimes|date_format:Y-m-d', '生日开始日期格式错误,应为YYYY-MM-DD'], + 'birthday_end' => ['sometimes|date_format:Y-m-d', '生日结束日期格式错误,应为YYYY-MM-DD'], + 'tag_id' => ['sometimes|array', '标签ID必须为数组'], + 'tag_id.*' => ['sometimes|integer', '标签ID数组中的每个元素必须为整数'], + 'type' => ['sometimes|in:noassign,assign', '分配状态类型错误,应为noassign或assign'], + 'salesperson_code' => ['sometimes|string', '导购编号必须为字符串'], + 'store_bn' => ['sometimes|string', '门店编号必须为字符串'], + 'point_start' => ['sometimes|integer|min:0', '积分开始值必须为非负整数'], + 'point_end' => ['sometimes|integer|min:0', '积分结束值必须为非负整数'], + 'grade_id' => ['sometimes|integer|min:1', '等级ID必须为正整数'], + 'buy_start' => ['sometimes|integer|min:0', '购买金额开始值必须为非负整数'], + 'buy_end' => ['sometimes|integer|min:0', '购买金额结束值必须为非负整数'], + 'keyword' => ['sometimes|string', '关键词(用于按手机号查询)'], + ]; + $error = validator_params($params, $rules); + if ($error) { + $this->api_response('fail', $error, null, 'E0001'); + } + + // 如果 scope 为 customer,走特殊逻辑 + $scope = $params['scope'] ?? 'fp'; + if ($scope === 'customer') { + return $this->getCustomerUnionids($request, $companyId, $params); + } + + // 分页参数 + $page = isset($params['page']) ? (int)$params['page'] : 1; + $pageSize = isset($params['page_size']) ? (int)$params['page_size'] : 10; + + // 构建过滤条件 + $filter = [ + 'company_id' => $companyId, + ]; + + // 生日范围查询 + if (!empty($params['birthday_start'])) { + $filter['birthday|gte'] = $params['birthday_start']; + } + if (!empty($params['birthday_end'])) { + $filter['birthday|lte'] = $params['birthday_end']; + } + + // 标签查询(支持数组) + if (!empty($params['tag_id'])) { + // 如果是单个值,转换为数组 + if (!is_array($params['tag_id'])) { + $params['tag_id'] = [(int)$params['tag_id']]; + } else { + // 确保数组中的值都是整数 + $params['tag_id'] = array_map('intval', $params['tag_id']); + } + $filter['tag_id'] = $params['tag_id']; + } + + // 分配状态查询 + if (!empty($params['type'])) { + if ($params['type'] == 'noassign') { + $filter['has_fp'] = 0; + } elseif ($params['type'] == 'assign') { + $filter['has_fp'] = 1; + $filter['is_become_friend'] = 0; + } + } + + // 导购编号查询 + if (!empty($params['salesperson_code'])) { + $filter['fp_salesperson'] = $params['salesperson_code']; + } + + // 门店编号查询(根据store_bn查询op_distributor) + if (!empty($params['store_bn'])) { + $distributorService = new DistributorService(); + $distributorInfo = $distributorService->getInfoSimple([ + 'company_id' => $companyId, + 'shop_code' => $params['store_bn'] + ]); + + if ($distributorInfo && !empty($distributorInfo['distributor_id'])) { + $filter['op_distributor'] = $distributorInfo['distributor_id']; + } else { + // 如果门店不存在,返回空结果 + $this->api_response('true', '操作成功', ['count' => 0, 'list' => []], 'E0000'); + } + } + + // 积分范围查询 + if (!empty($params['point_start'])) { + $filter['point|gte'] = (int)$params['point_start']; + } + if (!empty($params['point_end'])) { + $filter['point|lte'] = (int)$params['point_end']; + } + + // 等级查询 + if (!empty($params['grade_id'])) { + $filter['grade_id'] = (int)$params['grade_id']; + } + + // 关键词查询(按手机号模糊查询) + if (!empty($params['keyword'])) { + $filter['mobile|like'] = trim($params['keyword']); + } + + // 调用会员服务获取列表和总数 + $memberService = new MemberService(); + + // 获取总数 + $totalCount = $memberService->getMemberCount($filter); + + // 获取列表 + $memberList = $memberService->getMemberList($filter, $page, $pageSize, ['created' => 'DESC']); + + // 获取会员的unionid信息(getMemberList已经包含了unionid,但我们需要确保数据一致性) + $userIdList = array_column($memberList, 'user_id'); + $unionidMap = []; + if (!empty($userIdList)) { + $membersAssociationsRepository = app('registry')->getManager('default')->getRepository(MembersAssociations::class); + $associations = $membersAssociationsRepository->lists([ + 'user_id' => $userIdList, + 'company_id' => $companyId, + 'user_type' => 'wechat' + ], 'user_id,unionid', 1, -1); + + if (!empty($associations)) { + foreach ($associations as $assoc) { + $unionidMap[$assoc['user_id']] = $assoc['unionid'] ?? ''; + } + } + } + + // 处理返回数据,添加unionid和其他信息 + $memberBrowseHistoryService = new MemberBrowseHistoryService(); + $itemService = new ItemsService(); + $orderService = $this->getOrderService('normal'); + + foreach ($memberList as $key => &$value) { + // 确保unionid存在 + if (empty($value['unionid']) && isset($unionidMap[$value['user_id']])) { + $value['unionid'] = $unionidMap[$value['user_id']]; + } + + // 消费总额 + $total_amount = $orderService->sum(['user_id' => $value['user_id'], 'company_id' => $companyId], 'total_fee'); + $value['total_amount'] = $total_amount; + + // 浏览历史 + $browseHistory = $memberBrowseHistoryService->lists(['user_id' => $value['user_id'], 'company_id' => $companyId], 1, 1, ['updated' => 'DESC']); + if ($browseHistory['list']) { + $latestItem = $itemService->getItem(['item_id' => $browseHistory['list'][0]['item_id']]); + $value['browse_count'] = $browseHistory['total_count']; + $value['browse_time'] = date('Y-m-d H:i:s', $browseHistory['list'][0]['updated']); + $value['browse_item_name'] = $latestItem['item_name'] ?? null; + $value['browse_item_id'] = $browseHistory['list'][0]['item_id']; + } else { + $value['browse_count'] = 0; + $value['browse_time'] = ''; + $value['browse_item_name'] = null; + $value['browse_item_id'] = null; + } + } + unset($value); + + $return = [ + 'count' => $totalCount, + 'list' => $memberList + ]; + app('log')->info('david-memberList--->'. json_encode($return)); + $this->api_response('true', '操作成功', $return, 'E0000'); + } + + /** + * 获取导购客户 unionid 列表(scope=customer 时使用) + * + * @param Request $request + * @param int $companyId + * @param array $params + * @return \Illuminate\Http\Response + */ + private function getCustomerUnionids(Request $request, int $companyId, array $params) + { + // 必须提供导购编号 + if (empty($params['salesperson_code'])) { + return $this->api_response('fail', 'scope为customer时,salesperson_code必填', null, 'E0001'); + } + + // 调用导购端接口获取所有 unionid(不带其他条件) + try { + $marketingCenterRequest = new MarketingCenterRequest(); + $requestData = [ + 'employee_number' => $params['salesperson_code'], + ]; + + $result = $marketingCenterRequest->call($companyId, 'basics.salesperson.getBindMemberUnionids', $requestData); + + app('log')->info('获取导购客户unionid列表:导购端返回结果', [ + 'company_id' => $companyId, + 'salesperson_code' => $params['salesperson_code'], + 'result' => $result, + ]); + + // 处理返回结果 + if (empty($result) || !isset($result['errcode']) || $result['errcode'] != 0) { + $errorMsg = $result['errmsg'] ?? '获取导购客户unionid列表失败'; + app('log')->warning('获取导购客户unionid列表:接口调用失败', [ + 'company_id' => $companyId, + 'salesperson_code' => $params['salesperson_code'], + 'error' => $errorMsg, + 'result' => $result, + ]); + return $this->api_response('true', '操作成功', [], 'E0000'); + } + + // 获取 unionid 列表 + $unionids = $result['data']['unionids'] ?? []; + if (empty($unionids) || !is_array($unionids)) { + return $this->api_response('true', '操作成功', [], 'E0000'); + } + + // 根据 unionid 查询 user_id + $membersAssociationsRepository = app('registry')->getManager('default')->getRepository(MembersAssociations::class); + $associations = $membersAssociationsRepository->lists([ + 'unionid' => $unionids, + 'company_id' => $companyId, + 'user_type' => 'wechat' + ], 'user_id,unionid', 1, -1); + + if (empty($associations)) { + return $this->api_response('true', '操作成功', [], 'E0000'); + } + + // 构建 user_id 和 unionid 的映射 + $userIdList = array_column($associations, 'user_id'); + $unionidMap = []; + foreach ($associations as $assoc) { + $unionidMap[$assoc['user_id']] = $assoc['unionid']; + } + + // 构建过滤条件 + $filter = [ + 'company_id' => $companyId, + 'user_id' => $userIdList, + ]; + + // 等级查询 + if (!empty($params['grade_id'])) { + $filter['grade_id'] = (int)$params['grade_id']; + } + + // 积分范围查询 + if (!empty($params['point_start'])) { + $filter['point|gte'] = (int)$params['point_start']; + } + if (!empty($params['point_end'])) { + $filter['point|lte'] = (int)$params['point_end']; + } + + // 调用会员服务获取符合条件的会员列表 + $memberService = new MemberService(); + $memberList = $memberService->getMemberList($filter, 1, -1, ['created' => 'DESC']); + + // 如果设置了购买金额条件,需要进一步过滤 + $filteredUserIds = array_column($memberList, 'user_id'); + + if (!empty($params['buy_start']) || !empty($params['buy_end'])) { + $orderService = $this->getOrderService('normal'); + $finalUserIds = []; + + foreach ($filteredUserIds as $userId) { + // 计算该会员的购买总额 + $totalAmount = $orderService->sum(['user_id' => $userId, 'company_id' => $companyId], 'total_fee'); + + // 判断是否满足购买金额条件 + $meetBuyCondition = true; + if (!empty($params['buy_start']) && $totalAmount < (int)$params['buy_start']) { + $meetBuyCondition = false; + } + if (!empty($params['buy_end']) && $totalAmount > (int)$params['buy_end']) { + $meetBuyCondition = false; + } + + if ($meetBuyCondition) { + $finalUserIds[] = $userId; + } + } + + $filteredUserIds = $finalUserIds; + } + + // 根据过滤后的 user_id 获取对应的 unionid + $finalUnionids = []; + foreach ($filteredUserIds as $userId) { + if (isset($unionidMap[$userId])) { + $finalUnionids[] = $unionidMap[$userId]; + } + } + + return $this->api_response('true', '操作成功', $finalUnionids, 'E0000'); + + } catch (\Exception $e) { + app('log')->error('获取导购客户unionid列表:系统异常', [ + 'company_id' => $companyId, + 'salesperson_code' => $params['salesperson_code'], + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + return $this->api_response('fail', '获取导购客户unionid列表失败:' . $e->getMessage(), [], 'E9999'); + } + } + + /** + * @SWG\Get( + * path="/ecx.member.cardGrades", + * summary="获取会员卡等级列表", + * tags={"会员"}, + * description="获取会员卡等级列表,包括等级信息、会员数量等", + * @SWG\Parameter( in="query", type="string", required=true, name="method", description="方法名称 ecx.member.cardGrades" ), + * @SWG\Parameter( in="query", type="string", required=true, name="app_key", description="app_key" ), + * @SWG\Parameter( in="query", type="string", required=true, name="version", description="版本号" ), + * @SWG\Parameter( in="query", type="string", required=true, name="timestamp", description="请求时间" ), + * @SWG\Parameter( in="query", type="string", required=true, name="sign", description="签名" ), + * @SWG\Response( response=200, description="成功返回结构", @SWG\Schema( + * @SWG\Property( property="status", type="string", example="true", description="接口状态"), + * @SWG\Property( property="code", type="string", example="E0000", description="错误码"), + * @SWG\Property( property="message", type="string", example="操作成功", description="提示信息"), + * @SWG\Property( property="data", type="array", description="会员卡等级列表", + * @SWG\Items( type="object", + * @SWG\Property( property="grade_id", type="integer", example=1, description="等级ID"), + * @SWG\Property( property="company_id", type="integer", example=1001, description="企业ID"), + * @SWG\Property( property="grade_name", type="string", example="普通会员", description="等级名称"), + * @SWG\Property( property="default_grade", type="boolean", example=true, description="是否默认等级"), + * @SWG\Property( property="background_pic_url", type="string", example="https://example.com/bg.jpg", description="背景图片URL"), + * @SWG\Property( property="promotion_condition", type="object", description="升级条件", + * @SWG\Property( property="total_consumption", type="integer", example=10000, description="累计消费金额(分)"), + * @SWG\Property( property="total_order_count", type="integer", example=10, description="累计订单数"), + * ), + * @SWG\Property( property="privileges", type="object", description="等级权益", + * @SWG\Property( property="discount", type="integer", example=95, description="折扣(百分比,如95表示95折)"), + * @SWG\Property( property="point_rate", type="integer", example=110, description="积分倍率(百分比,如110表示1.1倍)"), + * ), + * @SWG\Property( property="description", type="string", example="普通会员等级", description="等级描述"), + * @SWG\Property( property="grade_background", type="string", example="#FF0000", description="等级背景色"), + * @SWG\Property( property="member_count", type="integer", example=100, description="该等级下的会员数量"), + * @SWG\Property( property="crm_open", type="string", example="false", description="CRM是否开启"), + * ), + * ), + * )), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/OpenapiErrorRespones"))) + * ) + */ + public function getMemberCardGrades(Request $request) + { + $companyId = $request->get('auth')['company_id']; + + try { + $memberCardService = new MemberCardService(); + $isMemberCount = true; // 包含会员数量统计 + $result = $memberCardService->getCompanyGradeSimpleList($companyId); + + + } catch (\Exception $e) { + app('log')->error('获取会员卡等级列表失败::' . $e->getMessage() . '::companyId=' . $companyId . '::trace=' . $e->getTraceAsString()); + $this->api_response('fail', '获取会员卡等级列表失败:' . $e->getMessage(), [], 'E9999'); + } + $this->api_response('true', '操作成功', $result, 'E0000'); + } } diff --git a/src/OpenapiBundle/Http/ThirdApi/V1/Action/Wxapp.php b/src/OpenapiBundle/Http/ThirdApi/V1/Action/Wxapp.php index e23eaca..f5cf21b 100644 --- a/src/OpenapiBundle/Http/ThirdApi/V1/Action/Wxapp.php +++ b/src/OpenapiBundle/Http/ThirdApi/V1/Action/Wxapp.php @@ -63,7 +63,7 @@ class Wxapp extends Controller } app('log')->debug('daogouapi - wxapp/wxcode - scene : '.print_r($params['scene'], true)); $rules = [ - 'path_type' => ['required|in:index,goods_list,goods_detail,recommend_list,recommend_detail','参数错误'], + 'path_type' => ['required|in:index,goods_list,goods_detail,recommend_list,recommend_detail,share_land','参数错误'], 'scene' => ['required', '参数错误'], 'scene.id' => ['required_if:path_type,goods_detail,recommend_detail|integer|min:1','参数错误'], ]; diff --git a/src/OpenapiBundle/Traits/OpenapiRoutes.php b/src/OpenapiBundle/Traits/OpenapiRoutes.php index fc4310e..082b0e7 100644 --- a/src/OpenapiBundle/Traits/OpenapiRoutes.php +++ b/src/OpenapiBundle/Traits/OpenapiRoutes.php @@ -38,9 +38,16 @@ trait OpenapiRoutes 'ecx.member.basicInfo' => ['uses' => 'Member@basicInfo'], //会员基础信息 'ecx.member.orderList' => ['uses' => 'Member@getMemberOrderLists'], //会员订单列表,已完成订单 'ecx.member.browserHistoryList' => ['uses' => 'Member@geMembertBrowseList'], //会员浏览足迹 - 'ecx.member.list' => ['uses' => 'Member@memberInfoList'], //会员基础信息 + 'ecx.member.listFp' => ['uses' => 'Member@memberList'], //会员列表查询(增强版,支持分配导购筛选) + 'ecx.member.list' => ['uses' => 'Member@memberInfoList'], //会员基础信息列表 'ecx.member.frequentItems' => ['uses' => 'Member@frequentItems'], //会员常购清单 'ecx.member.browserHistory' => ['uses' => 'Member@browseHistory'], //会员浏览足迹 + 'ecx.member.assignMemberToSalesperson' => ['uses' => 'Member@assignMemberToSalesperson'], //分配客户回调通知 + 'ecx.member.notifyBecomeFriend' => ['uses' => 'Member@notifyBecomeFriend'], //导购通知加好友 + 'ecx.member.cardGrades' => ['uses' => 'Member@getMemberCardGrades'], //获取会员卡等级列表 + 'ecx.member.tagLibrary' => ['uses' => 'Member@tagLibrary'], //获取标签库(标签和标签组) + 'ecx.member.tagLibrary.push' => ['uses' => 'Member@tagLibraryPush'], //推送标签库到云店 + 'ecx.member.tag.relation.push' => ['uses' => 'Member@tagRelationPush'], //导购推送会员标签关系到云店 'ecx.order.list' => ['uses' => 'Order@list'], //会员订单信息 'ecx.salesperson.push' => ['uses' => 'ShopSalesperson@pushSalesperson'], //创建更新导购 'ecx.salesperson.bathStatusUpdate' => ['uses' => 'ShopSalesperson@bathUpdateSalespersonStatus'], //更新导购状态 diff --git a/src/OrdersBundle/Services/Orders/AbstractNormalOrder.php b/src/OrdersBundle/Services/Orders/AbstractNormalOrder.php index aefebcc..05145a7 100644 --- a/src/OrdersBundle/Services/Orders/AbstractNormalOrder.php +++ b/src/OrdersBundle/Services/Orders/AbstractNormalOrder.php @@ -4175,12 +4175,46 @@ class AbstractNormalOrder implements OrderInterface } public function saveOrderRelZiti($params) { - $filter = [ - 'company_id' => $params['company_id'], - 'id' => $params['pickup_location'], - ]; - $pickupLocationService = new PickupLocationService(); - $pickupLocation = $pickupLocationService->getInfo($filter); + $pickupLocation = null; + + // 判断是否是店铺地址(负数ID) + if ($params['pickup_location'] < 0) { + // 从店铺表获取信息 + $distributorId = abs($params['pickup_location']); + $distributorService = new DistributorService(); + $distributor = $distributorService->getInfoSimple([ + 'company_id' => $params['company_id'], + 'distributor_id' => $distributorId + ]); + + if (!$distributor) { + throw new ResourceException('店铺不存在'); + } + + // 构造自提点格式的数据 + $pickupLocation = [ + 'name' => $distributor['name'], + 'lng' => $distributor['lng'], + 'lat' => $distributor['lat'], + 'province' => $distributor['province'] ?? '', + 'city' => $distributor['city'] ?? '', + 'area' => $distributor['area'] ?? '', + 'address' => $distributor['address'] ?? '', + 'contract_phone' => $distributor['mobile'] ?? '', // 使用 mobile 字段 + ]; + } else { + // 原有逻辑:从自提点表获取 + $filter = [ + 'company_id' => $params['company_id'], + 'id' => $params['pickup_location'], + ]; + $pickupLocationService = new PickupLocationService(); + $pickupLocation = $pickupLocationService->getInfo($filter); + } + + if (!$pickupLocation) { + throw new ResourceException('自提点不存在'); + } $data = [ 'company_id' => $params['company_id'], diff --git a/src/PaymentBundle/Services/Payments/OfflinePayService.php b/src/PaymentBundle/Services/Payments/OfflinePayService.php index 08aa35d..6a8ce9f 100644 --- a/src/PaymentBundle/Services/Payments/OfflinePayService.php +++ b/src/PaymentBundle/Services/Payments/OfflinePayService.php @@ -17,11 +17,12 @@ namespace PaymentBundle\Services\Payments; +use PaymentBundle\Interfaces\Payment; +use Dingo\Api\Exception\ResourceException; +use OrdersBundle\Traits\GetOrderServiceTrait; +use CompanysBundle\Services\CommonLangModService; use GoodsBundle\Services\MultiLang\MagicLangTrait; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Dingo\Api\Exception\ResourceException; -use PaymentBundle\Interfaces\Payment; -use OrdersBundle\Traits\GetOrderServiceTrait; class OfflinePayService implements Payment { @@ -46,7 +47,7 @@ class OfflinePayService implements Payment if(!empty($data['pay_name'])){ app('redis')->set($companyId.'_lang_pay_name_offline_pay:'.$lang,$data['pay_name']); } - $redisKey = $this->genReidsId($companyId); + $redisKey = $this->genReidsId($companyId, $lang); $result = app('redis')->set($redisKey, json_encode($data)); return $result; } @@ -58,7 +59,7 @@ class OfflinePayService implements Payment { $lang = $this->getLang(); $exitLangName = app('redis')->get($companyId.'_lang_pay_name_offline_pay:'.$lang); - $data = app('redis')->get($this->genReidsId($companyId)); + $data = app('redis')->get($this->genReidsId($companyId, $lang)); if ($data) { $data = json_decode($data, true); if(!empty($exitLangName)){ @@ -91,9 +92,13 @@ class OfflinePayService implements Payment /** * 获取redis存储的ID */ - private function genReidsId($companyId) + private function genReidsId($companyId, $lang = '') { - return $this->payType . 'Setting:' . sha1($companyId); + if (!empty($lang)) { + return $this->payType . 'Setting:' . sha1($companyId) . ':' . $lang; + }else { + return $this->payType . 'Setting:' . sha1($companyId); + } } /** diff --git a/src/PaymentBundle/Services/Payments/WechatPayService.php b/src/PaymentBundle/Services/Payments/WechatPayService.php index 79cd1a9..ec82553 100644 --- a/src/PaymentBundle/Services/Payments/WechatPayService.php +++ b/src/PaymentBundle/Services/Payments/WechatPayService.php @@ -58,7 +58,7 @@ class WechatPayService implements Payment } if ($cert = $data['cert']) { if ($cert->getClientOriginalName() != 'apiclient_cert.pem') { - throw new BadRequestHttpException('请上传apiclient_cert.pem'); + throw new BadRequestHttpException(trans('payment.cert_file_name_error')); } //$this->getFileSystem()->putFileAs('wechatPayment/' . $data['merchant_id'], $cert, 'apiclient_cert.pem'); $data['cert'] = file_get_contents($cert); @@ -68,14 +68,31 @@ class WechatPayService implements Payment if ($certKey = $data['cert_key']) { if ($certKey->getClientOriginalName() != 'apiclient_key.pem') { - throw new BadRequestHttpException('请上传apiclient_key.pem'); + throw new BadRequestHttpException(trans('payment.cert_key_file_name_error')); } //$this->getFileSystem()->putFileAs('wechatPayment/' . $data['merchant_id'], $certKey, 'apiclient_key.pem'); $data['cert_key'] = file_get_contents($certKey); } else { $data['cert_key'] = $redisData['cert_key'] ?? null; } - + + // 验证必填字段 + if (empty($data['app_id'])) { + throw new BadRequestHttpException(trans('payment.app_id_required')); + } + if (empty($data['merchant_id'])) { + throw new BadRequestHttpException(trans('payment.merchant_id_required')); + } + if (empty($data['key'])) { + throw new BadRequestHttpException(trans('payment.key_required')); + } + if (empty($data['cert'])) { + throw new BadRequestHttpException(trans('payment.cert_required')); + } + if (empty($data['cert_key'])) { + throw new BadRequestHttpException(trans('payment.cert_key_required')); + } + if (isset($data['app_id']) && $data['app_id']) { app('redis')->set('wechatPayment:companyId:' . $data['app_id'], $companyId); } @@ -86,7 +103,7 @@ class WechatPayService implements Payment if (isset($data['is_servicer']) && $data['is_servicer'] == 'true') { if (!$data['servicer_merchant_id'] || !$data['servicer_app_id']) { - throw new BadRequestHttpException('开启特约商户服务商APPID和服务商商户号必填!'); + throw new BadRequestHttpException(trans('payment.servicer_info_required')); } app('redis')->set('wechatServicerPayment:companyId:' . $data['servicer_app_id'], $companyId); @@ -157,8 +174,13 @@ class WechatPayService implements Payment app('redis')->set($this->genReidsId($companyId), json_encode($data)); } } - $data['cert_name'] = 'apiclient_cert.pem'; - $data['cert_url'] = app('filesystem')->path($certFile); + if(isset($data['cert']) && $data['cert']) { + $data['cert_name'] = 'apiclient_cert.pem'; + $data['cert_url'] = app('filesystem')->path($certFile); + } else { + $data['cert_name'] = ''; + $data['cert_url'] = ''; + } //商户证书秘钥 $certKeyFile = 'wechatPayment/' . $data['merchant_id'] . '/apiclient_key.pem'; @@ -188,8 +210,13 @@ class WechatPayService implements Payment app('redis')->set($this->genReidsId($companyId), json_encode($data)); } } - $data['cert_key_name'] = 'apiclient_key.pem'; - $data['cert_key_url'] = app('filesystem')->path($certKeyFile); + if(isset($data['cert_key']) && $data['cert_key']) { + $data['cert_key_name'] = 'apiclient_key.pem'; + $data['cert_key_url'] = app('filesystem')->path($certKeyFile); + } else { + $data['cert_key_name'] = ''; + $data['cert_key_url'] = ''; + } $data['app_app_id'] = $data['app_app_id'] ?? ''; $data['is_servicer'] = $data['is_servicer'] ?? 'false'; return $data; diff --git a/src/PointsmallBundle/Repositories/PointsmallItemsRepository.php b/src/PointsmallBundle/Repositories/PointsmallItemsRepository.php index fb65551..53a6184 100644 --- a/src/PointsmallBundle/Repositories/PointsmallItemsRepository.php +++ b/src/PointsmallBundle/Repositories/PointsmallItemsRepository.php @@ -18,11 +18,15 @@ namespace PointsmallBundle\Repositories; use Doctrine\ORM\EntityRepository; -use PointsmallBundle\Entities\PointsmallItems; use Doctrine\Common\Collections\Criteria; +use PointsmallBundle\Entities\PointsmallItems; +use GoodsBundle\Services\MultiLang\MagicLangTrait; +use GoodsBundle\Services\MultiLang\MultiLangService; class PointsmallItemsRepository extends EntityRepository { + use MagicLangTrait; + /** * 当前表名称 */ @@ -36,6 +40,12 @@ class PointsmallItemsRepository extends EntityRepository 'intro', 'audit_status', 'audit_reason', 'crossborder_tax_rate','origincountry_id','type', 'pay_class' ]; + private $prk = 'item_id'; + + private $multiLangField = [ + 'item_name','brief','intro' + ]; + /** * 添加商品 */ @@ -50,6 +60,10 @@ class PointsmallItemsRepository extends EntityRepository $em->flush(); $result = $this->getColumnNamesData($itemsEnt, $this->cols); + + $service = new MultiLangService(); + $service->addMultiLangByParams($result['item_id'],$params,$this->table, $this->multiLangField); +// $service->saveLang($result['company_id'],$langBag,$this->table,$result['item_id'],$this->table); return $result; } @@ -200,8 +214,19 @@ class PointsmallItemsRepository extends EntityRepository } $qb = $this->__filter($filter, $qb); - - return $qb->execute(); + if(isset($filter[$this->prk])){ + if(is_array($filter[$this->prk])){ + foreach ($filter[$this->prk] as $pprk){ + //更新数据 + $service = new MultiLangService(); + $service->updateLangDataNew($data,$this->table,$pprk, $this->multiLangField, $filter['company_id'] ?? 0); + } + }else{ + $service = new MultiLangService(); + $service->updateLangDataNew($data,$this->table,$filter[$this->prk], $this->multiLangField, $filter['company_id'] ?? 0); + } + } + return $qb->set('updated', time())->execute(); } @@ -272,8 +297,9 @@ class PointsmallItemsRepository extends EntityRepository $em = $this->getEntityManager(); $em->persist($itemsEnt); $em->flush(); - $result = $this->getColumnNamesData($itemsEnt); + $service = new MultiLangService(); + $service->updateLangDataNew($params,$this->table,$item_id, $this->multiLangField,$result['company_id'] ?? 0); return $result; } @@ -303,7 +329,12 @@ class PointsmallItemsRepository extends EntityRepository return []; } - return $this->getColumnNamesData($entity); + $result = $this->getColumnNamesData($entity); + //替换语言 + $service = new MultiLangService(); + $lang = $this->getLang(); + $result = $service->getOneLangData($result,$this->multiLangField,$this->table,$lang,$result['item_id'],$this->table); + return $result; } /** @@ -317,6 +348,9 @@ class PointsmallItemsRepository extends EntityRepository } $result = $this->getColumnNamesData($itemsEnt); + $service = new MultiLangService(); + $lang = $this->getLang(); + $result = $service->getOneLangData($result,$this->multiLangField,$this->table,$lang,$result['item_id'],$this->table); return $result; } @@ -387,6 +421,9 @@ class PointsmallItemsRepository extends EntityRepository public function list($filter, $orderBy = [], $pageSize = 100, $page = 1, $columns = null) { $criteria = Criteria::create(); + // 多语言处理filter + $service = new MultiLangService(); + $filter = $service->filterLang($filter, $this->multiLangField, $this->table, $this->prk); if ($filter) { foreach ($filter as $field => $value) { $list = explode('|', $field); @@ -427,6 +464,18 @@ class PointsmallItemsRepository extends EntityRepository } } $res['list'] = $newItemsList; + if(empty($res['list'])){ + return $res; + } + $service = new MultiLangService(); + $res['list'] = $service->getListAddLang($res['list'],$this->multiLangField,$this->table,$this->getLang(),$this->prk); + + // 历史原因特使处理 + // 重新赋值多语言字段 + foreach ($res['list'] as $k => &$v) { + $v['itemName'] = $v['item_name'] ?? ''; + } + return $res; } @@ -533,8 +582,14 @@ class PointsmallItemsRepository extends EntityRepository { $conn = app('registry')->getConnection('default'); $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + // 多语言处理filter + $service = new MultiLangService(); + $filter = $service->filterLang($filter, $this->multiLangField, $this->table, $this->prk); + $qb = $this->__filter($filter, $qb); $lists = $qb->execute()->fetchAll(); + $lists = $service->getListAddLang($lists,$this->multiLangField,$this->table,$this->getLang(),$this->prk); + return $lists; } diff --git a/src/PointsmallBundle/Services/ItemsService.php b/src/PointsmallBundle/Services/ItemsService.php index bddb939..bf5b42d 100644 --- a/src/PointsmallBundle/Services/ItemsService.php +++ b/src/PointsmallBundle/Services/ItemsService.php @@ -17,24 +17,25 @@ namespace PointsmallBundle\Services; +use GoodsBundle\Entities\ItemsMedicine; +use WechatBundle\Services\OpenPlatform; +use WechatBundle\Services\WeappService; +use OrdersBundle\Services\RightsService; +use Dingo\Api\Exception\ResourceException; +use CompanysBundle\Services\ArticleService; use CompanysBundle\Services\SettingService; use CrossBorderBundle\Entities\OriginCountry; -use GoodsBundle\Entities\ItemsMedicine; use GoodsBundle\Jobs\MedicineItemsSubmitAudit; -use GoodsBundle\Repositories\ItemsMedicineRepository; +use GoodsBundle\Services\ItemsCategoryService; use GoodsBundle\Services\ItemsMedicineService; use PointsmallBundle\Entities\PointsmallItems; -use PointsmallBundle\Entities\PointsmallItemRelAttributes; -use Dingo\Api\Exception\ResourceException; -use WechatBundle\Services\OpenPlatform; -use OrdersBundle\Services\RightsService; -use OrdersBundle\Services\Rights\TimesCardService; -use CompanysBundle\Services\ArticleService; -use WechatBundle\Services\Material as MaterialService; -use WechatBundle\Services\WeappService; -use OrdersBundle\Services\ShippingTemplatesService; -use GoodsBundle\Services\ItemsCategoryService; use GoodsBundle\Services\ItemsAttributesService; +use OrdersBundle\Services\Rights\TimesCardService; +use OrdersBundle\Services\ShippingTemplatesService; +use GoodsBundle\Services\MultiLang\MultiLangService; +use GoodsBundle\Repositories\ItemsMedicineRepository; +use WechatBundle\Services\Material as MaterialService; +use PointsmallBundle\Entities\PointsmallItemRelAttributes; // use PointsmallBundle\Services\ItemTaxRateService; @@ -307,7 +308,6 @@ class ItemsService if (isset($params['item_id']) && $params['item_id'] && !$isForceCreate) { $itemsResult = $this->itemsRepository->update($params['item_id'], $data); } else { - $itemsResult = $this->itemsRepository->create($data); } if ($data['store'] && $data['store'] > 0) { @@ -331,7 +331,18 @@ class ItemsService 'custom_attribute_value' => $row['spec_custom_value_name'] ?? null, ]; $sort++; - $this->itemRelAttributesRepository->create($paramsData); + // 如果商品关联规格存在更新,不存在新增 + $itemRelParamsData = [ + 'company_id' => $data['company_id'], + 'item_id' => $itemsResult['item_id'], + 'attribute_id' => $row['spec_id'], + ]; + $itemRelParamsInfo = $this->itemRelAttributesRepository->getInfo($itemRelParamsData); + if (!empty($itemRelParamsInfo)) { + $this->itemRelAttributesRepository->updateOneBy($itemRelParamsData, $paramsData); + }else { + $this->itemRelAttributesRepository->create($paramsData); + } } } diff --git a/src/PromotionsBundle/Services/RecommendLikeService.php b/src/PromotionsBundle/Services/RecommendLikeService.php index cc06714..9b0c91f 100644 --- a/src/PromotionsBundle/Services/RecommendLikeService.php +++ b/src/PromotionsBundle/Services/RecommendLikeService.php @@ -105,10 +105,10 @@ class RecommendLikeService } $itemsService = new ItemsService(); - $result = $itemsService->getItemsListMemberPrice($result, $filter['user_id'] ?? 0, $filter['company_id']); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], $filter['user_id'] ?? 0, $filter['company_id']); //营销标签 - $result = $itemsService->getItemsListActityTag($result, $filter['company_id']); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $filter['company_id']); $ItemTaxRateService = new ItemTaxRateService($filter['company_id']); foreach ($result['list'] as $key => $value) { diff --git a/src/SelfserviceBundle/Repositories/FormSettingRepository.php b/src/SelfserviceBundle/Repositories/FormSettingRepository.php index fb57d48..5091892 100644 --- a/src/SelfserviceBundle/Repositories/FormSettingRepository.php +++ b/src/SelfserviceBundle/Repositories/FormSettingRepository.php @@ -34,6 +34,7 @@ class FormSettingRepository extends EntityRepository public $prk = 'id'; private $multiLangField = [ + 'field_title', 'reason', 'remark' ]; diff --git a/src/SupplierBundle/Repositories/SupplierItemsRepository.php b/src/SupplierBundle/Repositories/SupplierItemsRepository.php index d5253c9..9ae7384 100644 --- a/src/SupplierBundle/Repositories/SupplierItemsRepository.php +++ b/src/SupplierBundle/Repositories/SupplierItemsRepository.php @@ -57,7 +57,48 @@ class SupplierItemsRepository extends BaseRepository $result = $this->getColumnNamesData($entity); $service = new MultiLangService(); - $service->addMultiLangByParams($result['item_id'],$data,'items'); + $service->addMultiLangByParams($result['item_id'],$data, $this->table); + return $result; + } + + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + throw new ResourceException("未查询到更新数据"); + } + $entity = $this->setColumnNamesData($entity, $data); + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + $result = $this->getColumnNamesData($entity); + $service = new MultiLangService(); + $service->updateLangDataNew($data,$this->table,$result['item_id'],$this->multiLangField, $filter['company_id'] ?? 0); + return $result; + } + + public function lists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + if ($result['total_count'] > 0) { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + $lists = $qb->execute()->fetchAll(); + $service = new MultiLangService(); + $lists = $service->getListAddLang($lists,$this->multiLangField,$this->table,$this->getLang(),$this->prk); + } + $result['list'] = $lists ?? []; return $result; } @@ -71,7 +112,7 @@ class SupplierItemsRepository extends BaseRepository $qb = $this->_filter($filter, $qb); $lists = $qb->execute()->fetchAll(); $service = new MultiLangService(); - $lists = $service->getListAddLang($lists,$this->multiLangField,'items',$this->getLang(),'item_id'); + $lists = $service->getListAddLang($lists,$this->multiLangField,$this->table,$this->getLang(),'item_id'); return $lists; } } diff --git a/src/ThemeBundle/Entities/OpenScreenAd.php b/src/ThemeBundle/Entities/OpenScreenAd.php index a76386f..e613752 100644 --- a/src/ThemeBundle/Entities/OpenScreenAd.php +++ b/src/ThemeBundle/Entities/OpenScreenAd.php @@ -308,6 +308,20 @@ class OpenScreenAd return $this->app; } + /** + * @var integer + * + * @ORM\Column(name="start_time", type="bigint", options={"comment":"开始时间"}) + */ + private $start_time; + + /** + * @var integer + * + * @ORM\Column(name="end_time", type="bigint", options={"comment":"结束时间"}) + */ + private $end_time; + /** * Set created. * @@ -427,4 +441,52 @@ class OpenScreenAd { return $this->is_jump; } + + /** + * Get start_time + * + * @return integer + */ + public function getStartTime() + { + return $this->start_time; + } + + /** + * Set start_time + * + * @param integer $startTime + * + * @return OpenScreenAd + */ + public function setStartTime($startTime) + { + $this->start_time = $startTime; + + return $this; + } + + /** + * Get end_time + * + * @return integer + */ + public function getEndTime() + { + return $this->end_time; + } + + /** + * Set end_time + * + * @param integer $endTime + * + * @return OpenScreenAd + */ + public function setEndTime($endTime) + { + $this->end_time = $endTime; + + return $this; + } } diff --git a/src/ThemeBundle/Entities/PagesAdPlace.php b/src/ThemeBundle/Entities/PagesAdPlace.php new file mode 100644 index 0000000..ef88baf --- /dev/null +++ b/src/ThemeBundle/Entities/PagesAdPlace.php @@ -0,0 +1,612 @@ +popup,轮播图=>carousel"}) + */ + private $ad_type; + + /** + * @var string + * + * @ORM\Column(name="name", type="string", length=100, options={"comment":"广告位名称"}) + */ + private $name; + + /** + * @var string + * + * @ORM\Column(name="pages", type="string", length=30, options={"comment":"关联页面"}) + */ + private $pages; + + /** + * @var integer + * + * @ORM\Column(name="start_time", type="bigint", options={"comment":"开始时间"}) + */ + private $start_time; + + /** + * @var integer + * + * @ORM\Column(name="end_time", type="bigint", options={"comment":"结束时间"}) + */ + private $end_time; + + /** + * @var text + * + * @ORM\Column(name="setting", type="text", nullable=true, options={"comment":"设置"}) + */ + private $setting; + + /** + * @var integer + * + * @ORM\Column(name="auto_play", type="integer", options={"comment":"自动播放", "default": 0}) + */ + private $auto_play = 0; + + /** + * @var integer + * + * @ORM\Column(name="play_interval", type="integer", options={"comment":"播放间隔时间", "default": 3}) + */ + private $play_interval = 3; + + /** + * @var integer + * + * @ORM\Column(name="auto_close", type="integer", options={"comment":"自动关闭", "default": 0}) + */ + private $auto_close = 0; + + /** + * @var integer + * + * @ORM\Column(name="close_delay", type="integer", options={"comment":"关闭延迟时间", "default": 10}) + */ + private $close_delay = 10; + + /** + * @var integer + * + * @ORM\Column(name="source_id", type="bigint", options={"comment":"添加者ID: 如店铺ID", "default": 0}) + */ + private $source_id = 0; + + /** + * @var \DateTime $created + * + * @Gedmo\Timestampable(on="create") + * @ORM\Column(type="integer") + */ + protected $created; + + /** + * @var \DateTime $updated + * + * @Gedmo\Timestampable(on="update") + * @ORM\Column(type="integer", nullable=true) + */ + protected $updated; + + /** + * @var string + * + * @ORM\Column(name="audit_status", type="string", options={"comment":"审核状态 submitting待提交 processing审核中 approved成功 rejected审核拒绝", "default":"submitting"}) + */ + private $audit_status = 'submitting'; + + /** + * @var string + * + * @ORM\Column(name="audit_remark", type="string", nullable=true, options={"comment":"审核备注"}) + */ + private $audit_remark; + + /** + * @var integer + * + * @ORM\Column(name="sort", type="integer", options={"comment":"排序", "default": 0}) + */ + private $sort = 0; + + /** + * @var string + * + * @ORM\Column(name="tracking_code", type="string", length=100, nullable=true, options={"comment":"埋点上报参数"}) + */ + private $tracking_code; + + /** + * 获取设置ID + * + * @return integer + */ + public function getId() + { + return $this->id; + } + + /** + * 设置公司ID + * + * @param integer $company_id + * @return PagesAdPlace + */ + public function setCompanyId($company_id) + { + $this->company_id = $company_id; + + return $this; + } + + /** + * 获取公司ID + * + * @return integer + */ + public function getCompanyId() + { + return $this->company_id; + } + + /** + * 设置区域ID + * + * @param integer $regionauth_id + * @return PagesAdPlace + */ + public function setRegionauthId($regionauth_id) + { + $this->regionauth_id = $regionauth_id; + + return $this; + } + + /** + * 获取区域ID + * + * @return integer + */ + public function getRegionauthId() + { + return $this->regionauth_id; + } + + /** + * 设置适用范围 + * + * @param integer $use_bound + * @return PagesAdPlace + */ + public function setUseBound($use_bound) + { + $this->use_bound = $use_bound; + + return $this; + } + + /** + * 获取适用范围 + * + * @return integer + */ + public function getUseBound() + { + return $this->use_bound; + } + + /** + * 设置广告类型 + * + * @param string $ad_type + * @return PagesAdPlace + */ + public function setAdType($ad_type) + { + $this->ad_type = $ad_type; + + return $this; + } + + /** + * 获取广告类型 + * + * @return string + */ + public function getAdType() + { + return $this->ad_type; + } + + /** + * 设置广告位名称 + * + * @param string $name + * @return PagesAdPlace + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * 获取广告位名称 + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * 设置关联页面 + * + * @param string $pages + * @return PagesAdPlace + */ + public function setPages($pages) + { + $this->pages = $pages; + + return $this; + } + + /** + * 获取关联页面 + * + * @return string + */ + public function getPages() + { + return $this->pages; + } + + /** + * 设置开始时间 + * + * @param integer $start_time + * @return PagesAdPlace + */ + public function setStartTime($start_time) + { + $this->start_time = $start_time; + + return $this; + } + + /** + * 获取开始时间 + * + * @return integer + */ + public function getStartTime() + { + return $this->start_time; + } + + /** + * 设置结束时间 + * + * @param integer $end_time + * @return PagesAdPlace + */ + public function setEndTime($end_time) + { + $this->end_time = $end_time; + + return $this; + } + + /** + * 获取结束时间 + * + * @return integer + */ + public function getEndTime() + { + return $this->end_time; + } + + /** + * 设置配置信息 + * + * @param string $setting + * @return PagesAdPlace + */ + public function setSetting($setting) + { + $this->setting = $setting; + + return $this; + } + + /** + * 获取配置信息 + * + * @return string + */ + public function getSetting() + { + return $this->setting; + } + + /** + * 设置是否自动播放 + * + * @param integer $auto_play + * @return PagesAdPlace + */ + public function setAutoPlay($auto_play) + { + $this->auto_play = $auto_play; + + return $this; + } + + /** + * 获取是否自动播放 + * + * @return integer + */ + public function getAutoPlay() + { + return $this->auto_play; + } + + /** + * 设置播放间隔时间 + * + * @param integer $play_interval + * @return PagesAdPlace + */ + public function setPlayInterval($play_interval) + { + $this->play_interval = $play_interval; + + return $this; + } + + /** + * 获取播放间隔时间 + * + * @return integer + */ + public function getPlayInterval() + { + return $this->play_interval; + } + + /** + * 设置是否自动关闭 + * + * @param integer $auto_close + * @return PagesAdPlace + */ + public function setAutoClose($auto_close) + { + $this->auto_close = $auto_close; + + return $this; + } + + /** + * 获取是否自动关闭 + * + * @return integer + */ + public function getAutoClose() + { + return $this->auto_close; + } + + /** + * 设置关闭延迟时间 + * + * @param integer $close_delay + * @return PagesAdPlace + */ + public function setCloseDelay($close_delay) + { + $this->close_delay = $close_delay; + + return $this; + } + + /** + * 获取关闭延迟时间 + * + * @return integer + */ + public function getCloseDelay() + { + return $this->close_delay; + } + + /** + * 设置添加者ID + * + * @param integer $source_id + * @return PagesAdPlace + */ + public function setSourceId($source_id) + { + $this->source_id = $source_id; + + return $this; + } + + /** + * 获取添加者ID + * + * @return integer + */ + public function getSourceId() + { + return $this->source_id; + } + + /** + * 获取创建时间 + * + * @return integer + */ + public function getCreated() + { + return $this->created; + } + + /** + * 获取更新时间 + * + * @return integer + */ + public function getUpdated() + { + return $this->updated; + } + + /** + * 设置审核状态 + * + * @param string $audit_status + * @return PagesAdPlace + */ + public function setAuditStatus($audit_status) + { + $this->audit_status = $audit_status; + + return $this; + } + + /** + * 获取审核状态 + * + * @return string + */ + public function getAuditStatus() + { + return $this->audit_status; + } + + /** + * 设置审核备注 + * + * @param string $audit_remark + * @return PagesAdPlace + */ + public function setAuditRemark($audit_remark) + { + $this->audit_remark = $audit_remark; + + return $this; + } + + /** + * 获取审核备注 + * + * @return string + */ + public function getAuditRemark() + { + return $this->audit_remark; + } + + /** + * 设置排序 + * + * @param integer $sort + * @return PagesAdPlace + */ + public function setSort($sort) + { + $this->sort = $sort; + + return $this; + } + + /** + * 获取排序 + * + * @return integer + */ + public function getSort() + { + return $this->sort; + } + + /** + * 设置埋点上报参数 + * + * @param string $tracking_code + * @return PagesAdPlace + */ + public function setTrackingCode($tracking_code) + { + $this->tracking_code = $tracking_code; + + return $this; + } + + /** + * 获取埋点上报参数 + * + * @return string + */ + public function getTrackingCode() + { + return $this->tracking_code; + } +} + + \ No newline at end of file diff --git a/src/ThemeBundle/Entities/PagesAdPlaceRelDistributors.php b/src/ThemeBundle/Entities/PagesAdPlaceRelDistributors.php new file mode 100644 index 0000000..0e42727 --- /dev/null +++ b/src/ThemeBundle/Entities/PagesAdPlaceRelDistributors.php @@ -0,0 +1,110 @@ +company_id; + } + + /** + * Set company_id + * + * @param integer $companyId + * + * @return PagesAdPlaceRelDistributors + */ + public function setCompanyId($companyId) + { + $this->company_id = $companyId; + + return $this; + } + + /** + * Get ad_place_id + * + * @return integer + */ + public function getAdPlaceId() + { + return $this->ad_place_id; + } + + /** + * Set ad_place_id + * + * @param integer $adPlaceId + * + * @return PagesAdPlaceRelDistributors + */ + public function setAdPlaceId($adPlaceId) + { + $this->ad_place_id = $adPlaceId; + + return $this; + } + + /** + * Get distributor_id + * + * @return integer + */ + public function getDistributorId() + { + return $this->distributor_id; + } + + /** + * Set distributor_id + * + * @param integer $distributorId + * + * @return PagesAdPlaceRelDistributors + */ + public function setDistributorId($distributorId) + { + $this->distributor_id = $distributorId; + + return $this; + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Entities/PagesAdPlaceRelMemberTags.php b/src/ThemeBundle/Entities/PagesAdPlaceRelMemberTags.php new file mode 100644 index 0000000..688ea12 --- /dev/null +++ b/src/ThemeBundle/Entities/PagesAdPlaceRelMemberTags.php @@ -0,0 +1,110 @@ +company_id; + } + + /** + * Set company_id + * + * @param integer $companyId + * + * @return PagesAdPlaceRelMemberTags + */ + public function setCompanyId($companyId) + { + $this->company_id = $companyId; + + return $this; + } + + /** + * Get ad_place_id + * + * @return integer + */ + public function getAdPlaceId() + { + return $this->ad_place_id; + } + + /** + * Set ad_place_id + * + * @param integer $adPlaceId + * + * @return PagesAdPlaceRelMemberTags + */ + public function setAdPlaceId($adPlaceId) + { + $this->ad_place_id = $adPlaceId; + + return $this; + } + + /** + * Get tag_id + * + * @return integer + */ + public function getTagId() + { + return $this->tag_id; + } + + /** + * Set tag_id + * + * @param integer $tagId + * + * @return PagesAdPlaceRelMemberTags + */ + public function setTagId($tagId) + { + $this->tag_id = $tagId; + + return $this; + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Entities/PagesSideBar.php b/src/ThemeBundle/Entities/PagesSideBar.php new file mode 100644 index 0000000..b426e93 --- /dev/null +++ b/src/ThemeBundle/Entities/PagesSideBar.php @@ -0,0 +1,276 @@ +id; + } + + /** + * 设置公司ID + * + * @param integer $company_id + * @return PagesSideBar + */ + public function setCompanyId($company_id) + { + $this->company_id = $company_id; + + return $this; + } + + /** + * 获取公司ID + * + * @return integer + */ + public function getCompanyId() + { + return $this->company_id; + } + + /** + * 设置区域ID + * + * @param integer $regionauth_id + * @return PagesSideBar + */ + public function setRegionauthId($regionauth_id) + { + $this->regionauth_id = $regionauth_id; + + return $this; + } + + /** + * 获取区域ID + * + * @return integer + */ + public function getRegionauthId() + { + return $this->regionauth_id; + } + + /** + * 设置名称 + * + * @param string $name + * @return PagesSideBar + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * 获取名称 + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * 设置关联页面 + * + * @param string $pages + * @return PagesSideBar + */ + public function setPages($pages) + { + $this->pages = $pages; + + return $this; + } + + /** + * 获取关联页面 + * + * @return string + */ + public function getPages() + { + return $this->pages; + } + + /** + * 设置是否禁用 + * + * @param boolean $disabled + * @return PagesSideBar + */ + public function setDisabled($disabled) + { + $this->disabled = $disabled; + + return $this; + } + + /** + * 获取是否禁用 + * + * @return boolean + */ + public function getDisabled() + { + return $this->disabled; + } + + /** + * 设置设置信息 + * + * @param text $setting + * @return PagesSideBar + */ + public function setSetting($setting) + { + $this->setting = $setting; + + return $this; + } + + /** + * 获取设置信息 + * + * @return text + */ + public function getSetting() + { + return $this->setting; + } + + /** + * 设置创建时间 + * + * @param integer $created + * @return PagesSideBar + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * 获取创建时间 + * + * @return integer + */ + public function getCreated() + { + return $this->created; + } + + /** + * 设置更新时间 + * + * @param integer $updated + * @return PagesSideBar + */ + public function setUpdated($updated) + { + $this->updated = $updated; + + return $this; + } + + /** + * 获取更新时间 + * + * @return integer + */ + public function getUpdated() + { + return $this->updated; + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Entities/PagesTemplate.php b/src/ThemeBundle/Entities/PagesTemplate.php index 6281adb..c52b525 100644 --- a/src/ThemeBundle/Entities/PagesTemplate.php +++ b/src/ThemeBundle/Entities/PagesTemplate.php @@ -51,6 +51,13 @@ class PagesTemplate */ private $company_id; + /** + * @var integer + * + * @ORM\Column(name="regionauth_id", type="bigint", nullable=true, options={"comment":"区域id", "default":0}) + */ + private $regionauth_id = 0; + /** * @var string * @@ -124,9 +131,9 @@ class PagesTemplate /** * @var string * - * @ORM\Column(name="weapp_pages", nullable=true, type="string", options={"comment":"模版页面"}) + * @ORM\Column(name="weapp_pages", nullable=true, type="string", options={"comment":"模版页面:index-首页 distributor_index-门店首页", "default": "index"}) */ - private $weapp_pages; + private $weapp_pages = 'index'; /** * @var string @@ -177,6 +184,30 @@ class PagesTemplate return $this->company_id; } + /** + * Set regionauthId. + * + * @param int|null $regionauthId + * + * @return PagesTemplate + */ + public function setRegionauthId($regionauthId = null) + { + $this->regionauth_id = $regionauthId; + + return $this; + } + + /** + * Get regionauthId. + * + * @return int|null + */ + public function getRegionauthId() + { + return $this->regionauth_id; + } + /** * Set distributorId. * diff --git a/src/ThemeBundle/Entities/PagesTemplateSet.php b/src/ThemeBundle/Entities/PagesTemplateSet.php index fbf180e..e7eed04 100644 --- a/src/ThemeBundle/Entities/PagesTemplateSet.php +++ b/src/ThemeBundle/Entities/PagesTemplateSet.php @@ -49,6 +49,13 @@ class PagesTemplateSet */ private $company_id; + /** + * @var integer + * + * @ORM\Column(name="regionauth_id", type="bigint", nullable=true, options={"comment":"区域id", "default":0}) + */ + private $regionauth_id = 0; + /** * @var string * @@ -139,6 +146,30 @@ class PagesTemplateSet return $this->company_id; } + /** + * Set regionauthId. + * + * @param int|null $regionauthId + * + * @return PagesTemplateSet + */ + public function setRegionauthId($regionauthId = null) + { + $this->regionauth_id = $regionauthId; + + return $this; + } + + /** + * Get regionauthId. + * + * @return int|null + */ + public function getRegionauthId() + { + return $this->regionauth_id; + } + /** * Set indexType. * diff --git a/src/ThemeBundle/Http/Api/V1/Action/OpenScreenAd.php b/src/ThemeBundle/Http/Api/V1/Action/OpenScreenAd.php index 103f58a..ece4de5 100644 --- a/src/ThemeBundle/Http/Api/V1/Action/OpenScreenAd.php +++ b/src/ThemeBundle/Http/Api/V1/Action/OpenScreenAd.php @@ -99,7 +99,7 @@ class OpenScreenAd extends Controller public function Save(Request $request) { // 请求参数 - $params = $request->all('ad_material', 'is_enable', 'show_time', 'position', 'is_jump', 'material_type', 'waiting_time', 'ad_url', 'app'); + $params = $request->all('ad_material', 'is_enable', 'show_time', 'position', 'is_jump', 'material_type', 'waiting_time', 'ad_url', 'app', 'start_time', 'end_time'); // 验证数据 $rules = [ @@ -108,6 +108,8 @@ class OpenScreenAd extends Controller 'show_time' => ['required|in:always,first', '请选择曝光时间'], 'waiting_time' => ['required', '请设置秒数'], // 'app' => ['required', '请选择应用端'], + 'start_time' => ['required', '请选择展示开始时间'], + 'end_time' => ['required', '请选择展示结束时间'], ]; $error = validator_params($params, $rules); if ($error) { diff --git a/src/ThemeBundle/Http/Api/V1/Action/PagesAdPlace.php b/src/ThemeBundle/Http/Api/V1/Action/PagesAdPlace.php new file mode 100644 index 0000000..ac7604f --- /dev/null +++ b/src/ThemeBundle/Http/Api/V1/Action/PagesAdPlace.php @@ -0,0 +1,841 @@ +popup,轮播图=>carousel", + * required=false, + * type="string" + * ), + * @SWG\Parameter( + * name="status", + * in="query", + * description="状态:0-未开始,1-进行中,2-已结束", + * required=false, + * type="string" + * ), + * @SWG\Parameter( + * name="pages", + * in="query", + * description="关联页面", + * required=false, + * type="string" + * ), + * @SWG\Parameter( + * name="audit_status", + * in="query", + * description="审核状态:submitting待提交 processing审核中 approved成功 rejected审核拒绝", + * required=false, + * type="string" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Property(property="data", type="object", + * @SWG\Property(property="total_count", type="integer", example="100", description="总数"), + * @SWG\Property(property="list", type="array", @SWG\Items(ref="#/definitions/PagesAdPlace")), + * ) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function getList(Request $request) + { + $params = $request->all(); + + $validator = app('validator')->make($params, [ + 'page' => 'required|integer|min:1', + 'pageSize' => 'required|integer|min:1|max:100', + 'ad_type' => 'in:popup,carousel', + 'audit_status' => 'in:submitting,processing,approved,rejected', + ]); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + + $filter['company_id'] = app('auth')->user()->get('company_id'); + $page = $params['page']; + $pageSize = $params['pageSize']; + + if (isset($params['regionauth_id']) && $params['regionauth_id']) { + $filter['regionauth_id'] = $params['regionauth_id']; + } + + if (isset($params['id']) && $params['id']) { + $filter['id'] = $params['id']; + } + + if (isset($params['name']) && $params['name']) { + $filter['name|contains'] = $params['name']; + } + + if (isset($params['ad_type']) && $params['ad_type']) { + $filter['ad_type'] = $params['ad_type']; + } + + if (isset($params['distributor_id']) && $params['distributor_id']) { + $filter['distributor_id'] = $params['distributor_id']; + } + + if (isset($params['pages']) && $params['pages']) { + $filter['pages'] = $params['pages']; + } + + if (isset($params['audit_status']) && $params['audit_status']) { + $filter['audit_status'] = $params['audit_status']; + //待提审, 待审核,需要没有过期 + if (in_array($filter['audit_status'], ['submitting', 'processing'])) { + $filter['end_time|gt'] = time(); + } + } + + $now = time(); + if (isset($params['status'])) { + switch ($params['status']) { + case '0': + $filter['start_time|gt'] = $now; + break; + case '1': + $filter['start_time|lte'] = $now; + $filter['end_time|gte'] = $now; + break; + case '2'://已失效 + $filter['end_time|lt'] = $now; + unset($filter['audit_status']);//显示全部已失效的数据 + break; + } + } + + // 店铺端 + $filter['source_id'] = 0; + $operatorType = app('auth')->user()->get('operator_type'); + if ($operatorType == 'distributor') { + $distributorId = $request->get('distributor_id'); + $filter['source_id'] = $distributorId; + } + + $orderBy = ['sort' => 'desc', 'id' => 'desc']; + $service = new PagesAdPlaceService(); + $result = $service->getListWithRelTags($filter, $page, $pageSize, $orderBy); + foreach ($result['list'] as $key => $val) { + if ($now < $val['start_time']) { + $result['list'][$key]['status'] = 0; + } else if ($now > $val['end_time']) { + $result['list'][$key]['status'] = 2; + } else { + $result['list'][$key]['status'] = 1; + } + } + return $this->response->array($result); + } + + /** + * @SWG\Get( + * path="/adplace/{id}", + * tags={"模版"}, + * summary="广告位详情", + * description="根据ID获取广告位详情", + * operationId="getInfo", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="广告位ID", + * required=true, + * type="integer" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema(ref="#/definitions/PagesAdPlace") + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function getInfo(Request $request, $id) + { + $filter['id'] = $id; + $filter['company_id'] = app('auth')->user()->get('company_id'); + + // 店铺端 + $filter['source_id'] = 0; + $operatorType = app('auth')->user()->get('operator_type'); + if ($operatorType == 'distributor') { + $distributorId = $request->get('distributor_id'); + $filter['source_id'] = $distributorId; + } + + $service = new PagesAdPlaceService(); + $result = $service->getInfoWithRelTags($filter); + return $this->response->array($result); + } + + /** + * @SWG\Post( + * path="/adplace", + * tags={"模版"}, + * summary="创建广告位", + * description="创建广告位", + * operationId="create", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="regionauth_id", + * in="formData", + * description="区域ID", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="distributor_id", + * in="formData", + * description="店铺ID", + * required=false, + * type="array", + * @SWG\Items(type="integer") + * ), + * @SWG\Parameter( + * name="ad_type", + * in="formData", + * description="广告类型:弹窗=>popup,轮播图=>carousel", + * required=true, + * type="string" + * ), + * @SWG\Parameter( + * name="name", + * in="formData", + * description="广告位名称", + * required=true, + * type="string" + * ), + * @SWG\Parameter( + * name="pages", + * in="formData", + * description="关联页面", + * required=true, + * type="string" + * ), + * @SWG\Parameter( + * name="start_time", + * in="formData", + * description="开始时间", + * required=true, + * type="integer" + * ), + * @SWG\Parameter( + * name="end_time", + * in="formData", + * description="结束时间", + * required=true, + * type="integer" + * ), + * @SWG\Parameter( + * name="setting", + * in="formData", + * description="设置信息,json格式", + * required=false, + * type="string" + * ), + * @SWG\Parameter( + * name="auto_play", + * in="formData", + * description="自动播放", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="play_interval", + * in="formData", + * description="播放间隔时间", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="auto_close", + * in="formData", + * description="自动关闭", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="close_delay", + * in="formData", + * description="关闭延迟时间", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="sort", + * in="formData", + * description="排序", + * required=false, + * type="integer" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema(ref="#/definitions/PagesAdPlace") + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function create(Request $request) + { + $params = $request->all(); + $params['company_id'] = app('auth')->user()->get('company_id'); + + $validator = app('validator')->make($params, [ + 'ad_type' => 'required|in:popup,carousel', + 'name' => 'required', + 'start_time' => 'required', + 'end_time' => 'required', + 'pages' => 'required', + 'rel_tags' => 'array', + 'rel_tags.*.tag_id' => 'required|integer', + ], [ + 'ad_type.*' => '广告类型必填', + 'name.*' => '广告名称必填', + 'start_time.*' => '开始时间必填', + 'end_time.*' => '结束时间比天', + 'pages.*' => '应用页面必填', + 'rel_tags.*' => '请选择适用人群', + 'rel_tags.*.tag_id.*' => '请选择适用人群', + ]); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + + // 店铺端 + $operatorType = app('auth')->user()->get('operator_type'); + if ($operatorType == 'distributor') { + $distributorId = $request->get('distributor_id'); + $params['distributor_id'] = [$distributorId]; + $params['source_id'] = $distributorId; + } + + // 待提交审核 + $params['audit_status'] = 'submitting'; + + $service = new PagesAdPlaceService(); + $result = $service->createWithRelTags($params); + return $this->response->array($result); + } + + /** + * @SWG\Put( + * path="/adplace/{id}", + * tags={"模版"}, + * summary="更新广告位", + * description="更新广告位", + * operationId="update", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="广告位ID", + * required=true, + * type="integer" + * ), + * @SWG\Parameter( + * name="regionauth_id", + * in="formData", + * description="区域ID", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="distributor_id", + * in="formData", + * description="店铺ID", + * required=false, + * type="array", + * @SWG\Items(type="integer") + * ), + * @SWG\Parameter( + * name="ad_type", + * in="formData", + * description="广告类型:弹窗=>popup,轮播图=>carousel", + * required=true, + * type="string" + * ), + * @SWG\Parameter( + * name="name", + * in="formData", + * description="广告位名称", + * required=true, + * type="string" + * ), + * @SWG\Parameter( + * name="pages", + * in="formData", + * description="关联页面", + * required=true, + * type="string" + * ), + * @SWG\Parameter( + * name="start_time", + * in="formData", + * description="开始时间", + * required=true, + * type="integer" + * ), + * @SWG\Parameter( + * name="end_time", + * in="formData", + * description="结束时间", + * required=true, + * type="integer" + * ), + * @SWG\Parameter( + * name="setting", + * in="formData", + * description="设置信息,json格式", + * required=false, + * type="string" + * ), + * @SWG\Parameter( + * name="auto_play", + * in="formData", + * description="自动播放", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="play_interval", + * in="formData", + * description="播放间隔时间", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="auto_close", + * in="formData", + * description="自动关闭", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="close_delay", + * in="formData", + * description="关闭延迟时间", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="sort", + * in="formData", + * description="排序", + * required=false, + * type="integer" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema( + * type="object", + * @SWG\Property(property="status", type="boolean") + * ) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function update(Request $request, $id) + { + $params = $request->all(); + $filter['company_id'] = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + + $validator = app('validator')->make($params, [ + 'ad_type' => 'required|in:popup,carousel', + 'name' => 'required', + 'start_time' => 'required', + 'end_time' => 'required', + 'pages' => 'required', + 'rel_tags' => 'array', + 'rel_tags.*.tag_id' => 'required|integer', + ], [ + 'ad_type.*' => '广告类型必填', + 'name.*' => '广告名称必填', + 'start_time.*' => '开始时间必填', + 'end_time.*' => '结束时间比天', + 'pages.*' => '应用页面必填', + 'rel_tags.*' => '请选择适用人群', + 'rel_tags.*.tag_id.*' => '请选择适用人群', + ]); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + + // 店铺端 + $filter['source_id'] = 0; + $operatorType = app('auth')->user()->get('operator_type'); + if ($operatorType == 'distributor') { + $distributorId = $request->get('distributor_id'); + $params['distributor_id'] = [$distributorId]; + $filter['source_id'] = $distributorId; + } + + // 待提交审核 + $params['audit_status'] = 'submitting'; + + $service = new PagesAdPlaceService(); + $result = $service->updateWithRelTags($filter, $params); + return $this->response->array($result); + } + + /** + * @SWG\Delete( + * path="/adplace/{id}", + * tags={"模版"}, + * summary="删除广告位", + * description="删除广告位", + * operationId="delete", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="广告位ID", + * required=true, + * type="integer" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema( + * type="object", + * @SWG\Property(property="status", type="boolean") + * ) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function delete(Request $request, $id) + { + $filter['company_id'] = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + + // 店铺端 + $filter['source_id'] = 0; + $operatorType = app('auth')->user()->get('operator_type'); + if ($operatorType == 'distributor') { + $distributorId = $request->get('distributor_id'); + $filter['source_id'] = $distributorId; + } + + $service = new PagesAdPlaceService(); + $result = $service->deleteWithRelTags($filter); + return $this->response->array(['status' => true]); + } + + /** + * @SWG\Post( + * path="/adplace/submit/{id}", + * tags={"模版"}, + * summary="提交审核广告位", + * description="提交审核广告位", + * operationId="submit", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="广告位ID", + * required=true, + * type="integer" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema( + * type="object", + * @SWG\Property(property="status", type="boolean") + * ) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function submit(Request $request, $id) + { + $filter['company_id'] = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + + // 店铺端 + $filter['source_id'] = 0; + $operatorType = app('auth')->user()->get('operator_type'); + if ($operatorType == 'distributor') { + $distributorId = $request->get('distributor_id'); + $filter['source_id'] = $distributorId; + } + + // 待审核 + $params['audit_status'] = 'processing'; + + $service = new PagesAdPlaceService(); + $result = $service->updateOneBy($filter, $params); + return $this->response->array(['status' => true]); + } + + /** + * @SWG\Post( + * path="/adplace/audit/{id}", + * tags={"模版"}, + * summary="审核广告位", + * description="审核广告位", + * operationId="audit", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="广告位ID", + * required=true, + * type="integer" + * ), + * @SWG\Parameter( + * name="audit_status", + * in="formData", + * description="审核状态", + * required=true, + * type="string" + * ), + * @SWG\Parameter( + * name="audit_remark", + * in="formData", + * description="审核备注", + * required=false, + * type="string" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema( + * type="object", + * @SWG\Property(property="status", type="boolean") + * ) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function audit(Request $request, $id) + { + $params = $request->all('audit_status', 'audit_remark'); + $filter['company_id'] = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + + // 店铺端 + $filter['source_id'] = 0; + $operatorType = app('auth')->user()->get('operator_type'); + if ($operatorType == 'distributor') { + $distributorId = $request->get('distributor_id'); + $filter['source_id'] = $distributorId; + } + + $validator = app('validator')->make($params, [ + 'audit_status' => 'required|in:approved,rejected', + 'audit_remark' => 'required_if:audit_status,rejected', + ], [ + 'audit_status.*' => '审核状态必填', + 'audit_remark.*' => '请填写拒绝原因', + ]); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + + $service = new PagesAdPlaceService(); + $result = $service->updateOneBy($filter, $params); + return $this->response->array($result); + } + + /** + * @SWG\Post( + * path="/adplace/withdraw/{id}", + * tags={"模版"}, + * summary="撤回广告位审核申请", + * description="撤回广告位审核申请", + * operationId="withdraw", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="广告位ID", + * required=true, + * type="integer" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema( + * type="object", + * @SWG\Property(property="status", type="boolean") + * ) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function withdraw(Request $request, $id) + { + $filter['company_id'] = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + + // 店铺端 + $filter['source_id'] = 0; + $operatorType = app('auth')->user()->get('operator_type'); + if ($operatorType == 'distributor') { + $distributorId = $request->get('distributor_id'); + $filter['source_id'] = $distributorId; + } + + // 待提交 + $params['audit_status'] = 'submitting'; + + $service = new PagesAdPlaceService(); + $result = $service->updateOneBy($filter, $params); + return $this->response->array($result); + } +} + +/** + * @SWG\Definition( + * definition="PagesAdPlace", + * type="object", + * @SWG\Property(property="id", type="integer", description="ID"), + * @SWG\Property(property="company_id", type="integer", description="公司ID"), + * @SWG\Property(property="regionauth_id", type="integer", description="区域ID"), + * @SWG\Property(property="distributor_id", type="integer", description="店铺ID"), + * @SWG\Property(property="ad_type", type="string", description="广告类型:弹窗=>popup,轮播图=>carousel"), + * @SWG\Property(property="name", type="string", description="广告位名称"), + * @SWG\Property(property="pages", type="array", @SWG\Items(type="string"), description="关联页面"), + * @SWG\Property(property="start_time", type="integer", description="开始时间"), + * @SWG\Property(property="end_time", type="integer", description="结束时间"), + * @SWG\Property(property="setting", type="string", description="设置信息,json格式"), + * @SWG\Property(property="auto_play", type="integer", description="自动播放"), + * @SWG\Property(property="play_interval", type="integer", description="播放间隔时间"), + * @SWG\Property(property="auto_close", type="integer", description="自动关闭"), + * @SWG\Property(property="close_delay", type="integer", description="关闭延迟时间"), + * @SWG\Property(property="status", type="integer", description="状态:0-未开始,1-进行中,2-已结束"), + * @SWG\Property(property="created", type="integer", description="创建时间"), + * @SWG\Property(property="updated", type="integer", description="更新时间"), + * @SWG\Property(property="audit_status", type="string", description="审核状态:submitting,processing,approved,rejected"), + * @SWG\Property(property="audit_remark", type="string", description="审核备注"), + * @SWG\Property(property="rel_tags", type="array", description="关联人群标签", @SWG\Items(ref="#/definitions/PagesAdPlaceTag")), + * @SWG\Property(property="sort", type="integer", description="排序"), + * @SWG\Property(property="rel_distributors", type="array", description="关联店铺", @SWG\Items(ref="#/definitions/PagesAdPlaceRelDistributor")), + * ) + */ + +/** + * @SWG\Definition( + * definition="PagesAdPlaceTag", + * type="object", + * @SWG\Property(property="tag_id", type="integer", description="标签ID"), + * @SWG\Property(property="tag_name", type="string", description="标签名称"), + * ) + */ + +/** + * @SWG\Definition( + * definition="PagesAdPlaceRelDistributor", + * type="object", + * @SWG\Property(property="distributor_id", type="integer", description="店铺ID"), + * @SWG\Property(property="distributor_name", type="string", description="店铺名称"), + * ) + */ \ No newline at end of file diff --git a/src/ThemeBundle/Http/Api/V1/Action/PagesSideBar.php b/src/ThemeBundle/Http/Api/V1/Action/PagesSideBar.php new file mode 100644 index 0000000..96e3b0c --- /dev/null +++ b/src/ThemeBundle/Http/Api/V1/Action/PagesSideBar.php @@ -0,0 +1,419 @@ +all(); + + $validator = app('validator')->make($params, [ + 'page' => 'required|integer|min:1', + 'pageSize' => 'required|integer|min:1|max:50', + ]); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + + $filter['company_id'] = app('auth')->user()->get('company_id'); + $page = $params['page']; + $pageSize = $params['pageSize']; + + if (isset($params['regionauth_id']) && $params['regionauth_id']) { + $filter['regionauth_id'] = $params['regionauth_id']; + } + + if (isset($params['id']) && $params['id']) { + $filter['id'] = $params['id']; + } + + if (isset($params['name']) && $params['name']) { + $filter['name|contains'] = $params['name']; + } + + if (isset($params['page_type']) && $params['page_type']) { + $filter['pages|contains'] = ','.$params['page_type'].','; + } + + $orderBy = ['id' => 'desc']; + $cols = 'id,company_id,regionauth_id,name,pages,disabled,created,updated'; + + $service = new PagesSideBarService(); + $result = $service->lists($filter, $cols, $page, $pageSize, $orderBy); + foreach ($result['list'] as $key => $val) { + if ($val['pages']) { + $result['list'][$key]['pages'] = explode(',', trim($val['pages'], ',')); + } + } + return $this->response->array($result); + } + + /** + * @SWG\Get( + * path="/sidebar/{id}", + * tags={"模版"}, + * summary="侧边栏详情", + * description="根据ID获取侧边栏详情", + * operationId="getInfo", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="侧边栏ID", + * required=true, + * type="integer" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema(ref="#/definitions/PagesSideBar") + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function getInfo(Request $request, $id) + { + $filter['company_id'] = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + + $service = new PagesSideBarService(); + $result = $service->getInfo($filter); + if (isset($result['pages']) && $result['pages']) { + $result['pages'] = explode(',', trim($result['pages'], ',')); + } + return $this->response->array($result); + } + + /** + * @SWG\Post( + * path="/sidebar", + * tags={"模版"}, + * summary="创建侧边栏", + * description="创建侧边栏", + * operationId="create", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="name", + * in="formData", + * description="侧边栏名称", + * required=true, + * type="string" + * ), + * @SWG\Parameter( + * name="pages", + * in="formData", + * description="关联页面", + * required=true, + * type="array", + * @SWG\Items(type="string") + * ), + * @SWG\Parameter( + * name="regionauth_id", + * in="formData", + * description="区域ID", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="disabled", + * in="formData", + * description="是否禁用,true禁用/false启用", + * required=false, + * type="boolean" + * ), + * @SWG\Parameter( + * name="setting", + * in="formData", + * description="设置信息,json格式", + * required=false, + * type="string" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema(ref="#/definitions/PagesSideBar") + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function create(Request $request) + { + $params = $request->all(); + $params['company_id'] = app('auth')->user()->get('company_id'); + + $validator = app('validator')->make($params, [ + 'name' => 'required', + 'pages' => 'required', + ]); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + + if (is_array($params['pages']) && $params['pages']) { + $params['pages'] = ','.implode(',', $params['pages']).','; + } + + $service = new PagesSideBarService(); + $regionauthId = $params['regionauth_id'] ?? 0; + $service->checkPagesExist($params['company_id'], $regionauthId, $params['pages']); + $result = $service->create($params); + return $this->response->array($result); + } + + /** + * @SWG\Put( + * path="/sidebar/{id}", + * tags={"模版"}, + * summary="更新侧边栏", + * description="更新侧边栏", + * operationId="update", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="侧边栏ID", + * required=true, + * type="integer" + * ), + * @SWG\Parameter( + * name="name", + * in="formData", + * description="侧边栏名称", + * required=false, + * type="string" + * ), + * @SWG\Parameter( + * name="pages", + * in="formData", + * description="关联页面", + * required=false, + * type="array", + * @SWG\Items(type="string") + * ), + * @SWG\Parameter( + * name="regionauth_id", + * in="formData", + * description="区域ID", + * required=false, + * type="integer" + * ), + * @SWG\Parameter( + * name="disabled", + * in="formData", + * description="是否禁用,true禁用/false启用", + * required=false, + * type="boolean" + * ), + * @SWG\Parameter( + * name="setting", + * in="formData", + * description="设置信息,json格式", + * required=false, + * type="string" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema( + * type="object", + * @SWG\Property(property="status", type="boolean") + * ) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function update(Request $request, $id) + { + $params = $request->all(); + $filter['company_id'] = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + $params['company_id'] = $filter['company_id']; + + $rules = []; + if (isset($params['name'])) { + $rules['name'] = 'required'; + } + if (isset($params['pages'])) { + $rules['pages'] = 'required'; + } + if ($rules) { + $validator = app('validator')->make($params, $rules); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + } + + if (isset($params['disabled'])) { + $params['disabled'] = $params['disabled'] == 'true' ? true : boolval($params['disabled']); + } + + if (isset($params['pages']) && is_array($params['pages']) && $params['pages']) { + $params['pages'] = ','.implode(',', $params['pages']).','; + } + + $service = new PagesSideBarService(); + if (isset($params['pages']) && $params['pages']) { + if (isset($params['regionauth_id']) && $params['regionauth_id']) { + $regionauthId = $params['regionauth_id']; + } else { + $info = $service->getInfo($filter); + if (!$info) { + throw new ResourceException('未查询到更新数据'); + } + $regionauthId = $info['regionauth_id']; + } + $service->checkPagesExist($params['company_id'], $regionauthId, $params['pages'], $id); + } + $result = $service->updateOneBy($filter, $params); + return $this->response->array($result); + } + + /** + * @SWG\Delete( + * path="/sidebar/{id}", + * tags={"模版"}, + * summary="删除侧边栏", + * description="删除侧边栏", + * operationId="delete", + * @SWG\Parameter( + * name="Authorization", + * in="header", + * description="JWT验证token", + * type="string" + * ), + * @SWG\Parameter( + * name="id", + * in="path", + * description="侧边栏ID", + * required=true, + * type="integer" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema( + * type="object", + * @SWG\Property(property="status", type="boolean") + * ) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function delete(Request $request, $id) + { + $params = $request->all(); + $filter['company_id'] = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + + $service = new PagesSideBarService(); + $result = $service->deleteBy($filter); + return $this->response->array(['status' => true]); + } + +} + +/** + * @SWG\Definition( + * definition="PagesSideBar", + * type="object", + * @SWG\Property(property="id", type="integer", description="ID"), + * @SWG\Property(property="company_id", type="integer", description="公司ID"), + * @SWG\Property(property="regionauth_id", type="integer", description="区域ID"), + * @SWG\Property(property="name", type="string", description="侧边栏名称"), + * @SWG\Property(property="pages", type="array", @SWG\Items(type="string"), description="关联页面"), + * @SWG\Property(property="disabled", type="boolean", description="是否禁用"), + * @SWG\Property(property="setting", type="string", description="设置信息,json格式"), + * @SWG\Property(property="created", type="integer", description="创建时间"), + * @SWG\Property(property="updated", type="integer", description="更新时间") + * ) + */ \ No newline at end of file diff --git a/src/ThemeBundle/Http/Api/V1/Action/PagesTemplate.php b/src/ThemeBundle/Http/Api/V1/Action/PagesTemplate.php index f676db9..6208b9e 100644 --- a/src/ThemeBundle/Http/Api/V1/Action/PagesTemplate.php +++ b/src/ThemeBundle/Http/Api/V1/Action/PagesTemplate.php @@ -22,9 +22,92 @@ use Dingo\Api\Exception\ResourceException; use Illuminate\Http\Request; use ThemeBundle\Jobs\PagesTemplateSyncJob; use ThemeBundle\Services\PagesTemplateServices; +use GoodsBundle\Services\ItemsService; +use CompanysBundle\Services\RegionauthService; class PagesTemplate extends Controller { + /** + * @SWG\Get( + * path="/pagestemplate/widget/items", + * summary="获取模板组件商品", + * tags={"模板"}, + * description="获取模板组件商品", + * @SWG\Parameter( + * name="regionauth_id", + * in="query", + * description="区域id", + * required=false, + * type="integer", + * ), + * @SWG\Parameter( + * name="distributor_id", + * in="query", + * description="店铺id", + * required=false, + * type="integer", + * ), + * @SWG\Parameter( + * name="data_type", + * in="query", + * description="数据类型 main_category-主类目 category-分类 seckill-限时特惠 group-拼团 sales-按销量 items-指定商品 distributor-指定店铺", + * required=true, + * type="string", + * ), + * @SWG\Parameter( + * name="data_value", + * in="query", + * description="数据值", + * required=true, + * type="string", + * ), + * @SWG\Parameter( + * name="num", + * in="query", + * description="数量", + * required=true, + * type="integer", + * ), + * @SWG\Response( + * response=200, + * description="成功返回结构", + * @SWG\Schema( + * @SWG\Property(property="data", type="object", + * @SWG\Property(property="data", type="array", + * @SWG\Items(type="object", + * @SWG\Property(property="item_id", type="integer"), + * @SWG\Property(property="item_name", type="string"), + * ), + * ), + * @SWG\Property(property="filter", type="object", + * @SWG\Property(property="main_category", type="integer"), + * @SWG\Property(property="category_id", type="integer"), + * @SWG\Property(property="seckill_id", type="integer"), + * @SWG\Property(property="group_id", type="integer"), + * @SWG\Property(property="item_id", type="integer"), + * @SWG\Property(property="distributor_id", type="integer"), + * ), + * @SWG\Property(property="goodsSort", type="integer"), + * ) + * ) + * ), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/WechatErrorRespones") ) ) + * ) + */ + public function getWidgetItems(Request $request) + { + $params = $request->all('regionauth_id', 'distributor_id', 'data_type', 'data_value', 'num', 'page', 'pageSize'); + $params['company_id'] = app('auth')->user()->get('company_id'); + $pages_template_services = new PagesTemplateServices(); + $result = $pages_template_services->getWidgetItems($params); + + //营销标签 + $itemsService = new ItemsService(); + $result['data'] = $itemsService->getItemsListActityTag($result['data'], $params['company_id'], $params['regionauth_id'], -1, 0, '', 'include_not_start'); + + return $this->response->array($result); + } + /** * @SWG\Get( * path="/pagestemplate/lists", @@ -40,6 +123,13 @@ class PagesTemplate extends Controller * type="string", * ), * @SWG\Parameter( + * name="regionauth_id", + * in="query", + * description="区域id", + * required=false, + * type="integer", + * ), + * @SWG\Parameter( * name="distributor_id", * in="query", * description="门店id", @@ -47,6 +137,13 @@ class PagesTemplate extends Controller * type="integer", * ), * @SWG\Parameter( + * name="weapp_pages", + * in="query", + * description="小程序页码类型 index-首页 distributor_index-门店首页", + * required=false, + * type="string", + * ), + * @SWG\Parameter( * name="page_no", * in="query", * description="页码", @@ -93,20 +190,40 @@ class PagesTemplate extends Controller { // Debug: 1e2364 $company_id = app('auth')->user()->get('company_id'); + $regionauth_id = $request->input('regionauth_id'); $distributor_id = $request->input('distributor_id', 0); - $page_no = $request->input('page_no', 1); - $page_size = $request->input('page_size', 50); + $weapp_pages = $request->input('weapp_pages', 'index'); + $page_no = $request->input('page', 1); + $page_size = $request->input('pageSize', 50); + + if ($distributor_id > 0 && $weapp_pages == 'index') { + $weapp_pages = 'distributor_index'; + } $params = [ 'company_id' => $company_id, 'distributor_id' => $distributor_id, + 'weapp_pages' => $weapp_pages, 'page_no' => $page_no, 'page_size' => $page_size ]; + if (isset($regionauth_id)) { + $params['regionauth_id'] = $regionauth_id; + } $pages_template_services = new PagesTemplateServices(); $result = $pages_template_services->lists($params); + if ($result['list']) { + $regionauthService = new RegionauthService(); + $regionauthList = $regionauthService->getLists(['company_id' => $company_id, 'regionauth_id' => array_column($result['list'], 'regionauth_id')], 'regionauth_id,regionauth_name'); + $regionauthNameMap = array_column($regionauthList, 'regionauth_name', 'regionauth_id'); + + foreach ($result['list'] as $key => $val) { + $result['list'][$key]['regionauth_name'] = $regionauthNameMap[$val['regionauth_id']] ?? ''; + } + } + return $this->response->array($result); } @@ -125,6 +242,13 @@ class PagesTemplate extends Controller * type="string", * ), * @SWG\Parameter( + * name="regionauth_id", + * in="formData", + * description="区域id", + * required=false, + * type="integer", + * ), + * @SWG\Parameter( * name="distributor_id", * in="formData", * description="门店id", @@ -155,7 +279,7 @@ class PagesTemplate extends Controller * @SWG\Parameter( * name="weapp_pages", * in="formData", - * description="小程序页码类型", + * description="小程序页码类型 index-首页 distributor_index-门店首页", * required=false, * type="string", * ), @@ -191,14 +315,20 @@ class PagesTemplate extends Controller public function add(Request $request) { $company_id = app('auth')->user()->get('company_id'); + $regionauth_id = $request->input('regionauth_id', 0); $distributor_id = $request->input('distributor_id', 0); $template_name = $request->input('template_name'); //展示客户端名称 如小程序商城 yykweishop $template_title = $request->input('template_title'); $template_pic = $request->input('template_pic'); $weapp_pages = $request->input('weapp_pages', 'index'); //小程序页面类型 默认为首页页面 + if ($distributor_id > 0 && $weapp_pages == 'index') { + $weapp_pages = 'distributor_index'; + } + $params = [ 'company_id' => $company_id, + 'regionauth_id' => $regionauth_id, 'distributor_id' => $distributor_id, 'template_name' => $template_name, 'template_title' => $template_title, @@ -236,6 +366,13 @@ class PagesTemplate extends Controller * type="string", * ), * @SWG\Parameter( + * name="regionauth_id", + * in="formData", + * description="区域id", + * required=false, + * type="integer", + * ), + * @SWG\Parameter( * name="distributor_id", * in="formData", * description="店铺ID", @@ -306,18 +443,20 @@ class PagesTemplate extends Controller $template_title = $request->input('template_title', false); $template_pic = $request->input('template_pic', false); - if ($template_title !== false || $template_pic !== false) { + $regionauth_id = $request->input('regionauth_id', false); + if ($template_title !== false || $template_pic !== false || $regionauth_id !== false) { $pages_template_services = new PagesTemplateServices(); $pages_template_services->updateInfo($company_id, $pages_template_id, [ 'template_title' => $template_title ?: '', 'template_pic' => $template_pic ?: '', + 'regionauth_id' => $regionauth_id ?: 0 ]); return $this->response->array(['status' => true]); } $template_content = $request->input('template_content'); $element_edit_status = $request->input('element_edit_status'); - $template_name = $request->input('template_name'); //展示客户端名称 如小程序商城 yykweishop + $template_name = $request->input('template_name', 'yykweishop'); //展示客户端名称 如小程序商城 yykweishop $params = [ 'company_id' => $company_id, diff --git a/src/ThemeBundle/Http/Api/V1/Action/PagesTemplateSet.php b/src/ThemeBundle/Http/Api/V1/Action/PagesTemplateSet.php index e9efe24..85c9793 100644 --- a/src/ThemeBundle/Http/Api/V1/Action/PagesTemplateSet.php +++ b/src/ThemeBundle/Http/Api/V1/Action/PagesTemplateSet.php @@ -89,6 +89,7 @@ class PagesTemplateSet extends Controller $params['tab_bar'] = $request->input('tab_bar'); $params['company_id'] = $company_id; $params['pages_template_id'] = $request->input('pages_template_id', 0); + $params['regionauth_id'] = $request->input('regionauth_id', 0); $pages = new PagesTemplateSetServices(); $result = $pages->saveData($params); @@ -140,6 +141,7 @@ class PagesTemplateSet extends Controller $company_id = app('auth')->user()->get('company_id'); $params['company_id'] = $company_id; $params['pages_template_id'] = $request->input('pages_template_id', 0); + $params['regionauth_id'] = $request->input('regionauth_id', 0); $pages = new PagesTemplateSetServices(); $result = $pages->getInfo($params); diff --git a/src/ThemeBundle/Http/FrontApi/V1/Action/OpenScreenAd.php b/src/ThemeBundle/Http/FrontApi/V1/Action/OpenScreenAd.php index d19069c..83647dd 100644 --- a/src/ThemeBundle/Http/FrontApi/V1/Action/OpenScreenAd.php +++ b/src/ThemeBundle/Http/FrontApi/V1/Action/OpenScreenAd.php @@ -64,14 +64,17 @@ class OpenScreenAd extends Controller $params = $request->all('company_id'); $auth_info = $request->get('auth'); + $filter['company_id'] = $auth_info['company_id']; + $filter['is_enable'] = 1; + $filter['start_time|lte'] = time(); + $filter['end_time|gte'] = time(); $OpenScreenAd = new OpenScreenAdServices(); - $data = $OpenScreenAd->getInfo($auth_info['company_id']); - if (empty($data)) { - $response = []; - } else { - $response = $data; + $data = $OpenScreenAd->lists($filter, '*', 1, 1); + $result = !empty($data['list']) ? reset($data['list']) : []; + if ($result) { + $result['ad_url'] = json_decode($result['ad_url'], true); } - return $this->response->array($response); + return $this->response->array($result); } } diff --git a/src/ThemeBundle/Http/FrontApi/V1/Action/PagesAdPlace.php b/src/ThemeBundle/Http/FrontApi/V1/Action/PagesAdPlace.php new file mode 100644 index 0000000..5207689 --- /dev/null +++ b/src/ThemeBundle/Http/FrontApi/V1/Action/PagesAdPlace.php @@ -0,0 +1,169 @@ +popup,轮播图=>carousel", + * required=true, + * type="string", + * enum={"popup", "carousel"} + * ), + * @SWG\Parameter( + * name="page_type", + * in="query", + * description="页面类型", + * required=true, + * type="string" + * ), + * @SWG\Response( + * response=200, + * description="成功", + * @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/PagesAdPlace")) + * ), + * @SWG\Response(response="default", description="错误返回结构", @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones"))) + * ) + */ + public function getAdList(Request $request) + { + $params = $request->all(); + $authInfo = $request->get('auth'); + + $validator = app('validator')->make($params, [ + 'ad_type' => 'required|in:popup,carousel', + 'page_type' => 'required|string', + ]); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + + $filter['company_id'] = $authInfo['company_id']; + $filter['regionauth_id'] = $params['regionauth_id'] ?? 0; + $filter['use_bound'] = 0; + $filter['start_time|lte'] = time(); + $filter['end_time|gte'] = time(); + $filter['ad_type'] = $params['ad_type']; + $filter['pages'] = $params['page_type']; + $filter['audit_status'] = 'approved'; + + $service = new PagesAdPlaceService(); + $result = $service->getListWithRelTags($filter, 1, -1, ['sort' => 'desc', 'id' => 'DESC']); + + if (isset($params['distributor_id']) && $params['distributor_id'] > 0) { + $filter['use_bound'] = 1; + $filter['distributor_id'] = $params['distributor_id']; + $distributorResult = $service->getListWithRelTags($filter, 1, -1, ['sort' => 'desc', 'id' => 'DESC']); + $result['list'] = array_merge($result['list'], $distributorResult['list']); + usort($result['list'], function($left, $right) { + if ($right['sort'] == $left['sort']) { + return $right['id'] - $left['id']; + } + return $right['sort'] - $left['sort']; + }); + } + + $tagRelAdPlaceIds = []; + foreach ($result['list'] as $key => $val) { + if ($authInfo['user_id'] > 0) { + foreach ($val['rel_tags'] as $relTag) { + if (!isset($tagRelAdPlaceIds[$relTag['tag_id']])) { + $tagRelAdPlaceIds[$relTag['tag_id']] = [$val['id']]; + } else { + if (!in_array($val['id'], $tagRelAdPlaceIds[$relTag['tag_id']])) { + $tagRelAdPlaceIds[$relTag['tag_id']][] = $val['id']; + } + } + } + } else { + if ($val['rel_tags']) { + unset($result['list'][$key]); + } + } + } + + if ($tagRelAdPlaceIds) { + $checkParams = [ + 'company_id' => $authInfo['company_id'], + 'user_id' => $authInfo['user_id'], + 'tag_id' => array_keys($tagRelAdPlaceIds), + ]; + $memberTagsService = new MemberTagsService(); + $bindTags = $memberTagsService->checkAndProcessTag($checkParams); + + $filterAdPlaceIds = []; + foreach ($bindTags as $tag) { + if ($tag['related'] && isset($tagRelAdPlaceIds[$tag['tag_id']])) { + $filterAdPlaceIds = array_merge($filterAdPlaceIds, $tagRelAdPlaceIds[$tag['tag_id']]); + } + } + + foreach ($result['list'] as $key => $val) { + if ($val['rel_tags'] && !in_array($val['id'], $filterAdPlaceIds)) { + unset($result['list'][$key]); + } + } + } + + return $this->response->array(array_values($result['list'])); + } +} + +/** + * @SWG\Definition( + * definition="PagesAdPlace", + * type="object", + * @SWG\Property(property="id", type="integer", description="ID"), + * @SWG\Property(property="company_id", type="integer", description="公司ID"), + * @SWG\Property(property="regionauth_id", type="integer", description="区域ID"), + * @SWG\Property(property="distributor_id", type="integer", description="店铺ID"), + * @SWG\Property(property="ad_type", type="string", description="广告类型:弹窗=>popup,轮播图=>carousel"), + * @SWG\Property(property="name", type="string", description="广告位名称"), + * @SWG\Property(property="pages", type="array", @SWG\Items(type="string"), description="关联页面"), + * @SWG\Property(property="start_time", type="integer", description="开始时间"), + * @SWG\Property(property="end_time", type="integer", description="结束时间"), + * @SWG\Property(property="setting", type="string", description="设置信息,json格式"), + * @SWG\Property(property="auto_play", type="integer", description="自动播放"), + * @SWG\Property(property="play_interval", type="integer", description="播放间隔时间"), + * @SWG\Property(property="auto_close", type="integer", description="自动关闭"), + * @SWG\Property(property="close_delay", type="integer", description="关闭延迟时间"), + * @SWG\Property(property="created", type="integer", description="创建时间"), + * @SWG\Property(property="updated", type="integer", description="更新时间"), + * @SWG\Property(property="sort", type="integer", description="排序") + * ) + */ \ No newline at end of file diff --git a/src/ThemeBundle/Http/FrontApi/V1/Action/PagesSideBar.php b/src/ThemeBundle/Http/FrontApi/V1/Action/PagesSideBar.php new file mode 100644 index 0000000..7351fcd --- /dev/null +++ b/src/ThemeBundle/Http/FrontApi/V1/Action/PagesSideBar.php @@ -0,0 +1,89 @@ +all(); + $authInfo = $request->get('auth'); + + $validator = app('validator')->make($params, [ + 'page_type' => 'required|string', + ]); + if ($validator->fails()) { + throw new ResourceException($validator->errors()->first()); + } + + $filter['company_id'] = $authInfo['company_id']; + $filter['regionauth_id'] = $params['regionauth_id'] ?? 0; + $filter['disabled'] = false; + $filter['pages|contains'] = ','.$params['page_type'].','; + + $service = new PagesSideBarService(); + $list = $service->getLists($filter, '*', 1, 1); + $result = []; + if ($list) { + $result = $list[0]; + } + return $this->response->array($result); + } +} + +/** + * @SWG\Definition( + * definition="PagesSideBar", + * type="object", + * @SWG\Property(property="id", type="integer", description="ID"), + * @SWG\Property(property="company_id", type="integer", description="公司ID"), + * @SWG\Property(property="regionauth_id", type="integer", description="区域ID"), + * @SWG\Property(property="name", type="string", description="侧边栏名称"), + * @SWG\Property(property="pages", type="array", @SWG\Items(type="string"), description="关联页面"), + * @SWG\Property(property="disabled", type="boolean", description="是否禁用"), + * @SWG\Property(property="setting", type="string", description="设置信息,json格式"), + * @SWG\Property(property="created", type="integer", description="创建时间"), + * @SWG\Property(property="updated", type="integer", description="更新时间") + * ) + */ \ No newline at end of file diff --git a/src/ThemeBundle/Http/FrontApi/V1/Action/PagesTemplate.php b/src/ThemeBundle/Http/FrontApi/V1/Action/PagesTemplate.php index 225585d..649f17f 100644 --- a/src/ThemeBundle/Http/FrontApi/V1/Action/PagesTemplate.php +++ b/src/ThemeBundle/Http/FrontApi/V1/Action/PagesTemplate.php @@ -20,13 +20,121 @@ namespace ThemeBundle\Http\FrontApi\V1\Action; use App\Http\Controllers\Controller as Controller; use Dingo\Api\Exception\ResourceException; use Illuminate\Http\Request; +use KaquanBundle\Services\DiscountCardService; +use KaquanBundle\Services\KaquanService; +use PromotionsBundle\Services\MarketingActivityService; use TdksetBundle\Services\TdkGlobalService; use ThemeBundle\Services\PagesTemplateServices; use ThemeBundle\Services\PagesTemplateSetServices; use DistributionBundle\Entities\Distributor; +use GoodsBundle\Services\ItemsService; class PagesTemplate extends Controller { + /** + * @SWG\Get( + * path="/h5app/wxapp/pagestemplate/widget/items", + * summary="获取模板组件商品", + * tags={"模板"}, + * description="获取模板组件商品", + * @SWG\Parameter( + * name="regionauth_id", + * in="query", + * description="区域id", + * required=false, + * type="integer", + * ), + * @SWG\Parameter( + * name="distributor_id", + * in="query", + * description="店铺id", + * required=false, + * type="integer", + * ), + * @SWG\Parameter( + * name="data_type", + * in="query", + * description="数据类型 main_category-主类目 category-分类 seckill-限时特惠 group-拼团 sales-按销量 items-指定商品 distributor-指定店铺", + * required=true, + * type="string", + * ), + * @SWG\Parameter( + * name="data_value", + * in="query", + * description="数据值", + * required=true, + * type="string", + * ), + * @SWG\Parameter( + * name="num", + * in="query", + * description="数量", + * required=true, + * type="integer", + * ), + * @SWG\Response( + * response=200, + * description="成功返回结构", + * @SWG\Schema( + * @SWG\Property(property="data", type="object", + * @SWG\Property(property="data", type="array", + * @SWG\Items(type="object", + * @SWG\Property(property="item_id", type="integer"), + * @SWG\Property(property="item_name", type="string"), + * ), + * ), + * @SWG\Property(property="filter", type="object", + * @SWG\Property(property="main_category", type="integer"), + * @SWG\Property(property="category_id", type="integer"), + * @SWG\Property(property="seckill_id", type="integer"), + * @SWG\Property(property="group_id", type="integer"), + * @SWG\Property(property="item_id", type="integer"), + * @SWG\Property(property="distributor_id", type="integer"), + * ), + * @SWG\Property(property="goodsSort", type="integer"), + * ) + * ) + * ), + * @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/ThemeErrorRespones") ) ) + * ) + */ + public function getWidgetItems(Request $request) + { + $authInfo = $request->get('auth'); + $params = $request->all('regionauth_id', 'distributor_id', 'data_type', 'data_value', 'num', 'page', 'pageSize', 'sort_gte'); + $params['company_id'] = $authInfo['company_id']; + $params['user_id'] = $authInfo['user_id'] ?? 0; + $pages_template_services = new PagesTemplateServices(); + $result = $pages_template_services->getWidgetItems($params); + + $itemsService = new ItemsService(); + // 如果是推广员不需要计算会员价 + if ($result['data']) { + // 计算会员价 + $result['data'] = $itemsService->getItemsListMemberPrice($result['data'], $authInfo['user_id'], $params['company_id']); + } + //营销标签 + if ($params['data_type'] == 'seckill') { + $promotionId = intval($params['data_value']); + $promotionType = 'limited_time_sale'; + } else { + $promotionId = 0; + $promotionType = ''; + } + $result['data'] = $itemsService->getItemsListActityTag($result['data'], $params['company_id'], $params['regionauth_id'], $params['user_id'], $promotionId, $promotionType, 'include_not_start'); + + //优惠券标签 + /** @var DiscountCardService $kaquanService */ + // $kaquanService = new KaquanService(new DiscountCardService()); + // $result['data'] = $kaquanService->getCardListByItemList($params['company_id'], $params['regionauth_id'], $result['data'], $params['user_id']); + + //会员优先购标识 + // $marketingService = new MarketingActivityService(); + // $result['data'] = $marketingService->getValidMemberPreferenceByItems($params['company_id'], $params['regionauth_id'], $result['data']); + + return $this->response->array($result); + } + /** * @SWG\Get( * path="/h5app/wxapp/pagestemplate/detail", @@ -105,6 +213,7 @@ class PagesTemplate extends Controller { $auth_info = $request->get('auth'); $distributor_id = $request->input('distributor_id', 0); //门店id + $regionauth_id = $request->input('regionauth_id', 0); //区域id $weapp_pages = $request->input('weapp_pages', 'index'); //小程序页面类型 $template_name = $request->input('template_name'); //小程序页面类型 $version = $request->input('version', 'v1.0.2'); //小程序版本 @@ -116,6 +225,7 @@ class PagesTemplate extends Controller $e_activity_id = $request->input('e_activity_id', 0); $params = [ 'company_id' => $auth_info['company_id'], + 'regionauth_id' => $regionauth_id, 'user_id' => ($auth_info['user_id']) ?? 0, 'distributor_id' => $distributor_id, 'weapp_pages' => $weapp_pages, @@ -228,7 +338,7 @@ class PagesTemplate extends Controller 'company_id' => $auth_info['company_id'], 'user_id' => ($auth_info['user_id']) ?? 0, 'distributor_id' => $distributor_id, - 'weapp_pages' => $weapp_pages, + 'weapp_pages' => $weapp_pages == 'index' ? 'distributor_index' : $weapp_pages, 'template_name' => $template_name, 'version' => $version ]; @@ -242,6 +352,8 @@ class PagesTemplate extends Controller throw new ResourceException('当前店铺已失效'); } + $params['regionauth_id'] = $createDistributorInfo['regionauth_id']; + $rules = [ 'distributor_id' => ['required|integer|min:1', '缺少门店id'], 'template_name' => ['required', '缺少模板展示类型'], @@ -306,6 +418,8 @@ class PagesTemplate extends Controller throw new ResourceException($error); } + $filter['regionauth_id'] = $request->input('regionauth_id', 0); + $pages_template_set_services = new PagesTemplateSetServices(); $result = $pages_template_set_services->getInfo($filter); diff --git a/src/ThemeBundle/Repositories/OpenScreenAdRepository.php b/src/ThemeBundle/Repositories/OpenScreenAdRepository.php index 0d75792..20057be 100644 --- a/src/ThemeBundle/Repositories/OpenScreenAdRepository.php +++ b/src/ThemeBundle/Repositories/OpenScreenAdRepository.php @@ -25,7 +25,7 @@ use Dingo\Api\Exception\ResourceException; class OpenScreenAdRepository extends EntityRepository { public $table = "pages_open_screen_ad"; - public $cols = ['id','company_id','ad_material','is_enable','show_time','position','is_jump','material_type','waiting_time','ad_url','app','created','updated']; + public $cols = ['id','company_id','ad_material','is_enable','show_time','position','is_jump','material_type','waiting_time','ad_url','app','start_time','end_time','created','updated']; /** * 新增 * @@ -174,7 +174,7 @@ class OpenScreenAdRepository extends EntityRepository array_walk($value, function (&$colVal) use ($qb) { $colVal = $qb->expr()->literal($colVal); }); - $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); } else { $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); } diff --git a/src/ThemeBundle/Repositories/PagesAdPlaceRelDistributorsRepository.php b/src/ThemeBundle/Repositories/PagesAdPlaceRelDistributorsRepository.php new file mode 100644 index 0000000..3d0ba91 --- /dev/null +++ b/src/ThemeBundle/Repositories/PagesAdPlaceRelDistributorsRepository.php @@ -0,0 +1,327 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 批量插入广告位与店铺关联 + * + * @param array $data + * @return bool + */ + public function batchInsert(array $data) + { + if (empty($data)) { + return false; + } + + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder(); + + $columns = array(); + foreach ($data[0] as $columnName => $value) { + $columns[] = $columnName; + } + + $sql = 'INSERT INTO '.$this->table. ' (' . implode(', ', $columns) . ') VALUES '; + + $time = time(); + $insertValue = []; + foreach ($data as $value) { + foreach ($value as &$v) { + $v = $qb->expr()->literal($v); + } + $insertValue[] = '(' . implode(', ', $value) . ')'; + } + + $sql .= implode(',', $insertValue); + return $conn->executeUpdate($sql); + } + + /** + * 根据条件更新单个关联 + * + * @param array $filter + * @param array $data + * @return array + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多个关联 + * + * @param array $filter + * @param array $data + * @return int + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach ($data as $key => $val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据条件删除关联 + * + * @param array $filter + * @return bool + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if (!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach ($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + /** + * 设置实体属性值 + * + * @param object $entity + * @param array $params + * @return object + */ + private function setColumnNamesData($entity, $params) + { + foreach ($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (!method_exists($entity, $fun)) { + continue; + } + $entity->$fun($params[$col]); + } + } + return $entity; + } + + /** + * 获取实体属性值 + * + * @param object $entity + * @param array $cols + * @param array $ignore + * @return array + */ + private function getColumnNamesData($entity, $cols = [], $ignore = []) + { + if (!$cols) { + $cols = $this->cols; + } + + $values = []; + foreach ($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (!method_exists($entity, $fun)) { + continue; + } + $values[$col] = $entity->$fun(); + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param array $filter + * @param object $qb + * @return object + */ + private function _filter($filter, $qb) + { + foreach ($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v, $k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 获取关联列表 + * + * @param array $filter + * @param string $cols + * @param int $page + * @param int $pageSize + * @param array $orderBy + * @return array + */ + public function getLists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + + return $qb->execute()->fetchAll(); + } + + /** + * 获取关联列表及总数 + * + * @param array $filter + * @param string $cols + * @param int $page + * @param int $pageSize + * @param array $orderBy + * @return array + */ + public function lists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + $result['list'] = array(); + + if ($result['total_count'] > 0) { + $result['list'] = $this->getLists($filter, $cols, $page, $pageSize, $orderBy); + } + + return $result; + } + + /** + * 获取单个关联信息 + * + * @param array $filter + * @return array + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计关联数量 + * + * @param array $filter + * @return int + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(*)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } + + public function getRelDistributorsByAdPlaceIds($adPlaceIds) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->from($this->table, 'r') + ->leftJoin('r', 'distribution_distributor', 'd', 'r.distributor_id = d.distributor_id') + ->where($qb->expr()->in('r.ad_place_id', $adPlaceIds)); + $distributorList =$qb->select('r.ad_place_id, r.distributor_id, d.name')->execute()->fetchAll(); + $relDistributors = []; + foreach ($distributorList as $distributor) { + if (!isset($relDistributors[$distributor['ad_place_id']])) { + $relDistributors[$distributor['ad_place_id']] = [['distributor_id' => $distributor['distributor_id'], 'distributor_name' => $distributor['name']]]; + } else { + $relDistributors[$distributor['ad_place_id']][] = ['distributor_id' => $distributor['distributor_id'], 'distributor_name' => $distributor['name']]; + } + } + return $relDistributors; + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Repositories/PagesAdPlaceRelMemberTagsRepository.php b/src/ThemeBundle/Repositories/PagesAdPlaceRelMemberTagsRepository.php new file mode 100644 index 0000000..a14ddcc --- /dev/null +++ b/src/ThemeBundle/Repositories/PagesAdPlaceRelMemberTagsRepository.php @@ -0,0 +1,327 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 批量插入广告位与会员标签关联 + * + * @param array $data + * @return bool + */ + public function batchInsert(array $data) + { + if (empty($data)) { + return false; + } + + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder(); + + $columns = array(); + foreach ($data[0] as $columnName => $value) { + $columns[] = $columnName; + } + + $sql = 'INSERT INTO '.$this->table. ' (' . implode(', ', $columns) . ') VALUES '; + + $time = time(); + $insertValue = []; + foreach ($data as $value) { + foreach ($value as &$v) { + $v = $qb->expr()->literal($v); + } + $insertValue[] = '(' . implode(', ', $value) . ')'; + } + + $sql .= implode(',', $insertValue); + return $conn->executeUpdate($sql); + } + + /** + * 根据条件更新单个关联 + * + * @param array $filter + * @param array $data + * @return array + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多个关联 + * + * @param array $filter + * @param array $data + * @return int + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach ($data as $key => $val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据条件删除关联 + * + * @param array $filter + * @return bool + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if (!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach ($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + /** + * 设置实体属性值 + * + * @param object $entity + * @param array $params + * @return object + */ + private function setColumnNamesData($entity, $params) + { + foreach ($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (!method_exists($entity, $fun)) { + continue; + } + $entity->$fun($params[$col]); + } + } + return $entity; + } + + /** + * 获取实体属性值 + * + * @param object $entity + * @param array $cols + * @param array $ignore + * @return array + */ + private function getColumnNamesData($entity, $cols = [], $ignore = []) + { + if (!$cols) { + $cols = $this->cols; + } + + $values = []; + foreach ($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (!method_exists($entity, $fun)) { + continue; + } + $values[$col] = $entity->$fun(); + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param array $filter + * @param object $qb + * @return object + */ + private function _filter($filter, $qb) + { + foreach ($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v, $k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 获取关联列表 + * + * @param array $filter + * @param string $cols + * @param int $page + * @param int $pageSize + * @param array $orderBy + * @return array + */ + public function getLists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + + return $qb->execute()->fetchAll(); + } + + /** + * 获取关联列表及总数 + * + * @param array $filter + * @param string $cols + * @param int $page + * @param int $pageSize + * @param array $orderBy + * @return array + */ + public function lists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + $result['list'] = array(); + + if ($result['total_count'] > 0) { + $result['list'] = $this->getLists($filter, $cols, $page, $pageSize, $orderBy); + } + + return $result; + } + + /** + * 获取单个关联信息 + * + * @param array $filter + * @return array + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计关联数量 + * + * @param array $filter + * @return int + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(*)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } + + public function getRelTagsByAdPlaceIds($adPlaceIds) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->from($this->table, 'r') + ->leftJoin('r', 'members_tags', 't', 'r.tag_id = t.tag_id') + ->where($qb->expr()->in('r.ad_place_id', $adPlaceIds)); + $tagList =$qb->select('r.ad_place_id, r.tag_id, t.tag_name')->execute()->fetchAll(); + $relTags = []; + foreach ($tagList as $tag) { + if (!isset($relTags[$tag['ad_place_id']])) { + $relTags[$tag['ad_place_id']] = [['tag_id' => $tag['tag_id'], 'tag_name' => $tag['tag_name']]]; + } else { + $relTags[$tag['ad_place_id']][] = ['tag_id' => $tag['tag_id'], 'tag_name' => $tag['tag_name']]; + } + } + return $relTags; + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Repositories/PagesAdPlaceRepository.php b/src/ThemeBundle/Repositories/PagesAdPlaceRepository.php new file mode 100644 index 0000000..85bf446 --- /dev/null +++ b/src/ThemeBundle/Repositories/PagesAdPlaceRepository.php @@ -0,0 +1,329 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件更新单个广告位设置 + * + * @param array $filter + * @param array $data + * @return array + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多个广告位设置 + * + * @param array $filter + * @param array $data + * @return int + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach ($data as $key => $val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据ID删除广告位设置 + * + * @param int $id + * @return bool + */ + public function deleteById($id) + { + $entity = $this->find($id); + if (!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除广告位设置 + * + * @param array $filter + * @return bool + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if (!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach ($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + /** + * 设置实体属性值 + * + * @param object $entity + * @param array $params + * @return object + */ + private function setColumnNamesData($entity, $params) + { + foreach ($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (!method_exists($entity, $fun)) { + continue; + } + $entity->$fun($params[$col]); + } + } + return $entity; + } + + /** + * 获取实体属性值 + * + * @param object $entity + * @param array $cols + * @param array $ignore + * @return array + */ + private function getColumnNamesData($entity, $cols = [], $ignore = []) + { + if (!$cols) { + $cols = $this->cols; + } + + $values = []; + foreach ($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (!method_exists($entity, $fun)) { + continue; + } + $values[$col] = $entity->$fun(); + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param array $filter + * @param object $qb + * @return object + */ + private function _filter($filter, $qb) + { + foreach ($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v, $k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb->andWhere($qb->expr()->$k($v, $value)); + } else { + $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 获取广告位设置列表 + * + * @param array $filter + * @param string $cols + * @param int $page + * @param int $pageSize + * @param array $orderBy + * @return array + */ + public function getLists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + + if (isset($filter['distributor_id'])) { + if ($filter['distributor_id'] > 0) { + $qb->leftJoin($this->table, 'pages_ad_place_rel_distributors', 'pages_ad_place_rel_distributors', 'pages_ad_place_rel_distributors.ad_place_id = '.$this->table.'.id'); + $qb->andWhere($qb->expr()->eq('distributor_id', $filter['distributor_id'])); + if (isset($filter['company_id'])) { + $qb->andWhere($qb->expr()->eq($this->table.'.company_id', $filter['company_id'])); + unset($filter['company_id']); + } + } + unset($filter['distributor_id']); + } + + $qb = $this->_filter($filter, $qb); + + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + + return $qb->execute()->fetchAll(); + } + + /** + * 获取广告位设置列表及总数 + * + * @param array $filter + * @param string $cols + * @param int $page + * @param int $pageSize + * @param array $orderBy + * @return array + */ + public function lists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total_count'] = $this->count($filter); + $result['list'] = []; + + if ($result['total_count'] > 0) { + $result['list'] = $this->getLists($filter, $cols, $page, $pageSize, $orderBy); + } + + return $result; + } + + /** + * 根据ID获取数据 + * + * @param int $id + * @return array + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 获取单个广告位设置信息 + * + * @param array $filter + * @return array + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计广告位设置数量 + * + * @param array $filter + * @return int + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(*)') + ->from($this->table); + if ($filter) { + if (isset($filter['distributor_id'])) { + if ($filter['distributor_id'] > 0) { + $qb->leftJoin($this->table, 'pages_ad_place_rel_distributors', 'pages_ad_place_rel_distributors', 'pages_ad_place_rel_distributors.ad_place_id = '.$this->table.'.id'); + $qb->andWhere($qb->expr()->eq('distributor_id', $filter['distributor_id'])); + if (isset($filter['company_id'])) { + $qb->andWhere($qb->expr()->eq($this->table.'.company_id', $filter['company_id'])); + unset($filter['company_id']); + } + } + unset($filter['distributor_id']); + } + + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Repositories/PagesSideBarRepository.php b/src/ThemeBundle/Repositories/PagesSideBarRepository.php new file mode 100644 index 0000000..7d8a053 --- /dev/null +++ b/src/ThemeBundle/Repositories/PagesSideBarRepository.php @@ -0,0 +1,343 @@ +setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 根据条件更新单个侧边栏设置 + * + * @param array $filter + * @param array $data + * @return array + */ + public function updateOneBy(array $filter, array $data) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + throw new ResourceException("未查询到更新数据"); + } + + $entity = $this->setColumnNamesData($entity, $data); + + $em = $this->getEntityManager(); + $em->persist($entity); + $em->flush(); + + return $this->getColumnNamesData($entity); + } + + /** + * 更新多个侧边栏设置 + * + * @param array $filter + * @param array $data + * @return int + */ + public function updateBy(array $filter, array $data) + { + $conn = app("registry")->getConnection("default"); + $qb = $conn->createQueryBuilder()->update($this->table); + foreach ($data as $key => $val) { + $qb = $qb->set($key, $qb->expr()->literal($val)); + } + + $qb = $this->_filter($filter, $qb); + + return $qb->execute(); + } + + /** + * 根据ID删除侧边栏设置 + * + * @param int $id + * @return bool + */ + public function deleteById($id) + { + $entity = $this->find($id); + if (!$entity) { + return true; + } + $em = $this->getEntityManager(); + $em->remove($entity); + $em->flush(); + return true; + } + + /** + * 根据条件删除侧边栏设置 + * + * @param array $filter + * @return bool + */ + public function deleteBy($filter) + { + $entityList = $this->findBy($filter); + if (!$entityList) { + return true; + } + $em = $this->getEntityManager(); + foreach ($entityList as $entityProp) { + $em->remove($entityProp); + $em->flush(); + } + return true; + } + + /** + * 设置实体属性值 + * + * @param object $entity + * @param array $params + * @return object + */ + private function setColumnNamesData($entity, $params) + { + foreach ($this->cols as $col) { + if (isset($params[$col])) { + $fun = "set". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (!method_exists($entity, $fun)) { + continue; + } + $entity->$fun($params[$col]); + } + } + return $entity; + } + + /** + * 获取实体属性值 + * + * @param object $entity + * @param array $cols + * @param array $ignore + * @return array + */ + private function getColumnNamesData($entity, $cols = [], $ignore = []) + { + if (!$cols) { + $cols = $this->cols; + } + + $values = []; + foreach ($cols as $col) { + if ($ignore && in_array($col, $ignore)) { + continue; + } + $fun = "get". str_replace(" ", "", ucwords(str_replace("_", " ", $col))); + if (!method_exists($entity, $fun)) { + continue; + } + $values[$col] = $entity->$fun(); + } + return $values; + } + + /** + * 筛选条件格式化 + * + * @param array $filter + * @param object $qb + * @return object + */ + private function _filter($filter, $qb) + { + foreach ($filter as $field => $value) { + $list = explode('|', $field); + if (count($list) > 1) { + list($v, $k) = $list; + if ($k == 'contains') { + $k = 'like'; + } + if ($k == 'like') { + $value = '%'.$value.'%'; + } + if (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); + } + continue; + } elseif (is_array($value)) { + array_walk($value, function (&$colVal) use ($qb) { + $colVal = $qb->expr()->literal($colVal); + }); + $qb = $qb->andWhere($qb->expr()->in($field, $value)); + } else { + $qb = $qb->andWhere($qb->expr()->eq($field, $qb->expr()->literal($value))); + } + } + return $qb; + } + + /** + * 获取侧边栏设置列表 + * + * @param array $filter + * @param string $cols + * @param int $page + * @param int $pageSize + * @param array $orderBy + * @return array + */ + public function getLists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder()->select($cols)->from($this->table); + $qb = $this->_filter($filter, $qb); + + if ($orderBy) { + foreach ($orderBy as $filed => $val) { + $qb->addOrderBy($filed, $val); + } + } + + if ($pageSize > 0) { + $qb->setFirstResult(($page - 1) * $pageSize) + ->setMaxResults($pageSize); + } + + return $qb->execute()->fetchAll(); + } + + /** + * 获取侧边栏设置列表及总数 + * + * @param array $filter + * @param string $cols + * @param int $page + * @param int $pageSize + * @param array $orderBy + * @return array + */ + public function lists($filter, $cols = '*', $page = 1, $pageSize = -1, $orderBy = array()) + { + $result['total'] = $this->count($filter); + $result['list'] = []; + + if ($result['total'] > 0) { + $result['list'] = $this->getLists($filter, $cols, $page, $pageSize, $orderBy); + } + + return $result; + } + + /** + * 根据ID获取数据 + * + * @param int $id + * @return array + */ + public function getInfoById($id) + { + $entity = $this->find($id); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 获取单个侧边栏设置信息 + * + * @param array $filter + * @return array + */ + public function getInfo(array $filter) + { + $entity = $this->findOneBy($filter); + if (!$entity) { + return []; + } + + return $this->getColumnNamesData($entity); + } + + /** + * 统计侧边栏设置数量 + * + * @param array $filter + * @return int + */ + public function count($filter) + { + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + $qb->select('count(*)') + ->from($this->table); + if ($filter) { + $this->_filter($filter, $qb); + } + $count = $qb->execute()->fetchColumn(); + return intval($count); + } + + public function checkPagesExist($companyId, $regionauthId, $pages, $excludeId = 0) + { + if (is_string($pages)) { + $pages = explode(',', trim($pages, ',')); + } + + $conn = app('registry')->getConnection('default'); + $qb = $conn->createQueryBuilder(); + + $orX = []; + array_walk($pages, function (&$page) use ($qb, &$orX) { + $orX[] = $qb->expr()->like('pages', $qb->expr()->literal('%'.$page.'%')); + }); + + $qb->select('id,pages')->from($this->table) + ->where( $qb->expr()->eq('disabled', 0)) + ->andWhere($qb->expr()->eq('company_id', $companyId)) + ->andWhere($qb->expr()->eq('regionauth_id', $regionauthId)) + ->andWhere($qb->expr()->orX(...$orX)); + + if ($excludeId > 0) { + $qb->andWhere($qb->expr()->neq('id', $excludeId)); + } + + $list = $qb->execute()->fetchAll(); + + $existPages = []; + foreach ($list as $item) { + $existPages = array_merge($existPages, array_intersect($pages, explode(',', trim($item['pages'], ',')))); + } + + if ($existPages) { + throw new ResourceException(implode(',', $existPages).'不可以重复配置'); + } + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Repositories/PagesTemplateRepository.php b/src/ThemeBundle/Repositories/PagesTemplateRepository.php index 5005299..88d5790 100644 --- a/src/ThemeBundle/Repositories/PagesTemplateRepository.php +++ b/src/ThemeBundle/Repositories/PagesTemplateRepository.php @@ -223,6 +223,10 @@ class PagesTemplateRepository extends EntityRepository $entity->setCompanyId($data['company_id']); } + if (isset($data['regionauth_id']) && $data['regionauth_id']) { + $entity->setRegionauthId($data['regionauth_id']); + } + if (isset($data['distributor_id'])) { $entity->setDistributorId($data['distributor_id']); } @@ -287,6 +291,7 @@ class PagesTemplateRepository extends EntityRepository return [ 'pages_template_id' => $entity->getPagesTemplateId(), 'company_id' => $entity->getCompanyId(), + 'regionauth_id' => $entity->getRegionauthId(), 'distributor_id' => $entity->getDistributorId(), 'template_name' => $entity->getTemplateName(), 'template_title' => $entity->getTemplateTitle(), diff --git a/src/ThemeBundle/Repositories/PagesTemplateSetRepository.php b/src/ThemeBundle/Repositories/PagesTemplateSetRepository.php index d75d5f1..eaecdcd 100644 --- a/src/ThemeBundle/Repositories/PagesTemplateSetRepository.php +++ b/src/ThemeBundle/Repositories/PagesTemplateSetRepository.php @@ -100,6 +100,10 @@ class PagesTemplateSetRepository extends EntityRepository $entity->setCompanyId($data['company_id']); } + if (isset($data['regionauth_id']) && $data['regionauth_id']) { + $entity->setRegionauthId($data['regionauth_id']); + } + if (isset($data['index_type']) && !empty($data['index_type'])) { $entity->setIndexType($data['index_type']); } @@ -145,6 +149,7 @@ class PagesTemplateSetRepository extends EntityRepository return [ 'id' => $entity->getId(), 'company_id' => $entity->getCompanyId(), + 'regionauth_id' => $entity->getRegionauthId(), 'index_type' => $entity->getIndexType(), 'pages_template_id' => $entity->getPagesTemplateId(), 'is_enforce_sync' => $entity->getIsEnforceSync(), diff --git a/src/ThemeBundle/Repositories/ThemeMemberCenterShareRepository.php b/src/ThemeBundle/Repositories/ThemeMemberCenterShareRepository.php index 3dbd8b0..c77ba3c 100644 --- a/src/ThemeBundle/Repositories/ThemeMemberCenterShareRepository.php +++ b/src/ThemeBundle/Repositories/ThemeMemberCenterShareRepository.php @@ -174,7 +174,7 @@ class ThemeMemberCenterShareRepository extends EntityRepository array_walk($value, function (&$colVal) use ($qb) { $colVal = $qb->expr()->literal($colVal); }); - $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); } else { $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); } diff --git a/src/ThemeBundle/Repositories/ThemePcTemplateContentRepository.php b/src/ThemeBundle/Repositories/ThemePcTemplateContentRepository.php index 072b207..fd8cb67 100644 --- a/src/ThemeBundle/Repositories/ThemePcTemplateContentRepository.php +++ b/src/ThemeBundle/Repositories/ThemePcTemplateContentRepository.php @@ -187,7 +187,7 @@ class ThemePcTemplateContentRepository extends EntityRepository array_walk($value, function (&$colVal) use ($qb) { $colVal = $qb->expr()->literal($colVal); }); - $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); } else { $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); } diff --git a/src/ThemeBundle/Repositories/ThemePcTemplateRepository.php b/src/ThemeBundle/Repositories/ThemePcTemplateRepository.php index b81961c..2568cd0 100644 --- a/src/ThemeBundle/Repositories/ThemePcTemplateRepository.php +++ b/src/ThemeBundle/Repositories/ThemePcTemplateRepository.php @@ -210,7 +210,7 @@ class ThemePcTemplateRepository extends EntityRepository array_walk($value, function (&$colVal) use ($qb) { $colVal = $qb->expr()->literal($colVal); }); - $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); } else { $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); } diff --git a/src/ThemeBundle/Services/OpenScreenAdServices.php b/src/ThemeBundle/Services/OpenScreenAdServices.php index 665ba18..000704a 100644 --- a/src/ThemeBundle/Services/OpenScreenAdServices.php +++ b/src/ThemeBundle/Services/OpenScreenAdServices.php @@ -31,6 +31,16 @@ class OpenScreenAdServices $this->entityRepository = app('registry')->getManager('default')->getRepository(OpenScreenAd::class); } + /** + * @param $method + * @param $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->entityRepository->$method(...$parameters); + } + /** * 设置信息 */ @@ -63,7 +73,8 @@ class OpenScreenAdServices $saveAdd['waiting_time'] = $params['waiting_time']; $saveAdd['ad_url'] = $params['ad_url']; $saveAdd['app'] = $params['app']; - + $saveAdd['start_time'] = $params['start_time']; + $saveAdd['end_time'] = $params['end_time']; return $this->saveAdd($saveAdd); } else { $saveUpdate['ad_material'] = $params['ad_material']; @@ -75,6 +86,8 @@ class OpenScreenAdServices $saveUpdate['waiting_time'] = $params['waiting_time']; $saveUpdate['ad_url'] = $params['ad_url']; $saveUpdate['app'] = $params['app']; + $saveUpdate['start_time'] = $params['start_time']; + $saveUpdate['end_time'] = $params['end_time']; $saveUpdate['updated'] = time(); return $this->saveUpdate($company_id, $saveUpdate); diff --git a/src/ThemeBundle/Services/PagesAdPlaceService.php b/src/ThemeBundle/Services/PagesAdPlaceService.php new file mode 100644 index 0000000..d22742c --- /dev/null +++ b/src/ThemeBundle/Services/PagesAdPlaceService.php @@ -0,0 +1,167 @@ +entityRepository = app('registry')->getManager('default')->getRepository(PagesAdPlace::class); + $this->relMemberTagsRepository = app('registry')->getManager('default')->getRepository(PagesAdPlaceRelMemberTags::class); + $this->relDistributorsRepository = app('registry')->getManager('default')->getRepository(PagesAdPlaceRelDistributors::class); + } + + public function getListWithRelTags($filter, $page, $pageSize, $orderBy) + { + $result = $this->entityRepository->lists($filter, '*', $page, $pageSize, $orderBy); + if ($result['list']) { + $adPlaceIds = array_column($result['list'], 'id'); + $relTags = $this->relMemberTagsRepository->getRelTagsByAdPlaceIds($adPlaceIds); + foreach ($result['list'] as $key => $value) { + $result['list'][$key]['rel_tags'] = $relTags[$value['id']] ?? []; + } + $relDistributors = $this->relDistributorsRepository->getRelDistributorsByAdPlaceIds($adPlaceIds); + foreach ($result['list'] as $key => $value) { + $result['list'][$key]['rel_distributors'] = $relDistributors[$value['id']] ?? []; + } + } + return $result; + } + + public function getInfoWithRelTags($filter) + { + $result = $this->entityRepository->getInfo($filter); + if ($result) { + $relTags = $this->relMemberTagsRepository->getRelTagsByAdPlaceIds([$result['id']]); + $result['rel_tags'] = $relTags[$result['id']] ?? []; + $relDistributors = $this->relDistributorsRepository->getRelDistributorsByAdPlaceIds([$result['id']]); + $result['rel_distributors'] = $relDistributors[$result['id']] ?? []; + } + return $result; + } + + public function createWithRelTags($params) + { + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + try { + $params['use_bound'] = 0; + if (isset($params['distributor_id'])) { + $params['distributor_id'] = (array)$params['distributor_id']; + $params['distributor_id'] = array_filter($params['distributor_id']); + if ($params['distributor_id']) { + $params['use_bound'] = 1; + } + } + $result = $this->entityRepository->create($params); + if (isset($params['rel_tags']) && $params['rel_tags']) { + $relTags = []; + foreach ($params['rel_tags'] as $tag) { + $relTags[] = [ + 'company_id' => $result['company_id'], + 'ad_place_id' => $result['id'], + 'tag_id' => $tag['tag_id'], + ]; + } + $this->relMemberTagsRepository->batchInsert($relTags); + } + if (isset($params['distributor_id']) && $params['distributor_id']) { + $relDistributors = []; + foreach ($params['distributor_id'] as $distributorId) { + $relDistributors[] = [ + 'company_id' => $result['company_id'], + 'ad_place_id' => $result['id'], + 'distributor_id' => $distributorId, + ]; + } + $this->relDistributorsRepository->batchInsert($relDistributors); + } + $conn->commit(); + return $result; + } catch (\Exception $e) { + $conn->rollBack(); + throw new ResourceException($e->getMessage()); + } + } + + public function updateWithRelTags($filter, $params) + { + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + try { + $params['use_bound'] = 0; + if (isset($params['distributor_id'])) { + $params['distributor_id'] = (array)$params['distributor_id']; + $params['distributor_id'] = array_filter($params['distributor_id']); + if ($params['distributor_id']) { + $params['use_bound'] = 1; + } + } + $result = $this->entityRepository->updateOneBy($filter, $params); + $this->relMemberTagsRepository->deleteBy(['ad_place_id' => $filter['id'], 'company_id' => $filter['company_id']]); + $this->relDistributorsRepository->deleteBy(['ad_place_id' => $filter['id'], 'company_id' => $filter['company_id']]); + if (isset($params['rel_tags']) && $params['rel_tags']) { + $relTags = []; + foreach ($params['rel_tags'] as $tag) { + $relTags[] = [ + 'company_id' => $result['company_id'], + 'ad_place_id' => $result['id'], + 'tag_id' => $tag['tag_id'], + ]; + } + $this->relMemberTagsRepository->batchInsert($relTags); + } + if (isset($params['distributor_id']) && $params['distributor_id']) { + $relDistributors = []; + foreach ($params['distributor_id'] as $distributorId) { + $relDistributors[] = [ + 'company_id' => $result['company_id'], + 'ad_place_id' => $result['id'], + 'distributor_id' => $distributorId, + ]; + } + $this->relDistributorsRepository->batchInsert($relDistributors); + } + $conn->commit(); + return $result; + } catch (\Exception $e) { + $conn->rollBack(); + throw new ResourceException($e->getMessage()); + } + } + + public function deleteWithRelTags($filter) + { + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + try { + $this->relMemberTagsRepository->deleteBy(['ad_place_id' => $filter['id'], 'company_id' => $filter['company_id']]); + $this->relDistributorsRepository->deleteBy(['ad_place_id' => $filter['id'], 'company_id' => $filter['company_id']]); + $this->entityRepository->deleteBy($filter); + $conn->commit(); + return true; + } catch (\Exception $e) { + $conn->rollBack(); + throw new ResourceException($e->getMessage()); + } + } + + /** + * @param $method + * @param $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->entityRepository->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Services/PagesSideBarService.php b/src/ThemeBundle/Services/PagesSideBarService.php new file mode 100644 index 0000000..473ef0a --- /dev/null +++ b/src/ThemeBundle/Services/PagesSideBarService.php @@ -0,0 +1,26 @@ +entityRepository = app('registry')->getManager('default')->getRepository(PagesSideBar::class); + } + + /** + * @param $method + * @param $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + return $this->entityRepository->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/ThemeBundle/Services/PagesTemplateServices.php b/src/ThemeBundle/Services/PagesTemplateServices.php index ba4a094..3547461 100644 --- a/src/ThemeBundle/Services/PagesTemplateServices.php +++ b/src/ThemeBundle/Services/PagesTemplateServices.php @@ -20,7 +20,10 @@ namespace ThemeBundle\Services; use CompanysBundle\Services\CommonLangModService; use Dingo\Api\Exception\ResourceException; use DistributionBundle\Entities\Distributor; +use DistributionBundle\Services\DistributorService; use DistributionBundle\Services\DistributorTagsService; +use GoodsBundle\Services\ItemsGroupRelItemService; +use GoodsBundle\Services\ItemsGroupService; use GoodsBundle\Services\ItemsService; use GoodsBundle\Services\ItemsTagsService; use GoodsBundle\Services\ItemTaxRateService; @@ -31,6 +34,7 @@ use ThemeBundle\Entities\PagesTemplateSet; use WechatBundle\Entities\WeappSetting; use EmployeePurchaseBundle\Services\ActivityItemsService; use EmployeePurchaseBundle\Services\ActivitiesService; +use MembersBundle\Services\MemberTagsService; class PagesTemplateServices { @@ -108,6 +112,7 @@ class PagesTemplateServices $template_params = [ 'template_title' => $params['template_title'], 'template_pic' => $params['template_pic'], + 'regionauth_id' => $params['regionauth_id'], ]; $this->pagesTemplateRepository->updateOneBy($template_filter, $template_params); } @@ -328,6 +333,11 @@ class PagesTemplateServices } $result = $this->pagesTemplateRepository->delete($filter); + + //删除关联的商品分组数据 + $group_key = 'widget-' . $params['pages_template_id']; + $itemsGroupService = new ItemsGroupService(); + $itemsGroupService->delGroupData($group_key); return $result; } @@ -341,6 +351,12 @@ class PagesTemplateServices 'company_id' => $params['company_id'], 'distributor_id' => $params['distributor_id'] ]; + if (isset($params['regionauth_id'])) { + $filter['regionauth_id'] = $params['regionauth_id']; + } + if (isset($params['weapp_pages'])) { + $filter['weapp_pages'] = $params['weapp_pages']; + } $page_size = $params['page_size']; $page = $params['page_no']; @@ -373,6 +389,7 @@ class PagesTemplateServices try { $creatr_params = [ 'company_id' => $result['company_id'], + 'regionauth_id' => $result['regionauth_id'], 'distributor_id' => $result['distributor_id'], 'template_name' => $result['template_name'], 'template_title' => $result['template_title'] . '-' . '复制', @@ -425,6 +442,7 @@ class PagesTemplateServices public function modifyStatus($params) { $company_id = $params['company_id']; + // $regionauth_id = $params['regionauth_id']; $pages_template_id = $params['pages_template_id']; $status = $params['status'];//模板启用状态 1启用 2未启用 $timer_status = $params['timer_status'];//定时启用状态 1启用 2未启用 @@ -432,6 +450,7 @@ class PagesTemplateServices $filter = [ 'company_id' => $company_id, + // 'regionauth_id' => $regionauth_id, 'pages_template_id' => $pages_template_id ]; $info = $this->pagesTemplateRepository->getInfo($filter); @@ -444,12 +463,14 @@ class PagesTemplateServices if ($status == 2) { $filter_count = [ 'company_id' => $company_id, + 'regionauth_id' => $info['regionauth_id'], 'distributor_id' => $distributor_id, + 'weapp_pages' => $info['weapp_pages'], 'status' => 1, ]; $count = $this->pagesTemplateRepository->count($filter_count); - if ($count <= 1) { + if ($count <= 1 && $distributor_id == 0) { throw new ResourceException("至少开启一套模版"); } } @@ -463,7 +484,9 @@ class PagesTemplateServices $filter_count = [ 'company_id' => $company_id, + 'regionauth_id' => $info['regionauth_id'], 'distributor_id' => $distributor_id, + 'weapp_pages' => $info['weapp_pages'], 'timer_status' => 1 ]; $count = $this->pagesTemplateRepository->count($filter_count); @@ -479,7 +502,9 @@ class PagesTemplateServices //模板状态为启用中的修改未 未开启状态 $_filter = [ 'company_id' => $company_id, + 'regionauth_id' => $info['regionauth_id'], 'distributor_id' => $distributor_id, + 'weapp_pages' => $info['weapp_pages'], 'status' => 1, ]; @@ -530,14 +555,15 @@ class PagesTemplateServices $template_title = $info['template_title']; $template_pic = $info['template_pic']; - $weapp_pages = $info['weapp_pages']; + $weapp_pages = 'distributor_index';//$info['weapp_pages']; $element_edit_status = $info['element_edit_status']; $pages_template_id = $info['pages_template_id']; $template_name = $info['template_name']; //获取模板设置信息 $_filter = [ - 'company_id' => $company_id + 'company_id' => $company_id, + 'regionauth_id' => $info['regionauth_id'], ]; $pages_template_set_info = $this->pagesTemplateSetRepository->getInfo($_filter); if (!empty($pages_template_set_info)) { @@ -616,7 +642,9 @@ class PagesTemplateServices //模板状态为启用中的修改未 未开启状态 $_filter = [ 'company_id' => $company_id, + 'regionauth_id' => $val['regionauth_id'], 'distributor_id' => $distributor_id, + 'weapp_pages' => $val['weapp_pages'], 'status' => 1, ]; @@ -633,7 +661,7 @@ class PagesTemplateServices $params = [ 'status' => 1, 'timer_status' => 2, - 'timer_time' => '', + // 'timer_time' => '', 'template_status_modify_time' => time() ]; $this->pagesTemplateRepository->updateOneBy($filter, $params); @@ -687,6 +715,7 @@ class PagesTemplateServices $company_id = $params['company_id']; $user_id = $params['user_id']; $distributor_id = $params['distributor_id']; + $regionauth_id = $params['regionauth_id']; $weapp_pages = $params['weapp_pages']; $template_name = $params['template_name']; $version = $params['version']; @@ -711,6 +740,7 @@ class PagesTemplateServices if ($pages_template_set_info['index_type'] == 1) { $filter = [ 'company_id' => $params['company_id'], + 'regionauth_id' => $regionauth_id, 'distributor_id' => 0, 'status' => 1, 'weapp_pages' => $weapp_pages @@ -730,11 +760,12 @@ class PagesTemplateServices if ($pages_template_id) { throw new ResourceException('模版ID错误'); } else { - if ($filter['distributor_id'] == 0) { - throw new ResourceException('总部未设置启用模板'); - } else { - throw new ResourceException('当前门店未设置启用模板'); - } + return $data; + // if ($filter['distributor_id'] == 0) { + // throw new ResourceException('总部未设置启用模板'); + // } else { + // throw new ResourceException('当前门店未设置启用模板'); + // } } } @@ -760,6 +791,10 @@ class PagesTemplateServices ]; $list = $this->templateContentByPage($params); + + // 按会员标签过滤组件 + $list = $this->filterTemplateContentByMemberTags($company_id, $user_id, $list); + // 处理模板参数 $this->templateHandler((int)$company_id, $list); $data['list'] = $list; @@ -797,9 +832,19 @@ class PagesTemplateServices ]; $result = $this->pagesTemplateRepository->getInfo($filter); if (empty($result)) { - $data['config'] = ''; - $data['list'] = ''; - return $data; + $filter = [ + 'company_id' => $params['company_id'], + 'regionauth_id' => $params['regionauth_id'], + 'distributor_id' => 0, + 'status' => 1, + 'weapp_pages' => $weapp_pages + ]; + $result = $this->pagesTemplateRepository->getInfo($filter); + if (empty($result)) { + $data['config'] = ''; + $data['list'] = ''; + return $data; + } } // 模版关联的导航设置 @@ -818,6 +863,10 @@ class PagesTemplateServices ]; $list = $this->templateContent($params); + + // 按会员标签过滤组件 + $list = $this->filterTemplateContentByMemberTags($company_id, $user_id, $list); + $data['list'] = $list; $config = []; foreach ($list as $row) { @@ -870,7 +919,7 @@ class PagesTemplateServices $params['config']['lastSeconds'] = $seckilldata['activity']['last_seconds'] ?? null; } - $seckilldata = $itemsService->getItemsListMemberPrice($seckilldata, $userId, $companyId); + $seckilldata['list'] = $itemsService->getItemsListMemberPrice($seckilldata['list'], $userId, $companyId); return (array)array_column($seckilldata['list'], null, 'item_id'); } @@ -907,9 +956,9 @@ class PagesTemplateServices $activityItemsService = new ActivityItemsService(); $result = $activityItemsService->getItemsListActityPrice($result, $params['e_activity_id'], $companyId); } - $result = $itemsService->getItemsListMemberPrice($result, $userId, $companyId); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], $userId, $companyId); //营销标签 - $result = $itemsService->getItemsListActityTag($result, $companyId); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $companyId); foreach ($result['list'] as $key => $value) { // 判断是否跨境,如果是,获取税费税率 if ($value['type'] == '1') { @@ -1309,6 +1358,94 @@ class PagesTemplateServices } $params['list'] = array_values($params['list']); break; + + case 'contentpart': + if (empty($params["data"]['data']) or !is_array($params["data"]['data'])) { + break; + } + $distributor_ids = []; + $distributorService = new DistributorService(); + //解析挂件里最新的店铺信息 + foreach ($params["data"]['data'] as $nav_k => $nav_v) { + if (empty($nav_v['children']) or !is_array($nav_v['children'])) { + continue; + } + foreach ($nav_v['children'] as $child_k => $child_v) { + if (empty($child_v['name']) or $child_v['name'] != 'shop' + or empty($child_v['data']) or !is_array($child_v['data'])) { + continue; + } + $distributor_ids = array_merge($distributor_ids, array_column($child_v['data'], 'distributor_id')); + } + } + $distributor_ids = array_filter(array_unique($distributor_ids)); + if (!$distributor_ids) { + break; + } + $distributor_list = $distributorService->entityRepository->getLists(['distributor_id' => $distributor_ids], 'distributor_id, name, logo, first_letter, tag_name, tag_start_time, tag_end_time'); + if (!$distributor_list) { + break; + } + $distributor_map = array_column($distributor_list, null, 'distributor_id'); + + foreach ($params["data"]['data'] as $nav_k => $nav_v) { + if (empty($nav_v['children']) or !is_array($nav_v['children'])) { + continue; + } + foreach ($nav_v['children'] as $child_k => $child_v) { + if (empty($child_v['name']) or $child_v['name'] != 'shop' + or empty($child_v['data']) or !is_array($child_v['data'])) { + continue; + } + foreach ($child_v['data'] as $child_data_k => $child_data_v) { + $distributor_info = $distributor_map[$child_data_v['distributor_id']] ?? []; + if (!$distributor_info) { + continue; + } + //店铺标签不在有效期内 + if (intval($distributor_info['tag_start_time']) > time() or intval($distributor_info['tag_end_time']) < time()) { + $distributor_info['tag_name'] = ''; + } + $child_data_v = array_merge($child_data_v, $distributor_info); + $child_v['data'][$child_data_k] = $child_data_v; + } + $nav_v['children'][$child_k] = $child_v; + } + $params["data"]['data'][$nav_k] = $nav_v; + } + break; + + case 'shop': + if (empty($params["data"]) or !is_array($params["data"])) { + break; + } + $distributor_ids = array_column($params['data'], 'distributor_id'); + $distributorService = new DistributorService(); + //解析挂件里最新的店铺信息 + $distributor_ids = array_filter(array_unique($distributor_ids)); + if (!$distributor_ids) { + break; + } + $distributor_list = $distributorService->entityRepository->getLists(['distributor_id' => $distributor_ids], 'distributor_id, name, logo, first_letter, tag_name, tag_start_time, tag_end_time'); + if (!$distributor_list) { + break; + } + $distributor_map = array_column($distributor_list, null, 'distributor_id'); + + foreach ($params['data'] as $tmp_k => $tmp_v) { + $distributor_info = $distributor_map[$tmp_v['distributor_id']] ?? []; + if (!$distributor_info) { + continue; + } + //店铺标签不在有效期内 + if (intval($distributor_info['tag_start_time']) > time() or intval($distributor_info['tag_end_time']) < time()) { + $distributor_info['tag_name'] = ''; + } + $tmp_v = array_merge($tmp_v, $distributor_info); + $params['data'][$tmp_k] = $tmp_v; + } + break; + case "store": if (isset($params["data"]) && is_array($params["data"])) { $distributor_map = []; @@ -1375,6 +1512,148 @@ class PagesTemplateServices return $list; } + public function getWidgetItems($params) + { + if ($params['data_type'] != 'sales') { + if (!isset($params['data_value']) || !$params['data_value']) { + return [ + 'data' => [], + 'filter' => [], + 'goodsSort' => null, + ]; + } + } + + $filter = [ + 'company_id' => $params['company_id'], + 'regionauth_id' => $params['regionauth_id'] ?? 0, + 'approve_status' => ['onsale', 'only_show'], + 'audit_status' => 'approved', + 'type' => 0, + 'item_type' => 'normal', + 'is_gift' => 0, + // 'store|gt' => 0, + 'valid_distributor' => 1, //过滤有效的店铺 + 'is_default' => 1, + ]; + + if (isset($params['distributor_id']) && $params['distributor_id']) { + $filter['distributor_id'] = $params['distributor_id']; + } + + if (isset($params['sort_gte'])) { + $filter['sort|gte'] = intval($params['sort_gte']); + } + + $orderBy = [ + 'sort' => 'desc', + 'sales' => 'desc', + ]; + + $newFilter = []; + $goodsSort = null; + switch ($params['data_type']) { + case 'main_category'://管理分类 + if (!is_array($params['data_value'])) { + $params['data_value'] = explode(',', $params['data_value']); + } + $filter['item_category'] = array_pop($params['data_value']); + $newFilter['main_category'] = $filter['item_category']; + break; + case 'category'://销售分类 + if (!is_array($params['data_value'])) { + $params['data_value'] = explode(',', $params['data_value']); + } + $filter['category_id'] = array_pop($params['data_value']); + $newFilter['category_id'] = $filter['category_id']; + break; + case 'seckill'://限时特惠 + $filter['seckill_id'] = $params['data_value']; + $newFilter['seckill_id'] = $params['data_value']; + //判断秒杀活动是否在有效期内 + $promotionSeckillActivityService = new PromotionSeckillActivityService(); + $seckillInfo = $promotionSeckillActivityService->getSeckillInfo(['company_id' => $filter['company_id'], 'seckill_id' => $filter['seckill_id']], false); + if (empty($seckillInfo) or $seckillInfo['activity_end_time'] < time()) { + return [ + 'data' => [], + 'filter' => [], + 'goodsSort' => null, + ]; + } + break; + case 'group'://拼团 + $filter['group_id'] = $params['data_value']; + $newFilter['group_id'] = $params['data_value']; + break; + case 'items_group'://商品分组 + $itemsGroupRelItemService = new ItemsGroupRelItemService(); + $rs = $itemsGroupRelItemService->repository->getLists(['group_id' => $params['data_value']], 'goods_id'); + if ($rs) { + $filter['goods_id'] = array_column($rs, 'goods_id'); + $newFilter['goods_id'] = array_column($rs, 'goods_id'); + } else { + $filter['goods_id'] = -1; + $newFilter['goods_id'] = -1; + } + break; + case 'sales'://按销量 + $orderBy = ['sales' => 'desc']; + $goodsSort = 1; + break; + case 'items'://指定商品 + $filter['goods_id'] = $params['data_value']; + $newFilter['goods_id'] = $params['data_value']; + break; + case 'distributor'://指定店铺 + $filter['distributor_id'] = $params['data_value']; + $newFilter['distributor_id'] = $params['data_value']; + break; + case 'price'://按价格 + if (!is_array($params['data_value'])) { + $params['data_value'] = json_decode($params['data_value'], true); + } + if (isset($params['data_value'][0])) { + $filter['price|gte'] = intval($params['data_value'][0] * 100); + $newFilter['start_price'] = intval($params['data_value'][0] * 100); + } + if (isset($params['data_value'][1])) { + $filter['price|lte'] = intval($params['data_value'][1] * 100); + $newFilter['end_price'] = intval($params['data_value'][1] * 100); + } + break; + default: + return [ + 'data' => [], + 'filter' => [], + 'goodsSort' => null, + ]; + } + $pageSize = $params['num'] ?? 10; + $page = $params['page'] ?? 1; + if (!empty($params['pageSize'])) { + $pageSize = intval($params['pageSize']); + } + + $itemsService = new ItemsService(); + $result = $itemsService->getItemListData($filter, $page, $pageSize, $orderBy, false); + + if ($result['list'] && $params['data_type'] == 'seckill') { + $promotionSeckillActivityService = new PromotionSeckillActivityService(); + $seckillInfo = $promotionSeckillActivityService->getSeckillInfo(['company_id' => $filter['company_id'], 'seckill_id' => $filter['seckill_id']], false); + + foreach ($result['list'] as $key => $row) { + $result['list'][$key]['activity_start_time'] = $seckillInfo['activity_start_time']; + $result['list'][$key]['activity_end_time'] = $seckillInfo['activity_end_time']; + } + } + + return [ + 'data' => $result['list'], + 'filter' => $newFilter, + 'goodsSort' => $goodsSort, + ]; + } + /** * @param $distributor_id 店铺id * @param $is_enforce_sync 店铺首页强制同步 1是 2否 @@ -1463,4 +1742,127 @@ class PagesTemplateServices return true; } + + public function filterTemplateContentByMemberTags($companyId, $userId, $list) { + $tagRelWidgetIds = []; + foreach ($list as $key => $widget) { + if (!empty($widget['params']['meber_tags'])) { + if ($userId > 0) { + foreach ($widget['params']['meber_tags'] as $relTag) { + if (!isset($tagRelWidgetIds[$relTag['tag_id']])) { + $tagRelWidgetIds[$relTag['tag_id']] = [$key]; + } else { + if (!in_array($key, $tagRelWidgetIds[$relTag['tag_id']])) { + $tagRelWidgetIds[$relTag['tag_id']][] = $key; + } + } + } + } else { + unset($list[$key]); + } + } + + if ($widget['name'] == 'contentpart') { + if (!empty($widget['params']['data']['data'])) { + foreach ($widget['params']['data']['data'] as $pkey => $part) { + if (!empty($part['meber_tags'])) { + if ($userId > 0) { + foreach ($part['meber_tags'] as $relTag) { + if (!isset($tagRelWidgetIds[$relTag['tag_id']])) { + $tagRelWidgetIds[$relTag['tag_id']] = [$key.'_'.$pkey]; + } else { + if (!in_array($key.'_'.$pkey, $tagRelWidgetIds[$relTag['tag_id']])) { + $tagRelWidgetIds[$relTag['tag_id']][] = $key.'_'.$pkey; + } + } + } + } else { + unset($list[$key]['params']['data']['data'][$pkey]); + } + } + + if (!empty($part['children'])) { + foreach ($part['children'] as $ckey => $child) { + if (!empty($child['meber_tags'])) { + if ($userId > 0) { + foreach ($child['meber_tags'] as $relTag) { + if (!isset($tagRelWidgetIds[$relTag['tag_id']])) { + $tagRelWidgetIds[$relTag['tag_id']] = [$key.'_'.$pkey.'_'.$ckey]; + } else { + if (!in_array($key.'_'.$pkey.'_'.$ckey, $tagRelWidgetIds[$relTag['tag_id']])) { + $tagRelWidgetIds[$relTag['tag_id']][] = $key.'_'.$pkey.'_'.$ckey; + } + } + } + } else { + unset($list[$key]['params']['data']['data'][$pkey]['children'][$ckey]); + } + } + } + } + } + } + } + } + + if ($tagRelWidgetIds) { + $checkParams = [ + 'company_id' => $companyId, + 'user_id' => $userId, + 'tag_id' => array_keys($tagRelWidgetIds), + ]; + $memberTagsService = new MemberTagsService(); + $bindTags = $memberTagsService->checkAndProcessTag($checkParams); + + $filterWidgetIds = []; + foreach ($bindTags as $tag) { + if ($tag['related'] && isset($tagRelWidgetIds[$tag['tag_id']])) { + $filterWidgetIds = array_merge($filterWidgetIds, $tagRelWidgetIds[$tag['tag_id']]); + } + } + + foreach ($list as $key => $widget) { + if (!empty($widget['params']['meber_tags']) && !in_array($key, $filterWidgetIds)) { + unset($list[$key]); + continue; + } + + if ($widget['name'] == 'contentpart') { + if (!empty($widget['params']['data']['data'])) { + foreach ($widget['params']['data']['data'] as $pkey => $part) { + if (!empty($part['meber_tags']) && !in_array($key.'_'.$pkey, $filterWidgetIds)) { + unset($list[$key]['params']['data']['data'][$pkey]); + continue; + } + + if (!empty($part['children'])) { + foreach ($part['children'] as $ckey => $child) { + if (!empty($child['meber_tags']) && !in_array($key.'_'.$pkey.'_'.$ckey, $filterWidgetIds)) { + unset($list[$key]['params']['data']['data'][$pkey]['children'][$ckey]); + } + } + } + } + } + } + } + } + + foreach ($list as $key => $widget) { + if ($widget['name'] == 'contentpart') { + if (!empty($widget['params']['data']['data'])) { + foreach ($widget['params']['data']['data'] as $pkey => $part) { + if (!empty($part['children'])) { + $widget['params']['data']['data'][$pkey]['children'] = array_values($part['children']); + } + } + + $list[$key]['params']['data']['data'] = array_values($widget['params']['data']['data']); + } + } + } + $list = array_values($list); + + return $list; + } } diff --git a/src/ThemeBundle/Services/PagesTemplateSetServices.php b/src/ThemeBundle/Services/PagesTemplateSetServices.php index 7c2613b..93fe7ac 100644 --- a/src/ThemeBundle/Services/PagesTemplateSetServices.php +++ b/src/ThemeBundle/Services/PagesTemplateSetServices.php @@ -35,11 +35,11 @@ class PagesTemplateSetServices public function saveData($params) { //判断数据是否存着 - $info = $this->pagesTemplateSetRepository->getInfo(['company_id' => $params['company_id'], 'pages_template_id' => ($params['pages_template_id'] ?? 0)]); + $info = $this->pagesTemplateSetRepository->getInfo(['company_id' => $params['company_id'], 'regionauth_id' => ($params['regionauth_id'] ?? 0), 'pages_template_id' => ($params['pages_template_id'] ?? 0)]); if (empty($info)) { $result = $this->pagesTemplateSetRepository->create($params); } else { - $result = $this->pagesTemplateSetRepository->updateOneBy(['company_id' => $params['company_id'], 'pages_template_id' => ($params['pages_template_id'] ?? 0)], $params); + $result = $this->pagesTemplateSetRepository->updateOneBy(['company_id' => $params['company_id'], 'regionauth_id' => ($params['regionauth_id'] ?? 0), 'pages_template_id' => ($params['pages_template_id'] ?? 0)], $params); } return $result; @@ -51,7 +51,7 @@ class PagesTemplateSetServices public function getInfo($params) { //判断数据是否存着 - $info = $this->pagesTemplateSetRepository->getInfo(['company_id' => $params['company_id'], 'pages_template_id' => ($params['pages_template_id'] ?? 0)]); + $info = $this->pagesTemplateSetRepository->getInfo(['company_id' => $params['company_id'], 'regionauth_id' => ($params['regionauth_id'] ?? 0), 'pages_template_id' => ($params['pages_template_id'] ?? 0)]); return $info; } diff --git a/src/ThemeBundle/Services/ThemePcTemplateContentServices.php b/src/ThemeBundle/Services/ThemePcTemplateContentServices.php index 4633522..b83799c 100644 --- a/src/ThemeBundle/Services/ThemePcTemplateContentServices.php +++ b/src/ThemeBundle/Services/ThemePcTemplateContentServices.php @@ -254,9 +254,9 @@ class ThemePcTemplateContentServices $itemsService = new ItemsService(); $list = $itemsService->getItemsList($itemfilter); - $list = $itemsService->getItemsListMemberPrice($list, $userId, $companyId); + $list['list'] = $itemsService->getItemsListMemberPrice($list['list'], $userId, $companyId); //营销标签-PC端暂时没有团购、秒杀等活动 - $list = $itemsService->getItemsListActityTag($list, $companyId); + $list['list'] = $itemsService->getItemsListActityTag($list['list'], $companyId); //计算税费、税率-PC端暂时没有跨境商品 /*$ItemTaxRateService = new ItemTaxRateService($companyId); foreach ($list['list'] as $key => $value) { diff --git a/src/WechatBundle/Entities/WeappCustomizePage.php b/src/WechatBundle/Entities/WeappCustomizePage.php index fad9a3d..2c79b81 100644 --- a/src/WechatBundle/Entities/WeappCustomizePage.php +++ b/src/WechatBundle/Entities/WeappCustomizePage.php @@ -50,6 +50,13 @@ class WeappCustomizePage */ private $company_id; + /** + * @var string + * + * @ORM\Column(name="regionauth_id", type="bigint", options={"comment":"区域id", "default":0}) + */ + private $regionauth_id = 0; + /** * @var string * @@ -95,9 +102,10 @@ class WeappCustomizePage /** * @var string * - * @ORM\Column(name="page_type", type="string", options={"default":"normal", "comment":"页面类型 salesperson:导购首页"}) + * @ORM\Column(name="page_type", type="string", options={"default":"normal", "comment":"页面类型 normal:普通页面 salesperson:导购首页 category:分类页 my:我的"}) */ private $page_type = 'normal'; + /** * Get id * @@ -156,6 +164,30 @@ class WeappCustomizePage return $this->company_id; } + /** + * Set regionauthId + * + * @param integer $regionauthId + * + * @return WeappCustomizePage + */ + public function setRegionauthId($regionauthId) + { + $this->regionauth_id = $regionauthId; + + return $this; + } + + /** + * Get regionauthId + * + * @return integer + */ + public function getRegionauthId() + { + return $this->regionauth_id; + } + /** * Set pageName * diff --git a/src/WechatBundle/Http/Api/V1/Action/CustomizePage.php b/src/WechatBundle/Http/Api/V1/Action/CustomizePage.php index 9e8f6f0..f0b5ff9 100644 --- a/src/WechatBundle/Http/Api/V1/Action/CustomizePage.php +++ b/src/WechatBundle/Http/Api/V1/Action/CustomizePage.php @@ -22,6 +22,8 @@ use Dingo\Api\Exception\ResourceException; use App\Http\Controllers\Controller as Controller; use WechatBundle\Services\Wxapp\CustomizePageService; use WechatBundle\Entities\WeappSetting; +use GoodsBundle\Services\ItemsCategoryService; +use CompanysBundle\Services\RegionauthService; class CustomizePage extends Controller { @@ -68,12 +70,14 @@ class CustomizePage extends Controller public function createCustomizePage(Request $request) { // Powered by ShopEx EcShopX - $params = $request->all('template_name', 'page_name', 'page_description', 'page_share_title', 'page_share_desc', 'page_share_imageUrl', 'is_open', 'page_type'); + $params = $request->all('template_name', 'page_name', 'page_description', 'page_share_title', 'page_share_desc', 'page_share_imageUrl', 'is_open', 'page_type', 'regionauth_id'); + $params['page_type'] = $params['page_type'] ?: 'normal'; $rules = [ 'template_name' => ['required', '模版名称不能为空'], 'page_name' => ['required', '自定义页面名称不能为空'], 'page_description' => ['required', '页面描述不能为空'], + 'page_type' => ['in:normal,salesperson,category,my,task_share', '页面类型不能为空'], ]; $error = validator_params($params, $rules); if ($error) { @@ -83,7 +87,7 @@ class CustomizePage extends Controller $companyId = app('auth')->user()->get('company_id'); $params['company_id'] = $companyId; // 只有当page_type为"my"且is_open为1时,才校验"只能开启一个"的规则 - if (($params['is_open'] == 1 || $params['is_open'] == true || $params['is_open'] == '1' || $params['is_open'] == 'true') + if (($params['is_open'] == 1 || $params['is_open'] == true || $params['is_open'] == '1' || $params['is_open'] == 'true') && isset($params['page_type']) && $params['page_type'] === 'my') { $cfilter['is_open'] = 1; $cfilter['company_id'] = $companyId; @@ -97,7 +101,7 @@ class CustomizePage extends Controller return $this->response->array(['status' => false, 'message' => "已经有启用的模版", 'status_code' => 422]); } } - + $result = $this->CustomizePageService->create($params); return $this->response->array($result); } @@ -138,7 +142,7 @@ class CustomizePage extends Controller */ public function updateCustomizePage(Request $request, $id) { - $params = $request->all('template_name', 'page_name', 'page_description', 'page_share_title', 'page_share_desc', 'page_share_imageUrl', 'is_open'); + $params = $request->all('template_name', 'page_name', 'page_description', 'page_share_title', 'page_share_desc', 'page_share_imageUrl', 'is_open', 'regionauth_id'); if (!$id) { throw new ResourceException("页面ID必传"); @@ -260,27 +264,45 @@ class CustomizePage extends Controller */ public function getCustomizepageList(Request $request) { - $params = $request->all('template_name', 'page', 'pageSize', 'page_type', 'is_open', 'page_name'); + $params = $request->all('template_name', 'page', 'pageSize', 'page_type', 'regionauth_id'); $page = $params['page'] ? intval($params['page']) : 1; $pageSize = $params['pageSize'] ? intval($params['pageSize']) : $this->limit; $companyId = app('auth')->user()->get('company_id'); $filter['company_id'] = $companyId; $filter['template_name'] = $params['template_name']; - $params['page_type'] = $params['page_type'] ? $params['page_type'] : 'normal'; - // is_open 参数:不传时查全部,传了再使用传入的值查询 - if (isset($params['is_open']) && $params['is_open'] !== '' && $params['is_open'] !== null) { - $filter['is_open'] = intval($params['is_open']); - } - if ($params['page_type']) { - $filter['page_type'] = $params['page_type']; - } - // page_name 参数:支持模糊查询 - if (isset($params['page_name']) && $params['page_name'] !== '' && $params['page_name'] !== null) { - $filter['page_name|contains'] = $params['page_name']; + $filter['page_type'] = $params['page_type'] ?: 'normal'; + if (isset($params['regionauth_id'])) { + $filter['regionauth_id'] = $params['regionauth_id']; } $orderBy = ['id' => 'DESC']; $result = $this->CustomizePageService->lists($filter, "*", $page, $pageSize, $orderBy); + + if ($result['list']) { + $regionauthService = new RegionauthService(); + $regionauthList = $regionauthService->getLists(['company_id' => $filter['company_id'], 'regionauth_id' => array_column($result['list'], 'regionauth_id')], 'regionauth_id,regionauth_name'); + $regionauthNameMap = array_column($regionauthList, 'regionauth_name', 'regionauth_id'); + + if ($filter['page_type'] == 'category') { + $pageIds = array_column($result['list'], 'id'); + $categoryService = new ItemsCategoryService(); + $categoryFilter['company_id'] = $companyId; + $categoryFilter['customize_page_id'] = $pageIds; + $categoryFilter['parent_id'] = 0; + $categoryFilter['category_level'] = 1; + $categoryFilter['is_main_category'] = false; + $categoryList = $categoryService->getItemsCategory($categoryFilter, false); + $categoryList = array_column($categoryList, null, 'customize_page_id'); + } + + foreach ($result['list'] as $key => $val) { + if ($filter['page_type'] == 'category' && isset($categoryList[$val['id']])) { + $result['list'][$key]['category_id'] = $categoryList[$val['id']]['category_id']; + $result['list'][$key]['category_name'] = $categoryList[$val['id']]['category_name']; + } + $result['list'][$key]['regionauth_name'] = $regionauthNameMap[$val['regionauth_id']] ?? ''; + } + } return $this->response->array($result); } @@ -340,10 +362,10 @@ class CustomizePage extends Controller $pageInfo = $this->CustomizePageService->getInfoById($id); if ($pageInfo) { $params = [ - 'template_name' => $pageInfo['template_name'], - 'company_id' => $filter['company_id'], - 'page_name' => 'custom_'.$id - ]; + 'template_name' => $pageInfo['template_name'], + 'company_id' => $filter['company_id'], + 'page_name' => 'custom_'.$id + ]; $this->weappSetting->deleteBy($params); $result = $this->CustomizePageService->deleteBy($filter); return $this->response->array(['status' => $result]); @@ -413,4 +435,91 @@ class CustomizePage extends Controller $result = ['id' => $info['id']]; return $this->response->array($result); } + + public function bindCategoryId($id, Request $request) + { + $companyId = app('auth')->user()->get('company_id'); + $regionauthId = $request->input('regionauth_id', 0); + $params = $request->all('category_id'); + $rules = [ + 'category_id' => ['required', '分类ID不能为空'], + ]; + $error = validator_params($params, $rules); + if ($error) { + throw new ResourceException($error); + } + + $pageFilter['id'] = $id; + $pageFilter['company_id'] = $companyId; + $pageFilter['regionauth_id'] = $regionauthId; + $pageInfo = $this->CustomizePageService->getInfo($pageFilter); + if (!$pageInfo) { + throw new ResourceException('页面不存在'); + } + + if ($pageInfo['page_type'] != 'category') { + throw new ResourceException('只能绑定分类页'); + } + + $categoryService = new ItemsCategoryService(); + $categoryFilter['company_id'] = $companyId; + $categoryFilter['regionauth_id'] = $regionauthId; + $categoryFilter['category_id'] = $params['category_id']; + $categoryInfo = $categoryService->getInfo($categoryFilter); + if (!$categoryInfo) { + throw new ResourceException('分类不存在'); + } + + if ($categoryInfo['category_level'] != 1 || $categoryInfo['is_main_category'] != false) { + throw new ResourceException('只能绑定一级销售分类'); + } + + $resetFilter['company_id'] = $companyId; + $resetFilter['regionauth_id'] = $regionauthId; + $resetFilter['customize_page_id'] = $id; + $resetCategory = $categoryService->getInfo($resetFilter); + if ($resetCategory) { + $categoryService->updateBy($resetFilter, ['customize_page_id' => 0]); + } + $categoryService->updateBy($categoryFilter, ['customize_page_id' => $id]); + + return $this->response->array(['status' => true]); + } + + public function copy($id, Request $request) + { + $companyId = app('auth')->user()->get('company_id'); + $filter['id'] = $id; + $filter['company_id'] = $companyId; + $info = $this->CustomizePageService->getInfo($filter); + if (!$info) { + throw new ResourceException('模版不存在'); + } + + $conn = app('registry')->getConnection('default'); + $conn->beginTransaction(); + try { + unset($info['id']); + $info['is_open'] = 0; + $result = $this->CustomizePageService->create($info); + + $weappSettingReposity = app('registry')->getManager('default')->getRepository(WeappSetting::class); + $data = $weappSettingReposity->getParamByTempName($companyId, $info['template_name'], 'custom_'.$id); + foreach ($data as $row) { + $companyId = $row->getCompanyId(); + $templateName = $row->getTemplateName(); + $pageName = 'custom_'.$result['id']; + $name = $row->getName(); + $params = unserialize($row->getParams()); + $version = $row->getVersion(); + $weappSettingReposity->setParams($companyId, $templateName, $pageName, $name, $params, $version); + } + + $conn->commit(); + return $this->response->array($result); + } catch (\Exception $e) { + $conn->rollback(); + throw new ResourceException($e->getMessage()); + } + } } diff --git a/src/WechatBundle/Http/Api/V1/Action/Wxa.php b/src/WechatBundle/Http/Api/V1/Action/Wxa.php index c4135aa..a071eed 100644 --- a/src/WechatBundle/Http/Api/V1/Action/Wxa.php +++ b/src/WechatBundle/Http/Api/V1/Action/Wxa.php @@ -17,8 +17,10 @@ namespace WechatBundle\Http\Api\V1\Action; +use CompanysBundle\Services\RegionauthService; use Illuminate\Http\Request; use App\Http\Controllers\Controller as Controller; +use PromotionsBundle\Services\ActivityCollectionService; use WechatBundle\Services\WeappService; use WechatBundle\Services\Wxapp\TemplateService; use Dingo\Api\Exception\StoreResourceFailedException; @@ -493,7 +495,13 @@ class Wxa extends Controller $weappService = new WeappService($wxaAppId, $companyId); $page = $request->input('page', 'pages/index'); + $regionauth_id = $request->input('regionauth_id', -1); + // if ($regionauth_id < 0) { + // throw new StoreResourceFailedException('区域ID不能为空'); + // } + $params = $request->input(); + unset($params['regionauth_id']); foreach ($params as $key => $val) { if (in_array($key, ['wxaAppId', 'page']) || !$val || $val === 'undefined') { unset($params[$key]); @@ -508,7 +516,25 @@ class Wxa extends Controller unset($params[$key]); continue; } + if ($key == 'collection_id') { + $activityCollectionServiceObj = new ActivityCollectionService(); + $rsCollection = $activityCollectionServiceObj->entityRepository->getInfoById($val); + if ($rsCollection && $rsCollection['regionauth_id']) { + $regionauth_id = $rsCollection['regionauth_id']; + } + continue; + } } + + if ($regionauth_id > 0) { + //获取区域编码 + $regionauthService = new RegionauthService(); + $regionauthInfo = $regionauthService->entityRepository->getInfoById($regionauth_id); + if ($regionauthInfo) { + $params['crmcode'] = $regionauthInfo['regionauth_code']; + } + } + $scene = $params ? http_build_query($params) : '1'; try { @@ -517,7 +543,7 @@ class Wxa extends Controller throw new \Exception($response['errmsg']); } } catch (\Exception $e) { - throw new StoreResourceFailedException('小程序还从未通过审核,无法生成小程序码,请查看体验二维码'); + throw new StoreResourceFailedException($e->getMessage()); } $base64 = 'data:image/jpg;base64,' . base64_encode($response); return $this->response->array(['base64Image' => $base64]); diff --git a/src/WechatBundle/Http/Controllers/PaymentNotify.php b/src/WechatBundle/Http/Controllers/PaymentNotify.php index d7f0eae..bb9840a 100644 --- a/src/WechatBundle/Http/Controllers/PaymentNotify.php +++ b/src/WechatBundle/Http/Controllers/PaymentNotify.php @@ -47,17 +47,18 @@ class PaymentNotify extends Controller // 获取tradeInfo $tradeService = new TradeService(); $tradeInfo = $tradeService->getInfo(['trade_id' => $data['out_trade_no']]); + $regionauthId = $tradeInfo['regionauth_id'] ?? 0; $distributorId = $tradeInfo['distributor_id'] ?? 0; - $services = new WechatPayService($distributorId); + $services = new WechatPayService($regionauthId, $distributorId); if ($companyId) { $payment = $services->getPayment($data['appid'], $data['appid'], $companyId); } else { if ($data['trade_type'] == 'APP') { $companyId = app('redis')->get('wechatAppPayment:companyId:' . $data['appid']); - $services = new WechatAppPayService($distributorId); + $services = new WechatAppPayService($regionauthId, $distributorId); } else { $companyId = app('redis')->get('wechatPayment:companyId:' . $data['appid']); - $services = new WechatH5PayService($distributorId); + $services = new WechatH5PayService($regionauthId, $distributorId); } if (!$companyId) { diff --git a/src/WechatBundle/Http/FrontApi/V1/Action/Wxapp.php b/src/WechatBundle/Http/FrontApi/V1/Action/Wxapp.php index 50a2701..ff5a041 100644 --- a/src/WechatBundle/Http/FrontApi/V1/Action/Wxapp.php +++ b/src/WechatBundle/Http/FrontApi/V1/Action/Wxapp.php @@ -40,6 +40,7 @@ use PopularizeBundle\Services\SettingService; use PromotionsBundle\Services\DistributorPromotionService; use ThirdPartyBundle\Services\DmCrm\DmCrmSettingService; use ThemeBundle\Services\PagesTemplateSetServices; +use ThemeBundle\Services\PagesTemplateServices; use WechatBundle\Services\OauthService; use WechatBundle\Services\OpenPlatform; use WechatBundle\Services\Wxapp\CustomizePageService; @@ -209,6 +210,7 @@ class Wxapp extends Controller $pageName = $request->input('page_name', 'index'); $version = $request->input('version', 'v1.0.0'); $distributorId = $request->input('distributor_id', 0); + $regionauthId = $request->input('regionauth_id', 0); $custom = false; if (strpos($pageName, 'custom_') !== false) { $customizePageService = new CustomizePageService(); @@ -217,11 +219,11 @@ class Wxapp extends Controller $custom_id = $customizePageService->getSalespersonCustomId($authInfo['company_id'], $templateName); } if ('my' == $custom_id) { - $custom_id = $customizePageService->getMyCustomId($authInfo['company_id']); - } + $custom_id = $customizePageService->getMyCustomId($authInfo['company_id'], $regionauthId); + } $custom_id = intval($custom_id); if (!$custom_id) { - throw new StoreResourceFailedException('小程序模板不存在'); + return $this->response->array(['list' => [], 'config' => []]); } $pageName = 'custom_'.$custom_id; $custom = true; @@ -503,40 +505,23 @@ class Wxapp extends Controller public function getUserOpentIdAndUnionid(Request $request) { if ($authInfo = $request->get('auth')) { - $companyId = $authInfo['company_id']; - - $WoaAppid = $this->openPlatform->getWoaAppidByCompanyId($companyId); - $app = $this->openPlatform->getAuthorizerApplication($WoaAppid); - - $user = $app->oauth->user(); - $open_id = $user->getId(); - if (!$open_id) { - return $this->response->array(['openid' => '', 'unionid' => '']); - } + $open_id = $authInfo['open_id']; + $unionid = $authInfo['unionid']; } else { - $inputData = $request->input(); - if (empty($inputData['appid'])) { - throw new StoreResourceFailedException('缺少参数,登录失败!'); + $params = $request->all('appid', 'code'); + if (!$params['appid']) { + throw new ResourceException('缺少appid'); } - $app = $this->openPlatform->getAuthorizerApplication($inputData['appid']); - $WoaAppid = $inputData['appid']; - $wxParams = [ - 'code' => $inputData['code'], - 'appid' => $inputData['appid'], - ]; - $res = $app->auth->session($inputData['code']); //调用微信获取sessionkey接口,返回session_key,openid,unionid - if (!isset($res['openid'])) { - return $this->response->array(['openid' => '', 'unionid' => '']); + if (!$params['code']) { + throw new ResourceException('缺少code'); } - $open_id = $res['openid']; + $app = $this->openPlatform->getAuthorizerApplication($params['appid']); + $res = $app->auth->session($params['code']); //调用微信获取sessionkey接口,返回session_key,openid,unionid + $open_id = $res['openid'] ?? ''; + $unionid = $res['unionid'] ?? ''; } $result['openid'] = $open_id; - $result['unionid'] = ''; - $wechatUserService = new WechatUserService(); - $wechatUserInfo = $wechatUserService->getSimpleUser(['open_id' => $open_id, 'authorizer_appid' => $WoaAppid]); - if ($wechatUserInfo['unionid'] ?? '') { - $result['unionid'] = $wechatUserInfo['unionid']; - } + $result['unionid'] = $unionid; return $this->response->array($result); } @@ -794,9 +779,14 @@ class Wxapp extends Controller ], ]; + $filter['company_id'] = $authInfo['company_id']; + if ($request->input('regionauth_id')) { + $filter['regionauth_id'] = $request->input('regionauth_id'); + } + // 获取小程序配置、小程序导航配置 $pages_template_set_services = new PagesTemplateSetServices(); - $pagestemplateSet = $pages_template_set_services->getInfo(['company_id' => $authInfo['company_id']]); + $pagestemplateSet = $pages_template_set_services->getInfo($filter); $return = array_merge($return, $pagestemplateSet); // 获取商城名称显示在小程序顶部 diff --git a/src/WechatBundle/Repositories/WeappCustomizePageRepository.php b/src/WechatBundle/Repositories/WeappCustomizePageRepository.php index 87af044..595a8c9 100644 --- a/src/WechatBundle/Repositories/WeappCustomizePageRepository.php +++ b/src/WechatBundle/Repositories/WeappCustomizePageRepository.php @@ -26,7 +26,7 @@ use Dingo\Api\Exception\ResourceException; class WeappCustomizePageRepository extends EntityRepository { - public $cols = ['id','template_name','company_id','page_name','page_description','page_share_title', + public $cols = ['id','template_name','company_id', 'regionauth_id', 'page_name','page_description','page_share_title', 'page_share_desc','page_share_imageUrl','is_open', 'page_type']; public $table = 'wechat_weapp_customize_page'; // 多语言对应的表名 public $module = 'wechat_weapp_customize_page'; // 多语言对应的模块 diff --git a/src/WechatBundle/Repositories/WeappSettingRepository.php b/src/WechatBundle/Repositories/WeappSettingRepository.php index 615c548..8ee20d6 100644 --- a/src/WechatBundle/Repositories/WeappSettingRepository.php +++ b/src/WechatBundle/Repositories/WeappSettingRepository.php @@ -105,7 +105,7 @@ class WeappSettingRepository extends EntityRepository * @param array $orderBy * @return array */ - public function getParamByTempName($companyId, $templateName, $pageName = null, $configName = null, $version = 'v1.0.0', $pages_template_id = 0, $id = 0, $orderBy = []) + public function getParamByTempName($companyId, $templateName, $pageName = null, $configName = null, $version = null, $pages_template_id = 0, $id = 0, $orderBy = []) { $filter = ['company_id' => $companyId, 'template_name' => $templateName]; diff --git a/src/WechatBundle/Repositories/WechatAuthRepository.php b/src/WechatBundle/Repositories/WechatAuthRepository.php index c88c540..4be3906 100644 --- a/src/WechatBundle/Repositories/WechatAuthRepository.php +++ b/src/WechatBundle/Repositories/WechatAuthRepository.php @@ -110,7 +110,7 @@ class WechatAuthRepository extends EntityRepository array_walk($value, function (&$colVal) use ($qb) { $colVal = $qb->expr()->literal($colVal); }); - $qb = $qb->andWhere($qb->expr()->$k($field, $value)); + $qb = $qb->andWhere($qb->expr()->$k($v, $value)); } else { $qb = $qb->andWhere($qb->expr()->$k($v, $qb->expr()->literal($value))); } diff --git a/src/WechatBundle/Services/Wxapp/CustomizePageService.php b/src/WechatBundle/Services/Wxapp/CustomizePageService.php index 0589056..3e849bb 100644 --- a/src/WechatBundle/Services/Wxapp/CustomizePageService.php +++ b/src/WechatBundle/Services/Wxapp/CustomizePageService.php @@ -53,14 +53,15 @@ class CustomizePageService return $info['id'] ?? 0; } - public function getMyCustomId($companyId, $regionauthId = '') + public function getMyCustomId($companyId, $regionauthId) { $filter = [ 'company_id' => $companyId, + 'regionauth_id' => $regionauthId > 0 ? [$regionauthId, 0] : 0,//小镇没有单独设置取平台的 'page_type' => 'my', 'is_open' => 1, ]; - $pageList = $this->lists($filter, 'id', 1, 1); + $pageList = $this->lists($filter, 'id', 1, 1, ['regionauth_id' => 'desc']); if ($pageList['list']) { return $pageList['list'][0]['id']; } diff --git a/src/WechatBundle/Services/Wxapp/TemplateService.php b/src/WechatBundle/Services/Wxapp/TemplateService.php index f58e418..9b51e62 100644 --- a/src/WechatBundle/Services/Wxapp/TemplateService.php +++ b/src/WechatBundle/Services/Wxapp/TemplateService.php @@ -316,9 +316,9 @@ class TemplateService $itemfilter['company_id'] = $companyId; $itemfilter['item_id'] = $itemIds; $result = $itemsService->getItemsList($itemfilter); - $result = $itemsService->getItemsListMemberPrice($result, $userId, $companyId); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], $userId, $companyId); //营销标签 - $result = $itemsService->getItemsListActityTag($result, $companyId); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $companyId); //获取品牌名和logo $result['list'] = $itemsService->getItemsListBrandData($result['list'], $companyId); $itemdatalist = array_column($result['list'], null, 'item_id'); @@ -361,9 +361,9 @@ class TemplateService $itemfilter['company_id'] = $companyId; $itemfilter['item_id'] = $itemIds; $result = $itemsService->getItemsList($itemfilter); - $result = $itemsService->getItemsListMemberPrice($result, $userId, $companyId); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], $userId, $companyId); //营销标签 - $result = $itemsService->getItemsListActityTag($result, $companyId); + $result['list'] = $itemsService->getItemsListActityTag($result['list'], $companyId); //获取品牌名和logo $result['list'] = $itemsService->getItemsListBrandData($result['list'], $companyId); $itemdatalist = array_column($result['list'], null, 'item_id'); diff --git a/src/WsugcBundle/Services/PostService.php b/src/WsugcBundle/Services/PostService.php index 48d4e22..7845943 100755 --- a/src/WsugcBundle/Services/PostService.php +++ b/src/WsugcBundle/Services/PostService.php @@ -206,7 +206,7 @@ class PostService // 如果是推广员不需要计算会员价 if ($result['list'] && ($v['user_id']??null)) { // 计算会员价 - $result = $itemsService->getItemsListMemberPrice($result, $v['user_id'], $v['company_id']??1); + $result['list'] = $itemsService->getItemsListMemberPrice($result['list'], $v['user_id'], $v['company_id']??1); } //$itemList = $itemService->getItemsList(); //,'item_id,goods_id,brief,default_item_id,item_name,itemName,itemBn,price,pics,store' diff --git a/storage/static/dealer_menu.json b/storage/static/dealer_menu.json index 1145fcf..8b650d7 100644 --- a/storage/static/dealer_menu.json +++ b/storage/static/dealer_menu.json @@ -1 +1 @@ -[{"shopmenu_id":"10493","company_id":0,"name":"\u4fe1\u606f\u7ba1\u7406","url":"\/dealer\/adapay_member","sort":1,"is_menu":true,"pid":"0","apis":"adapay.member.info\nadapay.dealer.list\nadapay.dealer.info\nadapay.dealer.disable\nadapay.dealer.rel\nwechat.authorizerInfo","icon":null,"is_show":true,"alias_name":"adapay_member","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10494","company_id":0,"name":"\u5f00\u6237\u7ba1\u7406","url":"\/dealer\/adapay_member\/entry","sort":1,"is_menu":true,"pid":"10493","apis":"adapay.corp_member.create\nadapay.corp_member.update\nadapay.corp_member.modify\nadapay.bank.list\nwechat.authorizerInfo","icon":null,"is_show":true,"alias_name":"entry","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u4fe1\u606f\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10495","company_id":0,"name":"\u5f00\u6237\u4fe1\u606f","url":"\/dealer\/adapay_member\/info","sort":1,"is_menu":true,"pid":"10493","apis":"wechat.authorizerInfo","icon":null,"is_show":true,"alias_name":"info","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u4fe1\u606f\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10496","company_id":0,"name":"\u5e97\u94fa","url":"\/dealer\/distributor","sort":2,"is_menu":true,"pid":"0","apis":"adapay.member.info\nadapay.dealer.list\nadapay.dealer.info\nadapay.dealer.disable\nadapay.dealer.rel\nadapay.dealer.distributorList\nadapay.member.auditState\nadapay.member.valid","icon":null,"is_show":true,"alias_name":"distributor","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10497","company_id":0,"name":"\u5e97\u94fa\u7ba1\u7406","url":"\/dealer\/distributor\/list","sort":1,"is_menu":true,"pid":"10496","apis":null,"icon":null,"is_show":true,"alias_name":"list","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u5e97\u94fa","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10498","company_id":0,"name":"\u4ea4\u6613\u7ba1\u7406","url":"\/dealer\/trades","sort":3,"is_menu":true,"pid":"0","apis":"adapay.tradeInfo.get\nadapay.trade.getList\nadapay.distributor.list\nadapay.member.info\nadapay.dealer.list\nadapay.dealer.info\nadapay.dealer.disable\nadapay.dealer.rel\nadapay.trades.list.export","icon":null,"is_show":true,"alias_name":"trades","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10499","company_id":0,"name":"\u5206\u8d26","url":"\/dealer\/trades\/adapay_trades","sort":1,"is_menu":true,"pid":"10498","apis":null,"icon":null,"is_show":true,"alias_name":"adapay_trades2","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u4ea4\u6613\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10500","company_id":0,"name":"\u63d0\u73b0","url":"\/dealer\/trades\/adapay_cash","sort":1,"is_menu":true,"pid":"10498","apis":null,"icon":null,"is_show":true,"alias_name":"adapay_cash2","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u4ea4\u6613\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10501","company_id":0,"name":"\u8bbe\u7f6e","url":"\/dealer\/setting","sort":4,"is_menu":true,"pid":"0","apis":"","icon":null,"is_show":true,"alias_name":"dealersetting","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10502","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/dealer\/setting\/baseexport","sort":1,"is_menu":true,"pid":"10501","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"dealer-baseexport","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10503","company_id":0,"name":"\u8d26\u53f7\u7ba1\u7406","url":"\/dealer\/setting\/account_management","sort":1,"is_menu":true,"pid":"10501","apis":"adapay.dealer_parent.get\nadapay.dealer.update\naccount.create\nadapay.dealer.del","icon":null,"is_show":true,"alias_name":"account_management","version":5,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file +[{"shopmenu_id":"738","company_id":0,"name":"\u4fe1\u606f\u7ba1\u7406","url":"\/dealer\/adapay_member","sort":1,"is_menu":true,"pid":"0","apis":"adapay.member.info\nadapay.dealer.list\nadapay.dealer.info\nadapay.dealer.disable\nadapay.dealer.rel\nwechat.authorizerInfo","icon":null,"is_show":true,"alias_name":"adapay_member","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"739","company_id":0,"name":"\u5f00\u6237\u7ba1\u7406","url":"\/dealer\/adapay_member\/entry","sort":1,"is_menu":true,"pid":"738","apis":"adapay.corp_member.create\nadapay.corp_member.update\nadapay.corp_member.modify\nadapay.bank.list\nwechat.authorizerInfo","icon":null,"is_show":true,"alias_name":"entry","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":2,"parent_name":"\u4fe1\u606f\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"740","company_id":0,"name":"\u5f00\u6237\u4fe1\u606f","url":"\/dealer\/adapay_member\/info","sort":1,"is_menu":true,"pid":"738","apis":"wechat.authorizerInfo","icon":null,"is_show":true,"alias_name":"info","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":2,"parent_name":"\u4fe1\u606f\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"741","company_id":0,"name":"\u5e97\u94fa","url":"\/dealer\/distributor","sort":2,"is_menu":true,"pid":"0","apis":"adapay.member.info\nadapay.dealer.list\nadapay.dealer.info\nadapay.dealer.disable\nadapay.dealer.rel\nadapay.dealer.distributorList\nadapay.member.auditState\nadapay.member.valid","icon":null,"is_show":true,"alias_name":"distributor","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"742","company_id":0,"name":"\u5e97\u94fa\u7ba1\u7406","url":"\/dealer\/distributor\/list","sort":1,"is_menu":true,"pid":"741","apis":null,"icon":null,"is_show":true,"alias_name":"list","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":2,"parent_name":"\u5e97\u94fa","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"743","company_id":0,"name":"\u4ea4\u6613\u7ba1\u7406","url":"\/dealer\/trades","sort":3,"is_menu":true,"pid":"0","apis":"adapay.tradeInfo.get\nadapay.trade.getList\nadapay.distributor.list\nadapay.member.info\nadapay.dealer.list\nadapay.dealer.info\nadapay.dealer.disable\nadapay.dealer.rel\nadapay.trades.list.export","icon":null,"is_show":true,"alias_name":"trades","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"744","company_id":0,"name":"\u5206\u8d26","url":"\/dealer\/trades\/adapay_trades","sort":1,"is_menu":true,"pid":"743","apis":null,"icon":null,"is_show":true,"alias_name":"adapay_trades2","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":2,"parent_name":"\u4ea4\u6613\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"745","company_id":0,"name":"\u63d0\u73b0","url":"\/dealer\/trades\/adapay_cash","sort":1,"is_menu":true,"pid":"743","apis":null,"icon":null,"is_show":true,"alias_name":"adapay_cash2","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":2,"parent_name":"\u4ea4\u6613\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"746","company_id":0,"name":"\u8bbe\u7f6e","url":"\/dealer\/setting","sort":4,"is_menu":true,"pid":"0","apis":"","icon":null,"is_show":true,"alias_name":"dealersetting","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"747","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/dealer\/setting\/baseexport","sort":1,"is_menu":true,"pid":"746","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"dealer-baseexport","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"748","company_id":0,"name":"\u8d26\u53f7\u7ba1\u7406","url":"\/dealer\/setting\/account_management","sort":1,"is_menu":true,"pid":"746","apis":"adapay.dealer_parent.get\nadapay.dealer.update\naccount.create\nadapay.dealer.del","icon":null,"is_show":true,"alias_name":"account_management","version":5,"disabled":false,"created":1770118481,"updated":1770118481,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file diff --git a/storage/static/it_menu.json b/storage/static/it_menu.json index ae774cc..0ea06ca 100644 --- a/storage/static/it_menu.json +++ b/storage/static/it_menu.json @@ -1 +1 @@ -[{"shopmenu_id":"10571","company_id":0,"name":"\u9996\u9875","url":"\/dashboard","sort":0,"is_menu":true,"pid":"0","apis":"","icon":"tachometer-alt","is_show":true,"alias_name":"index","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10753","company_id":0,"name":"\u4f9b\u5e94\u5546\u83dc\u5355","url":"\/suppliermenue","sort":1,"is_menu":true,"pid":"0","apis":null,"icon":null,"is_show":true,"alias_name":"suppliermenue","version":2,"disabled":false,"created":1720428607,"updated":1720428607,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10566","company_id":0,"name":"IT\u7aef\u83dc\u5355","url":"\/supermenu","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"th-list","is_show":true,"alias_name":"supermenu","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10567","company_id":0,"name":"\u5e73\u53f0\u83dc\u5355","url":"\/shopmenu","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"th-list","is_show":true,"alias_name":"shopmenu","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10568","company_id":0,"name":"\u56fe\u6807\u5217\u8868","url":"\/menuicon","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"grin","is_show":true,"alias_name":"menuicon","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10569","company_id":0,"name":"\u5c0f\u7a0b\u5e8f\u6a21\u677f","url":"\/wxapptemplate","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"weixin","is_show":true,"alias_name":"wxapptemplate","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10570","company_id":0,"name":"\u54c1\u724c\u5546\u57ce","url":"\/companys","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"university","is_show":true,"alias_name":"companys","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10572","company_id":0,"name":"\u64cd\u4f5c\u65e5\u5fd7","url":"\/companyogs","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"dizzy","is_show":true,"alias_name":"companyogs","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10573","company_id":0,"name":"\u5e97\u94fa\u83dc\u5355","url":"\/Distributormenu","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"th-list","is_show":true,"alias_name":"Distributormenu","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10574","company_id":0,"name":"\u7269\u6d41\u5217\u8868","url":"\/logistics","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"ambulance","is_show":true,"alias_name":"logistics","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10577","company_id":0,"name":"\u57fa\u7840\u7ba1\u7406","url":"\/base\/account","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"wrench","is_show":true,"alias_name":"base","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10578","company_id":0,"name":"\u8d26\u53f7\u7ba1\u7406","url":"\/base\/account\/accountmanagement","sort":1,"is_menu":true,"pid":"10577","apis":null,"icon":null,"is_show":true,"alias_name":"manager","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u57fa\u7840\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10579","company_id":0,"name":"\u89d2\u8272\u7ba1\u7406","url":"\/base\/account\/accountroles","sort":2,"is_menu":true,"pid":"10577","apis":null,"icon":null,"is_show":true,"alias_name":"roles","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u57fa\u7840\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10581","company_id":0,"name":"\u5c0f\u7a0b\u5e8f\u6a21\u7248\u5e93","url":"\/WxappOplatform","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"weixin","is_show":true,"alias_name":"wxappOplatform","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10582","company_id":0,"name":"\u8349\u7a3f\u7bb1","url":"\/WxappOplatform\/WxappOplatformDraft","sort":1,"is_menu":true,"pid":"10581","apis":null,"icon":"weixin","is_show":true,"alias_name":"WxappOplatformDraft","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5c0f\u7a0b\u5e8f\u6a21\u7248\u5e93","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10583","company_id":0,"name":"\u6a21\u677f\u5217\u8868","url":"\/WxappOplatform\/WxappOplatformTemplate","sort":1,"is_menu":true,"pid":"10581","apis":null,"icon":"weixin","is_show":true,"alias_name":"wxappOplatformTemplate","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5c0f\u7a0b\u5e8f\u6a21\u7248\u5e93","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10585","company_id":0,"name":"\u652f\u4ed8\u5b9d\u5c0f\u7a0b\u5e8f\u6a21\u677f","url":"\/alipaytemplate","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"alipay","is_show":true,"alias_name":"alipaytemplate","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10586","company_id":0,"name":"\u7ecf\u9500\u5546\u83dc\u5355","url":"\/dealermenu","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"th-list","is_show":true,"alias_name":"dealermenu","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10587","company_id":0,"name":"\u5546\u6237\u83dc\u5355","url":"\/merchantmenu","sort":1,"is_menu":true,"pid":"0","apis":null,"icon":"th-list","is_show":true,"alias_name":"merchantmenu","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10575","company_id":0,"name":"\u6570\u636e\u7edf\u8ba1","url":"\/goodsstatistics","sort":2,"is_menu":true,"pid":"0","apis":"","icon":"chart-bar","is_show":true,"alias_name":"goodsstatistics","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10576","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/baseexport","sort":3,"is_menu":true,"pid":"0","apis":"","icon":"chart-bar","is_show":true,"alias_name":"baseexport","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10584","company_id":0,"name":"\u589e\u503c\u670d\u52a1","url":"\/vaService","sort":5,"is_menu":true,"pid":"0","apis":"","icon":"yen-sign","is_show":true,"alias_name":"vaService","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10580","company_id":0,"name":"\u5168\u5c40\u8bbe\u7f6e","url":"\/globalconfig","sort":999,"is_menu":true,"pid":"0","apis":"","icon":"cog","is_show":true,"alias_name":"globalconfig","version":2,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file +[{"shopmenu_id":"247","company_id":0,"name":"\u9996\u9875","url":"\/dashboard","sort":0,"is_menu":true,"pid":"0","apis":"","icon":"tachometer-alt","is_show":true,"alias_name":"index","version":2,"disabled":false,"created":1770118363,"updated":1770118363,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"256","company_id":0,"name":"\u7269\u6d41\u5217\u8868","url":"\/logistics","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"ambulance","is_show":true,"alias_name":"logistics","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"257","company_id":0,"name":"\u57fa\u7840\u7ba1\u7406","url":"\/base\/account","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"wrench","is_show":true,"alias_name":"base","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"258","company_id":0,"name":"\u8d26\u53f7\u7ba1\u7406","url":"\/base\/account\/accountmanagement","sort":1,"is_menu":true,"pid":"257","apis":null,"icon":null,"is_show":true,"alias_name":"manager","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":2,"parent_name":"\u57fa\u7840\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"259","company_id":0,"name":"\u89d2\u8272\u7ba1\u7406","url":"\/base\/account\/accountroles","sort":2,"is_menu":true,"pid":"257","apis":null,"icon":null,"is_show":true,"alias_name":"roles","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":2,"parent_name":"\u57fa\u7840\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"260","company_id":0,"name":"\u5c0f\u7a0b\u5e8f\u6a21\u7248\u5e93","url":"\/WxappOplatform","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"weixin","is_show":true,"alias_name":"wxappOplatform","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"261","company_id":0,"name":"\u8349\u7a3f\u7bb1","url":"\/WxappOplatform\/WxappOplatformDraft","sort":1,"is_menu":true,"pid":"260","apis":null,"icon":"weixin","is_show":true,"alias_name":"WxappOplatformDraft","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":2,"parent_name":"\u5c0f\u7a0b\u5e8f\u6a21\u7248\u5e93","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"262","company_id":0,"name":"\u6a21\u677f\u5217\u8868","url":"\/WxappOplatform\/WxappOplatformTemplate","sort":1,"is_menu":true,"pid":"260","apis":null,"icon":"weixin","is_show":true,"alias_name":"wxappOplatformTemplate","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":2,"parent_name":"\u5c0f\u7a0b\u5e8f\u6a21\u7248\u5e93","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"263","company_id":0,"name":"\u652f\u4ed8\u5b9d\u5c0f\u7a0b\u5e8f\u6a21\u677f","url":"\/alipaytemplate","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"alipay","is_show":true,"alias_name":"alipaytemplate","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"264","company_id":0,"name":"\u7ecf\u9500\u5546\u83dc\u5355","url":"\/dealermenu","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"th-list","is_show":true,"alias_name":"dealermenu","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"265","company_id":0,"name":"\u5546\u6237\u83dc\u5355","url":"\/merchantmenu","sort":1,"is_menu":true,"pid":"0","apis":null,"icon":"th-list","is_show":true,"alias_name":"merchantmenu","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"248","company_id":0,"name":"\u4f9b\u5e94\u5546\u83dc\u5355","url":"\/suppliermenue","sort":1,"is_menu":true,"pid":"0","apis":null,"icon":null,"is_show":true,"alias_name":"suppliermenue","version":2,"disabled":false,"created":1770118363,"updated":1770118363,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"249","company_id":0,"name":"IT\u7aef\u83dc\u5355","url":"\/supermenu","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"th-list","is_show":true,"alias_name":"supermenu","version":2,"disabled":false,"created":1770118363,"updated":1770118363,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"250","company_id":0,"name":"\u5e73\u53f0\u83dc\u5355","url":"\/shopmenu","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"th-list","is_show":true,"alias_name":"shopmenu","version":2,"disabled":false,"created":1770118363,"updated":1770118363,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"251","company_id":0,"name":"\u56fe\u6807\u5217\u8868","url":"\/menuicon","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"grin","is_show":true,"alias_name":"menuicon","version":2,"disabled":false,"created":1770118363,"updated":1770118363,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"252","company_id":0,"name":"\u5c0f\u7a0b\u5e8f\u6a21\u677f","url":"\/wxapptemplate","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"weixin","is_show":true,"alias_name":"wxapptemplate","version":2,"disabled":false,"created":1770118363,"updated":1770118363,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"253","company_id":0,"name":"\u54c1\u724c\u5546\u57ce","url":"\/companys","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"university","is_show":true,"alias_name":"companys","version":2,"disabled":false,"created":1770118363,"updated":1770118363,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"254","company_id":0,"name":"\u64cd\u4f5c\u65e5\u5fd7","url":"\/companyogs","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"dizzy","is_show":true,"alias_name":"companyogs","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"255","company_id":0,"name":"\u5e97\u94fa\u83dc\u5355","url":"\/Distributormenu","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"th-list","is_show":true,"alias_name":"Distributormenu","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"266","company_id":0,"name":"\u6570\u636e\u7edf\u8ba1","url":"\/goodsstatistics","sort":2,"is_menu":true,"pid":"0","apis":"","icon":"chart-bar","is_show":true,"alias_name":"goodsstatistics","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"267","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/baseexport","sort":3,"is_menu":true,"pid":"0","apis":"","icon":"chart-bar","is_show":true,"alias_name":"baseexport","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"268","company_id":0,"name":"\u589e\u503c\u670d\u52a1","url":"\/vaService","sort":5,"is_menu":true,"pid":"0","apis":"","icon":"yen-sign","is_show":true,"alias_name":"vaService","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"269","company_id":0,"name":"\u5168\u5c40\u8bbe\u7f6e","url":"\/globalconfig","sort":999,"is_menu":true,"pid":"0","apis":"","icon":"cog","is_show":true,"alias_name":"globalconfig","version":2,"disabled":false,"created":1770118364,"updated":1770118364,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file diff --git a/storage/static/merchant_menu.json b/storage/static/merchant_menu.json index 85c39f0..0d75e05 100644 --- a/storage/static/merchant_menu.json +++ b/storage/static/merchant_menu.json @@ -1 +1 @@ -[{"shopmenu_id":"10536","company_id":0,"name":"\u6982\u51b5","url":"\/merchant","sort":1,"is_menu":true,"pid":"0","apis":"company.real.statistics\nwechat.authorizerInfo\nwechat.pre_auth_url","icon":"tachometer-alt","is_show":true,"alias_name":"merchant","version":6,"disabled":false,"created":1675936334,"updated":1722923526,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10513","company_id":0,"name":"\u4ea4\u6613","url":"\/merchant\/order","sort":2,"is_menu":true,"pid":"0","apis":null,"icon":"clipboard-list","is_show":true,"alias_name":"order","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10517","company_id":0,"name":"\u5b9e\u7269\u8ba2\u5355","url":"\/merchant\/order\/tradenormalorders","sort":1,"is_menu":true,"pid":"10513","apis":"order.list.get\ndistributor.list\nsource.list\ninvoice.list.export\norder.list.export\ncompany.logistics.list\norder.info.get\norder.delivery.lists\ntrade.logistics.list\nmember.info\norder.delivery.update\nespier.upload\nespier.subdistrict.list.get\npresale.pickupcode.setting.get\norder.deliverystaff.confirm\norder.deliverystaff.cancel\nall.setting.get","icon":null,"is_show":true,"alias_name":"tradenormalorders","version":6,"disabled":false,"created":1675936334,"updated":1746332736,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10518","company_id":0,"name":"\u552e\u540e\u5217\u8868","url":"\/merchant\/order\/aftersaleslist","sort":2,"is_menu":true,"pid":"10513","apis":"aftersales.list\naftersales.logexport\naftersales.remind.get\naftersales.info","icon":null,"is_show":true,"alias_name":"aftersaleslist","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10519","company_id":0,"name":"\u4ea4\u6613\u5355","url":"\/merchant\/order\/tradepayment","sort":3,"is_menu":true,"pid":"10513","apis":"order.trade.list\ntrades.list.export","icon":null,"is_show":true,"alias_name":"tradepayment","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10520","company_id":0,"name":"\u9000\u6b3e\u5355","url":"\/merchant\/order\/aftersalesrefundlist","sort":4,"is_menu":true,"pid":"10513","apis":"refund.list\nrefund.logexport\nrefund.info","icon":null,"is_show":true,"alias_name":"aftersalesrefundlist","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10521","company_id":0,"name":"\u9000\u6b3e\u5931\u8d25\u65e5\u5fd7","url":"\/merchant\/order\/Refunderrorlogs","sort":5,"is_menu":true,"pid":"10513","apis":"trade.refunderrorlogs.list","icon":null,"is_show":true,"alias_name":"Refunderrorlogs","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10514","company_id":0,"name":"\u5546\u5bb6","url":"\/merchant\/sellers","sort":3,"is_menu":true,"pid":"0","apis":null,"icon":"store-alt","is_show":true,"alias_name":"sellers","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10522","company_id":0,"name":"\u5546\u5bb6\u4fe1\u606f","url":"\/merchant\/sellers\/merchantinfo","sort":1,"is_menu":true,"pid":"10514","apis":"merchant.info.get\nmerchant.type.list\nespier.address.info\nmerchant.visibletype.list\nmerchant.basesetting.get\ngoods.category.lists\ngoods.attributes.list","icon":null,"is_show":true,"alias_name":"merchantinfo","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10523","company_id":0,"name":"\u5e97\u94fa\u5217\u8868","url":"\/merchant\/sellers\/marketingdistributor","sort":2,"is_menu":true,"pid":"10514","apis":"distributor.tag.list\nhfpay.ledgerconfig.index\ncompany.regionauth.list\ncompany.dada.info\ndistributor.create\ndistributor.tag.rel\ndistribution.distance.get\ndistribution.distance.save\nhfpay.enterapply.opensplit\ndistributor.edit\ndistributor.default.set\ndistributor.info\nwechat.material.list\nespier.image.list\npagestemplateset.getInfo\npagestemplate.lists\nrecommendlike.list\ncurrency.get.default\nshipping.templates.list\ngoods.sku.lists\npagestemplate.detail\ngoods.items.lists\npagestemplate.edit\npagestemplate.modifyStatus\npagestemplate.copy\npagestemplate.delete\npagestemplate.add\ndistributor.wxacode\ncard.list\ngoods.tag.list\narticle.list\nselfhelp.registrationActivity.easylist\nPromotions.seckill.list\nwechat.wxa.customizepage.list\npromotions.liverooms\nwxexternalconfig.list\nwxexternalconfigroutes.list\nespier.oss.uploadToken.get\nespier.image.save\ndistributor.aftersales.list\npickuplocation.list.get\nespier.image.cat.children\nespier.image.cat.edit\nespier.image.cat.del\nespier.image.move.cat\norders.setting.get","icon":null,"is_show":true,"alias_name":"marketingdistributor","version":6,"disabled":false,"created":1675936334,"updated":1730775516,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10524","company_id":0,"name":"\u552e\u540e\u5730\u5740","url":"\/merchant\/sellers\/distributoraftersalesaddress","sort":3,"is_menu":true,"pid":"10514","apis":"distributor.easy.list","icon":null,"is_show":true,"alias_name":"distributoraftersalesaddress","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10732","company_id":0,"name":"\u4e1a\u52a1\u5458\u5206\u9500\u5546\u54c1\u6c60","url":"\/merchant\/sellers\/popularize\/popularizegoods","sort":4,"is_menu":true,"pid":"10514","apis":"goods.itemsupdate\r\ngoods.rebateconf\r\npopularize.config.get","icon":null,"is_show":true,"alias_name":"popularizegoods","version":6,"disabled":false,"created":1619507570,"updated":1619507570,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10729","company_id":0,"name":"\u4e1a\u52a1\u5458","url":"\/merchant\/sellers\/marketingsalesman","sort":5,"is_menu":true,"pid":"10514","apis":"distribution.salesman.list.get\ndistribution.salesman.add\ndistribution.salesman.update\nworkwechat.rel.list\nshop.salesperson.getinfo\ndistribution.salesman.role.list\ndistribution.salesman.role.update\ndistribution.salesperson.role.list\npopularize.promoter.children.list","icon":null,"is_show":true,"alias_name":"marketingsalesman","version":6,"disabled":false,"created":1611714282,"updated":1723442497,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10731","company_id":0,"name":"\u4e1a\u52a1\u5458\u4e1a\u7ee9","url":"\/merchant\/sellers\/marketing\/popularize\/popularizedata","sort":6,"is_menu":true,"pid":"10514","apis":"popularize.promoter.exportx\npopularize.promoter.exportPopularizeOrder\npopularize.promoter.list.get\npopularize.promoter.exportPopularizeStatic\npopularize.brokerage.logs","icon":null,"is_show":true,"alias_name":"popularizedata","version":6,"disabled":false,"created":1656639108,"updated":1720678015,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10733","company_id":0,"name":"\u4e1a\u52a1\u5458\u63d0\u73b0","url":"\/merchant\/sellers\/marketing\/popularize\/salesman\/withdraw","sort":7,"is_menu":true,"pid":"10514","apis":"popularize.cash_withdrawals.list.get\r\npopularize.cash_withdrawals.process\r\npopularize.cash_withdrawals.pay.list.get\r\npopularize.brokerage.count\r\ndistribution.cash_withdrawal.list","icon":"money-check-alt","is_show":true,"alias_name":"popularizewithdraw","version":6,"disabled":false,"created":1656639108,"updated":1656639108,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10515","company_id":0,"name":"\u7edf\u8ba1","url":"\/merchant\/companydata","sort":4,"is_menu":true,"pid":"0","apis":"","icon":"chart-bar","is_show":true,"alias_name":"companydata","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10525","company_id":0,"name":"\u4ea4\u6613\u7edf\u8ba1","url":"\/merchant\/companydata\/orderstatistics","sort":1,"is_menu":true,"pid":"10515","apis":"datacube.company.data","icon":null,"is_show":true,"alias_name":"orderstatistics","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10526","company_id":0,"name":"\u5e97\u94fa\u7edf\u8ba1","url":"\/merchant\/companydata\/distributordata","sort":2,"is_menu":true,"pid":"10515","apis":"datacube.distributor.data\nwechat.wxa.template.list","icon":null,"is_show":true,"alias_name":"distributordata","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10527","company_id":0,"name":"\u5546\u54c1\u7edf\u8ba1","url":"\/merchant\/companydata\/goodsstatistics","sort":3,"is_menu":true,"pid":"10515","apis":"datacube.goods.data","icon":null,"is_show":true,"alias_name":"goodsstatistics","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10635","company_id":0,"name":"\u7ed3\u7b97","url":"\/merchant\/companydata\/financial\/settlement","sort":4,"is_menu":true,"pid":"10515","apis":"","icon":null,"is_show":true,"alias_name":"settlement","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10636","company_id":0,"name":"\u7ed3\u7b97\u6c47\u603b","url":"\/merchant\/companydata\/financial\/settlement\/summary","sort":1,"is_menu":true,"pid":"10635","apis":"merchant.list\nstatement.summarized.get\nstatement.confirm.post\nstatement.detail.get\nstatement.summarized.export\nstatement.detail.export","icon":null,"is_show":true,"alias_name":"summary","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":3,"parent_name":"\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10757","company_id":0,"name":"\u914d\u9001\u5458\u4e1a\u7ee9","url":"\/merchant\/companydata\/deliverystaffstatistics","sort":5,"is_menu":true,"pid":"10515","apis":"datacube.deliverystaff.data.export\nemployeepurchase.activity.list","icon":null,"is_show":true,"alias_name":"merchant_companydata_deliverystaffstatistics","version":6,"disabled":false,"created":1722662651,"updated":1722936111,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10516","company_id":0,"name":"\u8bbe\u7f6e","url":"\/merchant\/setting","sort":5,"is_menu":true,"pid":"0","apis":null,"icon":"cog","is_show":true,"alias_name":"setting","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10528","company_id":0,"name":"\u5e97\u94fa\u7ba1\u7406\u5458","url":"\/merchant\/setting\/Merchantstaff","sort":1,"is_menu":true,"pid":"10516","apis":"account.create\naccount.list\naccount.info\naccount.update\naccount.delete\nroles.list\naccount.roles.permission\nespier.subdistrict.list.get\noperator.status.change","icon":null,"is_show":true,"alias_name":"Merchantstaff","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10756","company_id":0,"name":"\u914d\u9001\u5458","url":"\/merchant\/setting\/staff\/selfdeliverystaff","sort":2,"is_menu":true,"pid":"10516","apis":"datacube.deliverystaff.data","icon":null,"is_show":true,"alias_name":"merchant_setting_staff_selfdeliverystaff","version":6,"disabled":false,"created":1722662537,"updated":1722662703,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10537","company_id":0,"name":"\u8d26\u53f7\u7ba1\u7406","url":"\/merchant\/setting\/account","sort":2,"is_menu":true,"pid":"10516","apis":"merchant.operator.list\nmerchant.operator.save","icon":null,"is_show":true,"alias_name":"account","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10529","company_id":0,"name":"\u6743\u9650\u5ba1\u6279","url":"\/merchant\/setting\/datapassapply","sort":3,"is_menu":true,"pid":"10516","apis":"companys.datapass.list\ncompanys.datapass.detail\ncompanys.datapass.log.list\ncompanys.datapass.approve","icon":null,"is_show":true,"alias_name":"datapassapply","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10530","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/merchant\/setting\/baseexport","sort":4,"is_menu":true,"pid":"10516","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"baseexport","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10531","company_id":0,"name":"\u64cd\u4f5c\u65e5\u5fd7","url":"\/merchant\/setting\/operatorlogs","sort":5,"is_menu":true,"pid":"10516","apis":"company.get.operatorlogs","icon":null,"is_show":true,"alias_name":"operatorlogs","version":6,"disabled":false,"created":1675936334,"updated":1675936334,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10785","company_id":0,"name":"\u5e94\u7528","url":"\/merchant\/applications","sort":5,"is_menu":true,"pid":"0","apis":"","icon":"yingyong-01","is_show":true,"alias_name":"applications","version":6,"disabled":false,"created":1741747818,"updated":1741747818,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"10786","company_id":0,"name":"\u6597\u62f1\u5206\u8d26","url":"\/merchant\/applications\/bspay","sort":1,"is_menu":true,"pid":"10785","apis":null,"icon":null,"is_show":true,"alias_name":"bspay","version":6,"disabled":false,"created":1741747941,"updated":1741747941,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"10787","company_id":0,"name":"\u7528\u6237\u8fdb\u4ef6","url":"\/merchant\/applications\/bspay\/user","sort":1,"is_menu":true,"pid":"10786","apis":"bspay.user_indv.create\nbspay.user_indv.modify\nbspay.user_ent.create\nbspay.user_ent.modify\nbspay.user.audit_state\nbspay.user_ent.info\nbspay.user_indv.info\nbspay.regions\nbspay.regions.third","icon":null,"is_show":true,"alias_name":"user","version":6,"disabled":false,"created":1741747964,"updated":1741748016,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10788","company_id":0,"name":"\u5206\u8d26\u660e\u7ec6","url":"\/merchant\/applications\/bspay\/trades","sort":1,"is_menu":true,"pid":"10786","apis":"bspay.trade.getList\nbspay.tradeInfo.get\nbspay.trades.list.export\nadapay.trade.getList","icon":null,"is_show":true,"alias_name":"bspay_trades","version":6,"disabled":false,"created":1741747991,"updated":1741748026,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["platform"]}] \ No newline at end of file +[{"shopmenu_id":"749","company_id":0,"name":"\u6982\u51b5","url":"\/merchant","sort":1,"is_menu":true,"pid":"0","apis":"company.real.statistics\nwechat.authorizerInfo\nwechat.pre_auth_url","icon":"tachometer-alt","is_show":true,"alias_name":"merchant","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"750","company_id":0,"name":"\u4ea4\u6613","url":"\/merchant\/order","sort":2,"is_menu":true,"pid":"0","apis":null,"icon":"clipboard-list","is_show":true,"alias_name":"order","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"751","company_id":0,"name":"\u5b9e\u7269\u8ba2\u5355","url":"\/merchant\/order\/tradenormalorders","sort":1,"is_menu":true,"pid":"750","apis":"order.list.get\ndistributor.list\nsource.list\ninvoice.list.export\norder.list.export\ncompany.logistics.list\norder.info.get\norder.delivery.lists\ntrade.logistics.list\nmember.info\norder.delivery.update\nespier.upload\nespier.subdistrict.list.get\npresale.pickupcode.setting.get\norder.deliverystaff.confirm\norder.deliverystaff.cancel\nall.setting.get\nthird.jushuitan.setting.get","icon":null,"is_show":true,"alias_name":"tradenormalorders","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"752","company_id":0,"name":"\u552e\u540e\u5217\u8868","url":"\/merchant\/order\/aftersaleslist","sort":2,"is_menu":true,"pid":"750","apis":"aftersales.list\naftersales.logexport\naftersales.remind.get\naftersales.info","icon":null,"is_show":true,"alias_name":"aftersaleslist","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"753","company_id":0,"name":"\u4ea4\u6613\u5355","url":"\/merchant\/order\/tradepayment","sort":3,"is_menu":true,"pid":"750","apis":"order.trade.list\ntrades.list.export","icon":null,"is_show":true,"alias_name":"tradepayment","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"754","company_id":0,"name":"\u9000\u6b3e\u5355","url":"\/merchant\/order\/aftersalesrefundlist","sort":4,"is_menu":true,"pid":"750","apis":"refund.list\nrefund.logexport\nrefund.info","icon":null,"is_show":true,"alias_name":"aftersalesrefundlist","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"755","company_id":0,"name":"\u9000\u6b3e\u5931\u8d25\u65e5\u5fd7","url":"\/merchant\/order\/Refunderrorlogs","sort":5,"is_menu":true,"pid":"750","apis":"trade.refunderrorlogs.list","icon":null,"is_show":true,"alias_name":"Refunderrorlogs","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"756","company_id":0,"name":"\u5546\u5bb6","url":"\/merchant\/sellers","sort":3,"is_menu":true,"pid":"0","apis":null,"icon":"store-alt","is_show":true,"alias_name":"sellers","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"757","company_id":0,"name":"\u5546\u5bb6\u4fe1\u606f","url":"\/merchant\/sellers\/merchantinfo","sort":1,"is_menu":true,"pid":"756","apis":"merchant.info.get\nmerchant.type.list\nespier.address.info\nmerchant.visibletype.list\nmerchant.basesetting.get\ngoods.category.lists\ngoods.attributes.list","icon":null,"is_show":true,"alias_name":"merchantinfo","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"758","company_id":0,"name":"\u5e97\u94fa\u5217\u8868","url":"\/merchant\/sellers\/marketingdistributor","sort":2,"is_menu":true,"pid":"756","apis":"distributor.tag.list\nhfpay.ledgerconfig.index\ncompany.regionauth.list\ncompany.dada.info\ndistributor.create\ndistributor.tag.rel\ndistribution.distance.get\ndistribution.distance.save\nhfpay.enterapply.opensplit\ndistributor.edit\ndistributor.default.set\ndistributor.info\nwechat.material.list\nespier.image.list\npagestemplateset.getInfo\npagestemplate.lists\nrecommendlike.list\ncurrency.get.default\nshipping.templates.list\ngoods.sku.lists\npagestemplate.detail\ngoods.items.lists\npagestemplate.edit\npagestemplate.modifyStatus\npagestemplate.copy\npagestemplate.delete\npagestemplate.add\ndistributor.wxacode\ncard.list\ngoods.tag.list\narticle.list\nselfhelp.registrationActivity.easylist\nPromotions.seckill.list\nwechat.wxa.customizepage.list\npromotions.liverooms\nwxexternalconfig.list\nwxexternalconfigroutes.list\nespier.oss.uploadToken.get\nespier.image.save\ndistributor.aftersales.list\npickuplocation.list.get\nespier.image.cat.children\nespier.image.cat.edit\nespier.image.cat.del\nespier.image.move.cat\norders.setting.get\ntrade.payment.setting.get\ntrade.payment.open.status.get\ntrade.payment.setting.set","icon":null,"is_show":true,"alias_name":"marketingdistributor","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"759","company_id":0,"name":"\u552e\u540e\u5730\u5740","url":"\/merchant\/sellers\/distributoraftersalesaddress","sort":3,"is_menu":true,"pid":"756","apis":"distributor.easy.list","icon":null,"is_show":true,"alias_name":"distributoraftersalesaddress","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u5546\u5bb6","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"760","company_id":0,"name":"\u7edf\u8ba1","url":"\/merchant\/companydata","sort":4,"is_menu":true,"pid":"0","apis":"","icon":"chart-bar","is_show":true,"alias_name":"companydata","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"761","company_id":0,"name":"\u4ea4\u6613\u7edf\u8ba1","url":"\/merchant\/companydata\/orderstatistics","sort":1,"is_menu":true,"pid":"760","apis":"datacube.company.data","icon":null,"is_show":true,"alias_name":"orderstatistics","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"762","company_id":0,"name":"\u5e97\u94fa\u7edf\u8ba1","url":"\/merchant\/companydata\/distributordata","sort":2,"is_menu":true,"pid":"760","apis":"datacube.distributor.data\nwechat.wxa.template.list","icon":null,"is_show":true,"alias_name":"distributordata","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"763","company_id":0,"name":"\u5546\u54c1\u7edf\u8ba1","url":"\/merchant\/companydata\/goodsstatistics","sort":3,"is_menu":true,"pid":"760","apis":"datacube.goods.data","icon":null,"is_show":true,"alias_name":"goodsstatistics","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"764","company_id":0,"name":"\u7ed3\u7b97","url":"\/merchant\/companydata\/financial\/settlement","sort":4,"is_menu":true,"pid":"760","apis":"","icon":null,"is_show":true,"alias_name":"settlement","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"765","company_id":0,"name":"\u7ed3\u7b97\u6c47\u603b","url":"\/merchant\/companydata\/financial\/settlement\/summary","sort":1,"is_menu":true,"pid":"764","apis":"merchant.list\nstatement.summarized.get\nstatement.confirm.post\nstatement.detail.get\nstatement.summarized.export\nstatement.detail.export","icon":null,"is_show":true,"alias_name":"summary","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":3,"parent_name":"\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"766","company_id":0,"name":"\u914d\u9001\u5458\u4e1a\u7ee9","url":"\/merchant\/companydata\/deliverystaffstatistics","sort":5,"is_menu":true,"pid":"760","apis":"datacube.deliverystaff.data.export\nemployeepurchase.activity.list","icon":null,"is_show":true,"alias_name":"merchant_companydata_deliverystaffstatistics","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"774","company_id":0,"name":"\u5e94\u7528","url":"\/merchant\/applications","sort":5,"is_menu":true,"pid":"0","apis":"","icon":"yingyong-01","is_show":true,"alias_name":"applications","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"775","company_id":0,"name":"\u6597\u62f1\u5206\u8d26","url":"\/merchant\/applications\/bspay","sort":1,"is_menu":true,"pid":"774","apis":null,"icon":null,"is_show":true,"alias_name":"bspay","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"776","company_id":0,"name":"\u7528\u6237\u8fdb\u4ef6","url":"\/merchant\/applications\/bspay\/user","sort":1,"is_menu":true,"pid":"775","apis":"bspay.user_indv.create\nbspay.user_indv.modify\nbspay.user_ent.create\nbspay.user_ent.modify\nbspay.user.audit_state\nbspay.user_ent.info\nbspay.user_indv.info\nbspay.regions\nbspay.regions.third","icon":null,"is_show":true,"alias_name":"user","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"777","company_id":0,"name":"\u5206\u8d26\u660e\u7ec6","url":"\/merchant\/applications\/bspay\/trades","sort":1,"is_menu":true,"pid":"775","apis":"bspay.trade.getList\nbspay.tradeInfo.get\nbspay.trades.list.export\nadapay.trade.getList","icon":null,"is_show":true,"alias_name":"bspay_trades","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"767","company_id":0,"name":"\u8bbe\u7f6e","url":"\/merchant\/setting","sort":5,"is_menu":true,"pid":"0","apis":null,"icon":"cog","is_show":true,"alias_name":"setting","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"768","company_id":0,"name":"\u5e97\u94fa\u7ba1\u7406\u5458","url":"\/merchant\/setting\/Merchantstaff","sort":1,"is_menu":true,"pid":"767","apis":"account.create\naccount.list\naccount.info\naccount.update\naccount.delete\nroles.list\naccount.roles.permission\nespier.subdistrict.list.get\noperator.status.change","icon":null,"is_show":true,"alias_name":"Merchantstaff","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"769","company_id":0,"name":"\u914d\u9001\u5458","url":"\/merchant\/setting\/staff\/selfdeliverystaff","sort":2,"is_menu":true,"pid":"767","apis":"datacube.deliverystaff.data","icon":null,"is_show":true,"alias_name":"merchant_setting_staff_selfdeliverystaff","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"770","company_id":0,"name":"\u8d26\u53f7\u7ba1\u7406","url":"\/merchant\/setting\/account","sort":2,"is_menu":true,"pid":"767","apis":"merchant.operator.list\nmerchant.operator.save","icon":null,"is_show":true,"alias_name":"account","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"771","company_id":0,"name":"\u6743\u9650\u5ba1\u6279","url":"\/merchant\/setting\/datapassapply","sort":3,"is_menu":true,"pid":"767","apis":"companys.datapass.list\ncompanys.datapass.detail\ncompanys.datapass.log.list\ncompanys.datapass.approve","icon":null,"is_show":true,"alias_name":"datapassapply","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"772","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/merchant\/setting\/baseexport","sort":4,"is_menu":true,"pid":"767","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"baseexport","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"773","company_id":0,"name":"\u64cd\u4f5c\u65e5\u5fd7","url":"\/merchant\/setting\/operatorlogs","sort":5,"is_menu":true,"pid":"767","apis":"company.get.operatorlogs","icon":null,"is_show":true,"alias_name":"operatorlogs","version":6,"disabled":false,"created":1770118488,"updated":1770118488,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file diff --git a/storage/static/platform_menu.json b/storage/static/platform_menu.json index 26c45a2..3e67624 100644 --- a/storage/static/platform_menu.json +++ b/storage/static/platform_menu.json @@ -1,5842 +1 @@ -[ - { - "shopmenu_id": "10906", - "company_id": 0, - "name": "\u6982\u51b5", - "url": "\/", - "sort": 1, - "is_menu": true, - "pid": "0", - "apis": "company.activate.info\nwechat.pre_auth_url\nwechat.authorizerInfo\nwechat.stats.userWeekSummary\ncompany.resources\nwechat.bind\ncompanys.setting\ncompany.real.statistics\ncompany.notice.statistics\ncompanys.ydleads.create\nselfhelp.form.add\nselfhelp.form.edit\nselfhelp.form.info\nselfhelp.form.delete\nselfhelp.template.add\nselfhelp.registrationActivity.info\nselfhelp.registrationActivity.delete\nselfhelp.registrationActivity.invalid\nselfhelp.physical.datelist\nmerchant.operator.update\noperator.update.data\noperator.select.distributor\norder.message.new", - "icon": "tachometer-alt-copy", - "is_show": true, - "alias_name": "index", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10907", - "company_id": 0, - "name": "\u5546\u54c1", - "url": "\/entity", - "sort": 2, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "shopping-bag-copy", - "is_show": true, - "alias_name": "entity", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10908", - "company_id": 0, - "name": "\u5546\u54c1\u7ba1\u7406", - "url": "\/entity\/goods", - "sort": 1, - "is_menu": true, - "pid": "10907", - "apis": "third.wdterp.setting.get\nthird.jushuitan.setting.get", - "icon": null, - "is_show": true, - "alias_name": "goods", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5546\u54c1", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10909", - "company_id": 0, - "name": "\u81ea\u8425\u5546\u54c1", - "url": "\/entity\/goods\/goodsphysical", - "sort": 1, - "is_menu": true, - "pid": "10908", - "apis": "goods.items.create\ngoods.items.templates_change\ngoods.items.category_change\ngoods.items.lists\ngoods.items.detail\ngoods.items.delete\ngoods.items.update\ngoods.items.distributiongoodswxacode\ngoods.items.warning_store\ngoods.category.lists\ngoods.category.get\ngoods.category.update\nshipping.templates.list\ncurrency.get.default\nespier.image.list\ndistributor.item.create\nespier.image.cat.children\ngoods.attributes.list\nwechat.material.upload\nwechat.material.list\ngoods.tag.list\ngoods.tag.rel\ngoods.status.upate\npopularize.config.get\ngoods.member.price\ngoods.store.upate\ngoods.export\ngoods.profit.info\ngoods.profit.save\ngoods.jishuitan.items.upload\ngoods.jushuitan.inventory.query\ngoods.sync.items\ngoods.isgift.upate\ngoods.createcategory.create\nespier.image.cat.edit\nthird.jushuitan.setting.get\nall.setting.get\nthird.wdterp.setting.get\npoint.member.rule.info\nespier.address.info\nespier.upload\nespier.oss.uploadToken.get\nespier.image.save", - "icon": null, - "is_show": true, - "alias_name": "goodsphysical", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1745221942, - "level": 3, - "parent_name": "\u5546\u54c1\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10910", - "company_id": 0, - "name": "\u5546\u6237\u5546\u54c1", - "url": "\/entity\/goods\/goodsaudit", - "sort": 2, - "is_menu": true, - "pid": "10908", - "apis": "goods.items.lists\ngoods.items.detail\ngoods.items.distributiongoodswxacode\ngoods.items.warning_store\ngoods.category.lists\nshipping.templates.list\ncurrency.get.default\nwechat.material.upload\nwechat.material.list\ngoods.tag.list\ngoods.items.audit", - "icon": null, - "is_show": true, - "alias_name": "goodsaudit", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5546\u54c1\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10911", - "company_id": 0, - "name": "\u95e8\u5e97\u5546\u54c1\u7ba1\u7406", - "url": "\/entity\/goods\/storeshopitemanagement", - "sort": 3, - "is_menu": true, - "pid": "10908", - "apis": "distributor.item.exportlist", - "icon": null, - "is_show": true, - "alias_name": "storeshopitemanagement", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5546\u54c1\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "10912", - "company_id": 0, - "name": "\u5546\u54c1\u5206\u7c7b", - "url": "\/entity\/goodsgroup", - "sort": 2, - "is_menu": true, - "pid": "10907", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "goodsgroup", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5546\u54c1", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10913", - "company_id": 0, - "name": "\u7ba1\u7406\u5206\u7c7b", - "url": "\/entity\/goodsgroup\/goodsmaincategory", - "sort": 1, - "is_menu": true, - "pid": "10912", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "goodsmaincategory", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5546\u54c1\u5206\u7c7b", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10914", - "company_id": 0, - "name": "\u9500\u552e\u5206\u7c7b", - "url": "\/entity\/goodsgroup\/goodscategory", - "sort": 2, - "is_menu": true, - "pid": "10912", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "goodscategory", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5546\u54c1\u5206\u7c7b", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10915", - "company_id": 0, - "name": "\u5546\u54c1\u6807\u7b7e", - "url": "\/entity\/goodsgroup\/itemtags", - "sort": 3, - "is_menu": true, - "pid": "10912", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "itemtags", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5546\u54c1\u5206\u7c7b", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10916", - "company_id": 0, - "name": "\u57fa\u7840\u914d\u7f6e", - "url": "\/entity\/goodsbase", - "sort": 2, - "is_menu": true, - "pid": "10907", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "goodsbase", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5546\u54c1", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10917", - "company_id": 0, - "name": "\u5546\u54c1\u89c4\u683c", - "url": "\/entity\/goodsbase\/goodsattributes", - "sort": 3, - "is_menu": true, - "pid": "10916", - "apis": "goods.attributes.update", - "icon": null, - "is_show": true, - "alias_name": "goodsattributes", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u57fa\u7840\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10918", - "company_id": 0, - "name": "\u5546\u54c1\u54c1\u724c", - "url": "\/entity\/goodsbase\/goodsbrand", - "sort": 4, - "is_menu": true, - "pid": "10916", - "apis": "goods.attributes.add", - "icon": null, - "is_show": true, - "alias_name": "goodsbrand", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u57fa\u7840\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10919", - "company_id": 0, - "name": "\u5546\u54c1\u53c2\u6570", - "url": "\/entity\/goodsbase\/goodsparams", - "sort": 5, - "is_menu": true, - "pid": "10916", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "goodsparams", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u57fa\u7840\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10920", - "company_id": 0, - "name": "\u8ba2\u5355", - "url": "\/order", - "sort": 3, - "is_menu": true, - "pid": "0", - "apis": "datacube.deliverystaff.data\norder.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel", - "icon": "receipt", - "is_show": true, - "alias_name": "order", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10921", - "company_id": 0, - "name": "\u8ba2\u5355\u7ba1\u7406", - "url": "\/order\/entitytrade", - "sort": 1, - "is_menu": true, - "pid": "10920", - "apis": "order.writeoff.qr.set\norder.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel", - "icon": null, - "is_show": true, - "alias_name": "entitytrade", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8ba2\u5355", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10922", - "company_id": 0, - "name": "\u8ba2\u5355\u5217\u8868", - "url": "\/order\/entitytrade\/tradenormalorders", - "sort": 1, - "is_menu": true, - "pid": "10921", - "apis": "order.list.get\nsource.list\norder.info.get\norder.delivery\norder.list.export\nshops.lists\ndistributor.list\nmember.info\ntrade.logistics.list\nespier.image.del\norder.cancel.info\norder.delivery.update\norder.cancel\ninvoice.list.export\norder.writeoff.info.get\norder.writeoff.set\norder.process.log.get\norder.invoiced.invoiced\norder.delivery.details\norder.delivery.lists\norder.businessreceipt\nworkwechat.distributor.js.config\nespier.subdistrict.list.get\norder.remarks.update\norder.writeoff.qr.set\norder.process.log.get\norder.invoiced.invoiced\norder.delivery.details\norder.delivery.lists\norder.remarks.update\ndelivery.process.list\nworkwechat.distributor.js.config\norder.message.new\ncompany.real.statistics\norder.writeoff.qr.set\noperator.update.data\nespier.oss.uploadToken.get\norder.message.list\norder.businessreceipt\nespier.localimage.upload\nespier.image.save\norder.message.update\ncard.consume\nespier.subdistrict.list.get\noperator.select.distributor\naftersales.remark.update\nespier.oss.uploadToken.get\nespier.localimage.upload\nespier.image.save\nespier.address.info\ngoods.items.onsale.lists\ncompanys.operator.cartdata.scanadd\ncompanys.operator.cartdata.add\ncompanys.operator.cartdata.update\ncompanys.operator.cartdata.list\ncompanys.operator.cartdata.del\norder.checkout\norder.create\norder.payment\norder.payment.query\nuser.card.list\nmember.create\ncompanys.operator.cartdata.pending\ncompanys.operator.order.pending\ncompanys.operator.pending.fetch\ncompanys.operator.pending.delete\ncompanys.operator.pending.list\norder.markdown\norder.markdown.confirm\norder.writeoff.qr.set\norder.deliverystaff.confirm\ndatacube.deliverystaff.data\norder.deliverystaff.cancel\nall.setting.get\npresale.pickupcode.setting.get", - "icon": null, - "is_show": true, - "alias_name": "tradenormalorders", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1744679673, - "level": 3, - "parent_name": "\u8ba2\u5355\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10923", - "company_id": 0, - "name": "\u81ea\u8425\u8ba2\u5355", - "url": "\/order\/entitytrade\/marketingdistribution_orders", - "sort": 2, - "is_menu": true, - "pid": "10921", - "apis": "source.list\norder.writeoff.qr.set", - "icon": null, - "is_show": true, - "alias_name": "marketingdistribution_orders", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "10924", - "company_id": 0, - "name": "\u81ea\u8425\u8ba2\u5355", - "url": "\/order\/entitytrade\/tradenormalshoporders", - "sort": 2, - "is_menu": true, - "pid": "10921", - "apis": "order.cancel.info\norder.delivery.lists\norder.writeoff.qr.set\norder.writeoff.qr.set\ndatacube.deliverystaff.data\norder.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel", - "icon": null, - "is_show": true, - "alias_name": "tradenormalshoporders", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10925", - "company_id": 0, - "name": "\u6279\u91cf\u53d1\u8d27", - "url": "\/order\/entitytrade\/normalordersupload", - "sort": 6, - "is_menu": true, - "pid": "10921", - "apis": "espier.upload.list\norder.deliverystaff.confirm\norder.deliverypackag.confirm", - "icon": null, - "is_show": true, - "alias_name": "normalordersupload", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10926", - "company_id": 0, - "name": "\u8ba2\u5355\u552e\u540e", - "url": "\/order\/aftersales", - "sort": 2, - "is_menu": true, - "pid": "10920", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "aftersales", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8ba2\u5355", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10927", - "company_id": 0, - "name": "\u552e\u540e\u5217\u8868", - "url": "\/order\/aftersales\/aftersaleslist", - "sort": 1, - "is_menu": true, - "pid": "10926", - "apis": "aftersales.list\naftersales.info\naftersales.review\naftersales.logexport\naftersales.remind.get\naftersales.remind.set\naftersales.apply\norder.deliverystaff.confirm\norder.deliverypackag.confirm\ndatacube.deliverystaff.data\naftersales.sendback", - "icon": null, - "is_show": true, - "alias_name": "aftersaleslist", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u552e\u540e", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10928", - "company_id": 0, - "name": "\u8ba2\u5355\u8bbe\u7f6e", - "url": "\/order\/ordersetting", - "sort": 3, - "is_menu": true, - "pid": "10920", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "ordersetting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8ba2\u5355", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10929", - "company_id": 0, - "name": "\u8ba2\u5355\u8bbe\u7f6e", - "url": "\/order\/ordersetting\/ordersettingdetail", - "sort": 1, - "is_menu": true, - "pid": "10928", - "apis": "orders.setting.get\nordersetting.set\norder.delivervstaff.confirm\norder.deliverypackag.confirm", - "icon": null, - "is_show": true, - "alias_name": "ordersettingdetail", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10930", - "company_id": 0, - "name": "\u793c\u54c1\u5305\u88c5", - "url": "\/order\/ordersetting\/tradesetting", - "sort": 1, - "is_menu": true, - "pid": "10928", - "apis": "trade.setting.get\ntrade.setting.set\norder.delivervstaff.confirm\norder.deliverypackag.confirm", - "icon": null, - "is_show": true, - "alias_name": "tradesetting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10931", - "company_id": 0, - "name": "\u552e\u540e\u539f\u56e0", - "url": "\/order\/ordersetting\/aftersalesreason", - "sort": 1, - "is_menu": true, - "pid": "10928", - "apis": "aftersales.reason.list\naftersales.reason.save\norder.delivervstaff.confirm\norder.deliverypackag.confirm", - "icon": null, - "is_show": true, - "alias_name": "aftersalesreason", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10932", - "company_id": 0, - "name": "\u8d2d\u7269\u63d0\u9192", - "url": "\/order\/ordersetting\/cartremind", - "sort": 4, - "is_menu": true, - "pid": "10928", - "apis": "wechat.wxa.cartremind.setting.set\nwechat.wxa.cartremind.setting.get", - "icon": null, - "is_show": true, - "alias_name": "cartremind", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10933", - "company_id": 0, - "name": "\u5546\u54c1\u9650\u8d2d", - "url": "\/order\/ordersetting\/goodslimit", - "sort": 5, - "is_menu": true, - "pid": "10928", - "apis": "promotions.limit.list.get\npromotions.limit.create\npromotions.limit.info.get\npromotions.limit.cancel\npromotions.limit.update", - "icon": null, - "is_show": true, - "alias_name": "goodslimit", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8ba2\u5355\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10934", - "company_id": 0, - "name": "\u4f1a\u5458", - "url": "\/member", - "sort": 4, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "crown", - "is_show": true, - "alias_name": "member", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10935", - "company_id": 0, - "name": "\u4f1a\u5458\u7ba1\u7406", - "url": "\/member\/member", - "sort": 0, - "is_menu": true, - "pid": "10934", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "memberlmana", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u4f1a\u5458", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10936", - "company_id": 0, - "name": "\u4f1a\u5458\u5217\u8868", - "url": "\/member\/member\/memberlist", - "sort": 1, - "is_menu": true, - "pid": "10935", - "apis": "member.subscribe.list\naliyunsms.status.get\npopularize.promoter.list.get", - "icon": null, - "is_show": true, - "alias_name": "memberlist", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1744679602, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10937", - "company_id": 0, - "name": "\u6279\u91cf\u66f4\u65b0", - "url": "\/member\/member\/managecustomer", - "sort": 1, - "is_menu": true, - "pid": "10935", - "apis": "espier.upload.list\nespier.upload\nespier.upload.error.export\nespier.upload.template.export", - "icon": null, - "is_show": true, - "alias_name": "managecustomer", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10938", - "company_id": 0, - "name": "\u4f1a\u5458\u6807\u7b7e", - "url": "\/member\/member\/Managetag", - "sort": 1, - "is_menu": true, - "pid": "10935", - "apis": "member.tag.add\nmember.tag.delete\nmember.tag.update\nmember.tag.list\nmember.tag.get\nmember.tag.rel\nmember.tagsearch\nmember.tagcategory.list", - "icon": null, - "is_show": true, - "alias_name": "Managetag", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10939", - "company_id": 0, - "name": "\u4f1a\u5458\u5bfc\u51fa", - "url": "\/member\/member\/memberlist", - "sort": 1, - "is_menu": false, - "pid": "10935", - "apis": "member.export", - "icon": null, - "is_show": true, - "alias_name": "member-export", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10940", - "company_id": 0, - "name": "\u624b\u52a8\u5ef6\u671f\u4ed8\u8d39\u4f1a\u5458", - "url": "\/member\/member\/memberlist", - "sort": 1, - "is_menu": false, - "pid": "10935", - "apis": "vipgrade.use.active.delay\nvipgrade.use.batch.active.delay\nvipgrade.use.list\nmember.upate.grade_id", - "icon": null, - "is_show": true, - "alias_name": "member-vip-delay", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "standard" - ] - }, - { - "shopmenu_id": "10941", - "company_id": 0, - "name": "\u6dfb\u52a0\u6743\u76ca", - "url": "\/member\/member\/memberlist", - "sort": 2, - "is_menu": false, - "pid": "10935", - "apis": "member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\ngoods.items.lists\norder.rights.add", - "icon": null, - "is_show": true, - "alias_name": "member-add-rights", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10942", - "company_id": 0, - "name": "\u4f1a\u5458\u4fe1\u606f\u67e5\u770b", - "url": "\/member\/member\/memberlist", - "sort": 2, - "is_menu": false, - "pid": "10935", - "apis": "member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\npoint.member.list\ndistributor.list\nvipgrade.order.list\npoint.member.list\nworkwechat.rel.log\npoint.adjustment", - "icon": null, - "is_show": true, - "alias_name": "member-list-view", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10943", - "company_id": 0, - "name": "\u7fa4\u53d1\u4f18\u60e0\u5238", - "url": "\/member\/member\/memberlist", - "sort": 4, - "is_menu": false, - "pid": "10935", - "apis": "member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\npromotions.give.create\npromotions.give.list\npromotions.give.info\nmember.tag.rel\ngoods.items.lists\nmember.batch.operating", - "icon": null, - "is_show": true, - "alias_name": "member-send-coupons", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10944", - "company_id": 0, - "name": "\u7fa4\u53d1\u77ed\u4fe1", - "url": "\/member\/member\/memberlist", - "sort": 5, - "is_menu": false, - "pid": "10935", - "apis": "member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\nmember.smssend", - "icon": null, - "is_show": true, - "alias_name": "member-send-sms", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10945", - "company_id": 0, - "name": "\u6253\u6807\u7b7e", - "url": "\/member\/member\/memberlist", - "sort": 6, - "is_menu": false, - "pid": "10935", - "apis": "member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\nmember.tag.rel\nmember.tag.del\nmember.batch.operating", - "icon": null, - "is_show": true, - "alias_name": "member-tag", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10946", - "company_id": 0, - "name": "\u4f1a\u5458\u624b\u673a\u53f7\u4fee\u6539", - "url": "\/member\/member\/memberlist", - "sort": 7, - "is_menu": false, - "pid": "10935", - "apis": "member.upate.mobile", - "icon": null, - "is_show": true, - "alias_name": "member-modify-phone-number", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10947", - "company_id": 0, - "name": "\u4f1a\u5458\u6743\u76ca", - "url": "\/member\/card", - "sort": 1, - "is_menu": true, - "pid": "10934", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "card", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u4f1a\u5458", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10948", - "company_id": 0, - "name": "\u4f1a\u5458\u7b49\u7ea7", - "url": "\/member\/card\/managecard", - "sort": 0, - "is_menu": true, - "pid": "10947", - "apis": "membercard.setting\nmembercard.info\nmembercard.grade.add\nmembercard.default.grade\nmembercard.grade.list\nmembercard.vipgrade.add\nmembercard.vipgrade.list\nvipgrade.use.list", - "icon": null, - "is_show": true, - "alias_name": "managecard", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u6743\u76ca", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10949", - "company_id": 0, - "name": "\u4ed8\u8d39\u8bb0\u5f55", - "url": "\/member\/card\/managecardorder", - "sort": 1, - "is_menu": true, - "pid": "10947", - "apis": "vipgrade.order.list", - "icon": null, - "is_show": true, - "alias_name": "managecardorder", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u6743\u76ca", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10950", - "company_id": 0, - "name": "\u79ef\u5206\u89c4\u5219", - "url": "\/member\/card\/pointrule", - "sort": 1, - "is_menu": true, - "pid": "10947", - "apis": "point.member.rule.info\npoint.member.rule.save", - "icon": null, - "is_show": true, - "alias_name": "pointrule", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u6743\u76ca", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10951", - "company_id": 0, - "name": "\u79ef\u5206\u6d41\u6c34", - "url": "\/member\/card\/pointoverview", - "sort": 1, - "is_menu": true, - "pid": "10947", - "apis": "point.member.list\nmember.pointcount.index", - "icon": null, - "is_show": true, - "alias_name": "pointoverview", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u6743\u76ca", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10952", - "company_id": 0, - "name": "\u4f1a\u5458\u89e6\u8fbe", - "url": "\/member\/membertouch", - "sort": 2, - "is_menu": true, - "pid": "10934", - "apis": "member.subscribe.list", - "icon": null, - "is_show": true, - "alias_name": "membertouch", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1744339281, - "level": 2, - "parent_name": "\u4f1a\u5458", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10953", - "company_id": 0, - "name": "\u7fa4\u53d1\u77ed\u4fe1", - "url": "\/member\/membertouch\/smssend", - "sort": 1, - "is_menu": true, - "pid": "10952", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "smssend", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u89e6\u8fbe", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10954", - "company_id": 0, - "name": "\u5230\u8d27\u901a\u77e5", - "url": "\/member\/membertouch\/arrivalnotice", - "sort": 2, - "is_menu": true, - "pid": "10952", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "arrivalnotice", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u89e6\u8fbe", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10955", - "company_id": 0, - "name": "\u4f1a\u5458\u8bbe\u7f6e", - "url": "\/member\/membersetting", - "sort": 3, - "is_menu": true, - "pid": "10934", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "membersetting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u4f1a\u5458", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10956", - "company_id": 0, - "name": "\u6ce8\u518c\u914d\u7f6e", - "url": "\/member\/membersetting\/Manageinfomation", - "sort": 1, - "is_menu": true, - "pid": "10955", - "apis": "member.register.set\nmember.register.get\nespier.config.request_field_setting.get\nespier.config.request_fields.get", - "icon": null, - "is_show": true, - "alias_name": "manageinfomation", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10957", - "company_id": 0, - "name": "\u6ce8\u9500\u914d\u7f6e", - "url": "\/member\/membersetting\/closeAccount", - "sort": 2, - "is_menu": true, - "pid": "10955", - "apis": "shops.protocol.put\nshops.protocol.get", - "icon": null, - "is_show": true, - "alias_name": "closeAccount", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10958", - "company_id": 0, - "name": "\u4fe1\u4efb\u767b\u5f55", - "url": "\/member\/membersetting\/trustlogin", - "sort": 3, - "is_menu": true, - "pid": "10955", - "apis": "member.trustlogin.list\nmember.trustlogin.setting", - "icon": null, - "is_show": true, - "alias_name": "trustlogin", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11162", - "company_id": 0, - "name": "\u4f1a\u5458\u767d\u540d\u5355", - "url": "\/member\/whitelistlist", - "sort": 4, - "is_menu": true, - "pid": "10934", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "whitelistlist", - "version": 1, - "disabled": false, - "created": 1745236884, - "updated": 1745236884, - "level": 2, - "parent_name": "\u4f1a\u5458", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11163", - "company_id": 0, - "name": "\u767d\u540d\u5355\u5bfc\u5165", - "url": "\/member\/whitelistuploade", - "sort": 5, - "is_menu": true, - "pid": "10934", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "whitelistuploade", - "version": 1, - "disabled": false, - "created": 1745236955, - "updated": 1745236955, - "level": 2, - "parent_name": "\u4f1a\u5458", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "10959", - "company_id": 0, - "name": "\u5546\u6237", - "url": "\/sellers", - "sort": 5, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "store-alt-copy", - "is_show": true, - "alias_name": "sellers", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10960", - "company_id": 0, - "name": "\u9500\u552e\u7ec4\u7ec7", - "url": "\/sellers\/salesorganization", - "sort": 0, - "is_menu": true, - "pid": "10959", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "salesorganization", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5546\u6237", - "isChildrenMenu": true, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10961", - "company_id": 0, - "name": "\u5546\u6237", - "url": "\/sellers\/salesorganization\/list", - "sort": 1, - "is_menu": true, - "pid": "10960", - "apis": "merchant.list\nmerchant.visibletype.list\nmerchant.detail.get\nmerchant.disabled.update\nmerchant.audit.goods.update\nmerchant.info.get", - "icon": null, - "is_show": true, - "alias_name": "storemanager", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u9500\u552e\u7ec4\u7ec7", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10962", - "company_id": 0, - "name": "\u5e97\u94fa\u7ba1\u7406", - "url": "\/sellers\/storemanager", - "sort": 1, - "is_menu": true, - "pid": "10959", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "sellersmanager", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5546\u6237", - "isChildrenMenu": true, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10963", - "company_id": 0, - "name": "\u5165\u9a7b\u5e97\u94fa", - "url": "\/sellers\/storemanager\/marketingdistributor", - "sort": 2, - "is_menu": true, - "pid": "10962", - "apis": "distributor.list\ndistributor.create\ndistributor.edit\ndistributor.item.list\ndistributor.wxacode\ndistributor.get.shop\ndistributor.item.update\ndistributor.default.set\ndistributor.create\ndistributor.item.delete\ngoods.items.distributiongoodswxacode\ncurrency.get.default\ndistributor.info\ndistributor.tag.list\npagestemplate.lists\npagestemplateset.getInfo\npagestemplate.detail\npagestemplate.modifyStatus\npagestemplate.add\npagestemplate.edit\npagestemplate.copy\npagestemplate.delete\nhfpay.ledgerconfig.index\ncompany.dada.info\ncompany.regionauth.list\nespier.image.cat.children\norder.writeoff.qr.set", - "icon": null, - "is_show": true, - "alias_name": "marketingsellers", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5e97\u94fa\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10964", - "company_id": 0, - "name": "\u5165\u9a7b\u5ba1\u6838", - "url": "\/sellers\/storemanager\/application", - "sort": 3, - "is_menu": true, - "pid": "10962", - "apis": "merchant.settlement.apply.list\nmerchant.settlement.apply.detail\nmerchant.settlement.apply.audit", - "icon": null, - "is_show": true, - "alias_name": "storemanager_application", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5e97\u94fa\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10965", - "company_id": 0, - "name": "\u9000\u8d27\u5730\u5740", - "url": "\/sellers\/storemanager\/distributoraftersalesaddress", - "sort": 4, - "is_menu": true, - "pid": "10962", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "distributoraftersalesaddress1", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5e97\u94fa\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10966", - "company_id": 0, - "name": "\u5e97\u94fa\u6807\u7b7e", - "url": "\/sellers\/storemanager\/distributortags", - "sort": 5, - "is_menu": true, - "pid": "10962", - "apis": "distributor.tag.add\ndistributor.tag.update\ndistributor.tag.get\ndistributor.tag.get\ndistributor.tag.delete", - "icon": null, - "is_show": true, - "alias_name": "Sellerstags", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5e97\u94fa\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10967", - "company_id": 0, - "name": "\u5546\u6237\u8bbe\u7f6e", - "url": "\/sellers\/salesetting", - "sort": 2, - "is_menu": true, - "pid": "10959", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "salesetting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5546\u6237", - "isChildrenMenu": true, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10968", - "company_id": 0, - "name": "\u5546\u6237\u7c7b\u76ee", - "url": "\/sellers\/salesetting\/setting", - "sort": 1, - "is_menu": true, - "pid": "10967", - "apis": "merchant.type.list\nmerchant.type.creat\nmerchant.type.update\nmerchant.type.delete\nmerchant.basesetting.get\nmerchant.basesetting.save", - "icon": null, - "is_show": true, - "alias_name": "storemanager_setting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5546\u6237\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "10969", - "company_id": 0, - "name": "\u5e97\u94fa", - "url": "\/store", - "sort": 5, - "is_menu": true, - "pid": "0", - "apis": "hfpay.ledgerconfig.index", - "icon": "store-alt-copy", - "is_show": true, - "alias_name": "store", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "10970", - "company_id": 0, - "name": "\u5e97\u94fa\u7ba1\u7406", - "url": "\/store\/storemanager", - "sort": 2, - "is_menu": true, - "pid": "10969", - "apis": "hfpay.ledgerconfig.index\norder.writeoff.qr.set\norders.setting.get ", - "icon": null, - "is_show": true, - "alias_name": "storemanager", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5e97\u94fa", - "isChildrenMenu": true, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "10971", - "company_id": 0, - "name": "\u81ea\u8425\u95e8\u5e97", - "url": "\/store\/storemanager\/marketingdistributor", - "sort": 0, - "is_menu": true, - "pid": "10970", - "apis": "distributor.list\ndistributor.create\ndistributor.edit\ndistributor.item.list\ndistributor.wxacode\ndistributor.get.shop\ndistributor.item.update\ndistributor.default.set\ndistributor.create\ndistributor.item.delete\ngoods.items.distributiongoodswxacode\ncurrency.get.default\ndistributor.info\ndistributor.tag.list\npagestemplate.lists\npagestemplateset.getInfo\npagestemplate.detail\npagestemplate.modifyStatus\npagestemplate.edit\npagestemplate.add\npagestemplate.delete\npagestemplate.copy\ndistribution.distance.get\ndistribution.distance.save\ncompany.regionauth.list\nhfpay.enterapply.opensplit\nhfpay.ledgerconfig.index\ncompany.dada.info\nwechat.material.list\nespier.oss.uploadToken.get\nespier.image.save\nespier.image.list\ndistributor.aftersales.list\norder.writeoff.qr.set\norders.setting.get ", - "icon": null, - "is_show": true, - "alias_name": "marketingdistributor", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5e97\u94fa\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "11160", - "company_id": 0, - "name": "\u5e97\u94fa\u767d\u540d\u5355", - "url": "\/store\/storemanager\/storewhitelist", - "sort": 1, - "is_menu": true, - "pid": "10970", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "storewhitelist", - "version": 1, - "disabled": false, - "created": 1744078492, - "updated": 1744078492, - "level": 3, - "parent_name": "\u5e97\u94fa\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "10972", - "company_id": 0, - "name": "\u9000\u8d27\u5730\u5740", - "url": "\/store\/storemanager\/distributoraftersalesaddress", - "sort": 3, - "is_menu": true, - "pid": "10970", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "distributoraftersalesaddress", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5e97\u94fa\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "11147", - "company_id": 0, - "name": "\u6d3b\u52a8", - "url": "\/activity", - "sort": 6, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "gift", - "is_show": true, - "alias_name": "activity", - "version": 1, - "disabled": false, - "created": 1743128021, - "updated": 1743128021, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "in_purchase" - ] - }, - { - "shopmenu_id": "11148", - "company_id": 0, - "name": "\u5185\u8d2d\u6d3b\u52a8", - "url": "\/activity\/purchases ", - "sort": 1, - "is_menu": true, - "pid": "11147", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "purchases ", - "version": 1, - "disabled": false, - "created": 1743128250, - "updated": 1743128250, - "level": 2, - "parent_name": "\u6d3b\u52a8", - "isChildrenMenu": false, - "menu_type": [ - "in_purchase" - ] - }, - { - "shopmenu_id": "11149", - "company_id": 0, - "name": "\u4f9b\u5e94", - "url": "\/supply", - "sort": 6, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "box", - "is_show": true, - "alias_name": "supply", - "version": 1, - "disabled": false, - "created": 1743669581, - "updated": 1743669581, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11154", - "company_id": 0, - "name": "\u4f9b\u5e94\u5546\u5546\u54c1", - "url": "\/supply\/supplygoods", - "sort": 1, - "is_menu": true, - "pid": "11149", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "supplygoods", - "version": 1, - "disabled": false, - "created": 1743670872, - "updated": 1743670872, - "level": 2, - "parent_name": "\u4f9b\u5e94", - "isChildrenMenu": true, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11155", - "company_id": 0, - "name": "\u5546\u54c1\u7ba1\u7406", - "url": "\/supply\/supplygoods\/supplier_goods_list", - "sort": 1, - "is_menu": true, - "pid": "11154", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "supplier_goods_list", - "version": 1, - "disabled": false, - "created": 1743670907, - "updated": 1743670907, - "level": 3, - "parent_name": "\u4f9b\u5e94\u5546\u5546\u54c1", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11156", - "company_id": 0, - "name": "\u5546\u54c1\u5ba1\u6838", - "url": "\/supply\/supplygoods\/suppliergoods", - "sort": 2, - "is_menu": true, - "pid": "11154", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "goods_suppliergoods", - "version": 1, - "disabled": false, - "created": 1743671911, - "updated": 1743671911, - "level": 3, - "parent_name": "\u4f9b\u5e94\u5546\u5546\u54c1", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11157", - "company_id": 0, - "name": "\u4f9b\u5e94\u5546\u7ba1\u7406", - "url": "\/supply\/supplymanage", - "sort": 2, - "is_menu": true, - "pid": "11149", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "supplymanage", - "version": 1, - "disabled": false, - "created": 1743671963, - "updated": 1743671963, - "level": 2, - "parent_name": "\u4f9b\u5e94", - "isChildrenMenu": true, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11158", - "company_id": 0, - "name": "\u4f9b\u5e94\u5546\u5217\u8868", - "url": "\/supply\/supplymanage\/supplier_list", - "sort": 1, - "is_menu": true, - "pid": "11157", - "apis": "supplier.get_supplier_list ", - "icon": null, - "is_show": true, - "alias_name": "supplier_list", - "version": 1, - "disabled": false, - "created": 1743671994, - "updated": 1744339294, - "level": 3, - "parent_name": "\u4f9b\u5e94\u5546\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11159", - "company_id": 0, - "name": "\u4f9b\u5e94\u5546\u8d26\u53f7", - "url": "\/supply\/supplymanage\/supplier", - "sort": 2, - "is_menu": true, - "pid": "11157", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "supplier", - "version": 1, - "disabled": false, - "created": 1743672019, - "updated": 1743672019, - "level": 3, - "parent_name": "\u4f9b\u5e94\u5546\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10973", - "company_id": 0, - "name": "\u8425\u9500", - "url": "\/marketing", - "sort": 6, - "is_menu": true, - "pid": "0", - "apis": "goods.sku.lists\ngoods.category.lists\ngoods.tag.list\ngoods.attributes.list\nmembercard.vipgrade.list\nwechat.wxa.template.list", - "icon": "tag", - "is_show": true, - "alias_name": "marketing", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10975", - "company_id": 0, - "name": "\u5361\u5238", - "url": "\/marketing\/coupon", - "sort": 1, - "is_menu": true, - "pid": "10973", - "apis": "wechat.wxa.template.list\ndistributor.easy.list", - "icon": null, - "is_show": true, - "alias_name": "coupon", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8425\u9500", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10976", - "company_id": 0, - "name": "\u5238\u7ba1\u7406", - "url": "\/marketing\/coupon\/membermarketing", - "sort": 0, - "is_menu": true, - "pid": "10975", - "apis": "card.list\ncard.create\ncard.delete\ncard.update\ncard.get\ncard.user.list\nshops.lists\ncard.detail.list\nwechat.material.list\nwechat.material.upload\ncurrency.get.default\ncard.store\ndistributor.easy.list\nwechat.wxa.template.list\ndistributor.easy.list", - "icon": null, - "is_show": true, - "alias_name": "membermarketing", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5361\u5238", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10977", - "company_id": 0, - "name": "\u5238\u5305\u7ba1\u7406", - "url": "\/marketing\/coupon\/couponspackage", - "sort": 1, - "is_menu": true, - "pid": "10975", - "apis": "voucher.package.list", - "icon": null, - "is_show": true, - "alias_name": "couponspackage", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5361\u5238", - "isChildrenMenu": false, - "menu_type": [ - "standard", - "platform" - ] - }, - { - "shopmenu_id": "10978", - "company_id": 0, - "name": "\u53d1\u5238\u8bb0\u5f55", - "url": "\/marketing\/coupon\/coupongive", - "sort": 2, - "is_menu": true, - "pid": "10975", - "apis": "promotions.give.list\npromotions.give.info", - "icon": null, - "is_show": true, - "alias_name": "coupongive", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5361\u5238", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10979", - "company_id": 0, - "name": "\u7fa4\u53d1\u4f18\u60e0\u5238", - "url": "\/marketing\/coupon\/couponsend", - "sort": 3, - "is_menu": false, - "pid": "10975", - "apis": "member.list\nmember.operate.logs\nmember.info\neffectiveCard.list\npromotions.give.create\npromotions.give.list\npromotions.give.info\nmember.tag.list\nmember.tag.rel\nmembercard.grade.list\norder.rights.list.get\nshops.lists\norder.rights.transfer.list\ngoods.items.lists\norder.list.get\norder.info.get\ndeposit.trades\nmember.batch.operating", - "icon": null, - "is_show": true, - "alias_name": "couponsend", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5361\u5238", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10980", - "company_id": 0, - "name": "\u4fc3\u9500", - "url": "\/marketing\/promotion", - "sort": 2, - "is_menu": true, - "pid": "10973", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "promotion", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8425\u9500", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10981", - "company_id": 0, - "name": "\u6ee1\u6298", - "url": "\/marketing\/promotion\/marketingsfulldiscount", - "sort": 1, - "is_menu": true, - "pid": "10980", - "apis": "marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ncurrency.get.default\ngoods.category.lists\ngoods.tag.list\ngoods.attributes.list\nmembercard.vipgrade.list\ndistributor.easy.list", - "icon": null, - "is_show": true, - "alias_name": "marketingsfulldiscount", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4fc3\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10982", - "company_id": 0, - "name": "\u6ee1\u51cf", - "url": "\/marketing\/promotion\/Marketingsfullminus", - "sort": 2, - "is_menu": true, - "pid": "10980", - "apis": "marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ncurrency.get.default\ngoods.category.lists\ngoods.tag.list\ngoods.attributes.list\nmembercard.vipgrade.list", - "icon": null, - "is_show": true, - "alias_name": "Marketingsfullminus", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4fc3\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10983", - "company_id": 0, - "name": "\u6ee1\u8d60", - "url": "\/marketing\/promotion\/Marketingsfullgift", - "sort": 3, - "is_menu": true, - "pid": "10980", - "apis": "marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ngoods.category.lists\ngoods.tag.list\ngoods.attributes.list\nmembercard.vipgrade.list", - "icon": null, - "is_show": true, - "alias_name": "Marketingsfullgift", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4fc3\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10984", - "company_id": 0, - "name": "\u9650\u65f6\u7279\u60e0", - "url": "\/marketing\/promotion\/limitedtimesale", - "sort": 4, - "is_menu": true, - "pid": "10980", - "apis": "Promotions.seckill.add\nPromotions.seckill.delete\nPromotions.seckill.update\nPromotions.seckill.list\nPromotions.seckill.info\nPromotions.seckill.statusupdate\nPromotions.seckill.item.list\nshipping.templates.list\ncurrency.get.default\nwechat.material.list\ngoods.items.lists\nPromotions.seckill.wxcode\nPromotions.seckill.search.item.list", - "icon": null, - "is_show": true, - "alias_name": "limitedtimesale", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4fc3\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10985", - "company_id": 0, - "name": "\u52a0\u4ef7\u8d2d", - "url": "\/marketing\/promotion\/Marketingspluspricebuy", - "sort": 5, - "is_menu": true, - "pid": "10980", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "marketingspluspricebuy", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4fc3\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10986", - "company_id": 0, - "name": "\u7ec4\u5408\u8d2d", - "url": "\/marketing\/promotion\/marketingpackage", - "sort": 5, - "is_menu": true, - "pid": "10980", - "apis": "promotions.package.list.get\npromotions.package.create\npromotions.package.info.get\npromotions.package.cancel\npromotions.package.update", - "icon": null, - "is_show": true, - "alias_name": "marketingpackage", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4fc3\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10987", - "company_id": 0, - "name": "\u4f1a\u5458\u8425\u9500", - "url": "\/marketing\/membermarket", - "sort": 3, - "is_menu": true, - "pid": "10973", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "membermarket", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8425\u9500", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10988", - "company_id": 0, - "name": "\u65b0\u5ba2\u8425\u9500", - "url": "\/marketing\/membermarket\/marketingindex", - "sort": 1, - "is_menu": true, - "pid": "10987", - "apis": "goods.items.lists\npromotions.register.get\nPromotions.register.add\ncard.list\npromotions.register.point.get\nPromotions.register.point.add\nespier.image.list\nespier.image.uploadToken.get\nespier.image.save", - "icon": null, - "is_show": true, - "alias_name": "marketingindex", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10989", - "company_id": 0, - "name": "\u5b9a\u5411\u8425\u9500", - "url": "\/marketing\/membermarket\/specificcrowddiscount", - "sort": 2, - "is_menu": true, - "pid": "10987", - "apis": "specific.crowd.discount.add\nspecific.crowd.discount.update\nspecific.crowd.discount.list\nspecific.crowd.discount.info\nmember.tag.list\nspecific.crowd.discount.loglist", - "icon": null, - "is_show": true, - "alias_name": "SpecificCrowdDiscount", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10990", - "company_id": 0, - "name": "\u4f18\u5148\u8d2d", - "url": "\/marketing\/membermarket\/memberpreference", - "sort": 3, - "is_menu": true, - "pid": "10987", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "memberpreference", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10991", - "company_id": 0, - "name": "\u81ea\u52a8\u5316\u8425\u9500", - "url": "\/marketing\/membermarket\/marketingactivity", - "sort": 4, - "is_menu": true, - "pid": "10987", - "apis": "promotions.activity.lists\npromotions.activity.validNum\nmembercard.grade.list\npromotions.activity.create\npromotions.activity.invalid\ngoods.items.lists\ncard.list\nmembercard.vipgrade.list", - "icon": null, - "is_show": true, - "alias_name": "marketingactivity", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10992", - "company_id": 0, - "name": "\u5546\u54c1\u63a8\u8350", - "url": "\/marketing\/membermarket\/recommendlike", - "sort": 5, - "is_menu": true, - "pid": "10987", - "apis": "recommendlike.list\nrecommendlike.update\nrecommendlike.list\nrecommendlike.save\nrecommendlike.delete\ngoods.items.lists", - "icon": null, - "is_show": true, - "alias_name": "recommendlike", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4f1a\u5458\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10993", - "company_id": 0, - "name": "\u88c2\u53d8\u8425\u9500", - "url": "\/marketing\/fissionmarketing", - "sort": 4, - "is_menu": true, - "pid": "10973", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "fissionmarketing", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8425\u9500", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10994", - "company_id": 0, - "name": "\u62fc\u56e2", - "url": "\/marketing\/fissionmarketing\/groupsindex", - "sort": 1, - "is_menu": true, - "pid": "10993", - "apis": "promotions.groups.list\npromotions.groups.detail\npromotions.groups.teamlist\npromotions.groups.teaminfo\npromotions.groups.create\npromotions.groups.update\npromotions.groups.finish\npromotions.groups.delete\ngoods.items.lists\norder.info.get\nmember.info\nwechat.material.upload\ncurrency.get.default", - "icon": null, - "is_show": true, - "alias_name": "groupsindex", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u88c2\u53d8\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10995", - "company_id": 0, - "name": "\u5fae\u4fe1\u52a9\u529b", - "url": "\/marketing\/fissionmarketing\/marketingbargain", - "sort": 2, - "is_menu": true, - "pid": "10993", - "apis": "Promotions.bargains.add\nPromotions.bargains.update\nPromotions.bargains.list\nPromotions.bargains.detail\nPromotions.bargains.terminate\nPromotions.bargains.update\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.material.list\nwechat.material.upload", - "icon": null, - "is_show": true, - "alias_name": "marketingbargain", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u88c2\u53d8\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "standard", - "b2c", - "platform" - ] - }, - { - "shopmenu_id": "10996", - "company_id": 0, - "name": "\u5206\u9500\u63a8\u5e7f", - "url": "\/marketing\/popularize", - "sort": 15, - "is_menu": true, - "pid": "10973", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "popularize", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8425\u9500", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10997", - "company_id": 0, - "name": "\u57fa\u7840\u8bbe\u7f6e", - "url": "\/marketing\/popularize\/popularizesetting", - "sort": 1, - "is_menu": true, - "pid": "10996", - "apis": "popularize.config.get\npopularize.config.set", - "icon": null, - "is_show": true, - "alias_name": "popularizesetting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u9500\u63a8\u5e7f", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10998", - "company_id": 0, - "name": "\u63a8\u5e7f\u5458\u7ba1\u7406", - "url": "\/marketing\/popularize\/popularizelist", - "sort": 2, - "is_menu": true, - "pid": "10996", - "apis": "popularize.brokerage.count\npopularize.brokerage.logs\npopularize.promoter.children.list\npopularize.promoter.list.get\npopularize.promoter.remove\npopularize.promoter.grade.put\npopularize.promoter.disabled\npopularize.promoter.config.get\npopularize.promoter.add\npopularize.promoter.shop.update", - "icon": null, - "is_show": true, - "alias_name": "popularizelist", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u9500\u63a8\u5e7f", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "10999", - "company_id": 0, - "name": "\u7b49\u7ea7\u7ba1\u7406", - "url": "\/marketing\/popularize\/promotersetting", - "sort": 3, - "is_menu": true, - "pid": "10996", - "apis": "popularize.promoter.config.get\npopularize.promoter.config.set", - "icon": null, - "is_show": true, - "alias_name": "promotersetting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u9500\u63a8\u5e7f", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11000", - "company_id": 0, - "name": "\u63a8\u5e7f\u5458\u4e1a\u7ee9", - "url": "\/marketing\/popularize\/popularizedata", - "sort": 4, - "is_menu": true, - "pid": "10996", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "popularizedata", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u9500\u63a8\u5e7f", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11001", - "company_id": 0, - "name": "\u63d0\u73b0\u7533\u8bf7", - "url": "\/marketing\/popularize\/popularizewithdraw", - "sort": 5, - "is_menu": true, - "pid": "10996", - "apis": "popularize.cash_withdrawals.list.get\npopularize.cash_withdrawals.process\npopularize.cash_withdrawals.pay.list.get\npopularize.brokerage.count", - "icon": "money-check-alt", - "is_show": true, - "alias_name": "popularizewithdraw", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u9500\u63a8\u5e7f", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11002", - "company_id": 0, - "name": "\u5206\u9500\u5546\u54c1", - "url": "\/marketing\/popularize\/popularizegoods", - "sort": 6, - "is_menu": true, - "pid": "10996", - "apis": "goods.rebateconf", - "icon": null, - "is_show": true, - "alias_name": "popularizegoods", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u9500\u63a8\u5e7f", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11003", - "company_id": 0, - "name": "\u4efb\u52a1\u4f63\u91d1\u660e\u7ec6", - "url": "\/marketing\/popularize\/taskbrokerage", - "sort": 7, - "is_menu": true, - "pid": "10996", - "apis": "popularize.task.brokerage.logs", - "icon": null, - "is_show": true, - "alias_name": "taskbrokerage", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u9500\u63a8\u5e7f", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11004", - "company_id": 0, - "name": "\u4efb\u52a1\u4f63\u91d1\u7edf\u8ba1", - "url": "\/marketing\/popularize\/taskbrokeragecount", - "sort": 8, - "is_menu": true, - "pid": "10996", - "apis": "popularize.task.brokerage.count\npopularize.task.brokerage.count.export", - "icon": null, - "is_show": true, - "alias_name": "taskbrokeragecount", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u9500\u63a8\u5e7f", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11006", - "company_id": 0, - "name": "\u5c0f\u7a0b\u5e8f\u76f4\u64ad", - "url": "\/marketing\/liveroomlist", - "sort": 21, - "is_menu": true, - "pid": "10973", - "apis": "promotions.liverooms", - "icon": null, - "is_show": true, - "alias_name": "liveroomlist", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11007", - "company_id": 0, - "name": "\u6d3b\u52a8\u62a5\u540d", - "url": "\/marketing\/marketing\/apply", - "sort": 23, - "is_menu": true, - "pid": "10973", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "apply", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8425\u9500", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11008", - "company_id": 0, - "name": "\u5168\u90e8\u6d3b\u52a8", - "url": "\/marketing\/marketing\/apply\/registrationactivity", - "sort": 0, - "is_menu": true, - "pid": "11007", - "apis": "selfhelp.registrationActivity.list\nselfhelp.registrationActivity.add\nselfhelp.template.info\nselfhelp.template.delete", - "icon": null, - "is_show": true, - "alias_name": "Registrationactivity", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u6d3b\u52a8\u62a5\u540d", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11009", - "company_id": 0, - "name": "\u62a5\u540d\u8bb0\u5f55", - "url": "\/marketing\/marketing\/apply\/Registrationrecord", - "sort": 1, - "is_menu": true, - "pid": "11007", - "apis": "selfhelp.registrationRecord.list\nselfhelp.registrationRecord.export\nselfhelp.registrationRecord.info", - "icon": null, - "is_show": true, - "alias_name": "Registrationrecord", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u6d3b\u52a8\u62a5\u540d", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "standard", - "platform" - ] - }, - { - "shopmenu_id": "11010", - "company_id": 0, - "name": "\u8868\u5355\u5143\u7d20", - "url": "\/marketing\/marketing\/apply\/formattrs", - "sort": 1, - "is_menu": true, - "pid": "11007", - "apis": "selfhelp.form.list", - "icon": null, - "is_show": true, - "alias_name": "formattrs", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u6d3b\u52a8\u62a5\u540d", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11011", - "company_id": 0, - "name": "\u8868\u5355\u6a21\u677f", - "url": "\/marketing\/marketing\/apply\/formtemplate", - "sort": 1, - "is_menu": true, - "pid": "11007", - "apis": "selfhelp.template.list\nselfhelp.template.info\nselfhelp.template.delete", - "icon": null, - "is_show": true, - "alias_name": "formtemplate", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u6d3b\u52a8\u62a5\u540d", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11161", - "company_id": 0, - "name": "\u5927\u8f6c\u76d8", - "url": "\/marketing\/wheel", - "sort": 30, - "is_menu": true, - "pid": "10973", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "wheel", - "version": 1, - "disabled": false, - "created": 1744090864, - "updated": 1744090864, - "level": 2, - "parent_name": "\u8425\u9500", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11012", - "company_id": 0, - "name": "\u5185\u5bb9", - "url": "\/site", - "sort": 7, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "newspaper1", - "is_show": true, - "alias_name": "site", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all", - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11013", - "company_id": 0, - "name": "\u8f6f\u6587", - "url": "\/site\/article", - "sort": 1, - "is_menu": true, - "pid": "11012", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "article", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5185\u5bb9", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11014", - "company_id": 0, - "name": "\u8f6f\u6587\u5217\u8868", - "url": "\/site\/article\/planting", - "sort": 1, - "is_menu": true, - "pid": "11013", - "apis": "article.create\narticle.update\narticle.delete\narticle.list\narticle.info\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\narticle.update.sortstatus\narticle.list.category", - "icon": null, - "is_show": true, - "alias_name": "planting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8f6f\u6587", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11015", - "company_id": 0, - "name": "\u8f6f\u6587\u9891\u9053", - "url": "\/site\/article\/articlecolumns", - "sort": 2, - "is_menu": true, - "pid": "11013", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "articlecolumns", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u8f6f\u6587", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11029", - "company_id": 0, - "name": "\u7d20\u6750", - "url": "\/site\/material", - "sort": 1, - "is_menu": true, - "pid": "11012", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "material", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5185\u5bb9", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11030", - "company_id": 0, - "name": "\u7d20\u6750\u7ba1\u7406", - "url": "\/site\/material\/brandmaterial", - "sort": 1, - "is_menu": true, - "pid": "11029", - "apis": "espier.oss.uploadToken.get\nespier.image.save", - "icon": null, - "is_show": true, - "alias_name": "brandmaterial", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1745221948, - "level": 3, - "parent_name": "\u7d20\u6750", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11016", - "company_id": 0, - "name": "\u6587\u7ae0", - "url": "\/site\/text", - "sort": 2, - "is_menu": true, - "pid": "11012", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "text", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5185\u5bb9", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11017", - "company_id": 0, - "name": "\u6587\u7ae0\u5217\u8868", - "url": "\/site\/text\/basearticle", - "sort": 1, - "is_menu": true, - "pid": "11016", - "apis": "article.create\narticle.update\narticle.delete\narticle.list\narticle.info\nwechat.material.list\nwechat.material.upload", - "icon": null, - "is_show": true, - "alias_name": "basearticle", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u6587\u7ae0", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11018", - "company_id": 0, - "name": "\u6587\u7ae0\u5206\u7c7b", - "url": "\/site\/text\/articlegeneralcolumns", - "sort": 2, - "is_menu": true, - "pid": "11016", - "apis": "article.create.category\narticle.delete.category", - "icon": null, - "is_show": true, - "alias_name": "Articlegeneralcolumns", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u6587\u7ae0", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11019", - "company_id": 0, - "name": "UGC\u793e\u533a", - "url": "\/site\/ugc", - "sort": 3, - "is_menu": true, - "pid": "11012", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "ugc", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5185\u5bb9", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11020", - "company_id": 0, - "name": "\u7b14\u8bb0\u7ba1\u7406", - "url": "\/site\/ugc\/ugcindex", - "sort": 1, - "is_menu": true, - "pid": "11019", - "apis": "ugc.post.list\nugc.badge.list\nugc.setting.point.getSetting\nugc.post.list\nugc.comment.list", - "icon": null, - "is_show": true, - "alias_name": "ugcindex", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "UGC\u793e\u533a", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11021", - "company_id": 0, - "name": "\u89d2\u6807\u7ba1\u7406", - "url": "\/site\/ugc\/ugcflags", - "sort": 2, - "is_menu": true, - "pid": "11019", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "ugcflags", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "UGC\u793e\u533a", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11022", - "company_id": 0, - "name": "\u7b14\u8bb0\u8bdd\u9898", - "url": "\/site\/ugc\/ugctopic", - "sort": 3, - "is_menu": true, - "pid": "11019", - "apis": "ugc.topic.list", - "icon": null, - "is_show": true, - "alias_name": "ugctopic", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "UGC\u793e\u533a", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11023", - "company_id": 0, - "name": "\u7b14\u8bb0\u8bc4\u8bba", - "url": "\/site\/ugc\/ugcreview", - "sort": 4, - "is_menu": true, - "pid": "11019", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "ugcreview", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "UGC\u793e\u533a", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11024", - "company_id": 0, - "name": "\u8bc4\u8bba\u8bbe\u7f6e", - "url": "\/site\/ugc\/ugcpoint", - "sort": 5, - "is_menu": true, - "pid": "11019", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "ugcpoint", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "UGC\u793e\u533a", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11025", - "company_id": 0, - "name": "\u5206\u4eab\u8f6c\u53d1", - "url": "\/site\/share", - "sort": 4, - "is_menu": true, - "pid": "11012", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "share", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5185\u5bb9", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11026", - "company_id": 0, - "name": "\u5206\u4eab\u8bbe\u7f6e", - "url": "\/site\/share\/sharesetting", - "sort": 1, - "is_menu": true, - "pid": "11025", - "apis": "share.setting.set\nshare.setting.get", - "icon": null, - "is_show": true, - "alias_name": "sharesetting", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u5206\u4eab\u8f6c\u53d1", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11027", - "company_id": 0, - "name": "\u7528\u6237\u8bc4\u4ef7", - "url": "\/site\/evaluate", - "sort": 5, - "is_menu": true, - "pid": "11012", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "evaluate", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u5185\u5bb9", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11028", - "company_id": 0, - "name": "\u5546\u54c1\u8bc4\u4ef7", - "url": "\/site\/evaluate\/rate", - "sort": 1, - "is_menu": true, - "pid": "11027", - "apis": "traderate.list.get", - "icon": null, - "is_show": true, - "alias_name": "rate", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1744339304, - "level": 3, - "parent_name": "\u7528\u6237\u8bc4\u4ef7", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11031", - "company_id": 0, - "name": "\u8d22\u52a1", - "url": "\/financial", - "sort": 8, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "money-check-alt", - "is_show": true, - "alias_name": "financial", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11032", - "company_id": 0, - "name": "\u4ea4\u6613\u6d41\u6c34", - "url": "\/financial\/financialManage", - "sort": 1, - "is_menu": true, - "pid": "11031", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "financialManage", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 2, - "parent_name": "\u8d22\u52a1", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11033", - "company_id": 0, - "name": "\u4ea4\u6613\u5355", - "url": "\/financial\/financialManage\/servicepayment", - "sort": 1, - "is_menu": true, - "pid": "11032", - "apis": "shops.lists\norder.trade.list\ntrades.list.export", - "icon": null, - "is_show": true, - "alias_name": "financialManageservicepayment", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4ea4\u6613\u6d41\u6c34", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11034", - "company_id": 0, - "name": "\u9000\u6b3e\u5355", - "url": "\/financial\/financialManage\/aftersalesrefundlist", - "sort": 2, - "is_menu": true, - "pid": "11032", - "apis": "refund.list\nrefund.logexport", - "icon": null, - "is_show": true, - "alias_name": "financialFinancialManageAftersalesrefundlist", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4ea4\u6613\u6d41\u6c34", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11035", - "company_id": 0, - "name": "\u9000\u6b3e\u5931\u8d25", - "url": "\/financial\/financialManage\/Refunderrorlogs", - "sort": 3, - "is_menu": true, - "pid": "11032", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "Refunderrorlogs", - "version": 1, - "disabled": false, - "created": 1742899516, - "updated": 1742899516, - "level": 3, - "parent_name": "\u4ea4\u6613\u6d41\u6c34", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11036", - "company_id": 0, - "name": "\u7ed3\u7b97", - "url": "\/financial\/settlement", - "sort": 1, - "is_menu": true, - "pid": "11031", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "settlement", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u8d22\u52a1", - "isChildrenMenu": true, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "11037", - "company_id": 0, - "name": "\u7ed3\u7b97\u6c47\u603b", - "url": "\/financial\/settlement\/summary", - "sort": 1, - "is_menu": true, - "pid": "11036", - "apis": "merchant.list\nstatement.summarized.get\nstatement.confirm.post\nstatement.detail.get\nstatement.summarized.export\nstatement.detail.export", - "icon": null, - "is_show": true, - "alias_name": "summary", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7ed3\u7b97", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "11038", - "company_id": 0, - "name": "\u7ed3\u7b97\u914d\u7f6e", - "url": "\/financial\/settlement\/configure", - "sort": 1, - "is_menu": true, - "pid": "11036", - "apis": "statement.period.default.setting.get\nstatement.period.distributor.setting.get\nstatement.period.setting.set", - "icon": null, - "is_show": true, - "alias_name": "configure", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7ed3\u7b97", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "11164", - "company_id": 0, - "name": "\u4f9b\u5e94\u5546\u7ed3\u7b97", - "url": "\/financial\/settlement_supplier", - "sort": 1, - "is_menu": true, - "pid": "11031", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "settlement_supplier", - "version": 1, - "disabled": false, - "created": 1749114541, - "updated": 1749114541, - "level": 2, - "parent_name": "\u8d22\u52a1", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11165", - "company_id": 0, - "name": "\u4f9b\u5e94\u5546\u7ed3\u7b97\u914d\u7f6e", - "url": "\/financial\/settlement_supplier\/configure_supplier", - "sort": 1, - "is_menu": true, - "pid": "11164", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "configure_supplier", - "version": 1, - "disabled": false, - "created": 1749114561, - "updated": 1749114561, - "level": 3, - "parent_name": "\u4f9b\u5e94\u5546\u7ed3\u7b97", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11166", - "company_id": 0, - "name": "\u4f9b\u5e94\u5546\u7ed3\u7b97\u6c47\u603b", - "url": "\/financial\/settlement_supplier\/summary_supplier", - "sort": 1, - "is_menu": true, - "pid": "11164", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "summary_supplier", - "version": 1, - "disabled": false, - "created": 1749114583, - "updated": 1749114583, - "level": 3, - "parent_name": "\u4f9b\u5e94\u5546\u7ed3\u7b97", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11039", - "company_id": 0, - "name": "\u7ebf\u4e0b\u8f6c\u8d26", - "url": "\/financial\/examine", - "sort": 2, - "is_menu": true, - "pid": "11031", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "examine", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u8d22\u52a1", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11040", - "company_id": 0, - "name": "\u8f6c\u8d26\u51ed\u8bc1\u5ba1\u6838", - "url": "\/financial\/examine\/transfer", - "sort": 1, - "is_menu": true, - "pid": "11039", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "transfer", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7ebf\u4e0b\u8f6c\u8d26", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11041", - "company_id": 0, - "name": "\u6570\u636e", - "url": "\/companydata", - "sort": 9, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "poll", - "is_show": true, - "alias_name": "companydata", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11042", - "company_id": 0, - "name": "\u7edf\u8ba1", - "url": "\/companydata\/statistics", - "sort": 1, - "is_menu": true, - "pid": "11041", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "statistics", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u6570\u636e", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11043", - "company_id": 0, - "name": "\u5546\u54c1\u7edf\u8ba1", - "url": "\/companydata\/statistics\/goodsstatistics", - "sort": 1, - "is_menu": true, - "pid": "11042", - "apis": "datacube.goods.data\norder.delivervstaff.confirm", - "icon": null, - "is_show": true, - "alias_name": "goodsstatistics", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7edf\u8ba1", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11044", - "company_id": 0, - "name": "\u4ea4\u6613\u7edf\u8ba1", - "url": "\/companydata\/statistics\/orderstatistics", - "sort": 2, - "is_menu": true, - "pid": "11042", - "apis": "datacube.company.data", - "icon": null, - "is_show": true, - "alias_name": "orderstatistics", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7edf\u8ba1", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11045", - "company_id": 0, - "name": "\u4f1a\u5458\u7edf\u8ba1", - "url": "\/companydata\/statistics\/memberstatistics", - "sort": 3, - "is_menu": true, - "pid": "11042", - "apis": "datacube.company.data", - "icon": null, - "is_show": true, - "alias_name": "member-statistics", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7edf\u8ba1", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11046", - "company_id": 0, - "name": "\u5e97\u94fa\u7edf\u8ba1", - "url": "\/companydata\/statistics\/distributordata", - "sort": 4, - "is_menu": true, - "pid": "11042", - "apis": "datacube.distributor.data", - "icon": null, - "is_show": true, - "alias_name": "distributordata", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7edf\u8ba1", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11047", - "company_id": 0, - "name": "\u62a5\u8868", - "url": "\/companydata\/report", - "sort": 2, - "is_menu": true, - "pid": "11041", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "report", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u6570\u636e", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11048", - "company_id": 0, - "name": "\u5bfc\u51fa\u8bb0\u5f55", - "url": "\/companydata\/report\/baseexport", - "sort": 1, - "is_menu": true, - "pid": "11047", - "apis": "espier.export.loglist\nespier.export.file.down", - "icon": null, - "is_show": true, - "alias_name": "baseexport", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1744350509, - "level": 3, - "parent_name": "\u62a5\u8868", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11049", - "company_id": 0, - "name": "\u88c5\u4fee", - "url": "\/wxapp", - "sort": 11, - "is_menu": true, - "pid": "0", - "apis": "wechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list\nwechat.pre_auth_url\nwechat.wxa.testqrcode\nwechat.wxa.tryrelease\nwechat.bind", - "icon": "brush-copy", - "is_show": true, - "alias_name": "wxapp-template", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11050", - "company_id": 0, - "name": "\u79fb\u52a8\u5546\u57ce", - "url": "\/wxapp\/manage", - "sort": 1, - "is_menu": true, - "pid": "11049", - "apis": "wechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list\nwechat.pre_auth_url\nwechat.wxa.testqrcode\nwechat.wxa.tryrelease\nwechat.bind\npagestemplateset.set\npagestemplateset.getInfo\npagestemplate.lists\npagestemplate.add\npagestemplate.edit\npagestemplate.detail\npagestemplate.copy\npagestemplate.delete\npagestemplate.modifyStatus\npagestemplate.sync\nmemberCenterShare.set\nmemberCenterShare.getInfo\nwechat.wxa.revertcoderelease", - "icon": null, - "is_show": true, - "alias_name": "wxappmanage", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u88c5\u4fee", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11051", - "company_id": 0, - "name": "\u9996\u9875", - "url": "\/wxapp\/manage\/templateedit", - "sort": 1, - "is_menu": true, - "pid": "11050", - "apis": "wechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list\nwechat.pre_auth_url\nwechat.wxa.testqrcode\nwechat.wxa.tryrelease\nwechat.bind\nwechat.wxa.customizepage.list\nrecommendlike.list\npagestemplate.lists\npagestemplateset.getInfo\npagestemplate.modifyStatus\npagestemplateset.set\npagestemplate.copy\npagestemplate.delete\npagestemplate.edit\npagestemplate.add\nwxexternalconfigroutes.list\nwxexternalconfig.list\ngoods.sku.lists\nselfhelp.registrationActivity.easylist\npagestemplate.sync\nselfhelp.registrationActivity.easylist", - "icon": null, - "is_show": true, - "alias_name": "wxapp-template-edit", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1744185031, - "level": 3, - "parent_name": "\u79fb\u52a8\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11052", - "company_id": 0, - "name": "\u9644\u8fd1\u5e97\u94fa\u9875", - "url": "\/wxapp\/manage\/classificationTemplate", - "sort": 2, - "is_menu": true, - "pid": "11050", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "classificationTemplate", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79fb\u52a8\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11053", - "company_id": 0, - "name": "\u5206\u7c7b\u9875", - "url": "\/wxapp\/manage\/editcategory", - "sort": 2, - "is_menu": true, - "pid": "11050", - "apis": "wechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list", - "icon": null, - "is_show": true, - "alias_name": "wxapp-editcategory", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79fb\u52a8\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11054", - "company_id": 0, - "name": "\u81ea\u5b9a\u4e49\u9875", - "url": "\/wxapp\/manage\/custompage", - "sort": 3, - "is_menu": true, - "pid": "11050", - "apis": "wechat.wxa.customizepage.update\nwechat.wxa.customizepage.delete\nwechat.wxa.customizepage.add\nwechat.wxa.customizepage.list\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list\nwechat.pre_auth_url\nwechat.wxa.testqrcode\nwechat.wxa.tryrelease\nwechat.bind\nwechat.wxa.customizepage.update\nwechat.wxa.customizepage.delete\nwechat.wxa.customizepage.add\nwechat.wxa.customizepage.list\n", - "icon": null, - "is_show": true, - "alias_name": "wxapp-custompage", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79fb\u52a8\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11055", - "company_id": 0, - "name": "\u5546\u57ce\u914d\u8272", - "url": "\/wxapp\/manage\/colorstyle", - "sort": 5, - "is_menu": true, - "pid": "11050", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "colorstyle", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79fb\u52a8\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11056", - "company_id": 0, - "name": "\u4f1a\u5458\u4e2d\u5fc3", - "url": "\/wxapp\/manage\/membercentersetting", - "sort": 6, - "is_menu": true, - "pid": "11050", - "apis": "memberCenterShare.set\nmemberCenterShare.update\nmemberCenterShare.getInfo\ndistributor.info", - "icon": null, - "is_show": true, - "alias_name": "membercentersetting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79fb\u52a8\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11057", - "company_id": 0, - "name": "\u5546\u57ce\u4fe1\u606f", - "url": "\/wxapp\/manage\/wxshopsetting", - "sort": 6, - "is_menu": true, - "pid": "11050", - "apis": "shops.setting.get\nshops.setting.set", - "icon": null, - "is_show": true, - "alias_name": "wxshopsetting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79fb\u52a8\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11058", - "company_id": 0, - "name": "\u5f00\u5c4f\u5e7f\u544a", - "url": "\/wxapp\/manage\/openscreenad", - "sort": 8, - "is_menu": true, - "pid": "11050", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "openscreenad", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79fb\u52a8\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11059", - "company_id": 0, - "name": "PC\u5546\u57ce", - "url": "\/wxapp\/pcmall", - "sort": 2, - "is_menu": true, - "pid": "11049", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "pcmall", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u88c5\u4fee", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11060", - "company_id": 0, - "name": "\u6a21\u677f\u5217\u8868", - "url": "\/wxapp\/pcmall\/templatelist", - "sort": 1, - "is_menu": true, - "pid": "11059", - "apis": "pctemplate.lists\npctemplate.edit\npctemplate.getHeaderOrFooter\npctemplate.getTemplateContent\npctemplate.saveTemplateContent\npctemplate.saveHeaderOrFooter\npagestemplate.detail", - "icon": null, - "is_show": true, - "alias_name": "templatelist", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "PC\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11061", - "company_id": 0, - "name": "\u6a21\u677f\u7f16\u8f91", - "url": "\/wxapp\/pcmall\/design", - "sort": 2, - "is_menu": false, - "pid": "11059", - "apis": "pctemplate.getHeaderOrFooter\npctemplate.getTemplateContent\npctemplate.saveTemplateContent\npctemplate.saveHeaderOrFooter\npagestemplate.detail", - "icon": null, - "is_show": true, - "alias_name": "design", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "PC\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11062", - "company_id": 0, - "name": "\u767b\u5f55\u9875", - "url": "\/wxapp\/pcmall\/loginPageSetting", - "sort": 2, - "is_menu": true, - "pid": "11059", - "apis": "pctemplate.getLoginPageSetting", - "icon": null, - "is_show": true, - "alias_name": "loginPageSetting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "PC\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11063", - "company_id": 0, - "name": "SEO\u914d\u7f6e", - "url": "\/wxapp\/pcmall\/seo", - "sort": 3, - "is_menu": true, - "pid": "11059", - "apis": "pcdecoration.tdkglobalset.info\npcdecoration.tdkglobalset.save", - "icon": null, - "is_show": true, - "alias_name": "seo", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "PC\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11064", - "company_id": 0, - "name": "\u9875\u9762SEO", - "url": "\/wxapp\/pcmall\/pageseo", - "sort": 4, - "is_menu": true, - "pid": "11059", - "apis": "pcdecoration.tdkgivenset.info\npcdecoration.tdkgivenset.save", - "icon": null, - "is_show": true, - "alias_name": "pageseo", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "PC\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11065", - "company_id": 0, - "name": "\u5e94\u7528", - "url": "\/applications", - "sort": 12, - "is_menu": true, - "pid": "0", - "apis": "adapay.open_account.step\npointsmall.goods.items.lists\nadapay.open_account.step\nadapay.regions.list\nadapay.regions.list", - "icon": "yingyong-01", - "is_show": true, - "alias_name": "applications", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11066", - "company_id": 0, - "name": "\u6597\u62f1\u5206\u8d26", - "url": "\/applications\/bspay", - "sort": 1, - "is_menu": true, - "pid": "11065", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "bspay", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u5e94\u7528", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11067", - "company_id": 0, - "name": "\u7528\u6237\u8fdb\u4ef6\u5ba1\u6279", - "url": "\/applications\/bspay\/user_audit", - "sort": 1, - "is_menu": true, - "pid": "11066", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "user_audit", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u6597\u62f1\u5206\u8d26", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11068", - "company_id": 0, - "name": "\u5206\u8d26\u660e\u7ec6", - "url": "\/applications\/bspay\/trades", - "sort": 1, - "is_menu": true, - "pid": "11066", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "bspay_trades", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u6597\u62f1\u5206\u8d26", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11074", - "company_id": 0, - "name": "Adapay\u5206\u8d26", - "url": "\/applications\/adapay", - "sort": 2, - "is_menu": true, - "pid": "11065", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "adapay", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u5e94\u7528", - "isChildrenMenu": true, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11075", - "company_id": 0, - "name": "\u5206\u8d26\u660e\u7ec6", - "url": "\/applications\/adapay\/adapay_trades", - "sort": 1, - "is_menu": true, - "pid": "11074", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "adapay_trades", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "Adapay\u5206\u8d26", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11076", - "company_id": 0, - "name": "\u63d0\u73b0", - "url": "\/applications\/adapay\/adapay_cash", - "sort": 2, - "is_menu": true, - "pid": "11074", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "adapay_cash", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "Adapay\u5206\u8d26", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11077", - "company_id": 0, - "name": "\u63d0\u73b0\u8bbe\u7f6e", - "url": "\/applications\/adapay\/adapay_cash_setting", - "sort": 3, - "is_menu": true, - "pid": "11074", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "adapay_cash_setting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "Adapay\u5206\u8d26", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11078", - "company_id": 0, - "name": "\u5f00\u6237\u5ba1\u6279", - "url": "\/applications\/adapay\/adapay_member_audit", - "sort": 4, - "is_menu": true, - "pid": "11074", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "adapay_member_audit", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "Adapay\u5206\u8d26", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11069", - "company_id": 0, - "name": "\u4f01\u4e1a\u8d2d", - "url": "\/applications\/ec", - "sort": 3, - "is_menu": true, - "pid": "11065", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "ec", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u5e94\u7528", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11072", - "company_id": 0, - "name": "\u4f01\u4e1a\u7ba1\u7406", - "url": "\/applications\/ec\/company", - "sort": 1, - "is_menu": true, - "pid": "11069", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "company-admin", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u4f01\u4e1a\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11071", - "company_id": 0, - "name": "\u5458\u5de5\u7ba1\u7406", - "url": "\/applications\/ec\/employee", - "sort": 2, - "is_menu": true, - "pid": "11069", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "employee-admin", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1743054593, - "level": 3, - "parent_name": "\u4f01\u4e1a\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11070", - "company_id": 0, - "name": "\u6d3b\u52a8\u7ba1\u7406", - "url": "\/applications\/ec\/purchaseactivity", - "sort": 3, - "is_menu": true, - "pid": "11069", - "apis": "promotions.employeepurchase.list\npromotions.employeepurchase.info\npromotions.employeepurchase.add\npromotions.employeepurchase.update\nespier.upload.template.export\nespier.upload\npromotions.employeepurchase.endactivity\npromotions.employeepurchase.dependents.lists\npromotions.employeepurchase.dependents.export", - "icon": null, - "is_show": true, - "alias_name": "purchase-admin", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u4f01\u4e1a\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11073", - "company_id": 0, - "name": "\u8ba2\u5355\u7ba1\u7406", - "url": "\/applications\/ec\/purchaseorder", - "sort": 4, - "is_menu": true, - "pid": "11069", - "apis": "order.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel", - "icon": null, - "is_show": true, - "alias_name": "purchase-list", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u4f01\u4e1a\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11083", - "company_id": 0, - "name": "\u5bfc\u8d2d\u52a9\u624b", - "url": "\/applications\/guide", - "sort": 4, - "is_menu": true, - "pid": "11065", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "guide", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u5e94\u7528", - "isChildrenMenu": true, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "11084", - "company_id": 0, - "name": "\u4f01\u4e1a\u5fae\u4fe1\u8bbe\u7f6e", - "url": "\/applications\/guide\/workwechat", - "sort": 1, - "is_menu": true, - "pid": "11083", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "workwechat", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u5bfc\u8d2d\u52a9\u624b", - "isChildrenMenu": false, - "menu_type": [ - "standard" - ] - }, - { - "shopmenu_id": "11132", - "company_id": 0, - "name": "\u793e\u533a\u56e2\u8d2d", - "url": "\/applications\/community", - "sort": 5, - "is_menu": true, - "pid": "11065", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "community", - "version": 1, - "disabled": false, - "created": 1742958789, - "updated": 1742958789, - "level": 2, - "parent_name": "\u5e94\u7528", - "isChildrenMenu": true, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11133", - "company_id": 0, - "name": "\u6d3b\u52a8\u7ba1\u7406", - "url": "\/applications\/community\/activity", - "sort": 2, - "is_menu": true, - "pid": "11132", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "activity", - "version": 1, - "disabled": false, - "created": 1742959236, - "updated": 1742959236, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11134", - "company_id": 0, - "name": "\u6d3b\u52a8\u5546\u54c1", - "url": "\/applications\/community\/communitygoods", - "sort": 3, - "is_menu": true, - "pid": "11132", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "communitygoods", - "version": 1, - "disabled": false, - "created": 1742959268, - "updated": 1742959268, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11135", - "company_id": 0, - "name": "\u6d3b\u52a8\u8ba2\u5355", - "url": "\/applications\/community\/order", - "sort": 3, - "is_menu": true, - "pid": "11132", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "communityorder", - "version": 1, - "disabled": false, - "created": 1742959422, - "updated": 1742959422, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11136", - "company_id": 0, - "name": "\u6d3b\u52a8\u914d\u7f6e", - "url": "\/applications\/community\/setting", - "sort": 4, - "is_menu": true, - "pid": "11132", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "communitysetting", - "version": 1, - "disabled": false, - "created": 1742959496, - "updated": 1742959496, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11137", - "company_id": 0, - "name": "\u793e\u533a\u7ba1\u7406", - "url": "\/applications\/community\/subdistrict", - "sort": 5, - "is_menu": true, - "pid": "11132", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "subdistrict", - "version": 1, - "disabled": false, - "created": 1742959536, - "updated": 1742959536, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11138", - "company_id": 0, - "name": "\u56e2\u957f\u7ba1\u7406", - "url": "\/applications\/community\/chief", - "sort": 6, - "is_menu": true, - "pid": "11132", - "apis": "community.setting.chief\ncommunity.chief.apply.list\ncommunity.chief.apply.info\ncommunity.chief.approve\ncommunity.chief.list", - "icon": null, - "is_show": true, - "alias_name": "communitychief", - "version": 1, - "disabled": false, - "created": 1742959644, - "updated": 1742961730, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11139", - "company_id": 0, - "name": "\u56e2\u957f\u4e1a\u7ee9", - "url": "\/applications\/community\/achievement", - "sort": 7, - "is_menu": true, - "pid": "11132", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "achievement", - "version": 1, - "disabled": false, - "created": 1742959713, - "updated": 1742959713, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11140", - "company_id": 0, - "name": "\u63d0\u73b0\u7533\u8bf7", - "url": "\/applications\/community\/withdraw", - "sort": 8, - "is_menu": true, - "pid": "11132", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "withdraw", - "version": 1, - "disabled": false, - "created": 1742959776, - "updated": 1742959776, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11141", - "company_id": 0, - "name": "\u56e2\u957f\u5bfc\u5165", - "url": "\/applications\/community\/chiefupload", - "sort": 9, - "is_menu": false, - "pid": "11132", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "chiefupload1", - "version": 1, - "disabled": false, - "created": 1742961792, - "updated": 1742961792, - "level": 3, - "parent_name": "\u793e\u533a\u56e2\u8d2d", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11079", - "company_id": 0, - "name": "\u79ef\u5206\u5546\u57ce", - "url": "\/applications\/jfmall", - "sort": 6, - "is_menu": true, - "pid": "11065", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "jfmall", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u5e94\u7528", - "isChildrenMenu": true, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11080", - "company_id": 0, - "name": "\u5546\u54c1\u7ba1\u7406", - "url": "\/applications\/jfmall\/jfgoods", - "sort": 1, - "is_menu": true, - "pid": "11079", - "apis": "pointsmall.setting.get\npointsmall.goods.items.lists", - "icon": null, - "is_show": true, - "alias_name": "jfgoods", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79ef\u5206\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11081", - "company_id": 0, - "name": "\u8ba2\u5355\u7ba1\u7406", - "url": "\/applications\/jfmall\/jforders", - "sort": 1, - "is_menu": true, - "pid": "11079", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "jforders", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79ef\u5206\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11082", - "company_id": 0, - "name": "\u57fa\u7840\u8bbe\u7f6e", - "url": "\/applications\/jfmall\/jfsetting", - "sort": 1, - "is_menu": true, - "pid": "11079", - "apis": "pointsmall.setting.get", - "icon": null, - "is_show": true, - "alias_name": "jfsetting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u79ef\u5206\u5546\u57ce", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11086", - "company_id": 0, - "name": "\u5e94\u7528\u4e2d\u5fc3", - "url": "\/applications\/appsgroup", - "sort": 100, - "is_menu": true, - "pid": "11065", - "apis": "adapay.open_account.step\nadapay.regions.list\npointsmall.goods.items.lists\nadapay.regions.list\npointsmall.goods.items.lists\nadapay.open_account.step", - "icon": "yingyong-01", - "is_show": true, - "alias_name": "appsgroup", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u5e94\u7528", - "isChildrenMenu": true, - "menu_type": [ - "platform", - "standard", - "b2c" - ] - }, - { - "shopmenu_id": "11087", - "company_id": 0, - "name": "\u6269\u5c55\u5e94\u7528", - "url": "\/applications\/appsgroup\/extapp", - "sort": 1, - "is_menu": true, - "pid": "11086", - "apis": "adapay.is_open", - "icon": null, - "is_show": true, - "alias_name": "extapp", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u5e94\u7528\u4e2d\u5fc3", - "isChildrenMenu": false, - "menu_type": [ - "b2c", - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11088", - "company_id": 0, - "name": "\u8bbe\u7f6e", - "url": "\/setting", - "sort": 13, - "is_menu": true, - "pid": "0", - "apis": "", - "icon": "cog-copy", - "is_show": true, - "alias_name": "setting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 1, - "parent_name": "\u65e0", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11089", - "company_id": 0, - "name": "\u7cfb\u7edf\u8d26\u53f7", - "url": "\/setting\/staff", - "sort": 0, - "is_menu": true, - "pid": "11088", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "staff", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u8bbe\u7f6e", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11090", - "company_id": 0, - "name": "\u5e73\u53f0\u8d26\u53f7", - "url": "\/setting\/staff\/Platformstaff", - "sort": 1, - "is_menu": true, - "pid": "11089", - "apis": "account.create\naccount.list\naccount.info\naccount.update\naccount.delete\nroles.list\naccount.roles.permission\noperator.status.change\ndatacube.deliverystaff.data\norder.delivervstaff.confirm", - "icon": null, - "is_show": true, - "alias_name": "platformstaff", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u8d26\u53f7", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11093", - "company_id": 0, - "name": "\u7cfb\u7edf\u89d2\u8272", - "url": "\/setting\/staff\/Platformstaffroles", - "sort": 2, - "is_menu": true, - "pid": "11089", - "apis": "roles.create\nroles.list\nroles.info\nroles.update\nroles.delete\n", - "icon": null, - "is_show": true, - "alias_name": "platformstaffroles", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u8d26\u53f7", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11091", - "company_id": 0, - "name": "\u5546\u6237\u8d26\u53f7", - "url": "\/setting\/staff\/storemanager", - "sort": 3, - "is_menu": true, - "pid": "11089", - "apis": "merchant.operator.list\nmerchant.operator.update", - "icon": null, - "is_show": true, - "alias_name": "storemanager_account", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u8d26\u53f7", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "11092", - "company_id": 0, - "name": "\u5e97\u94fa\u8d26\u53f7", - "url": "\/setting\/staff\/Merchantstaff", - "sort": 4, - "is_menu": true, - "pid": "11089", - "apis": "account.create\naccount.list\naccount.info\naccount.update\naccount.delete\nroles.list\naccount.roles.permission\nespier.subdistrict.list.get\noperator.status.change", - "icon": null, - "is_show": true, - "alias_name": "merchantstaff", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u8d26\u53f7", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11094", - "company_id": 0, - "name": "\u83dc\u5355\u7ba1\u7406", - "url": "\/setting\/menumanage", - "sort": 1, - "is_menu": true, - "pid": "11088", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "menumanage", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u8bbe\u7f6e", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11095", - "company_id": 0, - "name": "\u5546\u57ce\u83dc\u5355", - "url": "\/setting\/menumanage\/shopmenus", - "sort": 1, - "is_menu": true, - "pid": "11094", - "apis": "super.admin.shopmenu.get\r\nsuper.admin.shopmenu.add\r\nsuper.admin.shopmenu.update\r\nsuper.admin.shopmenu.del", - "icon": null, - "is_show": true, - "alias_name": "shopmenus", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u83dc\u5355\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11096", - "company_id": 0, - "name": "\u5e97\u94fa\u83dc\u5355", - "url": "\/setting\/menumanage\/distributormenu", - "sort": 1, - "is_menu": true, - "pid": "11094", - "apis": "super.admin.shopmenu.get\nsuper.admin.shopmenu.add\nsuper.admin.shopmenu.update\nsuper.admin.shopmenu.del\norders.setting.get ", - "icon": null, - "is_show": true, - "alias_name": "distributormenu", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u83dc\u5355\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11097", - "company_id": 0, - "name": "\u5546\u6237\u83dc\u5355", - "url": "\/setting\/menumanage\/merchantmenu", - "sort": 2, - "is_menu": true, - "pid": "11094", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "merchantmenu", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u83dc\u5355\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "platform" - ] - }, - { - "shopmenu_id": "11098", - "company_id": 0, - "name": "\u4f9b\u5e94\u5546\u83dc\u5355", - "url": "\/setting\/menumanage\/suppliermenus", - "sort": 10, - "is_menu": true, - "pid": "11094", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "suppliermenus", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u83dc\u5355\u7ba1\u7406", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11099", - "company_id": 0, - "name": "\u7cfb\u7edf\u914d\u7f6e", - "url": "\/setting\/systemsetting", - "sort": 2, - "is_menu": true, - "pid": "11088", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "systemsetting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u8bbe\u7f6e", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11100", - "company_id": 0, - "name": "\u901a\u7528\u8bbe\u7f6e", - "url": "\/setting\/systemsetting\/publicsetting", - "sort": 1, - "is_menu": true, - "pid": "11099", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "publicsetting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11101", - "company_id": 0, - "name": "\u652f\u4ed8\u914d\u7f6e", - "url": "\/setting\/systemsetting\/assetpayment", - "sort": 2, - "is_menu": true, - "pid": "11099", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "assetpayment", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11102", - "company_id": 0, - "name": "\u77ed\u4fe1\u670d\u52a1", - "url": "\/setting\/systemsetting\/datamessage", - "sort": 3, - "is_menu": true, - "pid": "11099", - "apis": "Promotions.sms.basic\nPromotions.sms.templates.list\nPromotions.sms.template.up\nPromotions.sms.sign.get\nPromotions.sms.sign.save\naliyunsms.status.get\naliyunsms.config.get\naliyunsms.scene.getList\naliyunsms.sign.getList\naliyunsms.tmpl.getList\naliyunsms.record.getList\naliyunsms.task.list", - "icon": null, - "is_show": true, - "alias_name": "datamessage", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11104", - "company_id": 0, - "name": "\u5c0f\u7968\u6253\u5370", - "url": "\/setting\/systemsetting\/Yilianyun", - "sort": 5, - "is_menu": true, - "pid": "11099", - "apis": "espier.printer.info\nespier.printer.shop.list\norder.delivervstaff.confirm\norder.deliverypackag.confirm", - "icon": null, - "is_show": true, - "alias_name": "Yilianyun", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11105", - "company_id": 0, - "name": "UGC\u5ba1\u6838\u914d\u7f6e", - "url": "\/setting\/systemsetting\/ugctpos", - "sort": 6, - "is_menu": true, - "pid": "11099", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "ugctpos", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11106", - "company_id": 0, - "name": "\u5c0f\u7a0b\u5e8f\u7ba1\u7406", - "url": "\/setting\/systemsetting\/wxaindex", - "sort": 7, - "is_menu": true, - "pid": "11099", - "apis": "wechat.bind.direct\nwechat.wxa.notice.templates", - "icon": null, - "is_show": true, - "alias_name": "wxaindex", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11107", - "company_id": 0, - "name": "\u6570\u636e\u5206\u6790", - "url": "\/setting\/systemsetting\/editdashboard", - "sort": 7, - "is_menu": false, - "pid": "11099", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "editdashboard", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11108", - "company_id": 0, - "name": "\u5343\u4eba\u5343\u7801", - "url": "\/setting\/systemsetting\/editsourcemanagement", - "sort": 7, - "is_menu": false, - "pid": "11099", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "editsourcemanagement", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11109", - "company_id": 0, - "name": "\u6d88\u606f\u6a21\u677f", - "url": "\/setting\/systemsetting\/noticemessage", - "sort": 7, - "is_menu": false, - "pid": "11099", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "noticemessage", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11110", - "company_id": 0, - "name": "\u516c\u4f17\u53f7\u6388\u6743", - "url": "\/setting\/systemsetting\/brand", - "sort": 8, - "is_menu": true, - "pid": "11099", - "apis": "wechat.user.open\n", - "icon": null, - "is_show": true, - "alias_name": "brand", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11111", - "company_id": 0, - "name": "\u5c0f\u7a0b\u5e8f\u5ba2\u670d", - "url": "\/setting\/systemsetting\/wxappchat", - "sort": 9, - "is_menu": true, - "pid": "11099", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "wxappchat", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11112", - "company_id": 0, - "name": "\u4e00\u6d3d\u5ba2\u670d", - "url": "\/setting\/systemsetting\/echat", - "sort": 9, - "is_menu": true, - "pid": "11099", - "apis": "im.echat.info\nim.echat.save", - "icon": null, - "is_show": true, - "alias_name": "EChat", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11113", - "company_id": 0, - "name": "\u7f8e\u6d3d\u5ba2\u670d", - "url": "\/setting\/systemsetting\/meiqia", - "sort": 10, - "is_menu": true, - "pid": "11099", - "apis": "im.meiqia.info\nim.meiqia.save", - "icon": null, - "is_show": true, - "alias_name": "meiqia", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11114", - "company_id": 0, - "name": "\u65fa\u5e97\u901a", - "url": "\/setting\/systemsetting\/wdtSetting", - "sort": 11, - "is_menu": true, - "pid": "11099", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "wdtSetting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11115", - "company_id": 0, - "name": "\u805a\u6c34\u6f6d", - "url": "\/setting\/systemsetting\/jstSetting", - "sort": 12, - "is_menu": true, - "pid": "11099", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "jstSetting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "platform", - "standard" - ] - }, - { - "shopmenu_id": "11117", - "company_id": 0, - "name": "\u57df\u540d\u8bbe\u7f6e", - "url": "\/setting\/systemsetting\/domain_setting", - "sort": 14, - "is_menu": true, - "pid": "11099", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "domain_setting", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11118", - "company_id": 0, - "name": "\u8131\u654f\u6570\u636e\u7533\u8bf7", - "url": "\/setting\/systemsetting\/approve", - "sort": 15, - "is_menu": true, - "pid": "11099", - "apis": "companys.datapass.list\ncompanys.datapass.apply", - "icon": null, - "is_show": true, - "alias_name": "approveDataPass", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1746117384, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11119", - "company_id": 0, - "name": "\u8131\u654f\u7533\u8bf7\u5ba1\u6279", - "url": "\/setting\/systemsetting\/apply", - "sort": 16, - "is_menu": true, - "pid": "11099", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "applyDataPass", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11120", - "company_id": 0, - "name": "\u5916\u94fe\u5c0f\u7a0b\u5e8f", - "url": "\/setting\/systemsetting\/extminilink", - "sort": 17, - "is_menu": true, - "pid": "11099", - "apis": "wxexternalconfig.create\nwxexternalconfig.update\nwxexternalroutes.list\nwxexternalroutes.create\nwxexternalroutes.update\nwxexternalroutes.delete\nwxexternalconfig.delete\nwxexternalconfigroutes.list", - "icon": null, - "is_show": true, - "alias_name": "extminilink", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u914d\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11121", - "company_id": 0, - "name": "\u914d\u9001\u8bbe\u7f6e", - "url": "\/setting\/delivery", - "sort": 3, - "is_menu": true, - "pid": "11088", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "delivery", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u8bbe\u7f6e", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11122", - "company_id": 0, - "name": "\u914d\u9001\u8bbe\u7f6e", - "url": "\/setting\/delivery\/logistics", - "sort": 1, - "is_menu": true, - "pid": "11121", - "apis": "company.logistics.list \ncompany.logistics.create\ncompany.logistics.delete\ntrade.logistics.list\npickuplocation.list.get\ndatacube.deliverystaff.data\norder.deliverystaff.confirm\norder.deliverypackag.confirm\ncompany.dada.info", - "icon": null, - "is_show": true, - "alias_name": "logistics", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1744679757, - "level": 3, - "parent_name": "\u914d\u9001\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11123", - "company_id": 0, - "name": "\u8fd0\u8d39\u6a21\u677f", - "url": "\/setting\/delivery\/shippingtemplates", - "sort": 2, - "is_menu": true, - "pid": "11121", - "apis": "espier.address.info\nshipping.templates.list\nshipping.templates.info\nshipping.templates.update\nshipping.templates.create\nshipping.templates.delete", - "icon": null, - "is_show": true, - "alias_name": "shippingtemplates", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1744679863, - "level": 3, - "parent_name": "\u914d\u9001\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11124", - "company_id": 0, - "name": "\u7269\u6d41\u67e5\u8be2\u914d\u7f6e", - "url": "\/setting\/delivery\/kdniao", - "sort": 2, - "is_menu": true, - "pid": "11121", - "apis": "trade.kuaidi.setting.get\ntrade.kuaidi.setting.set\norder.delivervstaff.confirm\norder.deliverypackag.confirm\ntrade.sfbsp.setting.get\ntrade.sfbsp.setting.set", - "icon": null, - "is_show": true, - "alias_name": "kdniao", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1744679914, - "level": 3, - "parent_name": "\u914d\u9001\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11125", - "company_id": 0, - "name": "\u914d\u9001\u5458\u7ba1\u7406", - "url": "\/setting\/delivery\/selfdeliverystaff", - "sort": 3, - "is_menu": true, - "pid": "11121", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "setting_staffself_deliverystaff", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u914d\u9001\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11126", - "company_id": 0, - "name": "\u914d\u9001\u5458\u4e1a\u7ee9", - "url": "\/setting\/delivery\/deliverystaffstatistics", - "sort": 4, - "is_menu": true, - "pid": "11121", - "apis": "datacube.deliverystaff.data\nmerchant.list\ndada.finance.info", - "icon": null, - "is_show": true, - "alias_name": "companydata_deliverystaffstatistics", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1744679960, - "level": 3, - "parent_name": "\u914d\u9001\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11127", - "company_id": 0, - "name": "\u8fbe\u8fbe\u8d26\u6237", - "url": "\/setting\/delivery\/dada", - "sort": 6, - "is_menu": true, - "pid": "11121", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "dada", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u914d\u9001\u8bbe\u7f6e", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11128", - "company_id": 0, - "name": "\u7cfb\u7edf\u4fe1\u606f", - "url": "\/setting\/systeminfo", - "sort": 4, - "is_menu": true, - "pid": "11088", - "apis": "", - "icon": null, - "is_show": true, - "alias_name": "systeminfo", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 2, - "parent_name": "\u8bbe\u7f6e", - "isChildrenMenu": true, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11130", - "company_id": 0, - "name": "\u8f6f\u4ef6\u534f\u8bae", - "url": "\/setting\/systeminfo\/agreement", - "sort": 2, - "is_menu": true, - "pid": "11128", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "agreement", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u4fe1\u606f", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - }, - { - "shopmenu_id": "11131", - "company_id": 0, - "name": "\u64cd\u4f5c\u65e5\u5fd7", - "url": "\/setting\/systeminfo\/operatorlogs", - "sort": 3, - "is_menu": true, - "pid": "11128", - "apis": null, - "icon": null, - "is_show": true, - "alias_name": "operator-logs", - "version": 1, - "disabled": false, - "created": 1742899517, - "updated": 1742899517, - "level": 3, - "parent_name": "\u7cfb\u7edf\u4fe1\u606f", - "isChildrenMenu": false, - "menu_type": [ - "all" - ] - } -] \ No newline at end of file +[{"shopmenu_id":"801","company_id":0,"name":"\u6982\u51b5","url":"\/","sort":1,"is_menu":true,"pid":"0","apis":"company.activate.info\nwechat.pre_auth_url\nwechat.authorizerInfo\nwechat.stats.userWeekSummary\ncompany.resources\nwechat.bind\ncompanys.setting\ncompany.real.statistics\ncompany.notice.statistics\ncompanys.ydleads.create\nselfhelp.form.add\nselfhelp.form.edit\nselfhelp.form.info\nselfhelp.form.delete\nselfhelp.template.add\nselfhelp.registrationActivity.info\nselfhelp.registrationActivity.delete\nselfhelp.registrationActivity.invalid\nselfhelp.physical.datelist\nmerchant.operator.update\noperator.update.data\noperator.select.distributor\norder.message.new","icon":"tachometer-alt-copy","is_show":true,"alias_name":"index","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":1,"parent_name":"\u65e0","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"802","company_id":0,"name":"\u5546\u54c1","url":"\/entity","sort":1,"is_menu":true,"pid":"0","apis":"","icon":"shopping-bag-copy","is_show":true,"alias_name":"entity","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"803","company_id":0,"name":"\u5546\u54c1\u7ba1\u7406","url":"\/entity\/goods","sort":1,"is_menu":true,"pid":"802","apis":"third.wdterp.setting.get\nthird.jushuitan.setting.get","icon":null,"is_show":true,"alias_name":"goods","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"name_lang":{"zh-CN":"\u5546\u54c1\u7ba1\u7406"},"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"804","company_id":0,"name":"\u81ea\u8425\u5546\u54c1","url":"\/entity\/goods\/goodsphysical","sort":1,"is_menu":true,"pid":"803","apis":"goods.items.create\ngoods.items.templates_change\ngoods.items.category_change\ngoods.items.lists\ngoods.items.detail\ngoods.items.delete\ngoods.items.update\ngoods.items.distributiongoodswxacode\ngoods.items.warning_store\ngoods.category.lists\ngoods.category.get\ngoods.category.update\nshipping.templates.list\ncurrency.get.default\nespier.image.list\ndistributor.item.create\nespier.image.cat.children\ngoods.attributes.list\nwechat.material.upload\nwechat.material.list\ngoods.tag.list\ngoods.tag.rel\ngoods.status.upate\npopularize.config.get\ngoods.member.price\ngoods.store.upate\ngoods.export\ngoods.profit.info\ngoods.profit.save\ngoods.jishuitan.items.upload\ngoods.jushuitan.inventory.query\ngoods.sync.items\ngoods.isgift.upate\ngoods.createcategory.create\nespier.image.cat.edit\nthird.jushuitan.setting.get\nall.setting.get\nthird.wdterp.setting.get\npoint.member.rule.info\nespier.address.info\nespier.upload\nespier.oss.uploadToken.get\nespier.image.save\ngoods.attributes.list\ngoods.tag.list","icon":null,"is_show":true,"alias_name":"goodsphysical","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"name_lang":{"zh-CN":"\u81ea\u8425\u5546\u54c1"},"level":3,"parent_name":"\u5546\u54c1\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"805","company_id":0,"name":"\u5546\u6237\u5546\u54c1","url":"\/entity\/goods\/goodsaudit","sort":2,"is_menu":true,"pid":"803","apis":"goods.items.lists\ngoods.items.detail\ngoods.items.distributiongoodswxacode\ngoods.items.warning_store\ngoods.category.lists\nshipping.templates.list\ncurrency.get.default\nwechat.material.upload\nwechat.material.list\ngoods.tag.list\ngoods.items.audit","icon":null,"is_show":true,"alias_name":"goodsaudit","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5546\u54c1\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"806","company_id":0,"name":"\u95e8\u5e97\u5546\u54c1\u7ba1\u7406","url":"\/entity\/goods\/storeshopitemanagement","sort":3,"is_menu":true,"pid":"803","apis":"distributor.item.exportlist\ndistributor.info\ndistributor.info","icon":null,"is_show":true,"alias_name":"storeshopitemanagement","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5546\u54c1\u7ba1\u7406","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"807","company_id":0,"name":"\u95e8\u5e97\u5546\u54c1\u66f4\u65b0","url":"\/entity\/goods\/exportstoreitems","sort":4,"is_menu":true,"pid":"803","apis":"","icon":null,"is_show":true,"alias_name":"exportstoreitems","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5546\u54c1\u7ba1\u7406","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"808","company_id":0,"name":"\u5546\u54c1\u5206\u7c7b","url":"\/entity\/goodsgroup","sort":2,"is_menu":true,"pid":"802","apis":"","icon":null,"is_show":true,"alias_name":"goodsgroup","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"809","company_id":0,"name":"\u7ba1\u7406\u5206\u7c7b","url":"\/entity\/goodsgroup\/goodsmaincategory","sort":1,"is_menu":true,"pid":"808","apis":"goods.category.delete","icon":null,"is_show":true,"alias_name":"goodsmaincategory","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5546\u54c1\u5206\u7c7b","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"810","company_id":0,"name":"\u9500\u552e\u5206\u7c7b","url":"\/entity\/goodsgroup\/goodscategory","sort":2,"is_menu":true,"pid":"808","apis":"","icon":null,"is_show":true,"alias_name":"goodscategory","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5546\u54c1\u5206\u7c7b","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"811","company_id":0,"name":"\u5546\u54c1\u6807\u7b7e","url":"\/entity\/goodsgroup\/itemtags","sort":3,"is_menu":true,"pid":"808","apis":null,"icon":null,"is_show":true,"alias_name":"itemtags","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5546\u54c1\u5206\u7c7b","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"812","company_id":0,"name":"\u57fa\u7840\u914d\u7f6e","url":"\/entity\/goodsbase","sort":2,"is_menu":true,"pid":"802","apis":"","icon":null,"is_show":true,"alias_name":"goodsbase","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"813","company_id":0,"name":"\u5546\u54c1\u89c4\u683c","url":"\/entity\/goodsbase\/goodsattributes","sort":3,"is_menu":true,"pid":"812","apis":"goods.attributes.update\ngoods.attributes.delete","icon":null,"is_show":true,"alias_name":"goodsattributes","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u57fa\u7840\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"814","company_id":0,"name":"\u5546\u54c1\u54c1\u724c","url":"\/entity\/goodsbase\/goodsbrand","sort":4,"is_menu":true,"pid":"812","apis":"goods.attributes.add","icon":null,"is_show":true,"alias_name":"goodsbrand","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u57fa\u7840\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"815","company_id":0,"name":"\u5546\u54c1\u53c2\u6570","url":"\/entity\/goodsbase\/goodsparams","sort":5,"is_menu":true,"pid":"812","apis":null,"icon":null,"is_show":true,"alias_name":"goodsparams","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u57fa\u7840\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"816","company_id":0,"name":"\u8ba2\u5355","url":"\/order","sort":3,"is_menu":true,"pid":"0","apis":"datacube.deliverystaff.data\norder.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel","icon":"receipt","is_show":true,"alias_name":"order","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"817","company_id":0,"name":"\u8ba2\u5355\u7ba1\u7406","url":"\/order\/entitytrade","sort":1,"is_menu":true,"pid":"816","apis":"order.writeoff.qr.set\norder.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel\norder.entitytrade.tradenormalorders\norder.entitytrade.tradenormalshoporders\norder.entitytrade.normalordersupload\norder.aftersales.aftersaleslist\norder.ordersetting.ordersettingdetail\norder.ordersetting.tradesetting\norder.ordersetting.aftersalesreason\norder.ordersetting.cartremind\norder.ordersetting.goodslimit","icon":null,"is_show":true,"alias_name":"entitytrade","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u8ba2\u5355","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"818","company_id":0,"name":"\u8ba2\u5355\u5217\u8868","url":"\/order\/entitytrade\/tradenormalorders","sort":1,"is_menu":true,"pid":"817","apis":"order.list.get\nsource.list\norder.info.get\norder.delivery\norder.list.export\nshops.lists\ndistributor.list\nmember.info\ntrade.logistics.list\nespier.image.del\norder.cancel.info\norder.delivery.update\norder.cancel\ninvoice.list.export\norder.writeoff.info.get\norder.writeoff.set\norder.process.log.get\norder.invoiced.invoiced\norder.delivery.details\norder.delivery.lists\norder.businessreceipt\nworkwechat.distributor.js.config\nespier.subdistrict.list.get\norder.remarks.update\norder.writeoff.qr.set\norder.process.log.get\norder.invoiced.invoiced\norder.delivery.details\norder.delivery.lists\norder.remarks.update\ndelivery.process.list\nworkwechat.distributor.js.config\norder.message.new\ncompany.real.statistics\norder.writeoff.qr.set\noperator.update.data\nespier.oss.uploadToken.get\norder.message.list\norder.businessreceipt\nespier.localimage.upload\nespier.image.save\norder.message.update\ncard.consume\nespier.subdistrict.list.get\noperator.select.distributor\naftersales.remark.update\nespier.oss.uploadToken.get\nespier.localimage.upload\nespier.image.save\nespier.address.info\ngoods.items.onsale.lists\ncompanys.operator.cartdata.scanadd\ncompanys.operator.cartdata.add\ncompanys.operator.cartdata.update\ncompanys.operator.cartdata.list\ncompanys.operator.cartdata.del\norder.checkout\norder.create\norder.payment\norder.payment.query\nuser.card.list\nmember.create\ncompanys.operator.cartdata.pending\ncompanys.operator.order.pending\ncompanys.operator.pending.fetch\ncompanys.operator.pending.delete\ncompanys.operator.pending.list\norder.markdown\norder.markdown.confirm\norder.writeoff.qr.set\norder.deliverystaff.confirm\ndatacube.deliverystaff.data\norder.deliverystaff.cancel\nall.setting.get\npresale.pickupcode.setting.get\naccount.list","icon":null,"is_show":true,"alias_name":"tradenormalorders","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"819","company_id":0,"name":"\u81ea\u8425\u8ba2\u5355","url":"\/order\/entitytrade\/marketingdistribution_orders","sort":2,"is_menu":true,"pid":"817","apis":"source.list\norder.writeoff.qr.set","icon":null,"is_show":true,"alias_name":"marketingdistribution_orders","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u7ba1\u7406","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"820","company_id":0,"name":"\u81ea\u8425\u8ba2\u5355","url":"\/order\/entitytrade\/tradenormalshoporders","sort":2,"is_menu":true,"pid":"817","apis":"order.cancel.info\norder.delivery.lists\norder.writeoff.qr.set\norder.writeoff.qr.set\ndatacube.deliverystaff.data\norder.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel","icon":null,"is_show":true,"alias_name":"tradenormalshoporders","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"821","company_id":0,"name":"\u6279\u91cf\u53d1\u8d27","url":"\/order\/entitytrade\/normalordersupload","sort":6,"is_menu":true,"pid":"817","apis":"espier.upload.list\norder.deliverystaff.confirm\norder.deliverypackag.confirm","icon":null,"is_show":true,"alias_name":"normalordersupload","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"822","company_id":0,"name":"\u8ba2\u5355\u552e\u540e","url":"\/order\/aftersales","sort":2,"is_menu":true,"pid":"816","apis":null,"icon":null,"is_show":true,"alias_name":"aftersales","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u8ba2\u5355","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"823","company_id":0,"name":"\u552e\u540e\u5217\u8868","url":"\/order\/aftersales\/aftersaleslist","sort":1,"is_menu":true,"pid":"822","apis":"aftersales.list\naftersales.info\naftersales.review\naftersales.logexport\naftersales.remind.get\naftersales.remind.set\naftersales.apply\norder.deliverystaff.confirm\norder.deliverypackag.confirm\ndatacube.deliverystaff.data\naftersales.sendback","icon":null,"is_show":true,"alias_name":"aftersaleslist","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u552e\u540e","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"824","company_id":0,"name":"\u8ba2\u5355\u8bbe\u7f6e","url":"\/order\/ordersetting","sort":3,"is_menu":true,"pid":"816","apis":null,"icon":null,"is_show":true,"alias_name":"ordersetting","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u8ba2\u5355","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"825","company_id":0,"name":"\u8ba2\u5355\u8bbe\u7f6e","url":"\/order\/ordersetting\/ordersettingdetail","sort":1,"is_menu":true,"pid":"824","apis":"orders.setting.get\nordersetting.set\norder.delivervstaff.confirm\norder.deliverypackag.confirm","icon":null,"is_show":true,"alias_name":"ordersettingdetail","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"826","company_id":0,"name":"\u793c\u54c1\u5305\u88c5","url":"\/order\/ordersetting\/tradesetting","sort":1,"is_menu":true,"pid":"824","apis":"trade.setting.get\ntrade.setting.set\norder.delivervstaff.confirm\norder.deliverypackag.confirm","icon":null,"is_show":true,"alias_name":"tradesetting","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"827","company_id":0,"name":"\u552e\u540e\u539f\u56e0","url":"\/order\/ordersetting\/aftersalesreason","sort":1,"is_menu":true,"pid":"824","apis":"aftersales.reason.list\naftersales.reason.save\norder.delivervstaff.confirm\norder.deliverypackag.confirm","icon":null,"is_show":true,"alias_name":"aftersalesreason","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"828","company_id":0,"name":"\u8d2d\u7269\u63d0\u9192","url":"\/order\/ordersetting\/cartremind","sort":4,"is_menu":true,"pid":"824","apis":"wechat.wxa.cartremind.setting.set\nwechat.wxa.cartremind.setting.get","icon":null,"is_show":true,"alias_name":"cartremind","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"829","company_id":0,"name":"\u5546\u54c1\u9650\u8d2d","url":"\/order\/ordersetting\/goodslimit","sort":5,"is_menu":true,"pid":"824","apis":"promotions.limit.list.get\npromotions.limit.create\npromotions.limit.info.get\npromotions.limit.cancel\npromotions.limit.update","icon":null,"is_show":true,"alias_name":"goodslimit","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u8ba2\u5355\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"830","company_id":0,"name":"\u4f1a\u5458","url":"\/member","sort":4,"is_menu":true,"pid":"0","apis":"","icon":"crown","is_show":true,"alias_name":"member","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"831","company_id":0,"name":"\u4f1a\u5458\u7ba1\u7406","url":"\/member\/member","sort":0,"is_menu":true,"pid":"830","apis":"","icon":null,"is_show":true,"alias_name":"memberlmana","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"832","company_id":0,"name":"\u4f1a\u5458\u5217\u8868","url":"\/member\/member\/memberlist","sort":1,"is_menu":true,"pid":"831","apis":"member.subscribe.list\naliyunsms.status.get\npopularize.promoter.list.get\nmember.register.get\nthird.dmcrm.setting.get","icon":null,"is_show":true,"alias_name":"memberlist","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"833","company_id":0,"name":"\u6279\u91cf\u66f4\u65b0","url":"\/member\/member\/managecustomer","sort":1,"is_menu":true,"pid":"831","apis":"espier.upload.list\nespier.upload\nespier.upload.error.export\nespier.upload.template.export","icon":null,"is_show":true,"alias_name":"managecustomer","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"834","company_id":0,"name":"\u4f1a\u5458\u5bfc\u51fa","url":"\/member\/member\/memberlist","sort":1,"is_menu":false,"pid":"831","apis":"member.export","icon":null,"is_show":true,"alias_name":"member-export","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"835","company_id":0,"name":"\u624b\u52a8\u5ef6\u671f\u4ed8\u8d39\u4f1a\u5458","url":"\/member\/member\/memberlist","sort":1,"is_menu":false,"pid":"831","apis":"vipgrade.use.active.delay\nvipgrade.use.batch.active.delay\nvipgrade.use.list\nmember.upate.grade_id","icon":null,"is_show":true,"alias_name":"member-vip-delay","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["b2c","standard"]},{"shopmenu_id":"836","company_id":0,"name":"\u6dfb\u52a0\u6743\u76ca","url":"\/member\/member\/memberlist","sort":2,"is_menu":false,"pid":"831","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\ngoods.items.lists\norder.rights.add","icon":null,"is_show":true,"alias_name":"member-add-rights","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"837","company_id":0,"name":"\u4f1a\u5458\u4fe1\u606f\u67e5\u770b","url":"\/member\/member\/memberlist","sort":2,"is_menu":false,"pid":"831","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\npoint.member.list\ndistributor.list\nvipgrade.order.list\npoint.member.list\nworkwechat.rel.log\npoint.adjustment","icon":null,"is_show":true,"alias_name":"member-list-view","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"838","company_id":0,"name":"\u7fa4\u53d1\u4f18\u60e0\u5238","url":"\/member\/member\/memberlist","sort":4,"is_menu":false,"pid":"831","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\npromotions.give.create\npromotions.give.list\npromotions.give.info\nmember.tag.rel\ngoods.items.lists\nmember.batch.operating","icon":null,"is_show":true,"alias_name":"member-send-coupons","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"839","company_id":0,"name":"\u7fa4\u53d1\u77ed\u4fe1","url":"\/member\/member\/memberlist","sort":5,"is_menu":false,"pid":"831","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\nmember.smssend","icon":null,"is_show":true,"alias_name":"member-send-sms","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"840","company_id":0,"name":"\u6253\u6807\u7b7e","url":"\/member\/member\/memberlist","sort":6,"is_menu":false,"pid":"831","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\nmember.tag.rel\nmember.tag.del\nmember.batch.operating","icon":null,"is_show":true,"alias_name":"member-tag","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"841","company_id":0,"name":"\u4f1a\u5458\u624b\u673a\u53f7\u4fee\u6539","url":"\/member\/member\/memberlist","sort":7,"is_menu":false,"pid":"831","apis":"member.upate.mobile","icon":null,"is_show":true,"alias_name":"member-modify-phone-number","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"842","company_id":0,"name":"\u6807\u7b7e\u7ba1\u7406","url":"\/member\/tagsmanage","sort":1,"is_menu":true,"pid":"830","apis":null,"icon":null,"is_show":true,"alias_name":"tagsmanage","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"843","company_id":0,"name":"\u5ba2\u6237\u6807\u7b7e","url":"\/member\/tagsmanage\/customerTags","sort":1,"is_menu":true,"pid":"842","apis":null,"icon":null,"is_show":true,"alias_name":"customerTags","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u6807\u7b7e\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"844","company_id":0,"name":"\u4eba\u7fa4\u6253\u6807","url":"\/member\/tagsmanage\/crowdMarking","sort":2,"is_menu":true,"pid":"842","apis":null,"icon":null,"is_show":true,"alias_name":"crowdMarking","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u6807\u7b7e\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"845","company_id":0,"name":"\u4f1a\u5458\u6743\u76ca","url":"\/member\/card","sort":1,"is_menu":true,"pid":"830","apis":"","icon":null,"is_show":true,"alias_name":"card","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"846","company_id":0,"name":"\u4f1a\u5458\u7b49\u7ea7","url":"\/member\/card\/managecard","sort":0,"is_menu":true,"pid":"845","apis":"membercard.setting\nmembercard.info\nmembercard.grade.add\nmembercard.default.grade\nmembercard.grade.list\nmembercard.vipgrade.add\nmembercard.vipgrade.list\nvipgrade.use.list","icon":null,"is_show":true,"alias_name":"managecard","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u6743\u76ca","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"847","company_id":0,"name":"\u4ed8\u8d39\u8bb0\u5f55","url":"\/member\/card\/managecardorder","sort":1,"is_menu":true,"pid":"845","apis":"vipgrade.order.list","icon":null,"is_show":true,"alias_name":"managecardorder","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u6743\u76ca","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"848","company_id":0,"name":"\u79ef\u5206\u89c4\u5219","url":"\/member\/card\/pointrule","sort":1,"is_menu":true,"pid":"845","apis":"point.member.rule.info\npoint.member.rule.save","icon":null,"is_show":true,"alias_name":"pointrule","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u6743\u76ca","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"849","company_id":0,"name":"\u79ef\u5206\u6d41\u6c34","url":"\/member\/card\/pointoverview","sort":1,"is_menu":true,"pid":"845","apis":"point.member.list\nmember.pointcount.index","icon":null,"is_show":true,"alias_name":"pointoverview","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u6743\u76ca","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"850","company_id":0,"name":"\u4f1a\u5458\u89e6\u8fbe","url":"\/member\/membertouch","sort":2,"is_menu":true,"pid":"830","apis":"member.subscribe.list","icon":null,"is_show":true,"alias_name":"membertouch","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"851","company_id":0,"name":"\u7fa4\u53d1\u77ed\u4fe1","url":"\/member\/membertouch\/smssend","sort":1,"is_menu":true,"pid":"850","apis":null,"icon":null,"is_show":true,"alias_name":"smssend","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u89e6\u8fbe","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"852","company_id":0,"name":"\u5230\u8d27\u901a\u77e5","url":"\/member\/membertouch\/arrivalnotice","sort":2,"is_menu":true,"pid":"850","apis":null,"icon":null,"is_show":true,"alias_name":"arrivalnotice","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u89e6\u8fbe","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"853","company_id":0,"name":"\u4f1a\u5458\u8bbe\u7f6e","url":"\/member\/membersetting","sort":3,"is_menu":true,"pid":"830","apis":"","icon":null,"is_show":true,"alias_name":"membersetting","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"854","company_id":0,"name":"\u6ce8\u518c\u914d\u7f6e","url":"\/member\/membersetting\/Manageinfomation","sort":1,"is_menu":true,"pid":"853","apis":"member.register.set\nmember.register.get\nespier.config.request_field_setting.get\nespier.config.request_fields.get","icon":null,"is_show":true,"alias_name":"manageinfomation","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"855","company_id":0,"name":"\u6ce8\u9500\u914d\u7f6e","url":"\/member\/membersetting\/closeAccount","sort":2,"is_menu":true,"pid":"853","apis":"shops.protocol.put\nshops.protocol.get","icon":null,"is_show":true,"alias_name":"closeAccount","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"856","company_id":0,"name":"\u4fe1\u4efb\u767b\u5f55","url":"\/member\/membersetting\/trustlogin","sort":3,"is_menu":true,"pid":"853","apis":"member.trustlogin.list\nmember.trustlogin.setting","icon":null,"is_show":true,"alias_name":"trustlogin","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u4f1a\u5458\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"857","company_id":0,"name":"\u4f1a\u5458\u767d\u540d\u5355","url":"\/member\/whitelistlist","sort":4,"is_menu":true,"pid":"830","apis":"member.whitelist.list","icon":null,"is_show":true,"alias_name":"whitelistlist","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"858","company_id":0,"name":"\u767d\u540d\u5355\u5bfc\u5165","url":"\/member\/whitelistuploade","sort":5,"is_menu":true,"pid":"830","apis":null,"icon":null,"is_show":true,"alias_name":"whitelistuploade","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"859","company_id":0,"name":"\u5546\u6237","url":"\/sellers","sort":5,"is_menu":true,"pid":"0","apis":"","icon":"store-alt-copy","is_show":true,"alias_name":"sellers","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"860","company_id":0,"name":"\u9500\u552e\u7ec4\u7ec7","url":"\/sellers\/salesorganization","sort":0,"is_menu":true,"pid":"859","apis":"","icon":null,"is_show":true,"alias_name":"salesorganization","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u5546\u6237","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"861","company_id":0,"name":"\u5546\u6237","url":"\/sellers\/salesorganization\/list","sort":1,"is_menu":true,"pid":"860","apis":"merchant.list\nmerchant.visibletype.list\nmerchant.detail.get\nmerchant.disabled.update\nmerchant.audit.goods.update\nmerchant.info.get","icon":null,"is_show":true,"alias_name":"storemanager","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u9500\u552e\u7ec4\u7ec7","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"862","company_id":0,"name":"\u5e97\u94fa\u7ba1\u7406","url":"\/sellers\/storemanager","sort":1,"is_menu":true,"pid":"859","apis":"","icon":null,"is_show":true,"alias_name":"sellersmanager","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u5546\u6237","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"863","company_id":0,"name":"\u5165\u9a7b\u5e97\u94fa","url":"\/sellers\/storemanager\/marketingdistributor","sort":2,"is_menu":true,"pid":"862","apis":"distributor.list\ndistributor.create\ndistributor.edit\ndistributor.item.list\ndistributor.wxacode\ndistributor.get.shop\ndistributor.item.update\ndistributor.default.set\ndistributor.create\ndistributor.item.delete\ngoods.items.distributiongoodswxacode\ncurrency.get.default\ndistributor.info\ndistributor.tag.list\npagestemplate.lists\npagestemplateset.getInfo\npagestemplate.detail\npagestemplate.modifyStatus\npagestemplate.add\npagestemplate.edit\npagestemplate.copy\npagestemplate.delete\nhfpay.ledgerconfig.index\ncompany.dada.info\ncompany.regionauth.list\nespier.image.cat.children\norder.writeoff.qr.set\ntrade.payment.open.status.get","icon":null,"is_show":true,"alias_name":"marketingsellers","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5e97\u94fa\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"864","company_id":0,"name":"\u5165\u9a7b\u5ba1\u6838","url":"\/sellers\/storemanager\/application","sort":3,"is_menu":true,"pid":"862","apis":"merchant.settlement.apply.list\nmerchant.settlement.apply.detail\nmerchant.settlement.apply.audit","icon":null,"is_show":true,"alias_name":"storemanager_application","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5e97\u94fa\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"865","company_id":0,"name":"\u9000\u8d27\u5730\u5740","url":"\/sellers\/storemanager\/distributoraftersalesaddress","sort":4,"is_menu":true,"pid":"862","apis":"espier.address.info\nespier.address.info\nwechat.wxa.customizepage.info","icon":null,"is_show":true,"alias_name":"distributoraftersalesaddress1","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5e97\u94fa\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"866","company_id":0,"name":"\u5e97\u94fa\u6807\u7b7e","url":"\/sellers\/storemanager\/distributortags","sort":5,"is_menu":true,"pid":"862","apis":"distributor.tag.add\ndistributor.tag.update\ndistributor.tag.get\ndistributor.tag.get\ndistributor.tag.delete","icon":null,"is_show":true,"alias_name":"Sellerstags","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5e97\u94fa\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"867","company_id":0,"name":"\u5546\u6237\u8bbe\u7f6e","url":"\/sellers\/salesetting","sort":2,"is_menu":true,"pid":"859","apis":null,"icon":null,"is_show":true,"alias_name":"salesetting","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":2,"parent_name":"\u5546\u6237","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"868","company_id":0,"name":"\u5546\u6237\u7c7b\u76ee","url":"\/sellers\/salesetting\/setting","sort":1,"is_menu":true,"pid":"867","apis":"merchant.type.list\nmerchant.type.creat\nmerchant.type.update\nmerchant.type.delete\nmerchant.basesetting.get\nmerchant.basesetting.save","icon":null,"is_show":true,"alias_name":"storemanager_setting","version":1,"disabled":false,"created":1770278867,"updated":1770278867,"level":3,"parent_name":"\u5546\u6237\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"869","company_id":0,"name":"\u5e97\u94fa","url":"\/store","sort":5,"is_menu":true,"pid":"0","apis":"hfpay.ledgerconfig.index","icon":"store-alt-copy","is_show":true,"alias_name":"store","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["standard","in_purchase"]},{"shopmenu_id":"870","company_id":0,"name":"\u5e97\u94fa\u7ba1\u7406","url":"\/store\/storemanager","sort":2,"is_menu":true,"pid":"869","apis":"hfpay.ledgerconfig.index\norder.writeoff.qr.set\norders.setting.get\ntrade.payment.open.status.get","icon":null,"is_show":true,"alias_name":"storemanager","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u5e97\u94fa","isChildrenMenu":true,"menu_type":["standard","in_purchase"]},{"shopmenu_id":"871","company_id":0,"name":"\u81ea\u8425\u95e8\u5e97","url":"\/store\/storemanager\/marketingdistributor","sort":0,"is_menu":true,"pid":"870","apis":"distributor.list\ndistributor.create\ndistributor.edit\ndistributor.item.list\ndistributor.wxacode\ndistributor.get.shop\ndistributor.item.update\ndistributor.default.set\ndistributor.create\ndistributor.item.delete\ngoods.items.distributiongoodswxacode\ncurrency.get.default\ndistributor.info\ndistributor.tag.list\npagestemplate.lists\npagestemplateset.getInfo\npagestemplate.detail\npagestemplate.modifyStatus\npagestemplate.edit\npagestemplate.add\npagestemplate.delete\npagestemplate.copy\ndistribution.distance.get\ndistribution.distance.save\ncompany.regionauth.list\nhfpay.enterapply.opensplit\nhfpay.ledgerconfig.index\ncompany.dada.info\nwechat.material.list\nespier.oss.uploadToken.get\nespier.image.save\nespier.image.list\ndistributor.aftersales.list\norder.writeoff.qr.set\norders.setting.get \ntrade.payment.open.status.get","icon":null,"is_show":true,"alias_name":"marketingdistributor","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5e97\u94fa\u7ba1\u7406","isChildrenMenu":false,"menu_type":["standard","in_purchase"]},{"shopmenu_id":"872","company_id":0,"name":"\u5e97\u94fa\u767d\u540d\u5355","url":"\/store\/storemanager\/storewhitelist","sort":1,"is_menu":true,"pid":"870","apis":null,"icon":null,"is_show":true,"alias_name":"storewhitelist","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5e97\u94fa\u7ba1\u7406","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"873","company_id":0,"name":"\u8fdb\u5e97\u89c4\u5219","url":"\/store\/storemanager\/storerules","sort":1,"is_menu":true,"pid":"870","apis":"wechat.wxa.customizepage.info","icon":null,"is_show":true,"alias_name":"storerules","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5e97\u94fa\u7ba1\u7406","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"874","company_id":0,"name":"\u9000\u8d27\u5730\u5740","url":"\/store\/storemanager\/distributoraftersalesaddress","sort":3,"is_menu":true,"pid":"870","apis":"espier.address.info","icon":null,"is_show":true,"alias_name":"distributoraftersalesaddress","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5e97\u94fa\u7ba1\u7406","isChildrenMenu":false,"menu_type":["standard","in_purchase"]},{"shopmenu_id":"875","company_id":0,"name":"\u4f9b\u5e94","url":"\/supply","sort":6,"is_menu":true,"pid":"0","apis":"","icon":"box","is_show":true,"alias_name":"supply","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"876","company_id":0,"name":"\u4f9b\u5e94\u5546\u5546\u54c1","url":"\/supply\/supplygoods","sort":1,"is_menu":true,"pid":"875","apis":null,"icon":null,"is_show":true,"alias_name":"supplygoods","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u4f9b\u5e94","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"877","company_id":0,"name":"\u5546\u54c1\u7ba1\u7406","url":"\/supply\/supplygoods\/supplier_goods_list","sort":1,"is_menu":true,"pid":"876","apis":"","icon":null,"is_show":true,"alias_name":"supplier_goods_list","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f9b\u5e94\u5546\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"878","company_id":0,"name":"\u5546\u54c1\u5ba1\u6838","url":"\/supply\/supplygoods\/suppliergoods","sort":2,"is_menu":true,"pid":"876","apis":"supplier.batch_review_items","icon":null,"is_show":true,"alias_name":"goods_suppliergoods","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f9b\u5e94\u5546\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"879","company_id":0,"name":"\u4f9b\u5e94\u5546\u7ba1\u7406","url":"\/supply\/supplymanage","sort":2,"is_menu":true,"pid":"875","apis":null,"icon":null,"is_show":true,"alias_name":"supplymanage","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u4f9b\u5e94","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"880","company_id":0,"name":"\u4f9b\u5e94\u5546\u5217\u8868","url":"\/supply\/supplymanage\/supplier_list","sort":1,"is_menu":true,"pid":"879","apis":"supplier.get_supplier_list ","icon":null,"is_show":true,"alias_name":"supplier_list","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f9b\u5e94\u5546\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"881","company_id":0,"name":"\u4f9b\u5e94\u5546\u8d26\u53f7","url":"\/supply\/supplymanage\/supplier","sort":2,"is_menu":true,"pid":"879","apis":null,"icon":null,"is_show":true,"alias_name":"supplier","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f9b\u5e94\u5546\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"882","company_id":0,"name":"\u8425\u9500","url":"\/marketing","sort":6,"is_menu":true,"pid":"0","apis":"goods.sku.lists\ngoods.category.lists\ngoods.tag.list\ngoods.attributes.list\nmembercard.vipgrade.list\nwechat.wxa.template.list","icon":"tag","is_show":true,"alias_name":"marketing","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["b2c","platform","standard","in_purchase"]},{"shopmenu_id":"883","company_id":0,"name":"\u5361\u5238","url":"\/marketing\/coupon","sort":1,"is_menu":true,"pid":"882","apis":"wechat.wxa.template.list\ndistributor.easy.list","icon":null,"is_show":true,"alias_name":"coupon","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"884","company_id":0,"name":"\u5238\u7ba1\u7406","url":"\/marketing\/coupon\/membermarketing","sort":0,"is_menu":true,"pid":"883","apis":"card.list\ncard.create\ncard.delete\ncard.update\ncard.get\ncard.user.list\nshops.lists\ncard.detail.list\nwechat.material.list\nwechat.material.upload\ncurrency.get.default\ncard.store\ndistributor.easy.list\nwechat.wxa.template.list\ndistributor.easy.list","icon":null,"is_show":true,"alias_name":"membermarketing","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5361\u5238","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"885","company_id":0,"name":"\u5238\u5305\u7ba1\u7406","url":"\/marketing\/coupon\/couponspackage","sort":1,"is_menu":true,"pid":"883","apis":"voucher.package.list","icon":null,"is_show":true,"alias_name":"couponspackage","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5361\u5238","isChildrenMenu":false,"menu_type":["standard","platform"]},{"shopmenu_id":"886","company_id":0,"name":"\u53d1\u5238\u8bb0\u5f55","url":"\/marketing\/coupon\/coupongive","sort":2,"is_menu":true,"pid":"883","apis":"promotions.give.list\npromotions.give.info","icon":null,"is_show":true,"alias_name":"coupongive","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5361\u5238","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"887","company_id":0,"name":"\u7fa4\u53d1\u4f18\u60e0\u5238","url":"\/marketing\/coupon\/couponsend","sort":3,"is_menu":false,"pid":"883","apis":"member.list\nmember.operate.logs\nmember.info\neffectiveCard.list\npromotions.give.create\npromotions.give.list\npromotions.give.info\nmember.tag.list\nmember.tag.rel\nmembercard.grade.list\norder.rights.list.get\nshops.lists\norder.rights.transfer.list\ngoods.items.lists\norder.list.get\norder.info.get\ndeposit.trades\nmember.batch.operating","icon":null,"is_show":true,"alias_name":"couponsend","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5361\u5238","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"888","company_id":0,"name":"\u4fc3\u9500","url":"\/marketing\/promotion","sort":2,"is_menu":true,"pid":"882","apis":"","icon":null,"is_show":true,"alias_name":"promotion","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"889","company_id":0,"name":"\u6ee1\u6298","url":"\/marketing\/promotion\/marketingsfulldiscount","sort":1,"is_menu":true,"pid":"888","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ncurrency.get.default\ngoods.category.lists\ngoods.tag.list\ngoods.attributes.list\nmembercard.vipgrade.list\ndistributor.easy.list","icon":null,"is_show":true,"alias_name":"marketingsfulldiscount","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4fc3\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"890","company_id":0,"name":"\u6ee1\u51cf","url":"\/marketing\/promotion\/Marketingsfullminus","sort":2,"is_menu":true,"pid":"888","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ncurrency.get.default\ngoods.category.lists\ngoods.tag.list\ngoods.attributes.list\nmembercard.vipgrade.list","icon":null,"is_show":true,"alias_name":"Marketingsfullminus","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4fc3\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"891","company_id":0,"name":"\u6ee1\u8d60","url":"\/marketing\/promotion\/Marketingsfullgift","sort":3,"is_menu":true,"pid":"888","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ngoods.category.lists\ngoods.tag.list\ngoods.attributes.list\nmembercard.vipgrade.list","icon":null,"is_show":true,"alias_name":"Marketingsfullgift","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4fc3\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"892","company_id":0,"name":"\u9650\u65f6\u7279\u60e0","url":"\/marketing\/promotion\/limitedtimesale","sort":4,"is_menu":true,"pid":"888","apis":"Promotions.seckill.add\nPromotions.seckill.delete\nPromotions.seckill.update\nPromotions.seckill.list\nPromotions.seckill.info\nPromotions.seckill.statusupdate\nPromotions.seckill.item.list\nshipping.templates.list\ncurrency.get.default\nwechat.material.list\ngoods.items.lists\nPromotions.seckill.wxcode\nPromotions.seckill.search.item.list","icon":null,"is_show":true,"alias_name":"limitedtimesale","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4fc3\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"893","company_id":0,"name":"\u52a0\u4ef7\u8d2d","url":"\/marketing\/promotion\/Marketingspluspricebuy","sort":5,"is_menu":true,"pid":"888","apis":"","icon":null,"is_show":true,"alias_name":"marketingspluspricebuy","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4fc3\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"894","company_id":0,"name":"\u7ec4\u5408\u8d2d","url":"\/marketing\/promotion\/marketingpackage","sort":5,"is_menu":true,"pid":"888","apis":"promotions.package.list.get\npromotions.package.create\npromotions.package.info.get\npromotions.package.cancel\npromotions.package.update","icon":null,"is_show":true,"alias_name":"marketingpackage","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4fc3\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"895","company_id":0,"name":"\u4f1a\u5458\u8425\u9500","url":"\/marketing\/membermarket","sort":3,"is_menu":true,"pid":"882","apis":"","icon":null,"is_show":true,"alias_name":"membermarket","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"896","company_id":0,"name":"\u65b0\u5ba2\u8425\u9500","url":"\/marketing\/membermarket\/marketingindex","sort":1,"is_menu":true,"pid":"895","apis":"goods.items.lists\npromotions.register.get\nPromotions.register.add\ncard.list\npromotions.register.point.get\nPromotions.register.point.add\nespier.image.list\nespier.image.uploadToken.get\nespier.image.save","icon":null,"is_show":true,"alias_name":"marketingindex","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f1a\u5458\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"897","company_id":0,"name":"\u79ef\u5206\u5347\u503c","url":"\/marketing\/membermarket\/pointupvaluation","sort":2,"is_menu":true,"pid":"895","apis":"promotions.pointupvaluation.list","icon":null,"is_show":true,"alias_name":"pointupvaluation","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f1a\u5458\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"898","company_id":0,"name":"\u989d\u5916\u79ef\u5206","url":"\/marketing\/membermarket\/extrapoint","sort":2,"is_menu":true,"pid":"895","apis":"promotions.extrapoints.lists","icon":null,"is_show":true,"alias_name":"extrapoint","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f1a\u5458\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"899","company_id":0,"name":"\u5b9a\u5411\u8425\u9500","url":"\/marketing\/membermarket\/specificcrowddiscount","sort":2,"is_menu":true,"pid":"895","apis":"specific.crowd.discount.add\nspecific.crowd.discount.update\nspecific.crowd.discount.list\nspecific.crowd.discount.info\nmember.tag.list\nspecific.crowd.discount.loglist","icon":null,"is_show":true,"alias_name":"SpecificCrowdDiscount","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f1a\u5458\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"900","company_id":0,"name":"\u4f18\u5148\u8d2d","url":"\/marketing\/membermarket\/memberpreference","sort":3,"is_menu":true,"pid":"895","apis":"","icon":null,"is_show":true,"alias_name":"memberpreference","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f1a\u5458\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"901","company_id":0,"name":"\u81ea\u52a8\u5316\u8425\u9500","url":"\/marketing\/membermarket\/marketingactivity","sort":4,"is_menu":true,"pid":"895","apis":"promotions.activity.lists\npromotions.activity.validNum\nmembercard.grade.list\npromotions.activity.create\npromotions.activity.invalid\ngoods.items.lists\ncard.list\nmembercard.vipgrade.list","icon":null,"is_show":true,"alias_name":"marketingactivity","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f1a\u5458\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"902","company_id":0,"name":"\u5546\u54c1\u63a8\u8350","url":"\/marketing\/membermarket\/recommendlike","sort":5,"is_menu":true,"pid":"895","apis":"recommendlike.list\nrecommendlike.update\nrecommendlike.list\nrecommendlike.save\nrecommendlike.delete\ngoods.items.lists","icon":null,"is_show":true,"alias_name":"recommendlike","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4f1a\u5458\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"903","company_id":0,"name":"\u4e92\u52a8\u8425\u9500","url":"\/marketing\/fissionmarketing","sort":4,"is_menu":true,"pid":"882","apis":"","icon":null,"is_show":true,"alias_name":"fissionmarketing","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u4e92\u52a8\u8425\u9500"},"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"904","company_id":0,"name":"\u62fc\u56e2","url":"\/marketing\/fissionmarketing\/groupsindex","sort":1,"is_menu":true,"pid":"903","apis":"promotions.groups.list\npromotions.groups.detail\npromotions.groups.teamlist\npromotions.groups.teaminfo\npromotions.groups.create\npromotions.groups.update\npromotions.groups.finish\npromotions.groups.delete\ngoods.items.lists\norder.info.get\nmember.info\nwechat.material.upload\ncurrency.get.default","icon":null,"is_show":true,"alias_name":"groupsindex","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4e92\u52a8\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"905","company_id":0,"name":"\u5206\u9500\u63a8\u5e7f","url":"\/marketing\/popularize","sort":15,"is_menu":true,"pid":"882","apis":"","icon":null,"is_show":true,"alias_name":"popularize","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"906","company_id":0,"name":"\u57fa\u7840\u8bbe\u7f6e","url":"\/marketing\/popularize\/popularizesetting","sort":1,"is_menu":true,"pid":"905","apis":"popularize.config.get\npopularize.config.set","icon":null,"is_show":true,"alias_name":"popularizesetting","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u9500\u63a8\u5e7f","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"907","company_id":0,"name":"\u63a8\u5e7f\u5458\u7ba1\u7406","url":"\/marketing\/popularize\/popularizelist","sort":2,"is_menu":true,"pid":"905","apis":"popularize.brokerage.count\npopularize.brokerage.logs\npopularize.promoter.children.list\npopularize.promoter.list.get\npopularize.promoter.remove\npopularize.promoter.grade.put\npopularize.promoter.disabled\npopularize.promoter.config.get\npopularize.promoter.add\npopularize.promoter.shop.update","icon":null,"is_show":true,"alias_name":"popularizelist","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u9500\u63a8\u5e7f","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"908","company_id":0,"name":"\u7b49\u7ea7\u7ba1\u7406","url":"\/marketing\/popularize\/promotersetting","sort":3,"is_menu":true,"pid":"905","apis":"popularize.promoter.config.get\npopularize.promoter.config.set","icon":null,"is_show":true,"alias_name":"promotersetting","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u9500\u63a8\u5e7f","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"909","company_id":0,"name":"\u63a8\u5e7f\u5458\u4e1a\u7ee9","url":"\/marketing\/popularize\/popularizedata","sort":4,"is_menu":true,"pid":"905","apis":"","icon":null,"is_show":true,"alias_name":"popularizedata","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u9500\u63a8\u5e7f","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"910","company_id":0,"name":"\u63d0\u73b0\u7533\u8bf7","url":"\/marketing\/popularize\/popularizewithdraw","sort":5,"is_menu":true,"pid":"905","apis":"popularize.cash_withdrawals.list.get\npopularize.cash_withdrawals.process\npopularize.cash_withdrawals.pay.list.get\npopularize.brokerage.count","icon":"money-check-alt","is_show":true,"alias_name":"popularizewithdraw","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u9500\u63a8\u5e7f","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"911","company_id":0,"name":"\u5206\u9500\u5546\u54c1","url":"\/marketing\/popularize\/popularizegoods","sort":6,"is_menu":true,"pid":"905","apis":"goods.rebateconf","icon":null,"is_show":true,"alias_name":"popularizegoods","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u9500\u63a8\u5e7f","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"912","company_id":0,"name":"\u4efb\u52a1\u4f63\u91d1\u660e\u7ec6","url":"\/marketing\/popularize\/taskbrokerage","sort":7,"is_menu":true,"pid":"905","apis":"popularize.task.brokerage.logs","icon":null,"is_show":true,"alias_name":"taskbrokerage","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u9500\u63a8\u5e7f","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"913","company_id":0,"name":"\u4efb\u52a1\u4f63\u91d1\u7edf\u8ba1","url":"\/marketing\/popularize\/taskbrokeragecount","sort":8,"is_menu":true,"pid":"905","apis":"popularize.task.brokerage.count\npopularize.task.brokerage.count.export","icon":null,"is_show":true,"alias_name":"taskbrokeragecount","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u9500\u63a8\u5e7f","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"914","company_id":0,"name":"\u6d3b\u52a8\u62a5\u540d","url":"\/marketing\/marketing\/apply","sort":23,"is_menu":true,"pid":"882","apis":"","icon":null,"is_show":true,"alias_name":"apply","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["b2c","platform","standard","in_purchase"]},{"shopmenu_id":"915","company_id":0,"name":"\u5168\u90e8\u6d3b\u52a8","url":"\/marketing\/marketing\/apply\/registrationactivity","sort":0,"is_menu":true,"pid":"914","apis":"selfhelp.registrationActivity.list\nselfhelp.registrationActivity.add\nselfhelp.template.info\nselfhelp.template.delete","icon":null,"is_show":true,"alias_name":"Registrationactivity","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u6d3b\u52a8\u62a5\u540d","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"916","company_id":0,"name":"\u62a5\u540d\u8bb0\u5f55","url":"\/marketing\/marketing\/apply\/Registrationrecord","sort":1,"is_menu":true,"pid":"914","apis":"selfhelp.registrationRecord.list\nselfhelp.registrationRecord.export\nselfhelp.registrationRecord.info","icon":null,"is_show":true,"alias_name":"Registrationrecord","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u6d3b\u52a8\u62a5\u540d","isChildrenMenu":false,"menu_type":["b2c","standard","platform"]},{"shopmenu_id":"917","company_id":0,"name":"\u8868\u5355\u5143\u7d20","url":"\/marketing\/marketing\/apply\/formattrs","sort":1,"is_menu":true,"pid":"914","apis":"selfhelp.form.list","icon":null,"is_show":true,"alias_name":"formattrs","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u6d3b\u52a8\u62a5\u540d","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"918","company_id":0,"name":"\u8868\u5355\u6a21\u677f","url":"\/marketing\/marketing\/apply\/formtemplate","sort":1,"is_menu":true,"pid":"914","apis":"selfhelp.template.list\nselfhelp.template.info\nselfhelp.template.delete","icon":null,"is_show":true,"alias_name":"formtemplate","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u6d3b\u52a8\u62a5\u540d","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"919","company_id":0,"name":"\u5c0f\u7a0b\u5e8f\u76f4\u64ad","url":"\/marketing\/liveroomlist","sort":24,"is_menu":true,"pid":"882","apis":"promotions.liverooms","icon":null,"is_show":true,"alias_name":"liveroomlist","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"920","company_id":0,"name":"\u5185\u5bb9","url":"\/site","sort":7,"is_menu":true,"pid":"0","apis":"","icon":"newspaper1","is_show":true,"alias_name":"site","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all","b2c","platform","standard"]},{"shopmenu_id":"921","company_id":0,"name":"\u8f6f\u6587","url":"\/site\/article","sort":1,"is_menu":true,"pid":"920","apis":"","icon":null,"is_show":true,"alias_name":"article","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u5185\u5bb9","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"922","company_id":0,"name":"\u8f6f\u6587\u5217\u8868","url":"\/site\/article\/planting","sort":1,"is_menu":true,"pid":"921","apis":"article.create\narticle.update\narticle.delete\narticle.list\narticle.info\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\narticle.update.sortstatus\narticle.list.category","icon":null,"is_show":true,"alias_name":"planting","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u8f6f\u6587","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"923","company_id":0,"name":"\u8f6f\u6587\u9891\u9053","url":"\/site\/article\/articlecolumns","sort":2,"is_menu":true,"pid":"921","apis":"","icon":null,"is_show":true,"alias_name":"articlecolumns","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u8f6f\u6587","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"924","company_id":0,"name":"\u7d20\u6750","url":"\/site\/material","sort":1,"is_menu":true,"pid":"920","apis":"","icon":null,"is_show":true,"alias_name":"material","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u5185\u5bb9","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"925","company_id":0,"name":"\u7d20\u6750\u7ba1\u7406","url":"\/site\/material\/brandmaterial","sort":1,"is_menu":true,"pid":"924","apis":"espier.oss.uploadToken.get\nespier.image.save","icon":null,"is_show":true,"alias_name":"brandmaterial","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u7d20\u6750","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"926","company_id":0,"name":"UGC\u793e\u533a","url":"\/site\/ugc","sort":3,"is_menu":true,"pid":"920","apis":"","icon":null,"is_show":true,"alias_name":"ugc","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u5185\u5bb9","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"927","company_id":0,"name":"\u7b14\u8bb0\u7ba1\u7406","url":"\/site\/ugc\/ugcindex","sort":1,"is_menu":true,"pid":"926","apis":"ugc.post.list\nugc.badge.list\nugc.setting.point.getSetting\nugc.post.list\nugc.comment.list\nugc.post.detail","icon":null,"is_show":true,"alias_name":"ugcindex","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"UGC\u793e\u533a","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"928","company_id":0,"name":"\u89d2\u6807\u7ba1\u7406","url":"\/site\/ugc\/ugcflags","sort":2,"is_menu":true,"pid":"926","apis":"","icon":null,"is_show":true,"alias_name":"ugcflags","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"UGC\u793e\u533a","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"929","company_id":0,"name":"\u7b14\u8bb0\u8bdd\u9898","url":"\/site\/ugc\/ugctopic","sort":3,"is_menu":true,"pid":"926","apis":"ugc.topic.list","icon":null,"is_show":true,"alias_name":"ugctopic","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"UGC\u793e\u533a","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"930","company_id":0,"name":"\u7b14\u8bb0\u8bc4\u8bba","url":"\/site\/ugc\/ugcreview","sort":4,"is_menu":true,"pid":"926","apis":"ugc.comment.detail","icon":null,"is_show":true,"alias_name":"ugcreview","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"UGC\u793e\u533a","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"931","company_id":0,"name":"\u8bc4\u8bba\u8bbe\u7f6e","url":"\/site\/ugc\/ugcpoint","sort":5,"is_menu":true,"pid":"926","apis":"","icon":null,"is_show":true,"alias_name":"ugcpoint","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"UGC\u793e\u533a","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"932","company_id":0,"name":"\u5206\u4eab\u8f6c\u53d1","url":"\/site\/share","sort":4,"is_menu":true,"pid":"920","apis":"","icon":null,"is_show":true,"alias_name":"share","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u5185\u5bb9","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"933","company_id":0,"name":"\u5206\u4eab\u8bbe\u7f6e","url":"\/site\/share\/sharesetting","sort":1,"is_menu":true,"pid":"932","apis":"share.setting.set\nshare.setting.get","icon":null,"is_show":true,"alias_name":"sharesetting","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u5206\u4eab\u8f6c\u53d1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"934","company_id":0,"name":"\u7528\u6237\u8bc4\u4ef7","url":"\/site\/evaluate","sort":5,"is_menu":true,"pid":"920","apis":"","icon":null,"is_show":true,"alias_name":"evaluate","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u5185\u5bb9","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"935","company_id":0,"name":"\u5546\u54c1\u8bc4\u4ef7","url":"\/site\/evaluate\/rate","sort":1,"is_menu":true,"pid":"934","apis":"traderate.list.get","icon":null,"is_show":true,"alias_name":"rate","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u7528\u6237\u8bc4\u4ef7","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"936","company_id":0,"name":"\u8d22\u52a1","url":"\/financial","sort":8,"is_menu":true,"pid":"0","apis":"","icon":"money-check-alt","is_show":true,"alias_name":"financial","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"937","company_id":0,"name":"\u4ea4\u6613\u6d41\u6c34","url":"\/financial\/financialManage","sort":1,"is_menu":true,"pid":"936","apis":"","icon":null,"is_show":true,"alias_name":"financialManage","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":2,"parent_name":"\u8d22\u52a1","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"938","company_id":0,"name":"\u4ea4\u6613\u5355","url":"\/financial\/financialManage\/servicepayment","sort":1,"is_menu":true,"pid":"937","apis":"shops.lists\norder.trade.list\ntrades.list.export","icon":null,"is_show":true,"alias_name":"financialManageservicepayment","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"level":3,"parent_name":"\u4ea4\u6613\u6d41\u6c34","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"939","company_id":0,"name":"\u9000\u6b3e\u5355","url":"\/financial\/financialManage\/aftersalesrefundlist","sort":2,"is_menu":true,"pid":"937","apis":"refund.list\nrefund.logexport","icon":null,"is_show":true,"alias_name":"financialFinancialManageAftersalesrefundlist","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u9000\u6b3e\u5355"},"level":3,"parent_name":"\u4ea4\u6613\u6d41\u6c34","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"940","company_id":0,"name":"\u9000\u6b3e\u5931\u8d25","url":"\/financial\/financialManage\/Refunderrorlogs","sort":3,"is_menu":true,"pid":"937","apis":"trade.refunderrorlogs.list","icon":null,"is_show":true,"alias_name":"Refunderrorlogs","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u9000\u6b3e\u5931\u8d25"},"level":3,"parent_name":"\u4ea4\u6613\u6d41\u6c34","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"941","company_id":0,"name":"\u7ed3\u7b97","url":"\/financial\/settlement","sort":1,"is_menu":true,"pid":"936","apis":null,"icon":null,"is_show":true,"alias_name":"settlement","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u7ed3\u7b97"},"level":2,"parent_name":"\u8d22\u52a1","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"942","company_id":0,"name":"\u7ed3\u7b97\u6c47\u603b","url":"\/financial\/settlement\/summary","sort":1,"is_menu":true,"pid":"941","apis":"merchant.list\nstatement.summarized.get\nstatement.confirm.post\nstatement.detail.get\nstatement.summarized.export\nstatement.detail.export","icon":null,"is_show":true,"alias_name":"summary","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u7ed3\u7b97\u6c47\u603b"},"level":3,"parent_name":"\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"943","company_id":0,"name":"\u7ed3\u7b97\u914d\u7f6e","url":"\/financial\/settlement\/configure","sort":1,"is_menu":true,"pid":"941","apis":"statement.period.default.setting.get\nstatement.period.distributor.setting.get\nstatement.period.setting.set","icon":null,"is_show":true,"alias_name":"configure","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u7ed3\u7b97\u914d\u7f6e"},"level":3,"parent_name":"\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"944","company_id":0,"name":"\u4f9b\u5e94\u5546\u7ed3\u7b97","url":"\/financial\/settlement_supplier","sort":1,"is_menu":true,"pid":"936","apis":"","icon":null,"is_show":true,"alias_name":"settlement_supplier","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u4f9b\u5e94\u5546\u7ed3\u7b97"},"level":2,"parent_name":"\u8d22\u52a1","isChildrenMenu":true,"menu_type":["standard"]},{"shopmenu_id":"945","company_id":0,"name":"\u7ed3\u7b97\u914d\u7f6e","url":"\/financial\/settlement_supplier\/configure_supplier","sort":1,"is_menu":true,"pid":"944","apis":"statement.period.default.setting.get\nstatement.period.supplier.setting.get","icon":null,"is_show":true,"alias_name":"configure_supplier","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u7ed3\u7b97\u914d\u7f6e"},"level":3,"parent_name":"\u4f9b\u5e94\u5546\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"946","company_id":0,"name":"\u7ed3\u7b97\u6c47\u603b","url":"\/financial\/settlement_supplier\/summary_supplier","sort":1,"is_menu":true,"pid":"944","apis":"statement.summarized.get","icon":null,"is_show":true,"alias_name":"summary_supplier","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u7ed3\u7b97\u6c47\u603b"},"level":3,"parent_name":"\u4f9b\u5e94\u5546\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"947","company_id":0,"name":"\u7ebf\u4e0b\u8f6c\u8d26","url":"\/financial\/examine","sort":2,"is_menu":true,"pid":"936","apis":"","icon":null,"is_show":true,"alias_name":"examine","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u7ebf\u4e0b\u8f6c\u8d26"},"level":2,"parent_name":"\u8d22\u52a1","isChildrenMenu":true,"menu_type":["all","in_purchase"]},{"shopmenu_id":"948","company_id":0,"name":"\u8f6c\u8d26\u51ed\u8bc1\u5ba1\u6838","url":"\/financial\/examine\/transfer","sort":1,"is_menu":true,"pid":"947","apis":"order.offline_payment.get_list\nespier.offline.backaccount.lists","icon":null,"is_show":true,"alias_name":"transfer","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u8f6c\u8d26\u51ed\u8bc1\u5ba1\u6838"},"level":3,"parent_name":"\u7ebf\u4e0b\u8f6c\u8d26","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"949","company_id":0,"name":"\u53d1\u7968","url":"\/financial\/invoice","sort":5,"is_menu":true,"pid":"936","apis":"","icon":null,"is_show":true,"alias_name":"invoice","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u53d1\u7968"},"level":2,"parent_name":"\u8d22\u52a1","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"950","company_id":0,"name":"\u5f00\u7968\u7533\u8bf7","url":"\/financial\/invoice\/invoice-list","sort":1,"is_menu":true,"pid":"949","apis":null,"icon":null,"is_show":true,"alias_name":"invoice-list","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5f00\u7968\u7533\u8bf7"},"level":3,"parent_name":"\u53d1\u7968","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"951","company_id":0,"name":"\u53d1\u7968\u8bbe\u7f6e","url":"\/financial\/invoice\/setting","sort":2,"is_menu":true,"pid":"949","apis":"financial.examine.invoiceSetting","icon":null,"is_show":true,"alias_name":"invoiceSetting","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u53d1\u7968\u8bbe\u7f6e"},"level":3,"parent_name":"\u53d1\u7968","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"952","company_id":0,"name":"\u9500\u65b9\u4fe1\u606f","url":"\/financial\/invoice\/information","sort":3,"is_menu":true,"pid":"949","apis":"financial.examine.invoiceInfo","icon":null,"is_show":true,"alias_name":"invoiceInfo","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u9500\u65b9\u4fe1\u606f"},"level":3,"parent_name":"\u53d1\u7968","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"953","company_id":0,"name":"\u5f00\u7968\u7a0e\u7387","url":"\/financial\/invoice\/invoiceTax","sort":4,"is_menu":true,"pid":"949","apis":"financial.examine.invoiceTax","icon":null,"is_show":true,"alias_name":"invoiceTax","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5f00\u7968\u7a0e\u7387"},"level":3,"parent_name":"\u53d1\u7968","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"954","company_id":0,"name":"\u4e13\u7968\u786e\u8ba4\u4e66","url":"\/financial\/invoice\/invoiceConfirmation","sort":5,"is_menu":true,"pid":"949","apis":"financial.examine.invoiceConfirmation","icon":null,"is_show":true,"alias_name":"invoiceConfirmation","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u4e13\u7968\u786e\u8ba4\u4e66"},"level":3,"parent_name":"\u53d1\u7968","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"955","company_id":0,"name":"\u6570\u636e","url":"\/companydata","sort":9,"is_menu":true,"pid":"0","apis":"","icon":"poll","is_show":true,"alias_name":"companydata","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u6570\u636e"},"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"956","company_id":0,"name":"\u7edf\u8ba1","url":"\/companydata\/statistics","sort":1,"is_menu":true,"pid":"955","apis":null,"icon":null,"is_show":true,"alias_name":"statistics","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u7edf\u8ba1"},"level":2,"parent_name":"\u6570\u636e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"957","company_id":0,"name":"\u5546\u54c1\u7edf\u8ba1","url":"\/companydata\/statistics\/goodsstatistics","sort":1,"is_menu":true,"pid":"956","apis":"datacube.goods.data\norder.delivervstaff.confirm\nemployeepurchase.activity.list","icon":null,"is_show":true,"alias_name":"goodsstatistics","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5546\u54c1\u7edf\u8ba1"},"level":3,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"958","company_id":0,"name":"\u4ea4\u6613\u7edf\u8ba1","url":"\/companydata\/statistics\/orderstatistics","sort":2,"is_menu":true,"pid":"956","apis":"datacube.company.data","icon":null,"is_show":true,"alias_name":"orderstatistics","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u4ea4\u6613\u7edf\u8ba1"},"level":3,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"959","company_id":0,"name":"\u4f1a\u5458\u7edf\u8ba1","url":"\/companydata\/statistics\/memberstatistics","sort":3,"is_menu":true,"pid":"956","apis":"datacube.company.data","icon":null,"is_show":true,"alias_name":"member-statistics","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u4f1a\u5458\u7edf\u8ba1"},"level":3,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"960","company_id":0,"name":"\u5e97\u94fa\u7edf\u8ba1","url":"\/companydata\/statistics\/distributordata","sort":4,"is_menu":true,"pid":"956","apis":"datacube.distributor.data","icon":null,"is_show":true,"alias_name":"distributordata","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5e97\u94fa\u7edf\u8ba1"},"level":3,"parent_name":"\u7edf\u8ba1","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"961","company_id":0,"name":"\u62a5\u8868","url":"\/companydata\/report","sort":2,"is_menu":true,"pid":"955","apis":null,"icon":null,"is_show":true,"alias_name":"report","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u62a5\u8868"},"level":2,"parent_name":"\u6570\u636e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"962","company_id":0,"name":"\u5bfc\u51fa\u8bb0\u5f55","url":"\/companydata\/report\/baseexport","sort":1,"is_menu":true,"pid":"961","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"baseexport","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5bfc\u51fa\u8bb0\u5f55"},"level":3,"parent_name":"\u62a5\u8868","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"963","company_id":0,"name":"\u88c5\u4fee","url":"\/wxapp","sort":11,"is_menu":true,"pid":"0","apis":"wechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list\nwechat.pre_auth_url\nwechat.wxa.testqrcode\nwechat.wxa.tryrelease\nwechat.bind","icon":"brush-copy","is_show":true,"alias_name":"wxapp-template","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u88c5\u4fee"},"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"964","company_id":0,"name":"\u79fb\u52a8\u5546\u57ce","url":"\/wxapp\/manage","sort":1,"is_menu":true,"pid":"963","apis":"wechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list\nwechat.pre_auth_url\nwechat.wxa.testqrcode\nwechat.wxa.tryrelease\nwechat.bind\npagestemplateset.set\npagestemplateset.getInfo\npagestemplate.lists\npagestemplate.add\npagestemplate.edit\npagestemplate.detail\npagestemplate.copy\npagestemplate.delete\npagestemplate.modifyStatus\npagestemplate.sync\nmemberCenterShare.set\nmemberCenterShare.getInfo\nwechat.wxa.revertcoderelease","icon":null,"is_show":true,"alias_name":"wxappmanage","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u79fb\u52a8\u5546\u57ce"},"level":2,"parent_name":"\u88c5\u4fee","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"965","company_id":0,"name":"\u9996\u9875","url":"\/wxapp\/manage\/templateedit","sort":1,"is_menu":true,"pid":"964","apis":"wechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list\nwechat.pre_auth_url\nwechat.wxa.testqrcode\nwechat.wxa.tryrelease\nwechat.bind\nwechat.wxa.customizepage.list\nrecommendlike.list\npagestemplate.lists\npagestemplateset.getInfo\npagestemplate.modifyStatus\npagestemplateset.set\npagestemplate.copy\npagestemplate.delete\npagestemplate.edit\npagestemplate.add\nwxexternalconfigroutes.list\nwxexternalconfig.list\ngoods.sku.lists\nselfhelp.registrationActivity.easylist\npagestemplate.sync\nselfhelp.registrationActivity.easylist","icon":null,"is_show":true,"alias_name":"wxapp-template-edit","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u9996\u9875"},"level":3,"parent_name":"\u79fb\u52a8\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"966","company_id":0,"name":"\u9644\u8fd1\u5e97\u94fa\u9875","url":"\/wxapp\/manage\/classificationTemplate","sort":2,"is_menu":true,"pid":"964","apis":"","icon":null,"is_show":true,"alias_name":"classificationTemplate","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u9644\u8fd1\u5e97\u94fa\u9875"},"level":3,"parent_name":"\u79fb\u52a8\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"967","company_id":0,"name":"\u5206\u7c7b\u9875","url":"\/wxapp\/manage\/editcategory","sort":2,"is_menu":true,"pid":"964","apis":"wechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list","icon":null,"is_show":true,"alias_name":"wxapp-editcategory","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5206\u7c7b\u9875"},"level":3,"parent_name":"\u79fb\u52a8\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"968","company_id":0,"name":"\u81ea\u5b9a\u4e49\u9875","url":"\/wxapp\/manage\/custompage","sort":3,"is_menu":true,"pid":"964","apis":"wechat.wxa.customizepage.update\nwechat.wxa.customizepage.delete\nwechat.wxa.customizepage.add\nwechat.wxa.customizepage.list\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.summarytrend\nwechat.wxa.stats.visittrend\nwechat.wxa.stats.visitpage\nwechat.wxa.stats.userportrait\nmonitors.list\nmonitors.detail\nmonitors.delete\nmonitors.add\nmonitors.relsources.detail\nmonitors.relsources.list\nmonitors.relsources.delete\nsource.list\nsource.create\nsource.detail\nsource.delete\nsource.update\nmonitors.stats\nwechat.wxa.create\nwechat.wxa.authorizer\nwechat.wxa.detail\nwechat.wxa.codeunlimit\nwechat.wxa.pageparams.setting.set\nwechat.wxa.pageparams.setting.get\nwechat.wxa.pageparams.setting.update\nwechat.wxa.template.list\nwechat.wxa.opentemplate.list\nwechat.wxa.opentemplate\nwechat.wxa.pageparams.setting.all.set\nminiprogram.pages\nwechat.material.list\nwechat.material.upload\ngoods.items.lists\ncard.list\ngoods.category.lists\narticle.list\nwechat.pre_auth_url\nwechat.wxa.testqrcode\nwechat.wxa.tryrelease\nwechat.bind\nwechat.wxa.customizepage.update\nwechat.wxa.customizepage.delete\nwechat.wxa.customizepage.add\nwechat.wxa.customizepage.list\n","icon":null,"is_show":true,"alias_name":"wxapp-custompage","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u81ea\u5b9a\u4e49\u9875"},"level":3,"parent_name":"\u79fb\u52a8\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"969","company_id":0,"name":"\u5546\u57ce\u914d\u8272","url":"\/wxapp\/manage\/colorstyle","sort":5,"is_menu":true,"pid":"964","apis":"","icon":null,"is_show":true,"alias_name":"colorstyle","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5546\u57ce\u914d\u8272"},"level":3,"parent_name":"\u79fb\u52a8\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"970","company_id":0,"name":"\u5546\u57ce\u4fe1\u606f","url":"\/wxapp\/manage\/wxshopsetting","sort":6,"is_menu":true,"pid":"964","apis":"shops.setting.get\nshops.setting.set","icon":null,"is_show":true,"alias_name":"wxshopsetting","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5546\u57ce\u4fe1\u606f"},"level":3,"parent_name":"\u79fb\u52a8\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"971","company_id":0,"name":"\u5f00\u5c4f\u5e7f\u544a","url":"\/wxapp\/manage\/openscreenad","sort":8,"is_menu":true,"pid":"964","apis":"openscreenad.set.info","icon":null,"is_show":true,"alias_name":"openscreenad","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5f00\u5c4f\u5e7f\u544a"},"level":3,"parent_name":"\u79fb\u52a8\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"972","company_id":0,"name":"PC\u5546\u57ce","url":"\/wxapp\/pcmall","sort":2,"is_menu":true,"pid":"963","apis":"","icon":null,"is_show":true,"alias_name":"pcmall","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"PC\u5546\u57ce"},"level":2,"parent_name":"\u88c5\u4fee","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"973","company_id":0,"name":"\u6a21\u677f\u5217\u8868","url":"\/wxapp\/pcmall\/templatelist","sort":1,"is_menu":true,"pid":"972","apis":"pctemplate.lists\npctemplate.edit\npctemplate.getHeaderOrFooter\npctemplate.getTemplateContent\npctemplate.saveTemplateContent\npctemplate.saveHeaderOrFooter\npagestemplate.detail","icon":null,"is_show":true,"alias_name":"templatelist","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u6a21\u677f\u5217\u8868"},"level":3,"parent_name":"PC\u5546\u57ce","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"974","company_id":0,"name":"\u6a21\u677f\u7f16\u8f91","url":"\/wxapp\/pcmall\/design","sort":2,"is_menu":false,"pid":"972","apis":"pctemplate.getHeaderOrFooter\npctemplate.getTemplateContent\npctemplate.saveTemplateContent\npctemplate.saveHeaderOrFooter\npagestemplate.detail","icon":null,"is_show":true,"alias_name":"design","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u6a21\u677f\u7f16\u8f91"},"level":3,"parent_name":"PC\u5546\u57ce","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"975","company_id":0,"name":"\u767b\u5f55\u9875","url":"\/wxapp\/pcmall\/loginPageSetting","sort":2,"is_menu":true,"pid":"972","apis":"pctemplate.getLoginPageSetting","icon":null,"is_show":true,"alias_name":"loginPageSetting","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u767b\u5f55\u9875"},"level":3,"parent_name":"PC\u5546\u57ce","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"976","company_id":0,"name":"SEO\u914d\u7f6e","url":"\/wxapp\/pcmall\/seo","sort":3,"is_menu":true,"pid":"972","apis":"pcdecoration.tdkglobalset.info\npcdecoration.tdkglobalset.save","icon":null,"is_show":true,"alias_name":"seo","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"SEO\u914d\u7f6e"},"level":3,"parent_name":"PC\u5546\u57ce","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"977","company_id":0,"name":"\u9875\u9762SEO","url":"\/wxapp\/pcmall\/pageseo","sort":4,"is_menu":true,"pid":"972","apis":"pcdecoration.tdkgivenset.info\npcdecoration.tdkgivenset.save","icon":null,"is_show":true,"alias_name":"pageseo","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u9875\u9762SEO"},"level":3,"parent_name":"PC\u5546\u57ce","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"978","company_id":0,"name":"\u79ef\u5206\u5546\u57ce","url":"\/rewardsStore","sort":11,"is_menu":true,"pid":"0","apis":null,"icon":"funds","is_show":true,"alias_name":"rewardsStore","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u79ef\u5206\u5546\u57ce"},"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"979","company_id":0,"name":"\u79ef\u5206\u5546\u54c1","url":"\/rewardsStore\/rewardItem","sort":1,"is_menu":true,"pid":"978","apis":"pointsmall.goods.items.lists\npointsmall.goods.items.detail\n","icon":null,"is_show":true,"alias_name":"rewardItemManagement","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u79ef\u5206\u5546\u54c1"},"level":2,"parent_name":"\u79ef\u5206\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"980","company_id":0,"name":"\u79ef\u5206\u8ba2\u5355","url":"\/rewardsStore\/rewardorder","sort":1,"is_menu":true,"pid":"978","apis":null,"icon":null,"is_show":true,"alias_name":"rewardordermanagement","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u79ef\u5206\u8ba2\u5355"},"level":2,"parent_name":"\u79ef\u5206\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"981","company_id":0,"name":"\u57fa\u7840\u914d\u7f6e","url":"\/rewardsStore\/basicSettings","sort":1,"is_menu":true,"pid":"978","apis":"pointsmall.setting.get","icon":null,"is_show":true,"alias_name":"basicSettings","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u57fa\u7840\u914d\u7f6e"},"level":2,"parent_name":"\u79ef\u5206\u5546\u57ce","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"982","company_id":0,"name":"\u5e94\u7528","url":"\/applications","sort":12,"is_menu":true,"pid":"0","apis":"adapay.open_account.step\npointsmall.goods.items.lists\nadapay.open_account.step\nadapay.regions.list\nadapay.regions.list","icon":"yingyong-01","is_show":true,"alias_name":"applications","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5e94\u7528"},"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"983","company_id":0,"name":"\u6597\u62f1\u5206\u8d26","url":"\/applications\/bspay","sort":1,"is_menu":true,"pid":"982","apis":"bspay.sub_approve.list","icon":null,"is_show":true,"alias_name":"bspay","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u6597\u62f1\u5206\u8d26"},"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"984","company_id":0,"name":"\u7528\u6237\u8fdb\u4ef6\u5ba1\u6279","url":"\/applications\/bspay\/user_audit","sort":1,"is_menu":true,"pid":"983","apis":"bspay.sub_approve.list\nbspay.trade.getList","icon":null,"is_show":true,"alias_name":"user_audit","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u7528\u6237\u8fdb\u4ef6\u5ba1\u6279"},"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"985","company_id":0,"name":"\u5206\u8d26\u660e\u7ec6","url":"\/applications\/bspay\/trades","sort":1,"is_menu":true,"pid":"983","apis":null,"icon":null,"is_show":true,"alias_name":"bspay_trades","version":1,"disabled":false,"created":1770278868,"updated":1770278868,"name_lang":{"zh-CN":"\u5206\u8d26\u660e\u7ec6"},"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"986","company_id":0,"name":"\u5e94\u7528","url":"\/applications\/adapay","sort":2,"is_menu":true,"pid":"982","apis":"","icon":null,"is_show":true,"alias_name":"adapay","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5e94\u7528"},"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"987","company_id":0,"name":"\u6597\u62f1\u5206\u8d26","url":"\/applications\/adapay\/adapay_trades","sort":1,"is_menu":true,"pid":"986","apis":"adapay.drawcash.getList\nadapay.trade.getList","icon":null,"is_show":true,"alias_name":"adapay_trades","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u6597\u62f1\u5206\u8d26"},"level":3,"parent_name":"\u5e94\u7528","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"988","company_id":0,"name":"\u7528\u6237\u8fdb\u4ef6\u5ba1\u6279","url":"\/applications\/adapay\/adapay_cash","sort":2,"is_menu":true,"pid":"986","apis":null,"icon":null,"is_show":true,"alias_name":"adapay_cash","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u7528\u6237\u8fdb\u4ef6\u5ba1\u6279"},"level":3,"parent_name":"\u5e94\u7528","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"989","company_id":0,"name":"\u5206\u8d26\u660e\u7ec6","url":"\/applications\/adapay\/adapay_cash_setting","sort":3,"is_menu":true,"pid":"986","apis":"adapay.sub_approve.draw_limit_get\nadapay.sub_approve.list","icon":null,"is_show":true,"alias_name":"adapay_cash_setting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5206\u8d26\u660e\u7ec6"},"level":3,"parent_name":"\u5e94\u7528","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"990","company_id":0,"name":"Adapay\u5206\u8d26","url":"\/applications\/adapay\/adapay_member_audit","sort":4,"is_menu":true,"pid":"986","apis":null,"icon":null,"is_show":true,"alias_name":"adapay_member_audit","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"Adapay\u5206\u8d26"},"level":3,"parent_name":"\u5e94\u7528","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"991","company_id":0,"name":"\u4f01\u4e1a\u8d2d","url":"\/applications\/ec","sort":3,"is_menu":true,"pid":"982","apis":"","icon":null,"is_show":true,"alias_name":"ec","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u4f01\u4e1a\u8d2d"},"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"992","company_id":0,"name":"\u4f01\u4e1a\u7ba1\u7406","url":"\/applications\/ec\/company","sort":1,"is_menu":true,"pid":"991","apis":"employeepurchase.enterprise.list","icon":null,"is_show":true,"alias_name":"company-admin","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u4f01\u4e1a\u7ba1\u7406"},"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"993","company_id":0,"name":"\u5458\u5de5\u7ba1\u7406","url":"\/applications\/ec\/employee","sort":2,"is_menu":true,"pid":"991","apis":"employeepurchase.employee.list","icon":null,"is_show":true,"alias_name":"employee-admin","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5458\u5de5\u7ba1\u7406"},"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"994","company_id":0,"name":"\u6d3b\u52a8\u7ba1\u7406","url":"\/applications\/ec\/purchaseactivity","sort":3,"is_menu":true,"pid":"991","apis":"promotions.employeepurchase.list\npromotions.employeepurchase.info\npromotions.employeepurchase.add\npromotions.employeepurchase.update\nespier.upload.template.export\nespier.upload\npromotions.employeepurchase.endactivity\npromotions.employeepurchase.dependents.lists\npromotions.employeepurchase.dependents.export\nemployeepurchase.activity.list\nespier.image.cat.children\nemployeepurchase.activity.create\nemployeepurchase.activity.info\nemployeepurchase.activity.items.list\nemployeepurchase.activity.items.add\nemployeepurchase.activity.items.delete\nemployeepurchase.activity.spec_items.update\nemployeepurchase.activity.items.update","icon":null,"is_show":true,"alias_name":"purchase-admin","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u6d3b\u52a8\u7ba1\u7406"},"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"995","company_id":0,"name":"\u8ba2\u5355\u7ba1\u7406","url":"\/applications\/ec\/purchaseorder","sort":4,"is_menu":true,"pid":"991","apis":"order.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel\nespier.subdistrict.list.get\ntrade.logistics.list\npresale.pickupcode.setting.get\nthird.jushuitan.setting.get\nemployeepurchase.activity.list\nemployeepurchase.activity.list","icon":null,"is_show":true,"alias_name":"purchase-list","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u8ba2\u5355\u7ba1\u7406"},"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"996","company_id":0,"name":"\u5bfc\u8d2d\u52a9\u624b","url":"\/applications\/guide","sort":4,"is_menu":true,"pid":"982","apis":"","icon":null,"is_show":true,"alias_name":"guide","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5bfc\u8d2d\u52a9\u624b"},"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["standard"]},{"shopmenu_id":"997","company_id":0,"name":"\u4f01\u4e1a\u5fae\u4fe1\u8bbe\u7f6e","url":"\/applications\/guide\/workwechat","sort":1,"is_menu":true,"pid":"996","apis":"workwechat.config.info","icon":null,"is_show":true,"alias_name":"workwechat","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u4f01\u4e1a\u5fae\u4fe1\u8bbe\u7f6e"},"level":3,"parent_name":"\u5bfc\u8d2d\u52a9\u624b","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"998","company_id":0,"name":"\u5bfc\u8d2d\u8d27\u67b6\u6a21\u677f","url":"\/applications\/guide\/salespersonshelfindex","sort":2,"is_menu":true,"pid":"996","apis":"wechat.wxa.salesperson.customizepage.get","icon":null,"is_show":true,"alias_name":"salespersonshelfindex","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5bfc\u8d2d\u8d27\u67b6\u6a21\u677f"},"level":3,"parent_name":"\u5bfc\u8d2d\u52a9\u624b","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"999","company_id":0,"name":"\u9177\u5bb6\u4e50","url":"\/applications\/kujiale","sort":5,"is_menu":true,"pid":"982","apis":"","icon":null,"is_show":true,"alias_name":"kujiale","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u9177\u5bb6\u4e50"},"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["standard"]},{"shopmenu_id":"1000","company_id":0,"name":"\u9177\u5bb6\u4e50\u5546\u54c1","url":"\/applications\/kujiale\/kujiale-products","sort":1,"is_menu":true,"pid":"999","apis":"","icon":null,"is_show":true,"alias_name":"kujiale-products","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u9177\u5bb6\u4e50\u5546\u54c1"},"level":3,"parent_name":"\u9177\u5bb6\u4e50","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"1001","company_id":0,"name":"\u8bbe\u7f6e","url":"\/setting","sort":13,"is_menu":true,"pid":"0","apis":"","icon":"cog-copy","is_show":true,"alias_name":"setting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u8bbe\u7f6e"},"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"1002","company_id":0,"name":"\u7cfb\u7edf\u8d26\u53f7","url":"\/setting\/staff","sort":0,"is_menu":true,"pid":"1001","apis":"","icon":null,"is_show":true,"alias_name":"staff","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u7cfb\u7edf\u8d26\u53f7"},"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"1003","company_id":0,"name":"\u5e73\u53f0\u8d26\u53f7","url":"\/setting\/staff\/Platformstaff","sort":1,"is_menu":true,"pid":"1002","apis":"account.create\naccount.list\naccount.info\naccount.update\naccount.delete\nroles.list\naccount.roles.permission\noperator.status.change\ndatacube.deliverystaff.data\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"platformstaff","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5e73\u53f0\u8d26\u53f7"},"level":3,"parent_name":"\u7cfb\u7edf\u8d26\u53f7","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1004","company_id":0,"name":"\u7cfb\u7edf\u89d2\u8272","url":"\/setting\/staff\/Platformstaffroles","sort":2,"is_menu":true,"pid":"1002","apis":"roles.create\nroles.list\nroles.info\nroles.update\nroles.delete\n","icon":null,"is_show":true,"alias_name":"platformstaffroles","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u7cfb\u7edf\u89d2\u8272"},"level":3,"parent_name":"\u7cfb\u7edf\u8d26\u53f7","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1005","company_id":0,"name":"\u5546\u6237\u8d26\u53f7","url":"\/setting\/staff\/storemanager","sort":3,"is_menu":true,"pid":"1002","apis":"merchant.operator.list\nmerchant.operator.update","icon":null,"is_show":true,"alias_name":"storemanager_account","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5546\u6237\u8d26\u53f7"},"level":3,"parent_name":"\u7cfb\u7edf\u8d26\u53f7","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"1006","company_id":0,"name":"\u5e97\u94fa\u8d26\u53f7","url":"\/setting\/staff\/Merchantstaff","sort":4,"is_menu":true,"pid":"1002","apis":"account.create\naccount.list\naccount.info\naccount.update\naccount.delete\nroles.list\naccount.roles.permission\nespier.subdistrict.list.get\noperator.status.change","icon":null,"is_show":true,"alias_name":"merchantstaff","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5e97\u94fa\u8d26\u53f7"},"level":3,"parent_name":"\u7cfb\u7edf\u8d26\u53f7","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"1007","company_id":0,"name":"\u83dc\u5355\u7ba1\u7406","url":"\/setting\/menumanage","sort":1,"is_menu":true,"pid":"1001","apis":"","icon":null,"is_show":true,"alias_name":"menumanage","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u83dc\u5355\u7ba1\u7406"},"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"1008","company_id":0,"name":"\u5546\u57ce\u83dc\u5355","url":"\/setting\/menumanage\/shopmenus","sort":1,"is_menu":true,"pid":"1007","apis":"super.admin.shopmenu.get\r\nsuper.admin.shopmenu.add\r\nsuper.admin.shopmenu.update\r\nsuper.admin.shopmenu.del","icon":null,"is_show":true,"alias_name":"shopmenus","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5546\u57ce\u83dc\u5355"},"level":3,"parent_name":"\u83dc\u5355\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1009","company_id":0,"name":"\u5e97\u94fa\u83dc\u5355","url":"\/setting\/menumanage\/distributormenu","sort":1,"is_menu":true,"pid":"1007","apis":"super.admin.shopmenu.get\nsuper.admin.shopmenu.add\nsuper.admin.shopmenu.update\nsuper.admin.shopmenu.del\norders.setting.get ","icon":null,"is_show":true,"alias_name":"distributormenu","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5e97\u94fa\u83dc\u5355"},"level":3,"parent_name":"\u83dc\u5355\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1010","company_id":0,"name":"\u5546\u6237\u83dc\u5355","url":"\/setting\/menumanage\/merchantmenu","sort":2,"is_menu":true,"pid":"1007","apis":null,"icon":null,"is_show":true,"alias_name":"merchantmenu","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5546\u6237\u83dc\u5355"},"level":3,"parent_name":"\u83dc\u5355\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"1011","company_id":0,"name":"\u4f9b\u5e94\u5546\u83dc\u5355","url":"\/setting\/menumanage\/suppliermenus","sort":10,"is_menu":true,"pid":"1007","apis":null,"icon":null,"is_show":true,"alias_name":"suppliermenus","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u4f9b\u5e94\u5546\u83dc\u5355"},"level":3,"parent_name":"\u83dc\u5355\u7ba1\u7406","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1012","company_id":0,"name":"\u7cfb\u7edf\u914d\u7f6e","url":"\/setting\/systemsetting","sort":2,"is_menu":true,"pid":"1001","apis":"","icon":null,"is_show":true,"alias_name":"systemsetting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u7cfb\u7edf\u914d\u7f6e"},"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"1013","company_id":0,"name":"\u901a\u7528\u8bbe\u7f6e","url":"\/setting\/systemsetting\/publicsetting","sort":1,"is_menu":true,"pid":"1012","apis":null,"icon":null,"is_show":true,"alias_name":"publicsetting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u901a\u7528\u8bbe\u7f6e"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1014","company_id":0,"name":"web\u9690\u79c1\u58f0\u660e","url":"\/setting\/systemsetting\/webPrivacyStatement","sort":1,"is_menu":true,"pid":"1012","apis":"companys.setting.getp","icon":null,"is_show":true,"alias_name":"webPrivacyStatement","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"web\u9690\u79c1\u58f0\u660e"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1015","company_id":0,"name":"\u652f\u4ed8\u914d\u7f6e","url":"\/setting\/systemsetting\/assetpayment","sort":2,"is_menu":true,"pid":"1012","apis":"trade.payment.hfpay.status\ntrade.payment.setting.get\ntrade.payment.setting.set","icon":null,"is_show":true,"alias_name":"assetpayment","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u652f\u4ed8\u914d\u7f6e"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1016","company_id":0,"name":"\u77ed\u4fe1\u670d\u52a1","url":"\/setting\/systemsetting\/datamessage","sort":3,"is_menu":true,"pid":"1012","apis":"Promotions.sms.basic\nPromotions.sms.templates.list\nPromotions.sms.template.up\nPromotions.sms.sign.get\nPromotions.sms.sign.save\naliyunsms.status.get\naliyunsms.config.get\naliyunsms.scene.getList\naliyunsms.sign.getList\naliyunsms.tmpl.getList\naliyunsms.record.getList\naliyunsms.task.list","icon":null,"is_show":true,"alias_name":"datamessage","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u77ed\u4fe1\u670d\u52a1"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1017","company_id":0,"name":"\u5730\u56fe\u670d\u52a1","url":"\/setting\/systemsetting\/mapsetting","sort":4,"is_menu":true,"pid":"1012","apis":"third.map.setting.get","icon":null,"is_show":true,"alias_name":"mapsetting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5730\u56fe\u670d\u52a1"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"1018","company_id":0,"name":"\u5f00\u7968\u914d\u7f6e","url":"\/setting\/systemsetting\/invoinceConfiguration","sort":4,"is_menu":true,"pid":"1012","apis":"","icon":null,"is_show":true,"alias_name":"invoinceConfiguration","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5f00\u7968\u914d\u7f6e"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all","platform","standard"]},{"shopmenu_id":"1019","company_id":0,"name":"\u5c0f\u7968\u6253\u5370","url":"\/setting\/systemsetting\/Yilianyun","sort":5,"is_menu":true,"pid":"1012","apis":"espier.printer.info\nespier.printer.shop.list\norder.delivervstaff.confirm\norder.deliverypackag.confirm","icon":null,"is_show":true,"alias_name":"Yilianyun","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5c0f\u7968\u6253\u5370"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"1020","company_id":0,"name":"UGC\u5ba1\u6838\u914d\u7f6e","url":"\/setting\/systemsetting\/ugctpos","sort":6,"is_menu":true,"pid":"1012","apis":null,"icon":null,"is_show":true,"alias_name":"ugctpos","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"UGC\u5ba1\u6838\u914d\u7f6e"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1024","company_id":0,"name":"\u6d88\u606f\u6a21\u677f","url":"\/setting\/systemsetting\/noticemessage","sort":7,"is_menu":false,"pid":"1012","apis":null,"icon":null,"is_show":true,"alias_name":"noticemessage","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u6d88\u606f\u6a21\u677f"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1021","company_id":0,"name":"\u5c0f\u7a0b\u5e8f\u7ba1\u7406","url":"\/setting\/systemsetting\/wxaindex","sort":7,"is_menu":true,"pid":"1012","apis":"wechat.bind.direct\nwechat.wxa.notice.templates","icon":null,"is_show":true,"alias_name":"wxaindex","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5c0f\u7a0b\u5e8f\u7ba1\u7406"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1022","company_id":0,"name":"\u6570\u636e\u5206\u6790","url":"\/setting\/systemsetting\/editdashboard","sort":7,"is_menu":false,"pid":"1012","apis":"","icon":null,"is_show":true,"alias_name":"editdashboard","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u6570\u636e\u5206\u6790"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1023","company_id":0,"name":"\u5343\u4eba\u5343\u7801","url":"\/setting\/systemsetting\/editsourcemanagement","sort":7,"is_menu":false,"pid":"1012","apis":null,"icon":null,"is_show":true,"alias_name":"editsourcemanagement","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5343\u4eba\u5343\u7801"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1025","company_id":0,"name":"\u516c\u4f17\u53f7\u6388\u6743","url":"\/setting\/systemsetting\/brand","sort":8,"is_menu":true,"pid":"1012","apis":"wechat.user.open\n","icon":null,"is_show":true,"alias_name":"brand","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u516c\u4f17\u53f7\u6388\u6743"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1026","company_id":0,"name":"\u5c0f\u7a0b\u5e8f\u5ba2\u670d","url":"\/setting\/systemsetting\/wxappchat","sort":9,"is_menu":true,"pid":"1012","apis":null,"icon":null,"is_show":true,"alias_name":"wxappchat","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5c0f\u7a0b\u5e8f\u5ba2\u670d"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1027","company_id":0,"name":"\u4e00\u6d3d\u5ba2\u670d","url":"\/setting\/systemsetting\/echat","sort":9,"is_menu":true,"pid":"1012","apis":"im.echat.info\nim.echat.save","icon":null,"is_show":true,"alias_name":"EChat","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u4e00\u6d3d\u5ba2\u670d"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1028","company_id":0,"name":"\u7f8e\u6d3d\u5ba2\u670d","url":"\/setting\/systemsetting\/meiqia","sort":10,"is_menu":true,"pid":"1012","apis":"im.meiqia.info\nim.meiqia.save","icon":null,"is_show":true,"alias_name":"meiqia","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u7f8e\u6d3d\u5ba2\u670d"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1029","company_id":0,"name":"\u65fa\u5e97\u901a","url":"\/setting\/systemsetting\/wdtSetting","sort":11,"is_menu":true,"pid":"1012","apis":"","icon":null,"is_show":true,"alias_name":"wdtSetting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u65fa\u5e97\u901a"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"1030","company_id":0,"name":"\u805a\u6c34\u6f6d","url":"\/setting\/systemsetting\/jstSetting","sort":12,"is_menu":true,"pid":"1012","apis":"","icon":null,"is_show":true,"alias_name":"jstSetting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u805a\u6c34\u6f6d"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"1031","company_id":0,"name":"\u5546\u6d3eERP","url":"\/setting\/systemsetting\/certificate","sort":13,"is_menu":true,"pid":"1012","apis":"","icon":null,"is_show":true,"alias_name":"certificate","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5546\u6d3eERP"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"1032","company_id":0,"name":"\u57df\u540d\u8bbe\u7f6e","url":"\/setting\/systemsetting\/domain_setting","sort":14,"is_menu":true,"pid":"1012","apis":"companys.domain_setting.get","icon":null,"is_show":true,"alias_name":"domain_setting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u57df\u540d\u8bbe\u7f6e"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1033","company_id":0,"name":"\u8131\u654f\u6570\u636e\u7533\u8bf7","url":"\/setting\/systemsetting\/approve","sort":15,"is_menu":true,"pid":"1012","apis":"companys.datapass.list\ncompanys.datapass.apply","icon":null,"is_show":true,"alias_name":"approveDataPass","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u8131\u654f\u6570\u636e\u7533\u8bf7"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1034","company_id":0,"name":"\u8131\u654f\u7533\u8bf7\u5ba1\u6279","url":"\/setting\/systemsetting\/apply","sort":16,"is_menu":true,"pid":"1012","apis":"companys.datapass.log.list\ncompanys.datapass.log.list","icon":null,"is_show":true,"alias_name":"applyDataPass","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u8131\u654f\u7533\u8bf7\u5ba1\u6279"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1035","company_id":0,"name":"\u5916\u94fe\u5c0f\u7a0b\u5e8f","url":"\/setting\/systemsetting\/extminilink","sort":17,"is_menu":true,"pid":"1012","apis":"wxexternalconfig.create\nwxexternalconfig.update\nwxexternalroutes.list\nwxexternalroutes.create\nwxexternalroutes.update\nwxexternalroutes.delete\nwxexternalconfig.delete\nwxexternalconfigroutes.list","icon":null,"is_show":true,"alias_name":"extminilink","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5916\u94fe\u5c0f\u7a0b\u5e8f"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1036","company_id":0,"name":"\u8fbe\u6469CRM","url":"\/setting\/systemsetting\/damoCrm","sort":18,"is_menu":true,"pid":"1012","apis":"third.dmcrm.setting.get","icon":null,"is_show":true,"alias_name":"damoCrm","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u8fbe\u6469CRM"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"1037","company_id":0,"name":"\u5343\u4eba\u5343\u7801","url":"\/setting\/systemsetting\/kjlsetting","sort":20,"is_menu":true,"pid":"1012","apis":null,"icon":null,"is_show":true,"alias_name":"kjlsetting","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u5343\u4eba\u5343\u7801"},"level":3,"parent_name":"\u7cfb\u7edf\u914d\u7f6e","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"1038","company_id":0,"name":"\u914d\u9001\u8bbe\u7f6e","url":"\/setting\/delivery","sort":3,"is_menu":true,"pid":"1001","apis":"","icon":null,"is_show":true,"alias_name":"delivery","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u914d\u9001\u8bbe\u7f6e"},"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"1039","company_id":0,"name":"\u914d\u9001\u8bbe\u7f6e","url":"\/setting\/delivery\/logistics","sort":1,"is_menu":true,"pid":"1038","apis":"company.logistics.list \ncompany.logistics.create\ncompany.logistics.delete\ntrade.logistics.list\npickuplocation.list.get\ndatacube.deliverystaff.data\norder.deliverystaff.confirm\norder.deliverypackag.confirm\ncompany.dada.info\npickuplocation.create\npickuplocation.info.get\npickuplocation.update\npickuplocation.reldistributor\npickuplocation.delete\ncompany.dada.create","icon":null,"is_show":true,"alias_name":"logistics","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u914d\u9001\u8bbe\u7f6e"},"level":3,"parent_name":"\u914d\u9001\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1040","company_id":0,"name":"\u8fd0\u8d39\u6a21\u677f","url":"\/setting\/delivery\/shippingtemplates","sort":2,"is_menu":true,"pid":"1038","apis":"espier.address.info\nshipping.templates.list\nshipping.templates.info\nshipping.templates.update\nshipping.templates.create\nshipping.templates.delete","icon":null,"is_show":true,"alias_name":"shippingtemplates","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u8fd0\u8d39\u6a21\u677f"},"level":3,"parent_name":"\u914d\u9001\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1041","company_id":0,"name":"\u7269\u6d41\u67e5\u8be2\u914d\u7f6e","url":"\/setting\/delivery\/kdniao","sort":2,"is_menu":true,"pid":"1038","apis":"trade.kuaidi.setting.get\ntrade.kuaidi.setting.set\norder.delivervstaff.confirm\norder.deliverypackag.confirm\ntrade.sfbsp.setting.get\ntrade.sfbsp.setting.set","icon":null,"is_show":true,"alias_name":"kdniao","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u7269\u6d41\u67e5\u8be2\u914d\u7f6e"},"level":3,"parent_name":"\u914d\u9001\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1042","company_id":0,"name":"\u914d\u9001\u5458\u7ba1\u7406","url":"\/setting\/delivery\/selfdeliverystaff","sort":3,"is_menu":true,"pid":"1038","apis":"","icon":null,"is_show":true,"alias_name":"setting_staffself_deliverystaff","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u914d\u9001\u5458\u7ba1\u7406"},"level":3,"parent_name":"\u914d\u9001\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1043","company_id":0,"name":"\u914d\u9001\u5458\u4e1a\u7ee9","url":"\/setting\/delivery\/deliverystaffstatistics","sort":4,"is_menu":true,"pid":"1038","apis":"datacube.deliverystaff.data\nmerchant.list\ndada.finance.info","icon":null,"is_show":true,"alias_name":"companydata_deliverystaffstatistics","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u914d\u9001\u5458\u4e1a\u7ee9"},"level":3,"parent_name":"\u914d\u9001\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1044","company_id":0,"name":"\u8fbe\u8fbe\u8d26\u6237","url":"\/setting\/delivery\/dada","sort":6,"is_menu":true,"pid":"1038","apis":"","icon":null,"is_show":true,"alias_name":"dada","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u8fbe\u8fbe\u8d26\u6237"},"level":3,"parent_name":"\u914d\u9001\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"1045","company_id":0,"name":"\u7cfb\u7edf\u4fe1\u606f","url":"\/setting\/systeminfo","sort":4,"is_menu":true,"pid":"1001","apis":"","icon":null,"is_show":true,"alias_name":"systeminfo","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u7cfb\u7edf\u4fe1\u606f"},"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"1046","company_id":0,"name":"\u64cd\u4f5c\u65e5\u5fd7","url":"\/setting\/systeminfo\/operatorlogs","sort":3,"is_menu":true,"pid":"1045","apis":"company.get.operatorlogs","icon":null,"is_show":true,"alias_name":"operator-logs","version":1,"disabled":false,"created":1770278869,"updated":1770278869,"name_lang":{"zh-CN":"\u64cd\u4f5c\u65e5\u5fd7"},"level":3,"parent_name":"\u7cfb\u7edf\u4fe1\u606f","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file diff --git a/storage/static/shop_menu.json b/storage/static/shop_menu.json index 5aa4b64..e1252d9 100644 --- a/storage/static/shop_menu.json +++ b/storage/static/shop_menu.json @@ -1 +1 @@ -[{"shopmenu_id":"10146","company_id":0,"name":"\u5546\u54c1","url":"\/shopadmin\/entity","sort":2,"is_menu":true,"pid":"0","apis":"point.member.rule.info\noperator.update.data\nwechat.pre_auth_url","icon":"shopping-bag","is_show":true,"alias_name":"entity","version":3,"disabled":false,"created":1675936333,"updated":1724735463,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10147","company_id":0,"name":"\u5546\u54c1\u7ba1\u7406","url":"\/shopadmin\/entity\/goodsphysical","sort":1,"is_menu":true,"pid":"10146","apis":"goods.items.create\ngoods.items.templates_change\ngoods.items.category_change\ngoods.items.lists\ngoods.items.detail\ngoods.items.delete\ngoods.items.update\ngoods.items.distributiongoodswxacode\ngoods.items.warning_store\ngoods.category.lists\nshipping.templates.list\ncurrency.get.default\nwechat.material.upload\nwechat.material.list\ngoods.tag.list\npoint.member.rule.info\npopularize.config.get\ngoods.category.get\ngoods.tag.rel\ngoods.store.upate\ngoods.member.price\ngoods.status.upate\ngoods.export\ngoods.sync.items\ngoods.tag.export\ngoods.isgift.upate\nwechat.authorizerInfo\ngoods.profit.info\ngoods.profit.save\nespier.subdistrict.list.get\ngoods.itemsupdate\nwechat.wxa.template.list\nthird.jushuitan.setting.get\nthird.wdterp.setting.get\ngoods.items.sort\nthird.wdterp.setting.get\nall.setting.get\ngoods.items.params.create","icon":null,"is_show":true,"alias_name":"goodsphysical","version":3,"disabled":false,"created":1675936333,"updated":1751362408,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10674","company_id":0,"name":"\u5e97\u94fa\u5546\u54c1","url":"\/shopadmin\/entity\/storeshopproductanagement","sort":1,"is_menu":true,"pid":"10146","apis":"popularize.config.get\ngoods.tag.list\nwechat.wxa.template.list\nshipping.templates.list\ngoods.attributes.list\ngoods.category.lists\ngoods.items.detail","icon":null,"is_show":true,"alias_name":"storeshopproductanagement","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["standard"]},{"shopmenu_id":"10172","company_id":0,"name":"\u5546\u54c1\u5bfc\u5165","url":"\/shopadmin\/entity\/physicalupload","sort":2,"is_menu":true,"pid":"10146","apis":"espier.upload.list\nespier.upload.template.export\nespier.upload\nespier.upload.error.export","icon":null,"is_show":true,"alias_name":"physicalupload","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10148","company_id":0,"name":"\u5546\u54c1\u54c1\u724c","url":"\/shopadmin\/entity\/goodsbrand","sort":3,"is_menu":true,"pid":"10146","apis":"goods.attributes.add\ngoods.attributes.update\ngoods.attributes.list\ngoods.attributes.delete\nespier.image.uploadToken.get\nespier.image.save\nespier.oss.uploadToken.get\ngoods.sync.brand","icon":null,"is_show":true,"alias_name":"goodsbrand","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10149","company_id":0,"name":"\u5e97\u94fa\u5206\u7c7b","url":"\/shopadmin\/entity\/goodscategory","sort":4,"is_menu":true,"pid":"10146","apis":"goods.category.lists\ngoods.category.create\ngoods.category.delete\ngoods.items.lists\nshipping.templates.list\ngoods.items.detail\ngoods.createcategory.create\ngoods.category.update\nwechat.wxa.customizepage.list","icon":null,"is_show":true,"alias_name":"goodscategory","version":3,"disabled":false,"created":1675936333,"updated":1722654946,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10150","company_id":0,"name":"\u5546\u54c1\u6807\u7b7e","url":"\/shopadmin\/entity\/itemtags","sort":5,"is_menu":true,"pid":"10146","apis":"goods.tag.add\ngoods.tag.delete\ngoods.tag.update\ngoods.tag.list\ngoods.tag.get\nmember.tag.add","icon":null,"is_show":true,"alias_name":"itemtags","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10490","company_id":0,"name":"\u5546\u54c1\u8bc4\u4ef7","url":"\/shopadmin\/entity\/rate","sort":6,"is_menu":true,"pid":"10146","apis":"traderate.list.get\ntraderate.details.get\ntraderate.rate.delete\ntraderate.reply.put","icon":null,"is_show":true,"alias_name":"rate","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10151","company_id":0,"name":"\u7d20\u6750\u7ba1\u7406","url":"\/shopadmin\/entity\/brandmaterial","sort":7,"is_menu":true,"pid":"10146","apis":"wechat.material.upload\nwechat.news.image.upload\nwechat.material.delete\nwechat.material.list\nwechat.material.stats\nwechat.material.news.add\nwechat.material.news.update\nwechat.material.news.get\nespier.image.del","icon":null,"is_show":true,"alias_name":"brandmaterial","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10143","company_id":0,"name":"\u4ea4\u6613","url":"\/shopadmin\/order","sort":3,"is_menu":true,"pid":"0","apis":"company.real.statistics\norder.writeoff.qr.set\norder.delivervstaff.confirm","icon":"clipboard-list","is_show":true,"alias_name":"order","version":3,"disabled":false,"created":1675936333,"updated":1730174304,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10144","company_id":0,"name":"\u5168\u90e8\u8ba2\u5355","url":"\/shopadmin\/order\/tradenormalorders","sort":1,"is_menu":true,"pid":"10143","apis":"order.list.get\ncompany.real.statistics\nsource.list\norder.info.get\norder.delivery\norder.list.export\nshops.lists\ndistributor.list\nmember.info\norder.cancel.info\norder.cancel\norder.writeoff.info.get\norder.writeoff.set\ninvoice.list.export\norder.process.log.get\norder.delivery.lists\norder.invoiced.invoiced\norder.delivery.update\norder.businessreceipt\norder.confirm.goods\norder.message.new\norder.message.list\norder.message.update\ngoods.items.onsale.lists\ncompanys.operator.cartdata.scanadd\ncompanys.operator.cartdata.add\ncompanys.operator.cartdata.update\ncompanys.operator.cartdata.list\ncompanys.operator.cartdata.del\norder.checkout\norder.create\norder.payment\norder.payment.query\nuser.card.list\npresale.pickupcode.setting.get\nmember.create\ncompanys.operator.cartdata.pending\ncompanys.operator.order.pending\ncompanys.operator.pending.fetch\ncompanys.operator.pending.delete\ncompanys.operator.pending.list\norder.markdown\norder.markdown.confirm\nespier.image.cat.children\naftersales.apply\ndelivery.process.list\norder.writeoff.qr.set\norder.deliverystaff.confirm\norder.deliverystaff.cancel\norder.deliverypackag.confirm\ndatacube.deliverystaff.data\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"shoptradenormalorders","version":3,"disabled":false,"created":1675936333,"updated":1730103284,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10145","company_id":0,"name":"\u4ea4\u6613\u5355","url":"\/shopadmin\/order\/tradepayment","sort":2,"is_menu":true,"pid":"10143","apis":"shops.lists\norder.trade.list\ntrades.list.export\ndelivery.process.list","icon":null,"is_show":true,"alias_name":"tradepayment","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10152","company_id":0,"name":"\u552e\u540e\u5217\u8868","url":"\/shopadmin\/order\/aftersaleslist","sort":4,"is_menu":true,"pid":"10143","apis":"aftersales.list\naftersales.info\naftersales.review\naftersales.logexport\naftersales.remind.get\ndelivery.process.list\norder.delivervstaff.confirm\naftersales.sendback","icon":null,"is_show":true,"alias_name":"aftersaleslist","version":3,"disabled":false,"created":1675936333,"updated":1737635493,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10641","company_id":0,"name":"\u9000\u6b3e\u5355","url":"\/shopadmin\/order\/aftersalesrefundlist","sort":5,"is_menu":true,"pid":"10143","apis":"refund.list\nrefund.logexport\ntrade.refunderrorlogs.list\ntrade.refunderrorlogs.resubmit\nrefund.info\ndelivery.process.list","icon":null,"is_show":true,"alias_name":"aftersalesrefundlist","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10153","company_id":0,"name":"\u8fd0\u8d39\u6a21\u677f","url":"\/shopadmin\/order\/shippingtemplates","sort":5,"is_menu":true,"pid":"10143","apis":"shipping.templates.list\nshipping.templates.info\nshipping.templates.create\nshipping.templates.update\nshipping.templates.delete\nespier.address.info\ndelivery.process.list","icon":null,"is_show":true,"alias_name":"shippingtemplates","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10213","company_id":0,"name":"\u914d\u9001\u7ba1\u7406","url":"\/shopadmin\/order\/logistics","sort":6,"is_menu":true,"pid":"10143","apis":"company.logistics.list\ncompany.logistics.create\ncompany.logistics.delete\ntrade.logistics.list\npickuplocation.list.get\npickuplocation.info.get\npickuplocation.create\npickuplocation.update\npickuplocation.reldistributor\npickuplocation.reldistributor.cancel\ndelivery.process.list\norder.delivervstaff.confirm\ndatacube.deliverystaff.data","icon":null,"is_show":true,"alias_name":"wl-logistics","version":3,"disabled":false,"created":1675936333,"updated":1730173113,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["platform","standard","all"]},{"shopmenu_id":"10154","company_id":0,"name":"\u4f1a\u5458","url":"\/shopadmin\/member","sort":4,"is_menu":true,"pid":"0","apis":"","icon":"gem1","is_show":true,"alias_name":"member","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"10155","company_id":0,"name":"\u4f1a\u5458\u7ba1\u7406","url":"\/shopadmin\/member\/member","sort":1,"is_menu":true,"pid":"10154","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\ndistributor.list\nvipgrade.order.list\nmember.register.get\npoint.member.list\nrights.log.list\nworkwechat.rel.log\nvipgrade.use.list\naliyunsms.status.get\npoint.adjustment","icon":null,"is_show":true,"alias_name":"member-list-view","version":3,"disabled":false,"created":1675936333,"updated":1727319297,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"10157","company_id":0,"name":"\u7fa4\u53d1\u4f18\u60e0\u5238","url":"\/shopadmin\/member\/member","sort":1,"is_menu":false,"pid":"10155","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\npromotions.give.create\npromotions.give.list\npromotions.give.info","icon":null,"is_show":true,"alias_name":"member-send-coupons","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"11182","company_id":0,"name":"\u4f1a\u5458\u5217\u8868","url":"\/shopadmin\/member\/member\/members-lists","sort":1,"is_menu":true,"pid":"10155","apis":null,"icon":null,"is_show":true,"alias_name":"members-lists","version":3,"disabled":false,"created":1750674825,"updated":1750674825,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10174","company_id":0,"name":"\u4f1a\u5458\u5bfc\u51fa","url":"\/shopadmin\/member\/member","sort":1,"is_menu":false,"pid":"10155","apis":"member.export","icon":null,"is_show":true,"alias_name":"member-export","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10159","company_id":0,"name":"\u6253\u6807\u7b7e","url":"\/shopadmin\/member\/member","sort":3,"is_menu":false,"pid":"10155","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\nmember.tag.rel\nmember.batch.operating","icon":null,"is_show":true,"alias_name":"member-tag","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10156","company_id":0,"name":"\u4f1a\u5458\u6807\u7b7e","url":"\/shopadmin\/member\/Managetag","sort":2,"is_menu":true,"pid":"10154","apis":"member.tagcategory.list\nmember.tag.update","icon":null,"is_show":true,"alias_name":"Managetag","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10160","company_id":0,"name":"\u5e97\u94fa","url":"\/shopadmin\/store","sort":4,"is_menu":true,"pid":"0","apis":"","icon":"store-alt","is_show":true,"alias_name":"store","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10161","company_id":0,"name":"\u5e97\u94fa\u4fe1\u606f","url":"\/shopadmin\/store\/marketingdistributor","sort":1,"is_menu":true,"pid":"10160","apis":"distributor.list\ndistributor.create\ndistributor.edit\ndistributor.item.list\ndistributor.wxacode\ndistributor.get.shop\ndistributor.item.update\ndistributor.default.set\ndistributor.create\ndistributor.item.delete\ngoods.items.distributiongoodswxacode\ncurrency.get.default\ndistributor.info\ndistributor.tag.list\npromotions.liverooms\nrecommendlike.list\ncompany.regionauth.list\nhfpay.ledgerconfig.index\ncompany.dada.info\npagestemplate.lists\npagestemplateset.getInfo\npagestemplate.add\npagestemplate.delete\npagestemplate.modifyStatus\npagestemplate.copy\npagestemplate.edit\npagestemplate.detail\ndistribution.distance.get\ndistribution.distance.save\ngoods.sku.lists\nPromotions.seckill.item.list\norder.writeoff.qr.set\ndistributor.aftersales.list\norder.delivervstaff.confirm\norders.setting.get\nespier.image.cat.edit\nselfhelp.registrationActivity.easylist","icon":null,"is_show":true,"alias_name":"marketingdistributor","version":3,"disabled":false,"created":1675936333,"updated":1744185055,"level":2,"parent_name":"\u5e97\u94fa","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10170","company_id":0,"name":"\u5e97\u94fa\u7801","url":"\/shopadmin\/store\/distributorCode","sort":2,"is_menu":true,"pid":"10160","apis":"","icon":null,"is_show":true,"alias_name":"distributorCode","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5e97\u94fa","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10905","company_id":0,"name":"\u5e97\u94fa\u767d\u540d\u5355","url":"\/shopadmin\/store\/storewhitelist","sort":14,"is_menu":true,"pid":"10160","apis":null,"icon":"storewhitelist","is_show":true,"alias_name":"storewhitelist","version":3,"disabled":false,"created":1742884880,"updated":1742884880,"level":2,"parent_name":"\u5e97\u94fa","isChildrenMenu":false,"menu_type":["in_purchase","standard"]},{"shopmenu_id":"10162","company_id":0,"name":"\u8425\u9500","url":"\/shopadmin\/marketing","sort":5,"is_menu":true,"pid":"0","apis":"","icon":"gift","is_show":true,"alias_name":"marketing","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"10163","company_id":0,"name":"\u4f18\u60e0\u5238","url":"\/shopadmin\/marketing\/coupon","sort":1,"is_menu":true,"pid":"10162","apis":"distributor.easy.list\ncard.consume","icon":null,"is_show":true,"alias_name":"coupon","version":3,"disabled":false,"created":1675936333,"updated":1729755065,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"10165","company_id":0,"name":"\u4f18\u60e0\u5238\u7ba1\u7406","url":"\/shopadmin\/marketing\/coupon\/membermarketing","sort":1,"is_menu":true,"pid":"10163","apis":"card.list\ncard.create\ncard.update\ncard.delete\ncard.get\ncard.user.list\nshops.lists\ncard.detail.list\nwechat.material.list\nwechat.material.upload\ncurrency.get.default\nwechat.wxa.codeunlimit\ndistributor.easy.list\ncard.consume","icon":null,"is_show":true,"alias_name":"membermarketing","version":3,"disabled":false,"created":1675936333,"updated":1729755061,"level":3,"parent_name":"\u4f18\u60e0\u5238","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10166","company_id":0,"name":"\u53d1\u5238\u8bb0\u5f55","url":"\/shopadmin\/marketing\/coupon\/coupongive","sort":2,"is_menu":true,"pid":"10163","apis":"promotions.give.list\npromotions.give.info\ncard.consume","icon":null,"is_show":true,"alias_name":"coupongive","version":3,"disabled":false,"created":1675936333,"updated":1729755069,"level":3,"parent_name":"\u4f18\u60e0\u5238","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10637","company_id":0,"name":"\u52a0\u4ef7\u8d2d","url":"\/shopadmin\/marketing\/Marketingspluspricebuy","sort":2,"is_menu":true,"pid":"10162","apis":"","icon":null,"is_show":true,"alias_name":"marketingspluspricebuy","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10638","company_id":0,"name":"\u7ec4\u5408\u8d2d","url":"\/shopadmin\/marketing\/marketingpackage","sort":3,"is_menu":true,"pid":"10162","apis":"promotions.package.list.get\npromotions.package.create\npromotions.package.info.get\npromotions.package.cancel\npromotions.package.update","icon":null,"is_show":true,"alias_name":"marketingpackage","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10212","company_id":0,"name":"\u9650\u65f6\u4f18\u60e0","url":"\/shopadmin\/marketing\/marketing\/limitedtimesale","sort":4,"is_menu":true,"pid":"10162","apis":"Promotions.seckill.list\nPromotions.seckill.add\nPromotions.seckill.info\nPromotions.seckill.update\nPromotions.seckill.statusupdate\nPromotions.seckill.search.item.list","icon":null,"is_show":true,"alias_name":"limitedtimesale","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10639","company_id":0,"name":"\u5546\u54c1\u9650\u8d2d","url":"\/shopadmin\/marketing\/goodslimit","sort":5,"is_menu":true,"pid":"10162","apis":"promotions.limit.list.get\npromotions.limit.info.get\npromotions.limit.create\npromotions.limit.cancel","icon":null,"is_show":true,"alias_name":"goodslimit","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10167","company_id":0,"name":"\u6ee1\u6298","url":"\/shopadmin\/marketing\/marketingsfulldiscount","sort":7,"is_menu":true,"pid":"10162","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ncurrency.get.default","icon":null,"is_show":true,"alias_name":"marketingsfulldiscount","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10164","company_id":0,"name":"\u6ee1\u51cf","url":"\/shopadmin\/marketing\/marketingsfullminus","sort":8,"is_menu":true,"pid":"10162","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ncurrency.get.default","icon":null,"is_show":true,"alias_name":"marketingsfullminus","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10168","company_id":0,"name":"\u6ee1\u8d60","url":"\/shopadmin\/marketing\/marketingsfullgift","sort":9,"is_menu":true,"pid":"10162","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\n","icon":null,"is_show":true,"alias_name":"marketingsfullgift","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10607","company_id":0,"name":"\u793e\u533a\u56e2\u8d2d","url":"\/shopadmin\/marketing\/community","sort":10,"is_menu":true,"pid":"10162","apis":"","icon":null,"is_show":true,"alias_name":"community","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"10617","company_id":0,"name":"\u56e2\u957f\u7ba1\u7406","url":"\/shopadmin\/marketing\/community\/chief","sort":0,"is_menu":true,"pid":"10607","apis":"community.setting.chief\ncommunity.chief.apply.list\ncommunity.chief.apply.info\ncommunity.chief.approve\ncommunity.chief.list","icon":null,"is_show":true,"alias_name":"communitychief","version":3,"disabled":false,"created":1675936333,"updated":1746329335,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10609","company_id":0,"name":"\u6d3b\u52a8\u7ba1\u7406","url":"\/shopadmin\/marketing\/community\/activity","sort":1,"is_menu":true,"pid":"10607","apis":"community.list\nespier.subdistrict.list.get\ncommunity.activity.deliver\ncommunity.setting.chief\ncommunity.order.list.export","icon":null,"is_show":true,"alias_name":"communityactivity","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10610","company_id":0,"name":"\u8ba2\u5355\u7ba1\u7406","url":"\/shopadmin\/marketing\/community\/order","sort":2,"is_menu":true,"pid":"10607","apis":"community.order.list.get\norder.remarks.update\norder.list.get\ncompany.real.statistics\nsource.list\norder.info.get\norder.delivery\norder.list.export\nshops.lists\ndistributor.list\nmember.info\norder.cancel.info\norder.cancel\norder.writeoff.info.get\norder.writeoff.set\ninvoice.list.export\norder.process.log.get\norder.delivery.lists\norder.invoiced.invoiced\norder.delivery.update\norder.businessreceipt\norder.confirm.goods\norder.message.new\norder.message.list\norder.message.update","icon":null,"is_show":true,"alias_name":"communityorder","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10608","company_id":0,"name":"\u6d3b\u52a8\u5546\u54c1","url":"\/shopadmin\/marketing\/community\/communitygoods","sort":3,"is_menu":true,"pid":"10607","apis":"community.items.list.get\ncommunity.item.sort.update\ncommunity.item.minDeliveryNum.update\ncommunity.item.delete\ncommunity.items.add","icon":null,"is_show":true,"alias_name":"communitygoods","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10618","company_id":0,"name":"\u6d3b\u52a8\u914d\u7f6e","url":"\/shopadmin\/marketing\/community\/setting","sort":4,"is_menu":true,"pid":"10607","apis":"community.setting.get\ncommunity.setting.save\ncommunity.chief.apply_field.list\ncommunity.chief.apply_field.create\ncommunity.chief.apply_field.switch\ncommunity.chief.apply_field.update\ncommunity.chief.apply_field.delete\ncommunity.chief.apply.wxaCode","icon":null,"is_show":true,"alias_name":"communitysetting","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10621","company_id":0,"name":"\u56e2\u957f\u4e1a\u7ee9","url":"\/shopadmin\/marketing\/community\/achievement","sort":5,"is_menu":true,"pid":"10607","apis":"community.chief.rebate.count","icon":null,"is_show":true,"alias_name":"achievement","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10622","company_id":0,"name":"\u63d0\u73b0\u7533\u8bf7","url":"\/shopadmin\/marketing\/community\/withdraw","sort":6,"is_menu":true,"pid":"10607","apis":"community.chief.cash_withdrawal.list\ncommunity.chief.cash_withdrawal.process\ncommunity.chief.cash_withdrawal.payinfo","icon":null,"is_show":true,"alias_name":"withdraw","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10178","company_id":0,"name":"\u62a5\u8868","url":"\/shopadmin\/statistics","sort":7,"is_menu":true,"pid":"0","apis":"","icon":"chart-bar","is_show":true,"alias_name":"statistics","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10205","company_id":0,"name":"\u5e97\u94fa\u7edf\u8ba1","url":"\/shopadmin\/statistics\/distributordata","sort":1,"is_menu":true,"pid":"10178","apis":"datacube.distributor.data","icon":null,"is_show":true,"alias_name":"distributordata","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u62a5\u8868","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10633","company_id":0,"name":"\u7ed3\u7b97","url":"\/shopadmin\/statistics\/financial\/settlement","sort":2,"is_menu":true,"pid":"10178","apis":"","icon":null,"is_show":true,"alias_name":"settlement","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u62a5\u8868","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"10634","company_id":0,"name":"\u7ed3\u7b97\u6c47\u603b","url":"\/shopadmin\/statistics\/financial\/settlement\/summary","sort":1,"is_menu":true,"pid":"10633","apis":"merchant.list\nstatement.summarized.get\nstatement.confirm.post\nstatement.detail.get\nstatement.summarized.export\nstatement.detail.export","icon":null,"is_show":true,"alias_name":"summary","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"10758","company_id":0,"name":"\u914d\u9001\u5458\u4e1a\u7ee9","url":"\/shopadmin\/statistics\/deliverystaffstatistics","sort":5,"is_menu":true,"pid":"10178","apis":"datacube.deliverystaff.data\ndatacube.deliverystaff.data.export\ndatacube.deliverystaff.data\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"shopadmin_statistics_deliverystaffstatistics","version":3,"disabled":false,"created":1722662821,"updated":1730173060,"level":2,"parent_name":"\u62a5\u8868","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10677","company_id":0,"name":"\u5e94\u7528","url":"\/shopadmin\/applications","sort":8,"is_menu":true,"pid":"0","apis":"","icon":"yingyong-01","is_show":true,"alias_name":"applications","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"10782","company_id":0,"name":"\u6597\u62f1\u5206\u8d26","url":"\/shopadmin\/applications\/bspay","sort":1,"is_menu":true,"pid":"10677","apis":null,"icon":null,"is_show":true,"alias_name":"bspay","version":3,"disabled":false,"created":1741747147,"updated":1741747147,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"10783","company_id":0,"name":"\u7528\u6237\u8fdb\u4ef6","url":"\/shopadmin\/applications\/bspay\/user","sort":1,"is_menu":true,"pid":"10782","apis":"bspay.user_indv.create\nbspay.user_indv.modify\nbspay.user_ent.create\nbspay.user_ent.modify\nbspay.user.audit_state\nbspay.user_ent.info\nbspay.user_indv.info\nbspay.regions\nbspay.regions.third\nbspay.user.audit_state\nbspay.trade.getList","icon":null,"is_show":true,"alias_name":"user","version":3,"disabled":false,"created":1741747196,"updated":1741747346,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10784","company_id":0,"name":"\u5206\u8d26\u660e\u7ec6","url":"\/shopadmin\/applications\/bspay\/trades","sort":1,"is_menu":true,"pid":"10782","apis":"bspay.trade.getList\nbspay.tradeInfo.get\nbspay.trades.list.export","icon":null,"is_show":true,"alias_name":"trades","version":3,"disabled":false,"created":1741747218,"updated":1741747362,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10678","company_id":0,"name":"Adapay\u5206\u8d26","url":"\/shopadmin\/applications\/adapay","sort":1,"is_menu":true,"pid":"10677","apis":null,"icon":null,"is_show":true,"alias_name":"adapay","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["b2c","standard","platform"]},{"shopmenu_id":"10679","company_id":0,"name":"\u8fdb\u4ef6","url":"\/shopadmin\/applications\/adapay\/adapay_member_entry","sort":1,"is_menu":true,"pid":"10678","apis":"adapay.member.create\nadapay.bank.list\nadapay.member.update\nadapay.corp_member.update\nadapay.generate.key\nadapay.member.auditState\nadapay.member.valid\nadapay.member.info\nadapay.corp_member.create\nadapay.member.modify\nadapay.corp_member.modify\nadapay.trade.getList","icon":null,"is_show":true,"alias_name":"adapay_member_entry","version":3,"disabled":false,"created":1675936333,"updated":1722997164,"level":3,"parent_name":"Adapay\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"10680","company_id":0,"name":"\u5206\u8d26","url":"\/shopadmin\/applications\/adapay\/adapay_trades","sort":2,"is_menu":true,"pid":"10678","apis":null,"icon":null,"is_show":true,"alias_name":"adapay_trades","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"Adapay\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"10681","company_id":0,"name":"\u63d0\u73b0","url":"\/shopadmin\/applications\/adapay\/adapay_cash","sort":3,"is_menu":true,"pid":"10678","apis":"adapay.drawcash.getList\nadapay.withdraw","icon":null,"is_show":true,"alias_name":"adapay_cash","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"Adapay\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"10682","company_id":0,"name":"\u8fdb\u4ef6\u4fe1\u606f","url":"\/shopadmin\/applications\/adapay\/adapay_member_info","sort":4,"is_menu":true,"pid":"10678","apis":"distributor.info","icon":null,"is_show":true,"alias_name":"adapay_member_info","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"Adapay\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"11142","company_id":0,"name":"\u4f01\u4e1a\u8d2d","url":"\/shopadmin\/applications\/ec","sort":3,"is_menu":true,"pid":"10677","apis":null,"icon":null,"is_show":true,"alias_name":"ec","version":3,"disabled":false,"created":1743051490,"updated":1743051490,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"11145","company_id":0,"name":"\u4f01\u4e1a\u7ba1\u7406","url":"\/shopadmin\/applications\/ec\/company","sort":1,"is_menu":true,"pid":"11142","apis":"employeepurchase.enterprise.add\nemployeepurchase.employee.create\nemployeepurchase.activity.create\nemployeepurchase.employee.delete\nemployeepurchase.enterprise.status.update\nemployeepurchase.activity.users\nemployeepurchase.activity.info\nemployeepurchase.activity.items.add\nemployeepurchase.activity.items.list\nemployeepurchase.activity.suspend\nemployeepurchase.activity.end\nemployeepurchase.enterprise.qrcode.get\npagestemplateset.set\nemployeepurchase.enterprise.update\nemployeepurchase.enterprise.sendtestemail","icon":null,"is_show":true,"alias_name":"company-admin","version":3,"disabled":false,"created":1743051642,"updated":1743412490,"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"11144","company_id":0,"name":"\u5458\u5de5\u7ba1\u7406","url":"\/shopadmin\/applications\/ec\/employee","sort":2,"is_menu":true,"pid":"11142","apis":"employeepurchase.enterprise.list\nemployeepurchase.employee.list\nemployeepurchase.employees.export\nemployeepurchase.employee.update","icon":null,"is_show":true,"alias_name":"employee-admin","version":3,"disabled":false,"created":1743051598,"updated":1743412475,"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"11143","company_id":0,"name":"\u6d3b\u52a8\u7ba1\u7406","url":"\/shopadmin\/applications\/ec\/purchaseactivity","sort":3,"is_menu":true,"pid":"11142","apis":"promotions.employeepurchase.list\npromotions.employeepurchase.info\npromotions.employeepurchase.add\npromotions.employeepurchase.update\nespier.upload.template.export\nespier.upload\npromotions.employeepurchase.endactivity\npromotions.employeepurchase.dependents.lists\npromotions.employeepurchase.dependents.export\ntemplate_name\nemployeepurchase.activity.items.update\nemployeepurchase.activity.update\nemployeepurchase.activity.if_share_store.set\nemployeepurchase.activity.ahead\nemployeepurchase.activity.items.delete","icon":null,"is_show":true,"alias_name":"purchase-admin","version":3,"disabled":false,"created":1743051533,"updated":1744183599,"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"11146","company_id":0,"name":"\u8ba2\u5355\u7ba1\u7406","url":"\/shopadmin\/applications\/ec\/purchaseorder","sort":4,"is_menu":true,"pid":"11142","apis":"order.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel\nemployeepurchase.activity.list","icon":null,"is_show":true,"alias_name":"purchase-list","version":3,"disabled":false,"created":1743051701,"updated":1743054668,"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10268","company_id":0,"name":"\u8bbe\u7f6e","url":"\/shopadmin\/shopsetting","sort":9,"is_menu":true,"pid":"0","apis":"order.delivervstaff.confirm","icon":"cog","is_show":true,"alias_name":"shopsetting","version":3,"disabled":false,"created":1675936333,"updated":1730169625,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10623","company_id":0,"name":"\u8d26\u53f7\u7ba1\u7406","url":"\/shopadmin\/shopsetting\/staff","sort":1,"is_menu":true,"pid":"10268","apis":"order.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"distributor-staff","version":3,"disabled":false,"created":1675936333,"updated":1730169628,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"10624","company_id":0,"name":"\u5e97\u94fa\u7ba1\u7406\u5458","url":"\/shopadmin\/shopsetting\/staff\/Merchantstaff","sort":1,"is_menu":true,"pid":"10623","apis":"account.create\naccount.list\naccount.info\naccount.update\naccount.delete\nroles.list\naccount.roles.permission\nespier.subdistrict.list.get\noperator.status.change\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"Merchant-staff","version":3,"disabled":false,"created":1675936333,"updated":1730169636,"level":3,"parent_name":"\u8d26\u53f7\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10625","company_id":0,"name":"\u5e97\u94fa\u89d2\u8272","url":"\/shopadmin\/shopsetting\/staff\/Merchantstaffroles","sort":1,"is_menu":true,"pid":"10623","apis":"roles.create\nroles.list\nroles.info\nroles.update\nroles.delete\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"platformstaffroles","version":3,"disabled":false,"created":1675936333,"updated":1730169640,"level":3,"parent_name":"\u8d26\u53f7\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10759","company_id":0,"name":"\u914d\u9001\u5458","url":"\/shopadmin\/shopsetting\/staff\/selfdeliverystaff","sort":2,"is_menu":true,"pid":"10623","apis":"datacube.deliverystaff.data\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"shopadmin_shopsetting_staff_selfdeliverystaff","version":3,"disabled":false,"created":1722662879,"updated":1730103301,"level":3,"parent_name":"\u8d26\u53f7\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10269","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/shopadmin\/shopsetting\/baseexport","sort":2,"is_menu":true,"pid":"10268","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"shop-baseexport","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"10488","company_id":0,"name":"\u8131\u654f\u6570\u636e","url":"\/shopadmin\/shopsetting\/datapass","sort":3,"is_menu":true,"pid":"10268","apis":"","icon":null,"is_show":true,"alias_name":"datapass","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10489","company_id":0,"name":"\u6743\u9650\u7533\u8bf7","url":"\/shopadmin\/shopsetting\/datapass\/apply","sort":1,"is_menu":true,"pid":"10488","apis":"companys.datapass.list\ncompanys.datapass.apply","icon":null,"is_show":true,"alias_name":"applyDataPass","version":3,"disabled":false,"created":1675936333,"updated":1675936333,"level":3,"parent_name":"\u8131\u654f\u6570\u636e","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file +[{"shopmenu_id":"669","company_id":0,"name":"\u5546\u54c1","url":"\/shopadmin\/entity","sort":2,"is_menu":true,"pid":"0","apis":"point.member.rule.info\noperator.update.data\nwechat.pre_auth_url\nthird.jushuitan.setting.get\nthird.wdterp.setting.get","icon":"shopping-bag","is_show":true,"alias_name":"entity","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"670","company_id":0,"name":"\u5546\u54c1\u7ba1\u7406","url":"\/shopadmin\/entity\/goodsphysical","sort":1,"is_menu":true,"pid":"669","apis":"goods.items.create\ngoods.items.templates_change\ngoods.items.category_change\ngoods.items.lists\ngoods.items.detail\ngoods.items.delete\ngoods.items.update\ngoods.items.distributiongoodswxacode\ngoods.items.warning_store\ngoods.category.lists\nshipping.templates.list\ncurrency.get.default\nwechat.material.upload\nwechat.material.list\ngoods.tag.list\npoint.member.rule.info\npopularize.config.get\ngoods.category.get\ngoods.tag.rel\ngoods.store.upate\ngoods.member.price\ngoods.status.upate\ngoods.export\ngoods.sync.items\ngoods.tag.export\ngoods.isgift.upate\nwechat.authorizerInfo\ngoods.profit.info\ngoods.profit.save\nespier.subdistrict.list.get\ngoods.itemsupdate\nwechat.wxa.template.list\nthird.jushuitan.setting.get\nthird.wdterp.setting.get\ngoods.items.sort\nthird.wdterp.setting.get\nall.setting.get\ngoods.items.params.create","icon":null,"is_show":true,"alias_name":"goodsphysical","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"671","company_id":0,"name":"\u5546\u54c1\u5bfc\u5165","url":"\/shopadmin\/entity\/physicalupload","sort":2,"is_menu":true,"pid":"669","apis":"espier.upload.list\nespier.upload.template.export\nespier.upload\nespier.upload.error.export","icon":null,"is_show":true,"alias_name":"physicalupload","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"672","company_id":0,"name":"\u5546\u54c1\u54c1\u724c","url":"\/shopadmin\/entity\/goodsbrand","sort":3,"is_menu":true,"pid":"669","apis":"goods.attributes.add\ngoods.attributes.update\ngoods.attributes.list\ngoods.attributes.delete\nespier.image.uploadToken.get\nespier.image.save\nespier.oss.uploadToken.get\ngoods.sync.brand","icon":null,"is_show":true,"alias_name":"goodsbrand","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"673","company_id":0,"name":"\u5e97\u94fa\u5206\u7c7b","url":"\/shopadmin\/entity\/goodscategory","sort":4,"is_menu":true,"pid":"669","apis":"goods.category.lists\ngoods.category.create\ngoods.category.delete\ngoods.items.lists\nshipping.templates.list\ngoods.items.detail\ngoods.createcategory.create\ngoods.category.update\nwechat.wxa.customizepage.list","icon":null,"is_show":true,"alias_name":"goodscategory","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"674","company_id":0,"name":"\u5546\u54c1\u6807\u7b7e","url":"\/shopadmin\/entity\/itemtags","sort":5,"is_menu":true,"pid":"669","apis":"goods.tag.add\ngoods.tag.delete\ngoods.tag.update\ngoods.tag.list\ngoods.tag.get\nmember.tag.add","icon":null,"is_show":true,"alias_name":"itemtags","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"675","company_id":0,"name":"\u5546\u54c1\u8bc4\u4ef7","url":"\/shopadmin\/entity\/rate","sort":6,"is_menu":true,"pid":"669","apis":"traderate.list.get\ntraderate.details.get\ntraderate.rate.delete\ntraderate.reply.put","icon":null,"is_show":true,"alias_name":"rate","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"676","company_id":0,"name":"\u7d20\u6750\u7ba1\u7406","url":"\/shopadmin\/entity\/brandmaterial","sort":7,"is_menu":true,"pid":"669","apis":"wechat.material.upload\nwechat.news.image.upload\nwechat.material.delete\nwechat.material.list\nwechat.material.stats\nwechat.material.news.add\nwechat.material.news.update\nwechat.material.news.get\nespier.image.del\nespier.image.move.cat","icon":null,"is_show":true,"alias_name":"brandmaterial","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"677","company_id":0,"name":"\u4ea4\u6613","url":"\/shopadmin\/order","sort":3,"is_menu":true,"pid":"0","apis":"company.real.statistics\norder.writeoff.qr.set\norder.delivervstaff.confirm\nthird.jushuitan.setting.get\nall.setting.get","icon":"clipboard-list","is_show":true,"alias_name":"order","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"678","company_id":0,"name":"\u4ea4\u6613\u5355","url":"\/shopadmin\/order\/tradepayment","sort":2,"is_menu":true,"pid":"677","apis":"shops.lists\norder.trade.list\ntrades.list.export\ndelivery.process.list","icon":null,"is_show":true,"alias_name":"tradepayment","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"679","company_id":0,"name":"\u552e\u540e\u5217\u8868","url":"\/shopadmin\/order\/aftersaleslist","sort":4,"is_menu":true,"pid":"677","apis":"aftersales.list\naftersales.info\naftersales.review\naftersales.logexport\naftersales.remind.get\ndelivery.process.list\norder.delivervstaff.confirm\naftersales.sendback","icon":null,"is_show":true,"alias_name":"aftersaleslist","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"680","company_id":0,"name":"\u9000\u6b3e\u5355","url":"\/shopadmin\/order\/aftersalesrefundlist","sort":5,"is_menu":true,"pid":"677","apis":"refund.list\nrefund.logexport\ntrade.refunderrorlogs.list\ntrade.refunderrorlogs.resubmit\nrefund.info\ndelivery.process.list\nrefund.offline","icon":null,"is_show":true,"alias_name":"aftersalesrefundlist","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"681","company_id":0,"name":"\u8fd0\u8d39\u6a21\u677f","url":"\/shopadmin\/order\/shippingtemplates","sort":5,"is_menu":true,"pid":"677","apis":"shipping.templates.list\nshipping.templates.info\nshipping.templates.create\nshipping.templates.update\nshipping.templates.delete\nespier.address.info\ndelivery.process.list","icon":null,"is_show":true,"alias_name":"shippingtemplates","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"682","company_id":0,"name":"\u914d\u9001\u7ba1\u7406","url":"\/shopadmin\/order\/logistics","sort":6,"is_menu":true,"pid":"677","apis":"company.logistics.list\ncompany.logistics.create\ncompany.logistics.delete\ntrade.logistics.list\npickuplocation.list.get\npickuplocation.info.get\npickuplocation.create\npickuplocation.update\npickuplocation.reldistributor\npickuplocation.reldistributor.cancel\ndelivery.process.list\norder.delivervstaff.confirm\ndatacube.deliverystaff.data","icon":null,"is_show":true,"alias_name":"wl-logistics","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["platform","standard","all"]},{"shopmenu_id":"683","company_id":0,"name":"\u4f1a\u5458","url":"\/shopadmin\/member","sort":4,"is_menu":true,"pid":"0","apis":"","icon":"gem1","is_show":true,"alias_name":"member","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"684","company_id":0,"name":"\u4f1a\u5458\u7ba1\u7406","url":"\/shopadmin\/member\/member","sort":1,"is_menu":true,"pid":"683","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\ndistributor.list\nvipgrade.order.list\nmember.register.get\npoint.member.list\nrights.log.list\nworkwechat.rel.log\nvipgrade.use.list\naliyunsms.status.get\npoint.adjustment\nthird.dmcrm.setting.get\naliyunsms.status.get","icon":null,"is_show":true,"alias_name":"member-list-view","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"685","company_id":0,"name":"\u7fa4\u53d1\u4f18\u60e0\u5238","url":"\/shopadmin\/member\/member","sort":1,"is_menu":false,"pid":"684","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\npromotions.give.create\npromotions.give.list\npromotions.give.info","icon":null,"is_show":true,"alias_name":"member-send-coupons","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"686","company_id":0,"name":"\u4f1a\u5458\u5217\u8868","url":"\/shopadmin\/member\/member\/members-lists","sort":1,"is_menu":true,"pid":"684","apis":"member.register.get\naliyunsms.status.get\nthird.dmcrm.setting.get","icon":null,"is_show":true,"alias_name":"members-lists","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"687","company_id":0,"name":"\u4f1a\u5458\u5bfc\u51fa","url":"\/shopadmin\/member\/member","sort":1,"is_menu":false,"pid":"684","apis":"member.export","icon":null,"is_show":true,"alias_name":"member-export","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"688","company_id":0,"name":"\u6253\u6807\u7b7e","url":"\/shopadmin\/member\/member","sort":3,"is_menu":false,"pid":"684","apis":"member.list\nmember.operate.logs\nmember.update\nmember.info\neffectiveCard.list\nmembercard.grade.list\nmembercard.vipgrade.list\norder.rights.list.get\nshops.lists\norder.list.get\norder.info.get\ndeposit.trades\norder.rights.transfer.list\nmember.tag.list\nmember.tagsearch\nmember.tag.rel\nmember.batch.operating","icon":null,"is_show":true,"alias_name":"member-tag","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f1a\u5458\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"689","company_id":0,"name":"\u4f1a\u5458\u6807\u7b7e","url":"\/shopadmin\/member\/Managetag","sort":2,"is_menu":true,"pid":"683","apis":"member.tagcategory.list\nmember.tag.update","icon":null,"is_show":true,"alias_name":"Managetag","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u4f1a\u5458","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"690","company_id":0,"name":"\u5e97\u94fa","url":"\/shopadmin\/store","sort":4,"is_menu":true,"pid":"0","apis":"","icon":"store-alt","is_show":true,"alias_name":"store","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"691","company_id":0,"name":"\u5e97\u94fa\u4fe1\u606f","url":"\/shopadmin\/store\/marketingdistributor","sort":1,"is_menu":true,"pid":"690","apis":"distributor.list\ndistributor.create\ndistributor.edit\ndistributor.item.list\ndistributor.wxacode\ndistributor.get.shop\ndistributor.item.update\ndistributor.default.set\ndistributor.create\ndistributor.item.delete\ngoods.items.distributiongoodswxacode\ncurrency.get.default\ndistributor.info\ndistributor.tag.list\npromotions.liverooms\nrecommendlike.list\ncompany.regionauth.list\nhfpay.ledgerconfig.index\ncompany.dada.info\npagestemplate.lists\npagestemplateset.getInfo\npagestemplate.add\npagestemplate.delete\npagestemplate.modifyStatus\npagestemplate.copy\npagestemplate.edit\npagestemplate.detail\ndistribution.distance.get\ndistribution.distance.save\ngoods.sku.lists\nPromotions.seckill.item.list\norder.writeoff.qr.set\ndistributor.aftersales.list\norder.delivervstaff.confirm\norders.setting.get\nespier.image.cat.edit\nselfhelp.registrationActivity.easylist\narticle.list\ntrade.payment.setting.get\ntrade.payment.setting.set\ntrade.payment.open.status.get","icon":null,"is_show":true,"alias_name":"marketingdistributor","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5e97\u94fa","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"692","company_id":0,"name":"\u5e97\u94fa\u767d\u540d\u5355","url":"\/shopadmin\/store\/storewhitelist","sort":14,"is_menu":true,"pid":"690","apis":null,"icon":"storewhitelist","is_show":true,"alias_name":"storewhitelist","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5e97\u94fa","isChildrenMenu":false,"menu_type":["in_purchase","standard"]},{"shopmenu_id":"693","company_id":0,"name":"\u8425\u9500","url":"\/shopadmin\/marketing","sort":5,"is_menu":true,"pid":"0","apis":"","icon":"gift","is_show":true,"alias_name":"marketing","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"694","company_id":0,"name":"\u4f18\u60e0\u5238","url":"\/shopadmin\/marketing\/coupon","sort":1,"is_menu":true,"pid":"693","apis":"distributor.easy.list\ncard.consume","icon":null,"is_show":true,"alias_name":"coupon","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"695","company_id":0,"name":"\u4f18\u60e0\u5238\u7ba1\u7406","url":"\/shopadmin\/marketing\/coupon\/membermarketing","sort":1,"is_menu":true,"pid":"694","apis":"card.list\ncard.create\ncard.update\ncard.delete\ncard.get\ncard.user.list\nshops.lists\ncard.detail.list\nwechat.material.list\nwechat.material.upload\ncurrency.get.default\nwechat.wxa.codeunlimit\ndistributor.easy.list\ncard.consume","icon":null,"is_show":true,"alias_name":"membermarketing","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f18\u60e0\u5238","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"696","company_id":0,"name":"\u53d1\u5238\u8bb0\u5f55","url":"\/shopadmin\/marketing\/coupon\/coupongive","sort":2,"is_menu":true,"pid":"694","apis":"promotions.give.list\npromotions.give.info\ncard.consume","icon":null,"is_show":true,"alias_name":"coupongive","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f18\u60e0\u5238","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"697","company_id":0,"name":"\u52a0\u4ef7\u8d2d","url":"\/shopadmin\/marketing\/Marketingspluspricebuy","sort":2,"is_menu":true,"pid":"693","apis":"","icon":null,"is_show":true,"alias_name":"marketingspluspricebuy","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"698","company_id":0,"name":"\u7ec4\u5408\u8d2d","url":"\/shopadmin\/marketing\/marketingpackage","sort":3,"is_menu":true,"pid":"693","apis":"promotions.package.list.get\npromotions.package.create\npromotions.package.info.get\npromotions.package.cancel\npromotions.package.update","icon":null,"is_show":true,"alias_name":"marketingpackage","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"699","company_id":0,"name":"\u9650\u65f6\u4f18\u60e0","url":"\/shopadmin\/marketing\/marketing\/limitedtimesale","sort":4,"is_menu":true,"pid":"693","apis":"Promotions.seckill.list\nPromotions.seckill.add\nPromotions.seckill.info\nPromotions.seckill.update\nPromotions.seckill.statusupdate\nPromotions.seckill.search.item.list","icon":null,"is_show":true,"alias_name":"limitedtimesale","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"700","company_id":0,"name":"\u5546\u54c1\u9650\u8d2d","url":"\/shopadmin\/marketing\/goodslimit","sort":5,"is_menu":true,"pid":"693","apis":"promotions.limit.list.get\npromotions.limit.info.get\npromotions.limit.create\npromotions.limit.cancel","icon":null,"is_show":true,"alias_name":"goodslimit","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"701","company_id":0,"name":"\u6ee1\u6298","url":"\/shopadmin\/marketing\/marketingsfulldiscount","sort":7,"is_menu":true,"pid":"693","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ncurrency.get.default","icon":null,"is_show":true,"alias_name":"marketingsfulldiscount","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"702","company_id":0,"name":"\u6ee1\u51cf","url":"\/shopadmin\/marketing\/marketingsfullminus","sort":8,"is_menu":true,"pid":"693","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\ncurrency.get.default","icon":null,"is_show":true,"alias_name":"marketingsfullminus","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"703","company_id":0,"name":"\u6ee1\u8d60","url":"\/shopadmin\/marketing\/marketingsfullgift","sort":9,"is_menu":true,"pid":"693","apis":"marketing.add\nmarketing.delete\nmarketing.update\nmarketing.list\nmarketing.info\nmarketing.item.list\ngoods.items.lists\nwechat.material.list\n","icon":null,"is_show":true,"alias_name":"marketingsfullgift","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"704","company_id":0,"name":"\u793e\u533a\u56e2\u8d2d","url":"\/shopadmin\/marketing\/community","sort":10,"is_menu":true,"pid":"693","apis":"","icon":null,"is_show":true,"alias_name":"community","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8425\u9500","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"705","company_id":0,"name":"\u56e2\u957f\u7ba1\u7406","url":"\/shopadmin\/marketing\/community\/chief","sort":0,"is_menu":true,"pid":"704","apis":"community.setting.chief\ncommunity.chief.apply.list\ncommunity.chief.apply.info\ncommunity.chief.approve\ncommunity.chief.list","icon":null,"is_show":true,"alias_name":"communitychief","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"706","company_id":0,"name":"\u6d3b\u52a8\u7ba1\u7406","url":"\/shopadmin\/marketing\/community\/activity","sort":1,"is_menu":true,"pid":"704","apis":"community.list\nespier.subdistrict.list.get\ncommunity.activity.deliver\ncommunity.setting.chief\ncommunity.order.list.export","icon":null,"is_show":true,"alias_name":"communityactivity","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"707","company_id":0,"name":"\u8ba2\u5355\u7ba1\u7406","url":"\/shopadmin\/marketing\/community\/order","sort":2,"is_menu":true,"pid":"704","apis":"community.order.list.get\norder.remarks.update\norder.list.get\ncompany.real.statistics\nsource.list\norder.info.get\norder.delivery\norder.list.export\nshops.lists\ndistributor.list\nmember.info\norder.cancel.info\norder.cancel\norder.writeoff.info.get\norder.writeoff.set\ninvoice.list.export\norder.process.log.get\norder.delivery.lists\norder.invoiced.invoiced\norder.delivery.update\norder.businessreceipt\norder.confirm.goods\norder.message.new\norder.message.list\norder.message.update","icon":null,"is_show":true,"alias_name":"communityorder","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"708","company_id":0,"name":"\u6d3b\u52a8\u5546\u54c1","url":"\/shopadmin\/marketing\/community\/communitygoods","sort":3,"is_menu":true,"pid":"704","apis":"community.items.list.get\ncommunity.item.sort.update\ncommunity.item.minDeliveryNum.update\ncommunity.item.delete\ncommunity.items.add","icon":null,"is_show":true,"alias_name":"communitygoods","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"709","company_id":0,"name":"\u6d3b\u52a8\u914d\u7f6e","url":"\/shopadmin\/marketing\/community\/setting","sort":4,"is_menu":true,"pid":"704","apis":"community.setting.get\ncommunity.setting.save\ncommunity.chief.apply_field.list\ncommunity.chief.apply_field.create\ncommunity.chief.apply_field.switch\ncommunity.chief.apply_field.update\ncommunity.chief.apply_field.delete\ncommunity.chief.apply.wxaCode","icon":null,"is_show":true,"alias_name":"communitysetting","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"710","company_id":0,"name":"\u56e2\u957f\u4e1a\u7ee9","url":"\/shopadmin\/marketing\/community\/achievement","sort":5,"is_menu":true,"pid":"704","apis":"community.chief.rebate.count","icon":null,"is_show":true,"alias_name":"achievement","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"711","company_id":0,"name":"\u63d0\u73b0\u7533\u8bf7","url":"\/shopadmin\/marketing\/community\/withdraw","sort":6,"is_menu":true,"pid":"704","apis":"community.chief.cash_withdrawal.list\ncommunity.chief.cash_withdrawal.process\ncommunity.chief.cash_withdrawal.payinfo","icon":null,"is_show":true,"alias_name":"withdraw","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u793e\u533a\u56e2\u8d2d","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"712","company_id":0,"name":"\u62a5\u8868","url":"\/shopadmin\/statistics","sort":7,"is_menu":true,"pid":"0","apis":"","icon":"chart-bar","is_show":true,"alias_name":"statistics","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"713","company_id":0,"name":"\u5e97\u94fa\u7edf\u8ba1","url":"\/shopadmin\/statistics\/distributordata","sort":1,"is_menu":true,"pid":"712","apis":"datacube.distributor.data","icon":null,"is_show":true,"alias_name":"distributordata","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u62a5\u8868","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"714","company_id":0,"name":"\u7ed3\u7b97","url":"\/shopadmin\/statistics\/financial\/settlement","sort":2,"is_menu":true,"pid":"712","apis":"","icon":null,"is_show":true,"alias_name":"settlement","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u62a5\u8868","isChildrenMenu":true,"menu_type":["platform"]},{"shopmenu_id":"715","company_id":0,"name":"\u7ed3\u7b97\u6c47\u603b","url":"\/shopadmin\/statistics\/financial\/settlement\/summary","sort":1,"is_menu":true,"pid":"714","apis":"merchant.list\nstatement.summarized.get\nstatement.confirm.post\nstatement.detail.get\nstatement.summarized.export\nstatement.detail.export","icon":null,"is_show":true,"alias_name":"summary","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["platform"]},{"shopmenu_id":"716","company_id":0,"name":"\u5e94\u7528","url":"\/shopadmin\/applications","sort":8,"is_menu":true,"pid":"0","apis":"","icon":"yingyong-01","is_show":true,"alias_name":"applications","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"717","company_id":0,"name":"\u6597\u62f1\u5206\u8d26","url":"\/shopadmin\/applications\/bspay","sort":1,"is_menu":true,"pid":"716","apis":null,"icon":null,"is_show":true,"alias_name":"bspay","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"718","company_id":0,"name":"\u7528\u6237\u8fdb\u4ef6","url":"\/shopadmin\/applications\/bspay\/user","sort":1,"is_menu":true,"pid":"717","apis":"bspay.user_indv.create\nbspay.user_indv.modify\nbspay.user_ent.create\nbspay.user_ent.modify\nbspay.user.audit_state\nbspay.user_ent.info\nbspay.user_indv.info\nbspay.regions\nbspay.regions.third\nbspay.user.audit_state\nbspay.trade.getList","icon":null,"is_show":true,"alias_name":"user","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"719","company_id":0,"name":"\u5206\u8d26\u660e\u7ec6","url":"\/shopadmin\/applications\/bspay\/trades","sort":1,"is_menu":true,"pid":"717","apis":"bspay.trade.getList\nbspay.tradeInfo.get\nbspay.trades.list.export","icon":null,"is_show":true,"alias_name":"trades","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"720","company_id":0,"name":"Adapay\u5206\u8d26","url":"\/shopadmin\/applications\/adapay","sort":1,"is_menu":true,"pid":"716","apis":null,"icon":null,"is_show":true,"alias_name":"adapay","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["b2c","standard","platform"]},{"shopmenu_id":"721","company_id":0,"name":"\u8fdb\u4ef6","url":"\/shopadmin\/applications\/adapay\/adapay_member_entry","sort":1,"is_menu":true,"pid":"720","apis":"adapay.member.create\nadapay.bank.list\nadapay.member.update\nadapay.corp_member.update\nadapay.generate.key\nadapay.member.auditState\nadapay.member.valid\nadapay.member.info\nadapay.corp_member.create\nadapay.member.modify\nadapay.corp_member.modify\nadapay.trade.getList","icon":null,"is_show":true,"alias_name":"adapay_member_entry","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"Adapay\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"722","company_id":0,"name":"\u5206\u8d26","url":"\/shopadmin\/applications\/adapay\/adapay_trades","sort":2,"is_menu":true,"pid":"720","apis":null,"icon":null,"is_show":true,"alias_name":"adapay_trades","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"Adapay\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"723","company_id":0,"name":"\u63d0\u73b0","url":"\/shopadmin\/applications\/adapay\/adapay_cash","sort":3,"is_menu":true,"pid":"720","apis":"adapay.drawcash.getList\nadapay.withdraw","icon":null,"is_show":true,"alias_name":"adapay_cash","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"Adapay\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"724","company_id":0,"name":"\u8fdb\u4ef6\u4fe1\u606f","url":"\/shopadmin\/applications\/adapay\/adapay_member_info","sort":4,"is_menu":true,"pid":"720","apis":"distributor.info","icon":null,"is_show":true,"alias_name":"adapay_member_info","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"Adapay\u5206\u8d26","isChildrenMenu":false,"menu_type":["b2c","platform","standard"]},{"shopmenu_id":"725","company_id":0,"name":"\u4f01\u4e1a\u8d2d","url":"\/shopadmin\/applications\/ec","sort":3,"is_menu":true,"pid":"716","apis":null,"icon":null,"is_show":true,"alias_name":"ec","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"726","company_id":0,"name":"\u4f01\u4e1a\u7ba1\u7406","url":"\/shopadmin\/applications\/ec\/company","sort":1,"is_menu":true,"pid":"725","apis":"employeepurchase.enterprise.add\nemployeepurchase.employee.create\nemployeepurchase.activity.create\nemployeepurchase.employee.delete\nemployeepurchase.enterprise.status.update\nemployeepurchase.activity.users\nemployeepurchase.activity.info\nemployeepurchase.activity.items.add\nemployeepurchase.activity.items.list\nemployeepurchase.activity.suspend\nemployeepurchase.activity.end\nemployeepurchase.enterprise.qrcode.get\npagestemplateset.set\nemployeepurchase.enterprise.update\nemployeepurchase.enterprise.sendtestemail","icon":null,"is_show":true,"alias_name":"company-admin","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"727","company_id":0,"name":"\u5458\u5de5\u7ba1\u7406","url":"\/shopadmin\/applications\/ec\/employee","sort":2,"is_menu":true,"pid":"725","apis":"employeepurchase.enterprise.list\nemployeepurchase.employee.list\nemployeepurchase.employees.export\nemployeepurchase.employee.update","icon":null,"is_show":true,"alias_name":"employee-admin","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"728","company_id":0,"name":"\u6d3b\u52a8\u7ba1\u7406","url":"\/shopadmin\/applications\/ec\/purchaseactivity","sort":3,"is_menu":true,"pid":"725","apis":"promotions.employeepurchase.list\npromotions.employeepurchase.info\npromotions.employeepurchase.add\npromotions.employeepurchase.update\nespier.upload.template.export\nespier.upload\npromotions.employeepurchase.endactivity\npromotions.employeepurchase.dependents.lists\npromotions.employeepurchase.dependents.export\ntemplate_name\nemployeepurchase.activity.items.update\nemployeepurchase.activity.update\nemployeepurchase.activity.if_share_store.set\nemployeepurchase.activity.ahead\nemployeepurchase.activity.items.delete\nemployeepurchase.activity.spec_items.update","icon":null,"is_show":true,"alias_name":"purchase-admin","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"729","company_id":0,"name":"\u8ba2\u5355\u7ba1\u7406","url":"\/shopadmin\/applications\/ec\/purchaseorder","sort":4,"is_menu":true,"pid":"725","apis":"order.deliverystaff.confirm\norder.deliverypackag.confirm\norder.deliverystaff.cancel\nemployeepurchase.activity.list","icon":null,"is_show":true,"alias_name":"purchase-list","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u4f01\u4e1a\u8d2d","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"730","company_id":0,"name":"\u8bbe\u7f6e","url":"\/shopadmin\/shopsetting","sort":9,"is_menu":true,"pid":"0","apis":"order.delivervstaff.confirm","icon":"cog","is_show":true,"alias_name":"shopsetting","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"731","company_id":0,"name":"\u8d26\u53f7\u7ba1\u7406","url":"\/shopadmin\/shopsetting\/staff","sort":1,"is_menu":true,"pid":"730","apis":"order.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"distributor-staff","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["platform","standard"]},{"shopmenu_id":"732","company_id":0,"name":"\u5e97\u94fa\u7ba1\u7406\u5458","url":"\/shopadmin\/shopsetting\/staff\/Merchantstaff","sort":1,"is_menu":true,"pid":"731","apis":"account.create\naccount.list\naccount.info\naccount.update\naccount.delete\nroles.list\naccount.roles.permission\nespier.subdistrict.list.get\noperator.status.change\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"Merchant-staff","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u8d26\u53f7\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"733","company_id":0,"name":"\u5e97\u94fa\u89d2\u8272","url":"\/shopadmin\/shopsetting\/staff\/Merchantstaffroles","sort":1,"is_menu":true,"pid":"731","apis":"roles.create\nroles.list\nroles.info\nroles.update\nroles.delete\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"platformstaffroles","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u8d26\u53f7\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"734","company_id":0,"name":"\u914d\u9001\u5458","url":"\/shopadmin\/shopsetting\/staff\/selfdeliverystaff","sort":2,"is_menu":true,"pid":"731","apis":"datacube.deliverystaff.data\norder.delivervstaff.confirm","icon":null,"is_show":true,"alias_name":"shopadmin_shopsetting_staff_selfdeliverystaff","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u8d26\u53f7\u7ba1\u7406","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"735","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/shopadmin\/shopsetting\/baseexport","sort":2,"is_menu":true,"pid":"730","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"shop-baseexport","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["platform","standard"]},{"shopmenu_id":"736","company_id":0,"name":"\u8131\u654f\u6570\u636e","url":"\/shopadmin\/shopsetting\/datapass","sort":3,"is_menu":true,"pid":"730","apis":"","icon":null,"is_show":true,"alias_name":"datapass","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"737","company_id":0,"name":"\u6743\u9650\u7533\u8bf7","url":"\/shopadmin\/shopsetting\/datapass\/apply","sort":1,"is_menu":true,"pid":"736","apis":"companys.datapass.list\ncompanys.datapass.apply","icon":null,"is_show":true,"alias_name":"applyDataPass","version":3,"disabled":false,"created":1770118453,"updated":1770118453,"level":3,"parent_name":"\u8131\u654f\u6570\u636e","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file diff --git a/storage/static/supplier_menu.json b/storage/static/supplier_menu.json index 52e5ac4..eb5bb1f 100644 --- a/storage/static/supplier_menu.json +++ b/storage/static/supplier_menu.json @@ -1 +1 @@ -[{"shopmenu_id":"10738","company_id":0,"name":"\u5546\u54c1","url":"\/supplier\/entity","sort":10,"is_menu":true,"pid":"0","apis":"goods.tag.rel","icon":"shopping-bag","is_show":true,"alias_name":"entity","version":7,"disabled":false,"created":1720078609,"updated":1720078918,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10741","company_id":0,"name":"\u5546\u54c1\u7ba1\u7406","url":"\/supplier\/entity\/goodsphysical","sort":10,"is_menu":true,"pid":"10738","apis":"currency.get.default\ngoods.items.lists\npopularize.config.get\nwechat.wxa.template.list\ngoods.category.lists\ngoods.attributes.list\ngoods.tag.list\ngoods.tag.export\ngoods.itemsupdate\ngoods.status.upate\npoint.member.rule.info\ngoods.category.get\nespier.image.list\nespier.image.cat.children\ngoods.items.creat\ngoods.items.create\ngoods.items.detail\nespier.oss.uploadToken.get\nespier.image.save\ngoods.items.sort\ngoods.items.delete\ngoods.member.price\ngoods.store.upate\ngoods.items.update\ngoods.items.templates_change\nespier.image.cat.edit\ngoods.items.warning_store\ngoods.export\ndistributor.item.list\ngoods.WarningStore.update\nespier.localimage.upload\nthird.wdterp.setting.get\nthird.jushuitan.setting.get\nall.setting.get\nwechat.wxa.codeunlimit\ngoods.isgift.upate","icon":null,"is_show":true,"alias_name":"goodsphysical","version":7,"disabled":false,"created":1720078679,"updated":1742370225,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10742","company_id":0,"name":"\u5546\u54c1\u5bfc\u5165","url":"\/supplier\/entity\/physicalupload","sort":20,"is_menu":true,"pid":"10738","apis":"espier.upload.list\nespier.upload\nespier.upload.error.export\nall.setting.get","icon":null,"is_show":true,"alias_name":"physicalupload","version":7,"disabled":false,"created":1720078694,"updated":1742370232,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10743","company_id":0,"name":"\u7d20\u6750\u7ba1\u7406","url":"\/supplier\/entity\/brandmaterial","sort":30,"is_menu":true,"pid":"10738","apis":"espier.oss.uploadToken.get\nespier.image.save\nespier.image.cat.edit\nespier.image.cat.del\nespier.image.del","icon":null,"is_show":true,"alias_name":"brandmaterial","version":7,"disabled":false,"created":1720078716,"updated":1720078943,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10739","company_id":0,"name":"\u4ea4\u6613","url":"\/supplier\/order","sort":20,"is_menu":true,"pid":"0","apis":null,"icon":"clipboard-list","is_show":true,"alias_name":"order","version":7,"disabled":false,"created":1720078633,"updated":1720078633,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10745","company_id":0,"name":"\u5168\u90e8\u8ba2\u5355","url":"\/supplier\/order\/tradenormalorders","sort":10,"is_menu":true,"pid":"10739","apis":"order.supplier.order_paid_confirm\norder.remarks.update\ntrade.logistics.list\nespier.subdistrict.list.get\npresale.pickupcode.setting.get\norder.list.get\nsource.list\norder.list.export\norder.info.get\nmember.info\norder.cancel\norder.cancel.info\norder.delivery\norder.delivery.lists\norder.delivery.details\norder.process.log.get\norder.supplier.get_order_list\ninvoice.list.export\nall.setting.get","icon":null,"is_show":true,"alias_name":"shoptradenormalorders","version":7,"disabled":false,"created":1720078763,"updated":1742370239,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10746","company_id":0,"name":"\u6279\u91cf\u53d1\u8d27","url":"\/supplier\/order\/normalordersupload","sort":20,"is_menu":true,"pid":"10739","apis":"espier.upload.template.export","icon":null,"is_show":true,"alias_name":"normalordersupload","version":7,"disabled":false,"created":1720078784,"updated":1720078986,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10747","company_id":0,"name":"\u552e\u540e\u5217\u8868","url":"\/supplier\/order\/aftersaleslist","sort":30,"is_menu":true,"pid":"10739","apis":"distributor.list\naftersales.list\naftersales.info\naftersales.review\naftersales.apply\naftersales.remind.get\naftersales.remind.set\naftersales.logexport\naftersales.sendback\nall.setting.get","icon":null,"is_show":true,"alias_name":"aftersaleslist","version":7,"disabled":false,"created":1720078807,"updated":1742370247,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10748","company_id":0,"name":"\u8fd0\u8d39\u6a21\u677f","url":"\/supplier\/order\/shippingtemplates","sort":40,"is_menu":true,"pid":"10739","apis":"shipping.templates.create\nshipping.templates.list\nespier.address.info\nshipping.templates.info\nshipping.templates.update\nshipping.templates.delete","icon":null,"is_show":true,"alias_name":"shippingtemplates","version":7,"disabled":false,"created":1720078826,"updated":1720079005,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10749","company_id":0,"name":"\u914d\u9001\u7ba1\u7406","url":"\/supplier\/order\/logistics","sort":50,"is_menu":true,"pid":"10739","apis":"company.logistics.list\npickuplocation.list.get\ncompany.dada.info\ncompany.logistics.create\ncompany.logistics.delete","icon":null,"is_show":true,"alias_name":"wl-logistics","version":7,"disabled":false,"created":1720078849,"updated":1720079013,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10768","company_id":0,"name":"\u9000\u6b3e\u5355","url":"\/supplier\/order\/aftersalesrefundlist","sort":60,"is_menu":true,"pid":"10739","apis":"refund.list\nrefund.logexport\nrefund.info","icon":null,"is_show":true,"alias_name":"aftersalesrefundlist","version":7,"disabled":false,"created":1729223037,"updated":1729223123,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10769","company_id":0,"name":"\u9000\u6b3e\u5931\u8d25\u65e5\u5fd7","url":"\/supplier\/order\/Refunderrorlogs","sort":70,"is_menu":true,"pid":"10739","apis":"trade.refunderrorlogs.list\ntrade.refunderrorlogs.resubmit","icon":null,"is_show":true,"alias_name":"order-Refunderrorlogs","version":7,"disabled":false,"created":1729223086,"updated":1729223112,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10740","company_id":0,"name":"\u8bbe\u7f6e","url":"\/supplier\/setting","sort":30,"is_menu":true,"pid":"0","apis":"supplier.register","icon":"cog","is_show":true,"alias_name":"setting","version":7,"disabled":false,"created":1720078659,"updated":1720079930,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"10750","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/supplier\/setting\/baseexport","sort":10,"is_menu":true,"pid":"10740","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"baseexport","version":7,"disabled":false,"created":1720078869,"updated":1720079023,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10751","company_id":0,"name":"\u8131\u654f\u6570\u636e","url":"\/supplier\/setting\/datapass","sort":20,"is_menu":true,"pid":"10740","apis":"companys.datapass.list\ncompanys.datapass.apply","icon":null,"is_show":true,"alias_name":"datapass","version":7,"disabled":false,"created":1720078886,"updated":1720078886,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"10752","company_id":0,"name":"\u4f9b\u5e94\u5546\u5165\u9a7b","url":"\/supplier\/setting\/supplier_register","sort":30,"is_menu":true,"pid":"10740","apis":"supplier.get_supplier_info\nsupplier.register","icon":null,"is_show":true,"alias_name":"supplier_register","version":7,"disabled":false,"created":1720078906,"updated":1720079884,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"11168","company_id":0,"name":"\u8d22\u52a1","url":"\/supplier\/financial","sort":99,"is_menu":true,"pid":"0","apis":"","icon":"","is_show":true,"alias_name":"\/supplier\/financial","version":7,"disabled":false,"created":1749556077,"updated":1749556077,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"11169","company_id":0,"name":"\u7ed3\u7b97","url":"\/supplier\/financial\/settlement","sort":99,"is_menu":true,"pid":"11168","apis":"","icon":"","is_show":true,"alias_name":"\/supplier\/financial\/settlement","version":7,"disabled":false,"created":1749556077,"updated":1749556077,"level":2,"parent_name":"\u8d22\u52a1","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"11181","company_id":0,"name":"\u4f9b\u5e94\u5546\u7ed3\u7b97\u6c47\u603b","url":"\/supplier\/financial\/settlement\/summary_supplier","sort":99,"is_menu":true,"pid":"11169","apis":"statement.summarized.get\nsupplier.get_supplier_list\nstatement.detail.get\nstatement.summarized.export","icon":"","is_show":true,"alias_name":"\/supplier\/financial\/settlement\/summary_supplier","version":7,"disabled":false,"created":1749556077,"updated":1749556077,"level":3,"parent_name":"\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"11183","company_id":0,"name":"\u5e94\u7528","url":"\/supplier\/applications","sort":99,"is_menu":true,"pid":"0","apis":"","icon":"","is_show":true,"alias_name":"\/supplier\/applications","version":7,"disabled":false,"created":1749556077,"updated":1749556077,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"11184","company_id":0,"name":"\u6597\u62f1\u5206\u8d26","url":"\/supplier\/applications\/bspay","sort":99,"is_menu":true,"pid":"11183","apis":"","icon":"","is_show":true,"alias_name":"\/supplier\/applications\/bspay","version":7,"disabled":false,"created":1749556077,"updated":1749556077,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"11185","company_id":0,"name":"\u7528\u6237\u8fdb\u4ef6\u5ba1\u6279","url":"\/supplier\/applications\/bspay\/user_audit","sort":99,"is_menu":true,"pid":"11184","apis":"bspay.sub_approve.list","icon":"","is_show":true,"alias_name":"\/supplier\/applications\/bspay\/user_audit","version":7,"disabled":false,"created":1749556077,"updated":1749556077,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"11186","company_id":0,"name":"\u5206\u8d26\u660e\u7ec6","url":"\/supplier\/applications\/bspay\/trades","sort":99,"is_menu":true,"pid":"11184","apis":"bspay.trade.getList\nbspay.trades.list.export\nstatement.detail.get\nstatement.detail.export","icon":"","is_show":true,"alias_name":"\/supplier\/applications\/bspay\/trades","version":7,"disabled":false,"created":1749556077,"updated":1749556077,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file +[{"shopmenu_id":"778","company_id":0,"name":"\u5546\u54c1","url":"\/supplier\/entity","sort":10,"is_menu":true,"pid":"0","apis":"goods.tag.rel","icon":"shopping-bag","is_show":true,"alias_name":"entity","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"779","company_id":0,"name":"\u5546\u54c1\u7ba1\u7406","url":"\/supplier\/entity\/goodsphysical","sort":10,"is_menu":true,"pid":"778","apis":"currency.get.default\ngoods.items.lists\npopularize.config.get\nwechat.wxa.template.list\ngoods.category.lists\ngoods.attributes.list\ngoods.tag.list\ngoods.tag.export\ngoods.itemsupdate\ngoods.status.upate\npoint.member.rule.info\ngoods.category.get\nespier.image.list\nespier.image.cat.children\ngoods.items.creat\ngoods.items.create\ngoods.items.detail\nespier.oss.uploadToken.get\nespier.image.save\ngoods.items.sort\ngoods.items.delete\ngoods.member.price\ngoods.store.upate\ngoods.items.update\ngoods.items.templates_change\nespier.image.cat.edit\ngoods.items.warning_store\ngoods.export\ndistributor.item.list\ngoods.WarningStore.update\nespier.localimage.upload\nthird.wdterp.setting.get\nthird.jushuitan.setting.get\nall.setting.get\nwechat.wxa.codeunlimit\ngoods.isgift.upate\ngoods.items.params.create","icon":null,"is_show":true,"alias_name":"goodsphysical","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"780","company_id":0,"name":"\u5546\u54c1\u5bfc\u5165","url":"\/supplier\/entity\/physicalupload","sort":20,"is_menu":true,"pid":"778","apis":"espier.upload.list\nespier.upload\nespier.upload.error.export\nall.setting.get","icon":null,"is_show":true,"alias_name":"physicalupload","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"781","company_id":0,"name":"\u7d20\u6750\u7ba1\u7406","url":"\/supplier\/entity\/brandmaterial","sort":30,"is_menu":true,"pid":"778","apis":"espier.oss.uploadToken.get\nespier.image.save\nespier.image.cat.edit\nespier.image.cat.del\nespier.image.del","icon":null,"is_show":true,"alias_name":"brandmaterial","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u5546\u54c1","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"782","company_id":0,"name":"\u4ea4\u6613","url":"\/supplier\/order","sort":20,"is_menu":true,"pid":"0","apis":null,"icon":"clipboard-list","is_show":true,"alias_name":"order","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"783","company_id":0,"name":"\u5168\u90e8\u8ba2\u5355","url":"\/supplier\/order\/tradenormalorders","sort":10,"is_menu":true,"pid":"782","apis":"order.supplier.order_paid_confirm\norder.remarks.update\ntrade.logistics.list\nespier.subdistrict.list.get\npresale.pickupcode.setting.get\norder.list.get\nsource.list\norder.list.export\norder.info.get\nmember.info\norder.cancel\norder.cancel.info\norder.delivery\norder.delivery.lists\norder.delivery.details\norder.process.log.get\norder.supplier.get_order_list\ninvoice.list.export\nall.setting.get\nthird.dmcrm.setting.get\norder.writeoff.set","icon":null,"is_show":true,"alias_name":"shoptradenormalorders","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"784","company_id":0,"name":"\u6279\u91cf\u53d1\u8d27","url":"\/supplier\/order\/normalordersupload","sort":20,"is_menu":true,"pid":"782","apis":"espier.upload.template.export","icon":null,"is_show":true,"alias_name":"normalordersupload","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"785","company_id":0,"name":"\u552e\u540e\u5217\u8868","url":"\/supplier\/order\/aftersaleslist","sort":30,"is_menu":true,"pid":"782","apis":"distributor.list\naftersales.list\naftersales.info\naftersales.review\naftersales.apply\naftersales.remind.get\naftersales.remind.set\naftersales.logexport\naftersales.sendback\nall.setting.get","icon":null,"is_show":true,"alias_name":"aftersaleslist","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"786","company_id":0,"name":"\u8fd0\u8d39\u6a21\u677f","url":"\/supplier\/order\/shippingtemplates","sort":40,"is_menu":true,"pid":"782","apis":"shipping.templates.create\nshipping.templates.list\nespier.address.info\nshipping.templates.info\nshipping.templates.update\nshipping.templates.delete","icon":null,"is_show":true,"alias_name":"shippingtemplates","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"787","company_id":0,"name":"\u914d\u9001\u7ba1\u7406","url":"\/supplier\/order\/logistics","sort":50,"is_menu":true,"pid":"782","apis":"company.logistics.list\npickuplocation.list.get\ncompany.dada.info\ncompany.logistics.create\ncompany.logistics.delete","icon":null,"is_show":true,"alias_name":"wl-logistics","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"788","company_id":0,"name":"\u9000\u6b3e\u5355","url":"\/supplier\/order\/aftersalesrefundlist","sort":60,"is_menu":true,"pid":"782","apis":"refund.list\nrefund.logexport\nrefund.info","icon":null,"is_show":true,"alias_name":"aftersalesrefundlist","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"789","company_id":0,"name":"\u9000\u6b3e\u5931\u8d25\u65e5\u5fd7","url":"\/supplier\/order\/Refunderrorlogs","sort":70,"is_menu":true,"pid":"782","apis":"trade.refunderrorlogs.list\ntrade.refunderrorlogs.resubmit","icon":null,"is_show":true,"alias_name":"order-Refunderrorlogs","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u4ea4\u6613","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"790","company_id":0,"name":"\u8bbe\u7f6e","url":"\/supplier\/setting","sort":30,"is_menu":true,"pid":"0","apis":"supplier.register","icon":"cog","is_show":true,"alias_name":"\/supplier\/setting","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"791","company_id":0,"name":"\u5bfc\u51fa\u5217\u8868","url":"\/supplier\/setting\/baseexport","sort":10,"is_menu":true,"pid":"790","apis":"espier.export.loglist\nespier.export.file.down","icon":null,"is_show":true,"alias_name":"baseexport","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"792","company_id":0,"name":"\u8131\u654f\u6570\u636e","url":"\/supplier\/setting\/datapass","sort":20,"is_menu":true,"pid":"790","apis":"companys.datapass.list\ncompanys.datapass.apply","icon":null,"is_show":true,"alias_name":"datapass","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"793","company_id":0,"name":"\u4f9b\u5e94\u5546\u5165\u9a7b","url":"\/supplier\/setting\/supplier_register","sort":30,"is_menu":true,"pid":"790","apis":"supplier.get_supplier_info\nsupplier.register","icon":null,"is_show":true,"alias_name":"supplier_register","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u8bbe\u7f6e","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"794","company_id":0,"name":"\u8d22\u52a1","url":"\/supplier\/financial","sort":99,"is_menu":true,"pid":"0","apis":"","icon":"","is_show":true,"alias_name":"\/supplier\/financial","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"795","company_id":0,"name":"\u7ed3\u7b97","url":"\/supplier\/financial\/settlement","sort":99,"is_menu":true,"pid":"794","apis":"","icon":"","is_show":true,"alias_name":"\/supplier\/financial\/settlement","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u8d22\u52a1","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"796","company_id":0,"name":"\u4f9b\u5e94\u5546\u7ed3\u7b97\u6c47\u603b","url":"\/supplier\/financial\/settlement\/summary_supplier","sort":99,"is_menu":true,"pid":"795","apis":"statement.summarized.get\nsupplier.get_supplier_list\nstatement.detail.get\nstatement.summarized.export","icon":"","is_show":true,"alias_name":"\/supplier\/financial\/settlement\/summary_supplier","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":3,"parent_name":"\u7ed3\u7b97","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"797","company_id":0,"name":"\u5e94\u7528","url":"\/supplier\/applications","sort":99,"is_menu":true,"pid":"0","apis":"","icon":"","is_show":true,"alias_name":"\/supplier\/applications","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":1,"parent_name":"\u65e0","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"798","company_id":0,"name":"\u6597\u62f1\u5206\u8d26","url":"\/supplier\/applications\/bspay","sort":99,"is_menu":true,"pid":"797","apis":"","icon":"","is_show":true,"alias_name":"\/supplier\/applications\/bspay","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":2,"parent_name":"\u5e94\u7528","isChildrenMenu":true,"menu_type":["all"]},{"shopmenu_id":"799","company_id":0,"name":"\u7528\u6237\u8fdb\u4ef6","url":"\/supplier\/applications\/bspay\/user","sort":1,"is_menu":true,"pid":"798","apis":"bspay.user_indv.create\nbspay.user_indv.modify\nbspay.user_ent.create\nbspay.user_ent.modify\nbspay.user.audit_state\nbspay.user_ent.info\nbspay.user_indv.info\nbspay.regions\nbspay.regions.third\nbspay.user.audit_state\nbspay.trade.getList","icon":null,"is_show":true,"alias_name":"user","version":7,"disabled":false,"created":1770118610,"updated":1770118610,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["all"]},{"shopmenu_id":"800","company_id":0,"name":"\u5206\u8d26\u660e\u7ec6","url":"\/supplier\/applications\/bspay\/trades","sort":1,"is_menu":true,"pid":"798","apis":"bspay.trade.getList\nbspay.tradeInfo.get\nbspay.trades.list.export","icon":null,"is_show":true,"alias_name":"trades","version":7,"disabled":false,"created":1770118611,"updated":1770118611,"level":3,"parent_name":"\u6597\u62f1\u5206\u8d26","isChildrenMenu":false,"menu_type":["all"]}] \ No newline at end of file