240 lines
6.4 KiB
JavaScript
240 lines
6.4 KiB
JavaScript
|
var bricks = window.bricks || {};
|
||
|
bricks.PageContent = class extends bricks.Layout {
|
||
|
constructor(opts){
|
||
|
super(opts);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bricks.AccordionItem = class extends bricks.Layout {
|
||
|
constructor(opts){
|
||
|
super(opts);
|
||
|
this.set_css('accordion-item');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bricks.AccordionHeader = class extends bricks.Layout {
|
||
|
constructor(opts){
|
||
|
super(opts);
|
||
|
this.set_css('accordion-item-header');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bricks.DynamicAccordion = class extends bricks.VScrollPanel {
|
||
|
/*
|
||
|
{
|
||
|
"title":
|
||
|
"description",
|
||
|
"data_url",
|
||
|
"content_url"
|
||
|
"content_view"
|
||
|
"cache_limit",
|
||
|
"page_rows",
|
||
|
"header":
|
||
|
"record_view"
|
||
|
"record_show_field":
|
||
|
}
|
||
|
*/
|
||
|
constructor(opts){
|
||
|
super(opts);
|
||
|
this.set_css("accordion");
|
||
|
this.element = this.dom_element;
|
||
|
this.dataUrl = this.opts.data_url;
|
||
|
this.base_params = opts.params || {};
|
||
|
this.rows = parseInt(this.opts.page_rows);
|
||
|
this.lastPage = null;
|
||
|
this.contentUrl = this.opts.content_url;
|
||
|
this.pages = new Map(); // 用于存储已加载的页面数据
|
||
|
this.pageContents = new Map(); // 用于存储已加载的页面内容
|
||
|
this.active_content = null;
|
||
|
this.loading = false;
|
||
|
this.cacheLimit = this.opts.cache_limit;
|
||
|
if (this.opts.content_view){
|
||
|
this.content_view_tmpl = JSON.stringify(this.opts.content_view);
|
||
|
}
|
||
|
if (this.opts.record_view){
|
||
|
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.render();
|
||
|
}
|
||
|
|
||
|
render(params) {
|
||
|
this.clear_widgets();
|
||
|
this.pages = new Map(); // 用于存储已加载的页面数据
|
||
|
this.pageContents = new Map(); // 用于存储已加载的页面内容
|
||
|
params = params || {};
|
||
|
this.params = bricks.extend(this.base_params, params);
|
||
|
this.loadPage(1);
|
||
|
}
|
||
|
|
||
|
async loadPage(page) {
|
||
|
if (this.loading){
|
||
|
return;
|
||
|
}
|
||
|
this.loading = true;
|
||
|
// 检查页面是否在缓存中
|
||
|
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){
|
||
|
console.log(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;
|
||
|
var w = this.pageContents.get(farthestPage);
|
||
|
this.remove_widget(w);
|
||
|
this.pages.delete(farthestPage);
|
||
|
this.pageContents.delete(farthestPage);
|
||
|
}
|
||
|
var pages = Array.from(this.pages.keys());
|
||
|
if (page == Math.min(pages)){
|
||
|
this.scrollY = 1 / pages.length;
|
||
|
if (this.scrollY == 1){
|
||
|
this.scrollY = 0;
|
||
|
}
|
||
|
} else {
|
||
|
this.scrollY = (pages.length - 1) / pages.length;
|
||
|
}
|
||
|
}
|
||
|
this.loading = false;
|
||
|
return;
|
||
|
}
|
||
|
async renderAccordionItems(data, page) {
|
||
|
|
||
|
const pageContent = new bricks.PageContent({height:"auto"});
|
||
|
pageContent.page = page;
|
||
|
|
||
|
for (var i=0;i<data.length;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 {
|
||
|
console.log('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, content, record));
|
||
|
item.add_widget(header);
|
||
|
item.add_widget(content);
|
||
|
pageContent.add_widget(item);
|
||
|
};
|
||
|
|
||
|
this.pageContents.set(page, pageContent);
|
||
|
var pages = Array.from(this.pages.keys());
|
||
|
if (page == Math.min(...pages)){
|
||
|
this.add_widget(pageContent, 0);
|
||
|
} else {
|
||
|
this.add_widget(pageContent);
|
||
|
}
|
||
|
}
|
||
|
async toggle_content(content, record, event){
|
||
|
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'){
|
||
|
console.log('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 (dir=='up'){
|
||
|
var page = Math.min(...pages);
|
||
|
console.log('page=', page, pages, 'dir=', dir);
|
||
|
return page - 1;
|
||
|
} else {
|
||
|
var page = Math.max(...pages);
|
||
|
console.log('page=', page, pages, 'dir=', dir);
|
||
|
return page + 1;
|
||
|
}
|
||
|
}
|
||
|
async load_previous_page(){
|
||
|
var pages = Array.from(this.pages.keys());
|
||
|
var page = this.get_load_page('up');
|
||
|
if (page > 0){
|
||
|
await this.loadPage(page);
|
||
|
console.log('page loaded, page=', page);
|
||
|
} else {
|
||
|
var pages = Array.from(this.pages.keys());
|
||
|
console.log('page NOT loaded, page=', page,
|
||
|
'lastPage=', this.lastPage,
|
||
|
'rows=', this.rows,
|
||
|
'cacheLimit=', this.cacheLimit,
|
||
|
'buffered page=', pages.length);
|
||
|
}
|
||
|
}
|
||
|
async load_next_page(){
|
||
|
var pages = Array.from(this.pages.keys());
|
||
|
var page = this.get_load_page('down');
|
||
|
if (page <= this.lastPage){
|
||
|
await this.loadPage(page);
|
||
|
console.log('page Loaded, page=', page);
|
||
|
} else {
|
||
|
console.log('page=', page,
|
||
|
'lastPage=', this.lastPage,
|
||
|
'rows=', this.rows,
|
||
|
'cacheLimit=', this.cacheLimit,
|
||
|
'buffered page=', pages);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
bricks.Factory.register('DynamicAccordion', bricks.DynamicAccordion);
|