20260808:大屏样式-时间范围便捷性调整
This commit is contained in:
parent
59a1f8dc61
commit
b2d9fe05c7
@ -26,6 +26,14 @@ INSERT INTO `sys_menu` VALUES(3604, '项目删除', 3600, 4, '#', '', NULL, 1, 0
|
|||||||
-- 子菜单:项目导出
|
-- 子菜单:项目导出
|
||||||
INSERT INTO `sys_menu` VALUES(3605, '项目导出', 3600, 5, '#', '', NULL, 1, 0, 'F', '0', '0', 'iot:project:export', '#', 'admin', NOW(), '', NULL, '');
|
INSERT INTO `sys_menu` VALUES(3605, '项目导出', 3600, 5, '#', '', NULL, 1, 0, 'F', '0', '0', 'iot:project:export', '#', 'admin', NOW(), '', NULL, '');
|
||||||
|
|
||||||
|
INSERT IGNORE INTO fastbee.sys_menu_translate (id, zh_cn, en_us) VALUES
|
||||||
|
(3372, '项目管理', 'Project management'),
|
||||||
|
(3373, '项目查询', 'Project query'),
|
||||||
|
(3374, '项目新增', 'Project add'),
|
||||||
|
(3375, '项目修改', 'Project edit'),
|
||||||
|
(3376, '项目删除', 'Project remove'),
|
||||||
|
(3377, '项目导出', 'Project export');
|
||||||
|
|
||||||
-- ========================================
|
-- ========================================
|
||||||
-- 菜单说明:
|
-- 菜单说明:
|
||||||
-- menu_id: 菜单ID(3600为主菜单,3601-3605为按钮权限)
|
-- menu_id: 菜单ID(3600为主菜单,3601-3605为按钮权限)
|
||||||
|
|||||||
@ -30,7 +30,7 @@ router.beforeEach((to, from, next) => {
|
|||||||
store.dispatch('GenerateRoutes').then((accessRoutes) => {
|
store.dispatch('GenerateRoutes').then((accessRoutes) => {
|
||||||
// 根据roles权限生成可访问的路由表
|
// 根据roles权限生成可访问的路由表
|
||||||
router.addRoutes(accessRoutes); // 动态添加可访问路由表
|
router.addRoutes(accessRoutes); // 动态添加可访问路由表
|
||||||
next({ path: '/bigscreen', replace: true }); // 登录后跳转到大数据看板
|
next({ ...to, replace: true }); // 保持当前目标路由,避免刷新后跳转
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|||||||
@ -1097,7 +1097,22 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.analysis-sidebar {
|
.analysis-sidebar {
|
||||||
grid-template-rows: 275px 1fr;
|
grid-template-rows: 400px 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分析条件卡片:固定高度,不滚动,避免布局跳动
|
||||||
|
.analysis-card:first-child {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测点列表卡片:内部滚动
|
||||||
|
.analysis-card:last-child {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.model-list {
|
||||||
|
height: calc(100% - 38px);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.analysis-content {
|
.analysis-content {
|
||||||
@ -1105,6 +1120,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.analysis-form {
|
.analysis-form {
|
||||||
|
.el-form-item {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.el-form-item__label {
|
.el-form-item__label {
|
||||||
color: #a8cff0;
|
color: #a8cff0;
|
||||||
}
|
}
|
||||||
@ -1228,3 +1247,121 @@
|
|||||||
.header-clock__week {
|
.header-clock__week {
|
||||||
font-size: 26px; /* 星期 */
|
font-size: 26px; /* 星期 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========== 时间范围选择器样式 ========== */
|
||||||
|
.time-preset-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
min-height: 64px; // 固定最小高度,容纳2行按钮
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-preset-btn {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
outline: none;
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid rgba(99, 184, 255, .35);
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #b8d9ff;
|
||||||
|
font-size: 12px;
|
||||||
|
background: rgba(4, 16, 56, .4);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color .18s, background .18s, border-color .18s;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #eaf8ff;
|
||||||
|
border-color: rgba(104, 224, 255, .6);
|
||||||
|
background: rgba(12, 45, 110, .55);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #fff;
|
||||||
|
border-color: rgba(69, 204, 255, .75);
|
||||||
|
background: linear-gradient(180deg, rgba(24, 96, 200, .9), rgba(10, 46, 120, .9));
|
||||||
|
box-shadow: 0 0 10px rgba(32, 150, 255, .35);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-range-display {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border: 1px solid rgba(71, 190, 255, .3);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(6, 22, 62, .5);
|
||||||
|
height: 56px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-shift-btn {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
outline: none;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px solid rgba(99, 184, 255, .35);
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #b8d9ff;
|
||||||
|
background: rgba(4, 16, 56, .4);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color .18s, background .18s, border-color .18s;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
color: #eaf8ff;
|
||||||
|
border-color: rgba(104, 224, 255, .6);
|
||||||
|
background: rgba(12, 45, 110, .55);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: .4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-range-text {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-range-start,
|
||||||
|
.time-range-end {
|
||||||
|
color: #dff7ff;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-range-end {
|
||||||
|
color: #80b5de;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义时间选择器样式增强 */
|
||||||
|
.analysis-form .el-date-editor--datetimerange {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|||||||
@ -240,13 +240,68 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="时间范围">
|
<el-form-item label="时间范围">
|
||||||
|
<!-- 预设时间按钮组 -->
|
||||||
|
<div class="time-preset-group">
|
||||||
|
<button
|
||||||
|
v-for="preset in timePresets"
|
||||||
|
:key="preset.key"
|
||||||
|
type="button"
|
||||||
|
class="time-preset-btn"
|
||||||
|
:class="{ active: analysisQuery.activePresetKey === preset.key }"
|
||||||
|
@click.stop="selectTimePreset(preset.key)"
|
||||||
|
>
|
||||||
|
{{ preset.shortLabel }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="time-preset-btn"
|
||||||
|
:class="{ active: analysisQuery.isCustomMode }"
|
||||||
|
@click.stop="enableCustomMode"
|
||||||
|
>
|
||||||
|
自定义
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 当前时间范围显示 -->
|
||||||
|
<div class="time-range-display">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="time-shift-btn"
|
||||||
|
:disabled="!canShiftLeft"
|
||||||
|
@click="shiftTimeLeft"
|
||||||
|
title="向前移动"
|
||||||
|
>
|
||||||
|
<i class="el-icon-arrow-left"></i>
|
||||||
|
</button>
|
||||||
|
<div class="time-range-text">
|
||||||
|
<div class="time-range-start">
|
||||||
|
{{ (analysisQuery.timeRange && analysisQuery.timeRange[0]) || '-' }}
|
||||||
|
</div>
|
||||||
|
<div class="time-range-end">
|
||||||
|
{{ (analysisQuery.timeRange && analysisQuery.timeRange[1]) || '-' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="time-shift-btn"
|
||||||
|
:disabled="!canShiftRight"
|
||||||
|
@click="shiftTimeRight"
|
||||||
|
title="向后移动"
|
||||||
|
>
|
||||||
|
<i class="el-icon-arrow-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 自定义时间选择器(仅在自定义模式下显示) -->
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
|
v-if="analysisQuery.isCustomMode"
|
||||||
v-model="analysisQuery.timeRange"
|
v-model="analysisQuery.timeRange"
|
||||||
type="datetimerange"
|
type="datetimerange"
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
range-separator="-"
|
range-separator="-"
|
||||||
start-placeholder="开始时间"
|
start-placeholder="开始时间"
|
||||||
end-placeholder="结束时间"
|
end-placeholder="结束时间"
|
||||||
|
@change="handleCustomTimeChange"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" :loading="analysisLoading" @click="runAnalysis">查询数据和曲线</el-button>
|
<el-button type="primary" icon="el-icon-search" :loading="analysisLoading" @click="runAnalysis">查询数据和曲线</el-button>
|
||||||
@ -397,13 +452,31 @@ export default {
|
|||||||
pendingProjectToFocus: null,
|
pendingProjectToFocus: null,
|
||||||
identifierList: [],
|
identifierList: [],
|
||||||
analysisLineList: [],
|
analysisLineList: [],
|
||||||
|
// 预设时间范围配置
|
||||||
|
timePresets: [
|
||||||
|
{ key: '5m', label: '过去 5 分钟', shortLabel: '5分钟', duration: { amount: 5, unit: 'minutes' }, moveStep: 5, moveUnit: 'minutes' },
|
||||||
|
{ key: '15m', label: '过去 15 分钟', shortLabel: '15分钟', duration: { amount: 15, unit: 'minutes' }, moveStep: 15, moveUnit: 'minutes' },
|
||||||
|
{ key: '1h', label: '过去 1 小时', shortLabel: '1小时', duration: { amount: 1, unit: 'hours' }, moveStep: 1, moveUnit: 'hours' },
|
||||||
|
{ key: '4h', label: '过去 4 小时', shortLabel: '4小时', duration: { amount: 4, unit: 'hours' }, moveStep: 4, moveUnit: 'hours' },
|
||||||
|
{ key: '12h', label: '过去 12 小时', shortLabel: '12小时', duration: { amount: 12, unit: 'hours' }, moveStep: 12, moveUnit: 'hours' },
|
||||||
|
{ key: '24h', label: '过去 24 小时', shortLabel: '24小时', duration: { amount: 24, unit: 'hours' }, moveStep: 24, moveUnit: 'hours' },
|
||||||
|
{ key: '2d', label: '过去 2 天', shortLabel: '2天', duration: { amount: 2, unit: 'days' }, moveStep: 2, moveUnit: 'days' },
|
||||||
|
{ key: '3d', label: '过去 3 天', shortLabel: '3天', duration: { amount: 3, unit: 'days' }, moveStep: 3, moveUnit: 'days' },
|
||||||
|
{ key: '5d', label: '过去 5 天', shortLabel: '5天', duration: { amount: 5, unit: 'days' }, moveStep: 5, moveUnit: 'days' },
|
||||||
|
{ key: '7d', label: '过去 7 天', shortLabel: '7天', duration: { amount: 7, unit: 'days' }, moveStep: 7, moveUnit: 'days' },
|
||||||
|
],
|
||||||
analysisQuery: {
|
analysisQuery: {
|
||||||
deviceId: null,
|
deviceId: null,
|
||||||
timeRange: [
|
timeRange: [
|
||||||
moment().subtract(2, 'hours').format('YYYY-MM-DD HH:mm:ss'),
|
moment().subtract(1, 'hours').format('YYYY-MM-DD HH:mm:ss'),
|
||||||
moment().format('YYYY-MM-DD HH:mm:ss'),
|
moment().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
],
|
], // 默认过去1小时,避免初始为空
|
||||||
|
activePresetKey: '1h', // 默认选中"过去 1 小时"
|
||||||
|
isCustomMode: false, // 是否自定义时间模式
|
||||||
},
|
},
|
||||||
|
customTimeVisible: false, // 自定义时间选择器是否显示
|
||||||
|
canShiftLeft: true, // 是否可以向左移动
|
||||||
|
canShiftRight: true, // 是否可以向右移动(初始时可以,因为时间窗口可以向前移动)
|
||||||
scrollOption: {
|
scrollOption: {
|
||||||
step: 0.8,
|
step: 0.8,
|
||||||
limitMoveNum: 4,
|
limitMoveNum: 4,
|
||||||
@ -602,6 +675,10 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.$nextTick(() => this.calcRate());
|
this.$nextTick(() => this.calcRate());
|
||||||
this.timeFn();
|
this.timeFn();
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// 确保 timeRange 已初始化后再更新按钮状态
|
||||||
|
this.updateShiftButtonState();
|
||||||
|
});
|
||||||
this.loadCockpitData();
|
this.loadCockpitData();
|
||||||
this.fetchHeaderUser();
|
this.fetchHeaderUser();
|
||||||
},
|
},
|
||||||
@ -1182,6 +1259,125 @@ export default {
|
|||||||
this.identifierList = [];
|
this.identifierList = [];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// ========== 时间范围选择器方法 ==========
|
||||||
|
// 选择预设时间范围
|
||||||
|
selectTimePreset(presetKey) {
|
||||||
|
const preset = this.timePresets.find(p => p.key === presetKey);
|
||||||
|
if (!preset) return;
|
||||||
|
|
||||||
|
const endTime = moment();
|
||||||
|
const startTime = moment().subtract(preset.duration.amount, preset.duration.unit);
|
||||||
|
|
||||||
|
this.analysisQuery.timeRange = [
|
||||||
|
startTime.format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
endTime.format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
];
|
||||||
|
this.analysisQuery.activePresetKey = presetKey;
|
||||||
|
this.analysisQuery.isCustomMode = false;
|
||||||
|
this.customTimeVisible = false;
|
||||||
|
|
||||||
|
// 更新移动按钮状态
|
||||||
|
this.updateShiftButtonState();
|
||||||
|
|
||||||
|
// 如果已经选择了设备,自动触发查询
|
||||||
|
if (this.analysisQuery.deviceId && this.activeMode === 'analysis') {
|
||||||
|
this.$nextTick(() => this.runAnalysis());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 左移时间窗口(往前推)
|
||||||
|
shiftTimeLeft() {
|
||||||
|
if (!this.canShiftLeft) return;
|
||||||
|
|
||||||
|
const preset = this.getActivePreset();
|
||||||
|
if (!preset) return;
|
||||||
|
|
||||||
|
const [startTime, endTime] = this.analysisQuery.timeRange;
|
||||||
|
const newStartTime = moment(startTime).subtract(preset.moveStep, preset.moveUnit);
|
||||||
|
const newEndTime = moment(endTime).subtract(preset.moveStep, preset.moveUnit);
|
||||||
|
|
||||||
|
// 更新时间范围
|
||||||
|
this.analysisQuery.timeRange = [
|
||||||
|
newStartTime.format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
newEndTime.format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
];
|
||||||
|
|
||||||
|
// 更新移动按钮状态
|
||||||
|
this.updateShiftButtonState();
|
||||||
|
|
||||||
|
// 自动触发查询
|
||||||
|
if (this.analysisQuery.deviceId) {
|
||||||
|
this.$nextTick(() => this.runAnalysis());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 右移时间窗口(往后推)
|
||||||
|
shiftTimeRight() {
|
||||||
|
if (!this.canShiftRight) return;
|
||||||
|
|
||||||
|
const preset = this.getActivePreset();
|
||||||
|
if (!preset) return;
|
||||||
|
|
||||||
|
const [startTime, endTime] = this.analysisQuery.timeRange;
|
||||||
|
const newStartTime = moment(startTime).add(preset.moveStep, preset.moveUnit);
|
||||||
|
const newEndTime = moment(endTime).add(preset.moveStep, preset.moveUnit);
|
||||||
|
|
||||||
|
// 不允许超过当前时间
|
||||||
|
if (newEndTime.isAfter(moment())) return;
|
||||||
|
|
||||||
|
// 更新时间范围
|
||||||
|
this.analysisQuery.timeRange = [
|
||||||
|
newStartTime.format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
newEndTime.format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
];
|
||||||
|
|
||||||
|
// 更新移动按钮状态
|
||||||
|
this.updateShiftButtonState();
|
||||||
|
|
||||||
|
// 自动触发查询
|
||||||
|
if (this.analysisQuery.deviceId) {
|
||||||
|
this.$nextTick(() => this.runAnalysis());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 启用自定义时间模式
|
||||||
|
enableCustomMode() {
|
||||||
|
this.analysisQuery.isCustomMode = true;
|
||||||
|
this.analysisQuery.activePresetKey = null;
|
||||||
|
this.canShiftLeft = false;
|
||||||
|
this.canShiftRight = false;
|
||||||
|
// 强制触发视图更新
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
// 自定义时间改变事件
|
||||||
|
handleCustomTimeChange() {
|
||||||
|
// 自定义时间模式下,禁用移动按钮
|
||||||
|
this.canShiftLeft = false;
|
||||||
|
this.canShiftRight = false;
|
||||||
|
},
|
||||||
|
// 获取当前激活的预设配置
|
||||||
|
getActivePreset() {
|
||||||
|
if (!this.analysisQuery.activePresetKey) return null;
|
||||||
|
return this.timePresets.find(p => p.key === this.analysisQuery.activePresetKey);
|
||||||
|
},
|
||||||
|
// 更新移动按钮状态
|
||||||
|
updateShiftButtonState() {
|
||||||
|
const preset = this.getActivePreset();
|
||||||
|
|
||||||
|
if (!preset || this.analysisQuery.isCustomMode) {
|
||||||
|
// 自定义时间模式下,禁用移动按钮
|
||||||
|
this.canShiftLeft = false;
|
||||||
|
this.canShiftRight = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [startTime, endTime] = this.analysisQuery.timeRange;
|
||||||
|
const now = moment();
|
||||||
|
|
||||||
|
// 检查是否可以向左移动(总是可以,除非已经是历史最早时间)
|
||||||
|
this.canShiftLeft = true;
|
||||||
|
|
||||||
|
// 检查是否可以向右移动(结束时间 + 步长 不能超过当前时间)
|
||||||
|
const testEndTime = moment(endTime).add(preset.moveStep, preset.moveUnit);
|
||||||
|
this.canShiftRight = testEndTime.isSameOrBefore(now);
|
||||||
|
},
|
||||||
runAnalysis() {
|
runAnalysis() {
|
||||||
const device = this.selectedAnalysisDevice;
|
const device = this.selectedAnalysisDevice;
|
||||||
if (!device) {
|
if (!device) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user