电子地图管理
This commit is contained in:
parent
2544f5e131
commit
a4e63a4ab6
138
src/api/ElectronicMapDraftApi.ts
Normal file
138
src/api/ElectronicMapDraftApi.ts
Normal file
@ -0,0 +1,138 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto } from './ApiCommon';
|
||||
import { DraftDataType } from './DraftApi';
|
||||
|
||||
export enum LineType {
|
||||
UNKNOWN,
|
||||
UR = 'UR',
|
||||
IR = 'IR',
|
||||
CR = 'CR',
|
||||
}
|
||||
|
||||
export const lineTypeOption = [
|
||||
{
|
||||
label: '城市轨道交通',
|
||||
value: LineType.UR,
|
||||
},
|
||||
{
|
||||
label: '城际轨道交通',
|
||||
value: LineType.IR,
|
||||
},
|
||||
{
|
||||
label: '市域轨道交通',
|
||||
value: LineType.CR,
|
||||
},
|
||||
];
|
||||
|
||||
export const searchLineTypeOption = [
|
||||
{
|
||||
label: '全部',
|
||||
value: LineType.UNKNOWN,
|
||||
},
|
||||
...lineTypeOption,
|
||||
];
|
||||
|
||||
export interface DraftItem {
|
||||
id: number;
|
||||
name: string;
|
||||
dataType: DraftDataType;
|
||||
options: string;
|
||||
data: string;
|
||||
userId: number;
|
||||
defaultReleaseDataId: number;
|
||||
isShared: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
defaultReleaseDataName: string;
|
||||
userName: string;
|
||||
}
|
||||
export interface LineInfoOptionsInput {
|
||||
lineType: LineType;
|
||||
city?: string;
|
||||
lineCode?: string;
|
||||
}
|
||||
export interface PagingQueryParams {
|
||||
paging: {
|
||||
page: number;
|
||||
itemsPerPage: number;
|
||||
};
|
||||
query: {
|
||||
dataType: DraftDataType;
|
||||
options?: LineInfoOptionsInput;
|
||||
name?: string;
|
||||
isShared?: boolean;
|
||||
userId?: number;
|
||||
};
|
||||
}
|
||||
export interface DraftEmDataDto {
|
||||
draftData: DraftItem;
|
||||
options: LineInfoOptionsInput;
|
||||
}
|
||||
|
||||
export async function draftPageQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<DraftEmDataDto>> {
|
||||
const query = `
|
||||
query userDraftEmDataPaging($paging: PageQueryDto, $query: UserDraftEmDataFilterDto) {
|
||||
userDraftEmDataPaging(paging: $paging, query: $query) {
|
||||
total
|
||||
items {
|
||||
draftData {id name dataType userName defaultReleaseDataId createdAt updatedAt isShared defaultReleaseDataName}
|
||||
options {lineType city lineCode}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
const response = await api.post('', {
|
||||
query,
|
||||
variables: params,
|
||||
});
|
||||
return response.data.data.userDraftEmDataPaging;
|
||||
}
|
||||
|
||||
export async function sharedDraftPageQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<DraftEmDataDto>> {
|
||||
const query = `
|
||||
query sharedDraftEmDataPaging($paging: PageQueryDto, $query: SharedDraftEmDataFilterDto) {
|
||||
sharedDraftEmDataPaging(paging: $paging, query: $query) {
|
||||
total
|
||||
items {
|
||||
draftData {id name dataType userName userId defaultReleaseDataId createdAt updatedAt isShared defaultReleaseDataName}
|
||||
options {lineType city lineCode}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
const response = await api.post('', {
|
||||
query,
|
||||
variables: params,
|
||||
});
|
||||
return response.data.data.sharedDraftEmDataPaging;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建草稿
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
interface CreateDraftEmDto {
|
||||
input: {
|
||||
name: string;
|
||||
options: LineInfoOptionsInput;
|
||||
};
|
||||
}
|
||||
export function createDraft(params: CreateDraftEmDto) {
|
||||
const mutation = `
|
||||
mutation createDraftEmData($input: CreateDraftEmDto) {
|
||||
createDraftEmData(input: $input) {
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
return api.post('', {
|
||||
query: mutation,
|
||||
variables: params,
|
||||
});
|
||||
}
|
63
src/api/ElectronicMapPublishApi.ts
Normal file
63
src/api/ElectronicMapPublishApi.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto } from './ApiCommon';
|
||||
import { DraftDataType } from './DraftApi';
|
||||
import { LineInfoOptionsInput } from './ElectronicMapDraftApi';
|
||||
|
||||
export interface PublishItem {
|
||||
id: number;
|
||||
name: string;
|
||||
dataType: DraftDataType;
|
||||
options: string;
|
||||
data: string;
|
||||
usedVersionId: number;
|
||||
userId: number;
|
||||
isPublished: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
description: string;
|
||||
userName: string;
|
||||
}
|
||||
|
||||
interface PagingQueryParams {
|
||||
page: {
|
||||
page: number;
|
||||
itemsPerPage: number;
|
||||
};
|
||||
query: {
|
||||
dataType: DraftDataType;
|
||||
userId?: number;
|
||||
name?: string;
|
||||
isPublished?: boolean;
|
||||
options?: LineInfoOptionsInput;
|
||||
};
|
||||
}
|
||||
export interface PublishEmDataDto {
|
||||
releaseData: PublishItem;
|
||||
options: LineInfoOptionsInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function publishPageQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<PublishEmDataDto>> {
|
||||
const query = `
|
||||
query releaseEmDataPaging($page: PageQueryDto, $query: ReleaseEmDataFilterDto) {
|
||||
releaseEmDataPaging(page: $page, query: $query) {
|
||||
total
|
||||
items {
|
||||
releaseData {id name dataType usedVersionId userName isPublished createdAt updatedAt description }
|
||||
options {lineType city lineCode}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
const response = await api.post('', {
|
||||
query,
|
||||
variables: params,
|
||||
});
|
||||
return response.data.data.releaseEmDataPaging;
|
||||
}
|
@ -115,8 +115,9 @@ export async function login(userLoginDto: LoginInfo) {
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
id: number;
|
||||
username: string;
|
||||
nickname: string;
|
||||
mobile: string;
|
||||
email: string;
|
||||
roles: [];
|
||||
@ -171,7 +172,7 @@ export async function getLoginUserInfo() {
|
||||
const query = `
|
||||
query loginUserInfo {
|
||||
loginUserInfo{
|
||||
id
|
||||
id username nickname mobile email roles createdAt updatedAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -181,20 +182,46 @@ export async function getLoginUserInfo() {
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取jwt令牌(mqtt验证)
|
||||
// */
|
||||
// export async function getJwt() {
|
||||
// const query = `
|
||||
// query getJwt {
|
||||
// getJwt
|
||||
// }
|
||||
// `;
|
||||
// const response = await api.post('', {
|
||||
// query: query,
|
||||
// });
|
||||
// return response.data.data;
|
||||
// }
|
||||
export enum Role {
|
||||
UNKNOWN,
|
||||
ADMIN = 'ADMIN',
|
||||
USER = 'USER',
|
||||
ORG_MANAGER = 'ORG_MANAGER', //组织管理员
|
||||
ORG_TEACHER = 'ORG_TEACHER', //组织教师
|
||||
ORG_STUDENT = 'ORG_STUDENT', //组织学生
|
||||
ORG_GUEST = 'ORG_GUEST', //组织访客
|
||||
}
|
||||
|
||||
export const rolesOptions = [
|
||||
{ label: '系统管理员', value: Role.ADMIN },
|
||||
{ label: '普通用户', value: Role.USER },
|
||||
{ label: '组织管理员', value: Role.ORG_MANAGER },
|
||||
{ label: '组织教师', value: Role.ORG_TEACHER },
|
||||
{ label: '组织学生', value: Role.ORG_STUDENT },
|
||||
{ label: '组织访客', value: Role.ORG_GUEST },
|
||||
];
|
||||
|
||||
/**
|
||||
* 更改用户角色
|
||||
* @param variables
|
||||
* @returns
|
||||
*/
|
||||
export async function updateUserRoles(variables: {
|
||||
userId: number;
|
||||
roles: Role[];
|
||||
}) {
|
||||
const mutation = `
|
||||
mutation updateUserRoles($userId: Int,$roles: [Role!]) {
|
||||
updateUserRoles(userId: $userId,roles: $roles,){
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
return api.post('', {
|
||||
query: mutation,
|
||||
variables,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认组织信息
|
||||
|
@ -1,11 +1,31 @@
|
||||
import { toUint8Array } from 'js-base64';
|
||||
import { GraphicData, IDrawApp, IGraphicStorage, newDrawApp } from 'jl-graphic';
|
||||
import { getDraft } from 'src/api/DraftApi';
|
||||
import { fromUint8Array, toUint8Array } from 'js-base64';
|
||||
import {
|
||||
calculateDistanceFromPointToLine,
|
||||
CombinationKey,
|
||||
ContextMenu,
|
||||
distance2,
|
||||
getRectangleCenter,
|
||||
GraphicData,
|
||||
IDrawApp,
|
||||
IGraphicStorage,
|
||||
KeyListener,
|
||||
MenuItemOptions,
|
||||
newDrawApp,
|
||||
} from 'jl-graphic';
|
||||
import { getDraft, saveDraft } from 'src/api/DraftApi';
|
||||
import { electronicMapGraphicData } from 'src/protos/electronicMap_graphic_data';
|
||||
import { useDrawStore } from 'src/stores/electronicMap-draw-store';
|
||||
import { PlatformDraw } from 'src/graphics/electronicMap/platform/PlatformDrawAssistant';
|
||||
import { PlatformTemplate } from 'src/graphics/electronicMap/platform/Platform';
|
||||
import {
|
||||
Platform,
|
||||
PlatformTemplate,
|
||||
} from 'src/graphics/electronicMap/platform/Platform';
|
||||
import { PlatformData } from './graphics/electronicMap/PlatformInteraction';
|
||||
import { errorNotify, successNotify } from 'src/utils/CommonNotify';
|
||||
import { common } from 'src/protos/common';
|
||||
import { toStorageTransform } from './graphics/GraphicDataBase';
|
||||
import { Section } from 'src/graphics/electronicMap/section/Section';
|
||||
import { OneClickGenerateDraw, OneClickGenerateTemplate } from 'src/graphics/electronicMap/trainWindow/oneClickDrawAssistant';
|
||||
|
||||
let electronicMapDrawApp: IDrawApp | null = null;
|
||||
|
||||
@ -20,19 +40,166 @@ export function destroyElectronicMapDrawApp(): void {
|
||||
}
|
||||
}
|
||||
|
||||
const UndoOptions: MenuItemOptions = {
|
||||
name: '撤销',
|
||||
};
|
||||
const RedoOptions: MenuItemOptions = {
|
||||
name: '重做',
|
||||
};
|
||||
const SelectAllOptions: MenuItemOptions = {
|
||||
name: '全选',
|
||||
};
|
||||
|
||||
export const DefaultEmCanvasMenu = new ContextMenu({
|
||||
name: '绘制-画布菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [UndoOptions, RedoOptions],
|
||||
},
|
||||
{
|
||||
items: [SelectAllOptions],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export function initElectronicMapDrawApp(): IDrawApp {
|
||||
electronicMapDrawApp = newDrawApp({
|
||||
dataLoader: loadThDrawDatas,
|
||||
dataLoader: loadElectronicMapDrawDatas,
|
||||
});
|
||||
const app = electronicMapDrawApp;
|
||||
new PlatformDraw(
|
||||
app,
|
||||
new PlatformTemplate(new PlatformData())
|
||||
new OneClickGenerateDraw(app, new OneClickGenerateTemplate()),
|
||||
new PlatformDraw(app, new PlatformTemplate(new PlatformData()));
|
||||
|
||||
// 画布右键菜单
|
||||
app.registerMenu(DefaultEmCanvasMenu);
|
||||
|
||||
app.canvas.on('_rightclick', (e) => {
|
||||
if (app.drawing) return;
|
||||
UndoOptions.disabled = !app.opRecord.hasUndo;
|
||||
RedoOptions.disabled = !app.opRecord.hasRedo;
|
||||
|
||||
UndoOptions.handler = () => {
|
||||
app.opRecord.undo();
|
||||
};
|
||||
RedoOptions.handler = () => {
|
||||
app.opRecord.redo();
|
||||
};
|
||||
SelectAllOptions.handler = () => {
|
||||
app.selectAllGraphics();
|
||||
};
|
||||
DefaultEmCanvasMenu.open(e.global);
|
||||
});
|
||||
app.on('destroy', () => {
|
||||
generateAxleCountingConfig =
|
||||
new electronicMapGraphicData.GenerateAxleCountingConfig();
|
||||
});
|
||||
app.addKeyboardListener(
|
||||
new KeyListener({
|
||||
value: 'KeyS',
|
||||
global: true,
|
||||
combinations: [CombinationKey.Ctrl],
|
||||
onPress: () => {
|
||||
saveDrawToServer(saveDrawDatas(app));
|
||||
},
|
||||
})
|
||||
);
|
||||
// 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 electronicMapDrawApp;
|
||||
}
|
||||
|
||||
export async function loadThDrawDatas(): Promise<IGraphicStorage> {
|
||||
export async function loadElectronicMapDrawDatas(): Promise<IGraphicStorage> {
|
||||
const drawStore = useDrawStore();
|
||||
const id = drawStore.draftId;
|
||||
if (!id) {
|
||||
@ -46,6 +213,9 @@ export async function loadThDrawDatas(): Promise<IGraphicStorage> {
|
||||
);
|
||||
const datas: GraphicData[] = [];
|
||||
generateAxleCountingConfig = storage.generateAxleCountingConfig;
|
||||
storage.Platforms.forEach((platform) => {
|
||||
datas.push(new PlatformData(platform));
|
||||
});
|
||||
console.log(storage, 'storage');
|
||||
return Promise.resolve({
|
||||
canvasProperty: storage.canvas,
|
||||
@ -58,8 +228,41 @@ export async function loadThDrawDatas(): Promise<IGraphicStorage> {
|
||||
}
|
||||
}
|
||||
|
||||
export function saveDrawDatas() {
|
||||
console.log(111);
|
||||
export function saveDrawDatas(app: IDrawApp) {
|
||||
const storage = new electronicMapGraphicData.ElectronicMapGraphicStorage();
|
||||
const canvasData = app.canvas.saveData();
|
||||
storage.canvas = new common.Canvas({
|
||||
width: canvasData.width,
|
||||
height: canvasData.height,
|
||||
backgroundColor: canvasData.backgroundColor,
|
||||
viewportTransform: toStorageTransform(canvasData.viewportTransform),
|
||||
});
|
||||
const graphics = app.queryStore.getAllGraphics();
|
||||
graphics.forEach((g) => {
|
||||
if (g instanceof Platform) {
|
||||
const platformData = g.saveData();
|
||||
storage.Platforms.push((platformData as PlatformData).data);
|
||||
}
|
||||
});
|
||||
storage.generateAxleCountingConfig = generateAxleCountingConfig;
|
||||
const base64 = fromUint8Array(storage.serialize());
|
||||
console.log('保存数据', storage);
|
||||
return base64;
|
||||
}
|
||||
|
||||
export function saveDrawToServer(base64: string) {
|
||||
const drawStore = useDrawStore();
|
||||
const id = drawStore.draftId;
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
saveDraft({ id, data: base64 })
|
||||
.then(() => {
|
||||
successNotify('保存数据成功!');
|
||||
})
|
||||
.catch((err) => {
|
||||
errorNotify(err.message, err);
|
||||
});
|
||||
}
|
||||
|
||||
//一键生成计轴配置
|
||||
|
@ -72,7 +72,7 @@
|
||||
<q-item-label caption>ID:</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-item-label>{{ userInfo?.id }}</q-item-label>
|
||||
<q-item-label>{{ userInfo.id }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
@ -80,7 +80,15 @@
|
||||
<q-item-label caption>用户名:</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-item-label>{{ userInfo?.name }}</q-item-label>
|
||||
<q-item-label>{{ userInfo.username }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>昵称:</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-item-label>{{ userInfo.nickname }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
@ -89,7 +97,7 @@
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label avatar style="text-align: right">
|
||||
{{ getRoleName(userInfo?.roles) }}
|
||||
{{ getRoleName(userInfo.roles) }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
@ -98,15 +106,27 @@
|
||||
<q-item-label caption>电话:</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-item-label>{{ userInfo?.mobile }}</q-item-label>
|
||||
<q-item-label>{{ userInfo.mobile }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>注册时间:</q-item-label>
|
||||
<q-item-label caption>创建时间:</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-item-label>{{ userInfo?.register_time }}</q-item-label>
|
||||
<q-item-label>{{
|
||||
formatTime(userInfo.createdAt)
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>更新时间:</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-item-label>{{
|
||||
formatTime(userInfo.updatedAt)
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
@ -123,10 +143,13 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
import SysMenu from 'src/components/SysMenu.vue';
|
||||
// import { useRoute } from 'vue-router';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { clearJwtToken } from 'src/configs/TokenManage';
|
||||
import { Dialog } from 'quasar';
|
||||
import { getLoginUserInfo, rolesOptions } from 'src/api/UserApi';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
const router = useRouter();
|
||||
const leftDrawerOpen = ref(false);
|
||||
function toggleLeftDrawer() {
|
||||
leftDrawerOpen.value = !leftDrawerOpen.value;
|
||||
@ -152,9 +175,23 @@ function onLeftResize(size: { width: number; height: number }) {
|
||||
}
|
||||
|
||||
const showInfo = ref(false);
|
||||
const userInfo = null;
|
||||
function showUserInfo() {
|
||||
showInfo.value = true;
|
||||
const userInfo = ref({
|
||||
username: '',
|
||||
nickname: '',
|
||||
mobile: '',
|
||||
email: '',
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
roles: [],
|
||||
});
|
||||
async function showUserInfo() {
|
||||
const res = await getLoginUserInfo();
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
errorNotify('报错', res.data.errors[0].message);
|
||||
} else {
|
||||
showInfo.value = true;
|
||||
userInfo.value = res.loginUserInfo;
|
||||
}
|
||||
}
|
||||
function closeShowInfo() {
|
||||
showInfo.value = false;
|
||||
@ -168,15 +205,22 @@ function logOut() {
|
||||
persistent: true,
|
||||
}).onOk(() => {
|
||||
clearJwtToken();
|
||||
// router.push({ name: 'login' });
|
||||
router.push({ name: 'login' });
|
||||
});
|
||||
}
|
||||
|
||||
function getRoleName(list: { id: number; name: string }[] | undefined) {
|
||||
function formatTime(data: string) {
|
||||
return new Date(data).toLocaleString();
|
||||
}
|
||||
function getRoleName(roles: string[]) {
|
||||
let name = '';
|
||||
if (list && list.length > 0) {
|
||||
const arr = list.map((item) => {
|
||||
return item.name;
|
||||
if (roles && roles.length > 0) {
|
||||
const arr = roles.map((role) => {
|
||||
for (let i = 0; i < rolesOptions.length; i++) {
|
||||
if (rolesOptions[i].value == role) {
|
||||
return rolesOptions[i].label;
|
||||
}
|
||||
}
|
||||
});
|
||||
name = arr.join(',');
|
||||
}
|
||||
|
@ -137,7 +137,9 @@ import { Platform } from 'src/graphics/electronicMap/platform/Platform';
|
||||
import { Section } from 'src/graphics/electronicMap/section/Section';
|
||||
import { Turnout } from 'src/graphics/electronicMap/turnout/Turnout';
|
||||
import { Signal } from 'src/graphics/electronicMap/signal/Signal'; */
|
||||
import { saveDrawToServer } from 'src/drawApp/commonApp';
|
||||
import { saveDrawDatas, saveDrawToServer } from 'src/drawApp/electronicMapApp';
|
||||
import { saveAsDraft } from 'src/api/DraftApi';
|
||||
import { successNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
const $q = useQuasar();
|
||||
const route = useRoute();
|
||||
@ -287,8 +289,8 @@ function onResize() {
|
||||
}
|
||||
|
||||
function saveAllDrawDatas() {
|
||||
let base64 = '';
|
||||
saveDrawToServer(base64);
|
||||
const drawApp = drawStore.getDrawApp();
|
||||
saveDrawToServer(saveDrawDatas(drawApp));
|
||||
}
|
||||
|
||||
function buildRelations() {
|
||||
@ -308,4 +310,19 @@ function backConfirm() {
|
||||
|
||||
const saveAsDialog = ref(false);
|
||||
const saveAsName = ref('');
|
||||
async function saveAs(name: string) {
|
||||
const res = await saveAsDraft({
|
||||
id: +route.params.id as number,
|
||||
name,
|
||||
});
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
successNotify('另存为草稿成功');
|
||||
saveAsDialog.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
838
src/pages/ElectronicMapDraftManage.vue
Normal file
838
src/pages/ElectronicMapDraftManage.vue
Normal file
@ -0,0 +1,838 @@
|
||||
<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"
|
||||
:filter="filter"
|
||||
binary-state-sort
|
||||
@request="onRequest"
|
||||
>
|
||||
<template v-slot:top-right>
|
||||
<div class="q-gutter-md q-mt-none row justify-center items-start">
|
||||
<q-input dense debounce="1000" v-model="filter.name" label="名称" />
|
||||
<q-select
|
||||
dense
|
||||
v-model="filter.lineType"
|
||||
:options="searchLineTypeOption"
|
||||
emit-value
|
||||
map-options
|
||||
options-dense
|
||||
class="ellipsis"
|
||||
label="线路类型"
|
||||
style="width: 130px"
|
||||
/>
|
||||
<q-select
|
||||
v-if="route.name == 'emDraft'"
|
||||
dense
|
||||
v-model="filter.isShared"
|
||||
:options="isSharedOption"
|
||||
class="ellipsis"
|
||||
label="共享相关"
|
||||
style="width: 130px"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
v-if="route.name == 'emDraft'"
|
||||
label="新建"
|
||||
@click="showCreateDialog"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="route.name !== 'emDraft'"
|
||||
flat
|
||||
round
|
||||
color="primary"
|
||||
icon="search"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:header-cell-name="props">
|
||||
<q-th :props="props">
|
||||
{{ props.col.label }}
|
||||
<q-icon name="edit" />
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-name="props">
|
||||
<q-td :props="props" class="cursor-pointer">
|
||||
{{ props.row.name }}
|
||||
<q-popup-edit
|
||||
title="编辑名称"
|
||||
v-model="props.row.name"
|
||||
buttons
|
||||
:cover="false"
|
||||
:validate="caloriesRangeValidation"
|
||||
@hide="caloriesRangeValidation"
|
||||
@update:model-value="saveRowDataName(props.row)"
|
||||
v-slot="scope"
|
||||
>
|
||||
<q-input
|
||||
v-model="scope.value"
|
||||
hint="请输入名称!"
|
||||
:error="errorCalories"
|
||||
:error-message="errorMessageCalories"
|
||||
dense
|
||||
autofocus
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</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"
|
||||
:disable="operateDisabled"
|
||||
label="编辑"
|
||||
@click="goToPath(props.row)"
|
||||
/>
|
||||
<q-btn-dropdown color="primary" label="发布">
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="item in publishMenuConfig"
|
||||
:key="item.label"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="item.click(props.row)"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
<q-btn
|
||||
v-if="
|
||||
route.name == 'emDraft' || props.row.userId == authStore.userId
|
||||
"
|
||||
color="info"
|
||||
style="width: 80px"
|
||||
:disable="operateDisabled"
|
||||
:label="props.row.isShared ? '取消共享' : '共享'"
|
||||
@click="sharedDraftData(props.row)"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="
|
||||
route.name == 'emDraft' || props.row.userId == authStore.userId
|
||||
"
|
||||
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: 300px">
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<div class="text-h6">新建草稿图</div>
|
||||
<q-input
|
||||
outlined
|
||||
label="名称 * "
|
||||
v-model="createForm.draftName"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请输入名称!']"
|
||||
@blur="checkDraftName"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="线路编号"
|
||||
v-model="createForm.lineCode"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="所属城市"
|
||||
v-model="createForm.city"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-select
|
||||
v-model="createForm.lineType"
|
||||
:options="lineTypeOption"
|
||||
emit-value
|
||||
map-options
|
||||
label="线路类型"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="primary" label="创建" type="submit" />
|
||||
<q-btn label="取消" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog
|
||||
v-model="publishFormShow"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<q-form
|
||||
ref="pubForm"
|
||||
@submit="publishDraftGraphics"
|
||||
class="q-gutter-md"
|
||||
>
|
||||
<div class="text-h6">草稿发布</div>
|
||||
<q-input
|
||||
outlined
|
||||
disable
|
||||
label="草稿名称"
|
||||
v-model="publishForm.draftName"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
:disable="publishNameDisable"
|
||||
label="发布名称 * "
|
||||
v-model="publishForm.pubName"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请输入名称!']"
|
||||
@blur="checkPublishName"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="备注 * "
|
||||
v-model="publishForm.note"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请输入备注!']"
|
||||
/>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn color="primary" label="发布" type="submit" />
|
||||
<q-btn label="取消" @click="canclePublish" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog
|
||||
v-model="publishInfoShow"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-card style="width: 1400px; max-width: 80vw">
|
||||
<q-card-section class="row items-center q-pb-none">
|
||||
<div class="text-h6">【{{ draftInfo.name }}】设置默认发布</div>
|
||||
<q-space />
|
||||
<q-btn icon="close" flat round dense v-close-popup />
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-table
|
||||
ref="publishTableRef"
|
||||
:rows="publishRows"
|
||||
:style="{ height: tableHeight * 0.6 + 'px' }"
|
||||
:columns="publishColumnDefs"
|
||||
v-model:pagination="publishPagination"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:loading="publishLoading"
|
||||
@request="publishOnRequest"
|
||||
>
|
||||
<template v-slot:body-cell-operations="props">
|
||||
<q-td :props="props" style="width: 150px">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
v-if="props.row.id !== currentUsedPublishVersionId"
|
||||
color="warning"
|
||||
label="此版本设为默认发布"
|
||||
@click="setDefaultPublishFn(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed, nextTick } from 'vue';
|
||||
import { useQuasar, type QTableColumn, QForm } from 'quasar';
|
||||
import {
|
||||
deleteDraft,
|
||||
DraftDataType,
|
||||
sharedDraft,
|
||||
setDraftRename,
|
||||
draftDataExist,
|
||||
} from '../api/DraftApi';
|
||||
import {
|
||||
DraftEmDataDto,
|
||||
draftPageQuery,
|
||||
PagingQueryParams,
|
||||
lineTypeOption,
|
||||
createDraft,
|
||||
LineType,
|
||||
sharedDraftPageQuery,
|
||||
DraftItem,
|
||||
searchLineTypeOption,
|
||||
} from 'src/api/ElectronicMapDraftApi';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import {
|
||||
publishDraft,
|
||||
publishDraftToDefault,
|
||||
setDefaultPublish,
|
||||
isReleaseDataNameExists,
|
||||
} from 'src/api/PublishApi';
|
||||
import { useAuthStore } from 'src/stores/auth-store';
|
||||
import { PageDto } from 'src/api/ApiCommon';
|
||||
import { PublishItem, publishPageQuery } from 'src/api/ElectronicMapPublishApi';
|
||||
|
||||
const $q = useQuasar();
|
||||
const router = useRouter();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
}>(),
|
||||
{ sizeHeight: 500 }
|
||||
);
|
||||
const authStore = useAuthStore();
|
||||
const route = useRoute();
|
||||
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
field: 'name',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
label: '线路类型',
|
||||
field: (row) => {
|
||||
return getTypeName(row);
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
label: '创建人',
|
||||
field: 'userName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'createdAt',
|
||||
label: '创建时间',
|
||||
field: (row) => new Date(row.createdAt).toLocaleString(),
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'updatedAt',
|
||||
label: '更新时间',
|
||||
field: (row) => new Date(row.updatedAt).toLocaleString(),
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'isShared',
|
||||
label: '是否共享',
|
||||
field: (row) => {
|
||||
return row.isShared ? '是' : '否';
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'defaultReleaseDataName',
|
||||
label: '默认发布',
|
||||
field: 'defaultReleaseDataName',
|
||||
align: 'center',
|
||||
},
|
||||
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
|
||||
];
|
||||
|
||||
const operateDisabled = ref(false);
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const filter = reactive({
|
||||
name: '',
|
||||
lineType: LineType.UNKNOWN,
|
||||
isShared: '全部',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
let allRequestData: DraftEmDataDto[] = [];
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
loading.value = true;
|
||||
const variables: PagingQueryParams = {
|
||||
paging: {
|
||||
page: page,
|
||||
itemsPerPage: rowsPerPage,
|
||||
},
|
||||
query: {
|
||||
dataType: DraftDataType.EM,
|
||||
},
|
||||
};
|
||||
if (filter.name) {
|
||||
Object.assign(variables.query, { name: filter.name });
|
||||
}
|
||||
if (filter.lineType) {
|
||||
Object.assign(variables.query, { options: { lineType: filter.lineType } });
|
||||
}
|
||||
if (filter.isShared !== '全部') {
|
||||
Object.assign(variables.query, {
|
||||
isShared: filter.isShared == '共享' ? true : false,
|
||||
});
|
||||
}
|
||||
try {
|
||||
let response: PageDto<DraftEmDataDto>;
|
||||
if (route.name == 'emDraft') {
|
||||
response = await draftPageQuery(variables);
|
||||
} else {
|
||||
response = await sharedDraftPageQuery(variables);
|
||||
}
|
||||
pagination.value.rowsNumber = response.total;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
rows.splice(
|
||||
0,
|
||||
rows.length,
|
||||
...(response.items.map((item) => item.draftData) as [])
|
||||
);
|
||||
allRequestData = response.items;
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeName(row: DraftItem) {
|
||||
const lineType = allRequestData.find((item) => item.draftData.id == row.id)
|
||||
.options.lineType;
|
||||
const lineTypeName = lineTypeOption.find(
|
||||
(item) => item.value == lineType
|
||||
).label;
|
||||
return lineTypeName;
|
||||
}
|
||||
|
||||
//查询相关
|
||||
const isSharedOption = ['全部', '共享', '不共享'];
|
||||
|
||||
//新建相关
|
||||
const createFormShow = ref(false);
|
||||
function showCreateDialog() {
|
||||
createFormShow.value = true;
|
||||
createForm.draftName = '';
|
||||
createForm.city = '';
|
||||
createForm.lineCode = '';
|
||||
createForm.lineType = LineType.UR;
|
||||
}
|
||||
const createForm = reactive({
|
||||
draftName: '',
|
||||
lineType: LineType.UR,
|
||||
city: '',
|
||||
lineCode: '',
|
||||
});
|
||||
const myForm = ref<QForm | null>(null);
|
||||
async function checkDraftName() {
|
||||
if (!createForm.draftName) return;
|
||||
const res = await draftDataExist({
|
||||
dataType: DraftDataType.EM,
|
||||
name: createForm.draftName,
|
||||
});
|
||||
if (res.data.data.draftDataExist) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '草稿名字已存在,请换一个名字',
|
||||
});
|
||||
}
|
||||
}
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
operateDisabled.value = true;
|
||||
const variables = {
|
||||
input: {
|
||||
name: createForm.draftName,
|
||||
options: { lineType: createForm.lineType },
|
||||
},
|
||||
};
|
||||
if (createForm.lineCode) {
|
||||
Object.assign(variables.input.options, {
|
||||
lineCode: createForm.lineCode,
|
||||
});
|
||||
}
|
||||
if (createForm.city) {
|
||||
Object.assign(variables.input.options, {
|
||||
city: createForm.city,
|
||||
});
|
||||
}
|
||||
const res = await createDraft(variables);
|
||||
operateDisabled.value = false;
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
createFormShow.value = false;
|
||||
createForm.draftName = '';
|
||||
createForm.lineType = LineType.UR;
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//编辑
|
||||
function goToPath(row: DraftItem) {
|
||||
let path = `/emPainting/${row.id}`;
|
||||
const lineType = allRequestData.find((item) => item.draftData.id == row.id)
|
||||
.options.lineType;
|
||||
router.push({
|
||||
path: path,
|
||||
query: { lineType, isShared: row.isShared ? 1 : 2 },
|
||||
});
|
||||
}
|
||||
|
||||
//发布相关
|
||||
const publishMenuConfig = [
|
||||
{ label: '新发布', click: newPublish },
|
||||
{ label: '发布到默认', click: publishToDefault },
|
||||
{ label: '设置默认发布', click: showpublishFn },
|
||||
];
|
||||
const pubForm = ref<QForm | null>(null);
|
||||
const publishFormShow = ref(false);
|
||||
const publishForm = reactive({
|
||||
id: '',
|
||||
draftName: '',
|
||||
pubName: '',
|
||||
note: '',
|
||||
});
|
||||
function newPublish(row: DraftItem) {
|
||||
publishFormShow.value = true;
|
||||
publishForm.id = row.id + '';
|
||||
publishForm.draftName = row.name;
|
||||
publishForm.pubName = row.defaultReleaseDataName || row.name;
|
||||
publishForm.note = '';
|
||||
}
|
||||
|
||||
async function checkPublishName() {
|
||||
if (!publishForm.draftName) return;
|
||||
const res = await isReleaseDataNameExists({
|
||||
dataType: DraftDataType.EM,
|
||||
name: publishForm.draftName,
|
||||
});
|
||||
if (res.data.data.isReleaseDataNameExists) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '发布名字已存在,请换一个名字',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const publishNameDisable = ref(false);
|
||||
function publishToDefault(row: DraftItem) {
|
||||
if (!row.defaultReleaseDataId) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '未设置默认发布,请新发布或设置默认发布',
|
||||
});
|
||||
} else {
|
||||
publishNameDisable.value = true;
|
||||
newPublish(row);
|
||||
}
|
||||
}
|
||||
|
||||
function publishDraftGraphics() {
|
||||
pubForm.value?.validate().then((res) => {
|
||||
if (res) {
|
||||
if (!publishNameDisable.value) {
|
||||
const params: { draftId: number; name: string; description: string } = {
|
||||
draftId: +publishForm.id,
|
||||
name: publishForm.pubName,
|
||||
description: publishForm.note,
|
||||
};
|
||||
publishDraft(params).then((response) => {
|
||||
if (response.data?.errors && response.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: response.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
publishNameDisable.value = false;
|
||||
publishFormShow.value = false;
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: '发布成功',
|
||||
});
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const params: { draftId: number; description: string } = {
|
||||
draftId: +publishForm.id,
|
||||
description: publishForm.note,
|
||||
};
|
||||
publishDraftToDefault(params).then((response) => {
|
||||
if (response.data?.errors && response.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: response.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
publishNameDisable.value = false;
|
||||
publishFormShow.value = false;
|
||||
tableRef.value.requestServerInteraction();
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: '发布成功',
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function canclePublish() {
|
||||
publishNameDisable.value = false;
|
||||
publishFormShow.value = false;
|
||||
}
|
||||
|
||||
//共享
|
||||
async function sharedDraftData(row: DraftItem) {
|
||||
operateDisabled.value = true;
|
||||
const res = await sharedDraft(row.id, !row.isShared);
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
operateDisabled.value = false;
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
//删除
|
||||
function deleteData(row: DraftItem) {
|
||||
operateDisabled.value = true;
|
||||
$q.dialog({
|
||||
title: '确认',
|
||||
message: `确认删除草稿图 "${row.name}" 吗?`,
|
||||
cancel: true,
|
||||
})
|
||||
.onOk(() => {
|
||||
deleteDraft(row.id).then((res) => {
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
});
|
||||
})
|
||||
.onDismiss(() => {
|
||||
operateDisabled.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
//编辑草稿图名称相关
|
||||
const errorCalories = ref(false);
|
||||
const errorMessageCalories = ref('');
|
||||
function caloriesRangeValidation(val?: string) {
|
||||
if (val !== undefined) {
|
||||
if (val.length == 0) {
|
||||
errorCalories.value = true;
|
||||
errorMessageCalories.value = '不能为空!';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
errorCalories.value = false;
|
||||
errorMessageCalories.value = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
async function saveRowDataName(row: DraftItem) {
|
||||
const params = {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
};
|
||||
const res = await setDraftRename(params);
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
//设置默认发布相关
|
||||
const publishInfoShow = ref(false);
|
||||
const draftInfo = ref<DraftItem>({
|
||||
id: 0,
|
||||
name: '',
|
||||
dataType: DraftDataType.EM,
|
||||
options: '',
|
||||
data: '',
|
||||
userId: 0,
|
||||
defaultReleaseDataId: 0,
|
||||
isShared: false,
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
defaultReleaseDataName: '',
|
||||
userName: '',
|
||||
});
|
||||
|
||||
const publishColumnDefs: QTableColumn[] = [
|
||||
{
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
field: 'name',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
label: '描述',
|
||||
field: 'description',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'userId',
|
||||
label: '发布人',
|
||||
field: 'userId',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'createdAt',
|
||||
label: '发布时间',
|
||||
field: (row) => new Date(row.createdAt).toLocaleString(),
|
||||
align: 'center',
|
||||
},
|
||||
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
|
||||
];
|
||||
|
||||
const publishTableRef = ref();
|
||||
const publishRows = reactive<PublishItem[]>([]);
|
||||
const publishLoading = ref(false);
|
||||
const publishPagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
async function publishOnRequest(props: any) {
|
||||
publishLoading.value = true;
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
const variables = {
|
||||
page: {
|
||||
page: page,
|
||||
itemsPerPage: rowsPerPage,
|
||||
},
|
||||
query: {
|
||||
dataType: DraftDataType.EM,
|
||||
name: filter.name,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await publishPageQuery(variables);
|
||||
publishPagination.value.rowsNumber = response.total;
|
||||
publishPagination.value.page = page;
|
||||
publishPagination.value.rowsPerPage = rowsPerPage;
|
||||
publishRows.splice(
|
||||
0,
|
||||
publishRows.length,
|
||||
...(response.items.map((item) => item.releaseData) as [])
|
||||
);
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
publishLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
const currentUsedPublishVersionId = ref();
|
||||
function showpublishFn(row: DraftItem) {
|
||||
currentUsedPublishVersionId.value = row.defaultReleaseDataId;
|
||||
draftInfo.value = row;
|
||||
publishInfoShow.value = true;
|
||||
nextTick(() => {
|
||||
publishTableRef.value.requestServerInteraction();
|
||||
});
|
||||
}
|
||||
|
||||
function setDefaultPublishFn(row: PublishItem) {
|
||||
if (!draftInfo.value.id || !row.id) return;
|
||||
$q.dialog({
|
||||
title: '确认',
|
||||
message: `确定把【${draftInfo.value.name}】的默认发布版本设为【${row.name}】吗?`,
|
||||
cancel: true,
|
||||
}).onOk(() => {
|
||||
setDefaultPublish({ id: draftInfo.value.id, releaseDataId: row.id }).then(
|
||||
(res) => {
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: '设置默认发布成功!',
|
||||
});
|
||||
tableRef.value.requestServerInteraction();
|
||||
publishInfoShow.value = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
src/api/ElectronicMapDraftApi
|
544
src/pages/ElectronicMapPublishManage.vue
Normal file
544
src/pages/ElectronicMapPublishManage.vue
Normal file
@ -0,0 +1,544 @@
|
||||
<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"
|
||||
:filter="filter"
|
||||
:selection="isProject ? 'multiple' : 'none'"
|
||||
v-model:selected="selected"
|
||||
:selected-rows-label="getSelectedString"
|
||||
binary-state-sort
|
||||
@request="onRequest"
|
||||
>
|
||||
<template v-slot:top-right>
|
||||
<div class="q-gutter-md q-mt-none row justify-center items-start">
|
||||
<q-input dense debounce="1000" v-model="filter.name" label="名称" />
|
||||
<q-select
|
||||
dense
|
||||
v-model="filter.lineType"
|
||||
:options="searchLineTypeOption"
|
||||
emit-value
|
||||
map-options
|
||||
options-dense
|
||||
class="ellipsis"
|
||||
label="线路类型"
|
||||
style="width: 130px"
|
||||
/>
|
||||
<q-select
|
||||
dense
|
||||
v-model="filter.isPublished"
|
||||
:options="isPublishedOption"
|
||||
class="ellipsis"
|
||||
label="上下架"
|
||||
style="width: 130px"
|
||||
/>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-cell-name="props">
|
||||
<q-th :props="props">
|
||||
{{ props.col.label }}
|
||||
<q-icon name="edit" />
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-name="props">
|
||||
<q-td :props="props" class="cursor-pointer">
|
||||
{{ props.row.name }}
|
||||
<q-popup-edit
|
||||
title="编辑名称"
|
||||
v-model="props.row.name"
|
||||
buttons
|
||||
:cover="false"
|
||||
:validate="caloriesRangeValidation"
|
||||
@hide="caloriesRangeValidation"
|
||||
@update:model-value="saveRowDataName(props.row)"
|
||||
v-slot="scope"
|
||||
>
|
||||
<q-input
|
||||
v-model="scope.value"
|
||||
hint="请输入名称!"
|
||||
:error="errorCalories"
|
||||
:error-message="errorMessageCalories"
|
||||
dense
|
||||
autofocus
|
||||
@keyup.enter="scope.set"
|
||||
/>
|
||||
</q-popup-edit>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-operations="props" v-if="!isProject">
|
||||
<q-td :props="props" style="width: 320px">
|
||||
<div class="q-gutter-sm row justify-start">
|
||||
<q-btn
|
||||
:color="!props.row.isPublished ? 'primary' : 'amber'"
|
||||
:label="!props.row.isPublished ? '上架' : '下架'"
|
||||
@click="dataReleaseFn(props.row)"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="另存到草稿"
|
||||
@click="saveToDraftFn(props.row)"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="发布历史"
|
||||
@click="showHistoryFn(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
<q-dialog
|
||||
v-model="historyInfoShow"
|
||||
persistent
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-card style="width: 1400px; max-width: 80vw">
|
||||
<q-card-section class="row items-center q-pb-none">
|
||||
<div class="text-h6">【{{ historyInfo.name }}】发布历史</div>
|
||||
<q-space />
|
||||
<q-btn icon="close" flat round dense v-close-popup />
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-table
|
||||
ref="historyTableRef"
|
||||
:rows="historyRows"
|
||||
:style="{ height: tableHeight * 0.6 + 'px' }"
|
||||
:columns="historyColumnDefs"
|
||||
v-model:pagination="historyPagination"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
:loading="historyLoading"
|
||||
@request="historyOnRequest"
|
||||
>
|
||||
<template v-slot:body-cell-operations="props" v-if="!isProject">
|
||||
<q-td :props="props" style="width: 150px">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn
|
||||
v-if="props.row.id !== currentUsedVersionId"
|
||||
color="warning"
|
||||
label="回退到此版本"
|
||||
@click="backVersion(props.row)"
|
||||
/>
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
</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 } from 'quasar';
|
||||
import {
|
||||
saveToDraft,
|
||||
setPublishRename,
|
||||
getPublishHistoryById,
|
||||
setPublishRelease,
|
||||
PublishHistoryItem,
|
||||
fallbackVersion,
|
||||
} from '../api/PublishApi';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { nextTick } from 'process';
|
||||
import { DraftDataType } from 'src/api/DraftApi';
|
||||
import {
|
||||
PublishEmDataDto,
|
||||
PublishItem,
|
||||
publishPageQuery,
|
||||
} from 'src/api/ElectronicMapPublishApi';
|
||||
import {
|
||||
LineType,
|
||||
lineTypeOption,
|
||||
searchLineTypeOption,
|
||||
} from 'src/api/ElectronicMapDraftApi';
|
||||
|
||||
const route = useRoute();
|
||||
const $q = useQuasar();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
sizeHeight: number;
|
||||
selects?: [];
|
||||
}>(),
|
||||
{ sizeHeight: 500, selects: () => [] }
|
||||
);
|
||||
const tableHeight = computed(() => {
|
||||
return props.sizeHeight - 32;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
selected.value = props.selects;
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
field: 'name',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
label: '线路类型',
|
||||
field: (row) => {
|
||||
return getTypeName(row);
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
label: '描述',
|
||||
field: 'description',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
label: '发布人',
|
||||
field: 'userName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'createdAt',
|
||||
label: '创建时间',
|
||||
field: (row) => new Date(row.createdAt).toLocaleString(),
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'updatedAt',
|
||||
label: '更新时间',
|
||||
field: (row) => new Date(row.updatedAt).toLocaleString(),
|
||||
align: 'center',
|
||||
},
|
||||
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
|
||||
];
|
||||
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const filter = reactive({
|
||||
name: '',
|
||||
lineType: LineType.UNKNOWN,
|
||||
isPublished: '全部',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
let allRequestData: PublishEmDataDto[] = [];
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
|
||||
loading.value = true;
|
||||
const variables = {
|
||||
page: {
|
||||
page: page,
|
||||
itemsPerPage: rowsPerPage,
|
||||
},
|
||||
query: {
|
||||
dataType: DraftDataType.EM,
|
||||
},
|
||||
};
|
||||
if (filter.name) {
|
||||
Object.assign(variables.query, { name: filter.name });
|
||||
}
|
||||
if (filter.lineType) {
|
||||
Object.assign(variables.query, { options: { lineType: filter.lineType } });
|
||||
}
|
||||
if (filter.isPublished !== '全部') {
|
||||
Object.assign(variables.query, {
|
||||
isPublished: filter.isPublished == '上架' ? true : false,
|
||||
});
|
||||
}
|
||||
try {
|
||||
const response = await publishPageQuery(variables);
|
||||
pagination.value.rowsNumber = response.total;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
rows.splice(
|
||||
0,
|
||||
rows.length,
|
||||
...(response.items.map((item) => item.releaseData) as [])
|
||||
);
|
||||
allRequestData = response.items;
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeName(row: PublishItem) {
|
||||
const lineType = allRequestData.find((item) => item.releaseData.id == row.id)
|
||||
.options.lineType;
|
||||
const lineTypeName = lineTypeOption.find(
|
||||
(item) => item.value == lineType
|
||||
).label;
|
||||
return lineTypeName || '';
|
||||
}
|
||||
|
||||
//查询相关
|
||||
const isPublishedOption = ['全部', '上架', '下架'];
|
||||
|
||||
//上下架
|
||||
function dataReleaseFn(row: PublishItem) {
|
||||
if (row.isPublished) {
|
||||
$q.dialog({
|
||||
title: '确认',
|
||||
message: `确定下架发布数据【${row.name}】吗?`,
|
||||
cancel: true,
|
||||
}).onOk(() => {
|
||||
setPublishRelease({ id: row.id, isPublished: !row.isPublished }).then(
|
||||
(res) => {
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
setPublishRelease({ id: row.id, isPublished: !row.isPublished }).then(
|
||||
(res) => {
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//另存草稿
|
||||
function saveToDraftFn(row: PublishItem) {
|
||||
saveToDraft({
|
||||
versionId: row.usedVersionId,
|
||||
}).then((res) => {
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
const draftName =
|
||||
res.data.data.createDraftDataFromReleaseDataVersion.name;
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: `另存草稿成功且草稿图名字为${draftName}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 项目管理相关
|
||||
const emit = defineEmits(['selectsed']);
|
||||
const selected = ref<PublishItem[] | []>([]);
|
||||
watch(
|
||||
() => selected.value,
|
||||
(val) => {
|
||||
if (val != props.selects) {
|
||||
emit('selectsed', val);
|
||||
}
|
||||
}
|
||||
);
|
||||
const isProject = computed(() => {
|
||||
return route.path.includes('dataManage/project');
|
||||
});
|
||||
function getSelectedString() {
|
||||
const nameArr = selected.value.map((item) => {
|
||||
return item.name;
|
||||
});
|
||||
const name = nameArr.join(',');
|
||||
return `已选:${name}`;
|
||||
}
|
||||
if (isProject.value) {
|
||||
const index = columnDefs.findIndex((item) => {
|
||||
return item.name == 'operations';
|
||||
});
|
||||
if (index >= 0) {
|
||||
columnDefs.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//修改发布图名字
|
||||
const errorCalories = ref(false);
|
||||
const errorMessageCalories = ref('');
|
||||
function caloriesRangeValidation(val?: string) {
|
||||
if (val !== undefined) {
|
||||
if (val.length == 0) {
|
||||
errorCalories.value = true;
|
||||
errorMessageCalories.value = '不能为空!';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
errorCalories.value = false;
|
||||
errorMessageCalories.value = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
async function saveRowDataName(row: PublishItem) {
|
||||
const params = {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
};
|
||||
const res = await setPublishRename(params);
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
//发布历史相关
|
||||
const historyInfoShow = ref(false);
|
||||
const historyInfo = ref<PublishItem>({
|
||||
id: 0,
|
||||
name: '',
|
||||
dataType: DraftDataType.EM,
|
||||
options: '',
|
||||
data: '',
|
||||
usedVersionId: 0,
|
||||
userId: 0,
|
||||
isPublished: false,
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
description: '',
|
||||
userName: '',
|
||||
});
|
||||
|
||||
const historyColumnDefs: QTableColumn[] = [
|
||||
{
|
||||
name: 'userName',
|
||||
label: '发布人',
|
||||
field: 'userName',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'createdAt',
|
||||
label: '发布时间',
|
||||
field: (row) => new Date(row.createdAt).toLocaleString(),
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
label: '描述',
|
||||
field: 'description',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
|
||||
];
|
||||
|
||||
const historyTableRef = ref();
|
||||
const historyRows = reactive<PublishHistoryItem[]>([]);
|
||||
const historyLoading = ref(false);
|
||||
const historyPagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
async function historyOnRequest(props: any) {
|
||||
historyLoading.value = true;
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
const variables = {
|
||||
dataId: historyInfo.value.id,
|
||||
page: {
|
||||
page: page,
|
||||
itemsPerPage: rowsPerPage,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await getPublishHistoryById(variables);
|
||||
historyPagination.value.rowsNumber = response.total;
|
||||
historyPagination.value.page = page;
|
||||
historyPagination.value.rowsPerPage = rowsPerPage;
|
||||
historyRows.splice(0, historyRows.length, ...(response.items as []));
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
} finally {
|
||||
historyLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
const currentUsedVersionId = ref();
|
||||
function showHistoryFn(row: PublishItem) {
|
||||
currentUsedVersionId.value = row.usedVersionId;
|
||||
historyInfo.value = row;
|
||||
historyInfoShow.value = true;
|
||||
nextTick(() => {
|
||||
historyTableRef.value.requestServerInteraction();
|
||||
});
|
||||
}
|
||||
|
||||
function backVersion(row: PublishHistoryItem) {
|
||||
if (!historyInfo.value.id || !row.id) return;
|
||||
$q.dialog({
|
||||
title: '确认',
|
||||
message: `确定把【${historyInfo.value.name}】回退到【${row.description}】版本吗?`,
|
||||
cancel: true,
|
||||
}).onOk(() => {
|
||||
fallbackVersion({ id: historyInfo.value.id, versionId: row.id }).then(
|
||||
(res) => {
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: '回退版本成功!',
|
||||
});
|
||||
tableRef.value.requestServerInteraction();
|
||||
historyInfoShow.value = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
</script>
|
@ -41,7 +41,14 @@
|
||||
color="primary"
|
||||
v-if="route.name == 'iscsDraft'"
|
||||
label="新建"
|
||||
@click="createFormShow = true"
|
||||
@click="showCreateDialog"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="route.name !== 'iscsDraft'"
|
||||
flat
|
||||
round
|
||||
color="primary"
|
||||
icon="search"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -436,6 +443,11 @@ const isSharedOption = ['全部', '共享', '不共享'];
|
||||
|
||||
//新建相关
|
||||
const createFormShow = ref(false);
|
||||
function showCreateDialog() {
|
||||
createFormShow.value = true;
|
||||
createForm.draftName = '';
|
||||
createForm.style = IscsStyle.DA_SHI_ZHI_NENG;
|
||||
}
|
||||
const createForm = reactive({
|
||||
draftName: '',
|
||||
style: IscsStyle.DA_SHI_ZHI_NENG,
|
||||
|
@ -39,6 +39,7 @@
|
||||
label="上下架"
|
||||
style="width: 130px"
|
||||
/>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -246,7 +247,6 @@ const pagination = ref({
|
||||
let allRequestData: PublishIscsDataDto[] = [];
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
const filter = props.filter;
|
||||
|
||||
loading.value = true;
|
||||
const variables = {
|
||||
|
@ -52,15 +52,71 @@
|
||||
</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>
|
||||
<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" class="q-gutter-md">
|
||||
<div class="text-h6">修改用户角色</div>
|
||||
<q-input
|
||||
outlined
|
||||
disable
|
||||
label="用户名"
|
||||
v-model="userInfo.username"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="userInfo.roles"
|
||||
:options="rolesOptions"
|
||||
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 { useQuasar, type QTableColumn } from 'quasar';
|
||||
import { PagingQueryParams, userPageQuery } from '../api/UserApi';
|
||||
import {
|
||||
PagingQueryParams,
|
||||
rolesOptions,
|
||||
updateUserRoles,
|
||||
User,
|
||||
userPageQuery,
|
||||
} from '../api/UserApi';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { successNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
const $q = useQuasar();
|
||||
|
||||
@ -125,6 +181,12 @@ const columnDefs: QTableColumn[] = [
|
||||
field: (row) => new Date(row.updatedAt).toLocaleString(),
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'operations',
|
||||
label: '操作',
|
||||
field: 'operations',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const tableRef = ref();
|
||||
@ -178,10 +240,6 @@ async function onRequest(props: any) {
|
||||
}
|
||||
}
|
||||
|
||||
const rolesOptions = [
|
||||
{ label: '管理员', value: 'ADMIN' },
|
||||
{ label: '用户', value: 'USER' },
|
||||
];
|
||||
function getRolesName(role: string) {
|
||||
for (let i = 0; i < rolesOptions.length; i++) {
|
||||
if (rolesOptions[i].value == role) {
|
||||
@ -189,4 +247,40 @@ function getRolesName(role: string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const editFormShow = ref(false);
|
||||
const userInfo = reactive({
|
||||
id: 0,
|
||||
username: '',
|
||||
nickname: '',
|
||||
roles: [],
|
||||
});
|
||||
const operateDisabled = ref(false);
|
||||
function edieUserData(row: User) {
|
||||
userInfo.id = row.id;
|
||||
userInfo.username = row.username;
|
||||
if (row?.roles) {
|
||||
userInfo.roles = row.roles;
|
||||
} else {
|
||||
userInfo.roles = [];
|
||||
}
|
||||
editFormShow.value = true;
|
||||
}
|
||||
async function edieUserRole() {
|
||||
operateDisabled.value = true;
|
||||
const res = await updateUserRoles({
|
||||
userId: userInfo.id,
|
||||
roles: userInfo.roles,
|
||||
});
|
||||
operateDisabled.value = false;
|
||||
if (res.data?.errors && res.data?.errors.length) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: res.data.errors[0].message,
|
||||
});
|
||||
} else {
|
||||
successNotify('修改成功');
|
||||
tableRef.value.requestServerInteraction();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -49,8 +49,8 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
|
||||
{
|
||||
path: '/dataManage',
|
||||
name: 'dataManage',
|
||||
path: '/iscsDataManage',
|
||||
name: 'iscsDataManage',
|
||||
component: () => import('layouts/MainLayout.vue'),
|
||||
meta: {
|
||||
label: 'ISCS数据管理',
|
||||
@ -86,6 +86,44 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/emDataManage',
|
||||
name: 'emDataManage',
|
||||
component: () => import('layouts/MainLayout.vue'),
|
||||
meta: {
|
||||
label: '电子地图数据管理',
|
||||
icon: 'list_alt',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'emDraft',
|
||||
name: 'emDraft',
|
||||
component: () => import('pages/ElectronicMapDraftManage.vue'),
|
||||
meta: {
|
||||
label: '草稿数据',
|
||||
icon: 'app_registration',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'emSharedDraft',
|
||||
name: 'emSharedDraft',
|
||||
component: () => import('pages/ElectronicMapDraftManage.vue'),
|
||||
meta: {
|
||||
label: '共享草稿数据',
|
||||
icon: 'app_registration',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'emPublish',
|
||||
name: 'emPublish',
|
||||
component: () => import('pages/ElectronicMapPublishManage.vue'),
|
||||
meta: {
|
||||
label: '发布数据',
|
||||
icon: 'playlist_add_check',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/iscsPainting/:id',
|
||||
name: 'iscsPainting',
|
||||
@ -95,8 +133,8 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/electronicMapPainting/:id',
|
||||
name: 'electronicMapPainting',
|
||||
path: '/emPainting/:id',
|
||||
name: 'emPainting',
|
||||
component: () => import('layouts/electronicMapDrawLayout.vue'),
|
||||
meta: {
|
||||
hidden: true,
|
||||
|
Loading…
Reference in New Issue
Block a user