广告-广告统计
广告统计模块功能解析文档
1. 系统架构
1.1 技术栈
1.2 架构设计
广告统计模块采用前后端分离的架构设计,具体架构层次如下:
前端层:
后端层:
数据层:
1.3 核心流程图
sequenceDiagram
participant User as 用户
participant Frontend as 前端组件
participant API as 前端API调用
participant Backend as 后端控制器
participant Service as 后端服务
participant Mapper as 数据访问
participant DB as 数据库
participant AmazonAPI as 亚马逊广告API
User->>Frontend: 访问广告统计模块
Frontend->>API: 请求运行中活动数据
API->>Backend: GET /api/v1/advSummary
Backend->>Service: 调用getenablesumtype()
Service->>Mapper: 查询广告活动数据
Mapper->>DB: SELECT * FROM ad_campaigns WHERE status='enabled'
DB-->>Mapper: 返回活动数据
Mapper-->>Service: 处理数据
Service-->>Backend: 返回汇总数据
Backend-->>API: 200 OK { campaigns: 10, adGroups: 20, ... }
API-->>Frontend: 更新运行中活动卡片
Frontend->>API: 请求异常预警数据
API->>Backend: GET /api/v1/advSummary/warning
Backend->>Service: 调用getProductWarningIndicator()
Service->>Mapper: 查询异常数据
Mapper->>DB: SELECT * FROM ad_warning WHERE type='productads'
DB-->>Mapper: 返回异常数据
Mapper-->>Service: 处理数据
Service-->>Backend: 返回预警数据
Backend-->>API: 200 OK { impco: 5, clickco: 3, ... }
API-->>Frontend: 更新异常预警卡片
Frontend->>API: 请求广告数据分析
API->>Backend: POST /api/v1/advReport/getsumproduct
Backend->>Service: 调用getSumProduct()
Service->>Mapper: 查询广告数据
Mapper->>DB: SELECT * FROM ad_summary WHERE date BETWEEN ? AND ?
DB-->>Mapper: 返回广告数据
Mapper-->>Service: 处理数据
Service-->>Backend: 返回分析数据
Backend-->>API: 200 OK { summary: {...}, chartdata: {...} }
API-->>Frontend: 更新数据分析面板和图表
2. 前端实现
2.1 组件结构
wimoor-ui/src/views/amazon/advertisement/overview/index.vue
广告统计模块主界面
loadWaringData(), loadWaringDataDetail()
广告统计组件
wimoor-ui/src/views/amazon/advertisement/overview/components/adStatistics.vue
广告数据分析和报表
loadSummaryChartData(), loadMonthSummaryData(), refreshChart()
漏斗分析组件
wimoor-ui/src/views/amazon/advertisement/overview/components/adFunnel.vue
广告转化漏斗分析
-
ROAS排名组件
wimoor-ui/src/views/amazon/advertisement/overview/components/roasRank.vue
广告投入产出比排名
-
指标详情组件
wimoor-ui/src/views/amazon/advertisement/overview/components/indicator_detail.vue
异常指标详情
-
指标设置组件
wimoor-ui/src/views/amazon/advertisement/overview/components/indicator.vue
预警指标设置
-
2.2 核心功能实现
2.2.1 运行中活动统计
实现原理:
summaryApi.getenablesumtype()获取当前运行中的广告活动、广告组、商品广告和关键词数量
数据返回后更新到typedata对象中,通过模板渲染到对应的数据卡片
关键代码:
// 加载运行中活动数据
onMounted(()=>{
summaryApi.getenablesumtype().then(res=>{
state.typedata=res.data;
});
loadWaringData();
})
2.2.2 异常数据预警
实现原理:
summaryApi.getProductWarningIndicator()或summaryApi.getKeywordsWarningIndicator()获取异常预警数据
点击异常指标可查看详细信息,调用loadWaringDataDetail()方法
关键代码:
// 加载预警数据
function loadWaringData(){
var param={ftype:state.waringType};
if(state.wardatatype=="productads"){
summaryApi.getProductWarningIndicator(param).then(res=>{
state.waringData=res.data;
});
}else{
summaryApi.getKeywordsWarningIndicator(param).then(res=>{
state.waringData=res.data;
});
}
}
// 查看预警详情
function loadWaringDataDetail(ftype){
indicatorDetailRef.value.show(ftype,state.waringType,state.wardatatype);
}
2.2.3 广告数据分析
实现原理:
summaryApi.getsumproduct()获取图表数据,调用summaryApi.getmonthsum()获取月度报表数据
关键代码:
// 加载图表数据
function loadSummaryChartData(){
summaryApi.getsumproduct(state.queryParams).then(res=>{
state.summaryData=res.data.summary;
state.chartData=res.data.chartdata;
var data=res.data.summary;
data.ordersummary=res.data.ordersummary;
state.summaryData.acosas = isNanPvalue(parseFloat(data.cost), data.ordersummary);
state.summaryData.cpc = isNanvalue(parseFloat(data.cost),parseFloat( data.clicks));
state.summaryData.roi = isNanvalue(parseFloat(data.attributedSales), parseFloat(data.cost));
if(state.queryParams.currency=="USD"){
state.adList.forEach(item=>{
if(item.prefix=='¥'){
item.prefix='$';
}
})
}else{
state.adList.forEach(item=>{
if(item.prefix=='$'){
item.prefix='¥';
}
})
}
refreshChart();
})
}
// 加载月度报表数据
function loadMonthSummaryData() {
summaryApi.getmonthsum(state.queryParams).then(res=>{
state.monthData=res.data;
if(state.queryParams.currency=="USD"){
state.rows.forEach(item=>{
if(item.prefix=='¥'){
item.prefix='$';
}
})
}else{
state.rows.forEach(item=>{
if(item.prefix=='$'){
item.prefix='¥';
}
})
}
});
}
// 刷新图表
function refreshChart() {
var chartdata=state.chartData;
if (chartdata != null) {
var labels = null;
var color = [];
var legends = [];
var series = [];
state.adList.forEach(row=>{
var type = row.field;
if (row.active&&chartdata[type]) {
labels = chartdata[type]["listLabel"];
legends.push(row.name);
color.push(row.color);
var datas = {};
datas.name = row.name;
if (type == "cr" || type == "ctr" || type == "acos") {
datas.type = "line";
datas.yAxisIndex = 1;
datas.symbol = 'emptycircle';
datas.smooth = true;
datas.symbolSize = 3;
datas.itemStyle = {
normal : {
lineStyle : {
width : 2
}
}
}
} else {
datas.type = "bar";
datas.barGap = "0%";
datas.boundaryGap = "0%";
datas.barMaxWidth = 32, datas.itemStyle = {
normal : {
barBorderRadius : [ 4, 4, 0, 0 ]
}
}
}
datas.data = chartdata[type].listData;
series.push(datas);
}
});
if (labels != null) {
lineChart(legends, labels, series, color);
} else {
document.getElementById("mychart").innerHTML="<div style='padding-top:10%' clas='font-extraSmall'>暂无数据</div>";
}
} else {
document.getElementById("mychart").innerHTML="<div style='padding-top:10%' clas='font-extraSmall'>暂无数据</div>";
}
}
2.2.4 漏斗分析
实现原理:
2.2.5 ROAS排名
实现原理:
2.3 API调用
3. 后端实现
3.1 控制器
wimoor-amazon-adv/amazon-adv-boot/src/main/java/com/wimoor/amazon/adv/controller/AdvertReportController.java
广告报表控制
getSumProductAction(), getMonthSumAction()
AdvertManagerController
wimoor-amazon-adv/amazon-adv-boot/src/main/java/com/wimoor/amazon/adv/controller/AdvertManagerController.java
广告管理控制
-
3.2 服务层
wimoor-amazon-adv/amazon-adv-boot/src/main/java/com/wimoor/amazon/adv/service/impl/AmzAdvSumServiceImpl.java
广告数据汇总服务
-
AmzAdvSumProductAdsService
wimoor-amazon-adv/amazon-adv-boot/src/main/java/com/wimoor/amazon/adv/report/service/IAmzAdvSumProductAdsService.java
商品广告数据汇总服务
getSumProduct(), getMonthSumProduct(), getDaysSumProduct()
AmazonReportAdvSummaryService
wimoor-amazon-adv/amazon-adv-boot/src/main/java/com/wimoor/amazon/adv/common/service/IAmazonReportAdvSummaryService.java
广告报表汇总服务
findAdvert()
3.3 数据模型
3.4 数据访问
selectSumProduct(), selectMonthSumProduct(), selectDaysSumProduct()
AmzAdvWarningMapper
数据访问映射
广告异常预警数据CRUD
selectWarningIndicator()
AmazonReportAdvSummaryMapper
数据访问映射
广告报表汇总数据CRUD
selectAdvert()
3.5 核心API实现
3.5.1 获取广告数据分析数据
实现原理:
amzAdvSumProductAdsService.getSumProduct()获取广告数据汇总
调用amzAdvSumProductAdsService.orderSummaryAll()获取总销售额
调用amzAdvSumProductAdsService.getDaysSumProduct()获取按日汇总的数据(用于图表展示)
将数据封装返回给前端
关键代码:
@PostMapping("/getsumproduct")
public Result<Map<String, Object>> getSumProductAction(@RequestBody QueryForSumProductDTO dto){
String begin =dto.getBegin();
String end = dto.getEnd();
String type = dto.getType();
String groupid = dto.getGroupid();
String profileid = dto.getProfileid();
String currency = dto.getCurrency();
UserInfo user = UserInfoContext.get();
Map<String,Object> param=new HashMap<String,Object>();
param.put("shopid", user.getCompanyid());
param.put("type", type);
param.put("currency", currency);
Map<String, Marketplace> allmarket = marketplaceService.findMapByMarketplaceId();
if(StringUtil.isNotEmpty(profileid) && !"all".equals(profileid)) {
if(StringUtil.isNotEmpty(groupid) && !"all".equals(groupid)) {
AmzAdvProfile profile = amzAdvAuthService.getAmzAdvProfileByKey(new BigInteger(profileid));
if(allmarket.get(profile.getMarketplaceid())!=null){
param.put("pmarketplaceId", allmarket.get(profile.getMarketplaceid()).getPointName());
}
param.put("sellerid", profile.getSellerid());
param.put("profileid", profileid);
param.put("groupid", groupid);
}else {
param.put("marketplaceId", profileid);
param.put("pmarketplaceId", allmarket.get(profileid).getPointName());
}
}else {
if(StringUtil.isNotEmpty(groupid) && !"all".equals(groupid)) {
List<Map<String, Object>> list = amzAdvAuthService.getSelleridBygroup(groupid);
List<String> sellerList = new ArrayList<String>();
for(Map<String,Object> map : list) {
String seller = (String) map.get("sellerId");
sellerList.add(seller);
}
param.put("sellerList", sellerList);
param.put("groupid", groupid);
}
}
if(StringUtil.isNotEmpty(begin)) {
param.put("begin", begin.replaceAll("/", "-").trim());
param.put("beginDate", begin.replaceAll("/", "-").trim());
}
if(StringUtil.isNotEmpty(end)) {
param.put("end",end.replaceAll("/", "-").trim());
param.put("endDate", end.replaceAll("/", "-").trim());
}
Map<String, Object> result =new HashMap<String,Object>();
Map<String, Object> map = amzAdvSumProductAdsService.getSumProduct(param);
BigDecimal mapordersum = amzAdvSumProductAdsService.orderSummaryAll(param);
Map<String, Object> chartdata = amzAdvSumProductAdsService.getDaysSumProduct(param);
result.put("summary", map);
result.put("ordersummary", mapordersum);
result.put("chartdata", chartdata);
return Result.success(result) ;
}
3.5.2 获取月度广告报表数据
实现原理:
amzAdvSumProductAdsService.getMonthSumProduct()获取月度广告报表数据
将数据封装返回给前端
关键代码:
@PostMapping("/getmonthsum")
public Result<Map<String, Object>> getMonthSumAction(@RequestBody QueryForSumProductDTO dto){
String begin =dto.getBegin();
String end = dto.getEnd();
String groupid = dto.getGroupid();
String profileid = dto.getProfileid();
String currency = dto.getCurrency();
UserInfo user = UserInfoContext.get();
Map<String,Object> param=new HashMap<String,Object>();
param.put("shopid", user.getCompanyid());
param.put("groupid", groupid);
param.put("profileid", profileid);
param.put("currency", currency);
if(StringUtil.isNotEmpty(groupid) && !"all".equals(groupid)) {
if(StringUtil.isNotEmpty(profileid) && !"all".equals(profileid)) {
AmzAdvProfile profile = amzAdvAuthService.getAmzAdvProfileByKey(new BigInteger(profileid));
Map<String, Marketplace> allmarket = marketplaceService.findMapByMarketplaceId();
param.put("pmarketplaceId",allmarket.get(profile.getMarketplaceid()).getPointName());
param.put("mmarketplaceId",profile.getMarketplaceid());
param.put("sellerid", profile.getSellerid());
}else {
List<String> sellerList = new ArrayList<String>();
List<Map<String, Object>> list = amzAdvAuthService.getSelleridBygroup(groupid);
for(Map<String,Object> map : list) {
String seller = (String) map.get("sellerId");
sellerList.add(seller);
}
param.put("sellerList", sellerList);
param.put("profileid", null);
}
}else {
param.put("groupid", null);
param.put("profileid", null);
if(StringUtil.isNotEmpty(profileid) && !"all".equals(profileid)) {
Map<String, Marketplace> allmarket = marketplaceService.findMapByMarketplaceId();
param.put("pmarketplaceId", allmarket.get(profileid).getPointName());
param.put("marketplaceId", profileid);
param.put("mmarketplaceId",profileid);
}
}
if(StringUtil.isNotEmpty(begin)) {
param.put("begin", begin.replaceAll("/", "-").trim()+"-01");
param.put("beginDate", begin.replaceAll("/", "-").trim()+"-01");
}
if(StringUtil.isNotEmpty(end)) {
String[] endarray=end.split("-");
if(endarray==null||endarray.length<2) {
endarray=end.split("/");
}
if(endarray.length>=2) {
String endate = GeneralUtil.getLastDayOfMonth(Integer.parseInt(endarray[0].trim()), Integer.parseInt(endarray[1].trim()));
param.put("end",endate);
param.put("endDate",endate);
}
}
Map<String, Object> result = amzAdvSumProductAdsService.getMonthSumProduct(param);
return Result.success(result) ;
}
4. 核心功能分析
4.1 数据统计功能
功能说明:
技术实现:
业务价值:
4.2 异常预警功能
功能说明:
技术实现:
业务价值:
4.3 数据导出功能
功能说明:
技术实现:
业务价值:
4.4 漏斗分析功能
功能说明:
技术实现:
业务价值:
4.5 ROAS排名功能
功能说明:
技术实现:
业务价值:
5. 技术亮点
5.1 数据可视化
技术实现:
优势:
5.2 智能预警
技术实现:
优势:
5.3 高效数据处理
技术实现:
优势:
5.4 灵活数据筛选
技术实现:
优势:
5.5 全面的指标体系
技术实现:
优势:
6. 数据安全
6.1 权限控制
实现方案:
安全措施:
6.2 数据保护
实现方案:
安全措施:
6.3 合规性
实现方案:
合规措施:
7. 扩展性分析
7.1 功能扩展
潜在扩展点:
扩展方案:
7.2 技术扩展
潜在扩展点:
扩展方案:
7.3 集成扩展
潜在扩展点:
扩展方案:
8. 代码优化建议
8.1 前端优化
优化建议:
具体实现:
// 优化前:频繁触发的事件处理函数
function handleQuery() {
if(state.activeName=="chart"){
loadSummaryChartData();
}else{
loadMonthSummaryData() ;
}
}
// 优化后:使用防抖函数
import { debounce } from 'lodash-es';
const handleQuery = debounce(() => {
if(state.activeName=="chart"){
loadSummaryChartData();
}else{
loadMonthSummaryData() ;
}
}, 300);
8.2 后端优化
优化建议:
具体实现:
// 优化前:重复的参数处理代码
if(StringUtil.isNotEmpty(begin)) {
param.put("begin", begin.replaceAll("/", "-").trim());
param.put("beginDate", begin.replaceAll("/", "-").trim());
}
if(StringUtil.isNotEmpty(end)) {
param.put("end",end.replaceAll("/", "-").trim());
param.put("endDate", end.replaceAll("/", "-").trim());
}
// 优化后:提取公共方法
private void processDateParams(Map<String, Object> param, String begin, String end) {
if(StringUtil.isNotEmpty(begin)) {
String formattedBegin = begin.replaceAll("/", "-").trim();
param.put("begin", formattedBegin);
param.put("beginDate", formattedBegin);
}
if(StringUtil.isNotEmpty(end)) {
String formattedEnd = end.replaceAll("/", "-").trim();
param.put("end", formattedEnd);
param.put("endDate", formattedEnd);
}
}
8.3 数据处理优化
优化建议:
具体实现:
// 优化前:实时计算统计数据
@PostMapping("/getsumproduct")
public Result<Map<String, Object>> getSumProductAction(@RequestBody QueryForSumProductDTO dto) {
// 实时计算统计数据
Map<String, Object> map = amzAdvSumProductAdsService.getSumProduct(param);
BigDecimal mapordersum = amzAdvSumProductAdsService.orderSummaryAll(param);
Map<String, Object> chartdata = amzAdvSumProductAdsService.getDaysSumProduct(param);
// ...
}
// 优化后:使用预计算数据
@PostMapping("/getsumproduct")
public Result<Map<String, Object>> getSumProductAction(@RequestBody QueryForSumProductDTO dto) {
// 优先使用预计算数据
Map<String, Object> precomputedData = amzAdvSumProductAdsService.getPrecomputedSumProduct(param);
if (precomputedData != null) {
return Result.success(precomputedData);
}
// 预计算数据不存在时,实时计算
Map<String, Object> map = amzAdvSumProductAdsService.getSumProduct(param);
BigDecimal mapordersum = amzAdvSumProductAdsService.orderSummaryAll(param);
Map<String, Object> chartdata = amzAdvSumProductAdsService.getDaysSumProduct(param);
// 缓存计算结果
amzAdvSumProductAdsService.cacheSumProductResult(param, map, mapordersum, chartdata);
// ...
}
9. 总结
9.1 核心价值
广告统计模块是Wimoor系统中功能强大、数据全面的广告分析工具,具有以下核心价值:
9.2 技术创新
广告统计模块在技术实现上具有以下创新点:
9.3 未来发展
广告统计模块具有广阔的发展前景,未来可以从以下几个方面进行发展:
9.4 结论
广告统计模块是Wimoor系统中不可或缺的核心功能模块,通过该模块,用户可以实时监控广告投放状态、分析投放效果、识别异常问题并优化投放策略。该模块采用先进的技术架构和实现方案,具有功能强大、数据全面、性能高效、扩展性强等特点,为用户提供了一站式的广告分析解决方案。
随着技术的不断发展和业务需求的不断变化,广告统计模块也将不断升级和完善,为用户提供更加智能、全面、高效的广告分析服务,帮助用户在激烈的市场竞争中获得更大的优势。