| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- <template>
- <div class="equip-list-and-timeline">
- <!-- 列表 -->
- <div class="list-wrap fill-scroll">
- <!-- 靶标 -->
- <el-table
- v-if="typeKey==='target'"
- :data="items"
- border
- size="small"
- stripe
- >
- <el-table-column label="名称" min-width="160" prop="name"/>
- <el-table-column label="类型" prop="type" width="80"/>
- <el-table-column label="经度" min-width="140" prop="lon"/>
- <el-table-column label="纬度" min-width="140" prop="lat"/>
- <el-table-column label="激活时间" prop="time" width="110"/>
- <el-table-column align="center" label="操作" width="200">
- <template slot-scope="scope">
- <el-button
- icon="el-icon-edit"
- size="mini"
- type="text"
- @click="$emit('edit', scope.$index)"
- >编辑</el-button>
- <el-button
- class="danger-btn"
- icon="el-icon-delete"
- size="mini"
- type="text"
- @click="$emit('remove', scope.$index)"
- >删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- <!-- 干扰 -->
- <el-table
- v-if="typeKey==='jammer'"
- :data="items"
- border
- size="small"
- stripe
- >
- <el-table-column label="名称" min-width="160" prop="name"/>
- <el-table-column label="类型" prop="type" width="80"/>
- <el-table-column label="经度" min-width="140" prop="lon"/>
- <el-table-column label="纬度" min-width="140" prop="lat"/>
- <el-table-column align="center" label="操作" width="220">
- <template slot-scope="scope">
- <el-button
- icon="el-icon-edit"
- size="mini"
- type="text"
- @click="$emit('edit', scope.$index)"
- >编辑</el-button>
- <el-button
- class="danger-btn"
- icon="el-icon-delete"
- size="mini"
- type="text"
- @click="$emit('remove', scope.$index)"
- >删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- <!-- 测量 -->
- <el-table
- v-if="typeKey==='measurement'"
- :data="items"
- border
- size="small"
- stripe
- >
- <el-table-column label="名称" min-width="160" prop="name"/>
- <el-table-column label="类型" prop="type" width="80"/>
- <el-table-column label="经度" min-width="140" prop="lon"/>
- <el-table-column label="纬度" min-width="140" prop="lat"/>
- <el-table-column label="启动时间" prop="time" width="110"/>
- <el-table-column align="center" label="操作" width="200">
- <template slot-scope="scope">
- <el-button
- icon="el-icon-edit"
- size="mini"
- type="text"
- @click="$emit('edit', scope.$index)"
- >编辑</el-button>
- <el-button
- class="danger-btn"
- icon="el-icon-delete"
- size="mini"
- type="text"
- @click="$emit('remove', scope.$index)"
- >删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <!-- 当前类事件时序 -->
- <div class="timeline-section">
- <div class="section-title">
- <i class="el-icon-time"></i><span>事件时序</span>
- <el-button size="mini" type="text" @click="$emit('refresh')">刷新</el-button>
- </div>
- <div class="timeline-wrap fill-scroll">
- <el-timeline>
- <el-timeline-item
- v-for="(e,i) in currentPreviewEvents"
- :key="i"
- :timestamp="e.time"
- :type="getTimelineType(e.typeClass)"
- placement="top"
- >
- <el-card :shadow="false" class="ui-card soft tl-card">
- <div class="tl-title">{{ e.title }}</div>
- <div class="tl-desc">
- {{ e.desc }}
- <el-tag :type="getTagType(e.badgeClass)" class="m-l-6" size="mini">
- {{ e.kindText }}
- </el-tag>
- <el-tag v-if="e.triggerTypeText" class="m-l-6" size="mini" type="info">
- {{ e.triggerTypeText }}
- </el-tag>
- </div>
- </el-card>
- </el-timeline-item>
- </el-timeline>
- </div>
- </div>
- </div>
- </template>
- <script>
- export default {
- name: 'EquipmentListWithTimeline',
- props: {
- /**
- * 'target' | 'jammer' | 'measurement'
- */
- typeKey: {
- type: String,
- required: true
- },
- /**
- * 列表数据(随 typeKey 结构不同):
- * target: { name,type,lon,lat,time,statusText,statusClass,params }
- * jammer: { name,type,lon,lat,params,schedules:[{time,triggerType,triggerDesc,delaySec}] }
- * measurement: { name,type,lon,lat,time,params }
- */
- items: {
- type: Array,
- default: () => []
- }
- },
- computed: {
- currentPreviewEvents() {
- const list = [];
- if (this.typeKey === 'target') {
- this.items.forEach(t => {
- if (!t.time) return;
- list.push({
- time: `T0+${t.time}`,
- rawTime: t.time,
- title: t.type === '动态' ? '动态靶标运行' : '靶标激活',
- desc: `${t.name} ${t.type === '动态' ? '按设定运动' : '激活'}`,
- kindText: '靶标装备',
- typeClass: t.type === '动态' ? 'tl-danger' : 'tl-warn',
- badgeClass: t.statusText === '可用'
- ? 'badge-success'
- : (t.statusText === '维护中' ? 'badge-warn' : 'badge-accent'),
- triggerTypeText: '定时触发'
- });
- });
- } else if (this.typeKey === 'jammer') {
- this.items.forEach(j => {
- (j.schedules || []).forEach(s => {
- if (!s.time) return;
- list.push({
- time: `T0+${s.time}`,
- rawTime: s.time,
- title: '干扰装备启动',
- desc: `${j.name} ${s.triggerType === 'condition' ? '(条件触发)' : '(激活)'}`,
- kindText: '干扰装备',
- typeClass: s.triggerType === 'condition' ? 'tl-danger' : 'tl-muted',
- badgeClass: s.triggerType === 'condition' ? 'badge-danger' : 'badge-accent',
- triggerTypeText: s.triggerType === 'time'
- ? '定时触发'
- : (s.triggerType === 'manual' ? '手动触发' : '条件触发')
- });
- });
- });
- } else if (this.typeKey === 'measurement') {
- this.items.forEach(m => {
- if (!m.time) return;
- list.push({
- time: `T0+${m.time}`,
- rawTime: m.time,
- title: '测量装备启动',
- desc: `${m.name} 开始工作`,
- kindText: '测量装备',
- typeClass: 'tl-secondary',
- badgeClass: 'badge-secondary',
- triggerTypeText: '定时触发'
- });
- });
- }
- return list.sort((a, b) => this.hhmmssToSec(a.rawTime) - this.hhmmssToSec(b.rawTime));
- }
- },
- methods: {
- hhmmssToSec(hms) {
- const [h = 0, m = 0, s = 0] = (hms || '00:00:00').split(':').map(n => parseInt(n, 10) || 0);
- return h * 3600 + m * 60 + s;
- },
- getTimelineType(c) {
- return c === 'tl-secondary'
- ? 'success'
- : c === 'tl-warn'
- ? 'warning'
- : c === 'tl-danger'
- ? 'danger'
- : c === 'tl-muted'
- ? 'info'
- : 'primary';
- },
- getTagType(c) {
- return c === 'badge-success'
- ? 'success'
- : c === 'badge-warn'
- ? 'warning'
- : c === 'badge-danger'
- ? 'danger'
- : c === 'badge-accent'
- ? 'info'
- : c === 'badge-secondary'
- ? 'primary'
- : 'default';
- }
- }
- };
- </script>
- <style scoped>
- /* 仅此组件样式(不污染父页) */
- .equip-list-and-timeline{
- display:grid;
- grid-template-rows: 1fr 1fr;
- gap:12px;
- min-height:0;
- height:100%;
- }
- /* 列表与时间轴容器复用父页命名,便于主题一致 */
- .list-wrap{ min-height:0; overflow:auto; }
- .timeline-section{ display:flex; flex-direction:column; min-height:0; }
- .section-title{ display:flex; align-items:center; gap:8px; margin:0 2px 6px; color:#EAF2FF; font-weight:700; }
- .timeline-wrap{ padding-right:4px; overflow:auto; }
- /* 质感与父页统一 */
- ::v-deep .el-table{
- background:var(--card-soft);
- color:var(--text-2);
- border-color:rgba(255,255,255,.08);
- }
- ::v-deep .el-table th{
- background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.03));
- color:var(--text); font-weight:700;
- border-color:rgba(255,255,255,.08);
- }
- ::v-deep .el-table td{ border-color:rgba(255,255,255,.06); }
- ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td{ background:rgba(255,255,255,.02); }
- ::v-deep .el-table__row:hover td{ background:rgba(102,177,255,.06)!important; }
- .tl-card{ border-left:3px solid var(--accent); padding:10px 12px; background:rgba(255,255,255,.03)!important; }
- .tl-title{ font-weight:800; color:#EAF2FF; margin-bottom:4px; font-size:14px; }
- .tl-desc{ font-size:12px; color:var(--text-2); }
- .m-l-6{ margin-left:6px; }
- /* 时间轴节点颜色与父页一致 */
- .el-timeline-item__tail{ border-left-color:rgba(255,255,255,.08)!important; }
- .el-timeline-item.is-success .el-timeline-item__node{ background:#2BD99F!important; }
- .el-timeline-item.is-warning .el-timeline-item__node{ background:#FFC15A!important; }
- .el-timeline-item.is-danger .el-timeline-item__node{ background:#FF7070!important; }
- .el-timeline-item.is-info .el-timeline-item__node{ background:#69B1FF!important; }
- /* Tag 质感 */
- .el-tag--success{ background:rgba(43,217,159,.15); border-color:rgba(43,217,159,.35); color:#2BD99F; }
- .el-tag--warning{ background:rgba(255,193,90,.15); border-color:rgba(255,193,90,.35); color:#FFC15A; }
- .el-tag--danger { background:rgba(255,112,112,.15); border-color:rgba(255,112,112,.35); color:#FF7070; }
- .el-tag--info { background:rgba(105,177,255,.12); border-color:rgba(105,177,255,.35); color:#9ED0FF; }
- .el-tag--primary{ background:rgba(105,177,255,.18); border-color:rgba(105,177,255,.4); color:#E8F3FF; }
- /* 删除按钮色 */
- .danger-btn{ color: var(--danger); }
- </style>
|