在当今教育行业竞争激烈的环境中,许多培训机构都有多个校区。本文将深入研究多分校网校系统源码,通过代码示例分析实现多校区差异化运营技术要点,为开发者提供实用的指导,助力构建灵活、多样的多校区运营管理。
技术栈综述
多分校网校平台源码采用了现代化的技术栈,主要包括前端使用vue框架,后端采用java语言,springcloud框架,而数据库则选择mysql。以下是源码中的核心代码示例:
前端代码(vue框架)
<template>
<a-card :bordered="false">
<div>
<h3>经销渠道</h3>
</div>
<a-divider orientation="left">
</a-divider>
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :md="6" :sm="12">
<a-form-item label="经销商名称">
<a-input placeholder="请输入" v-model="queryParam.dealerName"></a-input>
</a-form-item>
</a-col>
<a-col :md="6" :sm="12">
<a-form-item label="益华编码">
<a-input placeholder="请输入" v-model="queryParam.code"></a-input>
</a-form-item>
</a-col>
<a-col :md="6" :sm="12">
<a-form-item label="财务编码">
<a-input placeholder="请输入" v-model="queryParam.financialCode"></a-input>
</a-form-item>
</a-col>
<a-col :md="6" :sm="12">
<a-form-item label="经销商手机号">
<a-input placeholder="请输入" v-model="queryParam.phone"></a-input>
</a-form-item>
</a-col>
<a-col :md="6" :sm="12">
<a-form-item label="商务经理">
<j-multi-select-tag
v-model="queryParam.businessManagerId"
:options="businessManager"
placeholder="请选择">
</j-multi-select-tag>
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<a-form-item label="学员导流">
<a-select v-model="queryParam.diversionStatus" placeholder="请选择">
<a-select-option value="">请选择</a-select-option>
<a-select-option value="0">是</a-select-option>
<a-select-option value="1">否</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<a-form-item label="用户状态">
<a-select v-model="queryParam.userStatus" placeholder="请选择">
<a-select-option value="1">启用</a-select-option>
<a-select-option value="0">禁用</a-select-option>
<a-select-option value="2">冻结</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
<a-button @click="add" type="primary" icon="plus" style="margin-left: 8px">新增</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<!-- 高级查询区域 -->
<a-dropdown v-if="selectedRowKeys.length > 0">
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<a-table
ref="table"
size="middle"
:scroll="{x:true}"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
class="j-table-force-nowrap"
@change="handleTableChange">
<span slot="action" slot-scope="text, record">
<a @click="childUserClick(record)">二级分销</a>
<a-divider type="vertical"/>
<a @click="edit(record)">管理</a>
<a-divider type="vertical"/>
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down"/></a>
<a-menu slot="overlay">
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
<a-menu-item v-if='record.userStatus !=1'>
<a-popconfirm title="确定启用吗?" @confirm="() => handleUse(record.id,1)">
<a>启用</a>
</a-popconfirm>
</a-menu-item>
<a-menu-item v-if='record.userStatus !=2'>
<a-popconfirm title="确定冻结吗?" @confirm="() => handleUse(record.id,2)">
<a>冻结</a>
</a-popconfirm>
</a-menu-item>
<a-menu-item v-if='record.userStatus !=0'>
<a-popconfirm title="确定禁用吗?禁用后其名下学员将全部转入公海" @confirm="() => handleUse(record.id,0)">
<a>禁用</a>
</a-popconfirm>
</a-menu-item>
<a-menu-item>
<a-popconfirm title="确定重置密码吗?" @confirm="() => resetPassword(record.id)">
<a>重置密码</a>
</a-popconfirm>
</a-menu-item>
<!--<a-menu-item v-if="record.userStatus==0">-->
<!--<a-popconfirm title="确定禁止吗?" @confirm="() => handleUse(record.id,1)">-->
<!--<a>禁止用户</a>-->
<!--</a-popconfirm>-->
<!--</a-menu-item>-->
<!--<a-menu-item v-if="record.userStatus==1">-->
<!--<a-popconfirm title="确定启动吗?" @confirm="() => handleUse(record.id,0)">-->
<!--<a>启动用户</a>-->
<!--</a-popconfirm>-->
<!--</a-menu-item>-->
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<!--<wd-resources-distribution-modal ref="modalForm" @ok="modalFormOk"></wd-resources-distribution-modal>-->
<a-modal
title="二级经销商"
:width="1600"
:visible="childUserVis"
:confirm-loading="confirmLoading"
:maskClosable="false"
:destroyOnClose="true"
cancelText="关 闭"
@cancel="childUserCancel"
>
<UserAccountingList ref="userAccountingList" :distributionEntity="distributionEntity" ></UserAccountingList>
<template slot="footer">
<a-button @click="childUserCancel">关 闭</a-button>
</template>
</a-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import {mixinDevice} from '@/utils/mixin'
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import AddDistributionTable from './AddDistributionTable'
import WdResourcesDistributionModal from './modules/WdResourcesDistributionForm'
import {putAction,getAction} from "@api/manage";
import UserAccountingList from "../../childDistribution/accounting/UserAccountingList";
import { ajaxGetDictItems } from '@api/api'
export default {
name: 'DistributionList',
mixins: [JeecgListMixin, mixinDevice],
components: {
UserAccountingList,
AddDistributionTable,
WdResourcesDistributionModal
},
data() {
return {
childUserVis: false,
confirmLoading: false,
queryParam: {},
description: '经销商管理页面',
isorter:{
column: 'create_time,id',
order: 'desc',
},
// 表头
columns: [
{
title: '益华编码',
align: "center",
dataIndex: 'code'
},
{
title: '财务编码',
align: "center",
dataIndex: 'financialCode'
},
{
title: '经销商名称',
align: "center",
dataIndex: 'dealerName'
},
{
title: '负责人',
align: "center",
dataIndex: 'chargeName'
},
{
title: '联系电话',
align: "center",
dataIndex: 'phone'
},
{
title: '商务经理',
align: "center",
dataIndex: 'businessManagerId_dictText'
},
{
title: '学员数量',
align: "center",
dataIndex: 'studentCount'
},
{
title: '账户余额',
align: "center",
dataIndex: 'balance',
sorter: true
},
{
title: '对账余额',
align: "center",
dataIndex: 'reconciliationBalance',
},
{
title: '差',
align: "center",
dataIndex: 'differenceBalance',
},
{
title: '用户状态',
align: "center",
dataIndex: 'userStatus',
key: "userStatus",
customRender: function (text) {
if (text == 0) {
return "禁用";
} else if (text == 1){
return "启用";
} else if (text == 2){
return "冻结";
}
}
},
{
title: '操作',
dataIndex: 'action',
align: "center",
fixed: "right",
width: 147,
scopedSlots: {customRender: 'action'}
}
],
url: {
list: "/distribution/list",
delete: "/distribution/delete"
},
dictOptions: {},
superFieldList: [],
distributionEntity: {},
businessManager: [],
}
},
created() {
this.getSuperFieldList();
this.initDictConfig();
},
computed: {
},
methods: {
childUserCancel() {
this.childUserVis = false;
},
childUserClick(record) {
this.distributionEntity = record;
this.childUserVis = true;
},
initDictConfig() {
getAction("/distribution/getBusinessManagerList").then(res => {
if (res.success) {
this.businessManager = res.result.map((item,index,arr)=>{
let c = {label:item.name, value: item.id+""}
return c;
})
}
})
},
add() {
this.$router.push('/admin/resources/distribution/AddDistributionTable')
},
edit(record){
this.$router.push({
path:'/admin/resources/distribution/AddDistributionTable',
query:{
id:record.id
}
})
},
handleRelease: function (id, diversionStatus) {
let that = this;
let obj = {
id: id,
diversionStatus: diversionStatus
};
putAction("/distribution/prohibit", obj).then(res => {
if (res.success) {
that.$message.success(res.message);
that.loadData();
} else {
that.$message.warning(res.message);
}
})
},
handleUse: function (id, userStatus) {
let that = this;
let obj = {
id: id,
userStatus: userStatus
};
putAction("/distribution/use", obj).then(res => {
if (res.success) {
that.$message.success(res.message);
that.loadData();
} else {
that.$message.warning(res.message);
}
})
},
resetPassword: function (id) {
let that = this;
let obj = {
id: id
};
putAction("/distribution/resetPassword", obj).then(res => {
if (res.success) {
that.$message.success(res.message);
that.loadData();
} else {
that.$message.warning(res.message);
}
})
},
getSuperFieldList() {
let fieldList = [];
fieldList.push({type: 'string', value: 'dealerName', text: '经销商名称'});
fieldList.push({type: 'string', value: 'chargeName', text: '负责人'});
fieldList.push({type: 'string', value: 'phone', text: '手机号'});
fieldList.push({type: 'string', value: 'area', text: '省市区'});
fieldList.push({type: 'string', value: 'adress', text: '详细地址'});
fieldList.push({type: 'date', value: 'joinTime', text: '加盟日期'});
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
后端代码(springcloud框架)
@AutoLog(value = "分页列表查询")
@ApiOperation(value = "分页列表查询", notes = "分页列表查询")
@GetMapping(value = "/list")
public Result<?> queryPageList(@RequestParam(name = "dealerName", required = false) String dealerName,
@RequestParam(name = "businessManagerId", required = false) String businessManagerId,
@RequestParam(name = "diversionStatus", required = false) String diversionStatus,
@RequestParam(name = "code", required = false) String code,
@RequestParam(name = "financialCode", required = false) String financialCode,
@RequestParam(name = "phone", required = false) String phone,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "column", required = false) String column,
@RequestParam(name = "order", required = false) String order,
@RequestParam(name = "userStatus", required = false) Integer userStatus,
HttpServletRequest req) {
QueryWrapper<WdResourcesDistribution> queryWrapper = new QueryWrapper<>();
if (StringUtils.isNotBlank(dealerName)) {
queryWrapper.like("dealer_name", dealerName);
}
if (StringUtils.isNotBlank(businessManagerId)) {
queryWrapper.in("business_manager_id", businessManagerId.split(","));
}
if (StringUtils.isNotBlank(diversionStatus)) {
queryWrapper.eq("diversion_status", diversionStatus);
}
if (StringUtils.isNotBlank(phone)) {
queryWrapper.eq("phone", phone);
}
if (StringUtils.isNotBlank(code)) {
queryWrapper.like("code", code);
}
if (StringUtils.isNotBlank(financialCode)) {
queryWrapper.like("financial_code", financialCode);
}
if (userStatus !=null){
queryWrapper.like("user_status", userStatus);
}
queryWrapper.orderBy(true,order.equals("asc"),column.split(","));
Page<WdResourcesDistribution> page = new Page<>(pageNo, pageSize);
IPage<WdResourcesDistribution> pageList = wdResourcesDistributionService.page(page, queryWrapper);
List<WdResourcesDistribution> list = pageList.getRecords();
for (WdResourcesDistribution distribution : list) {
//设置学生数量
QueryWrapper<WdStudentManagement> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("distribution_id", distribution.getId());
queryWrapper1.eq("is_disable", "1");
int count = studentManagementService.count(queryWrapper1);
distribution.setStudentCount(count);
// 充值记录
BigDecimal rechargeAmount = wdFinanceTopupService.getDistributionRechargeAmount(distribution.getId(), null);
// 课程、题库订单支出
BigDecimal payAmount = wdOrderService.selectDistributionPayMoney(distribution.getId(), null);
// 图书订单支出
BigDecimal bookOrderPayAmount = wdBookOrderService.getDistributionBookOrderPayAmount(distribution.getId(), null);
//计算运费
BigDecimal sendBookOrderPayAmount = wdBookSendOrderService.getDistributionSendBookOrderPayAmount(distribution.getId(), null);
// 计算余额
BigDecimal balance = rechargeAmount.subtract(payAmount).subtract(bookOrderPayAmount).subtract(sendBookOrderPayAmount);
distribution.setReconciliationBalance(balance);
distribution.setDifferenceBalance(balance.subtract(distribution.getBalance()));
}
return Result.OK(pageList);
}
技术要点解析
- 前后端数据交互: 利用vue组件通过状态管理与用户交互,实现经销商信息的前端收集。
- 数据库操作: 在后端使用mysql库,将经销商信息存储到mysql数据库中,实现数据的持久化。
- 路由处理: 通过gateway框架实现路由RESTful API,后端处理前端请求,提供经销商信息的获取和存储功能。
- 响应式设计: 利用vue框架的组件化和状态管理,实现前端界面的动态响应,提升用户体验。
以上代码示例仅为源码的一部分,实际开发中可能需要更多的功能和优化。通过深入理解这些技术要点,开发者可以在源码的基础上进行二次开发,定制适应特定业务需求的预约系统,为用户提供更智能、更个性化的服务体验。