li.shaoyi 7 月之前
父節點
當前提交
d1fbdf1e6d

二進制
public/favicon.ico


+ 10 - 0
src/constants/report.ts

@@ -44,4 +44,14 @@ export function getQuarterList() {
         { label: '第三季度', value: Quarter.Third },
         { label: '第四季度', value: Quarter.Fourth },
     ]
+}
+
+/**
+ * 获取季度名称
+ * @param value 
+ * @returns 
+ */
+export function getQuarterName(value?: number) {
+    const item = getQuarterList().find((e) => e.value === value)
+    return item?.label ?? value
 }

+ 9 - 9
src/hooks/datatable-v2/index.ts

@@ -62,16 +62,16 @@ export function useDataFilter<T>(defaultOption: FilterOption<T, keyof T>) {
 
     const queryParams = computed(() => getQueryParams())
 
-    // 重置所有过滤条件
-    const resetFilters = () => {
-        const { filters } = _.cloneDeep(defaultOption)
-
-        const items = filters.map((defaultItem, index) => {
-            const currentItem = filterOption.filters[index]
-            return currentItem.locked ? currentItem : defaultItem
+    // 重置过滤条件
+    const resetFilters = (...fields: (keyof T)[]) => {
+        defaultOption.filters.forEach((defaultItem, index) => {
+            if (!defaultItem.locked) {
+                const currentItem = filterOption.filters[index]
+                if (!fields.length || fields.includes(defaultItem.field)) {
+                    currentItem.value = defaultItem.value
+                }
+            }
         })
-
-        filterOption.filters = items
     }
 
     // 获取过滤参数,支持多条件查询

+ 1 - 1
src/hooks/enum/index.ts

@@ -58,7 +58,7 @@ export function useEnum(code: string) {
         })
 
         return result.map((e) => ({
-            label: e.enumdicname,
+            label: e[localizedKey].toString(),
             value: e.enumitemname
         }))
     }

+ 0 - 1
src/packages/pc/assets/themes/base/reset.less

@@ -37,7 +37,6 @@ body {
 
         &:hover {
             color: inherit;
-            text-decoration: underline;
         }
 
         &:focus {

+ 1 - 1
src/packages/pc/components/base/pagination/index.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="app-pagination">
         <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.index"
-            :pager-count="7" :page-sizes="[20, 30, 40]" :page-size="page.size"
+            :pager-count="7" :page-sizes="[10, 20, 30, 40]" :page-size="page.size"
             layout="total, sizes, prev, pager, next, jumper," :total="total" background>
         </el-pagination>
     </div>

+ 29 - 5
src/packages/pc/components/base/table/index.ts

@@ -6,9 +6,9 @@ import { ComposeTableOptions } from './types'
  * 组合表格函数
  * @param rowKey 表格主键key
  */
-export function useComposeTable<T>({ rowKey }: ComposeTableOptions<T>) {
+export function useComposeTable<T>({ rowKey, sumText, summaryFields }: ComposeTableOptions<T>) {
     // 表格选中的行数据
-    const record = ref<T>()
+    const selectedRow = ref<T>()
 
     // 表格展开行,对应 row-key 中的值
     const expandKeys = shallowRef<T[keyof T][]>([])
@@ -28,7 +28,7 @@ export function useComposeTable<T>({ rowKey }: ComposeTableOptions<T>) {
         } else {
             expandKeys.value = [keyValue]
         }
-        record.value = row
+        selectedRow.value = row
     }
 
     // 表格右键事件
@@ -37,7 +37,7 @@ export function useComposeTable<T>({ rowKey }: ComposeTableOptions<T>) {
         event.preventDefault()
 
         // 表格选中的行数据
-        record.value = row
+        selectedRow.value = row
 
         // 显示表格右键菜单
         contextmenu.value = {
@@ -47,12 +47,36 @@ export function useComposeTable<T>({ rowKey }: ComposeTableOptions<T>) {
         }
     }
 
+    // 自定义合计行数据
+    const getSummaries = ({ columns, data }: { columns: TableColumnCtx<T>[]; data: []; }) => {
+        const sums: string[] = []
+        columns.forEach((column, index) => {
+            if (index === 0) {
+                sums[index] = sumText || '合计'
+                return
+            }
+
+            const fields = summaryFields?.map((field) => typeof field === 'string' ? { fieldName: field } : field)
+            const field = fields?.find((field) => field.fieldName === column.property)
+
+            if (field) {
+                const total = data.reduce((prev, curr) => prev + curr[column.property], 0)
+                sums[index] = total.toFixed(field.decimals ?? 2)
+            } else {
+                sums[index] = '--'
+            }
+        })
+
+        return sums
+    }
+
     return {
         rowKey,
         expandKeys,
-        record,
+        selectedRow,
         contextmenu,
         rowClick,
         rowContextmenu,
+        getSummaries
     }
 }

+ 2 - 0
src/packages/pc/components/base/table/types.ts

@@ -4,4 +4,6 @@
 export interface ComposeTableOptions<T> {
     rowKey: keyof T;
     columnKey?: string;
+    sumText?: string; // 显示摘要行第一列的文本
+    summaryFields?: (string | { fieldName: string; decimals?: number; })[]; // 合计行字段
 }

+ 4 - 4
src/packages/pc/components/layouts/header/index.vue

@@ -13,13 +13,13 @@
         </div>
         <div class="app-header__right">
             <slot name="right"></slot>
-            <div class="iconbar">
-                <!-- <el-badge type="danger" is-dot>
+            <!-- <div class="iconbar">
+                <el-badge type="danger" is-dot>
                     <span class="g-icon--notice"></span>
-                </el-badge> -->
+                </el-badge>
                 <span class="g-icon--minimize" @click="exitFullSreen" v-if="fullScreen"></span>
                 <span class="g-icon--maximize" @click="setFullSreen" v-else></span>
-            </div>
+            </div> -->
             <el-dropdown class="user-dropdown" trigger="click">
                 <span class="g-icon--language"></span>
                 <template #dropdown>

+ 20 - 4
src/packages/pc/views/account/fundacct/components/edit/index.vue

@@ -26,8 +26,9 @@
                                     <span v-if="row.tradeMode === 79">买大厅权限:可挂</span>
                                     <template v-else-if="row.tradeMode === 17 && row.tradeProperty === 4">
                                         <el-select v-model="row.dtype">
-                                            <template v-for="(value, key) in data.marketbstype" :key="key">
-                                                <el-option :label="value" :value="Number(key)" />
+                                            <template v-for="item in getMarketbstypeOptions(row.fdType)"
+                                                :key="item.value">
+                                                <el-option :label="item.label" :value="item.value" />
                                             </template>
                                         </el-select>
                                     </template>
@@ -42,8 +43,9 @@
                                     <span v-if="[77, 78].includes(row.tradeMode)">卖大厅权限:可挂</span>
                                     <template v-else-if="row.tradeProperty === 4">
                                         <el-select v-model="row.spotRightType">
-                                            <template v-for="(value, key) in data.marketbstype" :key="key">
-                                                <el-option :label="value" :value="Number(key)" />
+                                            <template v-for="item in getMarketbstypeOptions(row.fspotRightType)"
+                                                :key="item.value">
+                                                <el-option :label="item.label" :value="item.value" />
                                             </template>
                                         </el-select>
                                     </template>
@@ -93,6 +95,7 @@ const props = defineProps({
 })
 
 const mainaccounttypeEnum = useEnum('mainaccounttype') // 账户类型
+const marketbstypeEnum = useEnum('marketbstype')
 
 const t = i18n.global.t
 const tableRef = ref<TableInstance>()
@@ -140,6 +143,19 @@ const { loading } = useRequest(queryTaAccountDetail, {
     }
 })
 
+const getMarketbstypeOptions = (type: number) => {
+    switch (type) {
+        case 1:
+            return marketbstypeEnum.getEnumOptions()
+        case 2:
+            return marketbstypeEnum.getEnumOptions([1, 3], true)
+        case 3:
+            return marketbstypeEnum.getEnumOptions([1, 2], true)
+        default:
+            return marketbstypeEnum.getEnumOptions(0)
+    }
+}
+
 const handleSelectionChange = (selection: Model.UpdateTaAccountReq['dtype']) => {
     multipleSelection.value = selection
 }

+ 3 - 3
src/packages/pc/views/investor/manage/user/index.vue

@@ -42,7 +42,7 @@ import { i18n } from '@/stores'
 const { global: { t } } = i18n
 
 // 是否实名
-const flagEnum = useEnum('flag')
+const hasauthEnum = useEnum('hasauth')
 // 状态
 const areastatusEnum = useEnum('areastatus')
 // 变更状态
@@ -71,7 +71,7 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
     { field: 'memberUserName', label: 'investor.manage.user.memberUserName' },
     { field: 'parentName', label: 'investor.manage.user.parentName' },
     { field: 'refereeName', label: 'investor.manage.user.refereeName' },
-    { field: 'hasAuth', label: 'investor.manage.user.isAuth', formatValue: (val) => flagEnum.getEnumTypeName(val) },
+    { field: 'hasAuth', label: 'investor.manage.user.isAuth', formatValue: (val) => hasauthEnum.getEnumTypeName(val) },
     { field: 'accountStatus', label: 'investor.manage.user.accountStatus', formatValue: (val) => areastatusEnum.getEnumTypeName(val) },
     { field: 'modifyStatus', label: 'investor.manage.user.modifyStatus', formatValue: (val) => modifystatusEnum.getEnumTypeName(val) },
     { field: 'createTime', label: 'investor.manage.user.createTime', formatValue: (val) => formatDate(val) },
@@ -95,7 +95,7 @@ filterOptons.selectList = [
     {
         key: 'hasAuth',
         label: t('investor.manage.user.isAuth'),
-        options: () => flagEnum.getEnumOptions(),
+        options: () => hasauthEnum.getEnumOptions(),
     }
 ]
 

+ 1 - 1
src/packages/pc/views/report/goods/index.vue

@@ -38,7 +38,7 @@
 <script lang="ts" setup>
 import { shallowRef, computed } from 'vue'
 import { ElMessage } from 'element-plus'
-import { formatDate, parsePercent, handleNumberValue } from '@/filters'
+import { formatDate, parsePercent } from '@/filters'
 import { useDataFilter } from '@/hooks/datatable-v2'
 import { useRequest } from '@/hooks/request'
 import { useOperation } from '@/hooks/operation'

+ 122 - 0
src/packages/pc/views/report/instprofitshare/components/details/index.vue

@@ -0,0 +1,122 @@
+<!-- 报表查询-机构分润报表-机构分润单据明细 -->
+<template>
+    <app-drawer title="机构分润单据明细" width="960" v-model:show="show">
+        <app-table :data="dataList" :columns="tableColumns">
+            <!-- 源账户 -->
+            <template #accountid="{ row }">
+                {{ `${row.relateduserid}/${row.accountname}/${row.accountid}` }}
+            </template>
+            <template #footer>
+                <app-pagination :total="total" v-model:page-size="pageSize" v-model:page-index="pageIndex"
+                    @change="getDataList" />
+            </template>
+        </app-table>
+        <template #footer>
+            <el-button @click="onCancel">{{ t('operation.close') }}</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+import { handleNumberValue } from '@/filters'
+import { useEnum } from '@/hooks/enum'
+import { ReportType } from '@/constants/report'
+import { useRequest } from '@/hooks/request'
+import { queryDODPage } from '@/services/api/report'
+import { i18n } from '@/stores'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+import AppTable from '@pc/components/base/table/index.vue'
+import AppPagination from '@pc/components/base/pagination/index.vue'
+import moment from 'moment'
+
+const props = defineProps({
+    queryParams: {
+        type: Object as PropType<Model.ShareAmountQueryReq>,
+        required: true
+    },
+    record: {
+        type: Object as PropType<Model.ShareAmountQueryRsp>,
+        required: true
+    }
+})
+
+const dividetypeEnum = useEnum('dividetype') // 分润算法
+
+const t = i18n.global.t
+const show = shallowRef(true)
+const qs: Partial<Model.DODPageReq> = {}
+
+const { dataList, total, pageSize, pageIndex, run } = useRequest(queryDODPage, {
+    manual: true,
+    params: {
+        areaaccountid: props.record.areaaccountid,
+        areaid: props.record.areaid,
+        areatype: props.record.areatype,
+        goodsid: props.record.goodsid,
+        memberuserid: props.record.memberuserid,
+        pageNum: 1,
+        pageSize: 10,
+        parentuserid: props.record.parentuserid,
+        searchtype: props.record.searchtype,
+        tradefeetype: props.record.tradefeetype,
+        tradeproperty: props.record.tradeproperty
+    },
+    onError: (err) => {
+        ElMessage.error(err)
+    }
+})
+
+const tableColumns = shallowRef<Model.TableColumn[]>([
+    { field: 'accountid', label: '源账户', width: 300 },
+    { field: 'feeamount', label: '总费用金额' },
+    { field: 'dividetype', label: '分润算法', formatValue: (val) => dividetypeEnum.getEnumTypeName(val) },
+    { field: 'dividevalue', label: '分配值', formatValue: (val) => handleNumberValue(val) },
+    { field: 'divideamount', label: '分润金额' }
+])
+
+const getDataList = () => run(qs)
+
+const onCancel = () => {
+    show.value = false
+}
+
+onMounted(() => {
+    const { cycletype, tradedate, quarter } = props.queryParams
+    const date = moment(tradedate, 'YYYYMMDD')
+
+    switch (cycletype) {
+        case ReportType.Week: {
+            qs.startDate = date.startOf('isoWeek').format('YYYYMMDD') // 获取本周的星期一
+            qs.endDate = date.endOf('isoWeek').format('YYYYMMDD') // 获取本周的星期天
+            break
+        }
+        case ReportType.Month: {
+            qs.startDate = date.startOf('month').format('YYYYMMDD') // 获取本月的第一天
+            qs.endDate = date.endOf('month').format('YYYYMMDD') // 获取本月的最后一天
+            break
+        }
+        case ReportType.Quarter: {
+            // 定义季度的起始月份(0-11,所以第三季度从7月开始)
+            const startMonth = (quarter - 1) * 3
+            const endMonth = startMonth + 2 // 第三季度结束于9月
+            // 获取季度的第一天
+            const startDate = moment([tradedate, startMonth, 1])
+            // 获取季度的最后一天
+            const endDate = moment([tradedate, endMonth]).endOf('month')
+
+            qs.startDate = startDate.format('YYYYMMDD')
+            qs.endDate = endDate.format('YYYYMMDD')
+            break
+        }
+        case ReportType.Year: {
+            qs.startDate = tradedate + '0101'
+            qs.endDate = tradedate + '1231'
+            break
+        }
+    }
+
+    getDataList()
+})
+</script>

+ 180 - 0
src/packages/pc/views/report/instprofitshare/index.vue

@@ -0,0 +1,180 @@
+<!-- 报表查询-机构分润报表 -->
+<template>
+    <app-view>
+        <template #header>
+            <app-filter :option="filterOption">
+                <!-- 日期 -->
+                <template #tradedate="{ item }">
+                    <el-form-item :label="item.label" prop="tradedate">
+                        <el-date-picker :type="dateType" v-model="item.value" :format="dateFormat"
+                            :value-format="dateFormat" :placeholder="t('common.pleasechoice')" />
+                    </el-form-item>
+                </template>
+                <!-- 季度 -->
+                <template #quarter="{ item }">
+                    <el-form-item :label="item.label" prop="quarter"
+                        v-if="queryParams.cycletype === ReportType.Quarter">
+                        <el-select v-model="item.value">
+                            <el-option v-for="option in getQuarterList()" :key="option.value" :label="option.label"
+                                :value="option.value" />
+                        </el-select>
+                    </el-form-item>
+                    <template v-else>
+                        {{ (item.value = undefined) }}
+                    </template>
+                </template>
+                <!-- 是否包含子机构 -->
+                <template #isson="{ item }">
+                    <el-form-item :label="item.label" prop="isson">
+                        <el-switch v-model="item.value" active-value="1" inactive-value="0" />
+                    </el-form-item>
+                </template>
+            </app-filter>
+        </template>
+        <app-table :data="dataList" :columns="tableColumns" :loading="loading" :highlight-current-row="false"
+            :span-method="objectSpanMethod" :summary-method="getSummaries" show-summary>
+            <template #headerLeft>
+                <app-operation :data-list="getActionButtons(['query_internal_profitshare_export'])"
+                    @click="(code: string) => openComponent(code)" />
+            </template>
+            <!-- 商品/市场 -->
+            <template #goodsname="{ row }">
+                <el-link type="primary" @click="openComponent('Details', row)">{{ row.goodsname }}</el-link>
+            </template>
+        </app-table>
+        <component :is="componentMap.get(componentId)" v-bind="{ record, queryParams }" @closed="closeComponent"
+            v-if="componentId" />
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref, defineAsyncComponent } from 'vue'
+import { ElMessage } from 'element-plus'
+import { useEnum } from '@/hooks/enum'
+import { useDataFilter } from '@/hooks/datatable-v2'
+import { useRequest } from '@/hooks/request'
+import { formatDate } from '@/filters'
+import { shareAmountQuery } from '@/services/api/report'
+import { useOperation } from '@/hooks/operation'
+import { i18n } from '@/stores'
+import { getReportTypeList, ReportType, getQuarterList } from '@/constants/report'
+import { useComposeTable } from '@pc/components/base/table'
+import AppTable from '@pc/components/base/table/index.vue'
+import AppOperation from '@pc/components/base/operation/index.vue'
+import AppFilter from '@pc/components/base/table-filter-v2/index.vue'
+
+const roleTypeEnum = useEnum('roleType') // 角色
+const divideFeekindEnum = useEnum('divide_feekind') // 费用类型
+
+const { global: { t } } = i18n
+
+const { getSummaries } = useComposeTable<Model.ShareAmountQueryRsp>({
+    rowKey: 'areaaccountid',
+    sumText: '汇总',
+    summaryFields: [{ fieldName: 'totalcount', decimals: 0 }, 'totalfee', 'divideamount']
+})
+
+const { componentMap, componentId, record, openComponent, closeComponent, getActionButtons } = useOperation<Model.ShareAmountQueryRsp>()
+
+// 机构分润单据明细
+componentMap.set('Details', defineAsyncComponent(() => import('./components/details/index.vue')))
+
+const { dataList, loading, run } = useRequest(shareAmountQuery, {
+    manual: true,
+    onError: (err) => {
+        ElMessage.error(err)
+    }
+})
+
+// 计算行合并值
+const objectSpanMethod = (data: { rowIndex: number; columnIndex: number; }) => {
+    if (data.columnIndex < 2) {
+        if (data.rowIndex === 0) {
+            return {
+                rowspan: dataList.value.length,
+                colspan: 1,
+            }
+        } else {
+            return {
+                rowspan: 0,
+                colspan: 0,
+            }
+        }
+    }
+}
+
+const { queryParams, filterOption, getQueryParams, resetFilters } = useDataFilter<Model.ShareAmountQueryReq>({
+    filters: [
+        {
+            field: 'cycletype',
+            label: t('report.profitshare.cycletype'),
+            value: 0,
+            options: () => getReportTypeList(),
+            onChange: () => resetFilters('tradedate', 'quarter')
+        },
+        {
+            field: 'tradedate',
+            label: t('report.profitshare.tradedate'),
+            required: true
+        },
+        {
+            field: 'quarter',
+            label: t('report.profitshare.quarter'),
+            required: true
+        },
+        {
+            field: 'isson',
+            label: t('report.profitshare.isson'),
+            value: 0
+        }
+    ],
+    buttons: [
+        { label: t('operation.search'), className: 'el-button--primary', onClick: () => onSearch() },
+        { label: t('operation.reset'), className: 'el-button--primary', validateEvent: false, onClick: () => resetFilters() }
+    ]
+})
+
+// 日期类型
+const dateType = computed(() => {
+    switch (queryParams.value.cycletype) {
+        case ReportType.Week:
+            return 'week'
+        case ReportType.Month:
+            return 'month'
+        case ReportType.Quarter:
+        case ReportType.Year:
+            return 'year'
+        default:
+            return 'date'
+    }
+})
+
+// 日期格式
+const dateFormat = computed(() => {
+    switch (queryParams.value.cycletype) {
+        case ReportType.Month:
+            return 'YYYYMM'
+        case ReportType.Quarter:
+        case ReportType.Year:
+            return 'YYYY'
+        default:
+            return 'YYYYMMDD'
+    }
+})
+
+const tableColumns = ref<Model.TableColumn[]>([
+    { field: 'areatype', label: 'report.profitshare.areatype', formatValue: (val) => roleTypeEnum.getEnumTypeName(val) },
+    { field: 'areaaccountid', label: 'report.profitshare.areaaccountid' },
+    { field: 'goodsname', label: 'report.profitshare.goodsname' },
+    { field: 'tradefeetype', label: 'report.profitshare.searchtype', formatValue: (val) => divideFeekindEnum.getEnumTypeName(val) },
+    { field: 'totalcount', label: 'report.profitshare.totalcount' },
+    { field: 'totalfee', label: 'report.profitshare.totalfee' },
+    { field: 'divideamount', label: 'report.profitshare.divideamount' }
+])
+
+const onSearch = () => {
+    const qs = getQueryParams()
+    qs.tradedate = formatDate(qs.tradedate, dateFormat.value) // 处理日期格式
+    run(qs)
+}
+</script>

+ 126 - 0
src/packages/pc/views/report/profitshare/components/details/index.vue

@@ -0,0 +1,126 @@
+<!-- 报表查询-平台分润报表-机构分润统计明细 -->
+<template>
+    <teleport to="#appPageTeleport">
+        <app-view>
+            <app-table :data="dataList" :columns="tableColumns" :loading="loading" :highlight-current-row="false"
+                :span-method="objectSpanMethod" :summary-method="getSummaries" show-summary>
+                <template #headerLeft>
+                    <span>{{ `${formatDate}【${record.areaname}】分润明细月报表` }}</span>
+                </template>
+                <template #headerRight>
+                    <div>
+                        <el-button @click="emit('closed')">关闭</el-button>
+                    </div>
+                </template>
+                <!-- 商品/市场 -->
+                <template #goodsname="{ row }">
+                    <el-link type="primary" @click="showComponent('Details', row)">{{ row.goodsname }}</el-link>
+                </template>
+            </app-table>
+            <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="componentProps"
+                @closed="closeComponent" v-if="componentId" />
+        </app-view>
+    </teleport>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, PropType, computed, defineAsyncComponent } from 'vue'
+import { ElMessage } from 'element-plus'
+import { getQuarterName } from '@/constants/report'
+import { useEnum } from '@/hooks/enum'
+import { useComponent } from '@/hooks/component'
+import { useRequest } from '@/hooks/request'
+import { shareAmountQuery } from '@/services/api/report'
+import { useComposeTable } from '@pc/components/base/table'
+import moment from 'moment'
+import AppTable from '@pc/components/base/table/index.vue'
+
+const props = defineProps({
+    queryParams: {
+        type: Object as PropType<Model.ShareAmountQueryPlatReq>,
+        required: true
+    },
+    record: {
+        type: Object as PropType<Model.ShareAmountQueryPlatRsp>,
+        required: true
+    }
+})
+
+const emit = defineEmits(['closed'])
+
+const componentMap = new Map<string, unknown>([
+    ['Details', defineAsyncComponent(() => import('@pc/views/report/instprofitshare/components/details/index.vue'))], // 机构分润单据明细
+])
+
+const roleTypeEnum = useEnum('roleType') // 角色
+const divideFeekindEnum = useEnum('divide_feekind') // 费用类型
+
+// 组件属性
+const componentProps = reactive<{ queryParams: Partial<Model.ShareAmountQueryReq>; record: Partial<Model.ShareAmountQueryRsp>; }>({
+    queryParams: {
+        areaid: props.record.areaid,
+        cycletype: props.queryParams.cycletype,
+        tradedate: props.queryParams.tradedate,
+        quarter: props.queryParams.quarter
+    },
+    record: {}
+})
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent()
+
+const { getSummaries } = useComposeTable<Model.ShareAmountQueryRsp>({
+    rowKey: 'areaaccountid',
+    sumText: '汇总',
+    summaryFields: [{ fieldName: 'totalcount', decimals: 0 }, 'totalfee', 'divideamount']
+})
+
+const { dataList, loading } = useRequest(shareAmountQuery, {
+    params: componentProps.queryParams,
+    onError: (err) => {
+        ElMessage.error(err)
+    }
+})
+
+// 计算行合并值
+const objectSpanMethod = (data: { rowIndex: number; columnIndex: number; }) => {
+    if (data.columnIndex < 2) {
+        if (data.rowIndex === 0) {
+            return {
+                rowspan: dataList.value.length,
+                colspan: 1,
+            }
+        } else {
+            return {
+                rowspan: 0,
+                colspan: 0,
+            }
+        }
+    }
+}
+
+const tableColumns = ref<Model.TableColumn[]>([
+    { field: 'areatype', label: 'report.profitshare.areatype', formatValue: (val) => roleTypeEnum.getEnumTypeName(val) },
+    { field: 'areaaccountid', label: 'report.profitshare.areaaccountid' },
+    { field: 'goodsname', label: 'report.profitshare.goodsname' },
+    { field: 'tradefeetype', label: 'report.profitshare.searchtype', formatValue: (val) => divideFeekindEnum.getEnumTypeName(val) },
+    { field: 'totalcount', label: 'report.profitshare.totalcount' },
+    { field: 'totalfee', label: 'report.profitshare.totalfee' },
+    { field: 'divideamount', label: 'report.profitshare.divideamount' }
+])
+
+const showComponent = (code: string, row: Model.ShareAmountQueryRsp) => {
+    componentProps.record = row
+    openComponent(code)
+}
+
+const formatDate = computed(() => {
+    const { tradedate, quarter } = props.queryParams
+    const formats: { [key: number]: { parse: string; output: string } } = {
+        4: { parse: 'YYYY', output: 'YYYY年' },
+        6: { parse: 'YYYYMM', output: 'YYYY年MM月' },
+        8: { parse: 'YYYYMMDD', output: 'YYYY年MM月DD日' }
+    }
+    const { parse, output } = formats[tradedate.length]
+    return moment(tradedate, parse).format(output) + (quarter ? getQuarterName(quarter) : '')
+})
+</script>

+ 35 - 24
src/packages/pc/views/report/profitshare/index.vue

@@ -1,14 +1,16 @@
-<!-- 报表查询-分润报表 -->
+<!-- 报表查询-平台分润报表 -->
 <template>
     <app-view>
         <template #header>
             <app-filter :option="filterOption">
+                <!-- 日期 -->
                 <template #tradedate="{ item }">
                     <el-form-item :label="item.label" prop="tradedate">
                         <el-date-picker :type="dateType" v-model="item.value" :format="dateFormat"
                             :value-format="dateFormat" :placeholder="t('common.pleasechoice')" />
                     </el-form-item>
                 </template>
+                <!-- 季度 -->
                 <template #quarter="{ item }">
                     <el-form-item :label="item.label" prop="quarter"
                         v-if="queryParams.cycletype === ReportType.Quarter">
@@ -21,9 +23,16 @@
                         {{ (item.value = undefined) }}
                     </template>
                 </template>
-                <template #isson="{ item }">
-                    <el-form-item :label="item.label" prop="isson">
-                        <el-switch v-model="item.value" active-value="1" inactive-value="0" />
+                <!-- 会员代码/名称 -->
+                <template #areaname="{ item }">
+                    <el-form-item :label="item.label">
+                        <app-select-member v-model="item.value" :params="{ usertype: '1,2' }" />
+                    </el-form-item>
+                </template>
+                <!-- 所属营销中心 -->
+                <template #yxareauserid="{ item }">
+                    <el-form-item :label="item.label">
+                        <app-select-member v-model="item.value" :params="{ roles: '3' }" />
                     </el-form-item>
                 </template>
             </app-filter>
@@ -33,9 +42,9 @@
                 <app-operation :data-list="getActionButtons(['query_internal_profitshare_export'])"
                     @click="(code: string) => openComponent(code)" />
             </template>
-            <template #footer>
-                <app-pagination :total="total" v-model:page-size="pageSize" v-model:page-index="pageIndex"
-                    @change="onSearch" />
+            <!-- 会员/机构 -->
+            <template #areaname="{ row }">
+                <el-link type="primary" @click="openComponent('Details', row)">{{ row.areaname }}</el-link>
             </template>
         </app-table>
         <component :is="componentMap.get(componentId)" v-bind="{ record, queryParams }" @closed="closeComponent"
@@ -44,47 +53,47 @@
 </template>
 
 <script lang="ts" setup>
-import { computed, ref } from 'vue'
+import { computed, ref, defineAsyncComponent } from 'vue'
 import { ElMessage } from 'element-plus'
 import { useEnum } from '@/hooks/enum'
 import { useDataFilter } from '@/hooks/datatable-v2'
 import { useRequest } from '@/hooks/request'
 import { formatDate } from '@/filters'
-import { shareAmountQuery } from '@/services/api/report'
+import { shareAmountQueryPlat } from '@/services/api/report'
 import { useOperation } from '@/hooks/operation'
 import { i18n } from '@/stores'
 import { getReportTypeList, ReportType, getQuarterList } from '@/constants/report'
 import AppTable from '@pc/components/base/table/index.vue'
-import AppPagination from '@pc/components/base/pagination/index.vue'
 import AppOperation from '@pc/components/base/operation/index.vue'
 import AppFilter from '@pc/components/base/table-filter-v2/index.vue'
+import AppSelectMember from '@pc/components/modules/select-member/index.vue'
 
 const roleTypeEnum = useEnum('roleType') // 角色
 
-const { global: { t } } = i18n
+const t = i18n.global.t
 
-const { componentMap, componentId, record, openComponent, closeComponent, getActionButtons } = useOperation<Model.ShareAmountQueryRsp>({
+const { componentMap, componentId, record, openComponent, closeComponent, getActionButtons } = useOperation<Model.ShareAmountQueryPlatRsp>({
     onClose: () => onSearch()
 })
 
-const { dataList, total, pageSize, pageIndex, loading, run } = useRequest(shareAmountQuery, {
+// 机构分润统计明细
+componentMap.set('Details', defineAsyncComponent(() => import('./components/details/index.vue')))
+
+const { dataList, loading, run } = useRequest(shareAmountQueryPlat, {
     manual: true,
-    params: {
-        pageNum: 1,
-        pageSize: 20,
-    },
     onError: (err) => {
         ElMessage.error(err)
     }
 })
 
-const { queryParams, filterOption, getQueryParams, resetFilters } = useDataFilter<Model.ShareAmountQueryReq>({
+const { queryParams, filterOption, getQueryParams, resetFilters } = useDataFilter<Model.ShareAmountQueryPlatReq>({
     filters: [
         {
             field: 'cycletype',
             label: t('report.profitshare.cycletype'),
             value: 0,
-            options: () => getReportTypeList()
+            options: () => getReportTypeList(),
+            onChange: () => resetFilters('tradedate', 'quarter')
         },
         {
             field: 'tradedate',
@@ -97,9 +106,12 @@ const { queryParams, filterOption, getQueryParams, resetFilters } = useDataFilte
             required: true
         },
         {
-            field: 'isson',
-            label: t('report.profitshare.isson'),
-            value: 0
+            field: 'areaname',
+            label: '会员代码/名称',
+        },
+        {
+            field: 'yxareauserid',
+            label: '所属营销中心',
         }
     ],
     buttons: [
@@ -137,10 +149,9 @@ const dateFormat = computed(() => {
 })
 
 const tableColumns = ref<Model.TableColumn[]>([
+    { field: 'areaname', label: '会员/机构' },
     { field: 'areatype', label: 'report.profitshare.areatype', formatValue: (val) => roleTypeEnum.getEnumTypeName(val) },
     { field: 'areaaccountid', label: 'report.profitshare.areaaccountid' },
-    { field: 'goodsname', label: 'report.profitshare.goodsname' },
-    { field: 'searchtype', label: 'report.profitshare.searchtype' },
     { field: 'totalcount', label: 'report.profitshare.totalcount' },
     { field: 'totalfee', label: 'report.profitshare.totalfee' },
     { field: 'divideamount', label: 'report.profitshare.divideamount' }

+ 23 - 1
src/services/api/report/index.ts

@@ -31,7 +31,7 @@ export function queryRefUserSelect(options: CommonFetchOptions<{ request: Model.
 }
 
 /**
- * 报表管理-->分润报表
+ * 报表管理-->分润报表(机构)
  */
 export function shareAmountQuery(options: CommonFetchOptions<{ request: Partial<Model.ShareAmountQueryReq>; response: Model.ShareAmountQueryRsp[]; }>) {
     options.data = {
@@ -42,6 +42,28 @@ export function shareAmountQuery(options: CommonFetchOptions<{ request: Partial<
 }
 
 /**
+ * 报表管理-->分润报表(平台)
+ */
+export function shareAmountQueryPlat(options: CommonFetchOptions<{ request: Partial<Model.ShareAmountQueryPlatReq>; response: Model.ShareAmountQueryPlatRsp[]; }>) {
+    options.data = {
+        orgztypes: userStore.userInfo.orgztypes,
+        ...options.data
+    }
+    return httpClient.commonRequest('/reportForm/shareAmountQueryPlat', 'get', options)
+}
+
+/**
+ * 报表管理-->分润报表(机构)-->机构明细
+ */
+export function queryDODPage(options: CommonFetchOptions<{ request: Partial<Model.DODPageReq>; response: Model.DODPageRsp[]; }>) {
+    options.data = {
+        orgztypes: userStore.userInfo.orgztypes,
+        ...options.data
+    }
+    return httpClient.commonRequest('/reportForm/queryDODPage', 'get', options)
+}
+
+/**
  * 报表管理-->推荐成交报表
  */
 export function queryTrade(options: CommonFetchOptions<{ request: Model.TradeReq; response: Model.TradeRsp[]; }>) {

+ 81 - 14
src/types/model/report.d.ts

@@ -66,7 +66,7 @@ declare namespace Model {
         userid?: number
     }
 
-    /** 报表管理-->分润报表 请求 */
+    /** 报表管理-->分润报表(机构) 请求 */
     interface ShareAmountQueryReq {
         areaid: number  // 所属机构
         areaname: string
@@ -75,8 +75,6 @@ declare namespace Model {
         ismarketing: number
         isson: number // 是否包含子机构
         orgztypes: string  // 管理员所属机构角色类型
-        pageNum: number  // 页码
-        pageSize: number  // 页大小
         parentuserid: number
         quarter: number // 季度
         searchtype: number
@@ -84,16 +82,85 @@ declare namespace Model {
         yxareauserid: number // 所属营销中心
     }
 
-    /** 报表管理-->分润报表 响应 */
+    /** 报表管理-->分润报表(机构) 响应 */
     interface ShareAmountQueryRsp {
-        areaaccountid: number  // 结算资金账户
-        areaname: string   // 会员/机构 reletype == 1
-        areatype: number  // 角色
-        divideamount: number  // 分润金额
-        goodsname: string   // 商品/市场 会员/机构 reletype != 1
-        searchtype: number  // 费用类型
-        totalcount: number  // 总笔数
-        totalfee: number  // 总手续费
+        areaaccountid: number; // 结算资金账户
+        areaid: number;
+        areaname: string; // 会员/机构 reletype == 1
+        areatype: number; // 角色
+        divideamount: number; // 分润金额
+        goodsid: number;
+        goodsname: string; // 商品/市场 会员/机构 reletype != 1
+        memberuserid: number;
+        parentuserid: number;
+        searchtype: number; // 费用类型
+        totalcount: number; // 总笔数
+        totalfee: number; // 总手续费
+        tradefeetype: number;
+        tradeproperty: number;
+    }
+
+    /** 报表管理-->分润报表(平台) 请求 */
+    interface ShareAmountQueryPlatReq {
+        areaid: number; // 所属机构
+        areaname: string;
+        cycletime: string;
+        cycletype: number; // 报表类型
+        ismarketing: number;
+        isson: number; // 是否包含子机构
+        orgztypes: string; // 管理员所属机构角色类型
+        parentuserid: number;
+        quarter: number; // 季度
+        searchtype: number;
+        tradedate: string; // 日 期
+        yxareauserid: number; // 所属营销中心
+    }
+
+    /** 报表管理-->分润报表(平台) 响应 */
+    interface ShareAmountQueryPlatRsp {
+        areaaccountid: number; // 结算资金账户
+        areaid: number;
+        areaname: string; // 会员/机构 reletype == 1
+        areatype: number; // 角色
+        divideamount: number; // 分润金额
+        goodsid: number;
+        goodsname: string; // 商品/市场 会员/机构 reletype != 1
+        memberuserid: number;
+        parentuserid: number;
+        searchtype: number; // 费用类型
+        totalcount: number; // 总笔数
+        totalfee: number; // 总手续费
+        tradefeetype: number;
+        tradeproperty: number;
+    }
+
+    /** 报表管理-->分润报表(机构)-->机构明细 请求 */
+    interface DODPageReq {
+        areaaccountid: number;
+        areaid: number;
+        areatype: number;
+        endDate: string;
+        goodsid: number;
+        memberuserid: number;
+        orgztypes: string;
+        pageNum: number  // 页码
+        pageSize: number  // 页大小
+        parentuserid: number;
+        searchtype: number;
+        startDate: string;
+        tradefeetype: number;
+        tradeproperty: number;
+    }
+
+    /** 报表管理-->分润报表(机构)-->机构明细 响应 */
+    interface DODPageRsp {
+        accountid: string; // 源账户
+        accountname: string;
+        divideamount: number; // 分润金额
+        dividetype: number; // 分润算法
+        dividevalue: number; // 分配值
+        feeamount: number; // 总费用金额
+        relateduserid: number;
     }
 
     /** 报表管理-->推荐成交报表-->推荐人信息 请求 */
@@ -274,7 +341,7 @@ declare namespace Model {
         sellreceivedamount: number; // 今日已收金额(作为卖方)
         selltodayamount: number; // 今日收取金额(作为卖方)
     }
-    
+
     /** 报表管理-->交易商资金报表/机构资金报表 请求 */
     interface InvestorReportReq {
         // 交易商
@@ -593,7 +660,7 @@ declare namespace Model {
     }
 
     /** 报表管理-->服务费分润报表-->导出 请求 */
-     interface ManageDivExportReq {
+    interface ManageDivExportReq {
         // 结算银行
         cusbankname?: string
         // 结束时间