门户中用自定义界面和搜索交互案例

介绍

用户在门户展板中想要显示一个自定义的统计,显示后台返回的数据,并且与顶部的搜索交互

效果

实现步骤

  • 搜索条代码
const {h} = JE.useVue();
const {Button,DatePicker,Input,Panel,Select,Form,InputSelect} = JE.useUi();
const {container,$portal,refreshParams} = EventOptions;
const todayDate = JE.dateFormat(new Date(),'YYYY-MM-DD');
// 1. 确定基准日期(不传则用当前系统时间)
const baseDate = new Date();
const oneMonthAgo = new Date(baseDate);
// 2. 核心:减1个月 + 处理31日跨月的边界问题(如3月31日→2月最后一天)
const originalDay = baseDate.getDate(); // 基准日期的“日”(如31、28)
oneMonthAgo.setMonth(baseDate.getMonth() - 1);
// 若跨月后日期异常(如2月没有31日),自动修正为上月最后一天
if (oneMonthAgo.getDate() !== originalDay) {
    oneMonthAgo.setDate(0); // setDate(0) = 上个月最后一天
}
// 3. 格式化为 YYYY-MM-DD 字符串(控件要求的格式)
const year = oneMonthAgo.getFullYear();
const month = String(oneMonthAgo.getMonth() + 1).padStart(2, '0'); // 月份+1,补0
const day = String(oneMonthAgo.getDate()).padStart(2, '0'); // 日期补0

const formData = {
    CGBM: 'T2101,T2201,T2301,T2401',
    KSSJ: year + '-' + month + '-' + day,
    JSSJ: todayDate,
    SJLD: "DAY"
};

const onButtonClick = ()=>{
    // 获取筛选参数
    const params = {
        KSSJ: formData.KSSJ,
        JSSJ: formData.JSSJ
    };
    $portal.getPortalItem('SBQK').refresh(params);//刷新面板
};
// 渲染 UI
const node = h('div', { style: { display: 'flex', gap: '10px', alignItems: 'center' } }, [
    h('span', '储罐编码:'),
    h(InputSelect.Grid,{
        name: 'CGBM',
        value: formData.CGBM,
        configInfo:'SAFETY_MAINDATA_CGXX,CGBM,CGXX_CODE,M',
        'onUpdate:value': function (val) {
            formData.CGBM= val;
        },
        getPopupContainer:() => document.body,
        style:{width:'240px'}
    }),
    h('span', '开始时间:'),
    h(DatePicker,{
        value: formData.KSSJ,
        'onUpdate:value': function (val) {
            formData.KSSJ= val;
        },
        getPopupContainer:() => document.body,
        style:{width:'200px'},
        id:'startdates'
    }),
    h('span', '结束时间:'),
    h(DatePicker,{
        value: formData.JSSJ,
        'onUpdate:value': function (val) {
            formData.JSSJ= val;
        },
        getPopupContainer:() => document.body,
        style:{width:'200px'},
        id:'enddates'
    }),
    h('span', '数据粒度:'),
    h(Select,{
        name: 'SJLD',
        value: formData.SJLD,
        configInfo: 'HG_SJLD,SJLD,code,S',
        'onUpdate:value': function (val) {
            formData.SJLD= val;
        },
        getPopupContainer:() => document.body,
        style:{width:'200px'}
    }),
    // 检索按钮
    h(Button,{
        type:"primary",
        onClick:()=>{
            if(formData.KSSJ && formData.JSSJ && formData.SJLD){
                onButtonClick();
            }else {
                JE.alert('开始时间、结束时间、数据粒度不能为空!');
            }
        },style: { marginLeft: '10px' , width: '100px'}},
    '查询')
]);
return node;
  • 统计面板代码
const { h, ref, watch } = JE.useVue();
// 获取事件参数
let { refreshParams, $portal, container } = EventOptions;

if (container) {
    if(container.children.length > 0) {container.children[0].remove();}
}
const todayDate = JE.dateFormat(new Date(), 'YYYY-MM-DD');
// 基准日期处理
const baseDate = new Date();
const oneMonthAgo = new Date(baseDate);
oneMonthAgo.setMonth(baseDate.getMonth() - 1);
if (oneMonthAgo.getDate() !== baseDate.getDate()) {
    oneMonthAgo.setDate(0); // 处理31日跨月问题
}
// 初始化时间范围
let startTime = ref(refreshParams?.KSSJ || `${oneMonthAgo.getFullYear()}-${String(oneMonthAgo.getMonth() + 1).padStart(2, '0')}-${String(oneMonthAgo.getDate()).padStart(2, '0')}`);
let endTime = ref(refreshParams?.JSSJ || todayDate);

