refactor: snapshot

This commit is contained in:
wangjiahao
2025-06-10 17:58:37 +08:00
parent 3217546b87
commit 344027c833
25 changed files with 566 additions and 112 deletions
+21 -20
View File
@@ -1,39 +1,40 @@
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, validate_name
from apps.dashboard.crud.dashboard_service import list_resource, load_resource, \
create_resource, create_canvas, validate_name,delete_resource,update_resource
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,dashboard: QueryDashboard):
return get_dashboard_list(session=session,dashboard=dashboard)
@router.post("/list_resource")
async def list_resource_api(session: SessionDep,dashboard: QueryDashboard):
return list_resource(session=session,dashboard=dashboard)
@router.get("/preview_dashboard/{id}")
async def preview_dashboard(session: SessionDep,id:str):
return preview_with_id(session=session,dashboard_id=id)
@router.post("/load_resource")
async def load_resource_api(session: SessionDep,dashboard: QueryDashboard):
return load_resource(session=session,dashboard=dashboard)
@router.post("/add", response_model=BaseDashboard)
async def add(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
@router.post("/create_resource", response_model=BaseDashboard)
async def create_resource_api(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
return create_resource(session, user, dashboard)
@router.post("/update", response_model=BaseDashboard)
async def update(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
return create_resource(session, user, dashboard)
@router.post("/add_canvas", response_model=BaseDashboard)
async def add_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
@router.post("/update_resource", response_model=BaseDashboard)
async def update_resource_api(session: SessionDep, user: CurrentUser, dashboard: QueryDashboard):
return update_resource(session=session, user=user, dashboard=dashboard)
@router.delete("/delete_resource/{resource_id}")
async def delete_resource_api(session: SessionDep,resource_id:str):
return delete_resource(session,resource_id)
@router.post("/create_canvas", response_model=BaseDashboard)
async def create_canvas_api(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
return create_canvas(session, user, dashboard)
@router.post("/update_canvas", response_model=BaseDashboard)
async def update(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
async def update_canvas_api(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
return
@router.post("/check_name")
async def check_name(session: SessionDep, dashboard: QueryDashboard):
async def check_name_api(session: SessionDep, dashboard: QueryDashboard):
return validate_name(session,dashboard)
@@ -1,23 +1,42 @@
from sqlalchemy import select, and_, text
from apps.dashboard.models.dashboard_model import CoreDashboard, CreateDashboard, QueryDashboard
from apps.dashboard.models.dashboard_model import CoreDashboard, CreateDashboard, QueryDashboard,DashboardBaseResponse
from common.core.deps import SessionDep, CurrentUser
import uuid
import datetime
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)
import time
from common.utils.tree_utils import build_tree_generic
def list_resource(session: SessionDep, dashboard: QueryDashboard):
sql = "SELECT id, name, type, node_type, pid, create_time FROM core_dashboard"
filters = []
params = {}
if dashboard.node_type is not None and dashboard.node_type != "":
filters.append("node_type = :node_type")
params["node_type"] = dashboard.node_type
if filters:
sql += " WHERE " + " AND ".join(filters)
result = session.execute(text(sql), params)
nodes = [DashboardBaseResponse(**row) for row in result.mappings()]
tree = build_tree_generic(nodes, root_pid="root")
return tree
def load_resource(session: SessionDep,dashboard: QueryDashboard):
return session.query(CoreDashboard).filter(CoreDashboard.id == dashboard.id).first()
def preview_with_id(session: SessionDep, dashboard_id: str):
return session.query(CoreDashboard).filter(CoreDashboard.id == id).first()
def get_create_base_info(user: CurrentUser, dashboard: CreateDashboard):
new_id = uuid.uuid4().hex
record = CoreDashboard(**dashboard.model_dump())
record.id = new_id
record.create_by = user.id
record.create_time = int(time.time())
return record
def create_resource(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
record = get_create_base_info(user, dashboard)
session.add(record)
@@ -26,13 +45,15 @@ def create_resource(session: SessionDep, user: CurrentUser, dashboard: CreateDas
session.commit()
return record
def update_resource(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
def update_resource(session: SessionDep, user: CurrentUser, dashboard: QueryDashboard):
record = session.query(CoreDashboard).filter(CoreDashboard.id == dashboard.id).first()
record.name = dashboard.name
record.update_by = user.id
record.update_time = datetime.datetime.now()
record.update_time = int(time.time())
session.add(record)
session.commit()
return record
def create_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
record = get_create_base_info(user, dashboard)
@@ -41,13 +62,16 @@ def create_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashb
record.canvas_style_data = dashboard.canvas_style_data
session.add(record)
session.flush()
session.refresh(record)
session.commit()
return record
def update_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
record = session.query(CoreDashboard).filter(CoreDashboard.id == dashboard.id).first()
def validate_name( session: SessionDep, dashboard: QueryDashboard) -> bool:
def validate_name(session: SessionDep, dashboard: QueryDashboard) -> bool:
if not dashboard.workspace_id:
raise ValueError("workspace_id is required")
if not dashboard.pid:
@@ -63,7 +87,7 @@ def validate_name( session: SessionDep, dashboard: QueryDashboard) -> bool:
CoreDashboard.name == dashboard.name
)
)
elif dashboard.opt in ('updateLeaf', 'updateFolder'):
elif dashboard.opt in ('updateLeaf', 'updateFolder', 'rename'):
if not dashboard.id:
raise ValueError("id is required for update operation")
query = session.query(CoreDashboard).filter(
@@ -76,4 +100,11 @@ def validate_name( session: SessionDep, dashboard: QueryDashboard) -> bool:
)
else:
raise ValueError(f"Invalid opt value: {dashboard.opt}")
return not session.query(query.exists()).scalar()
return not session.query(query.exists()).scalar()
def delete_resource(session: SessionDep, resource_id: str):
sql = text("DELETE FROM core_dashboard WHERE id = :resource_id")
result = session.execute(sql, {"resource_id": resource_id})
session.commit()
return result.rowcount > 0
@@ -1,6 +1,6 @@
from sqlmodel import SQLModel, Field
from sqlalchemy import String, Column, Text, SmallInteger, BigInteger, Integer,DateTime
from typing import Optional
from typing import Optional, List
from pydantic import BaseModel
class CoreDashboard(SQLModel, table=True):
@@ -127,9 +127,11 @@ class DashboardBaseResponse(BaseModel):
name: Optional[str] = None
pid: Optional[str] = None
node_type: Optional[str] = None
leaf: Optional[bool] = False
type: Optional[str] = None
create_time: Optional[int] = None
update_time: Optional[int] = None
children: List['DashboardBaseResponse'] = []
class BaseDashboard(BaseModel):
id: str = ''
@@ -139,6 +141,7 @@ class BaseDashboard(BaseModel):
org_id: str = ''
type: str = ''
node_type: str = ''
level: int = 0
create_by: int = 0
class QueryDashboard(BaseDashboard):
+22
View File
@@ -0,0 +1,22 @@
from typing import List, Optional, Dict, TypeVar, Protocol, Any
from pydantic import BaseModel
class ITreeNode(Protocol):
id: Optional[str]
pid: Optional[str]
children: List['ITreeNode']
T = TypeVar('T', bound=ITreeNode)
def build_tree_generic(nodes: List[T], root_pid: Any = None) -> List[T]:
node_dict: Dict[str, T] = {node.id: node for node in nodes if node.id is not None}
tree: List[T] = []
for node in nodes:
if node.pid == root_pid:
tree.append(node)
elif node.pid in node_dict:
node_dict[node.pid].children.append(node)
return tree
+1
View File
@@ -13,6 +13,7 @@
"@npkg/tinymce-plugins": "^0.0.7",
"@tinymce/tinymce-vue": "^5.1.0",
"dayjs": "^1.11.13",
"element-plus": "^2.10.1",
"element-plus-secondary": "^1.0.0",
"lodash": "^4.17.21",
"snowflake-id": "^1.1.0",
+9 -9
View File
@@ -1,13 +1,13 @@
import { request } from '@/utils/request'
export const dashboardApi = {
list: (params: any) => request.post('/dashboard/list',params),
getDashboardInfo: (params:any) => request.post(`/dashboard/get_dashboard/${params.id}`,params),
sqNameCheck: (data: any) => request.post('/dashboard/name_check',data),
moveResource: (data: any) => request.post('/dashboard/move',data),
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),
check_name: (data: any) => request.post('/dashboard/check_name',data)
list_resource: (params: any) => request.post('/dashboard/list_resource',params),
load_resource: (params:any) => request.post('/dashboard/load_resource',params),
create_resource: (params: any) => request.post('/dashboard/create_resource',params),
update_resource: (params: any) => request.post('/dashboard/update_resource',params),
create_canvas: (params: any) => request.post('/dashboard/create_canvas',params),
update_canvas: (params: any) => request.post('/dashboard/update_canvas',params),
check_name: (params: any) => request.post('/dashboard/check_name',params),
delete_resource: (params: any) => request.delete(`/dashboard/delete_resource/${params.id}`,params),
move_resource: (params: any) => request.delete(`/dashboard/move_resource/${params.id}`,params),
}
+1 -1
View File
@@ -1 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1621433652678" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2364" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M930.668 386.638c-16.798 0-30.422-13.62-30.422-30.422V175.75c0-13.782-11.216-24.994-24.998-24.994H574.898c-16.798 0-30.422-13.62-30.422-30.422s13.622-30.422 30.422-30.422h300.352c47.334 0 85.842 38.508 85.842 85.838v180.466c-0.002 16.802-13.624 30.422-30.424 30.422z" p-id="2365"></path><path d="M941.828 965.542H82.172C36.862 965.542 0 928.682 0 883.372V143.92c0-47.124 38.338-85.462 85.462-85.462h251.608c47.124 0 85.462 38.338 85.462 85.462v74.936h519.298c45.31 0 82.172 36.862 82.172 82.17 0 16.802-13.622 30.422-30.422 30.422s-30.422-13.62-30.422-30.422c0-11.758-9.568-21.326-21.328-21.326h-549.72c-16.798 0-30.422-13.62-30.422-30.422V143.92c0-13.574-11.044-24.618-24.618-24.618H85.462c-13.574 0-24.618 11.044-24.618 24.618v739.452c0 11.758 9.568 21.326 21.328 21.326h859.654c16.798 0 30.422 13.62 30.422 30.422 0.002 16.802-13.622 30.422-30.42 30.422z" p-id="2366"></path><path d="M993.576 769.22V301.028c0-28.578-23.17-51.748-51.748-51.748h-549.72V143.92c0-30.398-24.642-55.04-55.04-55.04H85.462c-30.398 0-55.04 24.642-55.04 55.04v625.304h963.154v-0.004z" p-id="2367"></path><path d="M993.578 799.642H30.422c-16.8 0-30.422-13.62-30.422-30.422V143.92c0-47.124 38.338-85.462 85.462-85.462h251.608c47.124 0 85.462 38.338 85.462 85.462v74.936h519.298c45.31 0 82.172 36.862 82.172 82.17v468.192c-0.002 16.804-13.624 30.424-30.424 30.424zM60.844 738.798h902.312V301.028c0-11.758-9.568-21.326-21.328-21.326h-549.72c-16.798 0-30.422-13.62-30.422-30.422V143.92c0-13.574-11.044-24.618-24.618-24.618H85.462c-13.574 0-24.618 11.044-24.618 24.618v594.878z" p-id="2368"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1621433652678" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2364" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M930.668 386.638c-16.798 0-30.422-13.62-30.422-30.422V175.75c0-13.782-11.216-24.994-24.998-24.994H574.898c-16.798 0-30.422-13.62-30.422-30.422s13.622-30.422 30.422-30.422h300.352c47.334 0 85.842 38.508 85.842 85.838v180.466c-0.002 16.802-13.624 30.422-30.424 30.422z" p-id="2365"></path><path d="M941.828 965.542H82.172C36.862 965.542 0 928.682 0 883.372V143.92c0-47.124 38.338-85.462 85.462-85.462h251.608c47.124 0 85.462 38.338 85.462 85.462v74.936h519.298c45.31 0 82.172 36.862 82.172 82.17 0 16.802-13.622 30.422-30.422 30.422s-30.422-13.62-30.422-30.422c0-11.758-9.568-21.326-21.328-21.326h-549.72c-16.798 0-30.422-13.62-30.422-30.422V143.92c0-13.574-11.044-24.618-24.618-24.618H85.462c-13.574 0-24.618 11.044-24.618 24.618v739.452c0 11.758 9.568 21.326 21.328 21.326h859.654c16.798 0 30.422 13.62 30.422 30.422 0.002 16.802-13.622 30.422-30.42 30.422z" p-id="2366"></path><path d="M993.576 769.22V301.028c0-28.578-23.17-51.748-51.748-51.748h-549.72V143.92c0-30.398-24.642-55.04-55.04-55.04H85.462c-30.398 0-55.04 24.642-55.04 55.04v625.304h963.154v-0.004z" p-id="2367"></path><path d="M993.578 799.642H30.422c-16.8 0-30.422-13.62-30.422-30.422V143.92c0-47.124 38.338-85.462 85.462-85.462h251.608c47.124 0 85.462 38.338 85.462 85.462v74.936h519.298c45.31 0 82.172 36.862 82.172 82.17v468.192c-0.002 16.804-13.624 30.424-30.424 30.424zM60.844 738.798h902.312V301.028c0-11.758-9.568-21.326-21.328-21.326h-549.72c-16.798 0-30.422-13.62-30.422-30.422V143.92c0-13.574-11.044-24.618-24.618-24.618H85.462c-13.574 0-24.618 11.044-24.618 24.618v594.878z" p-id="2368"></path></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M5.33301 2.66732V2.00065C5.33301 1.63246 5.63148 1.33398 5.99967 1.33398H9.99967C10.3679 1.33398 10.6663 1.63246 10.6663 2.00065V2.66732H14.239C14.3876 2.66732 14.4415 2.68279 14.4958 2.71184C14.5501 2.74089 14.5928 2.78352 14.6218 2.83784C14.6509 2.89216 14.6663 2.94605 14.6663 3.09463V3.57334C14.6663 3.72192 14.6509 3.7758 14.6218 3.83013C14.5928 3.88445 14.5501 3.92708 14.4958 3.95613C14.4415 3.98518 14.3876 4.00065 14.239 4.00065H13.333V14.0007C13.333 14.3688 13.0345 14.6673 12.6663 14.6673H3.33301C2.96482 14.6673 2.66634 14.3688 2.66634 14.0007V4.00065H1.76032C1.61174 4.00065 1.55785 3.98518 1.50353 3.95613C1.44921 3.92708 1.40658 3.88445 1.37753 3.83013C1.34848 3.7758 1.33301 3.72192 1.33301 3.57334V3.09463C1.33301 2.94605 1.34848 2.89216 1.37753 2.83784C1.40658 2.78352 1.44921 2.74089 1.50353 2.71184C1.55785 2.68279 1.61174 2.66732 1.76032 2.66732H5.33301ZM3.99967 4.00065V13.334H11.9997V4.00065H3.99967ZM6.33301 5.33398H6.99967C7.18377 5.33398 7.33301 5.48322 7.33301 5.66732V11.6673C7.33301 11.8514 7.18377 12.0007 6.99967 12.0007H6.33301C6.14891 12.0007 5.99967 11.8514 5.99967 11.6673V5.66732C5.99967 5.48322 6.14891 5.33398 6.33301 5.33398ZM8.99967 5.33398H9.66634C9.85044 5.33398 9.99967 5.48322 9.99967 5.66732V11.6673C9.99967 11.8514 9.85044 12.0007 9.66634 12.0007H8.99967C8.81558 12.0007 8.66634 11.8514 8.66634 11.6673V5.66732C8.66634 5.48322 8.81558 5.33398 8.99967 5.33398Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12.2824 5.61836L14.2971 7.63301L15.7917 6.13697L13.7686 4.10319L12.2824 5.61836ZM12.8836 9.04793L10.8819 7.04629L4.03252 14.0296V14.0327L5.96748 15.9676H5.97053L12.8836 9.04793ZM17.5636 7.23777L17.5702 7.24403L6.81402 18.0001H3C2.44772 18.0001 2 17.5524 2 17.0001V13.1861L12.3894 2.71678L12.3796 2.70688L13.0848 2.00163C13.4753 1.61111 14.1085 1.61111 14.499 2.00163L14.5009 2.00349L17.9351 5.45575C18.3238 5.84657 18.323 6.47831 17.9332 6.86811L17.5636 7.23777ZM2.5 20.0002H21.5C21.7761 20.0002 22 20.224 22 20.5002V21.5002C22 21.7763 21.7761 22.0002 21.5 22.0002H2.5C2.22386 22.0002 2 21.7763 2 21.5002V20.5002C2 20.224 2.22386 20.0002 2.5 20.0002Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 755 B

After

Width:  |  Height:  |  Size: 732 B

@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M18 10.5L20 10.5C20.0657 10.5 20.1307 10.5129 20.1913 10.5381C20.252 10.5632 20.3071 10.6 20.3536 10.6464C20.4 10.6929 20.4368 10.748 20.4619 10.8087C20.4871 10.8693 20.5 10.9343 20.5 11L20.5 13C20.5 13.0657 20.4871 13.1307 20.4619 13.1913C20.4368 13.252 20.4 13.3071 20.3536 13.3536C20.3071 13.4 20.252 13.4368 20.1913 13.4619C20.1307 13.4871 20.0657 13.5 20 13.5L18 13.5C17.8674 13.5 17.7402 13.4473 17.6464 13.3536C17.5527 13.2598 17.5 13.1326 17.5 13L17.5 11C17.5 10.9343 17.5129 10.8693 17.5381 10.8087C17.5632 10.748 17.6 10.6929 17.6464 10.6464C17.6929 10.6 17.748 10.5632 17.8087 10.5381C17.8693 10.5129 17.9343 10.5 18 10.5ZM4 10.5L6 10.5C6.06566 10.5 6.13068 10.5129 6.19134 10.5381C6.252 10.5632 6.30712 10.6 6.35355 10.6464C6.39998 10.6929 6.43681 10.748 6.46194 10.8087C6.48707 10.8693 6.5 10.9343 6.5 11L6.5 13C6.5 13.1326 6.44732 13.2598 6.35355 13.3536C6.25979 13.4473 6.13261 13.5 6 13.5L4 13.5C3.93434 13.5 3.86932 13.4871 3.80866 13.4619C3.748 13.4368 3.69288 13.4 3.64645 13.3536C3.60002 13.3071 3.56319 13.252 3.53806 13.1913C3.51293 13.1307 3.5 13.0657 3.5 13L3.5 11C3.5 10.9343 3.51293 10.8693 3.53806 10.8087C3.56319 10.748 3.60002 10.6929 3.64645 10.6464C3.69288 10.6 3.748 10.5632 3.80866 10.5381C3.86932 10.5129 3.93434 10.5 4 10.5ZM11 10.5L13 10.5C13.0657 10.5 13.1307 10.5129 13.1913 10.5381C13.252 10.5632 13.3071 10.6 13.3536 10.6464C13.4 10.6929 13.4368 10.748 13.4619 10.8087C13.4871 10.8693 13.5 10.9343 13.5 11L13.5 13C13.5 13.0657 13.4871 13.1307 13.4619 13.1913C13.4368 13.252 13.4 13.3071 13.3536 13.3536C13.3071 13.4 13.252 13.4368 13.1913 13.4619C13.1307 13.4871 13.0657 13.5 13 13.5L11 13.5C10.8674 13.5 10.7402 13.4473 10.6464 13.3536C10.5527 13.2598 10.5 13.1326 10.5 13L10.5 11C10.5 10.9343 10.5129 10.8693 10.5381 10.8087C10.5632 10.748 10.6 10.6929 10.6464 10.6464C10.6929 10.6 10.748 10.5632 10.8087 10.5381C10.8693 10.5129 10.9343 10.5 11 10.5Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,3 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M11.0036 1.80702L14.272 5.07542C14.4108 5.21428 14.4108 5.4394 14.272 5.57826L10.6893 9.16093C10.5505 9.29978 10.3253 9.29978 10.1865 9.16093L9.7465 8.72095C9.60765 8.5821 9.60765 8.35698 9.7465 8.21812L12.1858 5.77755L6.44444 5.77783C4.60349 5.77783 3.1111 7.27021 3.1111 9.11116C3.1111 10.9521 4.60349 12.4445 6.44444 12.4445H8.97777C9.17414 12.4445 9.33333 12.6037 9.33333 12.8V13.4223C9.33333 13.6186 9.17414 13.7778 8.97777 13.7778H6.22222C3.74827 13.6568 1.77777 11.6141 1.77777 9.11116C1.77777 6.6082 3.74827 4.56548 6.22259 4.44967L6.22222 4.44449L11.7555 4.44421L10.0608 2.74983C9.92192 2.61098 9.92192 2.38585 10.0608 2.247L10.5008 1.80702C10.6396 1.66817 10.8647 1.66817 11.0036 1.80702Z"/>
</svg>

After

Width:  |  Height:  |  Size: 779 B

+4
View File
@@ -0,0 +1,4 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M5.35433 11.2497H7.625L14.379 4.49545C14.6111 4.26338 14.6116 3.88728 14.3801 3.65461L12.3345 1.5982C12.102 1.3657 11.7251 1.3657 11.4926 1.5982L11.0727 2.01807L11.0743 2.01972L4.75898 8.38366V10.6543C4.75898 10.9831 5.02553 11.2497 5.35433 11.2497ZM11.8947 2.84436L13.1003 4.05637L12.0801 5.07763L10.8806 3.87821L11.8947 2.84436ZM11.2385 5.91999L7.12283 10.0396H7.12102L5.96904 8.88583L10.0468 4.72831L11.2385 5.91999Z"/>
<path d="M8.76346 2.31685H2.44373C2.07839 2.31685 1.78223 2.61301 1.78223 2.97835V13.5623C1.78223 13.9277 2.07839 14.2238 2.44373 14.2238H13.0277C13.393 14.2238 13.6892 13.9277 13.6892 13.5623V7.16226L12.3579 8.50157V12.899H3.11347V3.64166H7.46273L8.76346 2.31685Z"/>
</svg>

After

Width:  |  Height:  |  Size: 769 B

@@ -0,0 +1,3 @@
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M6.43791 2.26348L2.3524 6.34898C2.17884 6.52255 2.17884 6.80395 2.3524 6.97752L6.83075 11.4559C7.00431 11.6294 7.28572 11.6294 7.45929 11.4559L8.00926 10.9059C8.18283 10.7323 8.18283 10.4509 8.00926 10.2774L4.9589 7.22552L12.2222 7.22219V7.22698C14.5234 7.22698 16.3889 9.09246 16.3889 11.3937C16.3889 13.6948 14.5234 15.5603 12.2222 15.5603V15.5555L8.9696 15.5597C8.72436 15.5601 8.52573 15.759 8.52573 16.0042V16.782C8.52573 16.9967 8.67808 17.1759 8.8806 17.2174L8.97075 17.2264L12 17.2214L12.2222 17.227C15.4439 17.227 18.0556 14.6153 18.0556 11.3937C18.0556 8.17199 15.4439 5.56032 12.2222 5.56032V5.55552L5.4989 5.55886L7.61642 3.44199C7.78999 3.26842 7.78999 2.98701 7.61642 2.81345L7.06645 2.26348C6.89288 2.08991 6.61148 2.08991 6.43791 2.26348Z"/>
</svg>

After

Width:  |  Height:  |  Size: 836 B

+12
View File
@@ -10,5 +10,17 @@
"confirm": "Confirm",
"cancel": "Cancel",
"system_manage": "System Management"
},
"dashboard": {
"length_1_64_characters": "Name field length must be 1-64 characters",
"rename": "Rename",
"delete": "Delete",
"delete_tips": "All resources in this folder will be deleted after deletion. Please proceed with caution.",
"undo": "Undo",
"reduction": "Restore",
"folder": "Folder",
"dashboard": "Dashboard",
"delete_warning": "Are you sure you want to delete?",
"delete_success": "Successfully deleted"
}
}
+12
View File
@@ -10,5 +10,17 @@
"confirm": "确认",
"cancel": "取消",
"system_manage": "系统管理"
},
"dashboard": {
"length_1_64_characters": "名称字段长度1-64个字符",
"rename": "重命名",
"delete": "删除",
"delete_tips": "删除后,此目录的所有资源都会被删除,请谨慎操作。",
"undo": "撤销",
"reduction": "恢复",
"folder": "目录",
"dashboard": "仪表板",
"delete_warning": "确定要删除吗?",
"delete_success": "删除成功"
}
}
+8 -3
View File
@@ -8,9 +8,11 @@ export const dashboardStore = defineStore('dashboard', {
tabMoveInActiveId: null,
curComponent: null,
curComponentId: null,
canvasStyle: {},
canvasStyleData: {},
componentData: [],
canvasViewInfo: {},
fullscreenFlag: false,
dataPrepareState: false,
dashboardInfo: {
id: null,
name: null,
@@ -43,8 +45,8 @@ export const dashboardStore = defineStore('dashboard', {
setComponentData(value: any) {
this.componentData = value
},
setCanvasStyle(value: any) {
this.canvasStyle = value
setCanvasStyleData(value: any) {
this.canvasStyleData = value
},
setTabCollisionActiveId(tabId: any) {
this.tabCollisionActiveId = tabId
@@ -58,6 +60,9 @@ export const dashboardStore = defineStore('dashboard', {
this.dashboardInfo[key] = params[key]
})
},
setCanvasViewInfo(params: any) {
this.canvasViewInfo = params
},
canvasDataInit() {
}
+149
View File
@@ -0,0 +1,149 @@
import {defineStore, storeToRefs} from 'pinia'
import _ from 'lodash'
import {dashboardStoreWithOut} from "@/stores/dashboard/dashboard.ts";
import {store} from "@/stores";
const dashboardStore = dashboardStoreWithOut()
const {
dashboardInfo,
componentData,
canvasStyleData,
canvasViewInfo,
dataPrepareState
} = storeToRefs(dashboardStore)
let defaultCanvasInfo = {
componentData: [],
canvasStyleData: {},
canvasViewInfo: {},
cacheViewIdInfo: {
snapshotCacheViewCalc: [],
snapshotCacheViewRender: []
}
}
// Storage snapshot structure {componentData:[],canvasStyleData:{},canvasViewInfo:{}}
export const snapshotStore = defineStore('snapshot', {
state: () => {
return {
snapshotDisableTime: 1, // Snapshot disable time (resolves style changes caused by redo/undo)
styleChangeTimes: -1, // Component style modification count
cacheStyleChangeTimes: 0, // Unsaved component style modification count in the dashboard
snapshotCacheTimes: 0, // Current unsnapshot modification count (timed cache, cached every 5 seconds; used for minor changes like style adjustments)
snapshotData: [], // Editor snapshot data
snapshotIndex: -1 // Snapshot index
}
},
actions: {
initSnapShot() {
this.styleChangeTimes = -1
this.cacheStyleChangeTimes = 0
this.snapshotCacheTimes = 0
this.snapshotData = []
this.snapshotIndex = -1
},
//Regularly check the number of changes, and if there are any changes, perform mirroring processing
snapshotCatchToStore() {
if (this.snapshotCacheTimes) {
this.recordSnapshot()
}
},
recordSnapshotCache() {
if (dataPrepareState.value) {
this.snapshotCacheTimes++
}
},
undo() {
if (this.snapshotIndex > 0) {
this.snapshotIndex--
const componentSnapshot = _.cloneDeep(this.snapshotData[this.snapshotIndex]) || getDefaultCanvasInfo()
// @ts-ignore
componentSnapshot.dashboardInfo.id = dashboardInfo.value.id
// @ts-ignore
componentSnapshot.dashboardInfo.pid = dashboardInfo.value.pid
// @ts-ignore
componentSnapshot.dashboardInfo.dataState = dashboardInfo.value.dataState
// @ts-ignore
componentSnapshot.dashboardInfo.contentId = dashboardInfo.value.contentId
this.snapshotPublish(componentSnapshot)
this.styleChangeTimes++
this.snapshotDisableTime = Date.now() + 3000
dashboardStore.setCurComponent(null)
}
},
redo() {
if (this.snapshotIndex < this.snapshotData.length - 1) {
this.snapshotIndex++
const snapshotInfo = _.cloneDeep(this.snapshotData[this.snapshotIndex])
// @ts-ignore
snapshotInfo.dashboardInfo.id = dashboardInfo.value.id
// @ts-ignore
snapshotInfo.dashboardInfo.pid = dashboardInfo.value.pid
// @ts-ignore
snapshotInfo.dashboardInfo.dataState = dashboardInfo.value.dataState
// @ts-ignore
snapshotInfo.dashboardInfo.contentId = dashboardInfo.value.contentId
this.snapshotPublish(snapshotInfo)
this.styleChangeTimes++
this.snapshotDisableTime = Date.now() + 3000
dashboardStore.setCurComponent(null)
}
},
snapshotPublish(snapshotInfo: any) {
dashboardStore.updateDashboardInfo(snapshotInfo.dashboardInfo)
dashboardStore.setComponentData(snapshotInfo.componentData)
dashboardStore.setCanvasStyleData(snapshotInfo.canvasStyleData)
dashboardStore.setCanvasViewInfo(snapshotInfo.canvasViewInfo)
},
resetStyleChangeTimes() {
this.styleChangeTimes = 0
this.snapshotCacheTimes = 0
},
resetSnapshot() {
this.styleChangeTimes = -1
this.cacheStyleChangeTimes = 0
this.snapshotCacheTimes = 0
this.snapshotData = []
this.snapshotIndex = -1
this.recordSnapshot()
},
recordSnapshot() {
if (dataPrepareState.value) {
this.styleChangeTimes = ++this.styleChangeTimes
// Add a new snapshot
// @ts-ignore
this.snapshotData[++this.snapshotIndex] = {
componentData: _.cloneDeep(componentData.value),
canvasStyleData: _.cloneDeep(canvasStyleData.value),
canvasViewInfo: _.cloneDeep(canvasViewInfo.value),
dashboardInfo: _.cloneDeep(dashboardInfo.value)
}
// During the undo process, when adding a new snapshot, the snapshots following it should be cleaned up
if (this.snapshotIndex < this.snapshotData.length - 1) {
this.snapshotData = this.snapshotData.slice(0, this.snapshotIndex + 1)
}
// Clean up cache counters
this.snapshotCacheTimes = 0
}
}
}
})
export function setDefaultComponentData(data = []) {
defaultCanvasInfo.componentData = data
}
function getDefaultCanvasInfo() {
return defaultCanvasInfo
}
export function setDefaultCanvasInfo(data: any) {
defaultCanvasInfo = data
}
export const snapshotStoreWithOut = () => {
return snapshotStore(store)
}
@@ -3,8 +3,12 @@ import folder from '@/assets/svg/folder.svg'
import {type SQTreeNode} from '@/views/dashboard/utils/treeNode'
import {ref, reactive, computed} from 'vue'
import {saveDashboardResource} from "@/views/dashboard/utils/canvasUtils.ts";
import {dashboardApi} from "@/api/dashboard.ts";
import _ from "lodash";
const emits = defineEmits(['finish'])
const state = reactive({
id: null,
opt: null,
placeholder: '',
nodeType: 'folder',
@@ -12,19 +16,20 @@ const state = reactive({
resourceFormNameLabel: 'Name',
dialogTitle: '',
tData: [],
tDataSource: [],
nameList: [],
targetInfo: null,
attachParams: null
})
let tData: any = []
const getTitle = (opt: string) => {
switch (opt) {
case 'newLeaf':
return 'New Dashboard'
case 'newFolder':
return 'New Folder'
case 'rename':
return 'Rename'
default:
return
}
@@ -41,10 +46,19 @@ const getResourceNewName = (opt: string) => {
}
}
const getTree = async () => {
const params = {node_type: 'folder'}
dashboardApi.list_resource(params).then((res) => {
state.tData = res || []
state.tDataSource = [...state.tData]
})
}
const optInit = (params: any) => {
// @ts-ignore
state.dialogTitle = getTitle(params.opt)
state.opt = params.opt
state.id = params.id
state.parentSelect = params.parentSelect
state.targetInfo = params.data
state.nodeType = params.nodeType || 'folder'
@@ -52,11 +66,15 @@ const optInit = (params: any) => {
// @ts-ignore
resourceForm.name = params.name || getResourceNewName(params.opt)
resourceForm.pid = params.pid || 'root'
if (params.parentSelect) {
getTree()
}
}
const resourceDialogShow = ref(false)
const loading = ref(false)
const resourceForm = reactive({
id: null,
pid: '',
pName: '',
name: 'New Dashboard'
@@ -100,6 +118,7 @@ const resetForm = () => {
}
const propsTree = {
value: 'id',
label: 'name',
children: 'children',
// @ts-ignore
@@ -112,20 +131,21 @@ const showPid = computed(() => {
const saveResource = () => {
const params = {
nodeType: state.nodeType,
id: state.id,
node_type: state.nodeType,
name: resourceForm.name,
opt: state.opt,
pid: resourceForm.pid,
type: 'dashboard'
type: 'dashboard',
level: state.nodeType === 'folder' ? 0 : 1,
}
saveDashboardResource(params, function (rsp:any) {
saveDashboardResource(params, function (rsp: any) {
const messageTips = state.opt === 'rename' ? 'Update Success' : 'Save Success'
ElMessage({
type: 'success',
message: 'Save Success',
message: messageTips,
})
if (state.opt === 'newLeaf') {
emits('finish', {opt: state.opt, resourceId: rsp.id})
}
emits('finish', {opt: state.opt, resourceId: rsp.id})
resetForm()
})
}
@@ -137,7 +157,7 @@ const nodeClick = (data: SQTreeNode) => {
const filterMethod = (value: any) => {
// @ts-ignore
state.tData = [...tData].filter(item => item.name.includes(value))
state.tData = state.tDataSource.filter(item => item.name.includes(value))
}
defineExpose({
@@ -187,7 +207,7 @@ defineExpose({
<template #default="{ data: { name } }">
<span class="custom-tree-node">
<el-icon>
<Icon name="dv-folder"><folder class="svg-icon"/></Icon>
<Icon name="dv-folder"><folder class="svg-icon custom-tree-folder"/></Icon>
</el-icon>
<span :title="name">{{ name }}</span>
</span>
@@ -246,4 +266,8 @@ defineExpose({
overflow: hidden;
}
}
.custom-tree-folder {
color: rgb(255, 198, 10)
}
</style>
@@ -7,6 +7,9 @@ import icon_folder from '@/assets/svg/icon_folder.svg'
import icon_fileAdd_outlined from '@/assets/svg/icon_file-add_outlined.svg'
import icon_dashboard from '@/assets/svg/icon_dashboard.svg'
import icon_edit_outlined from '@/assets/svg/icon_edit_outlined.svg'
import icon_rename from '@/assets/svg/icon_rename.svg'
import icon_delete from '@/assets/svg/icon_delete.svg'
import icon_more_outlined from '@/assets/svg/icon_more_outlined.svg'
import {onMounted, reactive, ref, watch, nextTick, computed} from 'vue'
import {ElIcon, ElScrollbar} from 'element-plus-secondary'
import {Icon} from '@/components/icon-custom'
@@ -16,7 +19,10 @@ import router from '@/router'
import {dashboardStoreWithOut} from "@/stores/dashboard/dashboard.ts";
import ResourceGroupOpt from "@/views/dashboard/common/ResourceGroupOpt.vue";
import {dashboardApi} from "@/api/dashboard.ts";
import HandleMore from "@/views/dashboard/common/HandleMore.vue";
import {useI18n} from "vue-i18n";
const {t} = useI18n()
const dashboardStore = dashboardStoreWithOut()
const resourceGroupOptRef = ref(null)
@@ -38,8 +44,7 @@ defineProps({
})
const defaultProps = {
children: 'children',
label: 'name',
disabled: (data: any) => data.extraFlag1 === 0
label: 'name'
}
const mounted = ref(false)
const selectedNodeKey: any = ref(null)
@@ -51,9 +56,21 @@ const state = reactive({
curSortType: 'time_desc',
resourceTree: [] as SQTreeNode[],
originResourceTree: [] as SQTreeNode[],
folderMenuList: [],
sortType: [],
templateCreatePid: 0
templateCreatePid: 0,
folderMenuList: [
{
label: t('dashboard.rename'),
command: 'rename',
svgName: icon_rename
},
{
label: t('dashboard.delete'),
command: 'delete',
svgName: icon_delete,
divided: true
}
],
})
@@ -101,7 +118,7 @@ const nodeClick = (data: SQTreeNode, node: any) => {
})
} else {
selectedNodeKey.value = data.id
if (data.leaf) {
if (data.node_type === 'leaf') {
emit('nodeClick', data)
} else {
resourceListTree.value.setCurrentKey(null)
@@ -112,7 +129,7 @@ const nodeClick = (data: SQTreeNode, node: any) => {
const getTree = async () => {
state.originResourceTree = []
const params = {}
dashboardApi.list(params).then((res: SQTreeNode[]) => {
dashboardApi.list_resource(params).then((res: SQTreeNode[]) => {
state.originResourceTree = res || []
state.resourceTree = _.cloneDeep(state.originResourceTree)
afterTreeInit()
@@ -214,6 +231,32 @@ const addOperation = (params: any) => {
}
}
const operation = (opt: string, data: SQTreeNode) => {
if (opt === 'delete') {
const msg = data.node_type === 'leaf' ? '' : t('dashboard.delete_tips')
const tips_label = data.node_type === 'leaf' ? 'Dashboard' : t('dashboard.folder')
ElMessageBox.confirm(t('dashboard.delete_warn', [tips_label]), {
confirmButtonType: 'danger',
type: 'warning',
tip: msg,
autofocus: false,
showClose: false
}).then(() => {
dashboardApi.delete_resource({id: data.id}).then(() => {
ElMessage.success(t('dashboard.delete_success'))
getTree()
})
})
} else if (opt === 'rename') {
//@ts-ignore
resourceGroupOptRef.value?.optInit({opt: 'rename',id: data.id,name:data.name})
}
}
const baseInfoChangeFinish = () => {
getTree()
}
defineExpose({
hasData,
@@ -289,7 +332,7 @@ defineExpose({
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon style="font-size: 18px" v-if="!data.leaf">
<el-icon style="font-size: 18px" v-if="data.node_type !== 'leaf'">
<Icon name="icon_folder"><icon_folder class="svg-icon"/></Icon>
</el-icon>
<el-icon style="font-size: 18px" v-else>
@@ -301,7 +344,7 @@ defineExpose({
<div class="icon-more">
<el-icon
v-on:click.stop
v-if="!data.leaf"
v-if="data.node_type !== 'leaf'"
class="hover-icon"
@click="addOperation({opt:'newLeaf',type:'dashboard',id:data.id} )"
>
@@ -309,26 +352,25 @@ defineExpose({
</el-icon>
<el-icon
v-on:click.stop
v-if="data.leaf"
v-if="data.node_type === 'leaf'"
class="hover-icon"
@click="resourceEdit(data.id)"
>
<Icon><icon_edit_outlined class="svg-icon"/></Icon>
</el-icon>
<!-- <HandleMore-->
<!-- @handle-command=" (opt:string) => addOperation({opt})-->
<!-- "-->
<!-- :menu-list="resourceTypeList"-->
<!-- :icon-name="icon_add_outlined"-->
<!-- placement="bottom-start"-->
<!-- v-if="!data.leaf"-->
<!-- ></HandleMore>-->
<HandleMore
@handle-command=" (opt:string) => operation(opt,data)"
:menu-list="state.folderMenuList"
:icon-name="icon_more_outlined"
placement="bottom-start"
v-if="data.node_type !== 'leaf'"
></HandleMore>
</div>
</span>
</template>
</el-tree>
</el-scrollbar>
<ResourceGroupOpt ref="resourceGroupOptRef"></ResourceGroupOpt>
<ResourceGroupOpt ref="resourceGroupOptRef" @finish="baseInfoChangeFinish"></ResourceGroupOpt>
</div>
</template>
<style lang="less" scoped>
+143 -8
View File
@@ -1,22 +1,37 @@
<script setup lang="ts">
import {dashboardStoreWithOut} from "@/stores/dashboard/dashboard.ts";
import {storeToRefs} from 'pinia'
import IconBack from '@/assets/svg/common-back.svg'
import ComponentButtonLabel from "@/views/dashboard/components/button-label/ComponentButtonLabel.vue";
import dvTab from '@/assets/svg/dv-tab.svg'
import dvText from '@/assets/svg/dv-text.svg'
import dvView from '@/assets/svg/dv-view.svg'
import ResourceGroupOpt from "@/views/dashboard/common/ResourceGroupOpt.vue";
import {ref} from 'vue'
import {ref, nextTick} from 'vue'
import {useI18n} from 'vue-i18n'
import {snapshotStoreWithOut} from "@/stores/dashboard/snapshot.ts";
import icon_undo_outlined from '@/assets/svg/icon_undo_outlined.svg'
import icon_redo_outlined from '@/assets/svg/icon_redo_outlined.svg'
const {t} = useI18n()
const dashboardStore = dashboardStoreWithOut()
const {dashboardInfo} = storeToRefs(dashboardStore)
const snapshotStore = snapshotStoreWithOut()
const {snapshotIndex} = storeToRefs(snapshotStore)
const emits = defineEmits(['addComponent'])
const resourceGroupOptRef = ref(null)
const openViewDialog = () => {
// do addComponent
}
let nameEdit = ref(false)
let inputName = ref('')
let nameInput = ref(null)
const onDvNameChange = () => {
}
const saveCanvasWithCheck = () => {
if (dashboardInfo.value.dataState === 'prepare') {
const createParams = {
@@ -41,16 +56,87 @@ const props = defineProps({
const groupOptFinish = (result: any) => {
let url = window.location.href
url = url.replace(/(#\/[^?]*)(?:\?[^#]*)?/, `$1?resourceId=${result.resourceId}`)
window.history.replaceState( { path: url }, '', url )
window.history.replaceState({path: url}, '', url)
}
const editCanvasName = () => {
nameEdit.value = true
//@ts-ignore
inputName.value = dashboardInfo.value.name
nextTick(() => {
//@ts-ignore
nameInput.value?.focus()
})
}
const closeEditCanvasName = () => {
nameEdit.value = false
if (!inputName.value || !inputName.value.trim()) {
return
}
if (inputName.value.trim() === dashboardInfo.value.name) {
return
}
if (inputName.value.trim().length > 64 || inputName.value.trim().length < 1) {
ElMessage.warning(t('dashboard.length_1_64_characters'))
editCanvasName()
return
}
//@ts-ignore
dashboardInfo.value.name = inputName.value
inputName.value = ''
}
const undo = () => {
if (snapshotIndex.value > 0) {
snapshotStore.undo()
}
}
const redo = () => {
if (snapshotIndex.value !== snapshotStore.snapshotData.length - 1) {
snapshotStore.redo()
}
}
</script>
<template>
<div class="toolbar-main">
<span>
<el-icon><IconBack/></el-icon>
</span>
<span>{{ dashboardInfo.name }}</span>
<div class="left-area">
<span id="canvas-name" class="name-area" @dblclick="editCanvasName">
{{ dashboardInfo.name }}
</span>
<div class="opt-area">
<el-tooltip effect="dark" :content="t('dashboard.undo')" placement="bottom">
<el-icon
class="toolbar-hover-icon"
:class="{ 'toolbar-icon-disabled': snapshotIndex < 1 }"
:disabled="snapshotIndex < 1"
@click="undo()"
>
<Icon name="icon_undo_outlined">
<icon_undo_outlined class="svg-icon"/>
</Icon>
</el-icon>
</el-tooltip>
<el-tooltip effect="dark" :content="t('dashboard.reduction')" placement="bottom">
<el-icon
class="toolbar-hover-icon opt-icon-redo"
:class="{
'toolbar-icon-disabled': snapshotIndex === snapshotStore.snapshotData.length - 1
}"
@click="redo()"
>
<Icon name="icon_redo_outlined">
<icon_redo_outlined class="svg-icon"/>
</Icon>
</el-icon>
</el-tooltip>
</div>
</div>
<div class="core-toolbar">
<component-button-label
:icon-name="dvView"
@@ -83,6 +169,14 @@ const groupOptFinish = (result: any) => {
Save
</el-button>
</div>
<Teleport v-if="nameEdit" :to="'#canvas-name'">
<input
@change="onDvNameChange"
ref="nameInput"
v-model="inputName"
@blur="closeEditCanvasName"
/>
</Teleport>
<ResourceGroupOpt @finish="groupOptFinish " ref="resourceGroupOptRef"></ResourceGroupOpt>
</div>
</template>
@@ -93,9 +187,50 @@ const groupOptFinish = (result: any) => {
height: 56px;
display: flex;
align-items: center;
background: #050e21;
background: #d1ddf6;
padding-left: 8px;
.left-area {
margin-top: 8px;
margin-left: 14px;
width: 300px;
display: flex;
flex-direction: column;
.name-area {
position: relative;
line-height: 24px;
height: 24px;
font-size: 16px;
width: 300px;
overflow: hidden;
cursor: pointer;
input {
position: absolute;
left: 0;
width: 100%;
color: #fff;
background-color: #d1ddf6;
outline: none;
border: 1px solid #295acc;
border-radius: 4px;
padding: 0 4px;
height: 100%;
}
}
.opt-area {
width: 300px;
text-align: left;
color: #a6a6a6;
.opt-icon-redo {
margin-left: 12px;
}
}
}
.core-toolbar {
display: flex;
position: absolute;
@@ -52,7 +52,7 @@ const baseParams = computed(() => {
return {
opt: state.opt,
resourceId: state.resourceId,
routerPid: state.routerPid
pid: state.routerPid
}
})
@@ -59,10 +59,10 @@ function createNew() {
resourceTreeRef.value?.createNewObject()
}
const loadCanvasData = (dashboardId: string) => {
const loadCanvasData = (params: any) => {
dataInitState.value = false
//@ts-ignore
initCanvasData({dashboardId},function ({dashboardInfo, canvasDataResult, canvasStyleResult, canvasViewInfoPreview }) {
initCanvasData({id:params.id}, function ({dashboardInfo, canvasDataResult, canvasStyleResult, canvasViewInfoPreview}) {
state.canvasDataPreview = canvasDataResult
state.canvasStylePreview = canvasStyleResult
state.canvasViewInfoPreview = canvasViewInfoPreview
@@ -81,12 +81,12 @@ const getPreviewStateInfo = () => {
return state
}
const reload = (dashboardId:string) => {
loadCanvasData(dashboardId)
const reload = (params: any) => {
loadCanvasData(params)
}
const resourceNodeClick = (data:any) => {
loadCanvasData(data.id)
const resourceNodeClick = (prams: any) => {
loadCanvasData(prams)
}
const previewShowFlag = computed(() => !!dashboardStore.dashboardInfo?.name)
@@ -134,10 +134,7 @@ defineExpose({
v-loading="!dataInitState"
>
<template v-if="previewShowFlag">
<SQPreviewHead
v-if="showPosition === 'preview'"
@reload="reload"
/>
<SQPreviewHead @reload="reload" />
<div
ref="previewCanvasContainer"
class="content"
@@ -3,12 +3,11 @@ import {dashboardStoreWithOut} from "@/stores/dashboard/dashboard.ts";
import {storeToRefs} from "pinia";
const dashboardStore = dashboardStoreWithOut()
const {componentData, canvasStyle} = storeToRefs(dashboardStore)
const {componentData, canvasStyleData} = storeToRefs(dashboardStore)
const workspace_id = 'default' // temp
export const initCanvasData = (params: any, callBack: Function) => {
dashboardApi.getDashboardInfo(params).then((res: any) => {
const canvasInfo = res.data;
dashboardApi.load_resource(params).then((canvasInfo: any) => {
const dashboardInfo = {
id: canvasInfo.id,
name: canvasInfo.name,
@@ -22,8 +21,8 @@ export const initCanvasData = (params: any, callBack: Function) => {
updateTime: canvasInfo.updateTime,
contentId: canvasInfo.contentId
}
const canvasDataResult = JSON.parse(canvasInfo.componentData)
const canvasStyleResult = JSON.parse(canvasInfo.canvasStyleData)
const canvasDataResult = JSON.parse(canvasInfo.component_data)
const canvasStyleResult = JSON.parse(canvasInfo.canvas_style_data)
const canvasViewInfoPreview = canvasInfo.canvasViewInfo
callBack({dashboardInfo, canvasDataResult, canvasStyleResult, canvasViewInfoPreview})
})
@@ -31,23 +30,32 @@ export const initCanvasData = (params: any, callBack: Function) => {
export const saveDashboardResource = (params: any, callBack: Function) => {
params['workspace_id'] = workspace_id
dashboardApi.check_name(params).then((res: any) => {
if (!res) {
dashboardApi.check_name(params).then((resCheck: any) => {
if (resCheck) {
if (params.opt === 'newLeaf') {// create canvas
const reqeustParams = {
...params,
component_data: JSON.stringify(componentData.value),
canvas_style_data: JSON.stringify(canvasStyle.value)
canvas_style_data: JSON.stringify(canvasStyleData.value)
}
dashboardApi.saveCanvas(reqeustParams).then((res: any) => {
dashboardApi.create_canvas(reqeustParams).then((res: any) => {
dashboardStore.updateDashboardInfo({id: res.id, dataState: 'ready'})
callBack(res)
})
} else if (params.opt === 'newFolder') {
dashboardApi.addResource(params).then((res: any) => {
dashboardApi.create_resource(params).then((res: any) => {
callBack(res)
})
} else if (params.opt === 'rename') {
dashboardApi.update_resource(params).then((res: any) => {
callBack(res)
})
}
} else {
ElMessage({
type: 'warning',
message: 'Name Already In Use',
})
}
})
}
@@ -102,7 +102,7 @@ const treeDraggableChart = (state:any, key:any, type:any) => {
}
try {
await dashboardApi.sqNameCheck(params)
await dashboardApi.check_name(params)
} catch (error) {
console.error(error)
}
@@ -115,7 +115,7 @@ const treeDraggableChart = (state:any, key:any, type:any) => {
dfsTreeNodeBack(state[key], '0', params)
}
dashboardApi.moveResource(params)
dashboardApi.move_resource(params)
.then(() => {
state.originResourceTree = cloneDeep(state[key])
})
@@ -4,9 +4,8 @@ export interface SQTreeNode {
name: string
leaf?: boolean
weight: number
ext?: number
extraFlag: number
extraFlag1: number
type: string
node_type: string
children?: SQTreeNode[]
}