This commit is contained in:
yumoqing 2024-03-11 15:22:03 +08:00
parent 278a520138
commit c1220be5bd
3 changed files with 279 additions and 161 deletions

View File

@ -1,5 +1,5 @@
SOURCES=" factory.js uitypesdef.js utils.js i18n.js widget.js \ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js \
layout.js bricks.js image.js \ i18n.js widget.js layout.js bricks.js image.js \
jsoncall.js myoperator.js scroll.js menu.js modal.js \ jsoncall.js myoperator.js scroll.js menu.js modal.js \
markdown_viewer.js video.js audio.js toolbar.js tab.js \ markdown_viewer.js video.js audio.js toolbar.js tab.js \
input.js registerfunction.js button.js accordion.js \ input.js registerfunction.js button.js accordion.js \

View File

@ -2,70 +2,257 @@ var bricks = window.bricks || {};
bricks.DataViewer = class extends bricks.VScrollPanel { bricks.DataViewer = class extends bricks.VScrollPanel {
/* /*
opts={ {
dataurl: "title":
pagerows: "description",
params: "data_url",
buffer_page: "mobile_cols":
viewer_url: or "content_view"
viewer_tmpl: "has_content",
"content_toggle_field"
"cache_page_limit",
"page_rows",
"header":
"record_view"
} }
*/ */
constructor(opts){ constructor(opts){
opts.width = '100%';
super(opts); super(opts);
this.loader = new bricks.BufferedDataLoader(this, { this.set_css("accordion");
pagerows: opts.pagerows || 80, this.element = this.dom_element;
buffer_pages: opts.buffer_pages || 5, this.dataUrl = this.opts.data_url;
url: opts.dataurl, this.base_params = opts.params || {};
method: opts.method || 'GET', this.rows = parseInt(this.opts.page_rows);
params: opts.params this.lastPage = null;
}); this.contentUrl = this.opts.content_url;
this.set_css('multicolumns'); this.pages = new Map(); // 用于存储已加载的页面数据
this.bind('min_threshold', this.pageContents = new Map(); // 用于存储已加载的页面内容
this.loader.previousPage.bind(this.loader)) this.active_content = null;
this.bind('max_threshold', this.loading = false;
this.loader.nextPage.bind(this.loader)) this.cachePageLimit = this.opts.cache_page_limit;
if (opts.viewer_tmpl){ if (this.opts.content_view){
this.viewer_tmpl = opts.viewer_tmpl; this.content_view_tmpl = JSON.stringify(this.opts.content_view);
} }
if (opts.viewer_url){ if (this.opts.record_view){
this.get_tmpl_string(); this.record_view_tmpl = JSON.stringify(this.opts.record_view);
} }
this.bind('min_threshold', this.load_previous_page.bind(this));
this.bind('max_threshold', this.load_next_page.bind(this));
this.oldscrollY = null;
this.render();
} }
loadData(params){ create_container(){
this.loader.loadData(params) this.container = new Filler();
} }
get_tmpl_string(){
fetch(this.opts.viewer_url) render(params) {
.then(response => response.text()) bricks.debug('params=', params, 'render() called');
.then(data => {
bricks.debug('viewer_tmpl=', data);
this.viewer_tmpl = data
schedule_once(this.loader.loadData.bind(this.loader), 0.01);
});
}
clear_data(){
this.clear_widgets(); this.clear_widgets();
this.pages = new Map(); // 用于存储已加载的页面数据
this.pageContents = new Map(); // 用于存储已加载的页面内容
params = params || {};
this.params = bricks.extend(this.base_params, params);
this.loadPage(1);
this.dom_element.scrollTop = 0;
} }
add_rows = async function(rows, direction){
for (var i=0;i<rows.length;i++){ async loadPage(page) {
await this.add_row(rows[i], direction); // 检查页面是否在缓存中
} if (! this.pages.has(page)) {
} var jc = new bricks.HttpJson();
add_row = async function(row, direction){ var params = bricks.extend({}, this.params);
var s = bricks.obj_fmtstr(row, this.viewer_tmpl); params = bricks.extend(params,{
var desc = JSON.parse(s); page:page,
var w = await bricks.widgetBuild(desc, this); rows:this.rows
if (! w){ });
bricks.debug(desc, 'widgetBuild() failed...........'); var d = await jc.get(this.dataUrl,{params:params});
if (!d){
bricks.debug(this.dataUrl,{params:params}, 'error');
this.loading = false;
return; return;
} }
w.row_data = row; var data = d.rows;
var index = null; this.lastPage = Math.ceil(d.total / this.rows);
if (direction == 'down') index = 0; this.pages.set(page, data); // 将数据缓存起来
bricks.debug('w=', w, 'this=', this); await this.renderAccordionItems(data, page);
this.add_widget(w, index); // 检查缓存是否已满
if (this.pages.size > this.cachePageLimit) {
// 删除当前页最远的一页
var max, min;
var pages = Array.from(this.pages.keys());
max = Math.max(...pages);
min = Math.min(...pages);
const farthestPage = page == max? min : max;
this.delete_page(farthestPage);
this.pages.delete(farthestPage);
}
} else {
bricks.debug(page, 'already n buffer, do not thing');
}
return;
}
is_max_page(page){
const pages = Array.from(this.pages.keys());
return page == Math.max(...pages);
}
is_min_page(page){
const pages = Array.from(this.pages.keys());
return page == Math.min(...pages);
}
async renderRecords(data, page) {
var pos;
for (var i=0;i<data.length;i++){
if (this.is_max_page(page)){
pos = -1;
} else {
pos = i;
}
const record = data[i];
const item = new bricks.AccordionItem({});
const header = new bricks.AccordionHeader({});
if (this.opts.record_view){
var w;
w = await bricks.widgetBuildWithData(this.record_view_tmpl,
header, record);
if (w){
header.add_widget(w);
} else {
bricks.debug('bricks.widgetBuildWithData(), tmpl=', this.record_view_tmpl, 'record=', record);
}
}
header.textContent = record.title; // 使用数据记录的标题字段
var content = new bricks.VBox({
height:'auto',
display:'none'
});
content.set_css('accordion-item-content');
content.hide();
header.bind('click', this.toggle_content.bind(this, header, content, record));
item.add_widget(header);
item.add_widget(content);
item.set_attribute('data-page', page);
this.add_widget(item, pos);
if (pos >= 0){
this.dom_element.scrollTop += item.get_height();
} else {
this.dom_element.scrollTop -= item.get_height();
}
};
}
delete_page(page){
var items = this.dom_element.querySelectorAll('[data-page="' + page + '"]');
for (var i=0;i<items.length;i++) {
var w = items[i].bricks_widget;
this.remove_widget(w);
}
}
async toggle_content(header, content, record, event){
var h = this.dom_element.offsetHeight - 3 * header.dom_element.offsetHeight;
content.set_style('height', h + 'px');
if (this.active_content){
if (this.active_content != content){
this.active_content.clear_widgets();
this.active_content.hide();
this.active_content = null;
}
}
content.toggle_hide();
if (content.dom_element.style.display == 'none'){
bricks.debug('content just collapsed');
content.clear_widgets();
this.active_content = null;
return;
}
var jc = new bricks.HttpJson();
var w;
if (this.content_view_tmpl){
w = await bricks.widgetBuildWithData(this.content_view_tmpl,
content, record);
} else if (this.contentUrl){
var url = this.contentUrl;
var params = {
'id':record.id
}
var desc = await jc.get(url, {params:params});
w = await bricks.widgetBuild(desc, content);
}
if (w){
content.add_widget(w);
this.active_content = content;
} else {
this.active_content = null;
content.hide();
}
}
get_load_page(dir){
var pages = Array.from(this.pages.keys());
if (pages.length == 0){
return 1;
}
if (dir=='up'){
var page = Math.min(...pages);
bricks.debug('page=', page, pages, 'dir=', dir);
return page - 1;
} else {
var page = Math.max(...pages);
bricks.debug('page=', page, pages, 'dir=', dir);
return page + 1;
}
}
async load_previous_page(){
if (this.loading){
bricks.debug('this.loading is set, do not thing');
return;
}
this.loading = true;
try {
var page = this.get_load_page('up');
if (page > 0){
await this.loadPage(page);
var pages = Array.from(this.pages.keys());
bricks.debug('load_previous_page():page loaded, page=', page, pages);
} else {
var pages = Array.from(this.pages.keys());
bricks.debug('page NOT loaded, page=', page,
'lastPage=', this.lastPage,
'rows=', this.rows,
'cachePageLimit=', this.cachePageLimit,
'buffered page=', pages.length);
}
} catch(e){
bricks.debug('error happened', e);
}
this.loading = false;
}
async load_next_page(){
if (this.loading){
bricks.debug('this.loading is set, do not thing');
return;
}
this.loading = true;
try {
var page = this.get_load_page('down');
if (page <= this.lastPage){
await this.loadPage(page);
var pages = Array.from(this.pages.keys());
bricks.debug('load_next_page():page Loaded, page=', page, pages);
} else {
var pages = Array.from(this.pages.keys());
bricks.debug('page=', page,
'lastPage=', this.lastPage,
'rows=', this.rows,
'cachePageLimit=', this.cachePageLimit,
'buffered page=', pages);
}
} catch (e){
bricks.debug('error happened', e);
}
this.loading = false;
bricks.debug('load_next_page() finished');
} }
} }
bricks.Factory.register('DataViewer', bricks.DataViewer); bricks.Factory.register('DynamicAccordion', bricks.DynamicAccordion);

