From 8fd76c4b2077b61569a4e2f212087a2fafb2b6df Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Mon, 9 Jun 2025 22:13:03 +0800 Subject: [PATCH] refactor: new resource --- backend/apps/dashboard/api/dashboard_api.py | 16 +++++--- .../apps/dashboard/crud/dashboard_service.py | 41 ++++++++++++++++--- .../apps/dashboard/models/dashboard_model.py | 5 ++- frontend/src/api/dashboard.ts | 3 +- .../dashboard/common/ResourceGroupOpt.vue | 15 ++----- .../views/dashboard/common/ResourceTree.vue | 24 +++++------ .../src/views/dashboard/editor/Toolbar.vue | 2 +- .../src/views/dashboard/utils/canvasUtils.ts | 40 ++++++++++-------- 8 files changed, 93 insertions(+), 53 deletions(-) diff --git a/backend/apps/dashboard/api/dashboard_api.py b/backend/apps/dashboard/api/dashboard_api.py index 9bcd16c6..4d392db4 100644 --- a/backend/apps/dashboard/api/dashboard_api.py +++ b/backend/apps/dashboard/api/dashboard_api.py @@ -1,16 +1,17 @@ +from xmlrpc.client import Boolean from fastapi import APIRouter, File, UploadFile, HTTPException from apps.dashboard.crud.dashboard_service import get_dashboard_list, preview_with_id, \ - create_resource, create_canvas -from apps.dashboard.models.dashboard_model import CreateDashboard,BaseDashboard + create_resource, create_canvas, validate_name +from apps.dashboard.models.dashboard_model import CreateDashboard, BaseDashboard, QueryDashboard from common.core.deps import SessionDep, CurrentUser router = APIRouter(tags=["dashboard"], prefix="/dashboard") @router.post("/list") -async def datasource_list(session: SessionDep): - return get_dashboard_list(session=session) +async def datasource_list(session: SessionDep,dashboard: QueryDashboard): + return get_dashboard_list(session=session,dashboard=dashboard) @router.get("/preview_dashboard/{id}") async def preview_dashboard(session: SessionDep,id:str): @@ -30,4 +31,9 @@ async def add_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDa @router.post("/update_canvas", response_model=BaseDashboard) async def update(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard): - return \ No newline at end of file + return + +@router.post("/check_name") +async def check_name(session: SessionDep, dashboard: QueryDashboard): + return validate_name(session,dashboard) + diff --git a/backend/apps/dashboard/crud/dashboard_service.py b/backend/apps/dashboard/crud/dashboard_service.py index 43df2d32..fe7c703d 100644 --- a/backend/apps/dashboard/crud/dashboard_service.py +++ b/backend/apps/dashboard/crud/dashboard_service.py @@ -1,10 +1,9 @@ -from sqlalchemy import select -from apps.dashboard.models.dashboard_model import CoreDashboard, CreateDashboard +from sqlalchemy import select, and_, text +from apps.dashboard.models.dashboard_model import CoreDashboard, CreateDashboard, QueryDashboard from common.core.deps import SessionDep, CurrentUser -from sqlmodel import text import uuid import datetime -def get_dashboard_list(session: SessionDep): +def get_dashboard_list(session: SessionDep,dashboard: QueryDashboard): sql = text("SELECT id, name, type,node_type, pid, create_time FROM core_dashboard") for row in session.exec(sql).mappings(): yield CoreDashboard(**row) @@ -45,4 +44,36 @@ def create_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashb return record def update_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard): - record = session.query(CoreDashboard).filter(CoreDashboard.id == dashboard.id).first() \ No newline at end of file + record = session.query(CoreDashboard).filter(CoreDashboard.id == dashboard.id).first() + + +def validate_name( session: SessionDep, dashboard: QueryDashboard) -> bool: + if not dashboard.workspace_id: + raise ValueError("workspace_id is required") + if not dashboard.pid: + raise ValueError("pid is required") + if not dashboard.opt: + raise ValueError("opt is required") + + if dashboard.opt in ('newLeaf', 'newFolder'): + query = session.query(CoreDashboard).filter( + and_( + CoreDashboard.workspace_id == dashboard.workspace_id, + CoreDashboard.pid == dashboard.pid, + CoreDashboard.name == dashboard.name + ) + ) + elif dashboard.opt in ('updateLeaf', 'updateFolder'): + if not dashboard.id: + raise ValueError("id is required for update operation") + query = session.query(CoreDashboard).filter( + and_( + CoreDashboard.workspace_id == dashboard.workspace_id, + CoreDashboard.pid == dashboard.pid, + CoreDashboard.name == dashboard.name, + CoreDashboard.id != dashboard.id + ) + ) + else: + raise ValueError(f"Invalid opt value: {dashboard.opt}") + return not session.query(query.exists()).scalar() \ No newline at end of file diff --git a/backend/apps/dashboard/models/dashboard_model.py b/backend/apps/dashboard/models/dashboard_model.py index 30eedec3..80015ee2 100644 --- a/backend/apps/dashboard/models/dashboard_model.py +++ b/backend/apps/dashboard/models/dashboard_model.py @@ -141,9 +141,12 @@ class BaseDashboard(BaseModel): node_type: str = '' create_by: int = 0 +class QueryDashboard(BaseDashboard): + opt: str = '' + # dashboard create obj -class CreateDashboard(BaseDashboard): +class CreateDashboard(QueryDashboard): canvas_style_data: str ='' component_data: str = '' description: str = '' diff --git a/frontend/src/api/dashboard.ts b/frontend/src/api/dashboard.ts index c6e20ef9..8c1eb1e2 100644 --- a/frontend/src/api/dashboard.ts +++ b/frontend/src/api/dashboard.ts @@ -8,5 +8,6 @@ export const dashboardApi = { addResource: (data: any) => request.post('/dashboard/add',data), updateResource: (data: any) => request.post('/dashboard/update',data), saveCanvas: (data: any) => request.post('/dashboard/add_canvas',data), - updateCanvas: (data: any) => request.post('/dashboard/update_',data) + updateCanvas: (data: any) => request.post('/dashboard/update_',data), + check_name: (data: any) => request.post('/dashboard/check_name',data) } \ No newline at end of file diff --git a/frontend/src/views/dashboard/common/ResourceGroupOpt.vue b/frontend/src/views/dashboard/common/ResourceGroupOpt.vue index 78dd22ee..5b6697bd 100644 --- a/frontend/src/views/dashboard/common/ResourceGroupOpt.vue +++ b/frontend/src/views/dashboard/common/ResourceGroupOpt.vue @@ -51,13 +51,11 @@ const optInit = (params: any) => { resourceDialogShow.value = true // @ts-ignore resourceForm.name = params.name || getResourceNewName(params.opt) + resourceForm.pid = params.pid || 'root' } const resourceDialogShow = ref(false) const loading = ref(false) -const pid = ref() -const id = ref() -const opt = ref('') const resourceForm = reactive({ pid: '', pName: '', @@ -101,11 +99,6 @@ const resetForm = () => { resourceDialogShow.value = false } -const editeInit = (param: SQTreeNode) => { - pid.value = param['pid'] - id.value = param.id -} - const propsTree = { label: 'name', children: 'children', @@ -114,7 +107,7 @@ const propsTree = { } const showPid = computed(() => { - return ['newLeaf'].includes(opt.value) && state.parentSelect + return state.opt && ['newLeaf'].includes(state.opt) && state.parentSelect }) const saveResource = () => { @@ -122,6 +115,7 @@ const saveResource = () => { nodeType: state.nodeType, name: resourceForm.name, opt: state.opt, + pid: resourceForm.pid, type: 'dashboard' } saveDashboardResource(params, function (rsp:any) { @@ -147,8 +141,7 @@ const filterMethod = (value: any) => { } defineExpose({ - optInit, - editeInit + optInit }) diff --git a/frontend/src/views/dashboard/common/ResourceTree.vue b/frontend/src/views/dashboard/common/ResourceTree.vue index cc7c2dd0..9ef95446 100644 --- a/frontend/src/views/dashboard/common/ResourceTree.vue +++ b/frontend/src/views/dashboard/common/ResourceTree.vue @@ -205,7 +205,7 @@ onMounted(() => { // @ts-ignore const addOperation = (params: any) => { - if (params.cmd === 'newLeaf') { + if (params.opt === 'newLeaf') { const newCanvasUrl = '#/canvas?opt=create' + (params?.id ? `&pid=${params?.id}` : '') window.open(newCanvasUrl, '_blank') } else { @@ -232,7 +232,7 @@ defineExpose({ @@ -243,7 +243,7 @@ defineExpose({ @@ -303,7 +303,7 @@ defineExpose({ v-on:click.stop v-if="!data.leaf" class="hover-icon" - @click="addOperation({cmd:'newLeaf',type:'dashboard',id:data.id} )" + @click="addOperation({opt:'newLeaf',type:'dashboard',id:data.id} )" > @@ -315,14 +315,14 @@ defineExpose({ > - - - - - - - - + + + + + + + + diff --git a/frontend/src/views/dashboard/editor/Toolbar.vue b/frontend/src/views/dashboard/editor/Toolbar.vue index 8985686a..6a13b39c 100644 --- a/frontend/src/views/dashboard/editor/Toolbar.vue +++ b/frontend/src/views/dashboard/editor/Toolbar.vue @@ -40,7 +40,7 @@ const props = defineProps({ const groupOptFinish = (result: any) => { let url = window.location.href - url = url.replace(/(#\/[^?]*)(?:\?[^#]*)?/, `$1?dvId=${result.id}`) + url = url.replace(/(#\/[^?]*)(?:\?[^#]*)?/, `$1?resourceId=${result.resourceId}`) window.history.replaceState( { path: url }, '', url ) } diff --git a/frontend/src/views/dashboard/utils/canvasUtils.ts b/frontend/src/views/dashboard/utils/canvasUtils.ts index f57d4f5c..e0e4da6b 100644 --- a/frontend/src/views/dashboard/utils/canvasUtils.ts +++ b/frontend/src/views/dashboard/utils/canvasUtils.ts @@ -1,9 +1,11 @@ import {dashboardApi} from "@/api/dashboard.ts"; import {dashboardStoreWithOut} from "@/stores/dashboard/dashboard.ts"; import {storeToRefs} from "pinia"; -const dashboardStore = dashboardStoreWithOut() -const {componentData,canvasStyle} = storeToRefs(dashboardStore) +const dashboardStore = dashboardStoreWithOut() +const {componentData, canvasStyle} = storeToRefs(dashboardStore) + +const workspace_id = 'default' // temp export const initCanvasData = (params: any, callBack: Function) => { dashboardApi.getDashboardInfo(params).then((res: any) => { const canvasInfo = res.data; @@ -28,20 +30,24 @@ export const initCanvasData = (params: any, callBack: Function) => { } export const saveDashboardResource = (params: any, callBack: Function) => { - if(params.opt === 'newLeaf'){// create canvas - const reqeustParams = { - ...params, - component_data:JSON.stringify(componentData.value), - canvas_style_data:JSON.stringify(canvasStyle.value) + params['workspace_id'] = workspace_id + dashboardApi.check_name(params).then((res: any) => { + if (!res) { + if (params.opt === 'newLeaf') {// create canvas + const reqeustParams = { + ...params, + component_data: JSON.stringify(componentData.value), + canvas_style_data: JSON.stringify(canvasStyle.value) + } + dashboardApi.saveCanvas(reqeustParams).then((res: any) => { + dashboardStore.updateDashboardInfo({id: res.id, dataState: 'ready'}) + callBack(res) + }) + } else if (params.opt === 'newFolder') { + dashboardApi.addResource(params).then((res: any) => { + callBack(res) + }) + } } - dashboardApi.saveCanvas(reqeustParams).then((res: any) => { - dashboardStore.updateDashboardInfo({id:res.id,dataState:'ready'}) - callBack(res) - }) - }else if(params.opt === 'newFolder'){ - dashboardApi.addResource(params).then((res: any) => { - callBack(res) - }) - } - + }) } \ No newline at end of file