新增前端下单首页

This commit is contained in:
Mrking 2024-09-24 23:45:12 +08:00
parent eecdbc1c71
commit 7550592b8a
15 changed files with 648 additions and 32 deletions

View File

@ -116,6 +116,10 @@ public class AppSaleOrderController{
public void exportSaleOrderExcel(@Valid SaleOrderPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
CustomerDO customer = customerService.getCustomerByUserId(loginUser.getId());
pageReqVO.setCustomerId(customer.getId());
List<SaleOrderDO> list = saleOrderService.getSaleOrderPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "销售订单.xls", "数据", SaleOrderRespVO.class,
@ -135,7 +139,13 @@ public class AppSaleOrderController{
@GetMapping("/get-count")
@Operation(summary = "获得销售订单 分页 tab count")
public CommonResult<Map<Integer, Long>> getSpuCount() {
return success(saleOrderService.getTabsCount());
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
CustomerDO customer = customerService.getCustomerByUserId(loginUser.getId());
Long customerId = null;
if(customer!=null){
customerId = customer.getId();
}
return success(saleOrderService.getTabsCount(customerId));
}
@PostMapping("/updateSaleOrderBillStatus")

View File

@ -0,0 +1,86 @@
package cn.hangtag.module.oms.controller.admin.app;
import cn.hangtag.framework.common.pojo.CommonResult;
import cn.hangtag.framework.security.core.LoginUser;
import cn.hangtag.framework.security.core.util.SecurityFrameworkUtils;
import cn.hangtag.module.oms.controller.admin.common.vo.DataComparisonRespVO;
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderCountRespVO;
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderSummaryRespVO;
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderTrendReqVO;
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderTrendRespVO;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.enums.common.BillStatusEnum;
import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.oms.service.saleorder.SaleOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import static cn.hangtag.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 订单统计")
@RestController
@RequestMapping("/oms/app/statistics/trade")
@Validated
@Slf4j
public class AppTradeStatisticsController {
@Resource
private SaleOrderService saleOrderService;
@Resource
private CustomerService customerService;
@GetMapping("/order-comparison")
@Operation(summary = "获得交易订单数量")
//@PreAuthorize("@ss.hasPermission('statistics:order:query')")
public CommonResult<DataComparisonRespVO<TradeOrderSummaryRespVO>> getOrderComparison() {
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
CustomerDO customer = customerService.getCustomerByUserId(loginUser.getId());
Long customerId = null;
if(customer!=null){
customerId = customer.getId();
}
return success(saleOrderService.getOrderComparison(customerId));
}
@GetMapping("/order-count")
@Operation(summary = "获得交易订单数量")
public CommonResult<TradeOrderCountRespVO> getOrderCount() {
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
CustomerDO customer = customerService.getCustomerByUserId(loginUser.getId());
Long customerId = null;
if(customer!=null){
customerId = customer.getId();
}
TradeOrderCountRespVO tradeOrderCountRespVO = new TradeOrderCountRespVO();
// 订单统计
Long rejectCount = saleOrderService.getCountByBillStatus(BillStatusEnum.REJECT.getValue(),customerId);
Long saveCount = saleOrderService.getCountByBillStatus(BillStatusEnum.SAVE.getValue(),customerId);
Long submitCount = saleOrderService.getCountByBillStatus(BillStatusEnum.SUBMIT.getValue(),customerId);
Long auditCount = saleOrderService.getCountByBillStatus(BillStatusEnum.AUDIT.getValue(),customerId);
tradeOrderCountRespVO.setOrderCountAA(rejectCount);
tradeOrderCountRespVO.setOrderCountA(saveCount);
tradeOrderCountRespVO.setOrderCountB(submitCount);
tradeOrderCountRespVO.setOrderCountC(auditCount);
// 拼接返回
return success(tradeOrderCountRespVO);
}
@GetMapping("/order-count-trend")
@Operation(summary = "获得订单量趋势统计")
public CommonResult<List<DataComparisonRespVO<TradeOrderTrendRespVO>>> getOrderCountTrendComparison(@Valid TradeOrderTrendReqVO reqVO) {
return success(saleOrderService.getOrderCountTrendComparison(reqVO));
}
}

View File

@ -8,7 +8,6 @@ import cn.hangtag.module.system.api.user.AdminUserApi;
import cn.hangtag.module.system.api.user.dto.AdminUserRespDTO;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
@ -18,12 +17,10 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.annotation.security.PermitAll;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import java.util.stream.Stream;
import cn.hangtag.framework.common.pojo.PageParam;
import cn.hangtag.framework.common.pojo.PageResult;
@ -136,7 +133,7 @@ public class SaleOrderController {
@Operation(summary = "获得销售订单 分页 tab count")
@PreAuthorize("@ss.hasPermission('oms:sale-order:query')")
public CommonResult<Map<Integer, Long>> getSpuCount() {
return success(saleOrderService.getTabsCount());
return success(saleOrderService.getTabsCount(null));
}
@PostMapping("/updateSaleOrderBillStatus")

View File

@ -67,7 +67,7 @@ public interface SaleOrderMapper extends BaseMapperX<SaleOrderDO> {
TradeOrderSummaryRespVO selectOrderQtySummaryByOrderStatusAndCreateTimeBetween(@Param("orderStatus") String orderStatus,
@Param("beginTime") LocalDateTime beginTime,
@Param("endTime") LocalDateTime endTime);
@Param("endTime") LocalDateTime endTime,@Param("customerId") Long customerId);
/**

View File

@ -13,7 +13,6 @@ import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderTrendRespVO;
import cn.hangtag.module.oms.dal.dataobject.saleorder.SaleOrderDO;
import cn.hangtag.module.oms.dal.dataobject.saleorderentry.SaleOrderEntryDO;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.pojo.PageParam;
/**
* 销售订单 Service 接口
@ -70,7 +69,7 @@ public interface SaleOrderService {
*/
List<SaleOrderEntryDO> getSaleOrderEntryListByParentId(Long parentId);
Map<Integer, Long> getTabsCount();
Map<Integer, Long> getTabsCount(Long customerId);
default void updateSaleOrderBillStatus(List<Long> ids, String status){
updateSaleOrderBillStatus(ids,status,null);
@ -81,16 +80,23 @@ public interface SaleOrderService {
void generatePdf(HttpServletResponse response) throws IOException;
default DataComparisonRespVO<TradeOrderSummaryRespVO> getOrderComparison(){
return getOrderComparison(null);
}
/**
* 交易订单销售额对照
*
* @return 销售额对照
*/
DataComparisonRespVO<TradeOrderSummaryRespVO> getOrderComparison();
DataComparisonRespVO<TradeOrderSummaryRespVO> getOrderComparison(Long customerId);
void updateOrderRemark(SaleOrderRemarkReqVO reqVO);
Long getCountByBillStatus(String value);
default Long getCountByBillStatus(String value){
return getCountByBillStatus(value,null);
}
Long getCountByBillStatus(String value, Long customerId);
List<DataComparisonRespVO<TradeOrderTrendRespVO>> getOrderCountTrendComparison(TradeOrderTrendReqVO reqVO);
}

View File

@ -1,18 +1,14 @@
package cn.hangtag.module.oms.service.saleorder;
import cn.hangtag.framework.common.exception.ServiceException;
import cn.hangtag.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.framework.security.core.LoginUser;
import cn.hangtag.framework.security.core.util.SecurityFrameworkUtils;
import cn.hangtag.framework.web.core.util.WebFrameworkUtils;
import cn.hangtag.module.oms.common.utils.NumberChineseFormatterUtils;
import cn.hangtag.module.oms.common.utils.WKHtmlToPdfUtil;
import cn.hangtag.module.oms.controller.admin.common.vo.DataComparisonRespVO;
import cn.hangtag.module.oms.controller.admin.produceorder.vo.ProduceOrderSaveReqVO;
import cn.hangtag.module.oms.controller.admin.product.vo.ProductPriceSaveReqVO;
import cn.hangtag.module.oms.controller.admin.salecontract.vo.SaleContractSaveReqVO;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderPageReqVO;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderRemarkReqVO;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderSaveReqVO;
@ -39,15 +35,14 @@ import cn.hangtag.module.oms.service.product.ProductPriceService;
import cn.hangtag.module.oms.service.productinfo.ProductInfoService;
import cn.hangtag.module.oms.service.salecontract.SaleContractService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@ -173,17 +168,35 @@ public class SaleOrderServiceImpl implements SaleOrderService {
}
@Override
public Map<Integer, Long> getTabsCount() {
public Map<Integer, Long> getTabsCount(Long customerId) {
Map<Integer, Long> counts = Maps.newLinkedHashMapWithExpectedSize(3);
LambdaQueryWrapper<SaleOrderDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(SaleOrderDO::getOrderStatus, SaleOrderStatusEnum.YXD.getValue());
if(customerId!=null){
lambdaQueryWrapper.eq(SaleOrderDO::getCustomerId, customerId);
}
LambdaQueryWrapper<SaleOrderDO> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
lambdaQueryWrapper1.eq(SaleOrderDO::getOrderStatus, SaleOrderStatusEnum.SCZ.getValue());
if(customerId!=null){
lambdaQueryWrapper1.eq(SaleOrderDO::getCustomerId, customerId);
}
LambdaQueryWrapper<SaleOrderDO> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
lambdaQueryWrapper2.eq(SaleOrderDO::getOrderStatus, SaleOrderStatusEnum.YWC.getValue());
if(customerId!=null){
lambdaQueryWrapper2.eq(SaleOrderDO::getCustomerId, customerId);
}
// 查询已下单订单数量
counts.put(SaleOrderStatusEnum.YXD.getValue(),
saleOrderMapper.selectCount(SaleOrderDO::getOrderStatus, SaleOrderStatusEnum.YXD.getValue()));
saleOrderMapper.selectCount(lambdaQueryWrapper));
// 查询已生产订单数量
counts.put(SaleOrderStatusEnum.SCZ.getValue(),
saleOrderMapper.selectCount(SaleOrderDO::getOrderStatus, SaleOrderStatusEnum.SCZ.getValue()));
saleOrderMapper.selectCount(lambdaQueryWrapper1));
// 查询已完成订单数量
counts.put(SaleOrderStatusEnum.YWC.getValue(),
saleOrderMapper.selectCount(SaleOrderDO::getOrderStatus, SaleOrderStatusEnum.YWC.getValue()));
saleOrderMapper.selectCount(lambdaQueryWrapper2));
return counts;
}
@ -376,7 +389,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
}
@Override
public DataComparisonRespVO<TradeOrderSummaryRespVO> getOrderComparison() {
public DataComparisonRespVO<TradeOrderSummaryRespVO> getOrderComparison(Long customerId) {
LocalDateTime dayDate = LocalDateTime.now();
LocalDateTime lastDayDate = LocalDateTime.now().minusDays(1);
LocalDateTime beginWeekDate = DateUtil.beginOfWeek(DateUtil.date()).toLocalDateTime();
@ -385,10 +398,10 @@ public class SaleOrderServiceImpl implements SaleOrderService {
LocalDateTime lastEndWeekDate = DateUtil.endOfWeek(DateUtil.lastWeek()).toLocalDateTime();
return new DataComparisonRespVO<TradeOrderSummaryRespVO>()
.setValue(getOrderQtySummary(dayDate,dayDate))//今日
.setReference(getOrderQtySummary(lastDayDate,lastDayDate))//昨日
.setValue2(getOrderQtySummary(beginWeekDate,endWeekDate))//本周
.setReference2(getOrderQtySummary(lastBeginWeekDate,lastEndWeekDate));//上周
.setValue(getOrderQtySummary(dayDate,dayDate,customerId))//今日
.setReference(getOrderQtySummary(lastDayDate,lastDayDate,customerId))//昨日
.setValue2(getOrderQtySummary(beginWeekDate,endWeekDate,customerId))//本周
.setReference2(getOrderQtySummary(lastBeginWeekDate,lastEndWeekDate,customerId));//上周
}
@Override
@ -402,8 +415,13 @@ public class SaleOrderServiceImpl implements SaleOrderService {
}
@Override
public Long getCountByBillStatus(String billstatus) {
return saleOrderMapper.selectCount(SaleOrderDO::getBillStatus,billstatus);
public Long getCountByBillStatus(String billstatus, Long customerId) {
LambdaQueryWrapper<SaleOrderDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(SaleOrderDO::getBillStatus,billstatus);
if(customerId!=null){
lambdaQueryWrapper.eq(SaleOrderDO::getCustomerId,customerId);
}
return saleOrderMapper.selectCount(lambdaQueryWrapper);
}
@Override
@ -431,11 +449,11 @@ public class SaleOrderServiceImpl implements SaleOrderService {
return saleOrderMapper.selectListByPayTimeBetweenAndGroupByDay(beginTime, endTime);
}
private TradeOrderSummaryRespVO getOrderQtySummary(LocalDateTime beginDate,LocalDateTime endDate) {
private TradeOrderSummaryRespVO getOrderQtySummary(LocalDateTime beginDate, LocalDateTime endDate, Long customerId) {
LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(beginDate);
LocalDateTime endTime = LocalDateTimeUtil.endOfDay(endDate);
return saleOrderMapper.selectOrderQtySummaryByOrderStatusAndCreateTimeBetween(
null, beginTime, endTime);
null, beginTime, endTime,customerId);
}

View File

@ -13,6 +13,9 @@
<if test="orderStatus != null">
AND order_status = #{orderStatus}
</if>
<if test="customerId != null">
AND customer_id = #{customerId}
</if>
AND create_time BETWEEN #{beginTime} AND #{endTime}
</select>

View File

@ -49,7 +49,7 @@ export interface TradeOrderTrendRespVO {
// 查询交易统计
export const getTradeStatisticsSummary = () => {
return request.get<DataComparisonRespVO<TradeSummaryRespVO>>({
url: '/statistics/trade/summary'
url: '/oms/statistics/trade/summary'
})
}
@ -58,7 +58,7 @@ export const getTradeStatisticsSummary = () => {
// 获得交易状况明细
export const getTradeStatisticsList = (params: TradeTrendReqVO) => {
return request.get<TradeTrendSummaryRespVO[]>({
url: '/statistics/trade/list',
url: '/oms/statistics/trade/list',
params: formatDateParam(params)
})
}
@ -66,7 +66,7 @@ export const getTradeStatisticsList = (params: TradeTrendReqVO) => {
// 导出交易状况明细
export const exportTradeStatisticsExcel = (params: TradeTrendReqVO) => {
return request.download({
url: '/statistics/trade/export-excel',
url: '/oms/statistics/trade/export-excel',
params: formatDateParam(params)
})
}

View File

@ -0,0 +1,7 @@
/** 数据对照 Response VO */
export interface DataComparisonRespVO<T> {
value: T
reference: T
value2: T
reference2: T
}

View File

@ -0,0 +1,101 @@
import request from '@/config/axios'
import dayjs from 'dayjs'
import { formatDate } from '@/utils/formatTime'
import { DataComparisonRespVO } from '@/api/oms/statistics/common'
/** 交易统计 Response VO */
export interface TradeSummaryRespVO {
yesterdayOrderCount: number
monthOrderCount: number
yesterdayPayPrice: number
monthPayPrice: number
}
/** 交易状况 Request VO */
export interface TradeTrendReqVO {
times: [dayjs.ConfigType, dayjs.ConfigType]
}
/** 交易订单数量 Response VO */
export interface TradeOrderCountRespVO {
/** 驳回 */
orderCountAA?: number
/** 待提交 */
orderCountA?: number
/** 提交中 */
orderCountB?: number
/** 已审核 */
orderCountC?: number
}
/** 交易订单统计 Response VO */
export interface TradeOrderSummaryRespVO {
/** 支付订单商品数 */
orderCount?: number
/** 总支付金额,单位:分 */
orderAmount?: number
}
/** 订单量趋势统计 Response VO */
export interface TradeOrderTrendRespVO {
/** 日期 */
date: string
/** 订单数量 */
orderCount: number
/** 订单支付金额 */
orderAmount: number
}
// 查询交易统计
export const getTradeStatisticsSummary = () => {
return request.get<DataComparisonRespVO<TradeSummaryRespVO>>({
url: '/oms/app/statistics/app/trade/summary'
})
}
// 获得交易状况明细
export const getTradeStatisticsList = (params: TradeTrendReqVO) => {
return request.get<TradeTrendSummaryRespVO[]>({
url: '/oms/app/statistics/trade/list',
params: formatDateParam(params)
})
}
// 导出交易状况明细
export const exportTradeStatisticsExcel = (params: TradeTrendReqVO) => {
return request.download({
url: '/oms/app/statistics/trade/export-excel',
params: formatDateParam(params)
})
}
// 获得交易订单数量
export const getOrderCount = async () => {
return await request.get<TradeOrderCountRespVO>({ url: `/oms/app/statistics/trade/order-count` })
}
// 获得交易订单数量对照
export const getOrderComparison = async () => {
return await request.get<DataComparisonRespVO<TradeOrderSummaryRespVO>>({
url: `/oms/app/statistics/trade/order-comparison`
})
}
// 获得订单量趋势统计
export const getOrderCountTrendComparison = (
type: number,
beginTime: dayjs.ConfigType,
endTime: dayjs.ConfigType
) => {
return request.get<DataComparisonRespVO<TradeOrderTrendRespVO>[]>({
url: '/oms/app/statistics/trade/order-count-trend',
params: { type, beginTime: formatDate(beginTime), endTime: formatDate(endTime) }
})
}
/** 时间参数需要格式化, 确保接口能识别 */
const formatDateParam = (params: TradeTrendReqVO) => {
return { times: [formatDate(params.times[0]), formatDate(params.times[1])] } as TradeTrendReqVO
}

View File

@ -19,6 +19,17 @@
</el-row>
</el-skeleton>
</el-card>
<el-row :gutter="16" class="row">
<el-col :md="12">
<!-- 快捷入口 -->
<ShortcutCard />
</el-col>
<el-col :md="12">
<!-- 运营数据 -->
<OperationDataCard />
</el-col>
</el-row>
</div>
</template>

View File

@ -0,0 +1,43 @@
<template>
<div class="flex flex-col gap-2 bg-[var(--el-bg-color-overlay)] p-6">
<div class="flex items-center justify-between text-gray-500">
<span>{{ title }}</span>
<el-tag>{{ tag }}</el-tag>
</div>
<div class="flex flex-row items-baseline justify-between">
<CountTo :prefix="prefix" :end-val="value" :decimals="decimals" class="text-3xl" />
<span :class="toNumber(percent) > 0 ? 'text-red-500' : 'text-green-500'">
{{ Math.abs(toNumber(percent)) }}%
<Icon :icon="toNumber(percent) > 0 ? 'ep:caret-top' : 'ep:caret-bottom'" class="!text-sm" />
</span>
</div>
<el-divider class="mb-1! mt-2!" />
<div class="flex flex-row items-center justify-between text-sm">
<span class="text-gray-500">{{lasttag}}</span>
<span>{{ prefix || '' }}{{ reference }}</span>
</div>
</div>
</template>
<script lang="ts" setup>
import { propTypes } from '@/utils/propTypes'
import { toNumber } from 'lodash-es'
import { calculateRelativeRate } from '@/utils'
/** 交易对照卡片 */
defineOptions({ name: 'ComparisonCard' })
const props = defineProps({
title: propTypes.string.def('').isRequired,
tag: propTypes.string.def(''),
lasttag: propTypes.string.def(''),
prefix: propTypes.string.def(''),
value: propTypes.number.def(0).isRequired,
reference: propTypes.number.def(0).isRequired,
decimals: propTypes.number.def(0)
})
//
const percent = computed(() =>
calculateRelativeRate(props.value as number, props.reference as number)
)
</script>

View File

@ -0,0 +1,76 @@
<template>
<el-card shadow="never">
<template #header>
<CardTitle title="运营数据" />
</template>
<div class="flex flex-row flex-wrap items-center gap-8 p-4">
<div
v-for="item in data"
:key="item.name"
class="h-20 w-20% flex flex-col cursor-pointer items-center justify-center gap-2"
@click="handleClick(item.routerName)"
>
<CountTo
:prefix="item.prefix"
:end-val="item.value"
:decimals="item.decimals"
class="text-3xl"
/>
<span class="text-center">{{ item.name }}</span>
</div>
</div>
</el-card>
</template>
<script lang="ts" setup>
import * as TradeStatisticsApi from '@/api/oms/statistics/trade'
import { CardTitle } from '@/components/Card'
/** 运营数据卡片 */
defineOptions({ name: 'OperationDataCard' })
const router = useRouter() //
/** 数据 */
const data = reactive({
orderCountAA: { name: '已驳回订单', value: 0, routerName: 'SaleOrder' },
orderCountA: { name: '待提交订单', value: 0, routerName: 'SaleOrder' },
orderCountB: { name: '待审核订单', value: 0, routerName: 'SaleOrder' },
orderCountC: { name: '已完成订单', value: 0, routerName: 'SaleOrder' }
})
/** 查询订单数据 */
const getOrderData = async () => {
const orderCount = await TradeStatisticsApi.getOrderCount()
if (orderCount.orderCountAA != null) {
data.orderCountAA.value = orderCount.orderCountAA
}
if (orderCount.orderCountA != null) {
data.orderCountA.value = orderCount.orderCountA
}
if (orderCount.orderCountB != null) {
data.orderCountB.value = orderCount.orderCountB
}
if (orderCount.orderCountC != null) {
data.orderCountC.value = orderCount.orderCountC
}
}
/**
* 跳转到对应页面
*
* @param routerName 路由页面组件的名称
*/
const handleClick = (routerName: string) => {
router.push({ name: routerName })
}
/** 激活时 */
onActivated(() => {
getOrderData()
})
/** 初始化 **/
onMounted(() => {
getOrderData()
})
</script>

View File

@ -0,0 +1,51 @@
<template>
<el-card shadow="never">
<template #header>
<CardTitle title="快捷入口" />
</template>
<div class="flex flex-row flex-wrap gap-8 p-4">
<div
v-for="menu in menuList"
:key="menu.name"
class="h-20 w-20% flex flex-col cursor-pointer items-center justify-center gap-2"
@click="handleMenuClick(menu.routerName)"
>
<div
:class="menu.bgColor"
class="h-48px w-48px flex items-center justify-center rounded text-white"
>
<Icon :icon="menu.icon" class="text-7.5!" />
</div>
<span>{{ menu.name }}</span>
</div>
</div>
</el-card>
</template>
<script lang="ts" setup>
/** 快捷入口卡片 */
import { CardTitle } from '@/components/Card'
defineOptions({ name: 'ShortcutCard' })
const router = useRouter() //
/** 菜单列表 */
const menuList = [
{ name: '订单管理', icon: 'ep:list', bgColor: 'bg-yellow-500', routerName: 'SaleOrder' },
{
name: '创建订单',
icon: 'fa-solid:project-diagram',
bgColor: 'bg-green-600',
routerName: 'CreateOrder'
}
]
/**
* 跳转到菜单对应页面
*
* @param routerName 路由页面组件的名称
*/
const handleMenuClick = (routerName: string) => {
router.push({ name: routerName })
}
</script>

View File

@ -0,0 +1,207 @@
<template>
<el-card shadow="never">
<template #header>
<div class="flex flex-row items-center justify-between">
<CardTitle title="交易量趋势" />
<!-- 查询条件 -->
<div class="flex flex-row items-center gap-2">
<el-radio-group v-model="timeRangeType" @change="handleTimeRangeTypeChange">
<el-radio-button v-for="[key, value] in timeRange.entries()" :key="key" :label="key">
{{ value.name }}
</el-radio-button>
</el-radio-group>
</div>
</div>
</template>
<!-- 折线图 -->
<Echart :height="300" :options="eChartOptions" />
</el-card>
</template>
<script lang="ts" setup>
import dayjs, { Dayjs } from 'dayjs'
import { EChartsOption } from 'echarts'
import * as TradeStatisticsApi from '@/api/oms/statistics/trade'
import { formatDate } from '@/utils/formatTime'
import { CardTitle } from '@/components/Card'
/** 交易量趋势 */
defineOptions({ name: 'TradeTrendCard' })
enum TimeRangeTypeEnum {
DAY30 = 1,
WEEK = 7,
MONTH = 30,
YEAR = 365
} //
const timeRangeType = ref(TimeRangeTypeEnum.DAY30) // , 30
const loading = ref(true) //
// Map
const timeRange = new Map()
.set(TimeRangeTypeEnum.DAY30, {
name: '30天',
series: [
{ name: '订单金额', type: 'bar', smooth: true, data: [] },
{ name: '订单数量', type: 'line', smooth: true, data: [] }
]
})
.set(TimeRangeTypeEnum.WEEK, {
name: '周',
series: [
{ name: '上周金额', type: 'bar', smooth: true, data: [] },
{ name: '本周金额', type: 'bar', smooth: true, data: [] },
{ name: '上周数量', type: 'line', smooth: true, data: [] },
{ name: '本周数量', type: 'line', smooth: true, data: [] }
]
})
.set(TimeRangeTypeEnum.MONTH, {
name: '月',
series: [
{ name: '上月金额', type: 'bar', smooth: true, data: [] },
{ name: '本月金额', type: 'bar', smooth: true, data: [] },
{ name: '上月数量', type: 'line', smooth: true, data: [] },
{ name: '本月数量', type: 'line', smooth: true, data: [] }
]
})
.set(TimeRangeTypeEnum.YEAR, {
name: '年',
series: [
{ name: '去年金额', type: 'bar', smooth: true, data: [] },
{ name: '今年金额', type: 'bar', smooth: true, data: [] },
{ name: '去年数量', type: 'line', smooth: true, data: [] },
{ name: '今年数量', type: 'line', smooth: true, data: [] }
]
})
/** 图表配置 */
const eChartOptions = reactive<EChartsOption>({
grid: {
left: 20,
right: 20,
bottom: 20,
top: 80,
containLabel: true
},
legend: {
top: 50,
data: []
},
series: [],
toolbox: {
feature: {
//
dataZoom: {
yAxisIndex: false // Y
},
brush: {
type: ['lineX', 'clear'] //
},
saveAsImage: { show: true, name: '订单量趋势' } //
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
xAxis: {
type: 'category',
inverse: true,
boundaryGap: false,
axisTick: {
show: false
},
data: [],
axisLabel: {
formatter: (date: string) => {
switch (timeRangeType.value) {
case TimeRangeTypeEnum.DAY30:
return formatDate(date, 'MM-DD')
case TimeRangeTypeEnum.WEEK:
let weekDay = formatDate(date, 'ddd')
if (weekDay == '0') weekDay = '日'
return '周' + weekDay
case TimeRangeTypeEnum.MONTH:
return formatDate(date, 'D')
case TimeRangeTypeEnum.YEAR:
return formatDate(date, 'M') + '月'
default:
return date
}
}
}
},
yAxis: {
axisTick: {
show: false
}
}
}) as EChartsOption
/** 时间范围类型单选按钮选中 */
const handleTimeRangeTypeChange = async () => {
//
let beginTime: Dayjs
let endTime: Dayjs
switch (timeRangeType.value) {
case TimeRangeTypeEnum.WEEK:
beginTime = dayjs().startOf('week')
endTime = dayjs().endOf('week')
break
case TimeRangeTypeEnum.MONTH:
beginTime = dayjs().startOf('month')
endTime = dayjs().endOf('month')
break
case TimeRangeTypeEnum.YEAR:
beginTime = dayjs().startOf('year')
endTime = dayjs().endOf('year')
break
case TimeRangeTypeEnum.DAY30:
default:
beginTime = dayjs().subtract(30, 'day').startOf('d')
endTime = dayjs().endOf('d')
break
}
//
await getOrderCountTrendComparison(beginTime, endTime)
}
/** 查询订单数量趋势对照数据 */
const getOrderCountTrendComparison = async (
beginTime: dayjs.ConfigType,
endTime: dayjs.ConfigType
) => {
loading.value = true
//
const list = await TradeStatisticsApi.getOrderCountTrendComparison(
timeRangeType.value,
beginTime,
endTime
)
//
const dates: string[] = []
const series = [...timeRange.get(timeRangeType.value).series]
for (let item of list) {
dates.push(item.value.date)
if (series.length === 2) {
series[0].data.push(item?.value?.orderAmount || 0) //
series[1].data.push(item?.value?.orderCount || 0) //
} else {
series[0].data.push(item?.reference?.orderAmount || 0) //
series[1].data.push(item?.value?.orderAmount || 0) //
series[2].data.push(item?.reference?.orderCount || 0) //
series[3].data.push(item?.value?.orderCount || 0) //
}
}
eChartOptions.xAxis!['data'] = dates
eChartOptions.series = series
// legend424
eChartOptions.legend['data'] = series.map((item) => item.name)
loading.value = false
}
/** 初始化 **/
onMounted(() => {
handleTimeRangeTypeChange()
})
</script>