diff --git a/.env.dev b/.env.dev index 3030631..2198551 100644 --- a/.env.dev +++ b/.env.dev @@ -1,4 +1,4 @@ -API=192.168.3.233:9081 +API=192.168.33.233:9081 HTTP=http:// NS= WS=ws:// diff --git a/package.json b/package.json index 250ca51..b163130 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "centrifuge": "^4.0.1", "dotenv": "^16.3.1", "google-protobuf": "^3.21.2", - "jl-graphic": "git+https://gitea.joylink.club/joylink/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", diff --git a/src/api/AuthApi.ts b/src/api/AuthApi.ts new file mode 100644 index 0000000..3f996fd --- /dev/null +++ b/src/api/AuthApi.ts @@ -0,0 +1,150 @@ +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; + paths: PathItem[]; +} + +/** + * 分页查询角色信息 + * @param params + * @returns + */ +export async function pageQueryRole( + params: PagingQueryParams +): Promise> { + 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 { + const response = await api.get(`${AuthBase}/role/${id}`); + return response.data; +} + +interface LinkRole { + id: number; + roleList: number[]; +} + +/** + * 用户关联角色 + * @param params + * @returns + */ +export async function userLinkRole(params: LinkRole): Promise { + 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> { + const response = await api.get(`${AuthBase}/res/page`, { + params: params, + }); + return response.data; +} + +/** + * 创建接口路径 + * @param data + * @returns + */ +export function createPath(data: Omit) { + 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 { + const response = await api.get(`${AuthBase}/res/${id}`); + return response.data; +} diff --git a/src/api/UserApi.ts b/src/api/UserApi.ts index 2773cbd..b3f09c4 100644 --- a/src/api/UserApi.ts +++ b/src/api/UserApi.ts @@ -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'; // 密码加盐 diff --git a/src/components/AuthData.ts b/src/components/AuthData.ts new file mode 100644 index 0000000..fc0d33e --- /dev/null +++ b/src/components/AuthData.ts @@ -0,0 +1,6 @@ +export enum MethodType { + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', + GET = 'GET', +} diff --git a/src/components/SysMenu.vue b/src/components/SysMenu.vue index e7c75a3..ee26e73 100644 --- a/src/components/SysMenu.vue +++ b/src/components/SysMenu.vue @@ -99,6 +99,16 @@ const list = reactive([ label: '用户管理', icon: 'manage_accounts', }, + { + path: '/sysManage/role', + label: '权限管理', + icon: 'nature_people', + }, + { + path: '/sysManage/authPath', + label: '权限接口管理', + icon: 'menu_open', + }, ], }, ]); diff --git a/src/drawApp/index.ts b/src/drawApp/index.ts index 2592cde..ec8da1a 100644 --- a/src/drawApp/index.ts +++ b/src/drawApp/index.ts @@ -14,6 +14,9 @@ import { IGraphicStorage, ContextMenu, MenuItemOptions, + calculateDistanceFromPointToLine, + distance2, + getRectangleCenter, } from 'jl-graphic'; import { IscsFanData } from './graphics/IscsFanInteraction'; import { LinkData } from './graphics/LinkInteraction'; @@ -296,6 +299,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.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; } diff --git a/src/graphics/axleCounting/AxleCountingDrawAssistant.ts b/src/graphics/axleCounting/AxleCountingDrawAssistant.ts index 519a30d..b1dbfe7 100644 --- a/src/graphics/axleCounting/AxleCountingDrawAssistant.ts +++ b/src/graphics/axleCounting/AxleCountingDrawAssistant.ts @@ -14,12 +14,12 @@ 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'; export interface IAxleCountingDrawOptions { newData: () => IAxleCountingData; @@ -112,14 +112,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.position.set(ps.x, ps.y); axleCounting.id = GraphicIdGenerator.next(); axleCounting.datas.axleCountingRef = [refData2, refData1]; axleCounting.datas.code = `${graphic.datas.code}-${port}+${refGraphic.datas.code}-${refPort}`; @@ -139,14 +132,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.position.set(ps.x, ps.y); axleCounting.id = GraphicIdGenerator.next(); axleCounting.datas.axleCountingRef = [refData]; axleCounting.datas.code = `${graphic.datas.code}-${port}`; @@ -156,9 +142,28 @@ export class AxleCountingDraw extends GraphicDrawAssistant< } oneGenerates(height: Point) { const map = new Map(); - const axleCountings = this.app.queryStore.queryByType( - AxleCounting.Type - ); + const needDelete: AxleCounting[] = []; + const axleCountings = this.app.queryStore + .queryByType(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
( + 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); diff --git a/src/graphics/section/SectionDrawAssistant.ts b/src/graphics/section/SectionDrawAssistant.ts index 8a3ad65..1e84767 100644 --- a/src/graphics/section/SectionDrawAssistant.ts +++ b/src/graphics/section/SectionDrawAssistant.ts @@ -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
{ 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.draggable = false; } } + onDragMove(e: GraphicTransformEvent) { + const section = e.target as Section; + this.app.setOptions({ + absorbablePositions: buildDragMoveAbsorbablePositions(section), + }); + } } diff --git a/src/graphics/turnout/TurnoutDrawAssistant.ts b/src/graphics/turnout/TurnoutDrawAssistant.ts index 1039877..d0492b5 100644 --- a/src/graphics/turnout/TurnoutDrawAssistant.ts +++ b/src/graphics/turnout/TurnoutDrawAssistant.ts @@ -17,6 +17,7 @@ import { AbsorbableLine, ContextMenu, MenuItemOptions, + distance, } from 'jl-graphic'; import { ITurnoutData, @@ -178,6 +179,126 @@ 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.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.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.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.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 +411,7 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin { sectionGraphic.off('rightclick'); }); + g.off('transformstart', this.onDragMove, this); } onSelected(g: DisplayObject) { @@ -327,6 +450,13 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin 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; diff --git a/src/pages/AuthPathManage.vue b/src/pages/AuthPathManage.vue new file mode 100644 index 0000000..8b5361e --- /dev/null +++ b/src/pages/AuthPathManage.vue @@ -0,0 +1,375 @@ + + + diff --git a/src/pages/RoleManage.vue b/src/pages/RoleManage.vue new file mode 100644 index 0000000..67a3779 --- /dev/null +++ b/src/pages/RoleManage.vue @@ -0,0 +1,276 @@ + + + diff --git a/src/pages/UserManage.vue b/src/pages/UserManage.vue index baededd..4ed20d3 100644 --- a/src/pages/UserManage.vue +++ b/src/pages/UserManage.vue @@ -24,16 +24,83 @@ > + + + + + + + +
修改用户角色
+ + + + + + + +
+
+
+
diff --git a/src/router/routes.ts b/src/router/routes.ts index 7ac4b19..e25f7a1 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -70,6 +70,22 @@ 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'), + }, ], }, { diff --git a/yarn.lock b/yarn.lock index 4cede9b..1982a6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2438,9 +2438,9 @@ 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://gitea.joylink.club/joylink/graphic-pixi.git#v0.1.3": - version "0.1.3" - resolved "git+https://gitea.joylink.club/joylink/graphic-pixi.git#100ddafc75ffa2fc646ad26359682e0f083511e3" +"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"