refactor: dashboard preview
@@ -4,6 +4,7 @@ from apps.system.api import login, user, aimodel
|
||||
from apps.settings.api import terminology
|
||||
from apps.datasource.api import datasource
|
||||
from apps.chat.api import chat
|
||||
from apps.dashboard.api import dashboard_api
|
||||
|
||||
|
||||
api_router = APIRouter()
|
||||
@@ -13,5 +14,6 @@ api_router.include_router(aimodel.router)
|
||||
api_router.include_router(terminology.router)
|
||||
api_router.include_router(datasource.router)
|
||||
api_router.include_router(chat.router)
|
||||
api_router.include_router(dashboard_api.router)
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import hashlib
|
||||
import os
|
||||
import uuid
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, File, UploadFile, HTTPException
|
||||
|
||||
from apps.dashboard.crud.dashboard_service import get_dashboard_list, preview_with_id
|
||||
from common.core.deps import SessionDep
|
||||
from apps.dashboard.crud.dashboard_service import get_dashboard_list, preview_with_id,create_dashboard
|
||||
from apps.dashboard.models.dashboard_model import CreateDashboard
|
||||
from common.core.deps import SessionDep, CurrentUser
|
||||
|
||||
router = APIRouter(tags=["dashboard"], prefix="/dashboard")
|
||||
|
||||
@@ -15,4 +13,8 @@ async def datasource_list(session: SessionDep):
|
||||
|
||||
@router.get("/preview_dashboard/{id}")
|
||||
async def preview_dashboard(session: SessionDep,id:str):
|
||||
return preview_with_id(session=session,dashboard_id=id)
|
||||
return preview_with_id(session=session,dashboard_id=id)
|
||||
|
||||
@router.post("/add", response_model=CreateDashboard)
|
||||
async def add(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
|
||||
return create_dashboard(session, user, dashboard)
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
from select import select
|
||||
|
||||
from apps.dashboard.models.dashboard_model import CoreDashboard
|
||||
from common.core.deps import SessionDep
|
||||
|
||||
|
||||
from apps.dashboard.models.dashboard_model import CoreDashboard, CreateDashboard
|
||||
from common.core.deps import SessionDep, CurrentUser
|
||||
import uuid
|
||||
def get_dashboard_list(session: SessionDep):
|
||||
statement = select(CoreDashboard).order_by(CoreDashboard.create_time.desc())
|
||||
dashboard_list = session.exec(statement).fetchall()
|
||||
return dashboard_list
|
||||
|
||||
def preview_with_id(session: SessionDep, dashboard_id: str):
|
||||
return session.query(CoreDashboard).filter(CoreDashboard.id == id).first()
|
||||
return session.query(CoreDashboard).filter(CoreDashboard.id == id).first()
|
||||
|
||||
|
||||
def create_dashboard(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
|
||||
new_id = uuid.uuid4().hex
|
||||
record = CoreDashboard(**dashboard.model_dump())
|
||||
record.id = new_id
|
||||
record.create_by = user.id
|
||||
session.add(record)
|
||||
session.flush()
|
||||
session.refresh(record)
|
||||
session.commit()
|
||||
return record
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from sqlmodel import SQLModel, Field
|
||||
from sqlalchemy import String, Column, Text, SmallInteger, BigInteger, Integer
|
||||
from sqlalchemy import String, Column, Text, SmallInteger, BigInteger, Integer,DateTime
|
||||
from pydantic import BaseModel
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class CoreDashboard(SQLModel, table=True):
|
||||
@@ -121,3 +123,18 @@ class CoreDashboard(SQLModel, table=True):
|
||||
max_length=50,
|
||||
sa_column=Column(String(50), nullable=True)
|
||||
)
|
||||
|
||||
# dashboard create obj
|
||||
class CreateDashboard(BaseModel):
|
||||
id: str = ''
|
||||
name: str = ''
|
||||
pid: str = ''
|
||||
workspace_id: str = ''
|
||||
org_id: str = ''
|
||||
description: str = ''
|
||||
type: str = ''
|
||||
node_type: str = ''
|
||||
canvas_style_data: str =''
|
||||
component_data: str = ''
|
||||
configuration: str = ''
|
||||
create_by: int = 0
|
||||
@@ -21,6 +21,7 @@ declare module '@vue/runtime-core' {
|
||||
ElDropdown: typeof import('element-plus-secondary/es')['ElDropdown']
|
||||
ElDropdownItem: typeof import('element-plus-secondary/es')['ElDropdownItem']
|
||||
ElDropdownMenu: typeof import('element-plus-secondary/es')['ElDropdownMenu']
|
||||
ElEmpty: typeof import('element-plus-secondary/es')['ElEmpty']
|
||||
ElFooter: typeof import('element-plus-secondary/es')['ElFooter']
|
||||
ElForm: typeof import('element-plus-secondary/es')['ElForm']
|
||||
ElFormItem: typeof import('element-plus-secondary/es')['ElFormItem']
|
||||
@@ -32,6 +33,7 @@ declare module '@vue/runtime-core' {
|
||||
ElMenuItem: typeof import('element-plus-secondary/es')['ElMenuItem']
|
||||
ElOption: typeof import('element-plus-secondary/es')['ElOption']
|
||||
ElPagination: typeof import('element-plus-secondary/es')['ElPagination']
|
||||
ElPopover: typeof import('element-plus-secondary/es')['ElPopover']
|
||||
ElRadio: typeof import('element-plus-secondary/es')['ElRadio']
|
||||
ElRadioGroup: typeof import('element-plus-secondary/es')['ElRadioGroup']
|
||||
ElRow: typeof import('element-plus-secondary/es')['ElRow']
|
||||
@@ -46,6 +48,8 @@ declare module '@vue/runtime-core' {
|
||||
ElTabPane: typeof import('element-plus-secondary/es')['ElTabPane']
|
||||
ElTabs: typeof import('element-plus-secondary/es')['ElTabs']
|
||||
ElTooltip: typeof import('element-plus-secondary/es')['ElTooltip']
|
||||
ElTree: typeof import('element-plus-secondary/es')['ElTree']
|
||||
ElTreeSelect: typeof import('element-plus-secondary/es')['ElTreeSelect']
|
||||
ElUpload: typeof import('element-plus-secondary/es')['ElUpload']
|
||||
Icon: typeof import('./src/components/icon-custom/src/Icon.vue')['default']
|
||||
Layout: typeof import('./src/components/layout/index.vue')['default']
|
||||
|
||||
@@ -5,4 +5,5 @@ export const dashboardApi = {
|
||||
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)
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,12 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_4299_58875)">
|
||||
<path d="M8.00033 3.66618C8.46056 3.66618 8.83366 4.03928 8.83366 4.49951C8.83366 4.95975 8.46056 5.33285 8.00033 5.33285C7.54009 5.33285 7.16699 4.95975 7.16699 4.49951C7.16699 4.03928 7.54009 3.66618 8.00033 3.66618Z" fill="#8D9199"/>
|
||||
<path d="M8.16699 5.99951H7.33366C7.05752 5.99951 6.83366 6.22337 6.83366 6.49951V6.83285C6.83366 7.10899 7.05752 7.33285 7.33366 7.33285H7.50033V10.6662H6.83366C6.55752 10.6662 6.33366 10.89 6.33366 11.1662V11.4995C6.33366 11.7757 6.55752 11.9995 6.83366 11.9995H9.50033C9.77647 11.9995 10.0003 11.7757 10.0003 11.4995V11.1662C10.0003 10.89 9.77647 10.6662 9.50033 10.6662H8.83366V6.66618C8.83366 6.29799 8.53518 5.99951 8.16699 5.99951Z" fill="#8D9199"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00033 15.3327C3.95033 15.3327 0.666992 12.0493 0.666992 7.99935C0.666992 3.94935 3.95033 0.666016 8.00033 0.666016C12.0503 0.666016 15.3337 3.94935 15.3337 7.99935C15.3337 12.0493 12.0503 15.3327 8.00033 15.3327ZM8.00033 13.9993C11.314 13.9993 14.0003 11.313 14.0003 7.99935C14.0003 4.68568 11.314 1.99935 8.00033 1.99935C4.68666 1.99935 2.00033 4.68568 2.00033 7.99935C2.00033 11.313 4.68666 13.9993 8.00033 13.9993Z" fill="#8D9199"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_4299_58875">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" 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>
|
||||
|
After Width: | Height: | Size: 755 B |
@@ -0,0 +1,6 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="icon_file-add_outlined">
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M4.16667 2.50001H13.3333V4.59959C13.3333 4.7101 13.3772 4.81608 13.4554 4.89422C13.5335 4.97236 13.6395 5.01626 13.75 5.01626H15.8333V10.8333H17.5V4.09626C17.5001 3.87532 17.4124 3.66341 17.2563 3.50709L14.8275 1.07751C14.7501 1.00007 14.6582 0.938651 14.557 0.896756C14.4558 0.85486 14.3474 0.833312 14.2379 0.833344H3.33333C3.11232 0.833344 2.90036 0.921141 2.74408 1.07742C2.5878 1.2337 2.5 1.44566 2.5 1.66668V18.3333C2.5 18.5544 2.5878 18.7663 2.74408 18.9226C2.90036 19.0789 3.11232 19.1667 3.33333 19.1667H10V17.5H4.16667V2.50001Z"/>
|
||||
<path id="Vector" d="M14.5833 12.5C14.3532 12.5 14.1667 12.6865 14.1667 12.9167V15H12.0833C11.8532 15 11.6667 15.1865 11.6667 15.4167V16.25C11.6667 16.4801 11.8532 16.6667 12.0833 16.6667H14.1667V18.75C14.1667 18.9801 14.3532 19.1667 14.5833 19.1667H15.4167C15.6468 19.1667 15.8333 18.9801 15.8333 18.75V16.6667H17.9167C18.1468 16.6667 18.3333 16.4801 18.3333 16.25V15.4167C18.3333 15.1865 18.1468 15 17.9167 15H15.8333V12.9167C15.8333 12.6865 15.6468 12.5 15.4167 12.5H14.5833Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" 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>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" >
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.33329 2.33332V9.33332H11.6666V2.33332H2.33329ZM1.16663 1.74999C1.16663 1.4277 1.42913 1.16666 1.74996 1.16666H12.25C12.5708 1.16666 12.8333 1.4277 12.8333 1.74999V9.91666C12.8333 10.2389 12.5708 10.5 12.25 10.5H1.74996C1.42913 10.5 1.16663 10.2389 1.16663 9.91666V1.74999Z" />
|
||||
<path d="M9.00573 3.96255L9.83057 4.78739L7.06848 7.54947L5.72157 6.20285L4.78736 7.13735L3.96252 6.31222L5.72157 4.55318L7.06819 5.89981L9.00573 3.96255Z" />
|
||||
<path d="M9.91671 11.6667H4.08337V12.8333H9.91671V11.6667Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 648 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.3333 1.33325H1.66667C1.29848 1.33325 1 1.63173 1 1.99992V11.3333C1 11.7014 1.29848 11.9999 1.66667 11.9999H14.3333C14.7015 11.9999 15 11.7014 15 11.3333V1.99992C15 1.63173 14.7015 1.33325 14.3333 1.33325ZM2.33333 8.66659V2.66659H13.6667V8.66659H2.33333ZM2.33333 9.99992H13.6667V10.6666H2.33333V9.99992ZM4.66667 13.3333H11.3333V14.6666H4.66667V13.3333Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 459 B |
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.4733 17.8875C14.8415 19.2086 12.7631 20 10.5 20C5.25329 20 1 15.7467 1 10.5C1 5.25329 5.25329 1 10.5 1C15.7467 1 20 5.25329 20 10.5C20 12.7631 19.2086 14.8415 17.8875 16.4733L22.0104 20.5962C22.2057 20.7915 22.2057 21.108 22.0104 21.3033L21.3033 22.0104C21.108 22.2057 20.7915 22.2057 20.5962 22.0104L16.4733 17.8875ZM18 10.5C18 6.35786 14.6421 3 10.5 3C6.35786 3 3 6.35786 3 10.5C3 14.6421 6.35786 18 10.5 18C14.6421 18 18 14.6421 18 10.5Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 525 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.833008 16.6667V3.33333C0.833008 2.8731 1.2061 2.5 1.66634 2.5H8.65131C8.96696 2.5 9.25551 2.67834 9.39667 2.96066L9.99967 4.16667H18.2933C18.7755 4.16667 19.1663 4.53976 19.1663 5V16.6667C19.1663 17.1269 18.7755 17.5 18.2933 17.5H1.70602C1.22387 17.5 0.833008 17.1269 0.833008 16.6667ZM2.49967 5.83333V15.8333H17.4997V5.83333H2.49967Z" fill="currentColor"/>
|
||||
<rect x="6.66699" y="10" width="6.66667" height="1.66667" rx="0.5" fill="currentColor"/>
|
||||
<rect x="9.16699" y="7.5" width="1.66667" height="6.66667" rx="0.5" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 652 B |
@@ -0,0 +1,248 @@
|
||||
<script lang="ts" setup>
|
||||
import folder from '@/assets/svg/folder.svg'
|
||||
import {type SQTreeNode} from '@/views/dashboard/utils/treeNode'
|
||||
import {ref, reactive, computed} from 'vue'
|
||||
import {dashboardApi} from "@/api/dashboard.ts";
|
||||
|
||||
const state = reactive({
|
||||
placeholder:'',
|
||||
showParentSelected: false,
|
||||
resourceFormNameLabel: 'Name',
|
||||
dialogTitle: '',
|
||||
tData: [],
|
||||
nameList: [],
|
||||
targetInfo: null,
|
||||
attachParams: null
|
||||
})
|
||||
|
||||
let tData: any = []
|
||||
|
||||
const getTitle = (cmd: string) => {
|
||||
switch (cmd) {
|
||||
case 'newLeaf':
|
||||
return 'New Dashboard'
|
||||
case 'newFolder':
|
||||
return 'New Folder'
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const getResourceNewName = (cmd: string) => {
|
||||
switch (cmd) {
|
||||
case 'newLeaf':
|
||||
return 'New Dashboard'
|
||||
case 'newFolder':
|
||||
return 'New Folder'
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const optInit = (params: any) => {
|
||||
state.dialogTitle = getTitle(params.cmd)
|
||||
state.showParentSelected = params.parentSelect
|
||||
state.targetInfo = params.data
|
||||
resourceDialogShow.value = true
|
||||
resourceForm.name = getResourceNewName(params.cmd)
|
||||
}
|
||||
|
||||
const resourceDialogShow = ref(false)
|
||||
const loading = ref(false)
|
||||
const pid = ref()
|
||||
const id = ref()
|
||||
const cmd = ref('')
|
||||
const treeRef = ref()
|
||||
const filterText = ref('')
|
||||
const resourceForm = reactive({
|
||||
pid: '',
|
||||
pName: '',
|
||||
name: 'New Dashboard'
|
||||
})
|
||||
|
||||
const resourceFormRules = ref({
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: state.placeholder,
|
||||
trigger: 'change'
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: state.placeholder,
|
||||
trigger: 'blur'
|
||||
},
|
||||
{
|
||||
min: 1,
|
||||
max: 64,
|
||||
message: 'Chart limit 1-64',
|
||||
trigger: 'change'
|
||||
},
|
||||
{required: true, trigger: 'blur'}
|
||||
],
|
||||
pid: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please select',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const resetForm = () => {
|
||||
state.dialogTitle = ''
|
||||
resourceForm.name = ''
|
||||
resourceForm.pid = ''
|
||||
resourceDialogShow.value = false
|
||||
}
|
||||
|
||||
const editeInit = (param: SQTreeNode) => {
|
||||
pid.value = param['pid']
|
||||
id.value = param.id
|
||||
}
|
||||
|
||||
const propsTree = {
|
||||
label: 'name',
|
||||
children: 'children',
|
||||
isLeaf: node => !node.children?.length
|
||||
}
|
||||
|
||||
const showPid = computed(() => {
|
||||
return ['newLeaf', 'copy', 'newLeafAfter'].includes(cmd.value) && state.showParentSelected
|
||||
})
|
||||
|
||||
const saveResource = () => {
|
||||
const params = {
|
||||
nodeType: 'folder',
|
||||
name: resourceForm.name,
|
||||
type: 'dashboard'
|
||||
}
|
||||
dashboardApi.addResource(params).then(res => {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: 'Save Success',
|
||||
})
|
||||
|
||||
resetForm()
|
||||
})
|
||||
}
|
||||
|
||||
const nodeClick = (data: SQTreeNode) => {
|
||||
resourceForm.pid = data.id as string
|
||||
resourceForm.pName = data.name as string
|
||||
}
|
||||
|
||||
const filterMethod = value => {
|
||||
state.tData = [...tData].filter(item => item.name.includes(value))
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
optInit,
|
||||
editeInit
|
||||
})
|
||||
|
||||
const emits = defineEmits(['finish'])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-dialog
|
||||
class="create-dialog"
|
||||
:title="state.dialogTitle"
|
||||
v-model="resourceDialogShow"
|
||||
width="420px"
|
||||
:before-close="resetForm"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form
|
||||
v-loading="loading"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
ref="resource"
|
||||
:model="resourceForm"
|
||||
:rules="resourceFormRules"
|
||||
>
|
||||
<el-form-item :label="state.resourceFormNameLabel" prop="name">
|
||||
<el-input
|
||||
@keydown.stop
|
||||
@keyup.stop
|
||||
:placeholder="state.placeholder"
|
||||
v-model="resourceForm.name"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="showPid" :label="'Folder'" prop="pid">
|
||||
<el-tree-select
|
||||
style="width: 100%"
|
||||
@keydown.stop
|
||||
@keyup.stop
|
||||
v-model="resourceForm.pid"
|
||||
:data="state.tData"
|
||||
:props="propsTree"
|
||||
@node-click="nodeClick"
|
||||
:filter-method="filterMethod"
|
||||
:render-after-expand="false"
|
||||
filterable
|
||||
>
|
||||
<template #default="{ data: { name } }">
|
||||
<span class="custom-tree-node">
|
||||
<el-icon>
|
||||
<Icon name="dv-folder"><folder class="svg-icon"/></Icon>
|
||||
</el-icon>
|
||||
<span :title="name">{{ name }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button secondary @click="resetForm()">Cancel</el-button>
|
||||
<el-button type="primary" @click="saveResource()">Confirm</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tree-content {
|
||||
width: 552px;
|
||||
height: 380px;
|
||||
border: 1px solid #dee0e3;
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
overflow-y: auto;
|
||||
|
||||
.empty-search {
|
||||
width: 100%;
|
||||
margin-top: 57px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: #646a73;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-tree-node {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
margin-left: 8.75px;
|
||||
width: 120px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,22 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import icon_add_outlined from '@/assets/svg/icon_add_outlined.svg'
|
||||
import { treeDraggableChart } from '@/views/dashboard/utils/treeDraggableChart'
|
||||
import dvNewFolder from '@/assets/svg/dv-new-folder.svg'
|
||||
import {treeDraggableChart} from '@/views/dashboard/utils/treeDraggableChart'
|
||||
import newFolder from '@/assets/svg/new-folder.svg'
|
||||
import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlined.svg'
|
||||
import dvFolder from '@/assets/svg/dv-folder.svg'
|
||||
import Folder from '@/assets/svg/folder.svg'
|
||||
import icon_fileAdd_outlined from '@/assets/svg/icon_file-add_outlined.svg'
|
||||
import icon_operationAnalysis_outlined from '@/assets/svg/icon_operation-analysis_outlined.svg'
|
||||
import icon_edit_outlined from '@/assets/svg/icon_edit_outlined.svg'
|
||||
import { onMounted, reactive, ref, watch, nextTick, computed } from 'vue'
|
||||
import { ElIcon, ElScrollbar } from 'element-plus-secondary'
|
||||
import { Icon } from '@/components/icon-custom'
|
||||
import { type SQTreeNode } from '@/views/dashboard/utils/treeNode'
|
||||
import {onMounted, reactive, ref, watch, nextTick, computed} from 'vue'
|
||||
import {ElIcon, ElScrollbar} from 'element-plus-secondary'
|
||||
import {Icon} from '@/components/icon-custom'
|
||||
import {type SQTreeNode} from '@/views/dashboard/utils/treeNode'
|
||||
import _ from 'lodash'
|
||||
import { treeParentWeight } from '@/views/dashboard/utils/treeSortUtils'
|
||||
import router from '@/router'
|
||||
import {dashboardStoreWithOut} from "@/stores/dashboard/dashboard.ts";
|
||||
import HandleMore from "@/views/dashboard/common/HandleMore.vue";
|
||||
const dashboardStore = dashboardStoreWithOut()
|
||||
import ResourceGroupOpt from "@/views/dashboard/common/ResourceGroupOpt.vue";
|
||||
|
||||
const dashboardStore = dashboardStoreWithOut()
|
||||
const resourceGroupOptRef = ref(null)
|
||||
|
||||
defineProps({
|
||||
curCanvasType: {
|
||||
@@ -40,35 +42,30 @@ const defaultProps = {
|
||||
disabled: (data: any) => data.extraFlag1 === 0
|
||||
}
|
||||
const mounted = ref(false)
|
||||
const rootManage = ref(false)
|
||||
const selectedNodeKey:any = ref(null)
|
||||
const selectedNodeKey: any = ref(null)
|
||||
const filterText = ref(null)
|
||||
const expandedArray = ref([])
|
||||
const resourceListTree = ref()
|
||||
const returnMounted = ref(false)
|
||||
const state = reactive({
|
||||
pWeightMap: {},
|
||||
curSortType: 'time_desc',
|
||||
resourceTree: [] as SQTreeNode[],
|
||||
originResourceTree: [] as SQTreeNode[],
|
||||
folderMenuList: [
|
||||
],
|
||||
sortType: [
|
||||
],
|
||||
folderMenuList: [],
|
||||
sortType: [],
|
||||
templateCreatePid: 0
|
||||
})
|
||||
|
||||
|
||||
|
||||
const resourceTypeList = computed(() => {
|
||||
return []
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
const { handleDrop, allowDrop, handleDragStart } = treeDraggableChart(
|
||||
state,
|
||||
'resourceTree',
|
||||
'dashboard'
|
||||
const {handleDrop, allowDrop, handleDragStart} = treeDraggableChart(
|
||||
state,
|
||||
'resourceTree',
|
||||
'dashboard'
|
||||
)
|
||||
|
||||
|
||||
@@ -77,14 +74,14 @@ if (routerDashboardId) {
|
||||
selectedNodeKey.value = routerDashboardId
|
||||
returnMounted.value = true
|
||||
}
|
||||
const nodeExpand = (data:any) => {
|
||||
const nodeExpand = (data: any) => {
|
||||
if (data.id) {
|
||||
// @ts-ignore
|
||||
expandedArray.value.push(data.id)
|
||||
}
|
||||
}
|
||||
|
||||
const nodeCollapse = (data:any) => {
|
||||
const nodeCollapse = (data: any) => {
|
||||
if (data.id) {
|
||||
// @ts-ignore
|
||||
expandedArray.value.splice(expandedArray.value.indexOf(data.id), 1)
|
||||
@@ -96,8 +93,8 @@ const filterNode = (value: string, data: SQTreeNode) => {
|
||||
return data.name?.toLocaleLowerCase().includes(value.toLocaleLowerCase())
|
||||
}
|
||||
|
||||
const nodeClick = (data: SQTreeNode, node:any) => {
|
||||
dashboardStore.setCurComponent({ component: null, index: null })
|
||||
const nodeClick = (data: SQTreeNode, node: any) => {
|
||||
dashboardStore.setCurComponent({component: null, index: null})
|
||||
if (node.disabled) {
|
||||
nextTick(() => {
|
||||
const currentNode = resourceListTree.value.$el.querySelector('.is-current')
|
||||
@@ -138,7 +135,6 @@ function flatTree(tree: SQTreeNode[]) {
|
||||
}
|
||||
|
||||
const afterTreeInit = () => {
|
||||
state.pWeightMap = treeParentWeight(state.originResourceTree, rootManage.value ? 9 : 0)
|
||||
mounted.value = true
|
||||
if (selectedNodeKey.value && returnMounted.value) {
|
||||
// @ts-ignore
|
||||
@@ -161,13 +157,14 @@ const emit = defineEmits(['nodeClick'])
|
||||
|
||||
function createNewObject() {
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const resourceEdit = resourceId => {
|
||||
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const getParentKeys = (tree:any, targetKey:any, parentKeys = []) => {
|
||||
const getParentKeys = (tree: any, targetKey: any, parentKeys = []) => {
|
||||
for (const node of tree) {
|
||||
if (node.id === targetKey) {
|
||||
return parentKeys
|
||||
@@ -198,20 +195,25 @@ watch(filterText, val => {
|
||||
})
|
||||
|
||||
|
||||
const loadInit = () => {}
|
||||
const loadInit = () => {
|
||||
}
|
||||
onMounted(() => {
|
||||
loadInit()
|
||||
getTree()
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
const addOperation = ( cmd: string, data?: SQTreeNode, nodeType?: string, parentSelect?: boolean) => {
|
||||
|
||||
const addOperation = (params: any) => {
|
||||
if (params.cmd === 'newLeaf') {
|
||||
const newCanvasUrl = '#/canvas?opt=create' + params.data?.id ? `&pid=${params.data?.id}` : ''
|
||||
window.open(newCanvasUrl, '_blank')
|
||||
} else {
|
||||
resourceGroupOptRef.value?.optInit(params)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defineExpose({
|
||||
rootManage,
|
||||
hasData,
|
||||
createNewObject,
|
||||
mounted
|
||||
@@ -221,90 +223,106 @@ defineExpose({
|
||||
<template>
|
||||
<div class="resource-tree">
|
||||
<div class="tree-header">
|
||||
<div class="icon-methods" v-show="showPosition === 'preview'">
|
||||
<div class="icon-methods">
|
||||
<span class="title"> Dashboard </span>
|
||||
<div v-if="rootManage" class="flex-align-center">
|
||||
<div class="flex-align-center">
|
||||
<el-tooltip :content="'New Folder'" placement="top" effect="dark">
|
||||
<el-icon
|
||||
class="custom-icon btn"
|
||||
style="margin-right: 20px"
|
||||
class="custom-icon btn"
|
||||
style="margin-right: 10px"
|
||||
@click="addOperation({cmd:'newFolder',type:'folder'} )"
|
||||
>
|
||||
<Icon name="dv-new-folder"><dvNewFolder class="svg-icon" /></Icon>
|
||||
<Icon name="dv-new-folder">
|
||||
<newFolder class="svg-icon"/>
|
||||
</Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="'Add Dashboard'" placement="top" effect="dark">
|
||||
<el-icon
|
||||
class="custom-icon btn"
|
||||
style="margin-right: 10px"
|
||||
>
|
||||
<Icon name="dv-new-folder">
|
||||
<icon_fileAdd_outlined class="svg-icon"/>
|
||||
</Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<el-input
|
||||
:placeholder="'Search'"
|
||||
v-model="filterText"
|
||||
clearable
|
||||
class="search-bar"
|
||||
:placeholder="'Search'"
|
||||
v-model="filterText"
|
||||
clearable
|
||||
class="search-bar"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon>
|
||||
<Icon name="icon_search-outline_outlined"
|
||||
><icon_searchOutline_outlined class="svg-icon"
|
||||
/></Icon>
|
||||
>
|
||||
<icon_searchOutline_outlined class="svg-icon"
|
||||
/>
|
||||
</Icon>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<el-scrollbar class="custom-tree" v-loading="copyLoading">
|
||||
<el-tree
|
||||
menu
|
||||
ref="resourceListTree"
|
||||
:default-expanded-keys="expandedArray"
|
||||
:data="state.resourceTree"
|
||||
:props="defaultProps"
|
||||
node-key="id"
|
||||
highlight-current
|
||||
:expand-on-click-node="true"
|
||||
:filter-node-method="filterNode"
|
||||
@node-expand="nodeExpand"
|
||||
@node-collapse="nodeCollapse"
|
||||
@node-click="nodeClick"
|
||||
@node-drag-start="handleDragStart"
|
||||
@node-drop="handleDrop"
|
||||
draggable
|
||||
menu
|
||||
ref="resourceListTree"
|
||||
:default-expanded-keys="expandedArray"
|
||||
:data="state.resourceTree"
|
||||
:props="defaultProps"
|
||||
node-key="id"
|
||||
highlight-current
|
||||
:expand-on-click-node="true"
|
||||
:filter-node-method="filterNode"
|
||||
@node-expand="nodeExpand"
|
||||
@node-collapse="nodeCollapse"
|
||||
@node-click="nodeClick"
|
||||
@node-drag-start="handleDragStart"
|
||||
@node-drop="handleDrop"
|
||||
draggable
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<span class="custom-tree-node" :class="{ 'node-disabled-custom': data.extraFlag1 === 0 }">
|
||||
<el-icon style="font-size: 18px" v-if="!data.leaf">
|
||||
<Icon name="dv-folder"><dvFolder class="svg-icon" /></Icon>
|
||||
<Icon name="dv-folder"><Folder class="svg-icon"/></Icon>
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="icon-screen-new color-dataV"
|
||||
:class="{ 'color-dataV': data.extraFlag1, 'color-dataV-disabled': !data.extraFlag1 }"
|
||||
style="font-size: 18px"
|
||||
v-else
|
||||
class="icon-screen-new color-dataV"
|
||||
:class="{ 'color-dataV': data.extraFlag1, 'color-dataV-disabled': !data.extraFlag1 }"
|
||||
style="font-size: 18px"
|
||||
v-else
|
||||
>
|
||||
<Icon name="icon_operation-analysis_outlined"
|
||||
><icon_operationAnalysis_outlined class="svg-icon"
|
||||
><icon_operationAnalysis_outlined class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
<div class="icon-more">
|
||||
<el-icon
|
||||
v-on:click.stop
|
||||
v-if="data.leaf"
|
||||
class="hover-icon"
|
||||
@click="resourceEdit(data.id)"
|
||||
v-on:click.stop
|
||||
v-if="data.leaf"
|
||||
class="hover-icon"
|
||||
@click="resourceEdit(data.id)"
|
||||
>
|
||||
<Icon><icon_edit_outlined class="svg-icon" /></Icon>
|
||||
<Icon><icon_edit_outlined class="svg-icon"/></Icon>
|
||||
</el-icon>
|
||||
<HandleMore
|
||||
@handle-command="
|
||||
@handle-command="
|
||||
cmd => addOperation(cmd, data, cmd === 'newFolder' ? 'folder' : 'leaf')
|
||||
"
|
||||
:menu-list="resourceTypeList"
|
||||
:icon-name="icon_add_outlined"
|
||||
placement="bottom-start"
|
||||
v-if="!data.leaf"
|
||||
:menu-list="resourceTypeList"
|
||||
:icon-name="icon_add_outlined"
|
||||
placement="bottom-start"
|
||||
v-if="!data.leaf"
|
||||
></HandleMore>
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
<ResourceGroupOpt ref="resourceGroupOptRef"></ResourceGroupOpt>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
@@ -322,6 +340,7 @@ defineExpose({
|
||||
.opt-icon:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #f5f6f7;
|
||||
}
|
||||
@@ -330,6 +349,7 @@ defineExpose({
|
||||
background: #eff0f1;
|
||||
}
|
||||
}
|
||||
|
||||
.resource-tree {
|
||||
padding: 16px 0 0;
|
||||
width: 100%;
|
||||
@@ -349,6 +369,7 @@ defineExpose({
|
||||
font-weight: 500;
|
||||
color: var(--TextPrimary, #1f2329);
|
||||
padding-bottom: 16px;
|
||||
|
||||
.title {
|
||||
margin-right: auto;
|
||||
font-size: 16px;
|
||||
@@ -356,32 +377,39 @@ defineExpose({
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.custom-icon {
|
||||
font-size: 20px;
|
||||
|
||||
&.btn {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
padding-bottom: 10px;
|
||||
width: calc(100% - 40px);
|
||||
}
|
||||
}
|
||||
|
||||
.title-area {
|
||||
margin-left: 6px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.title-area-outer {
|
||||
display: flex;
|
||||
flex: 1 1 0%;
|
||||
width: 0px;
|
||||
}
|
||||
|
||||
.custom-tree-node-list {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
@@ -390,6 +418,7 @@ defineExpose({
|
||||
font-size: 14px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.father .child {
|
||||
visibility: hidden;
|
||||
}
|
||||
@@ -421,6 +450,7 @@ defineExpose({
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.icon-more {
|
||||
margin-left: auto;
|
||||
display: none;
|
||||
@@ -462,6 +492,7 @@ defineExpose({
|
||||
|
||||
.sort-type-checked {
|
||||
color: var(--ed-color-primary);
|
||||
|
||||
i {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import SQPreviewShow from "@/views/dashboard/preview/SQPreviewShow.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h2>this is dashboard page</h2>
|
||||
</template>
|
||||
<SQPreviewShow></SQPreviewShow>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import dvInfoSvg from '@/assets/svg/dv-info.svg'
|
||||
import dashboardInfoSvg from '@/assets/svg/dashboard-info.svg'
|
||||
import icon_pc_outlined from '@/assets/svg/icon_pc_outlined.svg'
|
||||
import icon_edit_outlined from '@/assets/svg/icon_edit_outlined.svg'
|
||||
import DashboardDetailInfo from "@/views/dashboard/common/DashboardDetailInfo.vue";
|
||||
@@ -22,9 +22,7 @@ const edit = () =>{}
|
||||
>
|
||||
<el-popover show-arrow :offset="8" placement="bottom" width="400" trigger="hover">
|
||||
<template #reference>
|
||||
<el-icon class="info-tips"
|
||||
><Icon name="dv-info"><dvInfoSvg class="svg-icon" /></Icon
|
||||
></el-icon>
|
||||
<el-icon class="info-tips"><dashboardInfoSvg class="svg-icon" /></el-icon>
|
||||
</template>
|
||||
<DashboardDetailInfo></DashboardDetailInfo>
|
||||
</el-popover>
|
||||
|
||||