Compare commits
103 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a6c6de76eb | ||
|
dd7cb75ceb | ||
|
6252bf426c | ||
|
342aff6ebd | ||
|
ca8a2fb279 | ||
|
718835302e | ||
|
59ffd45dfb | ||
|
2070142e56 | ||
|
48c9adc9dc | ||
|
d02295b206 | ||
|
d142917797 | ||
|
c514486354 | ||
|
e6f6ac2b7e | ||
|
da04217a08 | ||
|
de64a23eb8 | ||
|
2e19a66a6b | ||
|
fac62de1ae | ||
|
bfebe3e28d | ||
|
e2faeb2d05 | ||
|
109a19527d | ||
|
09b6dcbb19 | ||
|
539e8b7d01 | ||
|
1cd4cb815c | ||
|
a37e33d7d8 | ||
|
f7634d7672 | ||
|
550bd752f8 | ||
|
67bfc01f6e | ||
|
35f41df852 | ||
|
6888e20634 | ||
|
4a3c2fafbf | ||
|
2aad7d4139 | ||
|
02e49ec6fa | ||
|
2b3673485c | ||
|
0c1471f651 | ||
|
e932e7d0ae | ||
|
05896cb241 | ||
|
debaf97510 | ||
|
99b7cba025 | ||
|
41e59960ee | ||
|
0da7654efa | ||
|
de94896fd7 | ||
|
84fac01c7a | ||
|
b26d213a0e | ||
|
1333a0ec6f | ||
|
52fbdba1af | ||
|
9ac2c2dc59 | ||
|
cfcf0e06d1 | ||
|
33292ca9b8 | ||
|
cdcad825f7 | ||
|
44f7389132 | ||
|
425d8e986b | ||
|
a2ae99209f | ||
|
2f815a0707 | ||
|
f10e55ce0d | ||
|
7971887d2c | ||
|
4adeedb4d5 | ||
|
a57d89a7f3 | ||
|
50b80fef68 | ||
|
b00010901a | ||
|
7cd0df6b1b | ||
|
0ecd9aac7c | ||
|
fbb08bb9e3 | ||
|
f8e36732d8 | ||
|
ae81b3f4f8 | ||
|
586e920216 | ||
|
25b89e8d34 | ||
|
3fc1f4deb7 | ||
|
d75c48a011 | ||
|
26f8581f55 | ||
|
f0495153e6 | ||
|
fb6c01dbfd | ||
|
9c7af7e256 | ||
|
670e9c14db | ||
|
ca75a70a0f | ||
|
37835ed2d6 | ||
|
a486e97e5a | ||
|
c06c626d52 | ||
|
c5cee6ee5c | ||
|
3ecc0558b1 | ||
|
330f7cc809 | ||
|
2a7cf2e186 | ||
|
fb18c04248 | ||
|
b6d345426f | ||
|
b8d08b40bb | ||
|
2676d4d1d8 | ||
|
5044db830b | ||
|
31ae2f378d | ||
|
c7d5464276 | ||
|
c77612e4dc | ||
|
199e775f81 | ||
|
e90c25523e | ||
|
00da31059b | ||
|
012340628a | ||
|
a3a5a18fc4 | ||
|
7b06dee5be | ||
|
aaf8b932a5 | ||
|
49b94329f7 | ||
|
acaf3d1f11 | ||
|
6296877798 | ||
|
be4df53219 | ||
|
20d39f9f4a | ||
|
d345a1dc87 | ||
45b34cb3b9 |
2
.env.dev
2
.env.dev
@ -1,4 +1,4 @@
|
||||
API=192.168.3.233:9081
|
||||
API=192.168.33.233:9081
|
||||
HTTP=http://
|
||||
NS=
|
||||
WS=ws://
|
||||
|
53
.gitea/workflows/CI_local_test.yaml
Normal file
53
.gitea/workflows/CI_local_test.yaml
Normal file
@ -0,0 +1,53 @@
|
||||
name: local-test分支构建发布
|
||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- local-test
|
||||
|
||||
jobs:
|
||||
Docker-Build:
|
||||
runs-on: joylink-local233
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: https://gitea.joylink.club/actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: 设置node环境
|
||||
uses: https://gitea.joylink.club/actions/local-setup-node@v0.1.2
|
||||
with:
|
||||
version: 'v18.19.1'
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: 'yarn.lock'
|
||||
- name: 安装yarn,并run build
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
npm install --global yarn
|
||||
yarn config set registry https://registry.npmmirror.com
|
||||
yarn
|
||||
yarn run build
|
||||
tar czvf ./dist-test.tar.gz ./dist
|
||||
- name: 打包发送到服务器
|
||||
uses: https://gitea.joylink.club/appleboy/scp-action@v0.1.7
|
||||
with:
|
||||
host: ${{ secrets.LOCAL_233_SSH_HOST }}
|
||||
username: ${{ secrets.LOCAL_233_SSH_USER }}
|
||||
password: ${{ secrets.LOCAL_233_SSH_PASSWORD }}
|
||||
port: ${{ secrets.LOCAL_233_SSH_PORT }}
|
||||
source: ./dist-test.tar.gz
|
||||
target: /home/minio/oss/xian-ncc-da-client
|
||||
overwrite: true
|
||||
- name: SSH连接服务器并解压发布
|
||||
uses: https://gitea.joylink.club/appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: ${{ secrets.LOCAL_233_SSH_HOST }}
|
||||
port: ${{ secrets.LOCAL_233_SSH_PORT }}
|
||||
username: ${{ secrets.LOCAL_233_SSH_USER }}
|
||||
password: ${{ secrets.LOCAL_233_SSH_PASSWORD }}
|
||||
script: |
|
||||
cd /home/minio/oss/xian-ncc-da-client
|
||||
rm -rf /usr/local/joylink/client/xianncc
|
||||
mkdir -p /usr/local/joylink/client
|
||||
tar xz --strip 2 -C /usr/local/joylink/client -f dist-test.tar.gz
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
||||
[submodule "xian-ncc-da-message"]
|
||||
path = xian-ncc-da-message
|
||||
url = https://git.code.tencent.com/xian-ncc-da/xian-ncc-da-message.git
|
||||
url = https://gitea.joylink.club/joylink/xian-ncc-da-message.git
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit b5ca64750380db0ff8e4e4a56a471363db684e12
|
@ -23,7 +23,7 @@
|
||||
"centrifuge": "^4.0.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"google-protobuf": "^3.21.2",
|
||||
"jl-graphic": "git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#v0.1.3",
|
||||
"jl-graphic": "git+https://gitea.joylink.club/joylink/graphic-pixi.git#v0.1.15",
|
||||
"js-base64": "^3.7.5",
|
||||
"pinia": "^2.0.11",
|
||||
"quasar": "^2.6.0",
|
||||
|
BIN
public/alarmMusic/3/platform_emerg_stop.mp3
Normal file
BIN
public/alarmMusic/3/platform_emerg_stop.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/3/switch_jammed.mp3
Normal file
BIN
public/alarmMusic/3/switch_jammed.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/all-line-blue.mp3
Normal file
BIN
public/alarmMusic/4/all-line-blue.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/atp-cut.mp3
Normal file
BIN
public/alarmMusic/4/atp-cut.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/blue.mp3
Normal file
BIN
public/alarmMusic/4/blue.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/cannot-close.mp3
Normal file
BIN
public/alarmMusic/4/cannot-close.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/cannot-open.mp3
Normal file
BIN
public/alarmMusic/4/cannot-open.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/orange-most.mp3
Normal file
BIN
public/alarmMusic/4/orange-most.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/orange.mp3
Normal file
BIN
public/alarmMusic/4/orange.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/platform_emerg_stop.mp3
Normal file
BIN
public/alarmMusic/4/platform_emerg_stop.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/red-most.mp3
Normal file
BIN
public/alarmMusic/4/red-most.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/red.mp3
Normal file
BIN
public/alarmMusic/4/red.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/switch-lost-most.mp3
Normal file
BIN
public/alarmMusic/4/switch-lost-most.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/switch-lost.mp3
Normal file
BIN
public/alarmMusic/4/switch-lost.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/4/switch_jammed.mp3
Normal file
BIN
public/alarmMusic/4/switch_jammed.mp3
Normal file
Binary file not shown.
@ -63,6 +63,8 @@ export interface Item {
|
||||
drivingInfo: string;
|
||||
submissionInfo: string;
|
||||
alarmStatus: number;
|
||||
lineId: number;
|
||||
lineType: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,7 +75,7 @@ export interface Item {
|
||||
export async function alarmInfoListQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<Item>> {
|
||||
const response = await api.post('/api/alertRecord/page/detail', params);
|
||||
const response = await api.get('/api/alertRecord/page/detail', { params });
|
||||
return response.data;
|
||||
}
|
||||
|
||||
|
164
src/api/AuthApi.ts
Normal file
164
src/api/AuthApi.ts
Normal file
@ -0,0 +1,164 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto, PageQueryDto } from './ApiCommon';
|
||||
|
||||
const AuthBase = '/api/role';
|
||||
|
||||
export interface Role {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export class PagingQueryParams extends PageQueryDto {
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface createRoleParams {
|
||||
name: string;
|
||||
resList: number[];
|
||||
}
|
||||
|
||||
export interface editRoleParams extends createRoleParams {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface RoleInfo {
|
||||
id: number;
|
||||
name: string;
|
||||
resList: number[];
|
||||
roleConfigStr: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询角色信息
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function pageQueryRole(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<Role>> {
|
||||
const response = await api.get(`${AuthBase}/role/page`, {
|
||||
params: params,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建角色
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export function createRole(data: createRoleParams) {
|
||||
return api.post(`${AuthBase}/role/saveOrUpdate`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除角色
|
||||
* @param id 角色id
|
||||
*/
|
||||
export function deleteRole(id: number) {
|
||||
return api.delete(`${AuthBase}/role/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改角色数据
|
||||
* @param id 角色id
|
||||
* @param data
|
||||
*/
|
||||
export function saveRoleData(data: editRoleParams) {
|
||||
return api.post(`${AuthBase}/role/saveOrUpdate`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取角色详情
|
||||
* @param id 角色id
|
||||
* @returns
|
||||
*/
|
||||
export async function getRoleInfo(id: number): Promise<RoleInfo> {
|
||||
const response = await api.get(`${AuthBase}/role/${id}`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色配置
|
||||
* @param id 角色id
|
||||
* @param data
|
||||
*/
|
||||
export function roleConfig(id: number, data: string) {
|
||||
return api.post(`${AuthBase}/config/${id}`, data, {
|
||||
headers: {
|
||||
'Content-Type': 'text/plain',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
interface LinkRole {
|
||||
id: number;
|
||||
roleList: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户关联角色
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function userLinkRole(params: LinkRole): Promise<string> {
|
||||
const response = await api.post('api/user/edit', params);
|
||||
return response.data.token;
|
||||
}
|
||||
|
||||
export interface PathItem {
|
||||
id: number;
|
||||
method: string;
|
||||
name: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询接口信息
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function pageQueryPath(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<PathItem>> {
|
||||
const response = await api.get(`${AuthBase}/res/page`, {
|
||||
params: params,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建接口路径
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export function createPath(data: Omit<PathItem, 'id'>) {
|
||||
return api.post(`${AuthBase}/res/saveOrUpdate`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除接口路径
|
||||
* @param id 接口路径id
|
||||
*/
|
||||
export function deletePath(id: number) {
|
||||
return api.delete(`${AuthBase}/res/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改接口路径数据
|
||||
* @param id 接口路径id
|
||||
* @param data
|
||||
*/
|
||||
export function savePathData(data: PathItem) {
|
||||
return api.post(`${AuthBase}/res/saveOrUpdate`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取接口路径数据详情
|
||||
* @param id 接口路径id
|
||||
* @returns
|
||||
*/
|
||||
export async function getPathInfo(id: number): Promise<PathItem> {
|
||||
const response = await api.get(`${AuthBase}/res/${id}`);
|
||||
return response.data;
|
||||
}
|
@ -6,6 +6,8 @@ const AlertTipUriBase = '/api/alertTip';
|
||||
|
||||
interface AlarmInfoCreateParams {
|
||||
id: number;
|
||||
lineId: number;
|
||||
lineType: string;
|
||||
alertType: string;
|
||||
tipTimeIds: string[];
|
||||
areaConfigId: number;
|
||||
@ -15,6 +17,8 @@ interface AlarmInfoCreateParams {
|
||||
|
||||
export interface AlarmInfoListItem {
|
||||
id: number;
|
||||
lineId: number;
|
||||
lineType: string;
|
||||
alertType: string;
|
||||
timeConfigList: TimeConfigItem[];
|
||||
areaConfigId: number;
|
||||
|
40
src/api/LogApi.ts
Normal file
40
src/api/LogApi.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto, PageQueryDto } from './ApiCommon';
|
||||
|
||||
const LogUriBase = '/api/log';
|
||||
|
||||
export interface Record {
|
||||
id: number;
|
||||
faceName: string;
|
||||
eventType: string;
|
||||
subEventType: string;
|
||||
uri: string;
|
||||
method: string;
|
||||
parameters: string;
|
||||
requestSuccess: boolean;
|
||||
userName: string;
|
||||
fromUserId: number;
|
||||
mobile: string;
|
||||
createDateTime: string;
|
||||
}
|
||||
|
||||
export class PagingQueryParams extends PageQueryDto {
|
||||
logType?: string;
|
||||
name?: string;
|
||||
beginDate?: string;
|
||||
endDate?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询事件信息列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function pageQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<Record>> {
|
||||
const response = await api.get(`${LogUriBase}/paging`, {
|
||||
params: params,
|
||||
});
|
||||
return response.data;
|
||||
}
|
@ -10,12 +10,13 @@ interface RegisterInfo {
|
||||
password: string;
|
||||
}
|
||||
|
||||
interface User {
|
||||
export interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
mobile: string;
|
||||
password: string;
|
||||
registerTime: string;
|
||||
roleList: { roleId: number; roleName: string }[];
|
||||
}
|
||||
|
||||
const PasswordSult = '4a6d74126bfd06d69406fcccb7e7d5d9'; // 密码加盐
|
||||
@ -71,3 +72,46 @@ export async function pageQuery(
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登出
|
||||
*/
|
||||
export async function logout(): Promise<string> {
|
||||
const response = await api.post(`${UserUriBase}/logout`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
interface tokenInfo {
|
||||
token: string;
|
||||
remainingSecond: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
*/
|
||||
export async function refreshToken(): Promise<tokenInfo> {
|
||||
const response = await api.post(`${UserUriBase}/refresh/token`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export interface role {
|
||||
id: number;
|
||||
name: string;
|
||||
roleConfig: {
|
||||
lineId: number;
|
||||
lineType: string;
|
||||
}[];
|
||||
}
|
||||
interface userInfo {
|
||||
remainingSecond: number;
|
||||
roles: role[];
|
||||
defaultRole: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export async function getUserInfo(): Promise<userInfo> {
|
||||
const response = await api.post(`${UserUriBase}/info`);
|
||||
return response.data;
|
||||
}
|
||||
|
94
src/api/faultQuery.ts
Normal file
94
src/api/faultQuery.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto, PageQueryDto } from './ApiCommon';
|
||||
|
||||
const faultQueryUriBase = '/api/fault/query';
|
||||
|
||||
export interface FaultQueryListItem {
|
||||
id?: number;
|
||||
lineId: number;
|
||||
faultType: string;
|
||||
faultNameShower: string;
|
||||
faultDriverShower: string;
|
||||
resultMsg: string;
|
||||
}
|
||||
|
||||
export interface FaultQueryInfo<T = unknown> {
|
||||
data: T;
|
||||
}
|
||||
|
||||
export class PagingQueryParams extends PageQueryDto {
|
||||
lineId?: string;
|
||||
faultType?: string;
|
||||
faultName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询故障查询
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function faultQueryPageQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<FaultQueryListItem>> {
|
||||
const response = await api.get(`${faultQueryUriBase}/page`, {
|
||||
params: params,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建或编辑故障查询
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function createFaultQuery(faultData: FaultQueryListItem) {
|
||||
return api.post(`${faultQueryUriBase}`, faultData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除故障查询
|
||||
* @param id 草稿id
|
||||
*/
|
||||
export function deleteFaultQueryById(id: number) {
|
||||
return api.delete(`${faultQueryUriBase}/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取故障查询
|
||||
* @param id 草稿id
|
||||
*/
|
||||
export function faultQueryById(
|
||||
id: number
|
||||
): Promise<FaultQueryInfo<FaultQueryListItem>> {
|
||||
return api.get(`${faultQueryUriBase}/${id}`);
|
||||
}
|
||||
|
||||
export interface FaultTypeItem {
|
||||
fts: { faultType: string; typeName: string }[];
|
||||
lineId: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取故障类型
|
||||
*/
|
||||
export async function faultQueryType(): Promise<Array<FaultTypeItem>> {
|
||||
const response = await api.get(`${faultQueryUriBase}/type`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export interface NccFaultQueryListItem {
|
||||
nccTypeName: string;
|
||||
nccData: { action: string; datas: string[] }[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询ncc故障查询
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function nccFaultQueryPageQuery(): Promise<
|
||||
NccFaultQueryListItem[]
|
||||
> {
|
||||
const response = await api.post(`${faultQueryUriBase}/ncc`);
|
||||
return response.data;
|
||||
}
|
6
src/components/AuthData.ts
Normal file
6
src/components/AuthData.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export enum MethodType {
|
||||
POST = 'POST',
|
||||
PUT = 'PUT',
|
||||
DELETE = 'DELETE',
|
||||
GET = 'GET',
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
ref="dialogRef"
|
||||
@show="onDialogShow"
|
||||
seamless
|
||||
title="与卡斯柯连接状态信息"
|
||||
title="与同方连接状态信息"
|
||||
:width="300"
|
||||
:height="0"
|
||||
>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<q-list bordered separator>
|
||||
<div v-for="(menu, ii) in list" :key="ii">
|
||||
<div v-if="menu.children">
|
||||
<div v-if="menu.children && menu.show">
|
||||
<q-expansion-item :icon="menu.icon" :label="menu.label">
|
||||
<q-card>
|
||||
<q-list bordered separator>
|
||||
@ -24,7 +24,7 @@
|
||||
</q-card>
|
||||
</q-expansion-item>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-else-if="menu.show">
|
||||
<q-item clickable :to="menu.path" exact>
|
||||
<q-item-section avatar>
|
||||
<q-icon :name="menu.icon"></q-icon>
|
||||
@ -39,20 +39,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getMonitorPath } from 'src/router/routes';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
import { reactive } from 'vue';
|
||||
const userStore = useUserStore();
|
||||
|
||||
const list = reactive([
|
||||
{
|
||||
path: '/monitor',
|
||||
label: '监控',
|
||||
icon: 'computer',
|
||||
},
|
||||
{
|
||||
path: '/alarmList',
|
||||
label: '报警列表',
|
||||
icon: 'access_alarm',
|
||||
},
|
||||
{
|
||||
show: userStore.defaultRole == 'ADMIN',
|
||||
path: '',
|
||||
label: '数据管理',
|
||||
icon: 'list_alt',
|
||||
@ -73,9 +67,9 @@ const list = reactive([
|
||||
icon: 'format_list_numbered',
|
||||
},
|
||||
{
|
||||
path: '/dataManage/decisionInfo',
|
||||
label: '决策信息管理',
|
||||
icon: 'format_align_center',
|
||||
path: '/dataManage/faultQuery',
|
||||
label: '故障查询管理',
|
||||
icon: 'disabled_by_default',
|
||||
},
|
||||
{
|
||||
path: '/dataManage/thresholdValue',
|
||||
@ -90,6 +84,7 @@ const list = reactive([
|
||||
],
|
||||
},
|
||||
{
|
||||
show: true,
|
||||
path: '',
|
||||
label: '系统管理',
|
||||
icon: 'dataset',
|
||||
@ -99,6 +94,57 @@ const list = reactive([
|
||||
label: '用户管理',
|
||||
icon: 'manage_accounts',
|
||||
},
|
||||
{
|
||||
show: userStore.defaultRole == 'ADMIN',
|
||||
path: '/sysManage/role',
|
||||
label: '权限管理',
|
||||
icon: 'nature_people',
|
||||
},
|
||||
{
|
||||
path: '/sysManage/loginRecord',
|
||||
label: '登录记录',
|
||||
icon: 'description',
|
||||
},
|
||||
{
|
||||
path: '/sysManage/operateRecord',
|
||||
label: '操作记录',
|
||||
icon: 'receipt',
|
||||
},
|
||||
{
|
||||
path: '/sysManage/alarmRecord',
|
||||
label: '报警记录',
|
||||
icon: 'alarm_on',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
show: true,
|
||||
path: getMonitorPath(userStore.roles).monitorPath,
|
||||
label: '监控管理',
|
||||
icon: 'computer',
|
||||
},
|
||||
{
|
||||
show: true,
|
||||
path: '/alarmInfo/list',
|
||||
label: '报警管理',
|
||||
icon: 'alarm_on',
|
||||
},
|
||||
{
|
||||
show: true,
|
||||
path: '',
|
||||
label: '辅助决策',
|
||||
icon: 'developer_board',
|
||||
children: [
|
||||
{
|
||||
path: '/dataManage/decisionInfo',
|
||||
label: '辅助决策方案管理查询',
|
||||
icon: 'format_align_center',
|
||||
},
|
||||
{
|
||||
path: '/dataManage/emergencyResponse',
|
||||
label: '应急处置流程表',
|
||||
icon: 'call_merge',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
@ -49,11 +49,22 @@
|
||||
/>
|
||||
<q-card-actions align="left">
|
||||
<div class="q-gutter-md">
|
||||
<q-btn color="primary" label="确认" type="submit" />
|
||||
<q-btn color="red" label="误报" @click="falseAlarm" />
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="确认"
|
||||
:disable="operateDisabled"
|
||||
type="submit"
|
||||
/>
|
||||
<q-btn
|
||||
color="red"
|
||||
label="误报"
|
||||
:disable="operateDisabled"
|
||||
@click="falseAlarm"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="人工接警"
|
||||
:disable="operateDisabled"
|
||||
@click="manualAlarm"
|
||||
/>
|
||||
</div>
|
||||
@ -88,7 +99,7 @@
|
||||
<script setup lang="ts">
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { useLineNetStore, AlarmInfo } from 'src/stores/line-net-store';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { QForm, useQuasar } from 'quasar';
|
||||
import { saveAlertTypeData, showAlertTypeData } from './alarmInfoEnum';
|
||||
import {
|
||||
@ -97,6 +108,8 @@ import {
|
||||
recordManualAlarmInfoById,
|
||||
} from 'src/api/AlertMock';
|
||||
import { queryAlarmInfoById } from 'src/api/DecisionInfo';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
import { getMonitorPath } from 'src/router/routes';
|
||||
|
||||
const props = defineProps<{
|
||||
alarmMeaasge?: AlarmInfo;
|
||||
@ -124,6 +137,7 @@ const alarmInfo = ref({
|
||||
level: '',
|
||||
time: '',
|
||||
lineId: '',
|
||||
lineType: '',
|
||||
alertObject: '',
|
||||
alertType: '',
|
||||
locator_device_id: '',
|
||||
@ -203,6 +217,7 @@ function updata() {
|
||||
];
|
||||
alarmInfo.value.alertObject = messageUse.alert_object.replace(/\[|]/g, '');
|
||||
alarmInfo.value.lineId = messageUse.line_id;
|
||||
alarmInfo.value.lineType = messageUse.line_type;
|
||||
}
|
||||
|
||||
async function searchByTipType() {
|
||||
@ -237,6 +252,15 @@ async function searchById() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const userStore = useUserStore();
|
||||
const operateDisabled = computed(() => {
|
||||
const config = getMonitorPath(userStore.roles);
|
||||
const disabled =
|
||||
config.lineType == alarmInfo.value.lineType &&
|
||||
config.lineIds.includes(+alarmInfo.value.lineId);
|
||||
return !disabled;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
|
@ -23,6 +23,15 @@ export enum showAlertTypeData {
|
||||
'联锁区橙光带',
|
||||
'联锁区失表',
|
||||
'一级联锁',
|
||||
'应急触发',
|
||||
'道岔挤岔',
|
||||
'zc联锁故障',
|
||||
'列车定位丢失',
|
||||
'列车完整性',
|
||||
'列车故障救援',
|
||||
'ats卡滞',
|
||||
'列车报点',
|
||||
'车站扣车',
|
||||
I = 'I类信息',
|
||||
II = 'II类信息',
|
||||
III = 'III类信息',
|
||||
@ -53,6 +62,15 @@ export enum showAlertTypeData {
|
||||
AXLE_LED_ORANGE_INTERLOCK_AREA = '联锁区橙光带',
|
||||
SWITCH_LOST_INTERLOCK_AREA = '联锁区失表',
|
||||
INTERLOCK_LEVEL_ONE = '一级联锁',
|
||||
PLATFORM_EMERG_STOP = '应急触发',
|
||||
SWITCH_JAMMED = '道岔挤岔',
|
||||
INTERLOCKED_ZC_FAULT = 'zc联锁故障',
|
||||
TRAIN_LOST_LOCATION = '列车定位丢失',
|
||||
TRAIN_INTEGRITY_ALARM = '列车完整性',
|
||||
TRAIN_FAULT_HELP = '列车故障救援',
|
||||
INTERLOCKED_ATS_STUCK = 'ats卡滞',
|
||||
TRAIN_RECORD = '列车报点',
|
||||
HOLD_PLATFORM_STAY_TRAIN_MORE = '车站扣车',
|
||||
}
|
||||
|
||||
export enum saveAlertTypeData {
|
||||
@ -82,6 +100,15 @@ export enum saveAlertTypeData {
|
||||
联锁区橙光带 = 'AXLE_LED_ORANGE_INTERLOCK_AREA',
|
||||
联锁区失表 = 'SWITCH_LOST_INTERLOCK_AREA',
|
||||
一级联锁 = 'INTERLOCK_LEVEL_ONE',
|
||||
应急触发 = 'PLATFORM_EMERG_STOP',
|
||||
道岔挤岔 = 'SWITCH_JAMMED',
|
||||
zc联锁故障 = 'INTERLOCKED_ZC_FAULT',
|
||||
列车定位丢失 = 'TRAIN_LOST_LOCATION',
|
||||
列车完整性 = 'TRAIN_INTEGRITY_ALARM',
|
||||
列车故障救援 = 'TRAIN_FAULT_HELP',
|
||||
ats卡滞 = 'INTERLOCKED_ATS_STUCK',
|
||||
列车报点 = 'TRAIN_RECORD',
|
||||
车站扣车 = 'HOLD_PLATFORM_STAY_TRAIN_MORE',
|
||||
}
|
||||
|
||||
export const GuardConfigTypeData = {
|
||||
|
@ -12,17 +12,33 @@ import { AlarmInfo, useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { DialogChainObject, useQuasar } from 'quasar';
|
||||
import alarmInfoDialog from 'src/components/alarm/alarmInfoDialog.vue';
|
||||
import { showAlertTypeData } from './alarmInfoEnum';
|
||||
import allLineBlue from '/alarmMusic/all-line-blue.mp3';
|
||||
import atpcut from '/alarmMusic/atp-cut.mp3';
|
||||
import blue from '/alarmMusic/blue.mp3';
|
||||
import cannotClose from '/alarmMusic/cannot-close.mp3';
|
||||
import cannotOpen from '/alarmMusic/cannot-open.mp3';
|
||||
import orangeMost from '/alarmMusic/orange-most.mp3';
|
||||
import orange from '/alarmMusic/orange.mp3';
|
||||
import redMost from '/alarmMusic/red-most.mp3';
|
||||
import red from '/alarmMusic/red.mp3';
|
||||
import switchLostMost from '/alarmMusic/switch-lost-most.mp3';
|
||||
import switchLost from '/alarmMusic/switch-lost.mp3';
|
||||
import allLineBlue3 from '/alarmMusic/3/all-line-blue.mp3';
|
||||
import atpcut3 from '/alarmMusic/3/atp-cut.mp3';
|
||||
import blue3 from '/alarmMusic/3/blue.mp3';
|
||||
import cannotClose3 from '/alarmMusic/3/cannot-close.mp3';
|
||||
import cannotOpen3 from '/alarmMusic/3/cannot-open.mp3';
|
||||
import orangeMost3 from '/alarmMusic/3/orange-most.mp3';
|
||||
import orange3 from '/alarmMusic/3/orange.mp3';
|
||||
import redMost3 from '/alarmMusic/3/red-most.mp3';
|
||||
import red3 from '/alarmMusic/3/red.mp3';
|
||||
import switchLostMost3 from '/alarmMusic/3/switch-lost-most.mp3';
|
||||
import switchLost3 from '/alarmMusic/3/switch-lost.mp3';
|
||||
import switchJammed3 from '/alarmMusic/3/switch_jammed.mp3';
|
||||
import platformEmergStop3 from '/alarmMusic/3/platform_emerg_stop.mp3';
|
||||
//4号线
|
||||
import allLineBlue4 from '/alarmMusic/4/all-line-blue.mp3';
|
||||
import atpcut4 from '/alarmMusic/4/atp-cut.mp3';
|
||||
import blue4 from '/alarmMusic/4/blue.mp3';
|
||||
import cannotClose4 from '/alarmMusic/4/cannot-close.mp3';
|
||||
import cannotOpen4 from '/alarmMusic/4/cannot-open.mp3';
|
||||
import orangeMost4 from '/alarmMusic/4/orange-most.mp3';
|
||||
import orange4 from '/alarmMusic/4/orange.mp3';
|
||||
import redMost4 from '/alarmMusic/4/red-most.mp3';
|
||||
import red4 from '/alarmMusic/4/red.mp3';
|
||||
import switchLostMost4 from '/alarmMusic/4/switch-lost-most.mp3';
|
||||
import switchLost4 from '/alarmMusic/4/switch-lost.mp3';
|
||||
import switchJammed4 from '/alarmMusic/4/switch_jammed.mp3';
|
||||
import platformEmergStop4 from '/alarmMusic/4/platform_emerg_stop.mp3';
|
||||
import buzzer from '/alarmMusic/buzzer.mp3';
|
||||
|
||||
const lineNetStore = useLineNetStore();
|
||||
@ -39,8 +55,8 @@ watch(
|
||||
const hasShow = countHasShowFiveDialog();
|
||||
if (!hasShow) {
|
||||
const alarmType = val[0].alert_type;
|
||||
alarm(alarmType, val[0].id);
|
||||
playAlarmMusic(alarmType);
|
||||
alarm(alarmType, val[0].id, +val[0].line_id);
|
||||
playAlarmMusic(alarmType, +val[0].line_id);
|
||||
} else {
|
||||
waitShowDialog.push(toRaw(lineNetStore.alarmInfo[0]));
|
||||
}
|
||||
@ -58,28 +74,53 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
function playAlarmMusic(type: number) {
|
||||
function playAlarmMusic(type: number, lineId: number) {
|
||||
for (let i = 0; i < dialogInstance.length; i++) {
|
||||
if (dialogInstance[i].show == false) {
|
||||
dialogInstance.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (!lineNetStore.handlePlayAble) return;
|
||||
if (lineNetStore.playAble && audio.value.paused) {
|
||||
const alarmType = (showAlertTypeData as never)[type + ''];
|
||||
const mapAlarmMusic = new Map([
|
||||
['蓝显', blue],
|
||||
['全线蓝显', allLineBlue],
|
||||
['整侧站台门无法打开', cannotOpen],
|
||||
['整侧站台门无法关闭', cannotClose],
|
||||
['道岔失表', switchLost],
|
||||
['道岔大面积失表', switchLostMost],
|
||||
['计轴红光带', red],
|
||||
['计轴大面积红光带', redMost],
|
||||
['计轴橙光带', orange],
|
||||
['计轴大面积橙光带', orangeMost],
|
||||
['列车信号故障', atpcut],
|
||||
let mapAlarmMusic = new Map();
|
||||
switch (lineId) {
|
||||
case 3:
|
||||
mapAlarmMusic = new Map([
|
||||
['蓝显', blue3],
|
||||
['全线蓝显', allLineBlue3],
|
||||
['整侧站台门无法打开', cannotOpen3],
|
||||
['整侧站台门无法关闭', cannotClose3],
|
||||
['道岔失表', switchLost3],
|
||||
['道岔大面积失表', switchLostMost3],
|
||||
['计轴红光带', red3],
|
||||
['计轴大面积红光带', redMost3],
|
||||
['计轴橙光带', orange3],
|
||||
['计轴大面积橙光带', orangeMost3],
|
||||
['列车信号故障', atpcut3],
|
||||
['应急触发', platformEmergStop3],
|
||||
['道岔挤岔', switchJammed3],
|
||||
]);
|
||||
break;
|
||||
case 4:
|
||||
mapAlarmMusic = new Map([
|
||||
['蓝显', blue4],
|
||||
['全线蓝显', allLineBlue4],
|
||||
['整侧站台门无法打开', cannotOpen4],
|
||||
['整侧站台门无法关闭', cannotClose4],
|
||||
['道岔失表', switchLost4],
|
||||
['道岔大面积失表', switchLostMost4],
|
||||
['计轴红光带', red4],
|
||||
['计轴大面积红光带', redMost4],
|
||||
['计轴橙光带', orange4],
|
||||
['计轴大面积橙光带', orangeMost4],
|
||||
['列车信号故障', atpcut4],
|
||||
['应急触发', platformEmergStop4],
|
||||
['道岔挤岔', switchJammed4],
|
||||
]);
|
||||
break;
|
||||
}
|
||||
const music = mapAlarmMusic.get(alarmType);
|
||||
if (music !== undefined) {
|
||||
audioSrc.value = music;
|
||||
@ -102,7 +143,7 @@ function timingPlayAlarmMusic(dialog: DialogChainObject) {
|
||||
!dialogInstance[i].hasHandle &&
|
||||
dialogInstance[i].dialog == dialog
|
||||
) {
|
||||
playAlarmMusic(dialogInstance[i].alarmType);
|
||||
playAlarmMusic(dialogInstance[i].alarmType, dialogInstance[i].lineId);
|
||||
timingPlayAlarmMusic(dialog);
|
||||
}
|
||||
}
|
||||
@ -116,6 +157,7 @@ const dialogInstance: {
|
||||
timer: string | number | NodeJS.Timeout | undefined;
|
||||
id: string;
|
||||
hasHandle: boolean;
|
||||
lineId: number;
|
||||
}[] = [];
|
||||
|
||||
function countHasShowFiveDialog(): boolean {
|
||||
@ -129,7 +171,12 @@ function countHasShowFiveDialog(): boolean {
|
||||
return hasShow > 4 ? true : false;
|
||||
}
|
||||
|
||||
function alarm(alarmType: number, id: string, waitAlarmMeaasge?: AlarmInfo) {
|
||||
function alarm(
|
||||
alarmType: number,
|
||||
id: string,
|
||||
lineId: number,
|
||||
waitAlarmMeaasge?: AlarmInfo
|
||||
) {
|
||||
const dialogInstanceItem = $q
|
||||
.dialog({
|
||||
component: alarmInfoDialog,
|
||||
@ -160,6 +207,7 @@ function alarm(alarmType: number, id: string, waitAlarmMeaasge?: AlarmInfo) {
|
||||
timer,
|
||||
hasHandle: false,
|
||||
id,
|
||||
lineId,
|
||||
});
|
||||
timingPlayAlarmMusic(dialogInstanceItem);
|
||||
}
|
||||
@ -169,9 +217,10 @@ function alarmWaitDialog() {
|
||||
alarm(
|
||||
waitShowDialog[0].alert_type,
|
||||
waitShowDialog[0].id,
|
||||
+waitShowDialog[0].line_id,
|
||||
waitShowDialog[0]
|
||||
);
|
||||
playAlarmMusic(waitShowDialog[0].alert_type);
|
||||
playAlarmMusic(waitShowDialog[0].alert_type, +waitShowDialog[0].line_id);
|
||||
waitShowDialog.shift();
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +103,8 @@ const optionsAlertType = [
|
||||
'计轴橙光带',
|
||||
'计轴大面积橙光带',
|
||||
'列车信号故障',
|
||||
'应急触发',
|
||||
'道岔挤岔',
|
||||
];
|
||||
const mapAlertType = new Map([
|
||||
['蓝显', ['station']],
|
||||
@ -115,6 +117,8 @@ const mapAlertType = new Map([
|
||||
['计轴橙光带', ['Section']],
|
||||
['计轴大面积橙光带', ['Section']],
|
||||
['列车信号故障', ['LogicSection', 'Turnout']],
|
||||
['应急触发', ['Platform']],
|
||||
['道岔挤岔', ['Turnout']],
|
||||
]);
|
||||
let selectGraphic: JlGraphic[] = [];
|
||||
|
||||
|
@ -40,7 +40,9 @@
|
||||
<q-card>
|
||||
<q-item no-wrap class="column">
|
||||
<q-input
|
||||
v-if="setAlartTextData.alertType == '列车信号故障'"
|
||||
v-if="
|
||||
needShowTrainGroup.includes(setAlartTextData.alertType)
|
||||
"
|
||||
outlined
|
||||
label="车组号"
|
||||
v-model="configItem.groupId"
|
||||
@ -81,7 +83,11 @@
|
||||
@click="clearAllSelect(index)"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="setAlartTextData.alertType == '列车信号故障'"
|
||||
v-if="
|
||||
needShowTrainGroup.includes(
|
||||
setAlartTextData.alertType
|
||||
)
|
||||
"
|
||||
label="删除测试组"
|
||||
color="secondary"
|
||||
@click="deleteSelectConfig(index)"
|
||||
@ -92,7 +98,7 @@
|
||||
</q-expansion-item>
|
||||
</q-list>
|
||||
<q-btn
|
||||
v-if="setAlartTextData.alertType == '列车信号故障'"
|
||||
v-if="needShowTrainGroup.includes(setAlartTextData.alertType)"
|
||||
class="q-mt-md"
|
||||
label="增加测试组"
|
||||
color="secondary"
|
||||
@ -116,7 +122,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { JlGraphic } from 'jl-graphic';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
@ -124,6 +130,8 @@ import { QForm, useQuasar } from 'quasar';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { mockLocalDemoTestSet } from 'src/api/AlertMock';
|
||||
import { isArraysEqual, saveAlertTypeData } from './alarmInfoEnum';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
const setAlartTextData = ref<{
|
||||
@ -152,12 +160,18 @@ const setAlartTextData = ref<{
|
||||
},
|
||||
],
|
||||
});
|
||||
const needShowTrainGroup = ['列车信号故障', '列车报点', '车站扣车'];
|
||||
const optionsAlertType = [
|
||||
'蓝显',
|
||||
'道岔失表',
|
||||
'计轴红光带',
|
||||
'计轴橙光带',
|
||||
'列车信号故障',
|
||||
'应急触发',
|
||||
'道岔挤岔',
|
||||
'列车完整性',
|
||||
'列车报点',
|
||||
'车站扣车',
|
||||
];
|
||||
const mapAlertType = new Map([
|
||||
['蓝显', ['station']],
|
||||
@ -165,17 +179,34 @@ const mapAlertType = new Map([
|
||||
['计轴红光带', ['LogicSection', 'Turnout']],
|
||||
['计轴橙光带', ['LogicSection', 'Turnout']],
|
||||
['列车信号故障', ['LogicSection', 'Turnout']],
|
||||
['应急触发', ['Platform']],
|
||||
['道岔挤岔', ['Turnout']],
|
||||
['列车完整性', ['LogicSection']],
|
||||
['列车报点', ['Section']],
|
||||
['车站扣车', ['Section', 'LogicSection']],
|
||||
]);
|
||||
enum DeviceType {
|
||||
station = 'DEVICE_TYPE_RTU',
|
||||
Turnout = 'DEVICE_TYPE_SWITCH',
|
||||
LogicSection = 'DEVICE_TYPE_TRACK',
|
||||
Platform = 'DEVICE_TYPE_PLATFORM',
|
||||
Section = 'DEVICE_TYPE_SECTION',
|
||||
}
|
||||
const optionsStatus = [
|
||||
const optionsStatus = computed(() => {
|
||||
if (setAlartTextData.value.alertType !== '列车报点') {
|
||||
return [
|
||||
{ label: '正常', value: 'NORMAL' },
|
||||
{ label: '设置', value: 'BEGIN' },
|
||||
{ label: '报警', value: 'ALERT' },
|
||||
];
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
{ label: '到站', value: 'NORMAL' },
|
||||
{ label: '离站', value: 'BEGIN' },
|
||||
];
|
||||
}
|
||||
});
|
||||
let allplatformRefSection: number[] = [];
|
||||
let selectGraphic: JlGraphic[] = [];
|
||||
|
||||
watch(
|
||||
@ -205,16 +236,27 @@ watch(
|
||||
setAlartTextData.value.alertType == '蓝显'
|
||||
) {
|
||||
select = true;
|
||||
}
|
||||
if (
|
||||
} else if (
|
||||
g.type == Section.Type &&
|
||||
setAlartTextData.value.alertType == '列车报点' &&
|
||||
allplatformRefSection.includes(g.id)
|
||||
) {
|
||||
select = true;
|
||||
} else if (
|
||||
g.type == Section.Type &&
|
||||
setAlartTextData.value.alertType == '车站扣车'
|
||||
) {
|
||||
select = true;
|
||||
} else if (
|
||||
g.type !== Station.Type &&
|
||||
g.type !== Section.Type &&
|
||||
mapAlertType.get(setAlartTextData.value.alertType)?.includes(g.type)
|
||||
) {
|
||||
select = true;
|
||||
}
|
||||
return select;
|
||||
}) as JlGraphic[];
|
||||
if (setAlartTextData.value.alertType !== '列车信号故障') {
|
||||
if (!needShowTrainGroup.includes(setAlartTextData.value.alertType)) {
|
||||
selectGraphic.push(...deviceFilter);
|
||||
} else if (deviceFilter.length) {
|
||||
selectGraphic = [deviceFilter[0]];
|
||||
@ -235,6 +277,12 @@ watch(
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const platforms = lineStore
|
||||
.getLineApp()
|
||||
.queryStore.queryByType<Platform>(Platform.Type);
|
||||
platforms.forEach((platform) =>
|
||||
allplatformRefSection.push(platform.datas.refSectionId)
|
||||
);
|
||||
lineStore.getLineApp().emit('options-update', {
|
||||
mouseToolOptions: {
|
||||
boxSelect: true,
|
||||
|
186
src/components/common/SelectConfigUtils.vue
Normal file
186
src/components/common/SelectConfigUtils.vue
Normal file
@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-expansion-item
|
||||
bordered
|
||||
expand-separator
|
||||
v-for="(configItem, index) in selectConfig"
|
||||
:key="configItem"
|
||||
v-model="configItem.expanded"
|
||||
:label="configItem.code"
|
||||
@click="toggleItem(index)"
|
||||
>
|
||||
<q-card>
|
||||
<q-item no-wrap class="q-gutter-y-sm column">
|
||||
<q-input
|
||||
v-if="props.ableAdd"
|
||||
outlined
|
||||
v-model="configItem.code"
|
||||
label="配置项类型"
|
||||
lazy-rules
|
||||
/>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="(item, selectIndex) in configItem.refDevicesCode"
|
||||
:key="item"
|
||||
square
|
||||
color="primary"
|
||||
text-color="white"
|
||||
removable
|
||||
@remove="removeSelect(selectIndex)"
|
||||
clickable
|
||||
@click="clickSelectCenter(selectIndex)"
|
||||
>
|
||||
{{ item }}
|
||||
</q-chip>
|
||||
</div>
|
||||
<div>
|
||||
<q-btn
|
||||
v-show="configItem.refDevicesCode.length > 0"
|
||||
style="width: 100px"
|
||||
label="清空选择"
|
||||
color="red"
|
||||
class="q-mr-md"
|
||||
@click="clearAllSelect(index)"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="props.ableAdd"
|
||||
label="删除配置项"
|
||||
color="secondary"
|
||||
@click="deleteSelectConfig(index)"
|
||||
/>
|
||||
</div>
|
||||
</q-item>
|
||||
</q-card>
|
||||
</q-expansion-item>
|
||||
</q-list>
|
||||
<q-btn
|
||||
v-if="props.ableAdd"
|
||||
class="q-mt-md"
|
||||
label="增加配置项"
|
||||
color="secondary"
|
||||
@click="addSelectConfig"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { inject, ref, watch } from 'vue';
|
||||
import { IDrawApp, JlGraphic } from 'jl-graphic';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
drawStore: {
|
||||
selectedGraphics: JlGraphic[];
|
||||
getDrawApp(): IDrawApp;
|
||||
};
|
||||
ableAdd?: boolean;
|
||||
}>(),
|
||||
{ ableAdd: false }
|
||||
);
|
||||
|
||||
const selectConfig = ref<
|
||||
{
|
||||
code: string;
|
||||
refDevices: number[];
|
||||
refDevicesCode: string[];
|
||||
expanded: boolean;
|
||||
}[]
|
||||
>([
|
||||
{
|
||||
code: '配置项模版',
|
||||
refDevices: [],
|
||||
refDevicesCode: [],
|
||||
expanded: false,
|
||||
},
|
||||
]);
|
||||
|
||||
let selectGraphic: JlGraphic[] = [];
|
||||
|
||||
defineExpose({
|
||||
selectConfig,
|
||||
selectGraphic,
|
||||
});
|
||||
|
||||
interface GraphicData {
|
||||
datas: { code: string };
|
||||
}
|
||||
|
||||
const filterSelect = inject('filter') as (g: JlGraphic) => boolean;
|
||||
watch(
|
||||
() => props.drawStore.selectedGraphics,
|
||||
(val) => {
|
||||
if (val && val.length > 0 && clickIndex !== null) {
|
||||
const selectFilter = props.drawStore.selectedGraphics?.filter(
|
||||
filterSelect
|
||||
) as JlGraphic[];
|
||||
selectGraphic.push(...selectFilter);
|
||||
selectGraphic = Array.from(new Set(selectGraphic));
|
||||
props.drawStore.getDrawApp().updateSelected(...selectGraphic);
|
||||
selectConfig.value[clickIndex].refDevicesCode = selectGraphic.map((g) =>
|
||||
(g as JlGraphic & GraphicData).datas.code == ''
|
||||
? g.id + ''
|
||||
: (g as JlGraphic & GraphicData).datas.code
|
||||
);
|
||||
selectConfig.value[clickIndex].refDevices = selectGraphic.map(
|
||||
(g) => g.id
|
||||
) as number[];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let clickIndex: null | number = null;
|
||||
function toggleItem(index: number) {
|
||||
const drawApp = props.drawStore.getDrawApp();
|
||||
selectGraphic = [];
|
||||
drawApp.updateSelected();
|
||||
if (selectConfig.value[index].expanded == true) {
|
||||
clickIndex = index;
|
||||
const select: JlGraphic[] = [];
|
||||
selectConfig.value[index].refDevices.forEach((id: number) => {
|
||||
const g = drawApp.queryStore.queryById(id);
|
||||
select.push(g);
|
||||
});
|
||||
drawApp.updateSelected(...select);
|
||||
} else {
|
||||
clickIndex = null;
|
||||
}
|
||||
}
|
||||
|
||||
function removeSelect(removeIndex: number) {
|
||||
const clickTarget = selectConfig.value[clickIndex as number];
|
||||
selectGraphic.splice(removeIndex, 1);
|
||||
clickTarget.refDevicesCode.splice(removeIndex, 1);
|
||||
clickTarget.refDevices.splice(removeIndex, 1);
|
||||
props.drawStore.getDrawApp().updateSelected(...selectGraphic);
|
||||
}
|
||||
|
||||
function clickSelectCenter(index: number) {
|
||||
const drawApp = props.drawStore.getDrawApp();
|
||||
const clickTarget = selectConfig.value[clickIndex as number];
|
||||
const clickGraphic = drawApp.queryStore.queryById(
|
||||
clickTarget.refDevices[index]
|
||||
);
|
||||
drawApp.makeGraphicCenterShow(clickGraphic);
|
||||
}
|
||||
|
||||
function clearAllSelect(index: number) {
|
||||
selectConfig.value[index].refDevices = [];
|
||||
selectConfig.value[index].refDevicesCode = [];
|
||||
selectGraphic = [];
|
||||
props.drawStore.getDrawApp().updateSelected();
|
||||
}
|
||||
|
||||
function addSelectConfig() {
|
||||
selectConfig.value.push({
|
||||
code: '配置项模版',
|
||||
refDevices: [],
|
||||
refDevicesCode: [],
|
||||
expanded: false,
|
||||
});
|
||||
}
|
||||
|
||||
function deleteSelectConfig(index: number) {
|
||||
selectConfig.value.splice(index, 1);
|
||||
selectGraphic = [];
|
||||
props.drawStore.getDrawApp().updateSelected();
|
||||
}
|
||||
</script>
|
357
src/components/dialog/FaultQueryDialog.vue
Normal file
357
src/components/dialog/FaultQueryDialog.vue
Normal file
@ -0,0 +1,357 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
ref="dialogRef"
|
||||
@show="onDialogShow"
|
||||
title="故障查询"
|
||||
:width="990"
|
||||
:height="600"
|
||||
>
|
||||
<div class="dialogContainer">
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:loading="loading"
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
@request="onRequest"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
style="width: 500px; height: 600px"
|
||||
>
|
||||
<template v-slot:body="props">
|
||||
<q-tr
|
||||
:props="props"
|
||||
:class="{ changeBackground: props.row.id === clickRowInfo.id }"
|
||||
@click="handleRowClick(props.row)"
|
||||
>
|
||||
<q-td
|
||||
v-for="col in props.cols"
|
||||
:key="col.name"
|
||||
:props="props"
|
||||
class="custom-column"
|
||||
>
|
||||
{{ col.value }}
|
||||
<q-tooltip
|
||||
anchor="bottom middle"
|
||||
v-if="props.value && props.value.length > 20"
|
||||
>
|
||||
<div class="message-tip">
|
||||
{{ col.value }}
|
||||
</div>
|
||||
</q-tooltip>
|
||||
</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
|
||||
<q-scroll-area style="width: 490px; height: 580px">
|
||||
<div class="detaiRow">
|
||||
<div class="text">
|
||||
<span class="textHead">故障类型</span> :{{
|
||||
clickRowInfo.faultType
|
||||
}}
|
||||
</div>
|
||||
<div class="text">
|
||||
<span class="textHead"> {{ showTitle.faultNameShower }}</span
|
||||
>:{{ clickRowInfo.faultNameShower }}
|
||||
</div>
|
||||
<q-card class="box-card">
|
||||
<div class="head">{{ showTitle.faultDriverShower }}</div>
|
||||
<q-separator />
|
||||
<div>
|
||||
<div class="detail">{{ clickRowInfo.faultDriverShower }}</div>
|
||||
</div>
|
||||
</q-card>
|
||||
<q-card class="box-card">
|
||||
<div class="head">{{ showTitle.resultMsg }}</div>
|
||||
<q-separator />
|
||||
<div>
|
||||
<div class="detail">{{ clickRowInfo.resultMsg }}</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</q-scroll-area>
|
||||
</div>
|
||||
<template v-slot:titleButton>
|
||||
<q-btn
|
||||
square
|
||||
color="purple"
|
||||
style="margin-right: 10px"
|
||||
icon="search"
|
||||
@click="reset"
|
||||
>
|
||||
<q-popup-edit
|
||||
ref="popupEdit"
|
||||
v-model="noUse"
|
||||
:cover="false"
|
||||
:offset="[0, 10]"
|
||||
>
|
||||
<q-select
|
||||
dense
|
||||
label="故障类型"
|
||||
v-model="filter.faultType"
|
||||
emit-value
|
||||
map-options
|
||||
:options="searchOptionsFaultType"
|
||||
style="min-width: 130px"
|
||||
/>
|
||||
<q-input
|
||||
dense
|
||||
label="故障现象(故障名称)"
|
||||
v-model="filter.faultName"
|
||||
lazy-rules
|
||||
/>
|
||||
<div class="button-container">
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="查询"
|
||||
type="submit"
|
||||
style="margin-top: 10px"
|
||||
@click="searchTable"
|
||||
/>
|
||||
</div>
|
||||
</q-popup-edit>
|
||||
</q-btn>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { QTable, useQuasar } from 'quasar';
|
||||
import {
|
||||
FaultQueryListItem,
|
||||
faultQueryPageQuery,
|
||||
faultQueryType,
|
||||
FaultTypeItem,
|
||||
} from 'src/api/faultQuery';
|
||||
|
||||
const $q = useQuasar();
|
||||
const lineId = useRoute().params.lineId as string;
|
||||
|
||||
const tableRef = ref<QTable>();
|
||||
const columns = computed(() => [
|
||||
{
|
||||
name: 'id',
|
||||
label: '编号',
|
||||
field: 'id',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faultType',
|
||||
label: '故障类型',
|
||||
field: (row: FaultQueryListItem) => {
|
||||
if (row.faultType) {
|
||||
return getFaultTypeName(row);
|
||||
}
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faultNameShower',
|
||||
label: '消息名称(故障现象)',
|
||||
field: 'faultNameShower',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
]);
|
||||
const rows = reactive([]);
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
const filter = reactive({
|
||||
faultType: '',
|
||||
faultName: '',
|
||||
});
|
||||
|
||||
const onRequest: QTable['onRequest'] = async (props) => {
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
loading.value = true;
|
||||
try {
|
||||
const params = {
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
lineId,
|
||||
};
|
||||
if (filter.faultType !== '') {
|
||||
Object.assign(params, {
|
||||
faultType: filter.faultType,
|
||||
});
|
||||
}
|
||||
if (filter.faultName !== '') {
|
||||
Object.assign(params, {
|
||||
faultName: filter.faultName,
|
||||
});
|
||||
}
|
||||
let resp = await faultQueryPageQuery(params);
|
||||
pagination.value.page = resp.current;
|
||||
pagination.value.rowsNumber = resp.total;
|
||||
pagination.value.rowsPerPage = resp.size;
|
||||
rows.splice(0, rows.length, ...(resp.records as []));
|
||||
if (rows.length) {
|
||||
handleRowClick(rows[0]);
|
||||
} else {
|
||||
clickRowInfo.faultType = '';
|
||||
clickRowInfo.faultNameShower = '';
|
||||
clickRowInfo.faultDriverShower = '';
|
||||
clickRowInfo.resultMsg = '';
|
||||
}
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取范围列表',
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const clickRowInfo = reactive({
|
||||
id: 0,
|
||||
faultType: '',
|
||||
faultNameShower: '',
|
||||
faultDriverShower: '',
|
||||
resultMsg: '',
|
||||
});
|
||||
const showTitle = reactive({
|
||||
faultNameShower: '',
|
||||
faultDriverShower: '',
|
||||
resultMsg: '',
|
||||
});
|
||||
function handleRowClick(row: FaultQueryListItem) {
|
||||
if (row.faultType.includes('FAULT_EMERGENCY_GUIDE')) {
|
||||
showTitle.faultNameShower = '故障现象';
|
||||
showTitle.faultDriverShower = '司机处理结果';
|
||||
showTitle.resultMsg = '行调提醒司机关键点';
|
||||
} else {
|
||||
showTitle.faultNameShower = '故障名称';
|
||||
showTitle.faultDriverShower = '故障现象';
|
||||
showTitle.resultMsg = '退出服务地点';
|
||||
}
|
||||
clickRowInfo.id = row?.id as number;
|
||||
clickRowInfo.faultType = getFaultTypeName(row) as string;
|
||||
clickRowInfo.faultNameShower = row.faultNameShower;
|
||||
clickRowInfo.faultDriverShower = row.faultDriverShower;
|
||||
clickRowInfo.resultMsg = row.resultMsg;
|
||||
}
|
||||
|
||||
async function queryAllFaultType() {
|
||||
try {
|
||||
allOptionsFaultType = await faultQueryType();
|
||||
handleSelectFaultType();
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取指定线路的故障类型配置',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let allOptionsFaultType: FaultTypeItem[] = [];
|
||||
function getFaultTypeName(row: FaultQueryListItem) {
|
||||
for (let i = 0; i < allOptionsFaultType.length; i++) {
|
||||
if (allOptionsFaultType[i].lineId == row.lineId) {
|
||||
const fts = allOptionsFaultType[i].fts;
|
||||
for (let j = 0; i < fts.length; j++) {
|
||||
if (fts[j].faultType == row.faultType) {
|
||||
return fts[j].typeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const searchOptionsFaultType = ref([{ label: '全部', value: '' }]);
|
||||
function handleSelectFaultType() {
|
||||
allOptionsFaultType.forEach((faultTypeOption) => {
|
||||
faultTypeOption.fts.forEach((fault) =>
|
||||
searchOptionsFaultType.value.push({
|
||||
label: fault.typeName,
|
||||
value: fault.faultType,
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function searchTable() {
|
||||
tableRef.value?.requestServerInteraction();
|
||||
}
|
||||
|
||||
const noUse = ref('');
|
||||
function reset() {
|
||||
filter.faultType = '';
|
||||
filter.faultName = '';
|
||||
}
|
||||
|
||||
const onDialogShow = () => {
|
||||
queryAllFaultType();
|
||||
setTimeout(() => {
|
||||
tableRef.value?.requestServerInteraction();
|
||||
}, 1000);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.changeBackground {
|
||||
background-color: #31ccec;
|
||||
}
|
||||
.custom-column {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.message-tip {
|
||||
width: 300px;
|
||||
overflow: auto;
|
||||
line-height: 22px;
|
||||
white-space: pre-wrap;
|
||||
font-size: 14px;
|
||||
}
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.dialogContainer {
|
||||
display: flex;
|
||||
.detaiRow {
|
||||
margin: 10px 0 0 20px;
|
||||
.text {
|
||||
width: 450px;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 10px;
|
||||
font-size: 18px;
|
||||
.textHead {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.box-card {
|
||||
width: 450px;
|
||||
height: 235px;
|
||||
margin-bottom: 10px;
|
||||
padding: 0 5px;
|
||||
.head {
|
||||
padding: 5px 5px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.detail {
|
||||
margin-bottom: 10px;
|
||||
padding: 5px 5px;
|
||||
line-height: 28px;
|
||||
white-space: pre-wrap;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
183
src/components/draw-app/properties/AxleCountingConfig.vue
Normal file
183
src/components/draw-app/properties/AxleCountingConfig.vue
Normal file
@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<q-card class="q-gutter-sm q-pa-sm">
|
||||
<q-card-section>
|
||||
<div class="text-h6">一键生成计轴配置</div>
|
||||
</q-card-section>
|
||||
<q-form ref="myForm">
|
||||
<selectConfig-utils ref="selectConfigUtils" :drawStore="drawStore" />
|
||||
<div class="q-mt-md q-gutter-md">
|
||||
<q-btn label="确认修改" color="primary" @click="onSubmit" />
|
||||
<q-btn label="返回" color="red" @click="goBack" />
|
||||
<q-btn label="生成计轴" color="primary" @click="generateAxleCounting" />
|
||||
</div>
|
||||
<div class="q-mt-md q-gutter-md">
|
||||
<q-btn
|
||||
label="检查计轴"
|
||||
color="primary"
|
||||
@click="showErrorAxleCounting"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="showCheck"
|
||||
label="上一个"
|
||||
color="primary"
|
||||
@click="clickSelectCenter(-1)"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="showCheck"
|
||||
label="下一个"
|
||||
color="primary"
|
||||
@click="clickSelectCenter(1)"
|
||||
/>
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, provide } from 'vue';
|
||||
import { QForm, useQuasar } from 'quasar';
|
||||
import { JlGraphic } from 'jl-graphic';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import {
|
||||
loadGenerateAxleCountingConfig,
|
||||
setGenerateAxleCountingConfig,
|
||||
} from 'src/drawApp';
|
||||
import SelectConfigUtils from 'src/components/common/SelectConfigUtils.vue';
|
||||
import { OneClickGenerate } from 'src/graphics/trainWindow/oneClickDrawAssistant';
|
||||
import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting';
|
||||
|
||||
//供公共选择组件使用
|
||||
const filterSelect = (g: JlGraphic) => g instanceof Turnout;
|
||||
const selectConfigUtils = ref<InstanceType<typeof SelectConfigUtils> | null>(
|
||||
null
|
||||
);
|
||||
provide('filter', filterSelect);
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const $q = useQuasar();
|
||||
|
||||
onMounted(() => {
|
||||
selectConfigUtils.value.selectConfig = [
|
||||
{
|
||||
code: 'bb连接的道岔',
|
||||
refDevices: [],
|
||||
refDevicesCode: [],
|
||||
expanded: false,
|
||||
},
|
||||
{
|
||||
code: '不生成计轴的道岔组',
|
||||
refDevices: [],
|
||||
refDevicesCode: [],
|
||||
expanded: false,
|
||||
},
|
||||
];
|
||||
const generateAxleCountingConfig = loadGenerateAxleCountingConfig();
|
||||
if (generateAxleCountingConfig !== undefined) {
|
||||
selectConfigUtils.value.selectConfig.forEach(
|
||||
(generate: {
|
||||
code: string;
|
||||
refDevices: number[];
|
||||
refDevicesCode: string[];
|
||||
}) => {
|
||||
if (generate.code == 'bb连接的道岔') {
|
||||
generate.refDevices = generateAxleCountingConfig.bbConnect;
|
||||
generateAxleCountingConfig.bbConnect.forEach((id) => {
|
||||
const g = drawStore.getDrawApp().queryStore.queryById(id);
|
||||
generate.refDevicesCode.push(g.code);
|
||||
});
|
||||
} else if (generate.code == '不生成计轴的道岔组') {
|
||||
generate.refDevices = generateAxleCountingConfig.noGenerateGroup;
|
||||
generateAxleCountingConfig.noGenerateGroup.forEach((id) => {
|
||||
const g = drawStore.getDrawApp().queryStore.queryById(id);
|
||||
generate.refDevicesCode.push(g.code);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
async function onSubmit() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
try {
|
||||
const generateAxleCountingConfig =
|
||||
new graphicData.GenerateAxleCountingConfig();
|
||||
selectConfigUtils.value.selectConfig.forEach(
|
||||
(generate: { code: string; refDevices: number[] }) => {
|
||||
if (generate.code == 'bb连接的道岔') {
|
||||
generateAxleCountingConfig.bbConnect = generate.refDevices;
|
||||
} else if (generate.code == '不生成计轴的道岔组') {
|
||||
generateAxleCountingConfig.noGenerateGroup = generate.refDevices;
|
||||
}
|
||||
}
|
||||
);
|
||||
setGenerateAxleCountingConfig(generateAxleCountingConfig);
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: '更新成功',
|
||||
});
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '更新失败',
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
emit('close');
|
||||
}
|
||||
|
||||
function generateAxleCounting() {
|
||||
drawStore.oneClickType = 'AxleCounting';
|
||||
drawStore.getDrawApp().interactionPlugin(OneClickGenerate.Type).resume();
|
||||
}
|
||||
|
||||
const selectConfig = ref<
|
||||
{
|
||||
axleCountingId: number;
|
||||
axleCountingCode: string;
|
||||
}[]
|
||||
>([]);
|
||||
function showErrorAxleCounting() {
|
||||
showCheck.value = true;
|
||||
const axleCountings = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<AxleCounting>(AxleCounting.Type);
|
||||
const erroeAxleCountings = axleCountings
|
||||
.filter((g) => g.datas.axleCountingRef.length < 2)
|
||||
.sort((a, b) => a.position.x - b.position.x);
|
||||
erroeAxleCountings.forEach((axleCounting) => {
|
||||
selectConfig.value.push({
|
||||
axleCountingId: axleCounting.id,
|
||||
axleCountingCode: axleCounting.datas.code,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const currentIndex = ref(-1);
|
||||
const showCheck = ref(false);
|
||||
function clickSelectCenter(add: number) {
|
||||
if (
|
||||
currentIndex.value + add < 0 ||
|
||||
currentIndex.value + add >= selectConfig.value.length
|
||||
)
|
||||
return;
|
||||
currentIndex.value = currentIndex.value + add;
|
||||
const target = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryById(
|
||||
selectConfig.value[currentIndex.value].axleCountingId
|
||||
);
|
||||
drawStore.getDrawApp().makeGraphicCenterShow(target);
|
||||
drawStore.getDrawApp().updateSelected(target);
|
||||
}
|
||||
</script>
|
@ -130,6 +130,8 @@ const optionsAlertType = [
|
||||
'道岔大面积失表',
|
||||
'列车信号故障',
|
||||
'一级联锁',
|
||||
'应急触发',
|
||||
'道岔挤岔',
|
||||
];
|
||||
|
||||
enum DeviceType {
|
||||
|
@ -16,7 +16,7 @@ export function getWebsocketUrl() {
|
||||
export function getShowSetAlarmTextButton() {
|
||||
let show = false;
|
||||
const host = window.location.hostname;
|
||||
if (process.env.NODE_ENV == 'development' || host == '192.168.3.233') {
|
||||
if (process.env.NODE_ENV == 'development' || host == '192.168.33.233') {
|
||||
show = true;
|
||||
}
|
||||
return show;
|
||||
|
@ -207,6 +207,12 @@ export class PlatformState extends GraphicStateBase implements IPlatformState {
|
||||
set rtuId(value: number) {
|
||||
this.states.rtuId = value;
|
||||
}
|
||||
get bizWaitTimeSec(): number {
|
||||
return this.states.bizWaitTimeSec;
|
||||
}
|
||||
set bizWaitTimeSec(value: number) {
|
||||
this.states.bizWaitTimeSec = value;
|
||||
}
|
||||
get states(): state.Platform {
|
||||
return this.getState<state.Platform>();
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import { RunLineGraphicHitArea } from 'src/graphics/runLine/RunLineDrawAssistant
|
||||
import { Dialog } from 'quasar';
|
||||
import SetDashLineDialog from '../../components/draw-app/dialogs/SetDashLineDialog.vue';
|
||||
import SetGaryLineDialog from '../../components/draw-app/dialogs/SetGaryLineDialog.vue';
|
||||
import { useLineNetStore } from 'src/stores/line-net-store';
|
||||
|
||||
export class RunLineData extends GraphicDataBase implements IRunLineData {
|
||||
constructor(data?: graphicData.RunLine) {
|
||||
@ -235,7 +236,6 @@ export class DrawRunLinePlugin extends GraphicInteractionPlugin<RunLine> {
|
||||
});
|
||||
};
|
||||
setGrayLineConfig.handler = () => {
|
||||
console.log(runLine.datas, '11111');
|
||||
Dialog.create({
|
||||
title: '设置灰线段',
|
||||
message: '',
|
||||
@ -280,10 +280,22 @@ export class RunLineOperateInteraction extends GraphicInteractionPlugin<RunLine>
|
||||
g.cursor = 'pointer';
|
||||
g.lineBody.hitArea = new RunLineGraphicHitArea(g);
|
||||
g.selectable = true;
|
||||
g.on('_leftclick', this.leftClick, this);
|
||||
}
|
||||
|
||||
unbind(g: RunLine): void {
|
||||
g.selectable = false;
|
||||
g.eventMode = 'none';
|
||||
g.off('_leftclick', this.leftClick, this);
|
||||
}
|
||||
|
||||
leftClick(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const runLine = target.getGraphic() as RunLine;
|
||||
const lineId = runLine.datas.lineId;
|
||||
if (lineId) {
|
||||
useLineNetStore().jumpLineCount++;
|
||||
useLineNetStore().jumpLineId = lineId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,9 @@ import {
|
||||
IGraphicStorage,
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
calculateDistanceFromPointToLine,
|
||||
distance2,
|
||||
getRectangleCenter,
|
||||
} from 'jl-graphic';
|
||||
import { IscsFanData } from './graphics/IscsFanInteraction';
|
||||
import { LinkData } from './graphics/LinkInteraction';
|
||||
@ -286,6 +289,9 @@ export function initDrawApp(): IDrawApp {
|
||||
if (app.drawing) return;
|
||||
handleRIghtClick(e);
|
||||
});
|
||||
app.on('destroy', () => {
|
||||
generateAxleCountingConfig = new graphicData.GenerateAxleCountingConfig();
|
||||
});
|
||||
app.addKeyboardListener(
|
||||
new KeyListener({
|
||||
value: 'KeyS',
|
||||
@ -296,6 +302,99 @@ export function initDrawApp(): IDrawApp {
|
||||
},
|
||||
})
|
||||
);
|
||||
// KeyA 用于区段复制--控制生成的区段位置
|
||||
const graphicCopyPlugin = app.app.graphicCopyPlugin;
|
||||
const copySectionListener = new KeyListener({
|
||||
value: 'KeyA',
|
||||
global: true,
|
||||
onPress: () => {
|
||||
graphicCopyPlugin.updateMoveLimit('sectionPointLimit');
|
||||
},
|
||||
});
|
||||
graphicCopyPlugin.addGraphicControlers([
|
||||
{
|
||||
controlerList: [copySectionListener],
|
||||
check: () => {
|
||||
if (
|
||||
graphicCopyPlugin.copys.length == 1 &&
|
||||
graphicCopyPlugin.copys[0].type == Section.Type
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
moveLimitOption: {
|
||||
moveLimitName: 'sectionPointLimit',
|
||||
moveLimit: (e) => {
|
||||
const mousePos = app.toCanvasCoordinates(e.global);
|
||||
const selectSection = app.selectedGraphics[0] as Section;
|
||||
let selectSectionLeft = selectSection.localToCanvasPoint(
|
||||
selectSection.getStartPoint()
|
||||
);
|
||||
let selectSectionRight = selectSection.localToCanvasPoint(
|
||||
selectSection.getEndPoint()
|
||||
);
|
||||
[selectSectionLeft, selectSectionRight] =
|
||||
selectSectionLeft.x < selectSectionRight.x
|
||||
? [selectSectionLeft, selectSectionRight]
|
||||
: [selectSectionRight, selectSectionLeft];
|
||||
//要移动到目标位的区段
|
||||
const sections = app.queryStore.queryByType<Section>(Section.Type);
|
||||
const minDistanceSection = sections.reduce((prev, cur) => {
|
||||
const prevDistance = calculateDistanceFromPointToLine(
|
||||
prev.localToCanvasPoint(prev.getStartPoint()),
|
||||
prev.localToCanvasPoint(prev.getEndPoint()),
|
||||
mousePos
|
||||
);
|
||||
const curDistance = calculateDistanceFromPointToLine(
|
||||
cur.localToCanvasPoint(cur.getStartPoint()),
|
||||
cur.localToCanvasPoint(cur.getEndPoint()),
|
||||
mousePos
|
||||
);
|
||||
return prevDistance > curDistance ||
|
||||
(prevDistance == curDistance &&
|
||||
distance2(
|
||||
prev.localToCanvasPoint(prev.getStartPoint()),
|
||||
mousePos
|
||||
) >
|
||||
distance2(
|
||||
cur.localToCanvasPoint(cur.getStartPoint()),
|
||||
mousePos
|
||||
))
|
||||
? cur
|
||||
: prev;
|
||||
});
|
||||
const minDistanceRefSectionsPos =
|
||||
minDistanceSection.localToCanvasPoint(
|
||||
getRectangleCenter(
|
||||
minDistanceSection.lineGraphic.getLocalBounds()
|
||||
)
|
||||
);
|
||||
let minDistanceSectionLeft = minDistanceSection.localToCanvasPoint(
|
||||
minDistanceSection.getStartPoint()
|
||||
);
|
||||
let minDistanceSectionRight = minDistanceSection.localToCanvasPoint(
|
||||
minDistanceSection.getEndPoint()
|
||||
);
|
||||
[minDistanceSectionLeft, minDistanceSectionRight] =
|
||||
minDistanceSectionLeft.x < minDistanceSectionRight.x
|
||||
? [minDistanceSectionLeft, minDistanceSectionRight]
|
||||
: [minDistanceSectionRight, minDistanceSectionLeft];
|
||||
|
||||
if (mousePos.x > minDistanceRefSectionsPos.x) {
|
||||
graphicCopyPlugin.container.position.x =
|
||||
minDistanceSectionRight.x - selectSectionLeft.x;
|
||||
graphicCopyPlugin.container.position.y =
|
||||
minDistanceSectionRight.y - selectSectionLeft.y;
|
||||
} else {
|
||||
graphicCopyPlugin.container.position.x =
|
||||
minDistanceSectionLeft.x - selectSectionRight.x;
|
||||
graphicCopyPlugin.container.position.y =
|
||||
minDistanceSectionLeft.y - selectSectionRight.y;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
return drawApp;
|
||||
}
|
||||
|
||||
@ -461,6 +560,7 @@ export function saveDrawDatas(app: IDrawApp) {
|
||||
// item.pcRef.nid = +item.pcRef.id;
|
||||
// }
|
||||
// });
|
||||
storage.generateAxleCountingConfig = generateAxleCountingConfig;
|
||||
const base64 = fromUint8Array(storage.serialize());
|
||||
console.log('保存数据', storage);
|
||||
// localStorage.setItem(StorageKey, base64);
|
||||
@ -483,6 +583,7 @@ export async function loadDrawDatas(): Promise<IGraphicStorage> {
|
||||
);
|
||||
console.log('加载数据', storage);
|
||||
const datas: GraphicData[] = [];
|
||||
generateAxleCountingConfig = storage.generateAxleCountingConfig;
|
||||
storage.links.forEach((link) => {
|
||||
datas.push(new LinkData(link));
|
||||
});
|
||||
@ -546,3 +647,15 @@ export async function loadDrawDatas(): Promise<IGraphicStorage> {
|
||||
datas: [],
|
||||
});
|
||||
}
|
||||
|
||||
//一键生成计轴配置
|
||||
let generateAxleCountingConfig = new graphicData.GenerateAxleCountingConfig();
|
||||
export function loadGenerateAxleCountingConfig() {
|
||||
return generateAxleCountingConfig;
|
||||
}
|
||||
|
||||
export function setGenerateAxleCountingConfig(
|
||||
newScreenDoorConfig: graphicData.GenerateAxleCountingConfig
|
||||
) {
|
||||
generateAxleCountingConfig = newScreenDoorConfig;
|
||||
}
|
||||
|
@ -73,23 +73,32 @@ import {
|
||||
import { Notify, QNotifyUpdateOptions } from 'quasar';
|
||||
import { useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { alert } from 'src/protos/alertInfo';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
import { getMonitorPath } from 'src/router/routes';
|
||||
|
||||
let lineApp: IGraphicApp | null = null;
|
||||
const lineAppMap = new Map<number, IGraphicApp>();
|
||||
|
||||
export function getLineApp() {
|
||||
return lineApp;
|
||||
}
|
||||
|
||||
export function destroyLineApp(): void {
|
||||
if (lineApp) {
|
||||
lineApp.destroy();
|
||||
lineApp = null;
|
||||
for (const key of lineAppMap.keys()) {
|
||||
const app = lineAppMap.get(key);
|
||||
if (app) {
|
||||
app.destroy();
|
||||
}
|
||||
}
|
||||
lineApp = null;
|
||||
}
|
||||
|
||||
export function initLineApp(): IGraphicApp {
|
||||
if (lineApp) return lineApp;
|
||||
|
||||
export function initLineApp(lineId: number): IGraphicApp {
|
||||
lineApp = lineAppMap.get(lineId) || null;
|
||||
if (lineApp) {
|
||||
handleSubscribe(lineApp);
|
||||
return lineApp;
|
||||
}
|
||||
lineApp = newGraphicApp({
|
||||
interactiveGraphicTypeIncludes: [
|
||||
Signal.Type,
|
||||
@ -107,6 +116,7 @@ export function initLineApp(): IGraphicApp {
|
||||
},
|
||||
dataLoader: loadLineDatas,
|
||||
});
|
||||
lineAppMap.set(lineId, lineApp);
|
||||
|
||||
const graphicTemplate = [
|
||||
new TrainTemplate(new TrainData(), new TrainState()),
|
||||
@ -251,6 +261,18 @@ export async function loadLineDatas(): Promise<IGraphicStorage> {
|
||||
}
|
||||
}
|
||||
|
||||
export function cancelSubscribe(lineApp: IGraphicApp) {
|
||||
const lineStore = useLineStore();
|
||||
const lineId = lineStore.lineId;
|
||||
if (lineId) {
|
||||
lineApp.unsubscribe(`/queue/line/${lineId}/device`);
|
||||
lineApp.unsubscribe(`/queue/line/${lineId}/train`);
|
||||
monitorDestinations.forEach((destination) => {
|
||||
lineApp.unsubscribe(destination);
|
||||
});
|
||||
}
|
||||
}
|
||||
let monitorDestinations: string[] = [];
|
||||
function handleSubscribe(lineApp: IGraphicApp) {
|
||||
const lineStore = useLineStore();
|
||||
const lineId = lineStore.lineId;
|
||||
@ -304,11 +326,15 @@ function handleSubscribe(lineApp: IGraphicApp) {
|
||||
},
|
||||
});
|
||||
const lineNetStore = useLineNetStore();
|
||||
const userStore = useUserStore();
|
||||
monitorDestinations = getMonitorPath(userStore.roles).destinations;
|
||||
monitorDestinations.forEach((destination) => {
|
||||
lineApp.subscribe({
|
||||
destination: '/queue/xian/ncc/alert',
|
||||
destination,
|
||||
messageHandle: (message: Uint8Array) => {
|
||||
const storage = alert.NccAlertInfoMessage.deserialize(message);
|
||||
lineNetStore.setAlarmInfo(storage.messages as []);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ import { getWebsocketUrl } from 'src/configs/UrlManage';
|
||||
import { getJwtToken } from 'src/configs/TokenManage';
|
||||
import { alert } from 'src/protos/alertInfo';
|
||||
import { Notify } from 'quasar';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
import { getMonitorPath } from 'src/router/routes';
|
||||
|
||||
let lineNetApp: IGraphicApp | null = null;
|
||||
|
||||
@ -50,6 +52,10 @@ export function destroyLineNetApp(): void {
|
||||
}
|
||||
|
||||
export function initLineNetApp(): IGraphicApp {
|
||||
if (lineNetApp) {
|
||||
handleSubscribe(lineNetApp);
|
||||
return lineNetApp;
|
||||
}
|
||||
lineNetApp = newGraphicApp({
|
||||
interactiveGraphicTypeIncludes: [
|
||||
RunLine.Type,
|
||||
@ -143,6 +149,14 @@ export async function loadLineNetDatas(): Promise<IGraphicStorage> {
|
||||
}
|
||||
}
|
||||
|
||||
export function cancelSubscribe(lineNetApp: IGraphicApp) {
|
||||
lineNetApp.unsubscribe('/queue/lineNet');
|
||||
monitorDestinations.forEach((destination) => {
|
||||
lineNetApp.unsubscribe(destination);
|
||||
});
|
||||
}
|
||||
|
||||
let monitorDestinations: string[] = [];
|
||||
function handleSubscribe(lineNetApp: IGraphicApp) {
|
||||
const lineNetStore = useLineNetStore();
|
||||
lineNetApp.enableWsMassaging({
|
||||
@ -161,11 +175,15 @@ function handleSubscribe(lineNetApp: IGraphicApp) {
|
||||
return states;
|
||||
},
|
||||
});
|
||||
const userStore = useUserStore();
|
||||
monitorDestinations = getMonitorPath(userStore.roles).destinations;
|
||||
monitorDestinations.forEach((destination) => {
|
||||
lineNetApp.subscribe({
|
||||
destination: '/queue/xian/ncc/alert',
|
||||
destination,
|
||||
messageHandle: (message: Uint8Array) => {
|
||||
const storage = alert.NccAlertInfoMessage.deserialize(message);
|
||||
lineNetStore.setAlarmInfo(storage.messages as []);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -14,12 +14,13 @@ import {
|
||||
IAxleCountingData,
|
||||
AxleCounting,
|
||||
AxleCountingTemplate,
|
||||
AxleCountingConsts,
|
||||
} from './AxleCounting';
|
||||
import { Section, SectionPort } from '../section/Section';
|
||||
import { Turnout, TurnoutPort } from '../turnout/Turnout';
|
||||
import { IRelatedRefData, createRelatedRefProto } from '../CommonGraphics';
|
||||
import { Signal } from '../signal/Signal';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { loadGenerateAxleCountingConfig } from 'src/drawApp';
|
||||
|
||||
export interface IAxleCountingDrawOptions {
|
||||
newData: () => IAxleCountingData;
|
||||
@ -80,12 +81,39 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
|
||||
refGraphic: Section | Turnout,
|
||||
refPort: TurnoutPort | SectionPort
|
||||
) {
|
||||
const generateAxleCountingConfig = loadGenerateAxleCountingConfig();
|
||||
if (generateAxleCountingConfig?.noGenerateGroup !== undefined) {
|
||||
const noGenerateGroup = generateAxleCountingConfig.noGenerateGroup;
|
||||
for (let i = 0; i < noGenerateGroup.length; i++) {
|
||||
if (
|
||||
noGenerateGroup[i] == graphic.id &&
|
||||
((i % 2 == 0 && refGraphic.id == noGenerateGroup[i + 1]) ||
|
||||
(i % 2 == 1 && refGraphic.id == noGenerateGroup[i - 1]))
|
||||
) {
|
||||
map.set(`${graphic.id}-${port}`, 1);
|
||||
map.set(`${refGraphic.id}-${refPort}`, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
graphic.type == 'Turnout' &&
|
||||
reftype == 'Turnout' &&
|
||||
port == TurnoutPort.B &&
|
||||
refPort == TurnoutPort.B
|
||||
) {
|
||||
//查看生成计轴bb配置
|
||||
let hasBB = false;
|
||||
if (generateAxleCountingConfig !== undefined) {
|
||||
const bbConnect = generateAxleCountingConfig.bbConnect;
|
||||
if (
|
||||
bbConnect.includes(graphic.id) ||
|
||||
bbConnect.includes(refGraphic.id)
|
||||
) {
|
||||
hasBB = true;
|
||||
}
|
||||
}
|
||||
//bb连接处有信号机需要生成
|
||||
const points = (graphic as Turnout).getPortPoints();
|
||||
const portPs = graphic.localToCanvasPoints(points[1][0])[0];
|
||||
let hasSingle = false;
|
||||
@ -95,7 +123,7 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
|
||||
hasSingle = true;
|
||||
}
|
||||
});
|
||||
if (!hasSingle) {
|
||||
if (!hasSingle && !hasBB) {
|
||||
map.set(`${graphic.id}-${port}`, 1);
|
||||
map.set(`${refGraphic.id}-${refPort}`, 1);
|
||||
return;
|
||||
@ -112,14 +140,7 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
|
||||
const refData2 = createRelatedRefProto(graphic.type, graphic.id, port);
|
||||
const axleCounting = new AxleCounting(direction);
|
||||
axleCounting.loadData(this.graphicTemplate.datas);
|
||||
if (graphic.type == 'Turnout') {
|
||||
axleCounting.position.set(ps.x, ps.y);
|
||||
} else {
|
||||
axleCounting.position.set(
|
||||
ps.x,
|
||||
ps.y - AxleCountingConsts.offsetSection * direction
|
||||
);
|
||||
}
|
||||
axleCounting.id = GraphicIdGenerator.next();
|
||||
axleCounting.datas.axleCountingRef = [refData2, refData1];
|
||||
axleCounting.datas.code = `${graphic.datas.code}-${port}+${refGraphic.datas.code}-${refPort}`;
|
||||
@ -139,14 +160,7 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
|
||||
const refData = createRelatedRefProto(graphic.type, graphic.id, port);
|
||||
const axleCounting = new AxleCounting(direction);
|
||||
axleCounting.loadData(this.graphicTemplate.datas);
|
||||
if (graphic.type == 'Turnout') {
|
||||
axleCounting.position.set(ps.x, ps.y);
|
||||
} else {
|
||||
axleCounting.position.set(
|
||||
ps.x,
|
||||
ps.y - AxleCountingConsts.offsetSection * direction
|
||||
);
|
||||
}
|
||||
axleCounting.id = GraphicIdGenerator.next();
|
||||
axleCounting.datas.axleCountingRef = [refData];
|
||||
axleCounting.datas.code = `${graphic.datas.code}-${port}`;
|
||||
@ -156,9 +170,28 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
|
||||
}
|
||||
oneGenerates(height: Point) {
|
||||
const map = new Map();
|
||||
const axleCountings = this.app.queryStore.queryByType<AxleCounting>(
|
||||
AxleCounting.Type
|
||||
const needDelete: AxleCounting[] = [];
|
||||
const axleCountings = this.app.queryStore
|
||||
.queryByType<AxleCounting>(AxleCounting.Type)
|
||||
.filter((axleCounting) => {
|
||||
if (axleCounting.datas.axleCountingRef.length == 1) {
|
||||
const refInfo = axleCounting.datas.axleCountingRef[0];
|
||||
if (refInfo.deviceType == graphicData.RelatedRef.DeviceType.Section) {
|
||||
const refSection = this.app.queryStore.queryById<Section>(
|
||||
refInfo.id
|
||||
);
|
||||
if (
|
||||
refSection.datas.paRef != undefined &&
|
||||
refSection.datas.pbRef != undefined
|
||||
) {
|
||||
needDelete.push(axleCounting);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
this.app.deleteGraphics(...needDelete);
|
||||
const axleCountingRefs: IRelatedRefData[] = [];
|
||||
axleCountings.forEach((axleCounting) => {
|
||||
axleCountingRefs.push(...axleCounting.datas.axleCountingRef);
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
} from 'jl-graphic';
|
||||
import { Station } from '../station/Station';
|
||||
import { Section } from '../section/Section';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
|
||||
export interface IPlatformData extends GraphicData {
|
||||
get code(): string; // 编号
|
||||
@ -66,6 +67,8 @@ export interface IPlatformState extends GraphicState {
|
||||
set stopTime(v: number);
|
||||
get rtuId(): number; // 集中站站号
|
||||
set rtuId(v: number);
|
||||
get bizWaitTimeSec(): number; //乘客等待秒数
|
||||
set bizWaitTimeSec(v: number);
|
||||
}
|
||||
|
||||
//站台颜色
|
||||
@ -189,6 +192,8 @@ class codeGraph extends Container {
|
||||
runLevel: VectorText = new VectorText(''); //运行等级
|
||||
runTime: VectorText = new VectorText(''); //运行时间
|
||||
stopTime: VectorText = new VectorText(''); //停站时间
|
||||
waitSec: VectorText = new VectorText(); //VectorText
|
||||
|
||||
circle: Graphics = new Graphics();
|
||||
constructor() {
|
||||
super();
|
||||
@ -197,12 +202,14 @@ class codeGraph extends Container {
|
||||
this.addChild(this.circle);
|
||||
this.addChild(this.stopTime);
|
||||
this.addChild(this.runTime);
|
||||
this.addChild(this.waitSec);
|
||||
this.character.setVectorFontSize(platformConsts.besideFontSize);
|
||||
this.runLevel.setVectorFontSize(platformConsts.besideFontSize);
|
||||
this.stopTime.setVectorFontSize(platformConsts.besideFontSize);
|
||||
this.runTime.setVectorFontSize(platformConsts.besideFontSize);
|
||||
this.waitSec.setVectorFontSize(platformConsts.besideFontSize);
|
||||
}
|
||||
draw(): void {
|
||||
draw(datas: IPlatformData): void {
|
||||
//扣车
|
||||
const character = this.character;
|
||||
character.text = 'H';
|
||||
@ -254,11 +261,25 @@ class codeGraph extends Container {
|
||||
platformConsts.besideSpacing
|
||||
);
|
||||
stopTime.style.fill = PlatformColorEnum.whiteNumbers;
|
||||
//乘客等待时间
|
||||
const waitSec = this.waitSec;
|
||||
|
||||
waitSec.anchor.set(0.5);
|
||||
let yPos = platformConsts.height / 2 + platformConsts.doorPlatformSpacing;
|
||||
|
||||
if (datas.direction == 'down') {
|
||||
yPos = -platformConsts.height / 2 - platformConsts.doorPlatformSpacing;
|
||||
}
|
||||
waitSec.position.set(0, yPos);
|
||||
|
||||
waitSec.style.fill = PlatformColorEnum.whiteNumbers;
|
||||
|
||||
character.visible = false;
|
||||
circle.visible = false;
|
||||
runLevel.visible = false;
|
||||
stopTime.visible = false;
|
||||
runTime.visible = false;
|
||||
waitSec.visible = false;
|
||||
}
|
||||
clear(): void {
|
||||
this.character.destroy();
|
||||
@ -309,6 +330,23 @@ class codeGraph extends Container {
|
||||
this.stopTime.visible = true;
|
||||
this.stopTime.text = stateData.stopTime;
|
||||
}
|
||||
if (useLineStore().faultStatistics) {
|
||||
const minutes = Math.floor(stateData.bizWaitTimeSec / 60);
|
||||
const seconds = stateData.bizWaitTimeSec % 60;
|
||||
let minutesString = '' + minutes;
|
||||
let secondsString = '' + seconds;
|
||||
if (minutes < 10) {
|
||||
minutesString = `0${minutes}`;
|
||||
}
|
||||
if (seconds < 10) {
|
||||
secondsString = `0${seconds}`;
|
||||
}
|
||||
|
||||
this.waitSec.visible = true;
|
||||
this.waitSec.text = `${minutesString}:${secondsString}`;
|
||||
} else {
|
||||
this.waitSec.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//子元素--站台旁菱形图标
|
||||
@ -388,7 +426,7 @@ export class Platform extends JlGraphic {
|
||||
}
|
||||
this.platformGraphic.draw(this.states);
|
||||
this.besideGraphic.draw();
|
||||
this.codeGraph.draw();
|
||||
this.codeGraph.draw(this.datas);
|
||||
|
||||
this.doorGraphic.position.set(
|
||||
0,
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
distance2,
|
||||
splitLineEvenly,
|
||||
ILineGraphic,
|
||||
epsilon,
|
||||
Vector2,
|
||||
} from 'jl-graphic';
|
||||
import {
|
||||
@ -29,6 +28,8 @@ export enum SectionPort {
|
||||
B = 'B',
|
||||
}
|
||||
|
||||
const sectionEpsilon = 0.1;
|
||||
|
||||
export interface ISectionData extends GraphicData {
|
||||
get code(): string; // 编号
|
||||
set code(v: string);
|
||||
@ -148,17 +149,17 @@ export class Section extends JlGraphic implements ILineGraphic {
|
||||
const destinationCodePosition = this.datas.childTransforms?.find(
|
||||
(t) => t.name === this.destinationCodeGraphic.name
|
||||
)?.transform.position;
|
||||
// if (destinationCodePosition) {
|
||||
// this.destinationCodeGraphic.position.set(
|
||||
// destinationCodePosition.x,
|
||||
// destinationCodePosition.y
|
||||
// );
|
||||
// } else {
|
||||
if (destinationCodePosition) {
|
||||
this.destinationCodeGraphic.position.set(
|
||||
destinationCodePosition.x,
|
||||
destinationCodePosition.y
|
||||
);
|
||||
} else {
|
||||
this.destinationCodeGraphic.position.set(
|
||||
this.datas.points[0].x,
|
||||
this.datas.points[0].y - 20
|
||||
);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,7 +245,7 @@ export class Section extends JlGraphic implements ILineGraphic {
|
||||
distance2(
|
||||
this.localToCanvasPoint(this.getStartPoint()),
|
||||
section.localToCanvasPoint(section.getStartPoint())
|
||||
) <= epsilon
|
||||
) <= sectionEpsilon
|
||||
) {
|
||||
param = [SectionPort.A, SectionPort.A];
|
||||
}
|
||||
@ -252,7 +253,7 @@ export class Section extends JlGraphic implements ILineGraphic {
|
||||
distance2(
|
||||
this.localToCanvasPoint(this.getEndPoint()),
|
||||
section.localToCanvasPoint(section.getStartPoint())
|
||||
) <= epsilon
|
||||
) <= sectionEpsilon
|
||||
) {
|
||||
param = [SectionPort.B, SectionPort.A];
|
||||
}
|
||||
@ -260,7 +261,7 @@ export class Section extends JlGraphic implements ILineGraphic {
|
||||
distance2(
|
||||
this.localToCanvasPoint(this.getStartPoint()),
|
||||
section.localToCanvasPoint(section.getEndPoint())
|
||||
) <= epsilon
|
||||
) <= sectionEpsilon
|
||||
) {
|
||||
param = [SectionPort.A, SectionPort.B];
|
||||
}
|
||||
@ -268,7 +269,7 @@ export class Section extends JlGraphic implements ILineGraphic {
|
||||
distance2(
|
||||
this.localToCanvasPoint(this.getEndPoint()),
|
||||
section.localToCanvasPoint(section.getEndPoint())
|
||||
) <= epsilon
|
||||
) <= sectionEpsilon
|
||||
) {
|
||||
param = [SectionPort.B, SectionPort.B];
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ import { AxleCounting } from '../axleCounting/AxleCounting';
|
||||
import { LogicSectionData } from 'src/drawApp/graphics/LogicSectionInteraction';
|
||||
import { LogicSectionDraw } from '../logicSection/LogicSectionDrawAssistant';
|
||||
import { LogicSection } from '../logicSection/LogicSection';
|
||||
import { buildDragMoveAbsorbablePositions } from '../turnout/TurnoutDrawAssistant';
|
||||
|
||||
export class SectionDraw extends GraphicDrawAssistant<
|
||||
SectionTemplate,
|
||||
@ -443,11 +444,13 @@ export class SectionPointEditPlugin extends GraphicInteractionPlugin<Section> {
|
||||
g.on('selected', this.onSelected, this);
|
||||
g.on('unselected', this.onUnselected, this);
|
||||
g.on('_rightclick', this.onContextMenu, this);
|
||||
g.on('transformstart', this.onDragMove, this);
|
||||
}
|
||||
unbind(g: Section): void {
|
||||
g.off('selected', this.onSelected, this);
|
||||
g.off('unselected', this.onUnselected, this);
|
||||
g.off('_rightclick', this.onContextMenu, this);
|
||||
g.off('transformstart', this.onDragMove, this);
|
||||
}
|
||||
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
@ -585,4 +588,10 @@ export class SectionPointEditPlugin extends GraphicInteractionPlugin<Section> {
|
||||
section.draggable = false;
|
||||
}
|
||||
}
|
||||
onDragMove(e: GraphicTransformEvent) {
|
||||
const section = e.target as Section;
|
||||
this.app.setOptions({
|
||||
absorbablePositions: buildDragMoveAbsorbablePositions(section),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -195,6 +195,7 @@ export class Station extends JlGraphic {
|
||||
codeGraph.anchor.set(0.5);
|
||||
const kilometerCode = this.datas.kilometerSystem?.kilometer || 12345678;
|
||||
if (Math.floor(kilometerCode * 1000).toString().length > 3) {
|
||||
if (Number(kilometerCode) > 0) {
|
||||
const kiloBit = Math.floor(Number(kilometerCode) / 1000000).toString();
|
||||
kilometerGraph.text =
|
||||
'K' +
|
||||
@ -203,6 +204,17 @@ export class Station extends JlGraphic {
|
||||
(
|
||||
Number(kilometerCode.toString().substring(kiloBit.length)) / 1000
|
||||
).toFixed(3);
|
||||
} else {
|
||||
const fuKilometerCode = Number(kilometerCode) * -1;
|
||||
const kiloBit = Math.floor(fuKilometerCode / 1000000).toString();
|
||||
kilometerGraph.text =
|
||||
'K-' +
|
||||
kiloBit +
|
||||
'-' +
|
||||
(
|
||||
Number(kilometerCode.toString().substring(kiloBit.length)) / 1000
|
||||
).toFixed(3);
|
||||
}
|
||||
} else {
|
||||
kilometerGraph.text = (kilometerCode * 1000).toFixed(3);
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import {
|
||||
angleOfIncludedAngle,
|
||||
distance2,
|
||||
getParallelOfPolyline,
|
||||
epsilon,
|
||||
Vector2,
|
||||
} from 'jl-graphic';
|
||||
import { Section, SectionPort, SectionType } from '../section/Section';
|
||||
@ -22,6 +21,7 @@ import {
|
||||
import { KilometerSystem } from '../signal/Signal';
|
||||
import { Station } from '../station/Station';
|
||||
|
||||
const turnoutEpsilon = 0.1;
|
||||
export interface ITurnoutData extends GraphicData {
|
||||
get code(): string;
|
||||
set code(code: string);
|
||||
@ -541,22 +541,20 @@ export class Turnout extends JlGraphic {
|
||||
buildRelation(): void {
|
||||
this.relationManage.deleteRelationOfGraphic(this);
|
||||
|
||||
|
||||
/** 道岔和区段 */
|
||||
this.queryStore.queryByType<Section>(Section.Type)
|
||||
.forEach((section) => {
|
||||
this.queryStore.queryByType<Section>(Section.Type).forEach((section) => {
|
||||
if (section.datas.sectionType === SectionType.TurnoutPhysical) {
|
||||
if (section.datas.children.includes(this.datas.id)) {
|
||||
this.relationManage.addRelation(this, section)
|
||||
this.relationManage.addRelation(this, section);
|
||||
}
|
||||
return
|
||||
return;
|
||||
}
|
||||
this.getPortPoints().forEach((port, i) => {
|
||||
if (
|
||||
distance2(
|
||||
section.localToCanvasPoint(section.getStartPoint()),
|
||||
this.localToCanvasPoint(port[port.length - 1])
|
||||
) <= epsilon
|
||||
) <= turnoutEpsilon
|
||||
) {
|
||||
this.relationManage.addRelation(
|
||||
new GraphicRelationParam(
|
||||
@ -570,7 +568,7 @@ export class Turnout extends JlGraphic {
|
||||
distance2(
|
||||
section.localToCanvasPoint(section.getEndPoint()),
|
||||
this.localToCanvasPoint(port[port.length - 1])
|
||||
) <= epsilon
|
||||
) <= turnoutEpsilon
|
||||
) {
|
||||
this.relationManage.addRelation(
|
||||
new GraphicRelationParam(
|
||||
@ -594,7 +592,7 @@ export class Turnout extends JlGraphic {
|
||||
distance2(
|
||||
this.localToCanvasPoint(thisPort[thisPort.length - 1]),
|
||||
turnout.localToCanvasPoint(otherPort[otherPort.length - 1])
|
||||
) <= epsilon
|
||||
) <= turnoutEpsilon
|
||||
) {
|
||||
const angle = angleOfIncludedAngle(
|
||||
this.localToCanvasPoint(thisPort[thisPort.length - 1]) /* 交点 */,
|
||||
@ -668,9 +666,13 @@ export class Turnout extends JlGraphic {
|
||||
const pcRelation = this.relationManage
|
||||
.getRelationsOfGraphic(this)
|
||||
.find(
|
||||
(relation) => relation.getRelationParam(this).param === TurnoutPort.C
|
||||
&& (!(relation.getOtherGraphic(this) instanceof Section
|
||||
&& relation.getOtherGraphic<Section>(this).datas.sectionType !== SectionType.TurnoutPhysical))
|
||||
(relation) =>
|
||||
relation.getRelationParam(this).param === TurnoutPort.C &&
|
||||
!(
|
||||
relation.getOtherGraphic(this) instanceof Section &&
|
||||
relation.getOtherGraphic<Section>(this).datas.sectionType !==
|
||||
SectionType.TurnoutPhysical
|
||||
)
|
||||
);
|
||||
const pcDevice = pcRelation?.getOtherGraphic<Section | Turnout>(this);
|
||||
if (pcDevice) {
|
||||
|
@ -17,6 +17,7 @@ import {
|
||||
AbsorbableLine,
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
distance,
|
||||
} from 'jl-graphic';
|
||||
import {
|
||||
ITurnoutData,
|
||||
@ -178,6 +179,130 @@ function buildAbsorbablePositions(turnout: Turnout): AbsorbablePosition[] {
|
||||
return aps;
|
||||
}
|
||||
|
||||
type dragType = Turnout | Section;
|
||||
class DragMoveAbsorbablePoint extends AbsorbablePoint {
|
||||
moveTarget:
|
||||
| {
|
||||
position: IPointData;
|
||||
portPos: IPointData[];
|
||||
}
|
||||
| undefined;
|
||||
constructor(point: IPointData, absorbRange = 15) {
|
||||
super(point, absorbRange);
|
||||
}
|
||||
tryAbsorb(...dragTargets: dragType[]): void {
|
||||
const dragTarget = dragTargets[0];
|
||||
if (dragTarget instanceof Turnout) {
|
||||
if (this.moveTarget == undefined) {
|
||||
const {
|
||||
pointA: [A],
|
||||
pointB: [B],
|
||||
pointC: [C],
|
||||
} = dragTarget.datas;
|
||||
this.moveTarget = {
|
||||
position: dragTarget
|
||||
.getGraphicApp()
|
||||
.toCanvasCoordinates(dragTarget.getGlobalPosition()),
|
||||
portPos: [
|
||||
dragTarget.localToCanvasPoint(A),
|
||||
dragTarget.localToCanvasPoint(B),
|
||||
dragTarget.localToCanvasPoint(C),
|
||||
],
|
||||
};
|
||||
}
|
||||
const {
|
||||
pointA: [A],
|
||||
pointB: [B],
|
||||
pointC: [C],
|
||||
} = dragTarget.datas;
|
||||
[A, B, C].forEach((p, i) => {
|
||||
const changePos = dragTarget.localToCanvasPoint(p);
|
||||
if (
|
||||
distance(this._point.x, this._point.y, changePos.x, changePos.y) <
|
||||
this.absorbRange &&
|
||||
this.moveTarget
|
||||
) {
|
||||
dragTarget.updatePositionByCanvasPosition(
|
||||
new Point(
|
||||
this.moveTarget.position.x +
|
||||
this._point.x -
|
||||
this.moveTarget.portPos[i].x,
|
||||
this.moveTarget.position.y +
|
||||
this._point.y -
|
||||
this.moveTarget.portPos[i].y
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (this.moveTarget == undefined) {
|
||||
this.moveTarget = {
|
||||
position: dragTarget
|
||||
.getGraphicApp()
|
||||
.toCanvasCoordinates(dragTarget.getGlobalPosition()),
|
||||
portPos: [
|
||||
dragTarget.localToCanvasPoint(dragTarget.getStartPoint()),
|
||||
dragTarget.localToCanvasPoint(dragTarget.getEndPoint()),
|
||||
],
|
||||
};
|
||||
}
|
||||
dragTarget
|
||||
.localToCanvasPoints(...dragTarget.datas.points)
|
||||
.forEach((p, i) => {
|
||||
if (
|
||||
distance(this._point.x, this._point.y, p.x, p.y) <
|
||||
this.absorbRange &&
|
||||
this.moveTarget
|
||||
) {
|
||||
dragTarget.updatePositionByCanvasPosition(
|
||||
new Point(
|
||||
this.moveTarget.position.x +
|
||||
this._point.x -
|
||||
this.moveTarget.portPos[i].x,
|
||||
this.moveTarget.position.y +
|
||||
this._point.y -
|
||||
this.moveTarget.portPos[i].y
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function buildDragMoveAbsorbablePositions(
|
||||
target: dragType
|
||||
): AbsorbablePosition[] {
|
||||
const aps: AbsorbablePosition[] = [];
|
||||
|
||||
const sections = target.queryStore.queryByType<Section>(Section.Type);
|
||||
sections.forEach((section) => {
|
||||
if (section.id !== target.id) {
|
||||
section.localToCanvasPoints(...section.datas.points).forEach((p) => {
|
||||
aps.push(new DragMoveAbsorbablePoint(p)); //区段端点
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const turnouts = target.queryStore.queryByType<Turnout>(Turnout.Type);
|
||||
turnouts.forEach((otherTurnout) => {
|
||||
if (otherTurnout.id !== target.id) {
|
||||
const {
|
||||
pointA: [A],
|
||||
pointB: [B],
|
||||
pointC: [C],
|
||||
} = otherTurnout.datas;
|
||||
[A, B, C].forEach((p) => {
|
||||
aps.push(
|
||||
new DragMoveAbsorbablePoint(otherTurnout.localToCanvasPoint(p)) //道岔端点
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return aps;
|
||||
}
|
||||
|
||||
function onEditPointCreate(turnout: Turnout, dp: DraggablePoint) {
|
||||
dp.on('transformstart', (e: GraphicTransformEvent) => {
|
||||
if (e.isShift()) {
|
||||
@ -290,6 +415,7 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
|
||||
g.transformSave = true;
|
||||
g.on('selected', this.onSelected, this);
|
||||
g.on('unselected', this.onUnSelected, this);
|
||||
g.on('transformstart', this.onDragMove, this);
|
||||
}
|
||||
|
||||
unbind(g: Turnout): void {
|
||||
@ -298,6 +424,7 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
|
||||
g.graphics.sections.forEach((sectionGraphic) => {
|
||||
sectionGraphic.off('rightclick');
|
||||
});
|
||||
g.off('transformstart', this.onDragMove, this);
|
||||
}
|
||||
|
||||
onSelected(g: DisplayObject) {
|
||||
@ -309,6 +436,9 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
|
||||
tep = new TurnoutEditPlugin(turnout, { onEditPointCreate });
|
||||
turnout.addAssistantAppend(tep);
|
||||
}
|
||||
tep.editPoints = [[], [], []];
|
||||
tep.removeChildren();
|
||||
tep.initEditPoints();
|
||||
// tep.reset();
|
||||
tep.showAll();
|
||||
tep.setRelatedDrag();
|
||||
@ -327,6 +457,13 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
|
||||
filter(...grahpics: JlGraphic[]): Turnout[] | undefined {
|
||||
return grahpics.filter((g) => g.type == Turnout.Type) as Turnout[];
|
||||
}
|
||||
|
||||
onDragMove(e: GraphicTransformEvent) {
|
||||
const turnout = e.target as Turnout;
|
||||
this.app.setOptions({
|
||||
absorbablePositions: buildDragMoveAbsorbablePositions(turnout),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
type onTurnoutEditPointCreate = (turnout: Turnout, dp: DraggablePoint) => void;
|
||||
@ -441,7 +578,7 @@ export class TurnoutEditPlugin extends GraphicEditPlugin<Turnout> {
|
||||
Array.from(cpMap.entries()).forEach(([cpDatas, dataPoints], i) => {
|
||||
cpDatas.forEach((cpData, j) => {
|
||||
const dp = new DraggablePoint(cpData);
|
||||
dp.on('transforming', (e: GraphicTransformEvent) => {
|
||||
dp.on('transforming', () => {
|
||||
const localPoint = this.graphic.canvasToLocalPoint(dp.position);
|
||||
dataPoints[j].x = localPoint.x;
|
||||
dataPoints[j].y = localPoint.y;
|
||||
|
@ -122,8 +122,11 @@
|
||||
|
||||
<q-drawer show-if-above bordered v-model="rightDrawerOpen" side="right">
|
||||
<q-resize-observer @resize="onRightResize" />
|
||||
<!-- drawer content -->
|
||||
<draw-properties></draw-properties>
|
||||
<axleCounting-config
|
||||
v-if="showGenerateAxleCountingConfig"
|
||||
@close="closeGenerateAxleCountingConfig"
|
||||
/>
|
||||
<draw-properties v-else></draw-properties>
|
||||
</q-drawer>
|
||||
|
||||
<q-page-container>
|
||||
@ -189,6 +192,7 @@ import {
|
||||
findContainDevice,
|
||||
handleCentralizedStationsData,
|
||||
} from 'src/graphics/concentrationDividingLine/ConcentrationDividingLineUtils';
|
||||
import AxleCountingConfig from 'src/components/draw-app/properties/AxleCountingConfig.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@ -358,10 +362,14 @@ function oneClickSeparator() {
|
||||
.getDrawAssistant(Separator.Type) as SeparatorDraw;
|
||||
separatorDraw.oneGenerates();
|
||||
}
|
||||
|
||||
const showGenerateAxleCountingConfig = ref(false);
|
||||
const closeGenerateAxleCountingConfig = () => {
|
||||
showGenerateAxleCountingConfig.value = false;
|
||||
};
|
||||
function oneClickAxleCounting() {
|
||||
//一键生成计轴
|
||||
drawStore.oneClickType = 'AxleCounting';
|
||||
drawStore.getDrawApp().interactionPlugin(OneClickGenerate.Type).resume();
|
||||
showGenerateAxleCountingConfig.value = true;
|
||||
}
|
||||
|
||||
function oneClickTurnoutSection() {
|
||||
|
@ -15,7 +15,13 @@
|
||||
<img :src="NCC" style="width: 80px" />
|
||||
</div>
|
||||
<q-toolbar-title> 西安NCC调度辅助决策系统 </q-toolbar-title>
|
||||
|
||||
<!-- <q-btn
|
||||
v-show="route.path.includes('line/monitor')"
|
||||
color="info"
|
||||
label="故障查询"
|
||||
class="q-mr-sm"
|
||||
@click="openFaultQueryDialog()"
|
||||
/> -->
|
||||
<q-btn
|
||||
v-show="route.path.includes('line/monitor')"
|
||||
color="info"
|
||||
@ -40,11 +46,45 @@
|
||||
|
||||
<div class="q-gutter-sm row items-center no-wrap">
|
||||
<q-btn
|
||||
v-show="route.path.includes('line/monitor/')"
|
||||
v-show="showBackMonitor"
|
||||
color="info"
|
||||
label="返回"
|
||||
@click="backConfirm"
|
||||
/>
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
flat
|
||||
:color="lineStore.faultStatistics ? 'white' : 'red'"
|
||||
:icon="lineStore.faultStatistics ? 'grid_on' : 'grid_off'"
|
||||
@click="
|
||||
() => {
|
||||
lineStore.faultStatistics = !lineStore.faultStatistics;
|
||||
}
|
||||
"
|
||||
>
|
||||
<q-tooltip style="font-size: 14px">
|
||||
{{
|
||||
lineStore.faultStatistics
|
||||
? '关闭故障信息统计'
|
||||
: '开启故障信息统计'
|
||||
}}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
flat
|
||||
:color="lineNetStore.handlePlayAble ? 'white' : 'red'"
|
||||
:icon="lineNetStore.handlePlayAble ? 'alarm_on' : 'alarm_off'"
|
||||
@click="changeCanPlayAlarmMusic"
|
||||
>
|
||||
<q-tooltip style="font-size: 14px">
|
||||
{{
|
||||
lineNetStore.handlePlayAble ? '关闭语音报警' : '开启语音报警'
|
||||
}}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
@ -54,6 +94,9 @@
|
||||
@click="$q.fullscreen.toggle()"
|
||||
v-if="$q.screen.gt.sm"
|
||||
>
|
||||
<q-tooltip style="font-size: 14px">
|
||||
{{ $q.fullscreen.isActive ? '关闭全屏' : '开启全屏' }}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
flat
|
||||
@ -62,7 +105,9 @@
|
||||
icon="connected_tv"
|
||||
:color="lineNetStore.connectButtonColor"
|
||||
@click="openConnectInfoDialog"
|
||||
/>
|
||||
>
|
||||
<q-tooltip style="font-size: 14px">与同方连接状态</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn-dropdown
|
||||
flat
|
||||
stretch
|
||||
@ -98,11 +143,11 @@
|
||||
</q-scroll-area>
|
||||
</q-page-container>
|
||||
</q-layout>
|
||||
<commonAlarm v-if="route.path.includes('alarmList')" />
|
||||
<commonAlarm v-if="route.path.includes('alarmInfo')" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, onUnmounted } from 'vue';
|
||||
import { ref, reactive, onMounted, onUnmounted, computed, watch } from 'vue';
|
||||
import SysMenu from 'src/components/SysMenu.vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { Dialog, DialogChainObject, useQuasar } from 'quasar';
|
||||
@ -124,12 +169,28 @@ import {
|
||||
webSocketConnect,
|
||||
closeWebSocketConnect,
|
||||
} from 'src/components/webSocketConnect';
|
||||
import { logout } from 'src/api/UserApi';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
import { getMonitorPath } from 'src/router/routes';
|
||||
import FaultQueryDialog from 'src/components/dialog/FaultQueryDialog.vue';
|
||||
|
||||
const leftDrawerOpen = ref(false);
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const lineStore = useLineStore();
|
||||
const lineNetStore = useLineNetStore();
|
||||
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
if (!route.path.includes('line/monitor') && faultQueryDialogInstance) {
|
||||
faultQueryDialogInstance.hide();
|
||||
faultQueryDialogInstance = null;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function toggleLeftDrawer() {
|
||||
leftDrawerOpen.value = !leftDrawerOpen.value;
|
||||
onResize();
|
||||
@ -153,6 +214,14 @@ function onLeftResize(size: { width: number; height: number }) {
|
||||
leftDrawerSize.height = size.height;
|
||||
}
|
||||
|
||||
const showBackMonitor = computed(() => {
|
||||
const userStore = useUserStore();
|
||||
const isShow =
|
||||
route.path.includes('line/monitor/') &&
|
||||
getMonitorPath(userStore.roles).lineType == 'NCC';
|
||||
return isShow;
|
||||
});
|
||||
|
||||
const watchInteract = () => {
|
||||
lineNetStore.playAble = true;
|
||||
document.removeEventListener('click', watchInteract);
|
||||
@ -168,6 +237,14 @@ onMounted(() => {
|
||||
socket = webSocketConnect(destination, handler);
|
||||
});
|
||||
|
||||
let faultQueryDialogInstance: DialogChainObject | null = null;
|
||||
function openFaultQueryDialog() {
|
||||
if (faultQueryDialogInstance) return;
|
||||
faultQueryDialogInstance = $q.dialog({
|
||||
component: FaultQueryDialog,
|
||||
});
|
||||
}
|
||||
|
||||
//模拟报警
|
||||
const $q = useQuasar();
|
||||
function openSetAlarmMockDialog() {
|
||||
@ -210,9 +287,18 @@ function logOut() {
|
||||
message: '确认是否登出?',
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk(() => {
|
||||
}).onOk(async () => {
|
||||
try {
|
||||
await logout();
|
||||
clearJwtToken();
|
||||
router.push({ name: 'login' });
|
||||
} catch (err) {
|
||||
const apiErr = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: apiErr.title,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -241,4 +327,8 @@ function resetFn() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function changeCanPlayAlarmMusic() {
|
||||
lineNetStore.handlePlayAble = !lineNetStore.handlePlayAble;
|
||||
}
|
||||
</script>
|
||||
|
@ -44,6 +44,13 @@
|
||||
lazy-rules
|
||||
:rules="[(val) => val >= 0 || '请选择线路ID!']"
|
||||
/>
|
||||
<q-select
|
||||
dense
|
||||
label="线路类型"
|
||||
v-model="filter.lineType"
|
||||
:options="searchOptionsLineType"
|
||||
style="width: 100px"
|
||||
/>
|
||||
<q-input
|
||||
dense
|
||||
v-model="filter.beginDateTime"
|
||||
@ -237,6 +244,8 @@ import {
|
||||
webSocketConnect,
|
||||
closeWebSocketConnect,
|
||||
} from 'src/components/webSocketConnect';
|
||||
import { getMonitorPath } from 'src/router/routes';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
|
||||
const $q = useQuasar();
|
||||
const lineNetStore = useLineNetStore();
|
||||
@ -246,6 +255,7 @@ const props = withDefaults(
|
||||
}>(),
|
||||
{ sizeHeight: 500 }
|
||||
);
|
||||
const userStore = useUserStore();
|
||||
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
@ -271,6 +281,13 @@ const columnDefs: QTableColumn[] = [
|
||||
field: 'lineId',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'lineType',
|
||||
label: '线路类型',
|
||||
field: 'lineType',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'alertObject',
|
||||
label: '设备',
|
||||
@ -334,7 +351,11 @@ async function onRequest(props: any) {
|
||||
lineId: filter.value.lineId,
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.value.lineType !== '全部') {
|
||||
Object.assign(params, {
|
||||
lineType: filter.value.lineType,
|
||||
});
|
||||
}
|
||||
if (filter.value.alertType !== '全部') {
|
||||
Object.assign(params, {
|
||||
alertType: (saveAlertTypeData as never)[filter.value.alertType],
|
||||
@ -369,10 +390,16 @@ async function onRequest(props: any) {
|
||||
|
||||
onMounted(() => {
|
||||
queryLineInfo();
|
||||
destinations = getMonitorPath(userStore.roles).destinations;
|
||||
setTimeout(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
lineNetStore.alarmInfoListTable = tableRef.value;
|
||||
socket = webSocketConnect(destination, handler);
|
||||
destinations.forEach((destination) => {
|
||||
allSocketsAndDestinations.push({
|
||||
socket: webSocketConnect(destination, handler),
|
||||
destination,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -386,8 +413,12 @@ watch(
|
||||
);
|
||||
|
||||
function updateSelect() {
|
||||
const config = getMonitorPath(userStore.roles);
|
||||
for (let i = 0; i < selected.value.length; i++) {
|
||||
if (selected.value[i].alarmStatus !== -1) {
|
||||
const canSelect =
|
||||
config.lineType == selected.value[i].lineType &&
|
||||
config.lineIds.includes(+selected.value[i].lineId);
|
||||
if (selected.value[i].alarmStatus !== -1 || !canSelect) {
|
||||
selected.value.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
@ -419,6 +450,7 @@ function batchHandle() {
|
||||
const filter = ref({
|
||||
alertType: '全部',
|
||||
lineId: 0,
|
||||
lineType: '全部',
|
||||
beginDateTime: '',
|
||||
endDateTime: '',
|
||||
alertStatus: 999,
|
||||
@ -427,6 +459,7 @@ const filter = ref({
|
||||
const optionsLineId = ref<{ label: string; value: number }[]>([
|
||||
{ label: '全部', value: 0 },
|
||||
]);
|
||||
const searchOptionsLineType = ['全部', 'NCC', 'OCC'];
|
||||
async function queryLineInfo() {
|
||||
try {
|
||||
let response = await pageQuery({
|
||||
@ -465,6 +498,9 @@ const optionsAlertType = [
|
||||
'列车信号故障',
|
||||
'联锁区红光带',
|
||||
'联锁区橙光带',
|
||||
'应急触发',
|
||||
'道岔挤岔',
|
||||
'车站扣车',
|
||||
];
|
||||
|
||||
//时间校验
|
||||
@ -532,6 +568,7 @@ function openAlarmDialog(row: any) {
|
||||
row.alert_time = row.alertTime;
|
||||
row.alert_type = row.alertType;
|
||||
row.line_id = row.lineId;
|
||||
row.line_type = row.lineType;
|
||||
row.alert_object = row.alertObject;
|
||||
row.alert_tip_id = row.alertTipId;
|
||||
row.alert_location_id = row.alertLocationId;
|
||||
@ -551,15 +588,20 @@ function openAlarmDialog(row: any) {
|
||||
});
|
||||
}
|
||||
|
||||
let socket: StompMessagingClient | null = null;
|
||||
const destination = '/queue/xian/ncc/alert';
|
||||
let allSocketsAndDestinations: {
|
||||
socket: StompMessagingClient;
|
||||
destination: string;
|
||||
}[] = [];
|
||||
let destinations: string[] = [];
|
||||
function handler(message: Uint8Array) {
|
||||
const storage = alert.NccAlertInfoMessage.deserialize(message);
|
||||
lineNetStore.setAlarmInfo(storage.messages as []);
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
closeWebSocketConnect(socket, destination);
|
||||
allSocketsAndDestinations.forEach((info) => {
|
||||
closeWebSocketConnect(info.socket, info.destination);
|
||||
});
|
||||
});
|
||||
|
||||
//报警统计
|
||||
|
294
src/pages/AlarmRecord.vue
Normal file
294
src/pages/AlarmRecord.vue
Normal file
@ -0,0 +1,294 @@
|
||||
<template>
|
||||
<div class="q-pa-md">
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
title="报警记录"
|
||||
:style="{ height: tableHeight + 'px' }"
|
||||
class="my-sticky-virtscroll-table"
|
||||
:rows="rows"
|
||||
:columns="columnDefs"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:loading="loading"
|
||||
binary-state-sort
|
||||
@request="onRequest"
|
||||
>
|
||||
<template v-slot:top-right>
|
||||
<q-input
|
||||
dense
|
||||
class="q-mr-md"
|
||||
debounce="1000"
|
||||
v-model="filter.name"
|
||||
label="操作人"
|
||||
></q-input>
|
||||
<q-input
|
||||
v-model="filter.beginDate"
|
||||
label="开始时间"
|
||||
debounce="1000"
|
||||
class="q-mr-md"
|
||||
dense
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-date v-model="filter.beginDate" mask="YYYY-MM-DD HH:mm:ss">
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-date>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<q-icon name="access_time" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-time
|
||||
v-model="filter.beginDate"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
format24h
|
||||
with-seconds
|
||||
>
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="Close" color="primary" flat />
|
||||
</div>
|
||||
</q-time>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
v-model="filter.endDate"
|
||||
label="截止时间"
|
||||
debounce="1000"
|
||||
class="q-mr-md"
|
||||
dense
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-date v-model="filter.endDate" mask="YYYY-MM-DD HH:mm:ss">
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-date>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<q-icon name="access_time" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-time
|
||||
v-model="filter.endDate"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
format24h
|
||||
with-seconds
|
||||
>
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-time>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
|
||||
</template>
|
||||
<!-- <template v-slot:body-cell-subEventType="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip outline size="sm" color="primary">
|
||||
{{ getSubEventType(props.row.subEventType) }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template> -->
|
||||
<template v-slot:body-cell-requestSuccess="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip outline size="sm" color="primary">
|
||||
{{ props.row.requestSuccess === 1 ? '连接' : '断开' }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
<!-- <template v-slot:top-right>
|
||||
<q-input
|
||||
dense
|
||||
debounce="1000"
|
||||
v-model="filter.name"
|
||||
label="用户名"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
</template> -->
|
||||
<!-- <template v-slot:body-cell-roles="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip
|
||||
outline
|
||||
size="sm"
|
||||
color="primary"
|
||||
v-for="(item, index) in props.row.roleList"
|
||||
:key="index"
|
||||
>
|
||||
{{ item.roleName }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template> -->
|
||||
<!-- <template v-slot:body-cell-operations="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="编辑角色"
|
||||
:disable="operateDisabled"
|
||||
@click="edieUserData(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template> -->
|
||||
</q-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { type QTableColumn } from 'quasar';
|
||||
import { pageQuery, Record } from '../api/LogApi';
|
||||
import { errorNotify } from '../utils/CommonNotify';
|
||||
|
||||
// const $q = useQuasar(); useQuasar
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
}>(),
|
||||
{ sizeHeight: 500 }
|
||||
);
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
|
||||
{
|
||||
name: 'lineId',
|
||||
label: '线路ID',
|
||||
field: 'lineId',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faceName',
|
||||
label: '接口名称',
|
||||
field: 'faceName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
label: '操作人员',
|
||||
field: 'userName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'createDateTime',
|
||||
label: '记录时间',
|
||||
field: 'createDateTime',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'requestSuccess',
|
||||
label: '连接断开',
|
||||
field: 'requestSuccess',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const filter = reactive({
|
||||
name: '',
|
||||
beginDate: '',
|
||||
endDate: '',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
let response = await pageQuery({
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
logType: 'WARN',
|
||||
name: filter.name,
|
||||
beginDate: filter.beginDate,
|
||||
endDate: filter.endDate,
|
||||
});
|
||||
|
||||
pagination.value.rowsNumber = response.total;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
pagination.value.sortBy = sortBy;
|
||||
pagination.value.descending = descending;
|
||||
rows.splice(0, rows.length, ...(response.records as []));
|
||||
} catch (error: any) {
|
||||
errorNotify('获取数据失败', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function getSubEventType(type: string) {
|
||||
switch (type) {
|
||||
case 'LOGIN':
|
||||
return '登录';
|
||||
case 'LOGOUT':
|
||||
return '登出';
|
||||
case 'QUERY':
|
||||
return '查询';
|
||||
case 'SAVE_OR_UPDATE':
|
||||
return '保存';
|
||||
case 'DELETE':
|
||||
return '删除';
|
||||
case 'WARN':
|
||||
return '报警';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function searchQuery() {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
</script>
|
372
src/pages/AuthPathManage.vue
Normal file
372
src/pages/AuthPathManage.vue
Normal file
@ -0,0 +1,372 @@
|
||||
<template>
|
||||
<div class="q-pa-md">
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
title="权限接口列表"
|
||||
:style="{ height: tableHeight + 'px' }"
|
||||
class="my-sticky-virtscroll-table"
|
||||
:rows="rows"
|
||||
:columns="columnDefs"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:loading="loading"
|
||||
:filter="filter"
|
||||
:selection="isRole ? 'multiple' : 'none'"
|
||||
v-model:selected="selected"
|
||||
@update:selected="tableSelected"
|
||||
:selected-rows-label="getSelectedString"
|
||||
binary-state-sort
|
||||
@request="onRequest"
|
||||
>
|
||||
<template v-slot:top-right>
|
||||
<q-input
|
||||
dense
|
||||
debounce="1000"
|
||||
v-model="filter.name"
|
||||
label="名称"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
<q-btn
|
||||
v-if="!isRole"
|
||||
color="primary"
|
||||
label="新建"
|
||||
@click="editFormShow = true"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-selection="scope">
|
||||
<q-checkbox v-model="scope.selected" />
|
||||
</template>
|
||||
|
||||
<template v-slot:body-selection="scope">
|
||||
<q-checkbox v-model="scope.selected" />
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-operations="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="编辑"
|
||||
@click="edieAuthData(props.row)"
|
||||
/>
|
||||
<q-btn
|
||||
color="red"
|
||||
:disable="operateDisabled"
|
||||
label="删除"
|
||||
@click="deleteAuthData(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
|
||||
<q-dialog
|
||||
v-model="editFormShow"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<q-form
|
||||
ref="myForm"
|
||||
@submit="edieAuthPath"
|
||||
@reset="onReset"
|
||||
class="q-gutter-md"
|
||||
>
|
||||
<div class="text-h6">{{ pathInfo.id ? '修改' : '新建' }}</div>
|
||||
<q-input outlined label="名称" v-model="pathInfo.name" />
|
||||
<q-input outlined label="接口" v-model="pathInfo.path" />
|
||||
<q-select
|
||||
outlined
|
||||
v-model="pathInfo.methodList"
|
||||
:options="options"
|
||||
multiple
|
||||
map-options
|
||||
emit-value
|
||||
label="方法"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请选择方法!']"
|
||||
></q-select>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="primary" label="保存" type="submit" />
|
||||
<q-btn label="取消" type="reset" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed, watch } from 'vue';
|
||||
import { useQuasar, type QTableColumn, QForm } from 'quasar';
|
||||
import {
|
||||
createPath,
|
||||
deletePath,
|
||||
pageQueryPath,
|
||||
PathItem,
|
||||
savePathData,
|
||||
} from '../api/AuthApi';
|
||||
import { successNotify } from '../utils/CommonNotify';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { MethodType } from 'src/components/AuthData';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const $q = useQuasar();
|
||||
|
||||
interface SelectItem {
|
||||
id: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
selects?: PathItem[];
|
||||
}>(),
|
||||
{ sizeHeight: 500, selects: () => [] }
|
||||
);
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
selected.value = props.selects;
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
|
||||
{
|
||||
name: 'name',
|
||||
label: '权限接口名称',
|
||||
field: 'name',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'path',
|
||||
label: '接口路径',
|
||||
field: 'path',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'method',
|
||||
label: '方法',
|
||||
field: (row) => {
|
||||
return getMethodName(row.method);
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
|
||||
];
|
||||
|
||||
const operateDisabled = ref(false);
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const filter = reactive({
|
||||
name: '',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
const filter = props.filter;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
let response = await pageQueryPath({
|
||||
name: filter.name,
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
});
|
||||
|
||||
pagination.value.rowsNumber = response.total;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
pagination.value.sortBy = sortBy;
|
||||
pagination.value.descending = descending;
|
||||
rows.splice(0, rows.length, ...(response.records as []));
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
const editFormShow = ref(false);
|
||||
|
||||
interface PathInfo extends Omit<PathItem, 'id' | 'method'> {
|
||||
id: string;
|
||||
methodList: MethodType[];
|
||||
}
|
||||
const pathInfo = reactive<PathInfo>({
|
||||
id: '',
|
||||
methodList: [],
|
||||
name: '',
|
||||
path: '',
|
||||
});
|
||||
|
||||
const options = computed(() => {
|
||||
const list: { label: string; value: string }[] = [];
|
||||
for (let item in MethodType) {
|
||||
const obj = {
|
||||
label: item,
|
||||
value: MethodType[item as MethodType],
|
||||
};
|
||||
list.push(obj);
|
||||
}
|
||||
return list;
|
||||
});
|
||||
|
||||
//编辑
|
||||
function edieAuthData(row: PathItem) {
|
||||
pathInfo.id = row.id + '';
|
||||
pathInfo.name = row.name;
|
||||
pathInfo.path = row.path;
|
||||
let list: MethodType[] = [];
|
||||
if (row.method == '*') {
|
||||
list = options.value.map((item) => item.value as MethodType);
|
||||
} else {
|
||||
list = row.method.split(',') as MethodType[];
|
||||
}
|
||||
pathInfo.methodList = list;
|
||||
editFormShow.value = true;
|
||||
}
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
|
||||
//提交编辑
|
||||
async function edieAuthPath() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
operateDisabled.value = true;
|
||||
try {
|
||||
let method = pathInfo.methodList.join(',');
|
||||
const everyM = options.value.every((item) => {
|
||||
return pathInfo.methodList.includes(item.value as MethodType);
|
||||
});
|
||||
if (everyM) {
|
||||
method = '*';
|
||||
}
|
||||
const params = {
|
||||
name: pathInfo.name,
|
||||
path: pathInfo.path,
|
||||
method: method,
|
||||
};
|
||||
if (pathInfo.id) {
|
||||
const cloneParams = Object.assign(params, { id: +pathInfo.id });
|
||||
await savePathData(cloneParams);
|
||||
} else {
|
||||
await createPath(params);
|
||||
}
|
||||
onReset();
|
||||
tableRef.value.requestServerInteraction(); // 刷新列表
|
||||
editFormShow.value = false;
|
||||
successNotify('保存成功!');
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
operateDisabled.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteAuthData(row: PathItem) {
|
||||
operateDisabled.value = true;
|
||||
$q.dialog({
|
||||
title: '确认',
|
||||
message: `确认删除权限接口 "${row.name}" 吗?`,
|
||||
cancel: true,
|
||||
})
|
||||
.onOk(async () => {
|
||||
try {
|
||||
await deletePath(row.id);
|
||||
tableRef.value.requestServerInteraction(); // 刷新列表
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
}
|
||||
})
|
||||
.onDismiss(() => {
|
||||
operateDisabled.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
pathInfo.id = '';
|
||||
pathInfo.name = '';
|
||||
pathInfo.methodList = [];
|
||||
pathInfo.path = '';
|
||||
myForm.value?.resetValidation();
|
||||
}
|
||||
|
||||
function getMethodName(val: string) {
|
||||
let name = val;
|
||||
if (val == '*') {
|
||||
const list = options.value.map((item) => item.value);
|
||||
name = list.join(',');
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
const route = useRoute();
|
||||
const isRole = computed(() => {
|
||||
// 角色管理
|
||||
return route.path.includes('/sysManage/role');
|
||||
});
|
||||
const selected = ref<SelectItem[]>([]);
|
||||
function getSelectedString() {
|
||||
const nameArr = selected.value.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
const name = nameArr.join(',');
|
||||
return `已选ID:${name}`;
|
||||
}
|
||||
if (isRole.value) {
|
||||
const index = columnDefs.findIndex((item) => {
|
||||
return item.name == 'operations';
|
||||
});
|
||||
if (index >= 0) {
|
||||
columnDefs.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const emit = defineEmits(['selectsed']);
|
||||
function tableSelected() {
|
||||
emit('selectsed', selected.value);
|
||||
}
|
||||
watch(
|
||||
() => props.selects,
|
||||
(val) => {
|
||||
selected.value = val.map((item) => {
|
||||
return { id: item.id };
|
||||
});
|
||||
}
|
||||
);
|
||||
</script>
|
@ -27,13 +27,48 @@
|
||||
</q-td>
|
||||
</template>
|
||||
<template v-slot:top-right>
|
||||
<q-btn
|
||||
class="q-mr-md"
|
||||
color="primary"
|
||||
label="查询"
|
||||
@click="openSearchDialog"
|
||||
<q-form ref="myForm" @submit="searchDecisionInfo" style="width: 100%">
|
||||
<div class="q-gutter-md q-mt-none row justify-center items-start">
|
||||
<q-select
|
||||
dense
|
||||
v-model="filter.lineId"
|
||||
:options="searchOptionsLineId"
|
||||
emit-value
|
||||
map-options
|
||||
options-dense
|
||||
label="线路ID"
|
||||
style="width: 75px"
|
||||
no-error-icon
|
||||
lazy-rules
|
||||
:rules="[(val) => val >= 0 || '请选择线路ID!']"
|
||||
/>
|
||||
<q-btn color="primary" label="新建" @click="createFormShow = true" />
|
||||
<q-select
|
||||
dense
|
||||
label="线路类型"
|
||||
v-model="filter.lineType"
|
||||
:options="searchOptionsLineType"
|
||||
style="width: 100px"
|
||||
/>
|
||||
<q-select
|
||||
dense
|
||||
label="故障类型"
|
||||
v-model="filter.alertType"
|
||||
:options="searchOptionsAlertType"
|
||||
style="width: 130px"
|
||||
/>
|
||||
<q-input
|
||||
dense
|
||||
v-model="filter.areaConfigName"
|
||||
label="区域名称"
|
||||
></q-input>
|
||||
<q-btn color="primary" label="查询" type="submit" />
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="新建"
|
||||
@click="createFormShow = true"
|
||||
/>
|
||||
</div>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-operations="props">
|
||||
@ -73,6 +108,23 @@
|
||||
<div class="text-h6">
|
||||
{{ creatForm.id ? '编辑决策信息' : '新建决策信息' }}
|
||||
</div>
|
||||
<q-select
|
||||
outlined
|
||||
label="线路ID"
|
||||
v-model="creatForm.lineId"
|
||||
:options="optionsLineId"
|
||||
emit-value
|
||||
map-options
|
||||
options-dense
|
||||
lazy-rules
|
||||
:rules="[(val) => val > 0 || '请选择线路ID!']"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
label="线路类型"
|
||||
v-model="creatForm.lineType"
|
||||
:options="optionsLineType"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
label="故障类型"
|
||||
@ -111,44 +163,12 @@
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="primary" label="创建" type="submit" />
|
||||
<q-btn color="primary" label="确定" type="submit" />
|
||||
<q-btn label="取消" type="reset" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog
|
||||
v-model="searchDialog"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<div class="text-h6">查询决策信息</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
outlined
|
||||
label="故障类型"
|
||||
v-model="filter.alertType"
|
||||
:options="optionsAlertType"
|
||||
class="q-mb-md"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="filter.areaConfigName"
|
||||
label="区域名称"
|
||||
></q-input>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="primary" label="确定" @click="searchDecisionInfo()" />
|
||||
<q-btn label="取消" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -169,6 +189,7 @@ import {
|
||||
} from 'src/components/alarm/alarmInfoEnum';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { ShowTipTimeConfig, TipTimeConfig } from 'src/api/AlarmTipTimeConfig';
|
||||
import { pageQuery } from 'src/api/LineInfoApi';
|
||||
|
||||
const $q = useQuasar();
|
||||
|
||||
@ -191,6 +212,20 @@ const columnDefs: QTableColumn[] = [
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'lineId',
|
||||
label: '线路',
|
||||
field: 'lineId',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'lineType',
|
||||
label: '线路类型',
|
||||
field: 'lineType',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'alertType',
|
||||
label: '故障类型',
|
||||
@ -255,16 +290,42 @@ const pagination = ref({
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
const filter = ref({
|
||||
alertType: '全部',
|
||||
areaConfigName: '',
|
||||
lineId: 0,
|
||||
lineType: '全部',
|
||||
});
|
||||
|
||||
const onRequest: QTable['onRequest'] = async (props) => {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
loading.value = true;
|
||||
try {
|
||||
let response = await alarmInfoPageQuery({
|
||||
const params = {
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
};
|
||||
if (filter.value.lineId !== 0) {
|
||||
Object.assign(params, {
|
||||
lineId: filter.value.lineId,
|
||||
});
|
||||
}
|
||||
if (filter.value.lineType !== '全部') {
|
||||
Object.assign(params, {
|
||||
lineType: filter.value.lineType,
|
||||
});
|
||||
}
|
||||
if (filter.value.alertType !== '全部') {
|
||||
Object.assign(params, {
|
||||
alertType: (saveAlertTypeData as never)[filter.value.alertType],
|
||||
});
|
||||
}
|
||||
if (filter.value.areaConfigName) {
|
||||
Object.assign(params, {
|
||||
areaConfigName: filter.value.areaConfigName,
|
||||
});
|
||||
}
|
||||
let response = await alarmInfoPageQuery(params);
|
||||
const pageData = response;
|
||||
pagination.value.rowsNumber = pageData.total;
|
||||
pagination.value.page = page;
|
||||
@ -283,22 +344,13 @@ const onRequest: QTable['onRequest'] = async (props) => {
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
queryLineInfo();
|
||||
setTimeout(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
});
|
||||
});
|
||||
|
||||
const searchDialog = ref(false);
|
||||
const filter = ref({
|
||||
alertType: '',
|
||||
areaConfigName: '',
|
||||
});
|
||||
function openSearchDialog() {
|
||||
filter.value = { alertType: '', areaConfigName: '' };
|
||||
searchDialog.value = true;
|
||||
}
|
||||
function searchDecisionInfo() {
|
||||
searchDialog.value = false;
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
|
||||
@ -306,6 +358,8 @@ const createFormShow = ref(false);
|
||||
const myForm = ref<QForm | null>(null);
|
||||
const creatForm = reactive({
|
||||
id: '',
|
||||
lineId: '',
|
||||
lineType: 'NCC',
|
||||
alertType: '',
|
||||
tipTimeIds: [],
|
||||
areaConfigId: '',
|
||||
@ -313,6 +367,30 @@ const creatForm = reactive({
|
||||
submissionInfo: '',
|
||||
});
|
||||
|
||||
const optionsLineId = ref<{ label: string; value: number }[]>([]);
|
||||
const searchOptionsLineId = ref<{ label: string; value: number }[]>([
|
||||
{ label: '全部', value: 0 },
|
||||
]);
|
||||
async function queryLineInfo() {
|
||||
try {
|
||||
let response = await pageQuery({
|
||||
current: 1,
|
||||
size: 50,
|
||||
});
|
||||
response.records.forEach((info) => {
|
||||
optionsLineId.value.push({ label: info.name, value: info.lineId });
|
||||
searchOptionsLineId.value.push({ label: info.name, value: info.lineId });
|
||||
});
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
const optionsLineType = ['NCC', 'OCC'];
|
||||
const searchOptionsLineType = ['全部', ...optionsLineType];
|
||||
const optionsAlertType = [
|
||||
'蓝显',
|
||||
'全线蓝显',
|
||||
@ -333,13 +411,24 @@ const optionsAlertType = [
|
||||
'联锁区红光带',
|
||||
'联锁区橙光带',
|
||||
'联锁区失表',
|
||||
'应急触发',
|
||||
'道岔挤岔',
|
||||
'zc联锁故障',
|
||||
'列车定位丢失',
|
||||
'列车完整性',
|
||||
'列车故障救援',
|
||||
'ats卡滞',
|
||||
];
|
||||
const searchOptionsAlertType = ['全部', ...optionsAlertType];
|
||||
let optionsLocationType = ref<string[]>([]);
|
||||
let optionsLocationList: AreaConfigItem[] = [];
|
||||
async function searchLocationType() {
|
||||
try {
|
||||
const alertType = (saveAlertTypeData as never)[creatForm.alertType];
|
||||
optionsLocationList = await getDeviceAreaByAlarmType(3, alertType);
|
||||
optionsLocationList = await getDeviceAreaByAlarmType(
|
||||
+creatForm.lineId,
|
||||
alertType
|
||||
);
|
||||
optionsLocationType.value = optionsLocationList.map(
|
||||
(item) => item.areaName
|
||||
);
|
||||
@ -372,6 +461,8 @@ function onCreate() {
|
||||
});
|
||||
const params = {
|
||||
id: +creatForm.id,
|
||||
lineId: +creatForm.lineId,
|
||||
lineType: creatForm.lineType,
|
||||
alertType: (saveAlertTypeData as never)[creatForm.alertType],
|
||||
tipTimeIds: tipTimeIds,
|
||||
areaConfigId: areaConfigId as number,
|
||||
@ -403,6 +494,8 @@ function onCreate() {
|
||||
|
||||
function editData(row: AlarmInfoListItem) {
|
||||
creatForm.id = row.id + '';
|
||||
creatForm.lineId = row.lineId + '';
|
||||
creatForm.lineType = row.lineType;
|
||||
creatForm.alertType = (showAlertTypeData as never)[row.alertType + ''];
|
||||
creatForm.tipTimeIds = row.timeConfigList?.map(
|
||||
(timeConfig) => (ShowTipTimeConfig as never)[timeConfig.timeType + '']
|
||||
@ -440,6 +533,8 @@ async function deleteData(row: AlarmInfoListItem) {
|
||||
|
||||
function onReset() {
|
||||
creatForm.id = '';
|
||||
creatForm.lineId = '';
|
||||
creatForm.lineType = 'NCC';
|
||||
creatForm.alertType = '';
|
||||
creatForm.tipTimeIds = [];
|
||||
creatForm.areaConfigId = '';
|
||||
|
@ -21,7 +21,7 @@
|
||||
v-model="filter.name"
|
||||
label="名称"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
|
||||
<q-btn color="primary" label="新建" @click="createFormShow = true" />
|
||||
</template>
|
||||
|
||||
@ -362,4 +362,7 @@ async function deleteData(row: any) {
|
||||
operateDisabled.value = false;
|
||||
});
|
||||
}
|
||||
function searchQuery() {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
</script>
|
||||
|
533
src/pages/EmergencyResponseManage.vue
Normal file
533
src/pages/EmergencyResponseManage.vue
Normal file
@ -0,0 +1,533 @@
|
||||
<template>
|
||||
<q-tabs
|
||||
v-model="tab"
|
||||
dense
|
||||
active-color="primary"
|
||||
indicator-color="primary"
|
||||
align="justify"
|
||||
narrow-indicator
|
||||
>
|
||||
<q-tab
|
||||
v-for="(item, index) in tabList"
|
||||
:key="index"
|
||||
:name="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</q-tabs>
|
||||
<q-separator />
|
||||
<q-tab-panel name="info">
|
||||
<div class="occContainer" v-if="roleType == 'OCC'">
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:loading="loading"
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
@request="onRequest"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:filter="filter"
|
||||
class="left"
|
||||
>
|
||||
<template v-slot:top-right>
|
||||
<q-form ref="myForm" style="width: 100%">
|
||||
<div class="q-gutter-md q-mt-none row justify-center items-start">
|
||||
<q-select
|
||||
dense
|
||||
label="故障类型"
|
||||
v-model="filter.faultType"
|
||||
emit-value
|
||||
map-options
|
||||
:options="searchOptionsFaultType"
|
||||
style="min-width: 130px"
|
||||
/>
|
||||
<q-input
|
||||
dense
|
||||
:label="inputSearchName"
|
||||
v-model="filter.faultName"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
color="primary"
|
||||
icon="search"
|
||||
@click="searchTable"
|
||||
/>
|
||||
</div>
|
||||
</q-form>
|
||||
</template>
|
||||
<template v-slot:body="props">
|
||||
<q-tr
|
||||
:props="props"
|
||||
:class="{ changeBackground: props.row.id === clickRowInfo.id }"
|
||||
@click="handleRowClick(props.row)"
|
||||
>
|
||||
<q-td
|
||||
v-for="col in props.cols"
|
||||
:key="col.name"
|
||||
:props="props"
|
||||
class="custom-column"
|
||||
@mouseover="onMouseOver"
|
||||
@mouseleave="showTooltip = false"
|
||||
>
|
||||
{{ col.value }}
|
||||
<q-tooltip v-if="showTooltip" anchor="bottom middle">
|
||||
<div class="message-tip">
|
||||
{{ col.value }}
|
||||
</div>
|
||||
</q-tooltip>
|
||||
</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
|
||||
<q-scroll-area class="right">
|
||||
<div class="detaiRow">
|
||||
<div class="text">
|
||||
<span class="textHead">故障类型</span> :{{
|
||||
clickRowInfo.faultType
|
||||
}}
|
||||
</div>
|
||||
<div class="text">
|
||||
<span class="textHead"> {{ showTitle.faultNameShower }}</span
|
||||
>:{{ clickRowInfo.faultNameShower }}
|
||||
</div>
|
||||
<q-card class="box-card">
|
||||
<div class="head">{{ showTitle.faultDriverShower }}</div>
|
||||
<q-separator />
|
||||
<div>
|
||||
<div class="detail">{{ clickRowInfo.faultDriverShower }}</div>
|
||||
</div>
|
||||
</q-card>
|
||||
<q-card class="box-card">
|
||||
<div class="head">{{ showTitle.resultMsg }}</div>
|
||||
<q-separator />
|
||||
<div>
|
||||
<div class="detail">{{ clickRowInfo.resultMsg }}</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</q-scroll-area>
|
||||
</div>
|
||||
<div v-else class="nccContainer">
|
||||
<q-btn-toggle
|
||||
v-model="selectMenuName"
|
||||
toggle-color="primary"
|
||||
:options="menuOption"
|
||||
@update:model-value="selectedMenu"
|
||||
class="q-btn-toggle"
|
||||
/>
|
||||
<q-card
|
||||
class="box-card"
|
||||
v-for="nccData in showNccData"
|
||||
:key="nccData.action"
|
||||
>
|
||||
<div class="head">{{ nccData.action }}</div>
|
||||
<q-separator />
|
||||
<div class="detail">
|
||||
<div v-for="data in nccData.datas" :key="data">{{ data }}</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</q-tab-panel>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, computed, onMounted, watch } from 'vue';
|
||||
import { QTable, useQuasar } from 'quasar';
|
||||
import {
|
||||
FaultQueryListItem,
|
||||
faultQueryPageQuery,
|
||||
faultQueryType,
|
||||
FaultTypeItem,
|
||||
NccFaultQueryListItem,
|
||||
nccFaultQueryPageQuery,
|
||||
} from 'src/api/faultQuery';
|
||||
import { getMonitorPath } from 'src/router/routes';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
sizeWidth: number;
|
||||
}>(),
|
||||
{ sizeHeight: 500, sizeWidth: 500 }
|
||||
);
|
||||
|
||||
const $q = useQuasar();
|
||||
const tab = ref('GUIDE');
|
||||
const tableTitle = reactive({
|
||||
faultNameShower: '故障现象',
|
||||
faultDriverShower: '司机处理结果',
|
||||
});
|
||||
const inputSearchName = ref('故障现象');
|
||||
watch(tab, (tabVal) => {
|
||||
if (tabVal == 'GUIDE') {
|
||||
inputSearchName.value = '故障现象';
|
||||
tableTitle.faultNameShower = '故障现象';
|
||||
tableTitle.faultDriverShower = '司机处理结果';
|
||||
} else {
|
||||
inputSearchName.value = '故障名称';
|
||||
tableTitle.faultNameShower = '故障名称';
|
||||
tableTitle.faultDriverShower = '故障现象';
|
||||
}
|
||||
handleSelectFaultType();
|
||||
});
|
||||
const tabList = ref();
|
||||
|
||||
const tableRef = ref<QTable>();
|
||||
const columns = computed(() => [
|
||||
{
|
||||
name: 'id',
|
||||
label: '编号',
|
||||
field: 'id',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'lineId',
|
||||
label: '线路',
|
||||
field: 'lineId',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faultType',
|
||||
label: '故障类型',
|
||||
field: (row: FaultQueryListItem) => {
|
||||
if (row.faultType) {
|
||||
return getFaultTypeName(row);
|
||||
}
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faultNameShower',
|
||||
label: tableTitle.faultNameShower,
|
||||
field: 'faultNameShower',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faultDriverShower',
|
||||
label: tableTitle.faultDriverShower,
|
||||
field: 'faultDriverShower',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
]);
|
||||
const rows = reactive([]);
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
const filter = reactive({
|
||||
lineId: 0,
|
||||
faultType: '',
|
||||
faultName: '',
|
||||
});
|
||||
|
||||
const onRequest: QTable['onRequest'] = async (props) => {
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
loading.value = true;
|
||||
try {
|
||||
const params = {
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
};
|
||||
if (filter.lineId !== 0) {
|
||||
Object.assign(params, {
|
||||
lineId: filter.lineId,
|
||||
});
|
||||
}
|
||||
if (filter.faultType !== '') {
|
||||
Object.assign(params, {
|
||||
faultType: filter.faultType,
|
||||
});
|
||||
}
|
||||
if (filter.faultName !== '') {
|
||||
Object.assign(params, {
|
||||
faultName: filter.faultName,
|
||||
});
|
||||
}
|
||||
let resp = await faultQueryPageQuery(params);
|
||||
pagination.value.page = resp.current;
|
||||
pagination.value.rowsNumber = resp.total;
|
||||
pagination.value.rowsPerPage = resp.size;
|
||||
rows.splice(0, rows.length, ...(resp.records as []));
|
||||
if (rows.length) {
|
||||
handleRowClick(rows[0]);
|
||||
} else {
|
||||
clickRowInfo.faultType = '';
|
||||
clickRowInfo.faultNameShower = '';
|
||||
clickRowInfo.faultDriverShower = '';
|
||||
clickRowInfo.resultMsg = '';
|
||||
}
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取范围列表',
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const clickRowInfo = reactive({
|
||||
id: 0,
|
||||
faultType: '',
|
||||
faultNameShower: '',
|
||||
faultDriverShower: '',
|
||||
resultMsg: '',
|
||||
});
|
||||
const showTitle = reactive({
|
||||
faultNameShower: '',
|
||||
faultDriverShower: '',
|
||||
resultMsg: '',
|
||||
});
|
||||
function handleRowClick(row: FaultQueryListItem) {
|
||||
if (row.faultType.includes('FAULT_EMERGENCY_GUIDE')) {
|
||||
showTitle.faultNameShower = '故障现象';
|
||||
showTitle.faultDriverShower = '司机处理结果';
|
||||
showTitle.resultMsg = '行调提醒司机关键点';
|
||||
} else {
|
||||
showTitle.faultNameShower = '故障名称';
|
||||
showTitle.faultDriverShower = '故障现象';
|
||||
showTitle.resultMsg = '退出服务地点';
|
||||
}
|
||||
clickRowInfo.id = row?.id as number;
|
||||
clickRowInfo.faultType = getFaultTypeName(row) as string;
|
||||
clickRowInfo.faultNameShower = row.faultNameShower;
|
||||
clickRowInfo.faultDriverShower = row.faultDriverShower;
|
||||
clickRowInfo.resultMsg = row.resultMsg;
|
||||
}
|
||||
|
||||
async function queryAllFaultType() {
|
||||
try {
|
||||
allOptionsFaultType = await faultQueryType();
|
||||
handleSelectFaultType();
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取指定线路的故障类型配置',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let allOptionsFaultType: FaultTypeItem[] = [];
|
||||
function getFaultTypeName(row: FaultQueryListItem) {
|
||||
for (let i = 0; i < allOptionsFaultType.length; i++) {
|
||||
if (allOptionsFaultType[i].lineId == row.lineId) {
|
||||
const fts = allOptionsFaultType[i].fts;
|
||||
for (let j = 0; i < fts.length; j++) {
|
||||
if (fts[j].faultType == row.faultType) {
|
||||
return fts[j].typeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const searchOptionsFaultType = ref([{ label: '全部', value: '' }]);
|
||||
function handleSelectFaultType() {
|
||||
let allType = '';
|
||||
searchOptionsFaultType.value = [{ label: '全部', value: '' }];
|
||||
for (let i = 0; i < allOptionsFaultType.length; i++) {
|
||||
if (allOptionsFaultType[i].lineId == filter.lineId) {
|
||||
allOptionsFaultType[i].fts.forEach((item) => {
|
||||
if (
|
||||
(tab.value == 'GUIDE' &&
|
||||
item.faultType.includes('FAULT_EMERGENCY_GUIDE')) ||
|
||||
(tab.value == 'SERVICE' &&
|
||||
item.faultType.includes('FAULT_EXIT_SERVICE'))
|
||||
) {
|
||||
searchOptionsFaultType.value.push({
|
||||
label: item.typeName,
|
||||
value: item.faultType,
|
||||
});
|
||||
if (allType == '') {
|
||||
allType = item.faultType;
|
||||
} else {
|
||||
allType = allType + ',' + item.faultType;
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
filter.faultType = allType;
|
||||
searchOptionsFaultType.value[0].value = allType;
|
||||
}
|
||||
|
||||
function searchTable() {
|
||||
tableRef.value?.requestServerInteraction();
|
||||
}
|
||||
|
||||
//ncc相关
|
||||
const nccDatas = ref<NccFaultQueryListItem[]>();
|
||||
const selectMenuName = ref('');
|
||||
const menuOption = ref<
|
||||
{
|
||||
label: string;
|
||||
value: string;
|
||||
}[]
|
||||
>([]);
|
||||
const showNccData = ref<{ action: string; datas: string[] }[]>();
|
||||
|
||||
function selectedMenu(name: string) {
|
||||
showNccData.value = nccDatas.value?.find(
|
||||
(nccData) => nccData.nccTypeName == name
|
||||
)?.nccData;
|
||||
}
|
||||
|
||||
async function nccFaultQueryPageQueryFn() {
|
||||
try {
|
||||
nccDatas.value = await nccFaultQueryPageQuery();
|
||||
nccDatas.value.forEach((nccDta) =>
|
||||
menuOption.value.push({
|
||||
label: nccDta.nccTypeName,
|
||||
value: nccDta.nccTypeName,
|
||||
})
|
||||
);
|
||||
selectMenuName.value = nccDatas.value[0].nccTypeName;
|
||||
showNccData.value = nccDatas.value[0].nccData;
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取ncc故障查询',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const showTooltip = ref(false);
|
||||
function onMouseOver(e: MouseEvent) {
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.scrollWidth > target.clientWidth) {
|
||||
showTooltip.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
const userStore = useUserStore();
|
||||
const roleType = ref('');
|
||||
onMounted(() => {
|
||||
const config = getMonitorPath(userStore.roles);
|
||||
if (config.lineType == 'NCC') {
|
||||
roleType.value = 'NCC';
|
||||
tabList.value = [
|
||||
{
|
||||
label: 'ncc应急处置流程',
|
||||
value: 'NCC',
|
||||
},
|
||||
];
|
||||
tab.value = 'NCC';
|
||||
nccFaultQueryPageQueryFn();
|
||||
} else {
|
||||
roleType.value = 'OCC';
|
||||
tabList.value = [
|
||||
{
|
||||
label: '故障指导',
|
||||
value: 'GUIDE',
|
||||
},
|
||||
{
|
||||
label: '退出服务',
|
||||
value: 'SERVICE',
|
||||
},
|
||||
];
|
||||
filter.lineId = config.lineIds[0];
|
||||
queryAllFaultType();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.changeBackground {
|
||||
background-color: #31ccec;
|
||||
}
|
||||
.custom-column {
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.message-tip {
|
||||
width: 300px;
|
||||
overflow: auto;
|
||||
line-height: 22px;
|
||||
white-space: pre-wrap;
|
||||
font-size: 14px;
|
||||
}
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.occContainer {
|
||||
display: flex;
|
||||
height: calc(100vh - 120px);
|
||||
.left {
|
||||
width: 67%;
|
||||
}
|
||||
.right {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
.detaiRow {
|
||||
margin: 10px 0 0 20px;
|
||||
.text {
|
||||
width: 450px;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 10px;
|
||||
font-size: 18px;
|
||||
.textHead {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.box-card {
|
||||
width: 98%;
|
||||
height: calc(50vh - 115px);
|
||||
margin-bottom: 10px;
|
||||
padding: 0 5px;
|
||||
.head {
|
||||
padding: 5px 5px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.detail {
|
||||
margin-bottom: 10px;
|
||||
padding: 5px 5px;
|
||||
line-height: 28px;
|
||||
white-space: pre-wrap;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.nccContainer {
|
||||
.q-btn-toggle {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.box-card {
|
||||
width: 98%;
|
||||
min-height: 150px;
|
||||
margin-bottom: 15px;
|
||||
padding: 0 5px;
|
||||
.head {
|
||||
padding: 5px 5px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.detail {
|
||||
margin-bottom: 10px;
|
||||
padding: 5px 5px;
|
||||
line-height: 28px;
|
||||
white-space: pre-wrap;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
501
src/pages/FaultQueryManage.vue
Normal file
501
src/pages/FaultQueryManage.vue
Normal file
@ -0,0 +1,501 @@
|
||||
<template>
|
||||
<div class="q-pa-md">
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
title="故障查询"
|
||||
:style="{ height: tableHeight + 'px' }"
|
||||
:rows="rows"
|
||||
:columns="columnDefs"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:loading="loading"
|
||||
binary-state-sort
|
||||
@request="onRequest"
|
||||
>
|
||||
<template v-slot:body-cell="props">
|
||||
<q-td :props="props" class="custom-column">
|
||||
{{ props.value }}
|
||||
<q-tooltip
|
||||
anchor="bottom middle"
|
||||
v-if="props.value && props.value.length > 20"
|
||||
>
|
||||
<div class="message-tip">
|
||||
{{ props.value }}
|
||||
</div>
|
||||
</q-tooltip>
|
||||
</q-td>
|
||||
</template>
|
||||
<template v-slot:top-right>
|
||||
<q-form ref="myForm" @submit="searchDecisionInfo" style="width: 100%">
|
||||
<div class="q-gutter-md q-mt-none row justify-center items-start">
|
||||
<q-select
|
||||
dense
|
||||
v-model="filter.lineId"
|
||||
:options="searchOptionsLineId"
|
||||
emit-value
|
||||
map-options
|
||||
options-dense
|
||||
label="线路ID"
|
||||
style="width: 75px"
|
||||
no-error-icon
|
||||
lazy-rules
|
||||
@update:model-value="handleSelectSearchLineId"
|
||||
:rules="[(val) => val >= 0 || '请选择线路ID!']"
|
||||
/>
|
||||
<q-select
|
||||
dense
|
||||
label="故障类型"
|
||||
v-model="filter.faultType"
|
||||
emit-value
|
||||
map-options
|
||||
:options="searchOptionsFaultType"
|
||||
style="min-width: 130px"
|
||||
/>
|
||||
<q-btn color="primary" label="查询" type="submit" />
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="新建"
|
||||
@click="createFormShow = true"
|
||||
/>
|
||||
</div>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-operations="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
color="primary"
|
||||
:disable="operateDisabled"
|
||||
label="编辑"
|
||||
@click="editData(props.row)"
|
||||
/>
|
||||
<q-btn
|
||||
color="red"
|
||||
:disable="operateDisabled"
|
||||
label="删除"
|
||||
@click="deleteData(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
|
||||
<q-dialog
|
||||
v-model="createFormShow"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-card style="width: 500px">
|
||||
<q-form
|
||||
ref="myForm"
|
||||
@submit="onCreate"
|
||||
@reset="onReset"
|
||||
class="q-gutter-md"
|
||||
>
|
||||
<q-card-section class="q-gutter-sm">
|
||||
<div class="text-h6">
|
||||
{{ creatForm.id ? '编辑故障查询' : '新建故障查询' }}
|
||||
</div>
|
||||
<q-select
|
||||
outlined
|
||||
label="线路ID"
|
||||
v-model="creatForm.lineId"
|
||||
:options="optionsLineId"
|
||||
emit-value
|
||||
map-options
|
||||
lazy-rules
|
||||
@update:model-value="handleSelectLineId"
|
||||
:rules="[(val) => val > 0 || '请选择线路ID!']"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
label="故障类型"
|
||||
v-model="creatForm.faultType"
|
||||
:options="optionsFaultType"
|
||||
emit-value
|
||||
map-options
|
||||
:rules="[(val) => val.length > 0 || '请选择故障类型!']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="消息名称(故障现象)"
|
||||
v-model="creatForm.faultNameShower"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请输入消息名称!']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
type="textarea"
|
||||
label="司机处理结果(服务故障现象)"
|
||||
v-model="creatForm.faultDriverShower"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请输入司机处理结果!']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
type="textarea"
|
||||
label="司机关键点(退出服务地点)"
|
||||
v-model="creatForm.resultMsg"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请输入司机关键点!']"
|
||||
/>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="primary" label="确定" type="submit" />
|
||||
<q-btn label="取消" type="reset" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { useQuasar, type QTableColumn, QForm, QTable } from 'quasar';
|
||||
import {
|
||||
faultQueryPageQuery,
|
||||
deleteFaultQueryById,
|
||||
createFaultQuery,
|
||||
FaultQueryListItem,
|
||||
faultQueryType,
|
||||
FaultTypeItem,
|
||||
} from '../api/faultQuery';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { pageQuery } from 'src/api/LineInfoApi';
|
||||
|
||||
const $q = useQuasar();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
}>(),
|
||||
{ sizeHeight: 500 }
|
||||
);
|
||||
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{
|
||||
name: 'id',
|
||||
label: '编号',
|
||||
field: 'id',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'lineId',
|
||||
label: '线路',
|
||||
field: 'lineId',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faultType',
|
||||
label: '故障类型',
|
||||
field: (row) => {
|
||||
if (row.faultType) {
|
||||
return getFaultTypeName(row);
|
||||
}
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faultNameShower',
|
||||
label: '消息名称(故障现象)',
|
||||
field: 'faultNameShower',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faultDriverShower',
|
||||
label: '司机处理结果(服务故障现象)',
|
||||
field: 'faultDriverShower',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'resultMsg',
|
||||
label: '司机关键点(退出服务地点)',
|
||||
field: 'resultMsg',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
|
||||
];
|
||||
|
||||
const operateDisabled = ref(false);
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
const filter = ref({
|
||||
faultType: '',
|
||||
lineId: 0,
|
||||
});
|
||||
|
||||
const onRequest: QTable['onRequest'] = async (props) => {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
loading.value = true;
|
||||
try {
|
||||
const params = {
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
};
|
||||
if (filter.value.lineId !== 0) {
|
||||
Object.assign(params, {
|
||||
lineId: filter.value.lineId,
|
||||
});
|
||||
}
|
||||
if (filter.value.faultType!=='') {
|
||||
Object.assign(params, {
|
||||
faultType: filter.value.faultType,
|
||||
});
|
||||
}
|
||||
let response = await faultQueryPageQuery(params);
|
||||
const pageData = response;
|
||||
pagination.value.rowsNumber = pageData.total;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
pagination.value.sortBy = sortBy;
|
||||
pagination.value.descending = descending;
|
||||
rows.splice(0, rows.length, ...(pageData.records as []));
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取故障查询列表',
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
queryLineInfo();
|
||||
queryAllFaultType();
|
||||
setTimeout(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
});
|
||||
});
|
||||
|
||||
function searchDecisionInfo() {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
|
||||
const createFormShow = ref(false);
|
||||
const myForm = ref<QForm | null>(null);
|
||||
const creatForm = reactive({
|
||||
id: '',
|
||||
lineId: '',
|
||||
faultType: '',
|
||||
faultNameShower: '',
|
||||
faultDriverShower: '',
|
||||
resultMsg: '',
|
||||
});
|
||||
|
||||
const optionsLineId = ref<{ label: string; value: number }[]>([]);
|
||||
const searchOptionsLineId = ref<{ label: string; value: number }[]>([
|
||||
{ label: '全部', value: 0 },
|
||||
]);
|
||||
async function queryLineInfo() {
|
||||
try {
|
||||
let response = await pageQuery({
|
||||
current: 1,
|
||||
size: 50,
|
||||
});
|
||||
response.records.forEach((info) => {
|
||||
optionsLineId.value.push({ label: info.name, value: info.lineId });
|
||||
searchOptionsLineId.value.push({ label: info.name, value: info.lineId });
|
||||
});
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let allOptionsFaultType: FaultTypeItem[] = [];
|
||||
let optionsFaultType = ref<{ label: string; value: string }[]>([]);
|
||||
async function queryAllFaultType() {
|
||||
try {
|
||||
allOptionsFaultType = await faultQueryType();
|
||||
handleSelectAllFaultType();
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取指定线路的故障类型配置',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getFaultTypeName(row: FaultQueryListItem) {
|
||||
for (let i = 0; i < allOptionsFaultType.length; i++) {
|
||||
if (allOptionsFaultType[i].lineId == row.lineId) {
|
||||
const fts = allOptionsFaultType[i].fts;
|
||||
for (let j = 0; i < fts.length; j++) {
|
||||
if (fts[j].faultType == row.faultType) {
|
||||
return fts[j].typeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleSelectLineId() {
|
||||
optionsFaultType.value = [];
|
||||
creatForm.faultType = '';
|
||||
for (let i = 0; i < allOptionsFaultType.length; i++) {
|
||||
if (allOptionsFaultType[i].lineId == +creatForm.lineId) {
|
||||
allOptionsFaultType[i].fts.forEach((item) => {
|
||||
optionsFaultType.value.push({
|
||||
label: item.typeName,
|
||||
value: item.faultType,
|
||||
});
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const searchOptionsFaultType = ref<{ label: string; value: string }[]>([
|
||||
{ label: '全部', value: '' },
|
||||
]);
|
||||
function handleSelectSearchLineId() {
|
||||
filter.value.faultType = '';
|
||||
searchOptionsFaultType.value = [{ label: '全部', value: '' }];
|
||||
if (filter.value.lineId == 0) {
|
||||
handleSelectAllFaultType();
|
||||
}
|
||||
for (let i = 0; i < allOptionsFaultType.length; i++) {
|
||||
if (allOptionsFaultType[i].lineId == filter.value.lineId) {
|
||||
allOptionsFaultType[i].fts.forEach((item) => {
|
||||
searchOptionsFaultType.value.push({
|
||||
label: item.typeName,
|
||||
value: item.faultType,
|
||||
});
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleSelectAllFaultType() {
|
||||
allOptionsFaultType.forEach((faultTypeOption) => {
|
||||
faultTypeOption.fts.forEach((fault) =>
|
||||
searchOptionsFaultType.value.push({
|
||||
label: fault.typeName,
|
||||
value: fault.faultType,
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
operateDisabled.value = true;
|
||||
try {
|
||||
const params = {
|
||||
lineId: +creatForm.lineId,
|
||||
faultType: creatForm.faultType,
|
||||
faultNameShower: creatForm.faultNameShower,
|
||||
faultDriverShower: creatForm.faultDriverShower,
|
||||
resultMsg: creatForm.resultMsg,
|
||||
};
|
||||
if (creatForm.id !== '') {
|
||||
Object.assign(params, {
|
||||
id: +creatForm.id,
|
||||
});
|
||||
}
|
||||
await createFaultQuery(params);
|
||||
onReset();
|
||||
createFormShow.value = false;
|
||||
tableRef.value.requestServerInteraction(); // 刷新列表
|
||||
} catch (err) {
|
||||
const apiErr = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: apiErr.title,
|
||||
});
|
||||
} finally {
|
||||
operateDisabled.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function editData(row: FaultQueryListItem) {
|
||||
creatForm.id = row.id + '';
|
||||
creatForm.lineId = row.lineId + '';
|
||||
creatForm.faultType = row.faultType;
|
||||
creatForm.faultNameShower = row.faultNameShower;
|
||||
creatForm.faultDriverShower = row.faultDriverShower;
|
||||
creatForm.resultMsg = row.resultMsg;
|
||||
createFormShow.value = true;
|
||||
}
|
||||
|
||||
async function deleteData(row: FaultQueryListItem) {
|
||||
operateDisabled.value = true;
|
||||
$q.dialog({
|
||||
title: '确认',
|
||||
message: `确认删除编号是"${row.id}"的决策信息吗?`,
|
||||
cancel: true,
|
||||
})
|
||||
.onOk(async () => {
|
||||
try {
|
||||
await deleteFaultQueryById(row.id as number);
|
||||
tableRef.value.requestServerInteraction(); // 刷新列表
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法删除决策信息',
|
||||
});
|
||||
}
|
||||
})
|
||||
.onDismiss(() => {
|
||||
operateDisabled.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
creatForm.id = '';
|
||||
creatForm.lineId = '';
|
||||
creatForm.faultType = '';
|
||||
creatForm.faultNameShower = '';
|
||||
creatForm.faultDriverShower = '';
|
||||
creatForm.resultMsg = '';
|
||||
myForm.value?.resetValidation();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.custom-column {
|
||||
max-width: 300px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.message-tip {
|
||||
width: 300px;
|
||||
max-height: 250px;
|
||||
overflow: auto;
|
||||
line-height: 22px;
|
||||
white-space: pre-wrap;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
@ -21,7 +21,7 @@
|
||||
v-model="filter.name"
|
||||
label="名称"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
|
||||
<q-btn color="primary" label="新建" @click="createFormShow = true" />
|
||||
</template>
|
||||
|
||||
@ -267,4 +267,7 @@ function editData(row: any) {
|
||||
editInfo.config = row.config || '';
|
||||
createFormShow.value = true;
|
||||
}
|
||||
function searchQuery() {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
</script>
|
||||
|
@ -3,14 +3,97 @@
|
||||
<q-page-container style="padding: 0; overflow: hidden">
|
||||
<div id="line-app-container"></div>
|
||||
</q-page-container>
|
||||
<div
|
||||
v-if="faultInfo"
|
||||
style="
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 10px;
|
||||
background: white;
|
||||
width: 400px;
|
||||
"
|
||||
>
|
||||
<div style="width: 100%; text-align: right" class="bg-primary q-pa-ms">
|
||||
<q-icon
|
||||
name="add_circle"
|
||||
size="md"
|
||||
v-if="faultInfoMin"
|
||||
style="cursor: pointer"
|
||||
@click="() => (faultInfoMin = false)"
|
||||
/>
|
||||
<q-icon
|
||||
name="remove_circle"
|
||||
size="md"
|
||||
v-if="!faultInfoMin"
|
||||
style="cursor: pointer"
|
||||
@click="() => (faultInfoMin = true)"
|
||||
/>
|
||||
<q-icon
|
||||
name="cancel"
|
||||
size="md"
|
||||
style="cursor: pointer"
|
||||
@click="() => (faultInfo = false)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="!faultInfoMin"
|
||||
class="q-pa-ms"
|
||||
style="
|
||||
background: white;
|
||||
max-width: 400px;
|
||||
height: 268px;
|
||||
overflow-y: scroll;
|
||||
"
|
||||
>
|
||||
<template v-for="(item, index) in timeInfoLabel" :key="index">
|
||||
<div
|
||||
class="row justify-between q-ma-sm bg-blue text-white"
|
||||
style="border-radius: 5px; padding: 5px"
|
||||
>
|
||||
<div
|
||||
style="
|
||||
max-width: 250px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
"
|
||||
>
|
||||
{{ item.split('--')[0] }}
|
||||
<q-tooltip>{{ item.split('--')[0] }}</q-tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ item.split('--')[1] }}</span>
|
||||
<q-icon
|
||||
name="cancel"
|
||||
size="xs"
|
||||
style="cursor: pointer; margin-left: 10px"
|
||||
@click="handleRemoveInfo(index)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <q-chip
|
||||
removable
|
||||
@remove="handleRemoveInfo(index)"
|
||||
color="primary"
|
||||
text-color="white"
|
||||
square
|
||||
:label="item"
|
||||
>
|
||||
<q-tooltip v-if="item.length > 34"> {{ item }} </q-tooltip>
|
||||
</q-chip> -->
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch, onUnmounted } from 'vue';
|
||||
import { onMounted, onUnmounted, watch, ref, reactive } from 'vue';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { AlarmInfo, useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { showAlertTypeData } from 'src/components/alarm/alarmInfoEnum';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@ -22,6 +105,11 @@ const props = withDefaults(
|
||||
const route = useRoute();
|
||||
const lineStore = useLineStore();
|
||||
const lineNetStore = useLineNetStore();
|
||||
const faultInfo = ref(false);
|
||||
const faultInfoMin = ref(false);
|
||||
const alarmInfoList: AlarmInfo[] = reactive([]);
|
||||
let timeInterval = null;
|
||||
let timeInfoLabel: string[] = reactive([]);
|
||||
|
||||
watch(
|
||||
() => props.sizeHeight,
|
||||
@ -36,13 +124,72 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => faultInfo.value,
|
||||
() => {
|
||||
if (!faultInfo.value) {
|
||||
alarmInfoList.splice(0, 1);
|
||||
timeInfoLabel.splice(0);
|
||||
timeInterval = null;
|
||||
} else {
|
||||
timeInterval = setInterval(() => {
|
||||
const now = Date.now();
|
||||
// const labels: string[] = [];
|
||||
timeInfoLabel.splice(0);
|
||||
alarmInfoList.forEach((info) => {
|
||||
const date = info.alert_time.substring(0, 19).replace('T', ' ');
|
||||
let infoTime = new Date(date).getTime();
|
||||
console.log(date, new Date(date), infoTime, now, 'now');
|
||||
const distance = formatTime((now - infoTime) / 1000);
|
||||
const label = handleShowLabel(info);
|
||||
timeInfoLabel.push(label + '--' + distance);
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => lineNetStore.alarmInfo,
|
||||
(val) => {
|
||||
if (val.length) {
|
||||
centerFaultDevice();
|
||||
const lineState = lineNetStore.connectInfo?.msgs.find(
|
||||
(msg) => msg.lineId == lineId
|
||||
);
|
||||
// console.log(lineState, 'line');
|
||||
if (lineState?.atsWarnShowCounter) {
|
||||
val.forEach((info) => {
|
||||
alarmInfoList.push(info);
|
||||
});
|
||||
faultInfo.value = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => lineNetStore.connectInfo,
|
||||
(val) => {
|
||||
if (val?.msgs) {
|
||||
const lineState = val.msgs.find((msg) => msg.lineId == lineId);
|
||||
if (!lineState?.atsWarnShowCounter) {
|
||||
faultInfo.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => lineStore.faultStatistics,
|
||||
() => {
|
||||
const platfroms = lineStore
|
||||
.getLineApp()
|
||||
.queryStore.queryByType<Platform>(Platform.Type);
|
||||
platfroms.forEach((platfrom) => {
|
||||
platfrom.changeState();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
const lineId = Number(route.params.lineId);
|
||||
@ -80,7 +227,41 @@ function centerFaultDevice() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleShowLabel(alarmInfo: AlarmInfo) {
|
||||
const type = (showAlertTypeData as never)[alarmInfo.alert_type + ''];
|
||||
const device = alarmInfo.alert_object.replace(/\[|]/g, '');
|
||||
return device + '[' + type + ']';
|
||||
}
|
||||
|
||||
function handleRemoveInfo(index: number) {
|
||||
alarmInfoList.splice(index, 1);
|
||||
timeInfoLabel.splice(index, 1);
|
||||
if (!alarmInfoList.length) {
|
||||
faultInfo.value = false;
|
||||
}
|
||||
console.log(alarmInfoList, faultInfo.value);
|
||||
}
|
||||
|
||||
function formatTime(seconds: number) {
|
||||
// 确保输入是整数
|
||||
seconds = Math.floor(seconds);
|
||||
|
||||
// 计算小时、分钟和秒
|
||||
const hours = Math.floor(seconds / 3600);
|
||||
const minutes = Math.floor((seconds % 3600) / 60);
|
||||
const secs = (seconds % 3600) % 60;
|
||||
console.log(hours, minutes, secs, seconds, 'sec');
|
||||
// 确保小时、分钟和秒都是两位数
|
||||
const hours1 = String(hours).padStart(2, '0');
|
||||
const minutes1 = String(minutes).padStart(2, '0');
|
||||
const secs1 = String(secs).padStart(2, '0');
|
||||
|
||||
// 返回格式化的时间字符串
|
||||
return `${hours1}:${minutes1}:${secs1}`;
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
lineStore.destroy();
|
||||
lineStore.cancelSubscribe();
|
||||
timeInterval = null;
|
||||
});
|
||||
</script>
|
||||
|
292
src/pages/LoginRecord.vue
Normal file
292
src/pages/LoginRecord.vue
Normal file
@ -0,0 +1,292 @@
|
||||
<template>
|
||||
<div class="q-pa-md">
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
title="登录记录"
|
||||
:style="{ height: tableHeight + 'px' }"
|
||||
class="my-sticky-virtscroll-table"
|
||||
:rows="rows"
|
||||
:columns="columnDefs"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:loading="loading"
|
||||
binary-state-sort
|
||||
@request="onRequest"
|
||||
>
|
||||
<template v-slot:top-right>
|
||||
<q-input
|
||||
dense
|
||||
class="q-mr-md"
|
||||
debounce="1000"
|
||||
v-model="filter.name"
|
||||
label="操作人"
|
||||
></q-input>
|
||||
<q-input
|
||||
v-model="filter.beginDate"
|
||||
label="开始时间"
|
||||
debounce="1000"
|
||||
class="q-mr-md"
|
||||
dense
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-date v-model="filter.beginDate" mask="YYYY-MM-DD HH:mm:ss">
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-date>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<q-icon name="access_time" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-time
|
||||
v-model="filter.beginDate"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
format24h
|
||||
with-seconds
|
||||
>
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="Close" color="primary" flat />
|
||||
</div>
|
||||
</q-time>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
v-model="filter.endDate"
|
||||
label="截止时间"
|
||||
debounce="1000"
|
||||
class="q-mr-md"
|
||||
dense
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-date v-model="filter.endDate" mask="YYYY-MM-DD HH:mm:ss">
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-date>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<q-icon name="access_time" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-time
|
||||
v-model="filter.endDate"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
format24h
|
||||
with-seconds
|
||||
>
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-time>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
|
||||
</template>
|
||||
<template v-slot:body-cell-subEventType="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip outline size="sm" color="primary">
|
||||
{{ getSubEventType(props.row.subEventType) }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
<template v-slot:body-cell-requestSuccess="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip outline size="sm" color="primary">
|
||||
{{ props.row.requestSuccess === 1 ? '成功' : '失败' }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
<!-- <template v-slot:top-right>
|
||||
<q-input
|
||||
dense
|
||||
debounce="1000"
|
||||
v-model="filter.name"
|
||||
label="用户名"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
</template> -->
|
||||
<!-- <template v-slot:body-cell-roles="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip
|
||||
outline
|
||||
size="sm"
|
||||
color="primary"
|
||||
v-for="(item, index) in props.row.roleList"
|
||||
:key="index"
|
||||
>
|
||||
{{ item.roleName }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template> -->
|
||||
<!-- <template v-slot:body-cell-operations="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="编辑角色"
|
||||
:disable="operateDisabled"
|
||||
@click="edieUserData(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template> -->
|
||||
</q-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { type QTableColumn } from 'quasar';
|
||||
import { pageQuery, Record } from '../api/LogApi';
|
||||
import { errorNotify } from '../utils/CommonNotify';
|
||||
|
||||
// const $q = useQuasar(); useQuasar
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
}>(),
|
||||
{ sizeHeight: 500 }
|
||||
);
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
|
||||
{
|
||||
name: 'subEventType',
|
||||
label: '操作',
|
||||
field: 'subEventType',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faceName',
|
||||
label: '接口名称',
|
||||
field: 'faceName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
label: '操作人员',
|
||||
field: 'userName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'createDateTime',
|
||||
label: '记录时间',
|
||||
field: 'createDateTime',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'requestSuccess',
|
||||
label: '请求成功',
|
||||
field: 'requestSuccess',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const filter = reactive({
|
||||
name: '',
|
||||
beginDate: '',
|
||||
endDate: '',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
let response = await pageQuery({
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
logType: 'LOGIN',
|
||||
name: filter.name,
|
||||
beginDate: filter.beginDate,
|
||||
endDate: filter.endDate,
|
||||
});
|
||||
|
||||
pagination.value.rowsNumber = response.total;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
pagination.value.sortBy = sortBy;
|
||||
pagination.value.descending = descending;
|
||||
rows.splice(0, rows.length, ...(response.records as []));
|
||||
} catch (error: any) {
|
||||
errorNotify('获取数据失败', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function getSubEventType(type: string) {
|
||||
switch (type) {
|
||||
case 'LOGIN':
|
||||
return '登录';
|
||||
case 'LOGOUT':
|
||||
return '登出';
|
||||
case 'QUERY':
|
||||
return '查询';
|
||||
case 'SAVE_OR_UPDATE':
|
||||
return '保存';
|
||||
case 'DELETE':
|
||||
return '删除';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function searchQuery() {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
</script>
|
@ -7,9 +7,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch, onUnmounted } from 'vue';
|
||||
import { onMounted, onUnmounted, watch } from 'vue';
|
||||
import { useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { RunLine } from 'src/graphics/runLine/RunLine';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const props = withDefaults(
|
||||
@ -35,13 +34,10 @@ watch(
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => lineNetStore.selectedGraphic,
|
||||
() => lineNetStore.jumpLineCount,
|
||||
(val) => {
|
||||
if (val && lineNetStore.selectedGraphicType == RunLine.Type) {
|
||||
const lineId = (val as RunLine)?.datas.lineId;
|
||||
if (lineId) {
|
||||
router.replace(`/line/monitor/${lineId}`);
|
||||
}
|
||||
if (val) {
|
||||
router.replace(`/line/monitor/${lineNetStore.jumpLineId}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -74,6 +70,6 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
lineNetStore.destroy();
|
||||
lineNetStore.cancelSubscribe();
|
||||
});
|
||||
</script>
|
||||
|
293
src/pages/OperateRecord.vue
Normal file
293
src/pages/OperateRecord.vue
Normal file
@ -0,0 +1,293 @@
|
||||
<template>
|
||||
<div class="q-pa-md">
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
title="操作记录"
|
||||
:style="{ height: tableHeight + 'px' }"
|
||||
class="my-sticky-virtscroll-table"
|
||||
:rows="rows"
|
||||
:columns="columnDefs"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:loading="loading"
|
||||
binary-state-sort
|
||||
@request="onRequest"
|
||||
>
|
||||
<template v-slot:top-right>
|
||||
<q-input
|
||||
dense
|
||||
class="q-mr-md"
|
||||
debounce="1000"
|
||||
v-model="filter.name"
|
||||
label="操作人"
|
||||
></q-input>
|
||||
<q-input
|
||||
v-model="filter.beginDate"
|
||||
label="开始时间"
|
||||
debounce="1000"
|
||||
class="q-mr-md"
|
||||
dense
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-date v-model="filter.beginDate" mask="YYYY-MM-DD HH:mm:ss">
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-date>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<q-icon name="access_time" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-time
|
||||
v-model="filter.beginDate"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
format24h
|
||||
with-seconds
|
||||
>
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="Close" color="primary" flat />
|
||||
</div>
|
||||
</q-time>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
v-model="filter.endDate"
|
||||
label="截止时间"
|
||||
debounce="1000"
|
||||
class="q-mr-md"
|
||||
dense
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-date v-model="filter.endDate" mask="YYYY-MM-DD HH:mm:ss">
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-date>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<q-icon name="access_time" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-time
|
||||
v-model="filter.endDate"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
format24h
|
||||
with-seconds
|
||||
>
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="关闭" color="primary" flat />
|
||||
</div>
|
||||
</q-time>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
|
||||
</template>
|
||||
<template v-slot:body-cell-subEventType="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip outline size="sm" color="primary">
|
||||
{{ getSubEventType(props.row.subEventType) }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
<template v-slot:body-cell-requestSuccess="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip outline size="sm" color="primary">
|
||||
{{ props.row.requestSuccess === 1 ? '成功' : '失败' }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
<!-- <template v-slot:top-right>
|
||||
<q-input
|
||||
dense
|
||||
debounce="1000"
|
||||
v-model="filter.name"
|
||||
label="用户名"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
</template> -->
|
||||
<!-- <template v-slot:body-cell-roles="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip
|
||||
outline
|
||||
size="sm"
|
||||
color="primary"
|
||||
v-for="(item, index) in props.row.roleList"
|
||||
:key="index"
|
||||
>
|
||||
{{ item.roleName }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template> -->
|
||||
<!-- <template v-slot:body-cell-operations="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="编辑角色"
|
||||
:disable="operateDisabled"
|
||||
@click="edieUserData(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template> -->
|
||||
</q-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { type QTableColumn } from 'quasar';
|
||||
import { pageQuery, Record } from '../api/LogApi';
|
||||
import { errorNotify } from '../utils/CommonNotify';
|
||||
|
||||
// const $q = useQuasar();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
}>(),
|
||||
{ sizeHeight: 500 }
|
||||
);
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
|
||||
{
|
||||
name: 'subEventType',
|
||||
label: '操作',
|
||||
field: 'subEventType',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'faceName',
|
||||
label: '接口名称',
|
||||
field: 'faceName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
label: '操作人员',
|
||||
field: 'userName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'createDateTime',
|
||||
label: '记录时间',
|
||||
field: 'createDateTime',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'requestSuccess',
|
||||
label: '请求成功',
|
||||
field: 'requestSuccess',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const filter = reactive({
|
||||
name: '',
|
||||
beginDate: '',
|
||||
endDate: '',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
let response = await pageQuery({
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
logType: 'OPERATE',
|
||||
name: filter.name,
|
||||
beginDate: filter.beginDate,
|
||||
endDate: filter.endDate,
|
||||
});
|
||||
|
||||
pagination.value.rowsNumber = response.total;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
pagination.value.sortBy = sortBy;
|
||||
pagination.value.descending = descending;
|
||||
rows.splice(0, rows.length, ...(response.records as []));
|
||||
} catch (error: any) {
|
||||
errorNotify('获取数据失败', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function searchQuery() {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
|
||||
function getSubEventType(type: string) {
|
||||
switch (type) {
|
||||
case 'LOGIN':
|
||||
return '登录';
|
||||
case 'LOGOUT':
|
||||
return '登出';
|
||||
case 'QUERY':
|
||||
return '查询';
|
||||
case 'SAVE_OR_UPDATE':
|
||||
return '保存';
|
||||
case 'DELETE':
|
||||
return '删除';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
</script>
|
@ -21,7 +21,7 @@
|
||||
v-model="filter.name"
|
||||
label="名称"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-operations="props">
|
||||
@ -183,4 +183,7 @@ async function deleteData(row: any) {
|
||||
operateDisabled.value = false;
|
||||
});
|
||||
}
|
||||
function searchQuery() {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
</script>
|
||||
|
208
src/pages/RoleManage.vue
Normal file
208
src/pages/RoleManage.vue
Normal file
@ -0,0 +1,208 @@
|
||||
<template>
|
||||
<div class="q-pa-md">
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
title="角色列表"
|
||||
:style="{ height: tableHeight + 'px' }"
|
||||
class="my-sticky-virtscroll-table"
|
||||
:rows="rows"
|
||||
:columns="columnDefs"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:loading="loading"
|
||||
:filter="filter"
|
||||
binary-state-sort
|
||||
@request="onRequest"
|
||||
>
|
||||
<template
|
||||
v-if="userStore.defaultRole == 'ADMIN'"
|
||||
v-slot:body-cell-operations="props"
|
||||
>
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
:disable="operateDisabled"
|
||||
color="primary"
|
||||
label="配置"
|
||||
@click="edieRoleData(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
|
||||
<q-dialog
|
||||
v-model="editFormShow"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
</q-dialog>
|
||||
<q-dialog
|
||||
v-model="editFormShow"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<q-form
|
||||
ref="myForm"
|
||||
@submit="roleConfigFn"
|
||||
@reset="onReset"
|
||||
class="q-gutter-md"
|
||||
>
|
||||
<div class="text-h6">配置角色信息</div>
|
||||
<q-input outlined disable label="角色" v-model="roleInfo.name" />
|
||||
<q-input outlined label="配置" v-model="roleInfo.config" />
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="primary" label="保存" type="submit" />
|
||||
<q-btn label="取消" type="reset" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { useQuasar, type QTableColumn, QForm } from 'quasar';
|
||||
import { pageQueryRole, roleConfig, RoleInfo } from 'src/api/AuthApi';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { successNotify } from 'src/utils/CommonNotify';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
const $q = useQuasar();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
}>(),
|
||||
{ sizeHeight: 500 }
|
||||
);
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
const userStore = useUserStore();
|
||||
|
||||
onMounted(() => {
|
||||
if (userStore.defaultRole == 'ADMIN') {
|
||||
columnDefs.push({
|
||||
name: 'operations',
|
||||
label: '操作',
|
||||
field: 'operations',
|
||||
align: 'center',
|
||||
});
|
||||
}
|
||||
tableRef.value.requestServerInteraction();
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{ name: 'id', label: '角色ID', field: 'id', align: 'center' },
|
||||
{
|
||||
name: 'name',
|
||||
label: '角色名称',
|
||||
field: 'name',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const filter = reactive({
|
||||
name: '',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
const filter = props.filter;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
let response = await pageQueryRole({
|
||||
name: filter.name,
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
});
|
||||
|
||||
pagination.value.rowsNumber = response.total;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
pagination.value.sortBy = sortBy;
|
||||
pagination.value.descending = descending;
|
||||
rows.splice(0, rows.length, ...(response.records as []));
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
//提交编辑用户
|
||||
interface RoleItemInfo extends Omit<RoleInfo, 'id'> {
|
||||
id: string;
|
||||
editPaths: { id: number }[];
|
||||
roleConfigStr: string;
|
||||
}
|
||||
const roleInfo = reactive<RoleItemInfo>({
|
||||
id: '',
|
||||
editPaths: [],
|
||||
name: '',
|
||||
resList: [],
|
||||
roleConfigStr: '',
|
||||
});
|
||||
function edieRoleData(row: RoleInfo) {
|
||||
roleInfo.id = row.id + '';
|
||||
roleInfo.name = row.name;
|
||||
roleInfo.roleConfigStr=row.roleConfigStr
|
||||
editFormShow.value = true;
|
||||
}
|
||||
|
||||
const operateDisabled = ref(false);
|
||||
const myForm = ref<QForm | null>(null);
|
||||
const editFormShow = ref(false);
|
||||
function roleConfigFn() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
operateDisabled.value = true;
|
||||
try {
|
||||
await roleConfig(+roleInfo.id, roleInfo.roleConfigStr);
|
||||
editFormShow.value = false;
|
||||
successNotify('修改成功');
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
operateDisabled.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
roleInfo.id = '';
|
||||
roleInfo.name = '';
|
||||
roleInfo.roleConfigStr = '';
|
||||
myForm.value?.resetValidation();
|
||||
}
|
||||
</script>
|
@ -24,8 +24,7 @@
|
||||
label="账号"
|
||||
lazy-rules
|
||||
type="tel"
|
||||
mask="###########"
|
||||
:rules="[(val) => val.length == 11 || '请输入正确手机格式!']"
|
||||
:rules="[(val) => val.length || '请输入账号!']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
@ -36,9 +35,9 @@
|
||||
lazy-rules
|
||||
/>
|
||||
|
||||
<div class="text-right">
|
||||
<!-- <div class="text-right">
|
||||
<q-btn flat label="注册" to="/register" color="primary" />
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="text-center">
|
||||
<q-btn label="登录" type="submit" color="primary" />
|
||||
@ -55,13 +54,17 @@
|
||||
<script setup lang="ts">
|
||||
import { useQuasar } from 'quasar';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { login } from 'src/api/UserApi';
|
||||
import { getUserInfo, login } from 'src/api/UserApi';
|
||||
import { clearJwtToken, saveJwtToken } from 'src/configs/TokenManage';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
import { handleRefreshToken } from 'src/utils/refreshToken';
|
||||
import { getMonitorPath } from 'src/router/routes';
|
||||
|
||||
const $q = useQuasar();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const loginInfo = reactive({
|
||||
account: '',
|
||||
@ -74,7 +77,15 @@ async function doLogin() {
|
||||
clearJwtToken();
|
||||
const token = await login(loginInfo);
|
||||
saveJwtToken(token);
|
||||
router.push({ name: 'home' });
|
||||
const userInfo = await getUserInfo();
|
||||
userStore.roles = userInfo.roles;
|
||||
userStore.defaultRole = userInfo.defaultRole;
|
||||
userStore.remainingSecond = userInfo.remainingSecond;
|
||||
setTimeout(
|
||||
() => handleRefreshToken(),
|
||||
userInfo.remainingSecond * 1000 - 10000
|
||||
);
|
||||
router.replace(getMonitorPath(userInfo.roles).monitorPath);
|
||||
} catch (err) {
|
||||
visible.value = false;
|
||||
const apiErr = err as ApiError;
|
||||
|
@ -22,18 +22,89 @@
|
||||
v-model="filter.name"
|
||||
label="用户名"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
|
||||
</template>
|
||||
<template v-slot:body-cell-roles="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-chip
|
||||
outline
|
||||
size="sm"
|
||||
color="primary"
|
||||
v-for="(item, index) in props.row.roleList"
|
||||
:key="index"
|
||||
>
|
||||
{{ item.roleName }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
<template
|
||||
v-if="userStore.defaultRole == 'ADMIN'"
|
||||
v-slot:body-cell-operations="props"
|
||||
>
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="编辑角色"
|
||||
:disable="operateDisabled"
|
||||
@click="edieUserData(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
|
||||
<q-dialog
|
||||
v-model="editFormShow"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<q-form
|
||||
ref="myForm"
|
||||
@submit="edieUserRole"
|
||||
@reset="onReset"
|
||||
class="q-gutter-md"
|
||||
>
|
||||
<div class="text-h6">修改用户角色</div>
|
||||
<q-input outlined disable label="用户名" v-model="userInfo.name" />
|
||||
<q-select
|
||||
outlined
|
||||
v-model="userInfo.Rids"
|
||||
:options="options"
|
||||
multiple
|
||||
map-options
|
||||
emit-value
|
||||
label="用户角色"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请选择角色!']"
|
||||
></q-select>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="primary" label="保存" type="submit" />
|
||||
<q-btn label="取消" type="reset" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { type QTableColumn } from 'quasar';
|
||||
import { pageQuery } from '../api/UserApi';
|
||||
import { errorNotify } from '../utils/CommonNotify';
|
||||
import { QForm, useQuasar, type QTableColumn } from 'quasar';
|
||||
import { pageQuery, User } from '../api/UserApi';
|
||||
import { errorNotify, successNotify } from '../utils/CommonNotify';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { pageQueryRole, userLinkRole } from 'src/api/AuthApi';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
|
||||
const $q = useQuasar();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
@ -43,9 +114,19 @@ const props = withDefaults(
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
const userStore = useUserStore();
|
||||
|
||||
onMounted(() => {
|
||||
if (userStore.defaultRole == 'ADMIN') {
|
||||
columnDefs.push({
|
||||
name: 'operations',
|
||||
label: '操作',
|
||||
field: 'operations',
|
||||
align: 'center',
|
||||
});
|
||||
}
|
||||
tableRef.value.requestServerInteraction();
|
||||
getAllRole();
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
@ -58,15 +139,16 @@ const columnDefs: QTableColumn[] = [
|
||||
},
|
||||
{ name: 'id', label: '用户ID', field: 'id', align: 'center' },
|
||||
{
|
||||
name: 'registerTime',
|
||||
label: '创建时间',
|
||||
field: 'registerTime',
|
||||
name: 'roles',
|
||||
label: '角色',
|
||||
field: 'roles',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'mobile',
|
||||
label: '手机号',
|
||||
field: 'mobile',
|
||||
name: 'registerTime',
|
||||
label: '创建时间',
|
||||
field: 'registerTime',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
@ -85,6 +167,7 @@ const pagination = ref({
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
const filter = props.filter;
|
||||
@ -109,4 +192,98 @@ async function onRequest(props: any) {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
const editFormShow = ref(false);
|
||||
|
||||
interface UserInfo extends Omit<User, 'password'> {
|
||||
Rids: number[];
|
||||
}
|
||||
const userInfo = reactive<UserInfo>({
|
||||
id: '',
|
||||
name: '',
|
||||
mobile: '',
|
||||
registerTime: '',
|
||||
roleList: [],
|
||||
Rids: [],
|
||||
});
|
||||
|
||||
const options: { label: string; value: number }[] = [];
|
||||
function getAllRole() {
|
||||
pageQueryRole({
|
||||
current: 1,
|
||||
size: 999,
|
||||
})
|
||||
.then((res) => {
|
||||
res.records.forEach((item) => {
|
||||
const obj = {
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
};
|
||||
options.push(obj);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
//编辑用户
|
||||
function edieUserData(row: User) {
|
||||
userInfo.id = row.id;
|
||||
userInfo.name = row.name;
|
||||
userInfo.registerTime = row.registerTime;
|
||||
if (row?.roleList) {
|
||||
userInfo.roleList = row.roleList;
|
||||
userInfo.Rids = row.roleList.map((item) => {
|
||||
return item.roleId;
|
||||
});
|
||||
} else {
|
||||
userInfo.roleList = [];
|
||||
userInfo.Rids = [];
|
||||
}
|
||||
editFormShow.value = true;
|
||||
}
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
|
||||
//提交编辑用户
|
||||
const operateDisabled = ref(false);
|
||||
function edieUserRole() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
operateDisabled.value = true;
|
||||
try {
|
||||
await userLinkRole({
|
||||
id: +userInfo.id,
|
||||
roleList: userInfo.Rids,
|
||||
});
|
||||
tableRef.value.requestServerInteraction(); // 刷新列表
|
||||
editFormShow.value = false;
|
||||
successNotify('修改成功');
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
operateDisabled.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
userInfo.id = '';
|
||||
userInfo.name = '';
|
||||
userInfo.mobile = '';
|
||||
userInfo.registerTime = '';
|
||||
userInfo.roleList = [];
|
||||
userInfo.Rids = [];
|
||||
myForm.value?.resetValidation();
|
||||
}
|
||||
|
||||
function searchQuery() {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
</script>
|
||||
|
@ -35,7 +35,15 @@ export namespace alert {
|
||||
AXLE_LED_RED_INTERLOCK_AREA = 20,
|
||||
AXLE_LED_ORANGE_INTERLOCK_AREA = 21,
|
||||
SWITCH_LOST_INTERLOCK_AREA = 22,
|
||||
INTERLOCK_LEVEL_ONE = 23
|
||||
INTERLOCK_LEVEL_ONE = 23,
|
||||
PLATFORM_EMERG_STOP = 24,
|
||||
SWITCH_JAMMED = 25,
|
||||
INTERLOCKED_ZC_FAULT = 26,
|
||||
TRAIN_LOST_LOCATION = 27,
|
||||
TRAIN_INTEGRITY_ALARM = 28,
|
||||
TRAIN_FAULT_HELP = 29,
|
||||
INTERLOCKED_ATS_STUCK = 30,
|
||||
TRAIN_RECORD = 31
|
||||
}
|
||||
export enum TipTimeConfig {
|
||||
HOLIDAYS_MORN_PEAK = 0,
|
||||
|
@ -87,6 +87,7 @@ export namespace alert {
|
||||
locator_device_id?: string;
|
||||
alert_location_id?: number;
|
||||
mock?: boolean;
|
||||
line_type?: string;
|
||||
}) {
|
||||
super();
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
|
||||
@ -121,6 +122,9 @@ export namespace alert {
|
||||
if ("mock" in data && data.mock != undefined) {
|
||||
this.mock = data.mock;
|
||||
}
|
||||
if ("line_type" in data && data.line_type != undefined) {
|
||||
this.line_type = data.line_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
get id() {
|
||||
@ -183,6 +187,12 @@ export namespace alert {
|
||||
set mock(value: boolean) {
|
||||
pb_1.Message.setField(this, 10, value);
|
||||
}
|
||||
get line_type() {
|
||||
return pb_1.Message.getFieldWithDefault(this, 11, "") as string;
|
||||
}
|
||||
set line_type(value: string) {
|
||||
pb_1.Message.setField(this, 11, value);
|
||||
}
|
||||
static fromObject(data: {
|
||||
id?: string;
|
||||
level?: string;
|
||||
@ -194,6 +204,7 @@ export namespace alert {
|
||||
locator_device_id?: string;
|
||||
alert_location_id?: number;
|
||||
mock?: boolean;
|
||||
line_type?: string;
|
||||
}): Message {
|
||||
const message = new Message({});
|
||||
if (data.id != null) {
|
||||
@ -226,6 +237,9 @@ export namespace alert {
|
||||
if (data.mock != null) {
|
||||
message.mock = data.mock;
|
||||
}
|
||||
if (data.line_type != null) {
|
||||
message.line_type = data.line_type;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
toObject() {
|
||||
@ -240,6 +254,7 @@ export namespace alert {
|
||||
locator_device_id?: string;
|
||||
alert_location_id?: number;
|
||||
mock?: boolean;
|
||||
line_type?: string;
|
||||
} = {};
|
||||
if (this.id != null) {
|
||||
data.id = this.id;
|
||||
@ -271,6 +286,9 @@ export namespace alert {
|
||||
if (this.mock != null) {
|
||||
data.mock = this.mock;
|
||||
}
|
||||
if (this.line_type != null) {
|
||||
data.line_type = this.line_type;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
serialize(): Uint8Array;
|
||||
@ -297,6 +315,8 @@ export namespace alert {
|
||||
writer.writeInt64(9, this.alert_location_id);
|
||||
if (this.mock != false)
|
||||
writer.writeBool(10, this.mock);
|
||||
if (this.line_type.length)
|
||||
writer.writeString(11, this.line_type);
|
||||
if (!w)
|
||||
return writer.getResultBuffer();
|
||||
}
|
||||
@ -336,6 +356,9 @@ export namespace alert {
|
||||
case 10:
|
||||
message.mock = reader.readBool();
|
||||
break;
|
||||
case 11:
|
||||
message.line_type = reader.readString();
|
||||
break;
|
||||
default: reader.skipField();
|
||||
}
|
||||
}
|
||||
|
@ -3191,6 +3191,9 @@ export namespace state {
|
||||
timestamp?: number;
|
||||
lineId?: number;
|
||||
receiveTime?: number;
|
||||
bizWaitTimerGoing?: boolean;
|
||||
bizWaitStartTimeSec?: number;
|
||||
bizWaitTimeSec?: number;
|
||||
}) {
|
||||
super();
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
|
||||
@ -3258,6 +3261,15 @@ export namespace state {
|
||||
if ("receiveTime" in data && data.receiveTime != undefined) {
|
||||
this.receiveTime = data.receiveTime;
|
||||
}
|
||||
if ("bizWaitTimerGoing" in data && data.bizWaitTimerGoing != undefined) {
|
||||
this.bizWaitTimerGoing = data.bizWaitTimerGoing;
|
||||
}
|
||||
if ("bizWaitStartTimeSec" in data && data.bizWaitStartTimeSec != undefined) {
|
||||
this.bizWaitStartTimeSec = data.bizWaitStartTimeSec;
|
||||
}
|
||||
if ("bizWaitTimeSec" in data && data.bizWaitTimeSec != undefined) {
|
||||
this.bizWaitTimeSec = data.bizWaitTimeSec;
|
||||
}
|
||||
}
|
||||
}
|
||||
get emergstop() {
|
||||
@ -3386,6 +3398,24 @@ export namespace state {
|
||||
set receiveTime(value: number) {
|
||||
pb_1.Message.setField(this, 21, value);
|
||||
}
|
||||
get bizWaitTimerGoing() {
|
||||
return pb_1.Message.getFieldWithDefault(this, 22, false) as boolean;
|
||||
}
|
||||
set bizWaitTimerGoing(value: boolean) {
|
||||
pb_1.Message.setField(this, 22, value);
|
||||
}
|
||||
get bizWaitStartTimeSec() {
|
||||
return pb_1.Message.getFieldWithDefault(this, 23, 0) as number;
|
||||
}
|
||||
set bizWaitStartTimeSec(value: number) {
|
||||
pb_1.Message.setField(this, 23, value);
|
||||
}
|
||||
get bizWaitTimeSec() {
|
||||
return pb_1.Message.getFieldWithDefault(this, 24, 0) as number;
|
||||
}
|
||||
set bizWaitTimeSec(value: number) {
|
||||
pb_1.Message.setField(this, 24, value);
|
||||
}
|
||||
static fromObject(data: {
|
||||
emergstop?: boolean;
|
||||
trainberth?: boolean;
|
||||
@ -3408,6 +3438,9 @@ export namespace state {
|
||||
timestamp?: number;
|
||||
lineId?: number;
|
||||
receiveTime?: number;
|
||||
bizWaitTimerGoing?: boolean;
|
||||
bizWaitStartTimeSec?: number;
|
||||
bizWaitTimeSec?: number;
|
||||
}): Platform {
|
||||
const message = new Platform({});
|
||||
if (data.emergstop != null) {
|
||||
@ -3473,6 +3506,15 @@ export namespace state {
|
||||
if (data.receiveTime != null) {
|
||||
message.receiveTime = data.receiveTime;
|
||||
}
|
||||
if (data.bizWaitTimerGoing != null) {
|
||||
message.bizWaitTimerGoing = data.bizWaitTimerGoing;
|
||||
}
|
||||
if (data.bizWaitStartTimeSec != null) {
|
||||
message.bizWaitStartTimeSec = data.bizWaitStartTimeSec;
|
||||
}
|
||||
if (data.bizWaitTimeSec != null) {
|
||||
message.bizWaitTimeSec = data.bizWaitTimeSec;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
toObject() {
|
||||
@ -3498,6 +3540,9 @@ export namespace state {
|
||||
timestamp?: number;
|
||||
lineId?: number;
|
||||
receiveTime?: number;
|
||||
bizWaitTimerGoing?: boolean;
|
||||
bizWaitStartTimeSec?: number;
|
||||
bizWaitTimeSec?: number;
|
||||
} = {};
|
||||
if (this.emergstop != null) {
|
||||
data.emergstop = this.emergstop;
|
||||
@ -3562,6 +3607,15 @@ export namespace state {
|
||||
if (this.receiveTime != null) {
|
||||
data.receiveTime = this.receiveTime;
|
||||
}
|
||||
if (this.bizWaitTimerGoing != null) {
|
||||
data.bizWaitTimerGoing = this.bizWaitTimerGoing;
|
||||
}
|
||||
if (this.bizWaitStartTimeSec != null) {
|
||||
data.bizWaitStartTimeSec = this.bizWaitStartTimeSec;
|
||||
}
|
||||
if (this.bizWaitTimeSec != null) {
|
||||
data.bizWaitTimeSec = this.bizWaitTimeSec;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
serialize(): Uint8Array;
|
||||
@ -3610,6 +3664,12 @@ export namespace state {
|
||||
writer.writeInt32(20, this.lineId);
|
||||
if (this.receiveTime != 0)
|
||||
writer.writeInt64(21, this.receiveTime);
|
||||
if (this.bizWaitTimerGoing != false)
|
||||
writer.writeBool(22, this.bizWaitTimerGoing);
|
||||
if (this.bizWaitStartTimeSec != 0)
|
||||
writer.writeInt64(23, this.bizWaitStartTimeSec);
|
||||
if (this.bizWaitTimeSec != 0)
|
||||
writer.writeInt64(24, this.bizWaitTimeSec);
|
||||
if (!w)
|
||||
return writer.getResultBuffer();
|
||||
}
|
||||
@ -3682,6 +3742,15 @@ export namespace state {
|
||||
case 21:
|
||||
message.receiveTime = reader.readInt64();
|
||||
break;
|
||||
case 22:
|
||||
message.bizWaitTimerGoing = reader.readBool();
|
||||
break;
|
||||
case 23:
|
||||
message.bizWaitStartTimeSec = reader.readInt64();
|
||||
break;
|
||||
case 24:
|
||||
message.bizWaitTimeSec = reader.readInt64();
|
||||
break;
|
||||
default: reader.skipField();
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ export namespace graphicData {
|
||||
separators?: Separator[];
|
||||
logicSections?: LogicSection[];
|
||||
concentrationDividingLines?: ConcentrationDividingLine[];
|
||||
generateAxleCountingConfig?: GenerateAxleCountingConfig;
|
||||
}) {
|
||||
super();
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], this.#one_of_decls);
|
||||
@ -92,6 +93,9 @@ export namespace graphicData {
|
||||
if ("concentrationDividingLines" in data && data.concentrationDividingLines != undefined) {
|
||||
this.concentrationDividingLines = data.concentrationDividingLines;
|
||||
}
|
||||
if ("generateAxleCountingConfig" in data && data.generateAxleCountingConfig != undefined) {
|
||||
this.generateAxleCountingConfig = data.generateAxleCountingConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
get canvas() {
|
||||
@ -217,6 +221,15 @@ export namespace graphicData {
|
||||
set concentrationDividingLines(value: ConcentrationDividingLine[]) {
|
||||
pb_1.Message.setRepeatedWrapperField(this, 20, value);
|
||||
}
|
||||
get generateAxleCountingConfig() {
|
||||
return pb_1.Message.getWrapperField(this, GenerateAxleCountingConfig, 21) as GenerateAxleCountingConfig;
|
||||
}
|
||||
set generateAxleCountingConfig(value: GenerateAxleCountingConfig) {
|
||||
pb_1.Message.setWrapperField(this, 21, value);
|
||||
}
|
||||
get has_generateAxleCountingConfig() {
|
||||
return pb_1.Message.getField(this, 21) != null;
|
||||
}
|
||||
static fromObject(data: {
|
||||
canvas?: ReturnType<typeof Canvas.prototype.toObject>;
|
||||
links?: ReturnType<typeof Link.prototype.toObject>[];
|
||||
@ -238,6 +251,7 @@ export namespace graphicData {
|
||||
separators?: ReturnType<typeof Separator.prototype.toObject>[];
|
||||
logicSections?: ReturnType<typeof LogicSection.prototype.toObject>[];
|
||||
concentrationDividingLines?: ReturnType<typeof ConcentrationDividingLine.prototype.toObject>[];
|
||||
generateAxleCountingConfig?: ReturnType<typeof GenerateAxleCountingConfig.prototype.toObject>;
|
||||
}): RtssGraphicStorage {
|
||||
const message = new RtssGraphicStorage({});
|
||||
if (data.canvas != null) {
|
||||
@ -300,6 +314,9 @@ export namespace graphicData {
|
||||
if (data.concentrationDividingLines != null) {
|
||||
message.concentrationDividingLines = data.concentrationDividingLines.map(item => ConcentrationDividingLine.fromObject(item));
|
||||
}
|
||||
if (data.generateAxleCountingConfig != null) {
|
||||
message.generateAxleCountingConfig = GenerateAxleCountingConfig.fromObject(data.generateAxleCountingConfig);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
toObject() {
|
||||
@ -324,6 +341,7 @@ export namespace graphicData {
|
||||
separators?: ReturnType<typeof Separator.prototype.toObject>[];
|
||||
logicSections?: ReturnType<typeof LogicSection.prototype.toObject>[];
|
||||
concentrationDividingLines?: ReturnType<typeof ConcentrationDividingLine.prototype.toObject>[];
|
||||
generateAxleCountingConfig?: ReturnType<typeof GenerateAxleCountingConfig.prototype.toObject>;
|
||||
} = {};
|
||||
if (this.canvas != null) {
|
||||
data.canvas = this.canvas.toObject();
|
||||
@ -385,6 +403,9 @@ export namespace graphicData {
|
||||
if (this.concentrationDividingLines != null) {
|
||||
data.concentrationDividingLines = this.concentrationDividingLines.map((item: ConcentrationDividingLine) => item.toObject());
|
||||
}
|
||||
if (this.generateAxleCountingConfig != null) {
|
||||
data.generateAxleCountingConfig = this.generateAxleCountingConfig.toObject();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
serialize(): Uint8Array;
|
||||
@ -431,6 +452,8 @@ export namespace graphicData {
|
||||
writer.writeRepeatedMessage(19, this.logicSections, (item: LogicSection) => item.serialize(writer));
|
||||
if (this.concentrationDividingLines.length)
|
||||
writer.writeRepeatedMessage(20, this.concentrationDividingLines, (item: ConcentrationDividingLine) => item.serialize(writer));
|
||||
if (this.has_generateAxleCountingConfig)
|
||||
writer.writeMessage(21, this.generateAxleCountingConfig, () => this.generateAxleCountingConfig.serialize(writer));
|
||||
if (!w)
|
||||
return writer.getResultBuffer();
|
||||
}
|
||||
@ -500,6 +523,9 @@ export namespace graphicData {
|
||||
case 20:
|
||||
reader.readMessage(message.concentrationDividingLines, () => pb_1.Message.addToRepeatedWrapperField(message, 20, ConcentrationDividingLine.deserialize(reader), ConcentrationDividingLine));
|
||||
break;
|
||||
case 21:
|
||||
reader.readMessage(message.generateAxleCountingConfig, () => message.generateAxleCountingConfig = GenerateAxleCountingConfig.deserialize(reader));
|
||||
break;
|
||||
default: reader.skipField();
|
||||
}
|
||||
}
|
||||
@ -5241,4 +5267,94 @@ export namespace graphicData {
|
||||
return Separator.deserialize(bytes);
|
||||
}
|
||||
}
|
||||
export class GenerateAxleCountingConfig extends pb_1.Message {
|
||||
#one_of_decls: number[][] = [];
|
||||
constructor(data?: any[] | {
|
||||
bbConnect?: number[];
|
||||
noGenerateGroup?: number[];
|
||||
}) {
|
||||
super();
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [1, 2], this.#one_of_decls);
|
||||
if (!Array.isArray(data) && typeof data == "object") {
|
||||
if ("bbConnect" in data && data.bbConnect != undefined) {
|
||||
this.bbConnect = data.bbConnect;
|
||||
}
|
||||
if ("noGenerateGroup" in data && data.noGenerateGroup != undefined) {
|
||||
this.noGenerateGroup = data.noGenerateGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
get bbConnect() {
|
||||
return pb_1.Message.getFieldWithDefault(this, 1, []) as number[];
|
||||
}
|
||||
set bbConnect(value: number[]) {
|
||||
pb_1.Message.setField(this, 1, value);
|
||||
}
|
||||
get noGenerateGroup() {
|
||||
return pb_1.Message.getFieldWithDefault(this, 2, []) as number[];
|
||||
}
|
||||
set noGenerateGroup(value: number[]) {
|
||||
pb_1.Message.setField(this, 2, value);
|
||||
}
|
||||
static fromObject(data: {
|
||||
bbConnect?: number[];
|
||||
noGenerateGroup?: number[];
|
||||
}): GenerateAxleCountingConfig {
|
||||
const message = new GenerateAxleCountingConfig({});
|
||||
if (data.bbConnect != null) {
|
||||
message.bbConnect = data.bbConnect;
|
||||
}
|
||||
if (data.noGenerateGroup != null) {
|
||||
message.noGenerateGroup = data.noGenerateGroup;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
toObject() {
|
||||
const data: {
|
||||
bbConnect?: number[];
|
||||
noGenerateGroup?: number[];
|
||||
} = {};
|
||||
if (this.bbConnect != null) {
|
||||
data.bbConnect = this.bbConnect;
|
||||
}
|
||||
if (this.noGenerateGroup != null) {
|
||||
data.noGenerateGroup = this.noGenerateGroup;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
serialize(): Uint8Array;
|
||||
serialize(w: pb_1.BinaryWriter): void;
|
||||
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
|
||||
const writer = w || new pb_1.BinaryWriter();
|
||||
if (this.bbConnect.length)
|
||||
writer.writePackedUint32(1, this.bbConnect);
|
||||
if (this.noGenerateGroup.length)
|
||||
writer.writePackedUint32(2, this.noGenerateGroup);
|
||||
if (!w)
|
||||
return writer.getResultBuffer();
|
||||
}
|
||||
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): GenerateAxleCountingConfig {
|
||||
const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new GenerateAxleCountingConfig();
|
||||
while (reader.nextField()) {
|
||||
if (reader.isEndGroup())
|
||||
break;
|
||||
switch (reader.getFieldNumber()) {
|
||||
case 1:
|
||||
message.bbConnect = reader.readPackedUint32();
|
||||
break;
|
||||
case 2:
|
||||
message.noGenerateGroup = reader.readPackedUint32();
|
||||
break;
|
||||
default: reader.skipField();
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
serializeBinary(): Uint8Array {
|
||||
return this.serialize();
|
||||
}
|
||||
static deserializeBinary(bytes: Uint8Array): GenerateAxleCountingConfig {
|
||||
return GenerateAxleCountingConfig.deserialize(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ export namespace state {
|
||||
lineId?: number;
|
||||
occRealConned?: boolean;
|
||||
occUnrealConned?: boolean;
|
||||
atsWarnShowCounter?: boolean;
|
||||
}) {
|
||||
super();
|
||||
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
|
||||
@ -91,6 +92,9 @@ export namespace state {
|
||||
if ("occUnrealConned" in data && data.occUnrealConned != undefined) {
|
||||
this.occUnrealConned = data.occUnrealConned;
|
||||
}
|
||||
if ("atsWarnShowCounter" in data && data.atsWarnShowCounter != undefined) {
|
||||
this.atsWarnShowCounter = data.atsWarnShowCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
get lineId() {
|
||||
@ -111,10 +115,17 @@ export namespace state {
|
||||
set occUnrealConned(value: boolean) {
|
||||
pb_1.Message.setField(this, 3, value);
|
||||
}
|
||||
get atsWarnShowCounter() {
|
||||
return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean;
|
||||
}
|
||||
set atsWarnShowCounter(value: boolean) {
|
||||
pb_1.Message.setField(this, 4, value);
|
||||
}
|
||||
static fromObject(data: {
|
||||
lineId?: number;
|
||||
occRealConned?: boolean;
|
||||
occUnrealConned?: boolean;
|
||||
atsWarnShowCounter?: boolean;
|
||||
}): WarnMessage {
|
||||
const message = new WarnMessage({});
|
||||
if (data.lineId != null) {
|
||||
@ -126,6 +137,9 @@ export namespace state {
|
||||
if (data.occUnrealConned != null) {
|
||||
message.occUnrealConned = data.occUnrealConned;
|
||||
}
|
||||
if (data.atsWarnShowCounter != null) {
|
||||
message.atsWarnShowCounter = data.atsWarnShowCounter;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
toObject() {
|
||||
@ -133,6 +147,7 @@ export namespace state {
|
||||
lineId?: number;
|
||||
occRealConned?: boolean;
|
||||
occUnrealConned?: boolean;
|
||||
atsWarnShowCounter?: boolean;
|
||||
} = {};
|
||||
if (this.lineId != null) {
|
||||
data.lineId = this.lineId;
|
||||
@ -143,6 +158,9 @@ export namespace state {
|
||||
if (this.occUnrealConned != null) {
|
||||
data.occUnrealConned = this.occUnrealConned;
|
||||
}
|
||||
if (this.atsWarnShowCounter != null) {
|
||||
data.atsWarnShowCounter = this.atsWarnShowCounter;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
serialize(): Uint8Array;
|
||||
@ -155,6 +173,8 @@ export namespace state {
|
||||
writer.writeBool(2, this.occRealConned);
|
||||
if (this.occUnrealConned != false)
|
||||
writer.writeBool(3, this.occUnrealConned);
|
||||
if (this.atsWarnShowCounter != false)
|
||||
writer.writeBool(4, this.atsWarnShowCounter);
|
||||
if (!w)
|
||||
return writer.getResultBuffer();
|
||||
}
|
||||
@ -173,6 +193,9 @@ export namespace state {
|
||||
case 3:
|
||||
message.occUnrealConned = reader.readBool();
|
||||
break;
|
||||
case 4:
|
||||
message.atsWarnShowCounter = reader.readBool();
|
||||
break;
|
||||
default: reader.skipField();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import {
|
||||
|
||||
import routes from './routes';
|
||||
import { getJwtToken } from 'src/configs/TokenManage';
|
||||
import { getUserInfo } from 'src/api/UserApi';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
import { handleRefreshToken } from 'src/utils/refreshToken';
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
@ -42,7 +45,24 @@ export default route(function (/* { store, ssrContext } */) {
|
||||
if (!getJwtToken()) {
|
||||
next({ path: '/login' });
|
||||
} else {
|
||||
try {
|
||||
const userStore = useUserStore();
|
||||
if (!userStore.remainingSecond) {
|
||||
const userInfo = await getUserInfo();
|
||||
userStore.defaultRole = userInfo.defaultRole;
|
||||
userStore.roles = userInfo.roles;
|
||||
userStore.remainingSecond = userInfo.remainingSecond;
|
||||
setTimeout(
|
||||
() => handleRefreshToken(),
|
||||
userInfo.remainingSecond * 1000 - 10000
|
||||
);
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (e) {
|
||||
console.error('获取用户信息出错:', e);
|
||||
next({ path: '/login' });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
import { role } from 'src/api/UserApi';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
redirect: '/monitor',
|
||||
redirect: '/login',
|
||||
// component: () => import('layouts/MainLayout.vue'),
|
||||
// children: [{ path: '', component: () => import('pages/IndexPage.vue') }],
|
||||
},
|
||||
@ -45,6 +46,16 @@ const routes: RouteRecordRaw[] = [
|
||||
name: 'decisionInfo',
|
||||
component: () => import('pages/DecisionInfoManage.vue'),
|
||||
},
|
||||
{
|
||||
path: 'faultQuery',
|
||||
name: 'faultQuery',
|
||||
component: () => import('pages/FaultQueryManage.vue'),
|
||||
},
|
||||
{
|
||||
path: 'emergencyResponse',
|
||||
name: 'emergencyResponse',
|
||||
component: () => import('pages/EmergencyResponseManage.vue'),
|
||||
},
|
||||
{
|
||||
path: 'thresholdValue',
|
||||
name: 'thresholdValue',
|
||||
@ -70,6 +81,61 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
component: () => import('pages/UserManage.vue'),
|
||||
},
|
||||
{
|
||||
path: 'role',
|
||||
name: 'role',
|
||||
meta: {
|
||||
description: '权限管理',
|
||||
},
|
||||
component: () => import('pages/RoleManage.vue'),
|
||||
},
|
||||
{
|
||||
path: 'authPath',
|
||||
name: 'authPath',
|
||||
meta: {
|
||||
description: '权限接口管理',
|
||||
},
|
||||
component: () => import('pages/AuthPathManage.vue'),
|
||||
},
|
||||
{
|
||||
path: 'loginRecord',
|
||||
name: 'loginRecord',
|
||||
meta: {
|
||||
description: '登录记录',
|
||||
},
|
||||
component: () => import('pages/LoginRecord.vue'),
|
||||
},
|
||||
{
|
||||
path: 'operateRecord',
|
||||
name: 'operateRecord',
|
||||
meta: {
|
||||
description: '操作记录',
|
||||
},
|
||||
component: () => import('pages/OperateRecord.vue'),
|
||||
},
|
||||
{
|
||||
path: 'alarmRecord',
|
||||
name: 'alarmRecord',
|
||||
meta: {
|
||||
description: '报警记录',
|
||||
},
|
||||
component: () => import('pages/AlarmRecord.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/alarmInfo',
|
||||
name: 'alarmInfo',
|
||||
component: () => import('layouts/MainLayout.vue'),
|
||||
children: [
|
||||
{
|
||||
path: 'list',
|
||||
name: 'list',
|
||||
meta: {
|
||||
description: '报警信息',
|
||||
},
|
||||
component: () => import('pages/AlarmInfoList.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -117,17 +183,6 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/alarmList',
|
||||
component: () => import('layouts/MainLayout.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'alarmList',
|
||||
component: () => import('src/pages/AlarmInfoList.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Always leave this as last one,
|
||||
// but you can also remove it
|
||||
@ -138,3 +193,45 @@ const routes: RouteRecordRaw[] = [
|
||||
];
|
||||
|
||||
export default routes;
|
||||
|
||||
export function getMonitorPath(roles: role[]) {
|
||||
const configInfo: {
|
||||
monitorPath: string;
|
||||
lineIds: number[];
|
||||
lineType: string;
|
||||
destinations: string[];
|
||||
} = {
|
||||
monitorPath: '',
|
||||
lineIds: [],
|
||||
lineType: '',
|
||||
destinations: [],
|
||||
};
|
||||
let allOCCLineIds: number[] = [];
|
||||
for (let i = 0; i < roles.length; i++) {
|
||||
const roleConfig = roles[i].roleConfig;
|
||||
for (let j = 0; j < roleConfig.length; j++) {
|
||||
if (roleConfig[j].lineType == 'NCC') {
|
||||
configInfo.monitorPath = '/monitor';
|
||||
configInfo.lineIds = roleConfig.map((config) => {
|
||||
configInfo.destinations.push(
|
||||
`/queue/xian/NCC/${config.lineId}/alert`
|
||||
);
|
||||
return config.lineId;
|
||||
});
|
||||
configInfo.lineType = 'NCC';
|
||||
return configInfo;
|
||||
} else {
|
||||
allOCCLineIds.push(roleConfig[j].lineId);
|
||||
}
|
||||
}
|
||||
}
|
||||
allOCCLineIds = [...new Set(allOCCLineIds)];
|
||||
const minId = Math.min(...allOCCLineIds);
|
||||
configInfo.monitorPath = `/line/monitor/${minId}`;
|
||||
configInfo.lineIds = allOCCLineIds;
|
||||
configInfo.lineType = 'OCC';
|
||||
allOCCLineIds.forEach((lineId) => {
|
||||
configInfo.destinations.push(`/queue/xian/OCC/${lineId}/alert`);
|
||||
});
|
||||
return configInfo;
|
||||
}
|
||||
|
@ -4,9 +4,10 @@ import {
|
||||
initLineNetApp,
|
||||
getLineNetApp,
|
||||
destroyLineNetApp,
|
||||
cancelSubscribe,
|
||||
} from 'src/drawApp/lineNetApp';
|
||||
import { markRaw } from 'vue';
|
||||
import { QTable } from 'quasar';
|
||||
import { Notify, QNotifyUpdateOptions, QTable } from 'quasar';
|
||||
import { state } from 'src/protos/system_warn_message';
|
||||
export interface AlarmInfo {
|
||||
id: string;
|
||||
@ -14,12 +15,17 @@ export interface AlarmInfo {
|
||||
alert_time: string;
|
||||
alert_tip_id: number;
|
||||
line_id: string;
|
||||
line_type: string;
|
||||
alert_object: string;
|
||||
alert_type: number;
|
||||
locator_device_id: string;
|
||||
alert_location_id: number;
|
||||
alarmStatus?: number;
|
||||
}
|
||||
let msgNotify: null | ((props?: QNotifyUpdateOptions | undefined) => void) =
|
||||
null;
|
||||
let tip = '';
|
||||
|
||||
export const useLineNetStore = defineStore('lineNet', {
|
||||
state: () => ({
|
||||
selectedGraphics: null as JlGraphic[] | null,
|
||||
@ -27,10 +33,13 @@ export const useLineNetStore = defineStore('lineNet', {
|
||||
alarmInfo: [] as AlarmInfo[], //报警信息
|
||||
untreatedMap: new Map(), // 未处理的报警
|
||||
alarmInfoListTable: undefined as QTable | undefined,
|
||||
playAble: false, //是否允许播放音乐
|
||||
playAble: false, //是否允许播放音乐(与页面交互之后为true)
|
||||
handlePlayAble: true, //默认交互之后可播放音乐
|
||||
closeAllAlarmInfoDialog: false,
|
||||
connectButtonColor: 'green',
|
||||
connectInfo: null as state.WarnLineMessage | null,
|
||||
jumpLineCount: 0,
|
||||
jumpLineId: '',
|
||||
}),
|
||||
getters: {
|
||||
untreatedNum: (state) => {
|
||||
@ -71,6 +80,10 @@ export const useLineNetStore = defineStore('lineNet', {
|
||||
this.selectedGraphics = [];
|
||||
return app;
|
||||
},
|
||||
cancelSubscribe() {
|
||||
const app = this.getLineNetApp();
|
||||
cancelSubscribe(app);
|
||||
},
|
||||
destroy() {
|
||||
this.selectedGraphics = null;
|
||||
destroyLineNetApp();
|
||||
@ -85,6 +98,45 @@ export const useLineNetStore = defineStore('lineNet', {
|
||||
});
|
||||
},
|
||||
setConnectInfo(data: state.WarnLineMessage) {
|
||||
let newTip = '';
|
||||
data.msgs.forEach((item: state.WarnMessage) => {
|
||||
if (!item.occRealConned) {
|
||||
newTip =
|
||||
newTip + `<div>${item.lineId}号线路与同方的实时连接已断开;</div>`;
|
||||
}
|
||||
if (!item.occUnrealConned) {
|
||||
newTip =
|
||||
newTip + `<div>${item.lineId}号线路与同方的非实时连接已断开</div>`;
|
||||
}
|
||||
});
|
||||
if (newTip && (newTip !== tip || !msgNotify)) {
|
||||
if (msgNotify) {
|
||||
msgNotify();
|
||||
}
|
||||
tip = newTip;
|
||||
msgNotify = Notify.create({
|
||||
type: 'negative',
|
||||
timeout: 0,
|
||||
position: 'top',
|
||||
html: true,
|
||||
message: tip,
|
||||
actions: [
|
||||
{
|
||||
icon: 'close',
|
||||
color: 'white',
|
||||
handler: () => {
|
||||
if (msgNotify) {
|
||||
msgNotify();
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
} else if (!newTip) {
|
||||
if (msgNotify) {
|
||||
msgNotify();
|
||||
}
|
||||
}
|
||||
this.connectInfo = data;
|
||||
const allConnectAmount = data.msgs.reduce((pre, cur) => {
|
||||
let addValue = 0;
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { IJlCanvas, JlGraphic, IGraphicApp } from 'jl-graphic';
|
||||
import { initLineApp, getLineApp, destroyLineApp } from 'src/drawApp/lineApp';
|
||||
import {
|
||||
initLineApp,
|
||||
getLineApp,
|
||||
destroyLineApp,
|
||||
cancelSubscribe,
|
||||
} from 'src/drawApp/lineApp';
|
||||
import { markRaw } from 'vue';
|
||||
|
||||
export const useLineStore = defineStore('line', {
|
||||
@ -8,6 +13,7 @@ export const useLineStore = defineStore('line', {
|
||||
selectedGraphics: null as JlGraphic[] | null,
|
||||
lineId: null as number | null,
|
||||
lineName: null as string | null,
|
||||
faultStatistics: false,
|
||||
}),
|
||||
getters: {
|
||||
selectedGraphicType: (state) => {
|
||||
@ -39,7 +45,7 @@ export const useLineStore = defineStore('line', {
|
||||
},
|
||||
initLineApp(lineId: number) {
|
||||
this.setLineId(lineId);
|
||||
const app = initLineApp();
|
||||
const app = initLineApp(lineId);
|
||||
app.on('graphicselected', (graphics) => {
|
||||
this.selectedGraphics = markRaw(graphics);
|
||||
});
|
||||
@ -50,6 +56,10 @@ export const useLineStore = defineStore('line', {
|
||||
this.selectedGraphics = null;
|
||||
destroyLineApp();
|
||||
},
|
||||
cancelSubscribe() {
|
||||
const app = this.getLineApp();
|
||||
cancelSubscribe(app);
|
||||
},
|
||||
setLineId(id: number | null) {
|
||||
this.lineId = id;
|
||||
},
|
||||
|
19
src/stores/user-store.ts
Normal file
19
src/stores/user-store.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { role } from 'src/api/UserApi';
|
||||
|
||||
export const useUserStore = defineStore('user', {
|
||||
state: () => ({
|
||||
remainingSecond: 0,
|
||||
roles: [] as role[],
|
||||
defaultRole: '',
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// setRemainingSecond(remainingSecond: number) {
|
||||
// this.remainingSecond = remainingSecond;
|
||||
// },
|
||||
// setDefaultRole(defaultRole: string) {
|
||||
// this.defaultRole = defaultRole;
|
||||
// },
|
||||
},
|
||||
});
|
18
src/utils/refreshToken.ts
Normal file
18
src/utils/refreshToken.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { saveJwtToken } from 'src/configs/TokenManage';
|
||||
import { refreshToken } from 'src/api/UserApi';
|
||||
import { useUserStore } from 'src/stores/user-store';
|
||||
|
||||
export async function handleRefreshToken() {
|
||||
try {
|
||||
const userStore = useUserStore();
|
||||
const tokenInfo = await refreshToken();
|
||||
saveJwtToken(tokenInfo.token);
|
||||
userStore.remainingSecond = tokenInfo.remainingSecond;
|
||||
setTimeout(
|
||||
() => handleRefreshToken(),
|
||||
tokenInfo.remainingSecond * 1000 - 10000
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('刷新 token 出错:', e);
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit c20feed4b6ae3bdd02cb21b4cc5af03c55be869b
|
||||
Subproject commit 2356a7fdcd388f28e13ba10d4cfc071aaa038646
|
261
yarn.lock
261
yarn.lock
@ -326,18 +326,6 @@
|
||||
eventemitter3 "^4.0.0"
|
||||
url "^0.11.0"
|
||||
|
||||
"@pkgr/utils@^2.4.2":
|
||||
version "2.4.2"
|
||||
resolved "https://registry.npmmirror.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc"
|
||||
integrity sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.3"
|
||||
fast-glob "^3.3.0"
|
||||
is-glob "^4.0.3"
|
||||
open "^9.1.0"
|
||||
picocolors "^1.0.0"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmmirror.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
|
||||
@ -448,13 +436,6 @@
|
||||
resolved "https://registry.npmmirror.com/@quasar/vite-plugin/-/vite-plugin-1.6.0.tgz#3b8f82656b14782fafe66b30dfac0775b87ab9dd"
|
||||
integrity sha512-LmbV76G1CwWZbrEQhqyZpkRQTJyO3xpW55aXY1zWN+JhyUeG77CcMCEWteBVnJ6I6ehUPFDC9ONd2+WlwH6rNQ==
|
||||
|
||||
"@rollup/plugin-alias@^5.1.0":
|
||||
version "5.1.0"
|
||||
resolved "https://registry.npmmirror.com/@rollup/plugin-alias/-/plugin-alias-5.1.0.tgz#99a94accc4ff9a3483be5baeedd5d7da3b597e93"
|
||||
integrity sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ==
|
||||
dependencies:
|
||||
slash "^4.0.0"
|
||||
|
||||
"@rollup/pluginutils@^4.1.2":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
|
||||
@ -1006,11 +987,6 @@ base64-js@^1.3.1:
|
||||
resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
big-integer@^1.6.44:
|
||||
version "1.6.52"
|
||||
resolved "https://registry.npmmirror.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85"
|
||||
integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
@ -1057,13 +1033,6 @@ boolbase@^1.0.0:
|
||||
resolved "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
|
||||
|
||||
bplist-parser@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmmirror.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e"
|
||||
integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==
|
||||
dependencies:
|
||||
big-integer "^1.6.44"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@ -1122,13 +1091,6 @@ buffer@^6.0.3:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
bundle-name@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a"
|
||||
integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==
|
||||
dependencies:
|
||||
run-applescript "^5.0.0"
|
||||
|
||||
bytes@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||
@ -1406,24 +1368,6 @@ deep-is@^0.1.3:
|
||||
resolved "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
|
||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||
|
||||
default-browser-id@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c"
|
||||
integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==
|
||||
dependencies:
|
||||
bplist-parser "^0.2.0"
|
||||
untildify "^4.0.0"
|
||||
|
||||
default-browser@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da"
|
||||
integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==
|
||||
dependencies:
|
||||
bundle-name "^3.0.0"
|
||||
default-browser-id "^3.0.0"
|
||||
execa "^7.1.1"
|
||||
titleize "^3.0.0"
|
||||
|
||||
defaults@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
|
||||
@ -1445,11 +1389,6 @@ define-lazy-prop@^2.0.0:
|
||||
resolved "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
|
||||
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
|
||||
|
||||
define-lazy-prop@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f"
|
||||
integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
@ -1808,19 +1747,6 @@ eslint-config-prettier@^8.1.0:
|
||||
resolved "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11"
|
||||
integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==
|
||||
|
||||
eslint-config-prettier@^9.1.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f"
|
||||
integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
|
||||
|
||||
eslint-plugin-prettier@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz#a3b399f04378f79f066379f544e42d6b73f11515"
|
||||
integrity sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==
|
||||
dependencies:
|
||||
prettier-linter-helpers "^1.0.0"
|
||||
synckit "^0.8.5"
|
||||
|
||||
eslint-plugin-vue@^9.0.0:
|
||||
version "9.19.2"
|
||||
resolved "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.19.2.tgz#7ab83a001a1ac8bccae013c5b9cb5d2c644fb376"
|
||||
@ -1855,7 +1781,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
|
||||
resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint@^8.10.0, eslint@^8.55.0:
|
||||
eslint@^8.10.0:
|
||||
version "8.55.0"
|
||||
resolved "https://registry.npmmirror.com/eslint/-/eslint-8.55.0.tgz#078cb7b847d66f2c254ea1794fa395bf8e7e03f8"
|
||||
integrity sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==
|
||||
@ -1962,36 +1888,6 @@ events@^3.3.0:
|
||||
resolved "https://registry.npmmirror.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
|
||||
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
|
||||
|
||||
execa@^5.0.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
|
||||
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.3"
|
||||
get-stream "^6.0.0"
|
||||
human-signals "^2.1.0"
|
||||
is-stream "^2.0.0"
|
||||
merge-stream "^2.0.0"
|
||||
npm-run-path "^4.0.1"
|
||||
onetime "^5.1.2"
|
||||
signal-exit "^3.0.3"
|
||||
strip-final-newline "^2.0.0"
|
||||
|
||||
execa@^7.1.1:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmmirror.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9"
|
||||
integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.3"
|
||||
get-stream "^6.0.1"
|
||||
human-signals "^4.3.0"
|
||||
is-stream "^3.0.0"
|
||||
merge-stream "^2.0.0"
|
||||
npm-run-path "^5.1.0"
|
||||
onetime "^6.0.0"
|
||||
signal-exit "^3.0.7"
|
||||
strip-final-newline "^3.0.0"
|
||||
|
||||
express@^4.17.3:
|
||||
version "4.18.2"
|
||||
resolved "https://registry.npmmirror.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
|
||||
@ -2043,11 +1939,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-diff@^1.1.2:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
|
||||
integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
|
||||
|
||||
fast-glob@3.2.12:
|
||||
version "3.2.12"
|
||||
resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
|
||||
@ -2059,7 +1950,7 @@ fast-glob@3.2.12:
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.4"
|
||||
|
||||
fast-glob@^3.2.9, fast-glob@^3.3.0:
|
||||
fast-glob@^3.2.9:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
|
||||
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
|
||||
@ -2229,11 +2120,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@
|
||||
has-symbols "^1.0.3"
|
||||
hasown "^2.0.0"
|
||||
|
||||
get-stream@^6.0.0, get-stream@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
|
||||
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
|
||||
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
@ -2378,16 +2264,6 @@ http-errors@2.0.0:
|
||||
statuses "2.0.1"
|
||||
toidentifier "1.0.1"
|
||||
|
||||
human-signals@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
||||
|
||||
human-signals@^4.3.0:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npmmirror.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2"
|
||||
integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
@ -2481,11 +2357,6 @@ is-docker@^2.0.0, is-docker@^2.1.1:
|
||||
resolved "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
|
||||
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
|
||||
|
||||
is-docker@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200"
|
||||
integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
@ -2503,13 +2374,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
|
||||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-inside-container@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4"
|
||||
integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==
|
||||
dependencies:
|
||||
is-docker "^3.0.0"
|
||||
|
||||
is-interactive@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
|
||||
@ -2537,16 +2401,6 @@ is-plain-object@^2.0.4:
|
||||
dependencies:
|
||||
isobject "^3.0.1"
|
||||
|
||||
is-stream@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
|
||||
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
|
||||
|
||||
is-stream@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
|
||||
integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
|
||||
|
||||
is-unicode-supported@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
|
||||
@ -2584,17 +2438,13 @@ isobject@^3.0.1:
|
||||
resolved "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
|
||||
integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
|
||||
|
||||
"jl-graphic@git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#v0.1.0":
|
||||
version "0.0.1"
|
||||
resolved "git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#95de26aad236a7ed2bed23bf82d1c28cbcc7bc73"
|
||||
"jl-graphic@git+https://gitea.joylink.club/joylink/graphic-pixi.git#v0.1.15":
|
||||
version "0.1.14"
|
||||
resolved "git+https://gitea.joylink.club/joylink/graphic-pixi.git#8b0ad14f7324a5eaba58239645a1fa0452e87ab4"
|
||||
dependencies:
|
||||
"@pixi/graphics-extras" "^7.3.2"
|
||||
"@pixi/utils" "^7.3.2"
|
||||
"@rollup/plugin-alias" "^5.1.0"
|
||||
"@stomp/stompjs" "^7.0.0"
|
||||
eslint "^8.55.0"
|
||||
eslint-config-prettier "^9.1.0"
|
||||
eslint-plugin-prettier "^5.0.1"
|
||||
mqtt "^5.2.1"
|
||||
pixi-viewport "^5.0.1"
|
||||
pixi.js "^7.3.2"
|
||||
@ -2771,11 +2621,6 @@ merge-descriptors@1.0.1:
|
||||
resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
|
||||
|
||||
merge2@^1.3.0, merge2@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
@ -2816,11 +2661,6 @@ mimic-fn@^2.1.0:
|
||||
resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
mimic-fn@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
|
||||
integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
|
||||
|
||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
@ -2934,20 +2774,6 @@ normalize-range@^0.1.2:
|
||||
resolved "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
||||
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
||||
|
||||
npm-run-path@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
|
||||
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
|
||||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
npm-run-path@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00"
|
||||
integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==
|
||||
dependencies:
|
||||
path-key "^4.0.0"
|
||||
|
||||
nth-check@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
|
||||
@ -2987,20 +2813,13 @@ once@^1.3.0, once@^1.4.0:
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
onetime@^5.1.0, onetime@^5.1.2:
|
||||
onetime@^5.1.0:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
|
||||
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
onetime@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmmirror.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
|
||||
integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
|
||||
dependencies:
|
||||
mimic-fn "^4.0.0"
|
||||
|
||||
open@^8.4.0:
|
||||
version "8.4.2"
|
||||
resolved "https://registry.npmmirror.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
|
||||
@ -3010,16 +2829,6 @@ open@^8.4.0:
|
||||
is-docker "^2.1.1"
|
||||
is-wsl "^2.2.0"
|
||||
|
||||
open@^9.1.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.npmmirror.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6"
|
||||
integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==
|
||||
dependencies:
|
||||
default-browser "^4.0.0"
|
||||
define-lazy-prop "^3.0.0"
|
||||
is-inside-container "^1.0.0"
|
||||
is-wsl "^2.2.0"
|
||||
|
||||
optionator@^0.9.3:
|
||||
version "0.9.3"
|
||||
resolved "https://registry.npmmirror.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
|
||||
@ -3095,16 +2904,11 @@ path-is-absolute@^1.0.0:
|
||||
resolved "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
path-key@^3.0.0, path-key@^3.1.0:
|
||||
path-key@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
||||
path-key@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
|
||||
integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
|
||||
|
||||
path-parse@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
@ -3206,13 +3010,6 @@ prelude-ls@^1.2.1:
|
||||
resolved "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||
|
||||
prettier-linter-helpers@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
|
||||
integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
|
||||
dependencies:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@^2.5.1:
|
||||
version "2.8.8"
|
||||
resolved "https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
|
||||
@ -3453,13 +3250,6 @@ rollup-plugin-visualizer@^5.5.4:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
run-applescript@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmmirror.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c"
|
||||
integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==
|
||||
dependencies:
|
||||
execa "^5.0.0"
|
||||
|
||||
run-async@^2.4.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.npmmirror.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
|
||||
@ -3599,7 +3389,7 @@ side-channel@^1.0.4:
|
||||
get-intrinsic "^1.0.2"
|
||||
object-inspect "^1.9.0"
|
||||
|
||||
signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
|
||||
signal-exit@^3.0.2:
|
||||
version "3.0.7"
|
||||
resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
@ -3609,11 +3399,6 @@ slash@^3.0.0:
|
||||
resolved "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
slash@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7"
|
||||
integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
|
||||
|
||||
slice-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
|
||||
@ -3683,16 +3468,6 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-final-newline@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
|
||||
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
|
||||
|
||||
strip-final-newline@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
|
||||
integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
|
||||
|
||||
strip-json-comments@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||
@ -3710,14 +3485,6 @@ supports-preserve-symlinks-flag@^1.0.0:
|
||||
resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
synckit@^0.8.5:
|
||||
version "0.8.6"
|
||||
resolved "https://registry.npmmirror.com/synckit/-/synckit-0.8.6.tgz#b69b7fbce3917c2673cbdc0d87fb324db4a5b409"
|
||||
integrity sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA==
|
||||
dependencies:
|
||||
"@pkgr/utils" "^2.4.2"
|
||||
tslib "^2.6.2"
|
||||
|
||||
table@^6.8.0:
|
||||
version "6.8.1"
|
||||
resolved "https://registry.npmmirror.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf"
|
||||
@ -3750,11 +3517,6 @@ through@^2.3.6:
|
||||
resolved "https://registry.npmmirror.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
|
||||
|
||||
titleize@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53"
|
||||
integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
@ -3784,7 +3546,7 @@ tslib@^1.8.1:
|
||||
resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.1.0, tslib@^2.6.0, tslib@^2.6.2:
|
||||
tslib@^2.1.0, tslib@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||
@ -3851,11 +3613,6 @@ unpipe@1.0.0, unpipe@~1.0.0:
|
||||
resolved "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
|
||||
|
||||
untildify@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
|
||||
integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
|
||||
|
||||
update-browserslist-db@^1.0.13:
|
||||
version "1.0.13"
|
||||
resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
|
||||
|
Loading…
Reference in New Issue
Block a user