修复导出进度:导出方法名与进度字段重名导致点击无反应,改用 exportedRows;去掉原生确认框
This commit is contained in:
parent
29defd2025
commit
18b4b9f0fb
@ -94,11 +94,11 @@ const dateConfig = {dateFormat:'Y-m-d',locale:Mandarin,disableMobile:true,allowI
|
||||
const emptyFilters = billType => ({store_name:'',ledger_remark:'',bill_item:'',start:'',end:'',keyword:'',keyword_match:'contains'});
|
||||
export default {
|
||||
name:'AccountBills', components:{ TableColumnSettings, flatPicker, [Select.name]:Select, [Option.name]:Option }, props:{ apiBase:{type:String,required:true}, billType:{type:String,required:true}, progressBase:{type:String,default:''}, userKey:{type:[String,Number],required:true} },
|
||||
data(){return{loading:false,loadError:false,sync:null,rows:[],sourceColumns:[],configuredColumns:[],columnsTitle:'',sourceGroups:[],summary:{income:0,expense:0,balance:0,count:0},total:0,currentPage:1,lastPage:1,perPage:20,filters:emptyFilters(this.billType),queryFilters:emptyFilters(this.billType),resultFilters:null,filterOptions:{shops:[],bill_items:[],ledger_remarks:[]},filterOptionsLoading:false,filterOptionsError:false,requestSerial:0,sort:{key:'occurred_at',dir:'desc'},exportMode:'filtered-visible',exporting:false,exportRows:0,exportTotal:0,exportTimer:null};},
|
||||
data(){return{loading:false,loadError:false,sync:null,rows:[],sourceColumns:[],configuredColumns:[],columnsTitle:'',sourceGroups:[],summary:{income:0,expense:0,balance:0,count:0},total:0,currentPage:1,lastPage:1,perPage:20,filters:emptyFilters(this.billType),queryFilters:emptyFilters(this.billType),resultFilters:null,filterOptions:{shops:[],bill_items:[],ledger_remarks:[]},filterOptionsLoading:false,filterOptionsError:false,requestSerial:0,sort:{key:'occurred_at',dir:'desc'},exportMode:'filtered-visible',exporting:false,exportedRows:0,exportTotal:0,exportTimer:null};},
|
||||
computed:{
|
||||
isDouyin(){return this.billType==='douyin';},
|
||||
exportPercent(){return this.exportTotal>0?Math.min(100,Math.round(this.exportRows*100/this.exportTotal)):0;},
|
||||
exportText(){return '导出已开始,浏览器会保存到下载目录,你可以继续查看其它页面 · 已导出 '+Number(this.exportRows||0).toLocaleString()+' / '+Number(this.exportTotal||0).toLocaleString()+' 行('+this.exportPercent+'%)';},
|
||||
exportPercent(){return this.exportTotal>0?Math.min(100,Math.round(this.exportedRows*100/this.exportTotal)):0;},
|
||||
exportText(){const total=Number(this.exportTotal||0);const minutes=Math.max(1,Math.ceil(total/1800/60));return '共 '+total.toLocaleString()+' 行,预计约 '+minutes+' 分钟 · 已导出 '+Number(this.exportedRows||0).toLocaleString()+' 行('+this.exportPercent+'%)· 导出在后台进行,可以继续查看其它页面';},
|
||||
// 费用结算时间标签、来源说明与收支净额统计口径按京东系列页签(京东账单/京喜账单)统一。
|
||||
isJdBillTab(){return JD_BILL_TABS.indexOf(this.billType)!==-1;},
|
||||
dateFilterLabel(){return DATE_FILTER_LABELS[this.billType]||'发生时间';},
|
||||
@ -135,7 +135,6 @@ export default {
|
||||
if(this.exportMode==='filtered-visible')this.visibleColumns.forEach(column=>params.append('columns[]',column.field));
|
||||
// 服务端逐行生成 CSV:行数大时要几分钟,先告知用户,避免误判成「导不出来」。
|
||||
const rows=Number(this.total||0);
|
||||
if(rows>20000){const minutes=Math.max(1,Math.ceil(rows/1800/60));if(!window.confirm(`即将导出 ${rows.toLocaleString('zh-CN')} 行,服务端逐行生成,预计需要 ${minutes} 分钟。导出会在后台进行,你可以继续看其它页面,页面上会显示导出进度。是否继续?`)){return;}}
|
||||
const token=`ab${Date.now().toString(36)}${Math.random().toString(36).slice(2,10)}`;
|
||||
params.set('token',token);
|
||||
params.set('total',String(rows));
|
||||
@ -146,7 +145,7 @@ export default {
|
||||
startExportWatch(token,total){
|
||||
this.stopExportWatch();
|
||||
this.exporting=true;
|
||||
this.exportRows=0;
|
||||
this.exportedRows=0;
|
||||
this.exportTotal=Number(total||0);
|
||||
const progressUrl=this.progressBase||`${this.apiBase}/export-progress`;
|
||||
this.exportTimer=window.setInterval(()=>{
|
||||
@ -154,7 +153,7 @@ export default {
|
||||
.then(response=>response.ok?response.json():null)
|
||||
.then(state=>{
|
||||
if(!state||state.status==='unknown'){return;}
|
||||
this.exportRows=Number(state.rows||0);
|
||||
this.exportedRows=Number(state.rows||0);
|
||||
if(state.total){this.exportTotal=Number(state.total);}
|
||||
if(state.status==='done'||state.status==='failed'){this.stopExportWatch();}
|
||||
})
|
||||
|
||||
@ -124,14 +124,14 @@ const SORTABLE = ['occurred_at', 'income', 'expense', 'balance', 'record_code'];
|
||||
export default {
|
||||
name: 'TaobaoAlipayBills', components: { TableColumnSettings, flatPicker, [Select.name]: Select, [Option.name]: Option },
|
||||
props: { apiBase: { type: String, required: true }, exportBase: { type: String, required: true }, progressBase: { type: String, default: '' }, userKey: { type: [String, Number], required: true } },
|
||||
data() { return { loading: false, error: '', rows: [], configuredColumns: [], summary: { income: 0, expense: 0, balance: 0, count: 0 }, total: 0, currentPage: 1, lastPage: 1, perPage: 20, filters: { store_name: '', ledger_remark: '', source_channel: '', bill_item: '', business_type: '', start: '', end: '', keyword: '' }, filterOptions: { shops: [], bill_items: [], ledger_remarks: [] }, filterOptionsLoading: false, filterOptionsError: false, sort: { key: 'occurred_at', dir: 'desc' }, exportMode: 'filtered-visible', exporting: false, exportRows: 0, exportTotal: 0, exportTimer: null }; },
|
||||
data() { return { loading: false, error: '', rows: [], configuredColumns: [], summary: { income: 0, expense: 0, balance: 0, count: 0 }, total: 0, currentPage: 1, lastPage: 1, perPage: 20, filters: { store_name: '', ledger_remark: '', source_channel: '', bill_item: '', business_type: '', start: '', end: '', keyword: '' }, filterOptions: { shops: [], bill_items: [], ledger_remarks: [] }, filterOptionsLoading: false, filterOptionsError: false, sort: { key: 'occurred_at', dir: 'desc' }, exportMode: 'filtered-visible', exporting: false, exportedRows: 0, exportTotal: 0, exportTimer: null }; },
|
||||
computed: {
|
||||
defaultColumns() { return COLUMNS; }, visibleColumns() { return this.configuredColumns.filter((column) => column.visible); },
|
||||
visibleGroups() { return this.visibleColumns.reduce((groups, column) => { const last = groups[groups.length - 1]; if (last && last.label === column.group) last.span += 1; else groups.push({ label: column.group, span: 1 }); return groups; }, []); },
|
||||
stats() { return [{ label: '收入合计', value: this.moneyWan(this.summary.income), note: `${this.summary.count} 笔交易`, className: 'is-income' }, { label: '支出合计', value: this.moneyWan(this.summary.expense), note: '按当前筛选', className: 'is-expense' }, { label: '收支差额', value: this.moneyWan(this.summary.balance), note: '收入合计 - 支出合计', className: '' }, { label: '交易笔数', value: this.summary.count, note: '当前筛选结果', className: '' }]; },
|
||||
rangeStart() { return this.total === 0 ? 0 : (this.currentPage - 1) * this.perPage + 1; }, rangeEnd() { return Math.min(this.currentPage * this.perPage, this.total); },
|
||||
exportPercent() { return this.exportTotal > 0 ? Math.min(100, Math.round(this.exportRows * 100 / this.exportTotal)) : 0; },
|
||||
exportText() { return '导出已开始,浏览器会保存到下载目录,你可以继续查看其它页面 · 已导出 ' + Number(this.exportRows || 0).toLocaleString() + ' / ' + Number(this.exportTotal || 0).toLocaleString() + ' 行(' + this.exportPercent + '%)'; },
|
||||
exportPercent() { return this.exportTotal > 0 ? Math.min(100, Math.round(this.exportedRows * 100 / this.exportTotal)) : 0; },
|
||||
exportText() { const total = Number(this.exportTotal || 0); const minutes = Math.max(1, Math.ceil(total / 1800 / 60)); return '共 ' + total.toLocaleString() + ' 行,预计约 ' + minutes + ' 分钟 · 已导出 ' + Number(this.exportedRows || 0).toLocaleString() + ' 行(' + this.exportPercent + '%)· 导出在后台进行,可以继续查看其它页面'; },
|
||||
invalidDateRange() { return Boolean(this.filters.start && this.filters.end && this.filters.start > this.filters.end); },
|
||||
startDateConfig() { return { ...dateConfig, maxDate: this.filters.end || null }; },
|
||||
endDateConfig() { return { ...dateConfig, minDate: this.filters.start || null }; },
|
||||
@ -156,10 +156,6 @@ export default {
|
||||
if (this.exportMode === 'filtered-visible') this.visibleColumns.forEach((column) => params.append('columns[]', column.field));
|
||||
// 服务端逐行生成 CSV:行数大时要几分钟,先告知用户,避免误判成「导不出来」。
|
||||
const rows = Number(this.total || 0);
|
||||
if (rows > 20000) {
|
||||
const minutes = Math.max(1, Math.ceil(rows / 1800 / 60));
|
||||
if (!window.confirm(`即将导出 ${rows.toLocaleString('zh-CN')} 行,服务端逐行生成,预计需要 ${minutes} 分钟。导出会在后台进行,你可以继续看其它页面,页面上会显示导出进度。是否继续?`)) { return; }
|
||||
}
|
||||
const token = `ab${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
||||
params.set('token', token);
|
||||
params.set('total', String(rows));
|
||||
@ -170,7 +166,7 @@ export default {
|
||||
startExportWatch(token, total) {
|
||||
this.stopExportWatch();
|
||||
this.exporting = true;
|
||||
this.exportRows = 0;
|
||||
this.exportedRows = 0;
|
||||
this.exportTotal = Number(total || 0);
|
||||
const progressUrl = this.progressBase || `${this.apiBase}/export-progress`;
|
||||
this.exportTimer = window.setInterval(() => {
|
||||
@ -178,7 +174,7 @@ export default {
|
||||
.then((response) => (response.ok ? response.json() : null))
|
||||
.then((state) => {
|
||||
if (!state || state.status === 'unknown') { return; }
|
||||
this.exportRows = Number(state.rows || 0);
|
||||
this.exportedRows = Number(state.rows || 0);
|
||||
if (state.total) { this.exportTotal = Number(state.total); }
|
||||
if (state.status === 'done' || state.status === 'failed') { this.stopExportWatch(); }
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user