提交 9486bf69 authored 作者: lidongxu's avatar lidongxu

feat(finance): 财务分析完成第一版本

完成
上级 e44d957a
......@@ -52,3 +52,21 @@ export const getFinanceListAPI = (data) => {
}
})
}
export const getFinanceDetailAPI = (data) => {
return request({
url: '/bi/finance/cost/detail/list',
method: 'POST',
data: {
zbjQdType: data.brand,
flavor: data.taste,
specName: data.spec,
series: data.seriesPrdMap.map(o => o[0]),
goodsName: data.seriesPrdMap.map(o => o[1]),
startDate: parseTime(data.date[0], `{y}-{m}-{d}`),
endDate: parseTime(data.date[1], `{y}-{m}-{d}`),
pageNum: data.pageNum,
pageSize: data.pageSize
}
})
}
\ No newline at end of file
......@@ -98,56 +98,76 @@
@change="getList()">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button icon="Refresh"
@click="reset">
重置
</el-button>
</el-form-item>
</el-form>
<!-- 操作工具 -->
<el-row :gutter="10"
<el-row
class="mb8">
<el-button icon="Refresh"
@click="reset"
v-show="showSearch">
重置
</el-button>
<right-toolbar v-model:showSearch="showSearch"
@queryTable="getList"
:columns="columns">
</right-toolbar>
</el-row>
<!-- 数据 -->
<el-table :data="tableData"
border>
<el-table :data="tableList"
border
@row-click="rowClick">
<template v-for="item in columns">
<el-table-column v-if="item.visible"
:key="item.prop"
:label="item.label"
:prop="item.prop"
:min-width="item.width"
:formatter="formatter">
</el-table-column>
</template>
</el-table>
<!-- 订单详情 -->
<el-dialog v-model="detailVisible"
title="Shipping address"
width="80%">
<el-table :data="detailTableData">
<el-table-column property="date"
label="Date"
width="150" />
<el-table-column property="name"
label="Name"
width="200" />
<el-table-column property="address"
label="Address" />
title="订单详情"
width="80%"
footer-class="dialog-footer">
<el-table :data="detailList"
ref="detailTableRef"
border
:key="showOverFlowToolTip"
height="100%"
scrollbar-always-on
:show-overflow-tooltip="showOverFlowToolTip"
scrollbar-tabindex="0">
<el-table-column v-for="item in detailColumns"
:prop="item.prop"
:label="item.label"
:width="item.width"
:formatter="detailFormatter" />
</el-table>
<template #footer>
<el-row>
<el-button class="semi-btn"
type="primary"
icon="SemiSelect"
@click="changeShowOver">
{{ showOverFlowToolTip ? '自然展示' : '强制一行' }}
</el-button>
<pagination :total="detailTotal"
v-model:page="detailQueryParams.pageNum"
v-model:limit="detailQueryParams.pageSize"
@pagination="getDetailList"></pagination>
</el-row>
</template>
</el-dialog>
</div>
</div>
</template>
<script setup>
import { getBrandListAPI, getTasteListAPI, getSpecListAPI, getSeriesListAPI, getProductListAPI, getFinanceListAPI } from '@/api'
import { getBrandListAPI, getTasteListAPI, getSpecListAPI, getSeriesListAPI, getProductListAPI, getFinanceListAPI, getFinanceDetailAPI } from '@/api'
import { useDatePickerOptions } from '@/hooks'
import { formatNumberWithUnit } from '@/utils'
import { formatNumberWithUnit, parseTime } from '@/utils'
const { lastPickerOptions: pickerOptions } = useDatePickerOptions()
const showSearch = ref(true) // 搜索
......@@ -158,21 +178,26 @@ const data = reactive({
brand: [], // 直播间
taste: [], // 口味
spec: [], // 规格
// series: [], // 系列
// goods: [], // 商品
date: [], // 日期
seriesPrdMap: [] // 系列商品
}
},
detailQueryParams: { // 详情查询
pageNum: 1,
pageSize: 10
},
})
const { queryParams } = toRefs(data)
const { queryParams, detailQueryParams } = toRefs(data)
const reset = () => {
queryParams.value = {
brand: [], // 直播间
taste: [], // 口味
spec: [], // 规格
date: [], // 日期
seriesPrdMap: [] // 系列商品
seriesPrdMap: [], // 系列商品
pageNum: 1,
pageSize: 10
}
getList()
}
......@@ -254,59 +279,69 @@ const columns = ref([
{
label: '直播间',
prop: 'zbjQdType',
visible: true
visible: true,
width: 140
},
{
label: '口味',
prop: 'flavorErp',
visible: true
visible: true,
width: 120
},
{
label: '规格',
prop: 'specNameErp',
visible: true
visible: true,
width: 140
},
{
label: '系列',
prop: 'a',
visible: true
prop: '',
visible: true,
width: 140
},
{
label: '商品',
prop: 'goodsName',
visible: true
visible: true,
width: 140
},
{
label: '分摊后总价',
prop: 'shareAmountSum',
visible: true
visible: true,
width: 120
},
{
label: '实际成本',
prop: 'actualCostSum',
visible: true
visible: true,
width: 120
},
{
label: '实际成本毛利',
prop: 'actualCostGrossProfitSum',
visible: true
visible: true,
width: 120
},
{
label: '标准成本',
prop: 'standardCostSum',
visible: true
visible: true,
width: 120
},
{
label: '标准成本毛利',
prop: 'standardCostGrossProfitSum',
visible: true
visible: true,
width: 120
}
])
const tableData = ref([
const tableList = ref([
])
const getList = async () => {
const res = await getFinanceListAPI(queryParams.value)
tableData.value = res.data.list
tableList.value = res.data.list
}
getList()
......@@ -319,86 +354,201 @@ const formatter = (row, column, value) => {
}
// 详情数据
const detailTableData = ref([])
const detailList = ref([])
const detailColumns = ref([
{
label: '订单编号',
prop: 'id'
prop: 'tradeNo',
width: 160
}, {
label: '店铺名称',
prop: 'name'
},
{
prop: 'shopName',
width: 220
}, {
label: '原始单号',
prop: ''
prop: 'srcTid',
width: 180
}, {
label: '原始子单号',
prop: ''
prop: 'srcOid',
width: 180
}, {
label: '订单状态',
prop: ''
prop: 'tradeStatus',
width: 80
}, {
label: '交易时间',
prop: ''
prop: 'tradeTime',
width: 170
}, {
label: '付款时间',
prop: ''
prop: 'payTime',
width: 170
}, {
label: '发货时间',
prop: ''
prop: 'consignTime',
width: 170
}, {
label: '省市县',
prop: ''
prop: 'receiverArea',
width: 170
}, {
label: '备注',
prop: ''
prop: 'remark',
width: 250
}, {
label: '应收金额',
prop: ''
prop: 'receivable',
width: 80
}, {
label: '货品编号',
prop: ''
prop: 'goodsNo',
width: 120
}, {
label: '货品名称',
prop: ''
prop: 'goodsName',
width: 250
}, {
label: '规格名称',
prop: ''
prop: 'specName'
}, {
label: '分类',
prop: ''
prop: 'goodsType',
width: 100
}, {
label: '数量',
prop: ''
prop: 'num'
}, {
label: '优惠',
prop: ''
prop: 'discount'
}, {
label: '分摊后总价',
prop: ''
prop: 'shareAmount',
width: 120
}, {
label: '拆自组合装',
prop: ''
prop: 'suiteNo',
width: 200
}, {
label: '组合装编码',
prop: ''
prop: 'suiteName',
width: 200
}, {
label: '组合装数量',
prop: ''
prop: 'suiteNum',
width: 140
}, {
label: '赠品方式',
prop: ''
prop: 'giftType',
width: 160
}, {
label: '分销商名称',
prop: ''
prop: 'fenxiaoName',
width: 240
}, {
label: '分销商编号',
prop: ''
prop: 'fenxiaoId',
width: 160
}, {
label: '平台货品名称',
prop: ''
prop: 'apiGoodsName',
width: 540
}
])
const detailTotal = ref(0)
const showOverFlowToolTip = ref(true) // 强制表格一行显示
const detailTableRef = ref(null)
// 订单状态
const orderStatus = {
4: "线下退款",
5: "已取消",
6: "待转预订单(待审核)",
7: "待转已完成",
10: "未付款",
12: "待尾款",
15: "等未付",
16: "延时审核",
19: "预订单前处理",
20: "审核前处理",
21: "自流转待发货",
23: "异常订单",
24: "换货预订单",
25: "待处理预订单",
27: "待分配预订单",
30: "待客审",
35: "待财审",
40: "审核中",
55: "已审核",
95: "已发货",
96: "成本确认(待录入计划成本,订单结算时有货品无计划成本)",
101: "已过账",
110: "已完成"
};
// 分类(货品类型)
const goodsType = {
1: "销售商品",
2: "原材料",
3: "包装",
4: "周转材料",
5: "虚拟商品",
6: "固定资产",
0: "其它"
};
// 赠品方式
const giftType = {
0: "非赠品",
1: "自动赠送",
2: "手工赠送",
4: "周期购赠送",
8: "平台赠送",
32: "阶梯满赠",
64: "CRM追加赠送",
128: "主品"
};
const rowClick = (row) => {
detailQueryParams.value = {
brand: row.zbjQdType && [row.zbjQdType], // 直播间
taste: row.flavorErp && [row.flavorErp], // 口味
spec: row.specNameErp && [row.specNameErp], // 规格
seriesPrdMap: [], // TODO:行里没有系列字段等会看下
date: queryParams.value.date, // 日期
pageNum: 1,
pageSize: 10
}
// 口味
row.flavorErp && (detailQueryParams.value.taste = [row.flavorErp])
// 规格
row.specNameErp && (detailQueryParams.value.spec = [row.specNameErp])
// 系列+商品
row.seriesId && (detailQueryParams.value.seriesPrdMap = [{ value: row.seriesId, label: row.seriesName }])
// 日期
detailQueryParams.value.date = queryParams.value.date
detailQueryParams.value.pageNum = 1
detailQueryParams.value.pageSize = 10
detailVisible.value = true
getDetailList()
}
const getDetailList = async () => {
const { data: { list, total } } = await getFinanceDetailAPI(detailQueryParams.value)
detailList.value = list
detailTotal.value = total
}
const detailFormatter = (row, column, value) => {
if (['tradeTime', 'payTime', 'consignTime'].includes(column.property)) {
return parseTime(value, '{y}-{m}-{d} {h}:{i}:{s}')
} else if (['tradeStatus'].includes(column.property)) {
return orderStatus[value]
} else if (['goodsType'].includes(column.property)) {
return goodsType[value]
} else if (['giftType'].includes(column.property)) {
return giftType[value]
}
return value
}
const changeShowOver = () => {
showOverFlowToolTip.value = !showOverFlowToolTip.value
}
</script>
<style scoped
......@@ -418,6 +568,22 @@ const detailColumns = ref([
::v-deep(.el-cascader) {
width: 460px !important;
}
}
.dialog-footer {
.el-row {
display: flex;
justify-content: flex-end;
align-items: center;
.semi-btn {
margin-right: 20px;
}
.pagination-container {
margin: 0 !important;
height: auto !important;
}
}
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论