// 数据模型
let innerGs = ref(0);
let outerGs = ref(0);
let innerSl = ref(0);
let outerSl = ref(0);
let innerJz = ref(0);
let outerJz = ref(0);

// 数据获取函数
const res = JE.syncAjax({
    url: '/je/common/script/sql/select',
    params: {
        templateCode: 'comprehensiveStatistics',
        projectCode: 'safety',
        KSSJ: startTime.value,
        JSSJ: endTime.value
    },
    headers: { pd: 'safety' }
});

if (res.data?.length > 0) {
    innerGs.value = res.data[0].INNER_GS ? res.data[0].INNER_GS : 0;
    outerGs.value = res.data[0].OUTER_GS ? res.data[0].OUTER_GS : 0;
    innerSl.value = res.data[0].INNER_SL ? res.data[0].INNER_SL : 0;
    outerSl.value = res.data[0].OUTER_SL ? res.data[0].OUTER_SL : 0;
    innerJz.value = res.data[0].INNER_JZ ? res.data[0].INNER_JZ : 0;
    outerJz.value = res.data[0].OUTER_JZ ? res.data[0].OUTER_JZ : 0;
}

// 统计卡片配置
const statsCards = [
    {
        inputValue: innerGs.value + '票/次',
        inputTitle: '进仓',
        outValue: outerGs.value + '票/次',
        outTitle: '出仓',
        icon: 'fal fa-ballot',
        backgroundimage: '/micro/boards/img/process.06a4ca5e.png'
    },
    {
        inputValue: innerSl.value + '万吨',
        inputTitle: '进仓',
        outValue: outerSl.value + '万吨',
        outTitle: '出仓',
        icon: 'fal fa-cubes',
        backgroundimage: '/micro/boards/img/annual.45b842b6.png'
    },
    {
        inputValue: innerJz.value + '万美元',
        inputTitle: '进仓',
        outValue: outerJz.value + '万美元',
        outTitle: '出仓',
        icon: 'fal fa-money-check-dollar',
        backgroundimage: '/micro/boards/img/evection.d043cbf8.png'
    }
];

// 格式化工具函数
const formatValue = (value) => {
    const match = value.match(/(\d+\.?\d*)(.*)/);
    return {
        number: match?.[1] || value,
        unit: match?.[2] || ''
    };
};

// 卡片渲染
const cards = statsCards.map(card => {
    const inputFormatted = formatValue(card.inputValue);
    const outFormatted = formatValue(card.outValue);
    return h('div', {
        style: {
            padding: '20px',
            borderRadius: '10px',
            flex: '1',
            margin: '0 10px',
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            backgroundImage: `url(${card.backgroundimage})`,
            backgroundSize: 'cover',
            backgroundPosition: 'center',
            position: 'relative'
        }
    }, [
        h('div', {
            style: {
                position: 'relative',
                zIndex: 1,
                padding: '13px 20px 13px 50px',
                borderRadius: '8px',
                color: 'white',
                display: 'flex',
                flexDirection: 'column',
                gap: '6px'
            }
        }, [
            // 进仓部分
            h('div', {
                style: {
                    display: 'flex',
                    alignItems: 'baseline',
                    gap: '8px'
                }
            }, [
                h('span', {
                    style: { fontSize: '32px', fontWeight: 500}
                }, inputFormatted.number),
                h('span', {
                    style: { fontSize: '14px', whiteSpace: 'nowrap'}
                }, inputFormatted.unit)
            ]),
            h('div', { style: { fontSize: '14px' } }, card.inputTitle),
            // 出仓部分
            h('div', {
                style: {
                    display: 'flex',
                    alignItems: 'baseline',
                    gap: '8px'
                }
            }, [
                h('span', {
                    style: { fontSize: '32px', fontWeight: 500 }
                }, outFormatted.number),
                h('span', {
                    style: { fontSize: '14px' ,whiteSpace: 'nowrap'}
                }, outFormatted.unit)
            ]),
            h('div', { style: { fontSize: '14px' } }, card.outTitle)
        ]),
        h('i', {
            style: {
                fontSize: '58px',
                color: 'white',
                zIndex: 2,
                // padding: '40px 50px 40px 20px'
            },
            class: card.icon
        })
    ]);
});
const node = h('div', {
    style: {
        display: 'flex',
        justifyContent: 'space-between',
        marginTop: '20px'
    }
}, cards);
const app = JE.useVue().createApp({
    render() {
        return node;
    }
});
app.mount(container);
最后编辑: 呼丽华  文档更新时间: 2025-12-11 14:13   作者:呼丽华