---
title: 2026-产品文档-开发文档
description: 文本抽取：知识库/03-批发经销采购场景/2026-产品文档-开发文档
updated: 2026-11-04
tags: [原始文档, 抽取, 知识库]
source: 知识库/03-批发经销采购场景/2026-产品文档-开发文档
source_type: txt
source_hash: 0db9b87c570a
extracted_at: 2026-11-04
quality: ok
---

---
source: 知识库/03-批发经销采购场景/2026-产品文档-开发文档.docx
type: docx
size_kb: 280
category: 03-批发经销采购场景
quality: ok
---

## 产品文档-开发文档-中文站点

## 前端

### PC商城

A Quasar Framework app使用的 vue2 全家桶开发Quasar 和 vue 的用法一模一样,默认的启动文件写在 boot 文件下,在 quasar.config 配置到 boot 下会自动添加到启动文件如同自动添加到 vue 的 main.js 具体使用看 quasar 文档,和 nuxt 的启动文件如出一辙 Quasar 的组件为自动按需导入,ElementUI 的通过 unplugin-vue-components 插件实现自动按需导入自动导入打包后体积极小整个项目 2Munplugin-vue-components 生成的映射文件为 components.d.ts 不可删除mixin 全局混入文件在 types 内编写

中文官网(http://v1.quasarchs.com/)

ssr 通过 Quasar 实现,支持 spa 和 ssr 同步运行需要 ssr 的数据加上 preFetch 预取方法即可无需其他额外更改

preFetch 内部的实例挂在在 store 上 请求请使用 store.apiGet 之类,因为这样可以保持 spa 和 ssr 的同步,在 spa 下没有上下文对象则不挂在在上下文对象使用,合并请求到的数据到 data 使用 store.commit('SET')则会自动合并到 data 中, 动态的 seo-meta 使用 store.commit('set_seoData') 则会把后台请求的 seo 配置自动合并到 data 的 seoData 数据中当前页面的 seo-meta 未配置则使用全局的 meta,此功能在 spa 下依旧有效,ssr 和 spa 的功能保持完全一致

#### 示例

meta() {
return {
  title: this.seoData.seoTitle,
    meta: {
      keywords: {
        name: 'keywords',
        content: this.seoData.seoKeyWord
      },
    description: {
      name: 'description',
      content: this.seoData.seoContent
      }
    }
  }
}

修改 ssr node 服务则在 scr-ssr 内部修改,路由自动生成,生成规则和 nuxt 一致,但是可以在 pages 编写组件会自动跳过 components 和 modules 的文件名或文件夹,也可以不使用css 使用 tailwindcss 框架 自动生成,只会生成用到的原子类,不会出现一行重复的 css,颜色配置统一在 tailwind.conf 和 quasar.variables 请同步修改一个是修改 quasar 组件的颜色变量 一个则是自己使用的原子类,如要使用 css 变量则一样的能保持颜色的统一自带 google icons 和 bootstrap icons 如想获得 icons 代码提示和预览效果则可以使用 vscode Iconify IntelliSense 插件

如有站长工具或者百度统计等外挂代码直接写入到 index.template.html 非 DO NOT touch the following DIV 区域即可

因为和 nuxt 一样根据目录自动生成路由,如需要添加额外的路由信息比如 meta 则在页面中使用 route 标签包裹内部数据为 json 自动合并到路由信息上 layout 可以指定父级在那一个 router-view 下 依赖于 vue-route-generator 和 vue-router-layout webpack 插件实现

#### 示例

{ "layout": "empty", "meta": { title:"登录" } }

vscode 全局组件获得代码提示则配置到 vetur.config 已经有的全局组件已配置 则使用的时候不会在当前页自动导入如有 css 自定义属性名则配置 tailwindcss 插件依旧可以获得代码提示,配合 Tailwind CSS IntelliSense 官方插件使用

#### NODE JS 版本

16版本

#### tailwindcss 运行命令

npm run css build

#### spa 命令

npm run dev 运行
npm run build 打包

#### ssr 运行命令

npm run dev:ssr

#### ssr 打包命令

npm run build:ssr

#### Install the dependencies

yarn

#### Start the app in development mode (hot-code reloading, error reporting, etc.)

quasar dev

#### Lint the files

yarn run lint

#### Build the app for production

quasar build

#### 目录说明

scripts/ # 构建脚本目录

src/ # 源代码主目录

src-ssr/ # SSR相关配置目录

types/ # TypeScript类型定义

README.md # 项目说明文档

babel.config.js # Babel配置文件

components.d.ts # 自动导入组件类型定义

i18n-config.js # 国际化配置

i18nauto.config.js # 自动国际化配置

jsconfig.json # JavaScript配置

package.json # 项目依赖配置

tailwind.config.js # Tailwind CSS配置

translate.js # 翻译脚本

vetur.config.js # Vetur配置

#### src 目录说明

assets/ # 静态资源

js/ # JavaScript工具类

Apis.js # API接口定义

enumeration.js # 枚举定义

urls.js # URL路径定义

watermark.js # 水印功能

boot/ # Quasar启动配置

axios.js # Axios配置

directive.js # 自定义指令

element.js # Element UI配置

filter.js # 过滤器定义

i18n.js # 国际化配置

mixins.js # 全局混入

permission.js # 权限路由守卫

plugins.js # 插件配置

v-export.js # 导出指令

components/ # 通用组件

cart/ # 购物车相关组件

goods/ # 商品相关组件

user/ # 用户相关组件

其他组件文件

css/ # 样式文件

app.scss # 应用主样式

element-variables.scss # Element UI变量

input.css # 输入框样式

quasar.variables.scss # Quasar变量

tailwind.css # Tailwind样式

i18n/ # 国际化配置

index.js # 国际化入口

layouts/ # 页面布局

404.vue # 404页面布局

README.md # 布局说明

default.vue # 默认布局

empty.vue # 空布局

error.vue # 错误布局

locale/ # 本地化文件

en.json # 英文本地化

suggestion.json # 建议文本

zh.js # 中文本地化

my-components/ # 自定义业务组件

modules/ # 模块化组件

单独组件文件

pages/ # 页面组件

activity/ # 活动页面

cart/ # 购物车页面

goods/ # 商品页面

news/ # 新闻页面

often/ # 常用页面

register/ # 注册页面

user/ # 用户页面

其他页面文件

router/ # 路由配置

index.js # 路由入口

loader.js # 路由加载器

routes.js # 路由定义

store/ # Vuex状态管理

module-example/ # 示例模块

index.js # 状态管理入口

store-flag.d.ts # 状态管理类型定义

widgets/ # 挂件组件

global/ # 全局挂件

pc-carousel.vue # PC轮播挂件

pc-editor.vue # PC编辑器挂件

pc-floor-left-and-right.vue # PC楼层左右布局挂件

pc-floor.vue # PC楼层挂件

pc-goods-card.vue # PC商品卡片挂件

pc-goods-grid.vue # PC商品网格挂件

pc-images.vue # PC图片挂件

pc-news-card.vue # PC新闻卡片挂件

pc-separator.vue # PC分割线挂件

pc-space.vue # PC间距挂件

pc-title.vue # PC标题挂件

pc-video.vue # PC视频挂件

quick-nav.vue #快速导航挂件

App.vue # 应用主组件

index.template.html # HTML模板

#### Customize the configuration

See Configuring quasar.conf.js.

#### 组件具体属性功能可直接看组件内部注释

#### j-address 地址选择组件

通过 dataKey 和 label 决定 显示属性

#### j-crumbs 基础面包屑和高级面包屑组件

disabled 传参是否开启高级面包屑

#### j-dialog 对话框组件

支持拖拽, 继承 quasar 对话框所有属性功能,扩展默认底部按钮和对话框拖拽功能

#### j-dict-multiple 字典多选组件

继承 ele 选择器属性功能只需要传递 dictCode 字典编码自动生成

#### j-dict-select 字典单选组件

继承 ele 选择器属性功能只需要传递 dictCode 字典编码自动生成

#### j-form-auto 自动表单生成组件

继承 ele 表单属性, 传递 config 表单配置项 生成表单配置项为 type 代表表单组件类型,比如 input,number-input,select,radio,checkbox,switch,j-dict-select 等常用表单组件表单组件传递 attrs 配置到具体的组件,required 为是否必填, 自带 手机号,邮箱,身份证,信用编码,银行卡,座机号格式验证,rules:[{type:'验证类型'}]验证类型为对应的英文,组件内部查看即可自定义验证规则则正常传入传递数组,options 为多选或 select 的子项,attrs 同样有效表单数据可以通过 v-model 绑定也可以在$refs.form.submit 验证通过时此方法.then(form)中返回出表单数据只有验证通过才会触发.then示例 config: [{ label: '所在地址', name: 'custom', required: true },{label: '地址标签',name: 'addressLabel',type: 'radio-button',options: [{ label: '家', value: 10 },{ label: '公司', value: 20 }]},{ label: '街道地址', name: 'reals', type: 'input', attrs: { type: 'textarea' }, required: true },{ label: '邮政编码', name: 'postalCode', type: 'number' },{ label: '收货人姓名', name: 'contactsName', type: 'input', required: true },{label: '收货人手机号',name: 'contactsPhone',type: 'phone',rules: [{ type: 'phone' }],required: true},{label: '',name: 'isDefault',type: 'checkbox',attrs: { 'true-label': 10, 'false-label': 20, name: '是否设置成默认地址' }}],

#### j-form 表单组件

验证包裹器单纯验证数据配合 j-form-item 可以验证任何组件只验证数据提示在被包裹的子组件

#### j-markup-table 简单表格同 j-table 继承 ele 表格功能实现为一致

自带分页 pages.sync 穿分页数据并且同步修改 pagesChange 则是分页变化后的回调columns 为表格配置项 label name width 等

#### j-pages 分页组件

同表格分页功能 pages.sync 变为 v-model

#### j-tool-bar 工具栏组件

只显示单行 多行则自动出现更多按钮 可以展开关闭

#### j-truncate 截取文字组件

自动根据父素宽度子素超出则溢出隐藏并 hover 出全部内容的提示框表格组件的溢出隐藏功能基于次组件会自动重新计算表格宽度重新是否溢出隐藏

#### j-upload 上传组件

v-model 使用支持传递数组和字符串已 "," 分割 自带进度条等

#### j-link 跳转组件

同 router-link 使用方法,默认 http 外部打开,并且处理为空时自动添加 javascript:;

#### 以上为基础组件 大部分基础组件在管理端同样通用参数功能皆为一致

#### 以下为业务组件和业务模块

address-list 地址列表

attr-card 左侧属性卡片筛选

class-bar 商品分类工具栏

goods-select 选择商品弹框

CutView 商品详情自定义 tabs

j-class-card 商品分类卡片

j-coupon 优惠劵列表

j-price 价格对象

j-cart-input 购买输入框

j-unit-input 购买单位选择器

j-sku-select 规格选择器

j-step-price 阶梯价

j-marketing 营销内容组件

order-btns 订单后端生成按钮功能集合

order-step 下单流程进度条

sku-card 商品列表卡片模式的 sku 卡片

#### 全局混入的方法

disEmpty 判断数组和对象是否为空

resetData 重置 data 数据为预设值,不传参则重置全部传参则根据传参重置,传参格式为 xxx,xxx,xxx 以字符串分割指定字段重置

enumeration.js 映射关系文件

#### 自定义指令

directive.js 文件

v-down 下载

v-upload 上传

v-export 导出

#### boot 文件

permission.js 为鉴权路由守卫

axios.js 为 axios 的封装

filter.js 为 vue 的过滤器

需要 ssr 的全局组件请配置到 element-ui, plugins 则是需要获得 window 对象等不能 ssr 的组件或者不需要 ssr 的组件配置

#### widgets 文件目录为挂件

一定要写组件 name 不然会报错,此文件夹下的组件会自动全局注册只需要把挂件丢到此文件夹即可, 配置项写在 widgets 对象下,content 为数据,config 为数据配置项,同 j-form-auto, 在管理端此组件新增了选择链接和图片库等组件具体配置写法参考已有挂件即可,在后台根据此配置项自动生成拖拽挂件对应在管理端的 template 的文件夹下同样自动注册,PC 端写好挂件后复制到管理的 template 文件夹下即可,分为全局挂件和普通挂件,全局挂件不可新增和拖拽

### 平台管理端

使用的 vue2 全家桶 组件库为 element UI 拖拽组件为 vue-slicksort 插件

vscode 全局组件获得代码提示则配置到 vetur.config 已经有的全局组件已配置 则使用的时候不会在当前页自动导入如有 css 自定义属性名则配置 tailwindcss 插件依旧可以获得代码提示,配合 Tailwind CSS IntelliSense 官方插件使用mixin 全局混入文件在 types 内编写

#### NODE JS 版本

16版本

#### tailwindcss 运行命令

npm run css:build

#### spa 命令

npm run dev 运行
npm run build 打包

#### 目录说明

api 请求封装和路由地址
assets 资源目录
components 公用组件
directive 指令封装
icons svg图片目录
layouts 公用布局
muxins 混入函数
model 模型文件
plugins 插件
router 路由文件
store vuex封装
styles 样式表
template 可视化组件封装
utils 工具函数包
views 页面文件

#### views 目录说明

bussiness    经销商
category     类目相关
category     审核
commodity    商品
enterprise   企业
finance      财务
home         首页
index        默认路由
login        登录相关
logistics    物流
marketing    营销活动
members      客户相关
open         开放平台
organization 组织架构
sale         销售
sales        销售任务
set          设置
site         站点
system       系统
template     模板
transaction  订单交易

#### Install the dependencies

yarn

#### 组件具体属性功能可直接看组件内部注释

#### j-address 地址选择组件

通过 dataKey 和 label 决定 显示属性

#### j-dialog 对话框组件

支持拖拽, 继承 element 对话框所有属性功能,扩展默认底部按钮和对话框拖拽功能

#### j-dict-multiple 字典多选组件

继承 ele 选择器属性功能只需要传递 dictCode 字典编码自动生成

#### j-dict-select 字典单选组件

继承 ele 选择器属性功能只需要传递 dictCode 字典编码自动生成

#### j-tabs 选项卡

isAll 为 true 会自动带上名为全部的选项卡,解决 ele-tabs 选择卡 name 不能为空的问题,options 传参则保持一致 label 和 name

#### j-pages-select 带分页的下拉选择器 和远程搜索器

继承 ele 选择器属性功能传递请求接口请求方式对应的 value-key label-key 即可

#### j-mapList 自增列表组件

有列表模式和表格模式,通过传参有 input 上传 选择地址 选择图片 等 自增添加组件,传入 serialize 会自动序列化 string

#### j-search 高级搜索组件

选择字段名称进行搜索通过传入 json示例selectList: [{label: '公司名称',value: 'userCompanyName',},{label: '法人代表',value: 'personName',},{label: '公司电话',value: 'corpTelephone',},],

#### j-form-auto 自动表单生成组件

继承 ele 表单属性, 传递 config 表单配置项 生成表单配置项为 type 代表表单组件类型,比如 input,number-input,select,radio,checkbox,switch,j-dict-select 等常用表单组件表单组件传递 attrs 配置到具体的组件,required 为是否必填, 自带 手机号,邮箱,身份证,信用编码,银行卡,座机号格式验证,rules:[{type:'验证类型'}]验证类型为对应的英文,组件内部查看即可自定义验证规则则正常传入传递数组,options 为多选或 select 的子项,attrs 同样有效表单数据可以通过 v-model 绑定也可以在$refs.form.submit 验证通过时此方法.then(form)中返回出表单数据只有验证通过才会触发.then示例 config: [{ label: '所在地址', name: 'custom', required: true },{label: '地址标签',name: 'addressLabel',type: 'radio-button',options: [{ label: '家', value: 10 },{ label: '公司', value: 20 }]},{ label: '街道地址', name: 'reals', type: 'input', attrs: { type: 'textarea' }, required: true },{ label: '邮政编码', name: 'postalCode', type: 'number' },{ label: '收货人姓名', name: 'contactsName', type: 'input', required: true },{label: '收货人手机号',name: 'contactsPhone',type: 'phone',rules: [{ type: 'phone' }],required: true},{label: '',name: 'isDefault',type: 'checkbox',attrs: { 'true-label': 10, 'false-label': 20, name: '是否设置成默认地址' }}],

#### j-pages 分页组件

同表格分页功能 pages.sync 变为 v-model

#### j-truncate 截取文字组件

自动根据父素宽度子素超出则溢出隐藏并 hover 出全部内容的提示框表格组件的溢出隐藏功能基于次组件会自动重新计算表格宽度重新是否溢出隐藏

#### j-upload 上传组件

v-model 使用支持传递数组和字符串已 "," 分割 自带进度条等

#### 以上为基础组件 大部分基础组件在管理端同样通用参数功能皆为一致

#### 以下为业务组件和业务模块

j-goods-select 选择商品弹框

#### 全局混入的方法

disEmpty 判断数组和对象是否为空

assignEmpty 合并数组或者对象如果原数据为高级数据类型,传入数据为 null 或者空则不覆盖默认值

resetData 重置 data 数据为预设值,不传参则重置全部传参则根据传参重置,传参格式为 xxx,xxx,xxx 以字符串分割指定字段重置

enumeration.js 映射关系文件

#### 自定义指令

directive.js 文件

v-down 下载

v-upload 上传

v-export 导出

v-verify 权限标识

#### widgets 文件目录为挂件

一定要写组件 name 不然会报错,此文件夹下的组件会自动全局注册只需要把挂件丢到此文件夹即可, 配置项写在 widgets 对象下,content 为数据,config 为数据配置项,同 j-form-auto, 在管理端此组件新增了选择链接和图片库等组件具体配置写法参考已有挂件即可,在后台根据此配置项自动生成拖拽挂件对应在管理端的 template 的文件夹下同样自动注册,PC 端写好挂件后复制到管理的 template 文件夹下即可,分为全局挂件和普通挂件,全局挂件不可新增和拖拽

## 后端

### 简介

以SpringCloud+Dubbo 为基础搭建项目

nacos注册中心

Seata事务处理框架

存储服务 MySQL, Redis,Elasticsearch

权限认证使用 SpringSecurity & Token & Redis

消息中间件RocketMq

### 应用架构

### 技术栈

### 项目结构

jinko-mall
  | pom.xml【定义全局变量,如引用jar版本，项目运行环境{开发环境/UAT环境/正式环境等}】
  | gs-commodity【商品】
  |  |  |  gs-commodity-api【dubbo接口】
  |  |  |  gs-commodity-rpc【dubbo接口实现,应用启动】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  |  gs-commodity-srv【业务处理】
  |  |  |  gs-commodity-entity【实体类】
  |  |  |  gs-commodity-repository【数据访问】
  |  | gs-foundation【系统配置/商户/系统组织】
  |  |  |  gs-foundation-api【dubbo接口】
  |  |  |  gs-foundation-rpc【dubbo接口实现,应用启动】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  |  gs-foundation-srv【业务处理】
  |  |  |  gs-foundation-entity【实体类】
  |  |  |  gs-foundation-repository【数据访问】
  |  | gs-marketing【营销】
  |  |  |  gs-marketing-api【dubbo接口】
  |  |  |  gs-marketing-srv【dubbo接口实现/业务处理,应用启动】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  |  gs-marketing-entity【实体类】
  |  |  |  gs-marketing-repository【数据访问】
  |  | gs-report【报表】
  |  |  |  gs-report-api【dubbo接口】
  |  |  |  gs-report-srv【dubbo接口实现/业务处理,应用启动】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  |  gs-report-entity【实体类】
  |  |  |  gs-report-repository【数据访问】
  |  | gs-trade【交易】
  |  |  |  gs-trade-api【dubbo接口】
  |  |  |  gs-trade-rpc【dubbo接口实现,应用启动】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  |  gs-trade-srv【业务处理】
  |  |  |  gs-trade-entity【实体类】
  |  |  |  gs-trade-repository【数据访问】
  |  | gs-user【客户】
  |  |  |  gs-user-api【dubbo接口】
  |  |  |  gs-user-rpc【dubbo接口实现,应用启动】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  |  gs-user-srv【业务处理】
  |  |  |  gs-user-entity【实体类】
  |  |  |  gs-user-repository【数据访问】
  | gs-facade【Web应用】
  |  |  gs-mall-bbb【商城PC/H5接口,应用启动】
  |  |  |  *.*.aop【web切面】
  |  |  |  *.*.config【web配置，如接口文档，初始数据加载】
  |  |  |  *.*.controller【web接口】
  |  |  |  *.*.security【账号/密码登录入口】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  META-INF
  |  |  |  |  |  |  antisamy【XSS脚本配置模板】
  |  |  |  |  |  |  dubbo【dubbo过滤配置,用于解析token获取登录信息】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  gs-mall-gateway【网关服务-未使用】
  |  |  gs-merchant-admin【商户接口-未使用】
  |  |  |  *.*.aop【web切面】
  |  |  |  *.*.config【web配置，如接口文档，初始数据加载】
  |  |  |  *.*.controller【web接口】
  |  |  |  *.*.security【账号/密码登录入口】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  META-INF
  |  |  |  |  |  |  antisamy【XSS脚本配置模板】
  |  |  |  |  |  |  dubbo【dubbo过滤配置,用于解析token获取登录信息】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  gs-platform-admin【平台接口/开放接口,应用启动】
  |  |  |  *.*.aop【web切面】
  |  |  |  *.*.config【web配置，如接口文档，初始数据加载】
  |  |  |  *.*.controller【web接口】
  |  |  |  *.*.security【账号/密码登录入口】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  META-INF
  |  |  |  |  |  |  antisamy【XSS脚本配置模板】
  |  |  |  |  |  |  dubbo【dubbo过滤配置,用于解析token获取登录信息】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  |  |  gs-sales-admin【业务员接口-未使用】
  |  |  |  *.*.aop【web切面】
  |  |  |  *.*.config【web配置，如接口文档，初始数据加载】
  |  |  |  *.*.controller【web接口】
  |  |  |  *.*.security【账号/密码登录入口】
  |  |  |  |  resources
  |  |  |  |  |  config【yml配置文件】
  |  |  |  |  |  logback【日志配置文件】
  |  |  |  |  |  META-INF
  |  |  |  |  |  |  antisamy【XSS脚本配置模板】
  |  |  |  |  |  |  dubbo【dubbo过滤配置,用于解析token获取登录信息】
  |  |  |  |  |  dubbo.properties【dubbo配置,需要注意dubbo.application.qos.port端口不重复】
  | gs-middle【工具组件】
  |  |  gs-auth【授权验证/XSS拦截过滤】
  |  |  gs-elasticsearch【elasticsearch组件】
  |  |  gs-entity-base【实体类/枚举值】
  |  |  gs-invoice【发票组件】
  |  |  gs-log【日志组件】
  |  |  gs-logistic【物流信息组件,未使用第三方物流】
  |  |  gs-mail【邮件组件】
  |  |  gs-mongo【mongo组件-未使用】
  |  |  gs-mq【MQ组件】
  |  |  gs-oss【文件组件,集成阿里云、腾讯云、本地上传等】
  |  |  gs-payment【支付组件-未使用,未使用第三方支付】
  |  |  gs-redis【redis组件】
  |  |  gs-sms【短信组件,集成阿里云、腾讯云等】
  |  |  gs-third-auth【三方授权对接组件,如微信/QQ-未使用,未使用第三方授权登录】
  |  |  gs-util【工具组件 】
  |  |  gs-quartz【定时任务组件】
  |  |  gs-site-config【站点配置组件】
  |  |  gs-sentinel-nacos【Sentinel组件-未使用】
  |  |  gs-notices【消息通知组件】
  |  |  gs-third-erp【ERP对接组件】
  |  |  gs-online-signing【在线合同组件】
  |  |  gs-doc-convert【excel/pdf转换组件】
  |  |  gs-open【对外接口组件】

### 二开示例

以系统组织架构保存/编辑为例说明

#### 1. 程序调用

controller接口

com.gs.khxx.facade.platform.controller.rbac.SysOrganController

@ApiOperation("新增")
@PostMapping("/save")
public ResponseData<Void> add(@Valid @RequestBody SysOrganDTO.ETO eto) {
    eto.setId(null);
    sysOrganRpc.saveSysOrgan(eto);
    return ResponseData.data(I18nGlobalConst.GLOBAL_MSG_HANDLE_SUCCESS);
}

@ApiOperation("编辑")
@PostMapping(value = "/save/{id}")
public ResponseData<Void> edit(@Valid @PathVariable String id, @Valid @RequestBody SysOrganDTO.ETO eto) {
    eto.setId(id);
    sysOrganRpc.saveSysOrgan(eto);
    return ResponseData.data(I18nGlobalConst.GLOBAL_MSG_HANDLE_SUCCESS);
}

RPC接口

com.gs.khxx.rpc.api.foundation.rbac.ISysOrganRpc

/**
 * 新增/编辑
 * @param eto
 * @return
 */
String saveSysOrgan(SysOrganDTO.ETO eto);

RPC接口实现

com.gs.khxx.biz.support.foundation.rpc.rbac.SysOrganRpc

@Autowired
ISysOrganService sysOrganService;
@Override
public String saveSysOrgan(SysOrganDTO.ETO eto) {
    return sysOrganService.saveSysOrgan(eto);
}

业务逻辑处理接口

com.gs.khxx.biz.support.foundation.service.rbac.ISysOrganService

/**
 * 新增/编辑
 * @param eto
 * @return
 */
String saveSysOrgan(SysOrganDTO.ETO eto);

业务逻辑处理接口实现

com.gs.khxx.biz.support.foundation.service.rbac.SysOrganServiceImpl

@Autowired
ISysOrganRepository sysOrganRepository;

@Override
public String saveSysOrgan(SysOrganDTO.ETO eto) {
    SysOrgan sysOrgan = FoundationStructMapper.INSTANCE.sysOrgan2PO(eto);
    if (!SysConst.DefaultParentId.equals(eto.getParentId())) {
        SysOrgan sysOrganParent = sysOrganRepository.getById(eto.getParentId());
        if (ObjectUtil.isNull(sysOrganParent)) {
            throw new BusinessException(I18nUserAuthConst.AUTH_MSG_ORGAN_NOT_EXISTS);
        }
    }
    if (StrUtil.isEmpty(eto.getId())) {
        if (SysOrganTypeEnum.DEPT.getCode().equals(sysOrgan.getOrganType())) {
            SysOrgan defautObj = getDefaultOrganObj();
            if (ObjectUtil.isNull(defautObj)) {
                sysOrgan.setRegistDefault(EnUnStateEnum.ENABLE.getCode());
            }
        }
        sysOrgan.setOrganCode(initOrganCode(sysOrgan.getParentId()));
        sysOrgan.setId(sysOrgan.getOrganCode());
        sysOrganRepository.save(sysOrgan);
    } else {
        SysOrgan sysOrganDb = sysOrganRepository.getById(eto.getId());
        sysOrgan.setOrganCode(sysOrganDb.getOrganCode());
        sysOrganRepository.updateById(sysOrgan);
    }
    Boolean needUpdate = EnUnStateEnum.ENABLE.getCode().equals(sysOrgan.getRegistDefault());
    if (needUpdate) {
        updateResetRegistDefault(sysOrgan.getId());
    }
    return sysOrgan.getId();
}

/**
 * 判断是否是默认的第一个部门信息
 *
 * @return
 */
private SysOrgan getDefaultOrganObj() {
    QueryWrapper<SysOrgan> queryWrapper = MybatisPlusUtil.query();
    queryWrapper.eq("organ_type", SysOrganTypeEnum.DEPT.getCode());
    queryWrapper.eq("regist_default", EnUnStateEnum.UNABLE.getCode());
    queryWrapper.last("limit 0,1");
    return sysOrganRepository.getOne(queryWrapper);
}

/**
 * 如果当前记录未默认,则更新其他值未非默认
 *
 * @param organId
 */
private void updateResetRegistDefault(String organId) {
    UpdateWrapper<SysOrgan> queryWrapper = MybatisPlusUtil.update();
    queryWrapper.ne("id", organId);
    queryWrapper.eq("regist_default", EnUnStateEnum.ENABLE.getCode());
    queryWrapper.set("regist_default", EnUnStateEnum.UNABLE.getCode());
    sysOrganRepository.update(queryWrapper);
}

/**
 * 生成组织编码
 * 本身编码3位流水号组成
 *
 * @param parentId
 * @return
 */
private String initOrganCode(String parentId) {
    SysOrgan queryObj = sysOrganRepository.getMapper().getMaxOrangCodeRecoed(parentId);
    if (ObjectUtil.isNull(queryObj)) {
        if (!SysConst.DefaultParentId.equals(parentId)) {
            throw new BusinessException(I18nUserAuthConst.AUTH_MSG_ORGAN_NOT_EXISTS);
        }
        return SysConst.DefaultOrganId;
    }
    //同一个父级目录下有记录
    String pre = SysConst.DefaultParentId.equals(parentId) ? SysSplitConst.BlankStr : parentId;
    if (queryObj.getParentId().equals(parentId)) {
        String currentNo = queryObj.getOrganCode().replaceFirst(parentId, SysSplitConst.BlankStr);
        return com.gs.khxx.base.utils.StrUtil.getNextFlowingCode(pre, Integer.valueOf(currentNo), SysNumberConst.P3);
    }
    return com.gs.khxx.base.utils.StrUtil.getNextFlowingCode(pre, SysNumberConst.P0, SysNumberConst.P3);
}

#### 2. 新增应用

新增加微服务模块服务命名规则：前缀以mallApplicationExtend开头，服务名称自定义，示例mallApplicationExtendStock

nacos配置文件license.applicationName值位步骤1定义的服务名称

web应用项目结构可参考jinko-mall->gs-facade->gs-platform-admin搭建，pom文件如无其他新增jar可以与其他web应用保持一致

biz应用项目接口参考分以下两种功能

RPC接口实现与Server服务合并参考jinko-mall->gs-biz-support->gs-marketing

RPC接口实现与Server服务分开参考jinko-mall->gs-biz-support-> gs-commodity

说明：

两者在应用运行上并无差别，RPC子项目仅用于应用启动/实现API接口

POM文件配置参对以上两个项目对应pom文件

新增应用未使用ES功能，可以屏蔽对应的ES引用

新增应用使用ES，可以在jinko-mall-> gs-middle->gs-elasticsearch中添加对应的ES功能

[表格]
技术栈 | 版本 | 备注
Spring Boot | 3.2.6 | 应用开发框架
Spring | 6.1.8 | 应用开发框架
Spring MVC | 6.1.8 | 应用开发框架
Spring Security | 6.1.8 | 应用开发框架
SpringCloud-Alibaba | 2023.0.1.0 | 应用开发框架
Dubbo | 3.2.12 | 应用开发框架
nacos | 2.3.2 | 注册中心
RocketMq | 5.0.0 | MQ开发框架
Seata | 2.0.0 | 分布式事务开发框架
Elasticsearch | 8.0 | 搜索开发框架
spring-Elasticsearch | 3.2.6 | 搜索开发框架
MySQL | 8.0 | 数据库服务器
HikariCP | 5.0.1 | JDBC 连接池
MyBatis Plus | 3.5.3.2 | MyBatis 增强工具包
Dynamic Datasource | 3.6.1 | 动态数据源
Redis | 5.0 | key-value 数据库
lock4j | 2.2.7 | 分布式锁 数据库
Redisson | 3.32.0 | Redis 客户端
Hibernate Validator | 6.2.5 | 参数校验组件
hutool | 5.5.8 | 综合工具开发框架
Quartz | 3.2.6 | 任务调度组件
Springdoc | 2.3.0 | 接口 文档
Jackson | 2.13.3 | JSON 工具库
MapStruct | 1.5.5.Final | Java Bean 转换
Lombok | 1.18.30 | 消除冗长的 Java 代码
logback | 1.5.6 | 日志框架