Merge branch 'master' of git.code.tencent.com:xian-ncc-da/xian-ncc-da-client

This commit is contained in:
Yuan 2023-07-19 09:00:56 +08:00
commit 438829ddab
12 changed files with 187 additions and 90 deletions

View File

@ -44,7 +44,7 @@ export async function alarmInfoPageQuery(
* id获取决策信息
* @param id 稿id
*/
export function queryAlarmInfoById(id: number): Promise<Item> {
export function queryAlarmInfoById(id: number): Promise<AlarmInfo<Item>> {
return api.get(`${DraftUriBase}/id/${id}`);
}
@ -73,3 +73,7 @@ export function deleteAlarmInfo(id: number) {
export function updataAlarmInfo(id: number, data: Item) {
return api.put(`${DraftUriBase}/id`, data);
}
export interface AlarmInfo<T = unknown> {
data: T;
}

View File

@ -7,8 +7,12 @@ const emit = defineEmits([...useDialogPluginComponent.emits]);
const props = withDefaults(
defineProps<{
title?: string;
titleHeight?: number;
titleColor?: string;
fontSize?: number;
width?: number;
height?: number;
bgColor?: string;
}>(),
{ width: 500, height: 800 }
);
@ -63,15 +67,21 @@ function onHide() {
class="column"
>
<q-card
:style="{ transform: `translate3d(${offset.x}px, ${offset.y}px, 1px)` }"
:style="{
transform: `translate3d(${offset.x}px, ${offset.y}px, 1px)`,
background: `${props.bgColor}`,
}"
style="max-width: 2000px"
>
<q-bar
ref="headerRef"
class="bg-primary text-white non-selectable q-gutter-l"
class="non-selectable q-gutter-l"
style="cursor: move"
:style="`height: ${props.titleHeight}px;background: ${props.titleColor}`"
>
<div>{{ props.title }}</div>
<div :style="`font-size: ${props.fontSize}px;`">
{{ props.title }}
</div>
<q-space />
<q-btn dense flat icon="sym_o_close" v-close-popup></q-btn>
</q-bar>

View File

@ -20,10 +20,26 @@
<q-list bordered separator class="rounded-borders">
<q-item>
<q-item-section no-wrap class="q-gutter-y-sm column">
<q-item-label> 关联的区段 </q-item-label>
<q-item-label> 关联的逻辑区段 </q-item-label>
<div class="q-gutter-sm row">
<q-chip
v-for="item in relatedProcessPositions"
v-for="item in relatedLogicSection"
:key="item.id"
square
color="primary"
text-color="white"
>
{{ item.datas.code }}
</q-chip>
</div>
</q-item-section>
</q-item>
<q-item>
<q-item-section no-wrap class="q-gutter-y-sm column">
<q-item-label> 关联的道岔 </q-item-label>
<div class="q-gutter-sm row">
<q-chip
v-for="item in relatedTurnout"
:key="item.id"
square
color="primary"
@ -40,8 +56,9 @@
<script setup lang="ts">
import { TrainWindowData } from 'src/drawApp/graphics/TrainWindowInteraction';
import { Section } from 'src/graphics/section/Section';
import { LogicSection } from 'src/graphics/logicSection/LogicSection';
import { TrainWindow } from 'src/graphics/trainWindow/TrainWindow';
import { Turnout } from 'src/graphics/turnout/Turnout';
import { useDrawStore } from 'src/stores/draw-store';
import { computed, onMounted, reactive, watch } from 'vue';
@ -74,7 +91,7 @@ function onUpdate() {
}
}
const relatedProcessPositions = computed((): Section[] => {
const relatedLogicSection = computed((): LogicSection[] => {
if (
drawStore.selectedGraphic &&
drawStore.selectedGraphic.type === 'TrainWindow'
@ -83,4 +100,13 @@ const relatedProcessPositions = computed((): Section[] => {
}
return [];
});
const relatedTurnout = computed((): Turnout[] => {
if (
drawStore.selectedGraphic &&
drawStore.selectedGraphic.type === 'TrainWindow'
) {
return (drawStore.selectedGraphic as TrainWindow).getRelatedTurnouts();
}
return [];
});
</script>

View File

@ -6,6 +6,7 @@ import { queryAlarmInfoById } from 'src/api/DecisionInfo';
import { ApiError } from 'src/boot/axios';
import { useQuasar } from 'quasar';
const bgColor = 'yellow';
const $q = useQuasar();
const lineNetStore = useLineNetStore();
const alarmInfo = ref({
@ -17,12 +18,13 @@ const alarmInfo = ref({
info: '',
reason: '',
});
alarmInfo.value.time = lineNetStore.alarmInfo[0].alert_time;
alarmInfo.value.level = lineNetStore.alarmInfo[0].level;
alarmInfo.value.deviceInfo = lineNetStore.alarmInfo[0].device_info;
alarmInfo.value.info = lineNetStore.alarmInfo[0].info;
alarmInfo.value.reason = lineNetStore.alarmInfo[0].reason;
const drivingInfo = ref('');
const submissionInfo = ref('');
onMounted(() => {
search();
@ -32,7 +34,9 @@ async function search() {
try {
const id = lineNetStore.alarmInfo[0].alert_tip_id;
const response = await queryAlarmInfoById(id);
alarmInfo.value.type = response.type;
alarmInfo.value.type = response.data.alertType;
drivingInfo.value = JSON.parse(response.data.drivingInfo);
submissionInfo.value = JSON.parse(response.data.submissionInfo);
} catch (err) {
const error = err as ApiError;
$q.notify({
@ -44,49 +48,65 @@ async function search() {
</script>
<template>
<DraggableDialog seamless title="设备故障" :width="720" :height="380">
<draggable-dialog
seamless
title="设备故障"
:titleColor="`${bgColor}`"
titleHeight="40"
:fontSize="22"
:width="720"
:height="440"
:bgColor="`${bgColor}`"
>
<div>
<div alarm-message class="alarm-message">
<q-card class="box-card">
<div class="text-h6">故障信息</div>
<div class="head">故障信息</div>
<q-separator />
<div class="alarm-message-detail">
<div class="left">
<div class="text">时间:{{ alarmInfo.time }}</div>
<div class="text">级别:{{ alarmInfo.level }}</div>
<div class="text">设备:{{ alarmInfo.deviceInfo }}</div>
<div class="text">类型:{{ alarmInfo.type }}</div>
</div>
<div class="right">
<div class="text">类型:{{ alarmInfo.type }}</div>
<div class="text">信息:{{ alarmInfo.info }}</div>
<div class="text">原因:{{ alarmInfo.reason }}</div>
<div class="text">信息:{{ alarmInfo.info }}</div>
</div>
</div>
</q-card>
</div>
<div class="decision-message">
<q-card class="box-card">
<div class="text-h6">行车方面</div>
<div class="head">行车方面</div>
<q-separator />
<div>
<div class="text item">1核对站级ATS是否蓝显</div>
<div class="text">{{ drivingInfo }}</div>
</div>
</q-card>
<q-card class="box-card">
<div class="text-h6">信息报送方面</div>
<div class="head">信息报送方面</div>
<q-separator />
<div>
<div class="text item">
1文字信息发党群信息群故障群/应急群
</div>
<div class="text">{{ submissionInfo }}</div>
</div>
</q-card>
</div>
</div>
</DraggableDialog>
</draggable-dialog>
</template>
<style lang='scss' scoped>
.alarm-message {
padding: 15px 10px 5px 10px;
padding: 5px 10px 5px 10px;
.box-card {
padding: 0 5px;
.head {
padding: 5px 5px;
font-size: 16px;
font-weight: 600;
}
.alarm-message-detail {
display: flex;
.left,
@ -94,7 +114,7 @@ async function search() {
width: 50%;
padding: 0 5px;
.text {
font-size: 18px;
font-size: 16px;
margin-bottom: 10px;
}
}
@ -106,12 +126,17 @@ async function search() {
justify-content: space-between;
padding: 10px;
.box-card {
.head {
padding: 5px 5px;
font-size: 16px;
font-weight: 600;
}
width: 49%;
padding: 0 5px;
.text {
white-space: pre-wrap;
padding: 0 5px;
font-size: 14px;
}
.item {
margin-bottom: 10px;
}
}

View File

@ -31,11 +31,11 @@ export class TrainWindowData
set code(v: string) {
this.data.code = v;
}
get sectionId(): string {
return this.data.sectionId;
get refDeviceId(): string[] {
return this.data.refDeviceId;
}
set sectionId(v: string) {
this.data.sectionId = v;
set refDeviceId(v: string[]) {
this.data.refDeviceId = v;
}
clone(): TrainWindowData {
return new TrainWindowData(this.data.cloneMessage());

View File

@ -193,9 +193,6 @@ export class PathLine extends JlGraphic {
}
}
});
if (sta.datas.code === '延平门') {
console.log(fp);
}
if (fp) {
kilometerPoints.push({
point: new Point(fp?.['x'], fp?.['y']),

View File

@ -31,6 +31,11 @@ export interface ITrainLineState extends GraphicState {
set dir(v: number);
}
const trainLineConsts = {
scaleX: 0.04,
scaleY: 0.04,
};
export class TrainLine extends JlGraphic {
static Type = 'TrainLine';
train: Sprite;
@ -41,8 +46,8 @@ export class TrainLine extends JlGraphic {
this.trainTextures = trainTextures;
this.train = new Sprite();
this.train.texture = this.trainTextures;
this.train.anchor.set(0.5);
this.train.scale.set(0.02, 0.02);
this.train.anchor.set(0.5, 0.1);
this.train.scale.set(trainLineConsts.scaleX, trainLineConsts.scaleY);
this.addChild(this.train);
this.zIndex = 1;
}
@ -113,9 +118,9 @@ export class TrainLine extends JlGraphic {
const py = startP.y + Math.round(offset * (endP.y - startP.y));
const angle = Math.atan2(endP.y - startP.y, endP.x - startP.x);
if (goalPath.datas.isKmIncrease) {
this.train.scale.set(-0.02, 0.02);
this.train.scale.set(-trainLineConsts.scaleX, -trainLineConsts.scaleY);
} else {
this.train.scale.set(0.02, 0.02);
this.train.scale.set(trainLineConsts.scaleX, trainLineConsts.scaleY);
}
this.train.position.set(px, py);
this.train.rotation = angle;

View File

@ -1,19 +1,18 @@
import { Color, Graphics, Rectangle } from 'pixi.js';
import {
GraphicData,
GraphicRelationParam,
JlGraphic,
JlGraphicTemplate,
distance2,
getRectangleCenter,
} from 'src/jl-graphic';
import { Section, SectionType } from '../section/Section';
import { LogicSection } from '../logicSection/LogicSection';
import { Turnout } from '../turnout/Turnout';
export interface ITrainWindowData extends GraphicData {
get code(): string; // 编号
set code(v: string);
get sectionId(): string; // 关联的区段的id
set sectionId(v: string);
get refDeviceId(): string[]; // 关联的区段的id
set refDeviceId(v: string[]);
clone(): ITrainWindowData;
copyFrom(data: ITrainWindowData): void;
eq(other: ITrainWindowData): boolean;
@ -38,13 +37,7 @@ export class TrainWindow extends JlGraphic {
return this.getDatas<ITrainWindowData>();
}
doRepaint(): void {
const section = this.queryStore.queryById<Section>(this.datas.sectionId);
let width = TrainWindowConsts.width;
if (section.datas.sectionType == SectionType.Logic) {
const ps = section.getStartPoint();
const pe = section.getEndPoint();
width = distance2(ps, pe);
}
const width = TrainWindowConsts.width;
const rectGraphic = this.rectGraphic;
rectGraphic.clear();
rectGraphic.lineStyle(
@ -56,20 +49,28 @@ export class TrainWindow extends JlGraphic {
rectGraphic.pivot = getRectangleCenter(rectP);
}
loadRelations(): void {
const sectionId = this.datas.sectionId;
if (sectionId) {
const section = this.queryStore.queryById<Section>(sectionId);
if (section) {
this.relationManage.addRelation(
this,
new GraphicRelationParam(section, section.datas.id)
);
}
const refDeviceId = this.datas.refDeviceId;
if (refDeviceId) {
refDeviceId.forEach((id) => {
const logicSection = this.queryStore.queryById<LogicSection>(id);
if (logicSection && logicSection.type == 'LogicSection') {
this.relationManage.addRelation(this, logicSection);
}
const turnout = this.queryStore.queryById<Turnout>(id);
if (turnout && turnout.type == 'Turnout') {
this.relationManage.addRelation(this, turnout);
}
});
}
}
getRelatedSections(): Section[] {
return this.queryRelationByType('Section').map((rl) =>
rl.getOtherGraphic<Section>(this)
getRelatedSections(): LogicSection[] {
return this.queryRelationByType('LogicSection').map((rl) =>
rl.getOtherGraphic<LogicSection>(this)
);
}
getRelatedTurnouts(): Turnout[] {
return this.queryRelationByType('Turnout').map((rl) =>
rl.getOtherGraphic<Turnout>(this)
);
}
}

View File

@ -7,7 +7,6 @@ import {
GraphicInteractionPlugin,
JlDrawApp,
JlGraphic,
distance2,
linePoint,
} from 'src/jl-graphic';
@ -18,6 +17,7 @@ import {
TrainWindowConsts,
} from './TrainWindow';
import { Section, SectionType } from '../section/Section';
import { LogicSection } from '../logicSection/LogicSection';
export interface ITrainWindowDrawOptions {
newData: () => ITrainWindowData;
@ -95,12 +95,24 @@ export class TrainWindowDraw extends GraphicDrawAssistant<
}
this.storeGraphic(...trainWindows);
}
draw(x: number, ps: Point, direction: number, section: Section) {
draw(
x: number,
ps: Point,
direction: number,
section: Section | LogicSection
) {
const trainWindow = new TrainWindow();
trainWindow.loadData(this.graphicTemplate.datas);
trainWindow.position.set(x, ps.y);
if (section.type == 'LogicSection') {
trainWindow.position.set(
x,
ps.y - direction * TrainWindowConsts.offsetSection
);
} else {
trainWindow.position.set(x, ps.y);
}
trainWindow.id = GraphicIdGenerator.next();
trainWindow.datas.sectionId = section.id;
trainWindow.datas.refDeviceId = [section.id];
this.storeGraphic(trainWindow);
trainWindow.loadRelations();
}
@ -108,28 +120,33 @@ export class TrainWindowDraw extends GraphicDrawAssistant<
const turnoutSections = this.app.queryStore
.queryByType<Section>(Section.Type)
.filter((g) => g.datas.sectionType == SectionType.TurnoutPhysical);
const logicSections = this.app.queryStore.queryByType<LogicSection>(
LogicSection.Type
);
const trainWindowAll = this.app.queryStore.queryByType<TrainWindow>(
TrainWindow.Type
);
this.app.deleteGraphics(...trainWindowAll);
turnoutSections.forEach((section) => {
const ps = section.localToCanvasPoint(section.getStartPoint());
const pe = section.localToCanvasPoint(section.getEndPoint());
let direction = 1;
if (ps.y > height.y) {
direction = -1;
}
const x = section.labelGraphic.position.x;
if (section.datas.children.length) {
section.childSections.forEach((childSection) => {
const psChild = childSection.localToCanvasPoint(
childSection.getStartPoint()
);
this.draw(psChild.x, psChild, direction, childSection);
});
} else {
this.draw(x, ps, direction, section);
this.draw(x, ps, direction, section);
});
logicSections.forEach((logicSection) => {
const ps = logicSection.localToCanvasPoint(logicSection.datas.points[0]);
const pe = logicSection.localToCanvasPoint(
logicSection.datas.points[logicSection.datas.points.length - 1]
);
let direction = 1;
if (ps.y > height.y) {
direction = -1;
}
const x = (ps.x + pe.x) / 2;
this.draw(x, ps, direction, logicSection);
});
}
}
@ -141,15 +158,7 @@ export class RectGraphicHitArea implements IHitArea {
this.rect = rect;
}
contains(x: number, y: number): boolean {
const section = this.rect.queryStore.queryById<Section>(
this.rect.datas.sectionId
);
let width = TrainWindowConsts.width;
if (section.datas.sectionType == SectionType.Logic) {
const ps = section.getStartPoint();
const pe = section.getEndPoint();
width = distance2(ps, pe);
}
const width = TrainWindowConsts.width;
let contains = false;
const tolerance = TrainWindowConsts.lineWidth;
const p1 = new Point(0, 0);

View File

@ -14,6 +14,11 @@
binary-state-sort
@request="onRequest"
>
<template v-slot:body-cell="props">
<q-td :props="props" class="custom-column">
{{ props.value }}
</q-td>
</template>
<template v-slot:top-right>
<q-input
dense
@ -51,14 +56,14 @@
transition-show="scale"
transition-hide="scale"
>
<q-card style="width: 300px">
<q-card style="width: 500px">
<q-form
ref="myForm"
@submit="onCreate"
@reset="onReset"
class="q-gutter-md"
>
<q-card-section>
<q-card-section class="q-gutter-sm">
<div class="text-h6">
{{ creatForm.id ? '编辑决策信息' : '新建决策信息' }}
</div>
@ -84,11 +89,13 @@
<q-input
outlined
label="行车方面"
type="textarea"
v-model="creatForm.drivingInfo"
lazy-rules
/>
<q-input
outlined
type="textarea"
label="信息报送方面"
v-model="creatForm.submissionInfo"
lazy-rules
@ -320,3 +327,12 @@ async function deleteData(row: any) {
});
}
</script>
<style scoped>
.custom-column {
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

View File

@ -64,7 +64,7 @@ function onResize() {
watch(
() => lineNetStore.alarmInfo,
(val) => {
if (val.length) {
if (val.length && !lineNetStore.alarmDialog) {
alarm();
}
}
@ -72,7 +72,10 @@ watch(
const $q = useQuasar();
function alarm() {
$q.dialog({ component: errrorMessageBox });
lineNetStore.alarmDialog = true;
$q.dialog({ component: errrorMessageBox }).onCancel(() => {
lineNetStore.alarmDialog = false;
});
}
onMounted(() => {

View File

@ -5,7 +5,7 @@ import {
getLineNetApp,
destroyLineNetApp,
} from 'src/drawApp/lineNetApp';
interface alarmInfo {
export interface AlarmInfo {
alert_tip_id: number;
id: string;
alert_time: string;
@ -18,7 +18,8 @@ export const useLineNetStore = defineStore('lineNet', {
state: () => ({
selectedGraphics: null as JlGraphic[] | null,
lineNetName: null as string | null,
alarmInfo: [] as alarmInfo[], //报警信息
alarmInfo: [] as AlarmInfo[], //报警信息
alarmDialog: false,
}),
getters: {
selectedGraphicType: (state) => {
@ -64,7 +65,7 @@ export const useLineNetStore = defineStore('lineNet', {
this.lineNetName = name;
},
setAlarmInfo(data: []) {
this.alarmInfo = data;
this.alarmInfo.push(...data);
},
},
});