优化增加第三方【每日推送】原始数据记录日志.log

This commit is contained in:
2026-07-21 16:44:39 +08:00
parent 2fbc07329e
commit 4fbc4500fd
16 changed files with 371 additions and 143 deletions

View File

@@ -5,6 +5,7 @@ export default {
receiver_name: 'receiver name',
phone: 'phone',
region: 'region',
region_tip: 'Separate levels with commas, e.g. Kuala Lumpur,KLCC',
detail_address: 'detail_address',
default_setting: 'Default address',
'default_setting 0': '--',

View File

@@ -11,15 +11,15 @@ export default {
'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_tip: 'Exports filtered and sorted data as Excel (.xlsx). The server writes in batches and supports exporting all matched records.',
export_fields: 'Export fields',
export_select_all: 'Select all',
export_clear_all: 'Clear all',
export_limit: 'Export limit',
export_limit: 'Export limit (0 = all matched)',
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_large_warning: 'Large export may take a while. Please keep this page open.',
export_confirm: 'Start export',
export_success: 'Successfully exported {count} record(s)',
export_failed: 'Export failed, please try again later',

View File

@@ -5,6 +5,7 @@ export default {
receiver_name: '收货人',
phone: '电话',
region: '地区',
region_tip: '多个层级请用英文逗号分隔,如:广东省,广州市,天河区',
detail_address: '详细地址',
default_setting: '默认地址',
'default_setting 0': '--',

View File

@@ -11,15 +11,15 @@ export default {
'quick Search Fields': 'ID',
export_excel: 'Excel导出',
export_title: '导出每日推送数据',
export_tip: '将按当前列表筛选条件与排序导出数据;采用服务端分批写入,避免一次性加载导致卡顿。',
export_tip: '将按当前列表筛选条件与排序导出为 Excel.xlsx服务端分批写入支持导出全部匹配数据。',
export_fields: '导出字段',
export_select_all: '全选',
export_clear_all: '清空',
export_limit: '导出条数',
export_limit: '导出条数0 表示全部匹配)',
export_all_matched: '全部匹配',
export_matched_count: '当前筛选条件下共 {count} 条',
export_actual_count: '实际将导出 {count} 条',
export_large_warning: '导出条数较多,可能需要等待较长时间;单次最多导出 {max} 条。',
export_large_warning: '导出条数较多,可能需要等待较长时间,请勿关闭页面。',
export_confirm: '开始导出',
export_success: '已成功导出 {count} 条数据',
export_failed: '导出失败,请稍后重试',

View File

@@ -50,6 +50,17 @@ const formatRegion = (raw: string) => {
return s.replace(/[,\s]+/g, ',')
}
const normalizeRegionInput = (raw: unknown) => {
const s = String(raw ?? '').trim()
if (!s) return ''
return s
.replace(//g, ',')
.split(',')
.map((part) => part.trim())
.filter(Boolean)
.join(',')
}
/**
* baTable 内包含了表格的所有数据且数据具备响应性,然后通过 provide 注入给了后代组件
*/
@@ -145,6 +156,15 @@ const baTable = new baTableClass(
},
{
defaultItems: {},
},
{
onSubmit: () => {
const items = baTable.form.items
if (items && items.region !== undefined && items.region !== null) {
items.region = normalizeRegionInput(items.region)
}
return true
},
}
)

View File

@@ -53,10 +53,10 @@
/>
<FormItem
:label="t('mall.address.region')"
type="city"
type="string"
v-model="baTable.form.items!.region"
prop="region"
:placeholder="t('Please select field', { field: t('mall.address.region') })"
:placeholder="t('mall.address.region_tip')"
/>
<FormItem
:label="t('mall.address.detail_address')"

View File

@@ -32,7 +32,7 @@
<div class="export-section">
<div class="section-title">{{ t('mall.dailyPush.export_limit') }}</div>
<div class="limit-row">
<el-input-number v-model="form.exportLimit" :min="1" :max="maxLimit" :step="1000" controls-position="right" />
<el-input-number v-model="form.exportLimit" :min="0" :max="matchedCount || undefined" :step="1000" controls-position="right" />
<div class="limit-presets">
<el-button
v-for="preset in limitPresets"
@@ -43,19 +43,19 @@
>
{{ preset }}
</el-button>
<el-button size="small" :type="form.exportLimit === matchedCount ? 'primary' : 'default'" @click="useMatchedCount">
<el-button size="small" :type="form.exportLimit === 0 ? 'primary' : 'default'" @click="useMatchedCount">
{{ t('mall.dailyPush.export_all_matched') }}
</el-button>
</div>
</div>
<div class="count-info" v-loading="countLoading">
{{ t('mall.dailyPush.export_matched_count', { count: matchedCount }) }}
<span v-if="actualExportCount < form.exportLimit">
<span v-if="actualExportCount > 0">
{{ t('mall.dailyPush.export_actual_count', { count: actualExportCount }) }}
</span>
</div>
<el-alert v-if="form.exportLimit > 10000" type="warning" :closable="false" class="large-export-warning">
{{ t('mall.dailyPush.export_large_warning', { max: maxLimit }) }}
<el-alert v-if="actualExportCount > 10000" type="warning" :closable="false" class="large-export-warning">
{{ t('mall.dailyPush.export_large_warning') }}
</el-alert>
</div>
@@ -84,7 +84,6 @@ const visible = defineModel<boolean>({ default: false })
const exporting = ref(false)
const countLoading = ref(false)
const matchedCount = ref(0)
const maxLimit = ref(100000)
const limitPresets = [1000, 5000, 10000, 50000]
const fieldOptions = computed(() => [
@@ -101,10 +100,15 @@ const fieldOptions = computed(() => [
const form = reactive({
fields: fieldOptions.value.map((item) => item.value),
exportLimit: 10000,
exportLimit: 0,
})
const actualExportCount = computed(() => Math.min(form.exportLimit, matchedCount.value, maxLimit.value))
const actualExportCount = computed(() => {
if (form.exportLimit <= 0) {
return matchedCount.value
}
return Math.min(form.exportLimit, matchedCount.value)
})
const selectAllFields = () => {
form.fields = fieldOptions.value.map((item) => item.value)
@@ -115,7 +119,7 @@ const clearFields = () => {
}
const useMatchedCount = () => {
form.exportLimit = Math.min(matchedCount.value || 1, maxLimit.value)
form.exportLimit = 0
}
const buildExportParams = () => {
@@ -123,7 +127,7 @@ const buildExportParams = () => {
return {
...filter,
fields: form.fields,
export_limit: actualExportCount.value,
export_limit: form.exportLimit <= 0 ? 0 : form.exportLimit,
}
}
@@ -136,7 +140,6 @@ const loadMatchedCount = async () => {
params: baTable.table.filter || {},
})
matchedCount.value = res.data.count
maxLimit.value = res.data.max_limit
} catch {
matchedCount.value = baTable.table.total || 0
} finally {
@@ -197,7 +200,7 @@ const submitExport = async () => {
const disposition = String(response.headers['content-disposition'] || '')
const filenameMatch = disposition.match(/filename="?([^";]+)"?/i)
const filename = filenameMatch?.[1] || `daily_push_${Date.now()}.csv`
const filename = filenameMatch?.[1] || `daily_push_${Date.now()}.xlsx`
downloadBlob(blob, filename)
ElNotification({