View File

@ -25,6 +25,7 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
"title": "title":
"description", "description",
"data_url", "data_url",
"data_method",
"content_url" "content_url"
"content_view" "content_view"
"cache_limit", "cache_limit",
@ -38,16 +39,16 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
super(opts); super(opts);
this.set_css("accordion"); this.set_css("accordion");
this.element = this.dom_element; this.element = this.dom_element;
this.dataUrl = this.opts.data_url; this.loader = new bricks.PageDataLoader({
this.base_params = opts.params || {}; url:this.opts.data_url,
this.rows = parseInt(this.opts.page_rows); params:this.opts.data_params,
this.lastPage = null; pagerows:this.opts.page_rows,
method:this.opts.data_method,
cache_pages:this.opts.cache_limit
});
this.contentUrl = this.opts.content_url; this.contentUrl = this.opts.content_url;
this.pages = new Map(); // 用于存储已加载的页面数据
this.pageContents = new Map(); // 用于存储已加载的页面内容
this.active_content = null; this.active_content = null;
this.loading = false; this.loading = false;
this.cacheLimit = this.opts.cache_limit;
if (this.opts.content_view){ if (this.opts.content_view){
this.content_view_tmpl = JSON.stringify(this.opts.content_view); this.content_view_tmpl = JSON.stringify(this.opts.content_view);
} }
@ -56,70 +57,32 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
} }
this.bind('min_threshold', this.load_previous_page.bind(this)); this.bind('min_threshold', this.load_previous_page.bind(this));
this.bind('max_threshold', this.load_next_page.bind(this)); this.bind('max_threshold', this.load_next_page.bind(this));
this.oldscrollY = null; schedule_once(this.render.bind(this), 0.1);
this.render();
} }
render(params) { async render(params) {
bricks.debug('params=', params, 'render() called');
this.clear_widgets();
this.pages = new Map(); // 用于存储已加载的页面数据
this.pageContents = new Map(); // 用于存储已加载的页面内容
params = params || {}; params = params || {};
this.params = bricks.extend(this.base_params, params); bricks.debug('params=', params, 'render() called');
this.loadPage(1); var d = await this.loader.loadData(params);
this.dom_element.scrollTop = 0; if (d){
this.clear_widgets();
await this.dataHandle(d);
}
async loadPage(page) {
// 检查页面是否在缓存中
if (! this.pages.has(page)) {
var jc = new bricks.HttpJson();
var params = bricks.extend({}, this.params);
params = bricks.extend(params,{
page:page,
rows:this.rows
});
var d = await jc.get(this.dataUrl,{params:params});
if (!d){
bricks.debug(this.dataUrl,{params:params}, 'error');
this.loading = false;
return;
}
var data = d.rows;
this.lastPage = Math.ceil(d.total / this.rows);
this.pages.set(page, data); // 将数据缓存起来
await this.renderAccordionItems(data, page);
// 检查缓存是否已满
if (this.pages.size > this.cacheLimit) {
// 删除当前页最远的一页
var max, min;
var pages = Array.from(this.pages.keys());
max = Math.max(...pages);
min = Math.min(...pages);
const farthestPage = page == max? min : max;
this.delete_page(farthestPage);
this.pages.delete(farthestPage);
}
} else { } else {
bricks.debug(page, 'already n buffer, do not thing'); bricks.debug(params, 'load data return null');
} }
return;
} }
is_max_page(page){ async dataHandle(d){
const pages = Array.from(this.pages.keys()); var data = d.rows;
return page == Math.max(...pages); var page = d.add_page;
await this.renderAccordionItems(data, page);
if (d.delete_page){
this.delete_page(d.delete_page);
} }
is_min_page(page){
const pages = Array.from(this.pages.keys());
return page == Math.min(...pages);
} }
async renderAccordionItems(data, page) { async renderAccordionItems(data, page) {
var pos; var pos;
for (var i=0;i<data.length;i++){ for (var i=0;i<data.length;i++){
if (this.is_max_page(page)){ if (this.loader.is_max_page(page)){
pos = -1; pos = -1;
} else { } else {
pos = i; pos = i;
@ -137,7 +100,6 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
bricks.debug('bricks.widgetBuildWithData(), tmpl=', this.record_view_tmpl, 'record=', record); bricks.debug('bricks.widgetBuildWithData(), tmpl=', this.record_view_tmpl, 'record=', record);
} }
} }
header.textContent = record.title; // 使用数据记录的标题字段
var content = new bricks.VBox({ var content = new bricks.VBox({
height:'auto', height:'auto',
display:'none' display:'none'
@ -149,11 +111,6 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
item.add_widget(content); item.add_widget(content);
item.set_attribute('data-page', page); item.set_attribute('data-page', page);
this.add_widget(item, pos); this.add_widget(item, pos);
if (pos >= 0){
this.dom_element.scrollTop += item.get_height();
} else {
this.dom_element.scrollTop -= item.get_height();
}
}; };
} }
delete_page(page){ delete_page(page){
@ -163,7 +120,6 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
this.remove_widget(w); this.remove_widget(w);
} }
} }
async toggle_content(header, content, record, event){ async toggle_content(header, content, record, event){
var h = this.dom_element.offsetHeight - 3 * header.dom_element.offsetHeight; var h = this.dom_element.offsetHeight - 3 * header.dom_element.offsetHeight;
content.set_style('height', h + 'px'); content.set_style('height', h + 'px');
@ -203,21 +159,6 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
content.hide(); content.hide();
} }
} }
get_load_page(dir){
var pages = Array.from(this.pages.keys());
if (pages.length == 0){
return 1;
}
if (dir=='up'){
var page = Math.min(...pages);
bricks.debug('page=', page, pages, 'dir=', dir);
return page - 1;
} else {
var page = Math.max(...pages);
bricks.debug('page=', page, pages, 'dir=', dir);
return page + 1;
}
}
async load_previous_page(){ async load_previous_page(){
if (this.loading){ if (this.loading){
bricks.debug('this.loading is set, do not thing'); bricks.debug('this.loading is set, do not thing');
@ -225,21 +166,16 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
} }
this.loading = true; this.loading = true;
try { try {
var page = this.get_load_page('up'); var d = await this.loader.loadPreviousPage();
if (page > 0){ if (d){
await this.loadPage(page); this.dataHandle(d);
var pages = Array.from(this.pages.keys()); var total = this.dom_element.scrollHeight - this.dom_element.clientHeight;
bricks.debug('load_previous_page():page loaded, page=', page, pages); this.dom_element.scrollTop = d.pos_rate * total;
} else { } else {
var pages = Array.from(this.pages.keys()); bricks.debug(this.loader, 'load previous page error');
bricks.debug('page NOT loaded, page=', page,
'lastPage=', this.lastPage,
'rows=', this.rows,
'cacheLimit=', this.cacheLimit,
'buffered page=', pages.length);
} }
} catch(e){ } catch (e) {
bricks.debug('error happened', e); bricks.debug('e=', e);
} }
this.loading = false; this.loading = false;
} }
@ -250,18 +186,13 @@ bricks.DynamicAccordion = class extends bricks.VScrollPanel {
} }
this.loading = true; this.loading = true;
try { try {
var page = this.get_load_page('down'); var d = await this.loader.loadNextPage();
if (page <= this.lastPage){ if (d){
await this.loadPage(page); this.dataHandle(d);
var pages = Array.from(this.pages.keys()); var total = this.dom_element.scrollHeight - this.dom_element.clientHeight;
bricks.debug('load_next_page():page Loaded, page=', page, pages); this.dom_element.scrollTop = d.pos_rate * total;
} else { } else {
var pages = Array.from(this.pages.keys()); bricks.debug(this.loader, 'load next page error');
bricks.debug('page=', page,
'lastPage=', this.lastPage,
'rows=', this.rows,
'cacheLimit=', this.cacheLimit,
'buffered page=', pages);
} }
} catch (e){ } catch (e){
bricks.debug('error happened', e); bricks.debug('error happened', e);