diff --git a/README.md b/README.md index 218bbf72..ecdcdc5b 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,14 @@ # Lilishop(PickMall) 开源商城系统 -[![GitHub Stars](https://img.shields.io/github/stars/hongyehuicheng/lilishop.svg?style=social&logo=github)](https://github.com/hongyehuicheng/lilishop) +[![GitHub Stars](https://img.shields.io/github/stars/lilishop/lilishop.svg?style=social&logo=github)](https://github.com/lilishop/lilishop) [![Gitee Stars](https://gitee.com/beijing_hongye_huicheng/lilishop/badge/star.svg?theme=dark)](https://gitee.com/beijing_hongye_huicheng/lilishop) +[![License](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)](./LICENSE) +[![Vue](https://img.shields.io/badge/Vue-3-brightgreen.svg)](https://vuejs.org/) +

简体中文 | English

-## All-In-One 一键启动 - -如果只是想快速体验完整商城,不需要分别部署后端、PC、商家端、运营端、IM Web、H5、MySQL 和 Redis。安装 Docker Desktop 后,可以直接下载 `docker` 仓库 `allinone-lite-mysql-redis` 分支的一键安装脚本,按提示输入 IP/域名、端口、密码和数据目录,即可启动单镜像单容器体验环境。 - -macOS / Linux: - -```bash -curl -fsSL https://gitee.com/beijing_hongye_huicheng/docker/raw/allinone-lite-mysql-redis/install/install-lilishop.sh -o install-lilishop.sh -chmod +x install-lilishop.sh -./install-lilishop.sh -``` - -Windows PowerShell: - -```powershell -Invoke-WebRequest -Uri "https://gitee.com/beijing_hongye_huicheng/docker/raw/allinone-lite-mysql-redis/install/install-lilishop.ps1" -OutFile "install-lilishop.ps1" -Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -.\install-lilishop.ps1 -``` - -默认镜像:`ccr.ccs.tencentyun.com/lilishop/lilishop-all-in-one:lite`。启动后可访问买家 PC、商家端、运营端、IM Web 会话/消息页、uniapp H5 和后端 API。更多说明见 [docker/all-in-one 文档](https://gitee.com/beijing_hongye_huicheng/docker/tree/allinone-lite-mysql-redis/all-in-one)。 - -All-In-One `lite` 是本地体验和演示形态:一个容器内包含应用、前端资源、H5、MariaDB、Redis 和本地文件存储。它不是生产高可用架构,也不内置 Elasticsearch、RocketMQ、XXL-Job、Kibana、Logstash 或 RocketMQ Dashboard;搜索、消息和定时任务逻辑在 lite 环境中使用 MySQL / Redis / 本地调度兼容实现。 LILISHOP 是基于 Spring Boot / Spring Cloud / Vue / Uniapp 开发的 Java 开源商城系统,支持 B2B2C 多商户商城、小程序商城、微服务商城、直播电商、分销返佣、秒杀活动、Docker 私有化部署。 @@ -36,7 +16,7 @@ LILISHOP 是基于 Spring Boot / Spring Cloud / Vue / Uniapp 开发的 Java 开 - Java商城系统 - 开源商城系统 -- SpringBoot商城系统 +- Spring Boot 4商城系统 - SpringCloud微服务商城 - B2B2C商城源码 - 多商户商城系统 @@ -58,14 +38,15 @@ LILISHOP 是基于 Spring Boot / Spring Cloud / Vue / Uniapp 开发的 Java 开 ### 1. 项目简介 **Lilishop** 是一款功能完善的B2B2C多商户商城系统,采用前后端分离架构,全端代码开源。 -后端基于 **SpringBoot3** 构建,具备高内聚、低耦合的特性,支持分布式部署。 +后端基于 **Spring Boot 4**(Java 21)构建,具备高内聚、低耦合的特性,支持分布式部署。 前端覆盖PC、H5、小程序和APP,基于 **Vue** 和 **uni-app** 开发。 - **官方网站**: - **官方文档**: -- **Gitee 仓库**: +- **Gitee 仓库**: - **GitHub 仓库**: +本仓库为 **PC / 商家端 / 运营端 / IM Web** 源码(`lilishop-ui`)。 --- @@ -103,30 +84,10 @@ LILISHOP 是基于 Spring Boot / Spring Cloud / Vue / Uniapp 开发的 Java 开 [**部署文档 -> 环境准备**](https://docs.pickmall.cn/deply/deply.html) #### 数据库初始化 -- **推荐方式**: 使用 [`docker`](https://gitee.com/beijing_hongye_huicheng/docker) 仓库中的 `docker-compose`,可自动完成 **MySQL、Redis** 等中间件的部署与初始化。 +- **推荐方式**: 使用项目提供的 `docker-compose` 配置,可自动完成数据库(MySQL、Redis 等)的部署与初始化。 - **手动方式**: 如果您选择手动部署,SQL脚本位于以下地址。请确保获取与您代码版本一致的SQL文件。 [**数据库脚本 (Gitee)**](https://gitee.com/beijing_hongye_huicheng/docker/tree/master/init/mysql) -#### 后端服务与端口(`vue3` 分支) - -| 服务 | 端口 | 说明 | -| :--- | :--- | :--- | -| buyer-api | 8888 | 买家端 API | -| manager-api | 8887 | 平台 + 商家 API(`/manager/**`、`/store/**`) | -| im-api | 8885 | 客服 IM / WebSocket | - -运行依赖:**MySQL + Redis**。商品搜索使用 MySQL;异步消息使用 Redis 队列;定时任务使用 Spring `@Scheduled`(内嵌在 manager-api)。 - -#### 前端 API 路径约定 - -| 端 | 公共接口前缀 | -| :--- | :--- | -| 买家 PC/H5 | `{buyerUrl}/buyer/common/*` | -| 商家端 | `{sellerUrl}/store/common/*` | -| 平台端 | `{managerUrl}/manager/common/*` | - -`common-api` 已下线,请勿再使用 `/common/common/*` 旧路径。 - --- ### 5. 架构文档边界 @@ -140,10 +101,13 @@ LILISHOP 是基于 Spring Boot / Spring Cloud / Vue / Uniapp 开发的 Java 开 - H5 / 小程序 / APP:`lilishop-uniapp` - 部署、SQL、镜像与启动脚本:`docker` +--- + ### 6. 功能列表 [功能清单](https://bdwx2tfwwt.feishu.cn/sheets/FFQKscQKDhUx60to1k9cbMngnYb?from=from_copylink) +--- ### 7. 开源与授权 @@ -160,6 +124,34 @@ LILISHOP 是基于 Spring Boot / Spring Cloud / Vue / Uniapp 开发的 Java 开 我们欢迎任何形式的交流与贡献。在提问前,请先查阅 [官方文档](https://docs.pickmall.cn/) ,并参考 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md) 以便高效沟通。 - **[在线客服](https://work.weixin.qq.com/kfid/kfc4d8dc24a73c15f44)** -- **微信交流1群(已满)** -- **微信交流2群**: +- **微信交流群**: ![微信群](https://lilishop-wechat.oss-cn-beijing.aliyuncs.com/wechat.jpg) + +--- + +### 9. 升级计划 + +以下功能将陆续在后续版本中发布:✅ 已完成 · 🔜 规划中 + +- ✅ 商品定时上下架 +- ✅ 商品分组 +- ✅ 会员分组 +- ✅ 商品虚拟销量 +- ✅ 专用发票(发票上传) +- ✅ 置顶评论 +- ✅ 客户等级 +- ✅ 购物卡 +- ✅ 腾讯云-云直播 +- ✅ 统计:营业概况、商品概况、会员概况、积分分析、储值分析、营销概况、分销统计 +- ✅ 经营报表(店铺业绩报表、商品同比环比报表、销售订单明细报表、商品销售汇总报表) +- ✅ 卡密商品 +- ✅ 二级分销 +- ✅ 定时任务管理 +- 🔜 主题色管理 +- 🔜 店铺结算汇总 +- 🔜 支付方式汇总 +- 🔜 结算台账 +- 🔜 钱包流水 +- 🔜 财务汇总 +- 🔜 微信小店对接 +- 🔜 抖店对接 diff --git a/buyer/src/api/member.js b/buyer/src/api/member.js index 31a55140..76ab273d 100644 --- a/buyer/src/api/member.js +++ b/buyer/src/api/member.js @@ -356,33 +356,19 @@ export function distribution () { } /** - * 申请成为分销商 - * @param idNumber 身份证号 - * @param name 名字 + * 提交招募申请 */ -export function applyDistribution (params) { +export function submitRecruitApplication (data) { return request({ - url: `/buyer/distribution/distribution`, + url: `/buyer/distribution/distribution/recruit/apply`, method: Method.POST, needToken: true, - params + data }); } /** - * 获取分销商订单列表 - */ -export function getDistOrderList (params) { - return request({ - url: `/buyer/distribution/order`, - method: Method.GET, - needToken: true, - params - }); -} - -/** - * 获取分销商商品列表 + * 获取分销员商品列表 */ export function getDistGoodsList (params) { return request({ @@ -408,7 +394,7 @@ export function selectDistGoods (params) { } /** - * 分销商提现历史 + * 分销员提现历史 */ export function distCashHistory (params) { return request({ @@ -420,7 +406,7 @@ export function distCashHistory (params) { } /** - * 分销商提现 + * 分销员提现 */ export function distCash (params) { return request({ diff --git a/buyer/src/pages/home/memberCenter/Distribution.vue b/buyer/src/pages/home/memberCenter/Distribution.vue index 875c4d25..b2b7eabe 100644 --- a/buyer/src/pages/home/memberCenter/Distribution.vue +++ b/buyer/src/pages/home/memberCenter/Distribution.vue @@ -4,24 +4,11 @@
- 分销商申请 + 分销员申请 - - + + - - - - - - - - - - - - - 提交申请 { if (valid) { this.applyLoading = true; - applyDistribution(this.applyForm).then((res) => { + submitRecruitApplication({ agreementAccepted: true }).then((res) => { this.applyLoading = false; if (res.success) { Message.success("申请已提交,请等待管理员审核"); @@ -496,7 +451,7 @@ export default { }, //申诉 repaying(){ - applyDistribution().then((res) => { + submitRecruitApplication({ agreementAccepted: true }).then((res) => { this.applyLoading = false; if (res.success) { Message.success("申诉已提交,请等待管理员审核"); @@ -505,7 +460,7 @@ export default { }); }, distribution() { - // 获取分销商信息 + // 获取分销员信息 distribution() .then((res) => { if (res?.result) { diff --git a/manager/public/config.js b/manager/public/config.js index 59011110..4478e187 100644 --- a/manager/public/config.js +++ b/manager/public/config.js @@ -3,7 +3,7 @@ var BASE = { * @description api请求基础路径 */ API_DEV: { - manager: "https://admin-api.pickmall.cn", + manager: "http://127.0.0.1:8887", }, API_PROD: { manager: "https://admin-api.pickmall.cn" diff --git a/manager/src/api/distribution.js b/manager/src/api/distribution.js index b12706a6..2f118b1c 100644 --- a/manager/src/api/distribution.js +++ b/manager/src/api/distribution.js @@ -1,11 +1,45 @@ // 统一请求路径前缀在libs/axios.js中修改 -import {getRequest, postRequest, putRequest, deleteRequest} from '@/libs/axios'; +import {getRequest, postRequest, postRequestWithNoForm, putRequest, putRequestWithNoForm, deleteRequest, importRequest} from '@/libs/axios'; //查询分销员 export const getDistributionListData = (params) => { return getRequest('/distribution/distribution/getByPage', params) } +// 分销员聚合分页(V2) +export const getDistributionMemberPage = (params) => { + return getRequest('/distribution/distribution/memberPage', params) +} +export const getDistributionMemberDetail = (id) => { + return getRequest(`/distribution/distribution/memberDetail/${id}`) +} +export const updateDistributionMember = (id, params) => { + return putRequestWithNoForm(`/distribution/distribution/member/${id}`, params) +} +export const createDistributionMember = (params) => { + return postRequestWithNoForm('/distribution/distribution/member', params) +} +export const batchUpdateDistributionGrade = (params) => { + return putRequestWithNoForm('/distribution/distribution/member/batchGrade', params) +} +export const exportDistributionMembers = (params) => { + return getRequest('/distribution/distribution/memberExport', params, 'blob') +} +export const downloadDistributionImportTemplate = () => { + return getRequest('/distribution/memberImport/template', {}, 'blob') +} +export const importDistributionMembers = (formData) => { + return importRequest('/distribution/memberImport/import', formData) +} +export const getDistributionImportBatches = (params) => { + return getRequest('/distribution/memberImport/batch', params) +} +export const getDistributionImportItems = (batchId, params) => { + return getRequest(`/distribution/memberImport/batch/${batchId}/items`, params) +} +export const downloadDistributionImportFailItems = (batchId) => { + return getRequest(`/distribution/memberImport/batch/${batchId}/failExport`, {}, 'blob') +} //审核分销员 export const auditDistribution = (id, params) => { return putRequest(`/distribution/distribution/audit/${id}`, params) @@ -34,6 +68,50 @@ export const getDistributionSetting = (id, params) => { return getRequest(`/distribution/setting/get/${id}`, params) } +// V2客户关系设置 +export const getDistributionCustomerSetting = () => getRequest('/distribution/setting/v2/customer') +export const putDistributionCustomerSetting = (params) => putRequestWithNoForm('/distribution/setting/v2/customer', params) +// V2结算方案设置 +export const getDistributionSettlementSetting = () => getRequest('/distribution/setting/v2/settlement') +export const putDistributionSettlementSetting = (params) => putRequestWithNoForm('/distribution/setting/v2/settlement', params) +// 分销商品设置 +export const getDistributionFeaturedGoodsSetting = () => getRequest('/distribution/setting/v2/featured-goods') +export const putDistributionFeaturedGoodsSetting = (params) => putRequestWithNoForm('/distribution/setting/v2/featured-goods', params) +// 平台海报设置 +export const getDistributionPromotionPosterSetting = () => getRequest('/distribution/setting/v2/promotion-poster') +export const putDistributionPromotionPosterSetting = (params) => putRequestWithNoForm('/distribution/setting/v2/promotion-poster', params) +// 邀请卡设置 +export const getDistributionInviteCardSetting = () => getRequest('/distribution/setting/v2/invite-card') +export const putDistributionInviteCardSetting = (params) => putRequestWithNoForm('/distribution/setting/v2/invite-card', params) +// 分销等级 +export const getDistributionGrades = () => getRequest('/distribution/grade') +export const saveAllDistributionGrades = (params) => putRequestWithNoForm('/distribution/grade/batch', params) +export const deleteDistributionGrade = (id) => deleteRequest(`/distribution/grade/${id}`) +export const getDistributionGradeHistoryPage = (params) => getRequest('/distribution/gradeHistory', params) + +// 客户关系 +export const getCustomerRelations = (params) => getRequest('/distribution/customerRelation', params) +export const getCustomerRelationDetail = (id) => getRequest(`/distribution/customerRelation/${id}`) +export const getCustomerRelationLogs = (id) => getRequest(`/distribution/customerRelation/${id}/logs`) +export const rebindCustomerRelation = (params) => putRequest('/distribution/customerRelation/rebind', params) +export const unbindCustomerRelation = (params) => putRequest('/distribution/customerRelation/unbind', params) + +// 分销招募设置 +export const getCurrentRecruitPlan = () => getRequest('/distribution/recruit/plan/current') +export const getPublishedRecruitPlan = () => getRequest('/distribution/recruit/plan/published') +export const saveRecruitPlan = (params) => postRequestWithNoForm('/distribution/recruit/plan', params) +export const getDistributionRecruitSetting = () => getRequest('/distribution/setting/v2/recruit') +export const putDistributionRecruitSetting = (params) => putRequestWithNoForm('/distribution/setting/v2/recruit', params) +export const publishRecruitPlan = (planId) => putRequest(`/distribution/recruit/plan/publish/${planId}`) +export const auditRecruitApplication = (applicationId, params) => putRequest(`/distribution/recruit/application/audit/${applicationId}`, params) + +// 统计V2 +export const getDistributionOverviewV2 = (params) => getRequest('/statistics/distribution/v2/overview', params) +export const getDistributionBehaviorV2 = (params) => getRequest('/statistics/distribution/v2/behavior', params) +export const getDistributionGoodsV2 = (params) => getRequest('/statistics/distribution/v2/goods', params) + +// 钱包流水 +export const getDistributionWalletLogs = (params) => getRequest('/distribution/walletLog', params) //获取分销订单列表 export const getDistributionOrder = (params) => { @@ -48,6 +126,10 @@ export const getDistributionGoods = (params) => { export const delDistributionGoods = (ids) => { return deleteRequest(`/distribution/goods/delByIds/${ids}`) } + +export const auditDistributionGoods = (params) => { + return putRequestWithNoForm('/distribution/goods/audit', params) +} //获取分销佣金信息 export const getDistributionCash = (params) => { return getRequest('/distribution/cash/getByPage', params) @@ -56,6 +138,3 @@ export const getDistributionCash = (params) => { export const auditDistributionCash = (id,params) => { return postRequest(`/distribution/cash/audit/${id}`, params) } - - - diff --git a/manager/src/api/timedTask.js b/manager/src/api/timedTask.js new file mode 100644 index 00000000..7b838365 --- /dev/null +++ b/manager/src/api/timedTask.js @@ -0,0 +1,11 @@ +import { managerApiUrl, getRequest, postRequest } from '@/libs/axios'; + +// 获取定时任务列表 +export const getTimedTaskList = () => { + return getRequest(`${managerApiUrl}/manager/setting/timed-task`); +}; + +// 手动触发定时任务 +export const triggerTimedTask = (type) => { + return postRequest(`${managerApiUrl}/manager/setting/timed-task/trigger/${type}`); +}; diff --git a/manager/src/components/distribution/distribution-selector.vue b/manager/src/components/distribution/distribution-selector.vue new file mode 100644 index 00000000..d644697d --- /dev/null +++ b/manager/src/components/distribution/distribution-selector.vue @@ -0,0 +1,188 @@ + + + + + diff --git a/manager/src/libs/util.js b/manager/src/libs/util.js index 2b46a803..60151925 100644 --- a/manager/src/libs/util.js +++ b/manager/src/libs/util.js @@ -7,7 +7,6 @@ let util = {}; /** 已弃用、前端未实现或已移除的菜单 frontRoute,注册路由时跳过 */ const DEPRECATED_FRONT_ROUTES = new Set([ "goods/goods-manage/spec", - "distribution/distrbutionGrade", ]); function isDeprecatedMenu(menu) { @@ -334,8 +333,8 @@ util.initAllMenuData = function(constRoutes, data) { util.initMenuData = function(vm, data) { const menuRoutes = []; let menuData = data; - // 顶部菜单 - let navList = []; + // 顶部菜单 —— 首页固定置顶 + let navList = [{ name: 'home_index', title: '首页' }]; menuData.forEach(e => { let nav = { name: e.name, @@ -358,11 +357,16 @@ util.initMenuData = function(vm, data) { } } } else { - // 默认第一个 - currNav = navList[0].name; - vm.$store.commit("setCurrNavTitle", navList[0].title); + // 默认首页 + currNav = 'home_index'; + vm.$store.commit("setCurrNavTitle", '首页'); } vm.$store.commit("setCurrNav", currNav); + // 首页不需要二级菜单 + if (currNav === 'home_index') { + vm.$store.commit("updateMenulist", []); + return; + } for (let item of menuData) { if (item.name == currNav) { // 过滤 diff --git a/manager/src/router/router.js b/manager/src/router/router.js index ab17a940..06dfe87f 100644 --- a/manager/src/router/router.js +++ b/manager/src/router/router.js @@ -455,6 +455,20 @@ export const otherRouter = { meta: { title: "商品销售汇总报表" }, component: () => import("@/views/statistics/goods-sales-summary.vue") }, + { + path: "distributionImportRecord", + title: "分销员导入记录", + name: "distributionImportRecord", + meta: { title: "分销员导入记录" }, + component: () => import("@/views/distribution/distributionImportRecord.vue") + }, + { + path: "distributionGradeHistory", + title: "等级变更记录", + name: "distributionGradeHistory", + meta: { title: "等级变更记录" }, + component: () => import("@/views/distribution/distributionGradeHistory.vue") + }, { path: "procurement/purchase-order/detail", title: "采购单详情", diff --git a/manager/src/styles/element.scss b/manager/src/styles/element.scss index 32300bdd..6448267f 100644 --- a/manager/src/styles/element.scss +++ b/manager/src/styles/element.scss @@ -47,6 +47,20 @@ background-color: transparent; } +/* 全局表格表头 */ +.el-table { + .el-table__header th.el-table__cell { + background: var(--el-color-primary-light-9, #ecf5ff); + color: #303133; + font-weight: normal; + } + + .el-table__header th.el-table__cell .cell { + color: #303133; + font-weight: normal; + } +} + /* 列表操作列统一样式 */ .link-text { color: #409eff; diff --git a/manager/src/views/Main.vue b/manager/src/views/Main.vue index d2072feb..79c1b402 100644 --- a/manager/src/views/Main.vue +++ b/manager/src/views/Main.vue @@ -2,7 +2,7 @@ @import "./main.scss"; + + diff --git a/manager/src/views/distribution/distributionApply.vue b/manager/src/views/distribution/distributionApply.vue deleted file mode 100644 index c31c0bf2..00000000 --- a/manager/src/views/distribution/distributionApply.vue +++ /dev/null @@ -1,156 +0,0 @@ - - - - diff --git a/manager/src/views/distribution/distributionCash.vue b/manager/src/views/distribution/distributionCash.vue index 43dddb40..a0228fcc 100644 --- a/manager/src/views/distribution/distributionCash.vue +++ b/manager/src/views/distribution/distributionCash.vue @@ -7,10 +7,10 @@ class="search-form" @keyup.enter="handleSearch" > - + @@ -23,16 +23,6 @@ style="width: 240px" /> - - - - - 搜索 @@ -40,6 +30,13 @@ + + + + + + + - + + - - - - - - - - + + + + @@ -108,34 +155,162 @@ />
+ + + + + + 通过 + 驳回 + + + + + + + + + + diff --git a/manager/src/views/distribution/distributionGradeHistory.vue b/manager/src/views/distribution/distributionGradeHistory.vue new file mode 100644 index 00000000..95455f4a --- /dev/null +++ b/manager/src/views/distribution/distributionGradeHistory.vue @@ -0,0 +1,220 @@ + + + + + diff --git a/manager/src/views/distribution/distributionImportRecord.vue b/manager/src/views/distribution/distributionImportRecord.vue new file mode 100644 index 00000000..4f561839 --- /dev/null +++ b/manager/src/views/distribution/distributionImportRecord.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/manager/src/views/distribution/distributionOrder.vue b/manager/src/views/distribution/distributionOrder.vue index 54c21f76..6c263e09 100644 --- a/manager/src/views/distribution/distributionOrder.vue +++ b/manager/src/views/distribution/distributionOrder.vue @@ -1,5 +1,5 @@