增加每日推送的导出和排序
This commit is contained in:
@@ -4,6 +4,7 @@ namespace app\admin\controller\mall;
|
|||||||
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use app\common\library\MallDailyPushBackfill;
|
use app\common\library\MallDailyPushBackfill;
|
||||||
|
use app\common\library\MallDailyPushExport;
|
||||||
use app\common\controller\Backend;
|
use app\common\controller\Backend;
|
||||||
use support\Response;
|
use support\Response;
|
||||||
use Webman\Http\Request;
|
use Webman\Http\Request;
|
||||||
@@ -35,6 +36,11 @@ class DailyPush extends Backend
|
|||||||
'create_time',
|
'create_time',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exportCount 与 export 共用导出权限
|
||||||
|
*/
|
||||||
|
protected array $noNeedPermission = ['exportCount'];
|
||||||
|
|
||||||
public function initialize(): void
|
public function initialize(): void
|
||||||
{
|
{
|
||||||
parent::initialize();
|
parent::initialize();
|
||||||
@@ -59,6 +65,73 @@ class DailyPush extends Backend
|
|||||||
return $this->_index();
|
return $this->_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出筛选结果条数预览
|
||||||
|
*/
|
||||||
|
public function exportCount(Request $request): Response
|
||||||
|
{
|
||||||
|
$response = $this->initializeBackend($request);
|
||||||
|
if ($response !== null) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->auth->check('mall/dailyPush/export')) {
|
||||||
|
return $this->error(__('You have no permission'), [], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
[$where, $alias] = $this->buildExportQueryParts();
|
||||||
|
$count = $this->model->alias($alias)->where($where)->count();
|
||||||
|
$exporter = new MallDailyPushExport();
|
||||||
|
return $this->success('', [
|
||||||
|
'count' => $count,
|
||||||
|
'max_limit' => $exporter->getMaxExportLimit(),
|
||||||
|
]);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出 Excel(CSV 流式写入,兼容 Excel 打开)
|
||||||
|
*/
|
||||||
|
public function export(Request $request): Response
|
||||||
|
{
|
||||||
|
$response = $this->initializeBackend($request);
|
||||||
|
if ($response !== null) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fieldsRaw = $request->post('fields', $request->get('fields', []));
|
||||||
|
$fields = is_array($fieldsRaw) ? $fieldsRaw : explode(',', strval($fieldsRaw));
|
||||||
|
$limitRaw = strval($request->post('export_limit', $request->get('export_limit', '1000')));
|
||||||
|
if (!is_numeric($limitRaw)) {
|
||||||
|
return $this->error(__('Parameter error'));
|
||||||
|
}
|
||||||
|
$limit = intval($limitRaw);
|
||||||
|
if ($limit < 1) {
|
||||||
|
return $this->error(__('Parameter error'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
[$where, $alias, $order] = $this->buildExportQueryParts();
|
||||||
|
$lang = strval($request->header('think-lang', 'zh-cn'));
|
||||||
|
$exporter = new MallDailyPushExport();
|
||||||
|
return $exporter->export($this->model, $where, $alias, $order, $fields, $limit, $lang);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{0: array, 1: array, 2: array}
|
||||||
|
*/
|
||||||
|
private function buildExportQueryParts(): array
|
||||||
|
{
|
||||||
|
[$where, $alias, , $order] = $this->queryBuilder();
|
||||||
|
return [$where, $alias, $order];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按历史 mall_daily_push 记录回补用户信息
|
* 按历史 mall_daily_push 记录回补用户信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -9,4 +9,18 @@ export default {
|
|||||||
lifetime_total_withdraw: 'Lifetime total withdraw',
|
lifetime_total_withdraw: 'Lifetime total withdraw',
|
||||||
create_time: 'Created at',
|
create_time: 'Created at',
|
||||||
'quick Search Fields': 'ID',
|
'quick Search Fields': 'ID',
|
||||||
|
export_excel: 'Export Excel',
|
||||||
|
export_title: 'Export daily push data',
|
||||||
|
export_tip: 'Exports data using the current filters and sort order. The server writes in batches to avoid freezing on large datasets.',
|
||||||
|
export_fields: 'Export fields',
|
||||||
|
export_select_all: 'Select all',
|
||||||
|
export_clear_all: 'Clear all',
|
||||||
|
export_limit: 'Export limit',
|
||||||
|
export_all_matched: 'All matched',
|
||||||
|
export_matched_count: '{count} record(s) match the current filters',
|
||||||
|
export_actual_count: 'will export {count} record(s)',
|
||||||
|
export_large_warning: 'Large export may take a while. Maximum {max} records per export.',
|
||||||
|
export_confirm: 'Start export',
|
||||||
|
export_success: 'Successfully exported {count} record(s)',
|
||||||
|
export_failed: 'Export failed, please try again later',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,19 @@ export default {
|
|||||||
lifetime_total_withdraw: '历史总提现',
|
lifetime_total_withdraw: '历史总提现',
|
||||||
create_time: '创建时间',
|
create_time: '创建时间',
|
||||||
'quick Search Fields': 'ID',
|
'quick Search Fields': 'ID',
|
||||||
|
export_excel: 'Excel导出',
|
||||||
|
export_title: '导出每日推送数据',
|
||||||
|
export_tip: '将按当前列表筛选条件与排序导出数据;采用服务端分批写入,避免一次性加载导致卡顿。',
|
||||||
|
export_fields: '导出字段',
|
||||||
|
export_select_all: '全选',
|
||||||
|
export_clear_all: '清空',
|
||||||
|
export_limit: '导出条数',
|
||||||
|
export_all_matched: '全部匹配',
|
||||||
|
export_matched_count: '当前筛选条件下共 {count} 条',
|
||||||
|
export_actual_count: '实际将导出 {count} 条',
|
||||||
|
export_large_warning: '导出条数较多,可能需要等待较长时间;单次最多导出 {max} 条。',
|
||||||
|
export_confirm: '开始导出',
|
||||||
|
export_success: '已成功导出 {count} 条数据',
|
||||||
|
export_failed: '导出失败,请稍后重试',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,31 @@
|
|||||||
<TableHeader
|
<TableHeader
|
||||||
:buttons="['refresh', 'comSearch', 'quickSearch', 'columnDisplay']"
|
:buttons="['refresh', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('mall.dailyPush.quick Search Fields') })"
|
:quick-search-placeholder="t('Quick search placeholder', { fields: t('mall.dailyPush.quick Search Fields') })"
|
||||||
></TableHeader>
|
>
|
||||||
|
<template #refreshAppend>
|
||||||
|
<el-tooltip v-if="baTable.auth('export')" :content="t('mall.dailyPush.export_excel')" placement="top">
|
||||||
|
<el-button v-blur class="table-header-operate btns-ml-12" type="success" @click="exportVisible = true">
|
||||||
|
<Icon name="fa fa-file-excel-o" />
|
||||||
|
<span class="table-header-operate-text">{{ t('mall.dailyPush.export_excel') }}</span>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</TableHeader>
|
||||||
|
|
||||||
<Table ref="tableRef"></Table>
|
<Table ref="tableRef"></Table>
|
||||||
|
<ExportDialog v-model="exportVisible" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, provide, useTemplateRef } from 'vue'
|
import { onMounted, provide, ref, useTemplateRef } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { baTableApi } from '/@/api/common'
|
import { baTableApi } from '/@/api/common'
|
||||||
import MallPageIntro from '/@/components/mall/MallPageIntro.vue'
|
import MallPageIntro from '/@/components/mall/MallPageIntro.vue'
|
||||||
import TableHeader from '/@/components/table/header/index.vue'
|
import TableHeader from '/@/components/table/header/index.vue'
|
||||||
import Table from '/@/components/table/index.vue'
|
import Table from '/@/components/table/index.vue'
|
||||||
import baTableClass from '/@/utils/baTable'
|
import baTableClass from '/@/utils/baTable'
|
||||||
|
import ExportDialog from './exportDialog.vue'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'mall/dailyPush',
|
name: 'mall/dailyPush',
|
||||||
@@ -27,6 +38,7 @@ defineOptions({
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const tableRef = useTemplateRef('tableRef')
|
const tableRef = useTemplateRef('tableRef')
|
||||||
|
const exportVisible = ref(false)
|
||||||
|
|
||||||
const baTable = new baTableClass(
|
const baTable = new baTableClass(
|
||||||
new baTableApi('/admin/mall.DailyPush/'),
|
new baTableApi('/admin/mall.DailyPush/'),
|
||||||
@@ -67,21 +79,21 @@ const baTable = new baTableClass(
|
|||||||
prop: 'yesterday_win_loss_net',
|
prop: 'yesterday_win_loss_net',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
operator: 'RANGE',
|
operator: 'RANGE',
|
||||||
sortable: false,
|
sortable: 'custom',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('mall.dailyPush.yesterday_total_deposit'),
|
label: t('mall.dailyPush.yesterday_total_deposit'),
|
||||||
prop: 'yesterday_total_deposit',
|
prop: 'yesterday_total_deposit',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
operator: 'RANGE',
|
operator: 'RANGE',
|
||||||
sortable: false,
|
sortable: 'custom',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('mall.dailyPush.lifetime_total_deposit'),
|
label: t('mall.dailyPush.lifetime_total_deposit'),
|
||||||
prop: 'lifetime_total_deposit',
|
prop: 'lifetime_total_deposit',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
operator: 'RANGE',
|
operator: 'RANGE',
|
||||||
sortable: false,
|
sortable: 'custom',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('mall.dailyPush.lifetime_total_withdraw'),
|
label: t('mall.dailyPush.lifetime_total_withdraw'),
|
||||||
@@ -89,7 +101,7 @@ const baTable = new baTableClass(
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
minWidth: 95,
|
minWidth: 95,
|
||||||
operator: 'RANGE',
|
operator: 'RANGE',
|
||||||
sortable: false,
|
sortable: 'custom',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('mall.dailyPush.create_time'),
|
label: t('mall.dailyPush.create_time'),
|
||||||
|
|||||||
Reference in New Issue
Block a user