mirror of
https://github.com/dataease/dataease.git
synced 2026-06-17 04:51:43 +08:00
fix(copilot): 删除copilot相关代码
This commit is contained in:
@@ -1,92 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import copilot from '@/assets/svg/copilot.svg'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
const visible = ref(true)
|
||||
const emits = defineEmits(['confirm'])
|
||||
|
||||
const confirm = () => {
|
||||
emits('confirm')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// do
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<el-popover
|
||||
:visible="visible"
|
||||
placement="bottom"
|
||||
popper-class="copilot-popper-tips"
|
||||
:width="288"
|
||||
show-arrow
|
||||
>
|
||||
<div class="copilot-popper-tips-content">
|
||||
<p class="title">{{ t('copilot.talking_analysis') }}</p>
|
||||
<p class="constant">
|
||||
{{ t('copilot.hello') }}
|
||||
<br />{{ t('copilot.click_talk') }}<br />
|
||||
</p>
|
||||
<div class="bottom">
|
||||
<el-button size="middle" @click="confirm"> {{ t('copilot.know') }} </el-button>
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
<div class="copilot-popper-tips-icon">
|
||||
<el-icon style="margin: 2px" class="ai-icon">
|
||||
<Icon name="copilot"><copilot class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.copilot-popper-tips {
|
||||
z-index: 10001 !important;
|
||||
padding: 24px !important;
|
||||
box-shadow: none !important;
|
||||
border: 0px !important;
|
||||
background: var(--ed-color-primary) !important;
|
||||
.ed-popper__arrow::before {
|
||||
border: 1px solid var(--ed-color-primary) !important;
|
||||
background: var(--ed-color-primary) !important;
|
||||
}
|
||||
}
|
||||
.copilot-popper-tips-content {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
.title {
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 28px;
|
||||
}
|
||||
.content {
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
}
|
||||
.bottom {
|
||||
line-height: 22px;
|
||||
text-align: right;
|
||||
button {
|
||||
border: 0px !important;
|
||||
border-color: #ffffff !important;
|
||||
font-weight: 500;
|
||||
color: var(--ed-color-primary, rgba(51, 112, 255, 1)) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copilot-popper-tips-icon {
|
||||
margin: 0 8px;
|
||||
z-index: 10003;
|
||||
border-radius: 50%;
|
||||
background: #ffffff;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import iconSetting from '@/assets/svg/icon-setting.svg'
|
||||
import copilot from '@/assets/svg/copilot.svg'
|
||||
import LangSelector from '@/layout/components/LangSelector.vue'
|
||||
import { useRouter } from 'vue-router_2'
|
||||
import TopDesktopCard from './TopDesktopCard.vue'
|
||||
@@ -47,10 +46,6 @@ const initAiBase = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleCopilotClick = () => {
|
||||
push('/copilot/index')
|
||||
}
|
||||
|
||||
const handleAiClick = () => {
|
||||
useEmitt().emitter.emit('aiComponentChange')
|
||||
}
|
||||
@@ -109,14 +104,6 @@ onMounted(() => {
|
||||
name: $t('commons.assistant')
|
||||
}"
|
||||
></TopDesktopCard>
|
||||
<TopDesktopCard
|
||||
v-if="appearanceStore.getShowCopilot"
|
||||
@openBlank="handleCopilotClick"
|
||||
:cardInfo="{
|
||||
icon: copilot,
|
||||
name: 'Copilot'
|
||||
}"
|
||||
></TopDesktopCard>
|
||||
</div>
|
||||
<div class="border-top">
|
||||
<el-popover
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import logo from '@/assets/svg/logo.svg'
|
||||
import copilot from '@/assets/svg/copilot.svg'
|
||||
import msgNotice from '@/assets/svg/icon_notification_outlined.svg'
|
||||
import dvAi from '@/assets/svg/dv-ai.svg'
|
||||
import dvPreviewDownload from '@/assets/svg/icon_download_outlined.svg'
|
||||
@@ -22,7 +21,6 @@ import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
|
||||
import AiComponent from '@/layout/components/AiComponent.vue'
|
||||
import { findBaseParams } from '@/api/aiComponent'
|
||||
import AiTips from '@/layout/components/AiTips.vue'
|
||||
import CopilotCom from '@/layout/components/Copilot.vue'
|
||||
import DesktopSetting from './DesktopSetting.vue'
|
||||
|
||||
const appearanceStore = useAppearanceStoreWithOut()
|
||||
@@ -42,9 +40,6 @@ const handleAiClick = () => {
|
||||
useEmitt().emitter.emit('aiComponentChange')
|
||||
}
|
||||
const { t } = useI18n()
|
||||
const handleCopilotClick = () => {
|
||||
push('/copilot/index')
|
||||
}
|
||||
|
||||
const desktop = isDesktop()
|
||||
const activeIndex = computed(() => {
|
||||
@@ -111,10 +106,6 @@ const msgNoticePush = () => {
|
||||
push('/msg/msg-fill')
|
||||
}
|
||||
|
||||
const copilotConfirm = () => {
|
||||
wsCache.set('DE-COPILOT-TIPS-CHECK', 'CHECKED')
|
||||
showOverlayCopilot.value = false
|
||||
}
|
||||
const badgeCount = ref('0')
|
||||
|
||||
onMounted(() => {
|
||||
@@ -146,20 +137,6 @@ onMounted(() => {
|
||||
</el-menu>
|
||||
<div class="operate-setting" v-if="!desktop">
|
||||
<XpackComponent jsname="c3dpdGNoZXI=" />
|
||||
<el-tooltip effect="dark" content="Copilot" placement="bottom">
|
||||
<el-icon
|
||||
style="margin: 0 10px"
|
||||
class="ai-icon copilot-icon"
|
||||
v-if="!showOverlayCopilot && appearanceStore.getShowCopilot"
|
||||
>
|
||||
<Icon name="copilot"><copilot @click="handleCopilotClick" class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<CopilotCom
|
||||
@confirm="copilotConfirm"
|
||||
v-if="showOverlayCopilot && appearanceStore.getShowCopilot"
|
||||
class="copilot-icon-tips"
|
||||
/>
|
||||
<el-tooltip effect="dark" :content="t('commons.assistant')" placement="bottom">
|
||||
<el-icon
|
||||
style="margin: 0 10px"
|
||||
@@ -215,7 +192,6 @@ onMounted(() => {
|
||||
:base-url="aiBaseUrl"
|
||||
></ai-component>
|
||||
<div v-if="showOverlay && appearanceStore.getShowAi" class="overlay"></div>
|
||||
<div v-if="showOverlayCopilot && appearanceStore.getShowCopilot" class="overlay"></div>
|
||||
</div>
|
||||
<div v-else class="operate-setting">
|
||||
<desktop-setting />
|
||||
|
||||
@@ -23,7 +23,6 @@ const DashboardPanel = defineAsyncComponent(
|
||||
() => import('@/views/dashboard/DashboardPreviewShow.vue')
|
||||
)
|
||||
|
||||
const Copilot = defineAsyncComponent(() => import('@/views/copilot/index.vue'))
|
||||
const TemplateManage = defineAsyncComponent(() => import('@/views/template/indexInject.vue'))
|
||||
|
||||
const Preview = defineAsyncComponent(() => import('@/views/data-visualization/PreviewCanvas.vue'))
|
||||
@@ -49,7 +48,6 @@ const componentMap = {
|
||||
DashboardPanel,
|
||||
DatasetEditor,
|
||||
DashboardEmpty,
|
||||
Copilot,
|
||||
TemplateManage
|
||||
}
|
||||
|
||||
|
||||
@@ -20,22 +20,6 @@ export const routes: AppRouteRecordRaw[] = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/copilot',
|
||||
name: 'copilot',
|
||||
component: () => import('@/layout/index.vue'),
|
||||
hidden: true,
|
||||
meta: {},
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'cpt',
|
||||
hidden: true,
|
||||
component: () => import('@/views/copilot/index.vue'),
|
||||
meta: { hidden: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
|
||||
@@ -28,7 +28,6 @@ const ScreenPanel = defineAsyncComponent(() => import('@/views/data-visualizatio
|
||||
const DashboardPanel = defineAsyncComponent(
|
||||
() => import('@/views/dashboard/DashboardPreviewShow.vue')
|
||||
)
|
||||
const Copilot = defineAsyncComponent(() => import('@/views/copilot/index.vue'))
|
||||
const TemplateManage = defineAsyncComponent(() => import('@/views/template/indexInject.vue'))
|
||||
|
||||
const AsyncXpackComponent = defineAsyncComponent(() => import('@/components/plugin/src/index.vue'))
|
||||
@@ -43,7 +42,6 @@ const componentMap = {
|
||||
Datasource,
|
||||
ScreenPanel,
|
||||
DashboardPanel,
|
||||
Copilot,
|
||||
TemplateManage
|
||||
}
|
||||
const iframeStyle = ref(null)
|
||||
|
||||
@@ -1,547 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import icon_chartLineC from '@/assets/svg/icon_chart-line-c.svg'
|
||||
import icon_dashboard_outlinedC from '@/assets/svg/icon_dashboard_outlined-c.svg'
|
||||
import icon_pie_outlinedC from '@/assets/svg/icon_pie_outlined-c.svg'
|
||||
import default_avatar from '@/assets/svg/default_avatar.svg'
|
||||
import copilot from '@/assets/svg/copilot.svg'
|
||||
import chartTable from '@/assets/svg/chart-table.svg'
|
||||
import chartDownload from '@/assets/svg/chart-download.svg'
|
||||
import { PropType, computed, onMounted, shallowRef, ref, nextTick, watch } from 'vue'
|
||||
import { useElementSize } from '@vueuse/core'
|
||||
import { downloadCanvas } from '@/utils/imgUtils'
|
||||
import ExcelJS from 'exceljs'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
interface Copilot {
|
||||
msgType: string
|
||||
question: string
|
||||
chart: object
|
||||
loading: boolean
|
||||
chartData: object
|
||||
msgStatus: number
|
||||
id: string
|
||||
}
|
||||
const props = defineProps({
|
||||
copilotInfo: {
|
||||
type: Object as PropType<Copilot>,
|
||||
default: () => ({
|
||||
msgType: 'api',
|
||||
chart: {},
|
||||
id: '',
|
||||
loading: false,
|
||||
question: '',
|
||||
chartData: {
|
||||
data: {},
|
||||
title: ''
|
||||
},
|
||||
msgStatus: 0
|
||||
})
|
||||
},
|
||||
isWelcome: {
|
||||
type: Boolean
|
||||
},
|
||||
isAnswer: {
|
||||
type: Boolean
|
||||
}
|
||||
})
|
||||
|
||||
const content = ref()
|
||||
const chartTypeList = ref()
|
||||
let columnPlot = null
|
||||
const chartRef = ref()
|
||||
const { width } = useElementSize(chartRef)
|
||||
onMounted(() => {
|
||||
const { chart, msgType, msgStatus, chartData, id } = props.copilotInfo
|
||||
/* if (msgStatus === 1 && msgType === 'api' && chartData) {
|
||||
if (['bar', 'line'].includes(chart.type)) {
|
||||
activeCommand.value = chart.type
|
||||
const chartType = chart.type === 'bar' ? Column : Line
|
||||
columnPlot = new chartType(`de-${id}-ed`, {
|
||||
data: chartData.data.data,
|
||||
xField: chart.axis?.x?.value,
|
||||
yField: chart.axis?.y?.value,
|
||||
legend: {
|
||||
layout: 'horizontal',
|
||||
position: 'left'
|
||||
}
|
||||
})
|
||||
columnPlot.render()
|
||||
} else if (chart.type === 'pie') {
|
||||
activeCommand.value = chart.type
|
||||
columnPlot = new Pie(`de-${id}-ed`, {
|
||||
appendPadding: 10,
|
||||
data: chartData.data.data,
|
||||
angleField: chart.axis?.y?.value,
|
||||
colorField: chart.axis?.x?.value,
|
||||
radius: 0.9,
|
||||
interactions: [{ type: 'element-active' }]
|
||||
})
|
||||
columnPlot.render()
|
||||
} else {
|
||||
columns.value = chart.columns.map(_ => ({
|
||||
key: `${_.value}`,
|
||||
dataKey: `${_.value}`,
|
||||
title: `${_.name}`,
|
||||
width: 150
|
||||
}))
|
||||
|
||||
data.value = chartData.data.data.map((ele, index) => {
|
||||
return {
|
||||
...ele,
|
||||
id: index + 'row'
|
||||
}
|
||||
})
|
||||
renderTableLocal.value = true
|
||||
}
|
||||
} */
|
||||
nextTick(() => {
|
||||
;(chartTypeList.value || content.value).scrollIntoView({
|
||||
block: 'end',
|
||||
inline: 'nearest',
|
||||
behavior: 'smooth'
|
||||
})
|
||||
})
|
||||
})
|
||||
const exportExcel = () => {
|
||||
const { chartData, chart } = props.copilotInfo
|
||||
const workbook = new ExcelJS.Workbook()
|
||||
const worksheet = workbook.addWorksheet('Sheet1')
|
||||
// 设置列标题
|
||||
worksheet.columns = chart.columns.map(ele => {
|
||||
return { header: ele.name, key: ele.value }
|
||||
})
|
||||
const arr = chart.columns.map(ele => ele.value)
|
||||
chartData.data.data.forEach(item => {
|
||||
worksheet.addRow(arr.map(ele => item[ele]))
|
||||
})
|
||||
// 导出excel文件
|
||||
workbook.xlsx.writeBuffer().then(buffer => {
|
||||
const blob = new Blob([buffer], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = chart.title + '.xlsx'
|
||||
link.click()
|
||||
window.URL.revokeObjectURL(url)
|
||||
})
|
||||
}
|
||||
const renderTableLocal = ref(false)
|
||||
const changeChartType = () => {
|
||||
switchChartType(activeCommand.value)
|
||||
}
|
||||
const switchChartType = type => {
|
||||
renderTableLocal.value = false
|
||||
/* nextTick(() => {
|
||||
if (columnPlot?.chart && !columnPlot.chart.wrapperElement) {
|
||||
columnPlot.chart.wrapperElement = document.querySelector(
|
||||
`#de-${props.copilotInfo.id}-ed > div`
|
||||
)
|
||||
}
|
||||
|
||||
if (columnPlot?.chart?.wrapperElement) {
|
||||
columnPlot.destroy()
|
||||
}
|
||||
if (['bar', 'line', 'pie'].includes(type)) {
|
||||
activeCommand.value = type
|
||||
}
|
||||
const { chart, msgType, msgStatus, chartData, id } = props.copilotInfo
|
||||
if (msgStatus === 1 && msgType === 'api' && chartData) {
|
||||
if (['bar', 'line'].includes(type)) {
|
||||
const chartType = type === 'bar' ? Column : Line
|
||||
const columnPlot = new chartType(`de-${id}-ed`, {
|
||||
data: chartData.data.data,
|
||||
xField: chart.axis?.x?.value,
|
||||
yField: chart.axis?.y?.value,
|
||||
legend: {
|
||||
layout: 'horizontal',
|
||||
position: 'left'
|
||||
}
|
||||
})
|
||||
columnPlot.render()
|
||||
return
|
||||
}
|
||||
|
||||
if (type === 'pie') {
|
||||
columnPlot = new Pie(`de-${id}-ed`, {
|
||||
appendPadding: 10,
|
||||
data: chartData.data.data,
|
||||
angleField: chart.axis?.y?.value,
|
||||
colorField: chart.axis?.x?.value,
|
||||
radius: 0.9,
|
||||
interactions: [{ type: 'element-active' }]
|
||||
})
|
||||
columnPlot.render()
|
||||
return
|
||||
}
|
||||
|
||||
columns.value = chart.columns.map(_ => ({
|
||||
key: `${_.value}`,
|
||||
dataKey: `${_.value}`,
|
||||
title: `${_.name}`,
|
||||
width: 150
|
||||
}))
|
||||
|
||||
data.value = chartData.data.data.map((ele, index) => {
|
||||
return {
|
||||
...ele,
|
||||
id: index + 'row'
|
||||
}
|
||||
})
|
||||
|
||||
renderTableLocal.value = true
|
||||
}
|
||||
}) */
|
||||
}
|
||||
const chartTypeRef = ref()
|
||||
const downloadChart = () => {
|
||||
if (renderTableLocal.value) {
|
||||
exportExcel()
|
||||
return
|
||||
}
|
||||
downloadCanvas('img', chartTypeRef.value, t('copilot.chart'))
|
||||
}
|
||||
watch(
|
||||
() => props.copilotInfo.loading,
|
||||
val => {
|
||||
if (!val) {
|
||||
switchChartType(renderTableLocal.value ? 'table' : activeCommand.value)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const renderTable = computed(() => {
|
||||
const { chart, msgType, msgStatus, chartData } = props.copilotInfo
|
||||
return (
|
||||
msgType === 'api' &&
|
||||
msgStatus === 1 &&
|
||||
!['bar', 'line', 'pie'].includes(chart?.type) &&
|
||||
chartData.data
|
||||
)
|
||||
})
|
||||
const activeCommand = ref('')
|
||||
|
||||
const curTypeList = [
|
||||
{
|
||||
label: t('copilot.line'),
|
||||
value: 'line',
|
||||
icon: icon_chartLineC
|
||||
},
|
||||
{
|
||||
label: t('copilot.bar'),
|
||||
icon: icon_dashboard_outlinedC,
|
||||
value: 'bar'
|
||||
},
|
||||
{
|
||||
label: t('copilot.pie'),
|
||||
icon: icon_pie_outlinedC,
|
||||
value: 'pie'
|
||||
}
|
||||
]
|
||||
|
||||
const columns = shallowRef([])
|
||||
const data = shallowRef([])
|
||||
|
||||
const tips = computed(() => {
|
||||
const { chart, msgType, question, msgStatus } = props.copilotInfo
|
||||
if (msgType === 'api' && msgStatus === 1) {
|
||||
return chart.title
|
||||
}
|
||||
if (msgStatus === 0) {
|
||||
return t('copilot.sorry')
|
||||
} else if (msgType === 'user') {
|
||||
return question
|
||||
}
|
||||
return ''
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="dialogue-chart"
|
||||
:class="[
|
||||
copilotInfo.msgType === 'user' ? 'user-dialogue' : 'api-dialogue',
|
||||
copilotInfo.msgType === 'api' && copilotInfo.msgStatus === 1 && 'chart-dialogue'
|
||||
]"
|
||||
>
|
||||
<el-icon style="font-size: 32px" class="dialogue-chart_icon">
|
||||
<Icon
|
||||
><component
|
||||
class="svg-icon"
|
||||
:is="copilotInfo.msgType === 'api' ? copilot : default_avatar"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
<div ref="content" class="content">
|
||||
<div v-if="isWelcome" class="question-or-title" style="font-size: 16px; font-weight: 500">
|
||||
{{ t('copilot.hello1') }}
|
||||
</div>
|
||||
<div v-else-if="isAnswer" class="question-or-title" style="font-size: 16px; font-weight: 500">
|
||||
{{ t('copilot.answer') }}<span class="dot">...</span>
|
||||
</div>
|
||||
<div v-else class="question-or-title">
|
||||
{{ tips }}
|
||||
</div>
|
||||
<div v-if="isWelcome" class="is-welcome">{{ t('copilot.example') }}</div>
|
||||
<div
|
||||
v-else-if="copilotInfo.msgType === 'api' && copilotInfo.msgStatus === 1"
|
||||
class="chart-type"
|
||||
ref="chartTypeRef"
|
||||
>
|
||||
<div
|
||||
v-if="!copilotInfo.loading"
|
||||
ref="chartRef"
|
||||
class="column-plot_de"
|
||||
:id="`de-${copilotInfo.id}-ed`"
|
||||
>
|
||||
<el-table-v2
|
||||
v-if="renderTable || renderTableLocal"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:width="width"
|
||||
:height="335"
|
||||
fixed
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref="chartTypeList"
|
||||
class="chart-type_list"
|
||||
v-if="copilotInfo.msgType === 'api' && copilotInfo.msgStatus === 1"
|
||||
>
|
||||
<template v-if="!renderTable">
|
||||
<el-icon
|
||||
:class="!(renderTable || renderTableLocal) && 'active'"
|
||||
v-if="activeCommand"
|
||||
class="select-prefix"
|
||||
>
|
||||
<Icon
|
||||
><component
|
||||
class="svg-icon"
|
||||
:is="curTypeList.find(ele => ele.value === activeCommand).icon"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
<el-tooltip effect="dark" :content="t('copilot.switch_chart')" placement="top">
|
||||
<div
|
||||
v-show="renderTable || renderTableLocal"
|
||||
@click="switchChartType(activeCommand)"
|
||||
class="fake-mask_select"
|
||||
></div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="t('copilot.switch_chart')" placement="top">
|
||||
<el-select
|
||||
popper-class="copilot-select_popper"
|
||||
class="select-copilot-list"
|
||||
:class="!(renderTable || renderTableLocal) && 'active'"
|
||||
v-model="activeCommand"
|
||||
size="small"
|
||||
@change="changeChartType"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in curTypeList"
|
||||
:key="item.label"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-divider direction="vertical" />
|
||||
</template>
|
||||
<el-tooltip effect="dark" :content="t('copilot.switch_table')" placement="top">
|
||||
<el-icon
|
||||
:class="(renderTable || renderTableLocal) && 'active'"
|
||||
class="ed-icon_chart"
|
||||
@click="switchChartType('table')"
|
||||
>
|
||||
<Icon name="chart-table"><chartTable class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-divider direction="vertical" />
|
||||
<el-tooltip effect="dark" :content="t('copilot.download')" placement="top">
|
||||
<el-icon class="ed-icon_chart" @click="downloadChart">
|
||||
<Icon name="chart-download"><chartDownload class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.dialogue-chart {
|
||||
display: flex;
|
||||
margin-top: 24px;
|
||||
position: relative;
|
||||
|
||||
.select-copilot-list {
|
||||
width: 40px;
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
|
||||
:deep(.ed-input__wrapper) {
|
||||
background: transparent;
|
||||
box-shadow: none !important;
|
||||
padding-right: 4px;
|
||||
.ed-input__inner {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
:deep(.ed-input__wrapper) {
|
||||
background: #3370ff1a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chart-type_list {
|
||||
position: absolute;
|
||||
bottom: -36px;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 24px;
|
||||
.fake-mask_select {
|
||||
width: 40px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
transform: translateY(-50%);
|
||||
z-index: 101;
|
||||
&:hover {
|
||||
background: #1f23291a;
|
||||
}
|
||||
}
|
||||
.ed-icon_chart {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
color: #646a73;
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: #1f23291a;
|
||||
transform: translate(-50%, -50%);
|
||||
display: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--ed-color-primary, #3370ff);
|
||||
&::after {
|
||||
display: block;
|
||||
background: #3370ff1a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-prefix {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 16px;
|
||||
color: #646a73;
|
||||
&.active {
|
||||
color: var(--ed-color-primary, #3370ff);
|
||||
}
|
||||
}
|
||||
.ed-divider--vertical {
|
||||
border-color: #1f232926;
|
||||
height: 14px;
|
||||
margin: 0 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&.chart-dialogue {
|
||||
margin-bottom: 52px;
|
||||
}
|
||||
|
||||
&.user-dialogue {
|
||||
.content {
|
||||
background: #d6e2ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.api-dialogue {
|
||||
.content {
|
||||
background: #fff;
|
||||
box-shadow: 0px 4px 8px 0px #1f23291a;
|
||||
}
|
||||
}
|
||||
|
||||
.column-plot_de {
|
||||
width: calc(100% - 32px);
|
||||
height: 335px;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
margin-left: 8px;
|
||||
border-radius: 8px;
|
||||
.question-or-title {
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
padding: 12px 16px;
|
||||
|
||||
@keyframes identifier {
|
||||
0% {
|
||||
width: 0px;
|
||||
}
|
||||
|
||||
33% {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.dot {
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
animation: identifier 1s infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.chart-type {
|
||||
height: 360px;
|
||||
border-top: 1px solid #1f232926;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.is-welcome {
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
color: #646a73;
|
||||
margin: -8px 16px 12px 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
.copilot-select_popper {
|
||||
width: 128px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,642 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import activeBtn_copilot from '@/assets/svg/active-btn_copilot.svg'
|
||||
import btn_copilot from '@/assets/svg/btn_copilot.svg'
|
||||
import copilot from '@/assets/svg/copilot.svg'
|
||||
import icon_loading_outlined from '@/assets/svg/icon_loading_outlined.svg'
|
||||
import treeSort from '@/utils/treeSortUtils'
|
||||
import icon_right_outlined from '@/assets/svg/icon_right_outlined.svg'
|
||||
import icon_left_outlined from '@/assets/svg/icon_left_outlined.svg'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
import { useEmbedded } from '@/store/modules/embedded'
|
||||
import dvFolder from '@/assets/svg/dv-folder.svg'
|
||||
import icon_dataset from '@/assets/svg/icon_dataset.svg'
|
||||
import icon_expandRight_filled from '@/assets/svg/icon_expand-right_filled.svg'
|
||||
import { ref, shallowRef, computed, watch, nextTick, unref } from 'vue'
|
||||
import { ElMessageBox } from 'element-plus-secondary'
|
||||
import {
|
||||
getDatasetTree,
|
||||
clearAllCopilot,
|
||||
copilotFields,
|
||||
getListCopilot,
|
||||
copilotChat
|
||||
} from '@/api/dataset'
|
||||
import { useElementSize } from '@vueuse/core'
|
||||
import { fieldType } from '@/utils/attr'
|
||||
import DialogueChart from '@/views/copilot/DialogueChart.vue'
|
||||
import { type Tree } from '@/views/visualized/data/dataset/form/CreatDsGroup.vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { iconFieldMap } from '@/components/icon-group/field-list'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
|
||||
const embeddedStore = useEmbedded()
|
||||
const { wsCache } = useCache()
|
||||
const { t } = useI18n()
|
||||
const quota = shallowRef([])
|
||||
const dimensions = shallowRef([])
|
||||
const datasetTree = shallowRef([])
|
||||
const historyArr = ref([])
|
||||
const datasetId = ref('')
|
||||
const questionInput = ref('')
|
||||
const showLeft = ref(false)
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name'
|
||||
}
|
||||
|
||||
const dsSelectProps = {
|
||||
label: 'name',
|
||||
children: 'children',
|
||||
value: 'id',
|
||||
isLeaf: node => !node.children?.length
|
||||
}
|
||||
const expandedD = ref(true)
|
||||
const expandedQ = ref(true)
|
||||
const dfs = arr => {
|
||||
return arr.filter(ele => {
|
||||
if (!!ele.children?.length && !ele.leaf) {
|
||||
ele.children = dfs(ele.children)
|
||||
return !!ele.children?.length
|
||||
}
|
||||
return ele.leaf
|
||||
})
|
||||
}
|
||||
const originResourceTree = ref([])
|
||||
const computedTree = computed(() => {
|
||||
if (datasetTree.value[0]?.id === '0') {
|
||||
return dfs(datasetTree.value[0].children)
|
||||
}
|
||||
return dfs(datasetTree.value)
|
||||
})
|
||||
|
||||
const isActive = computed(() => {
|
||||
return questionInput.value.trim().length && !!datasetId.value
|
||||
})
|
||||
const sortList = ['time_asc', 'time_desc', 'name_asc', 'name_desc']
|
||||
const initDataset = async () => {
|
||||
await getDatasetTree({}).then(res => {
|
||||
datasetTree.value = (res as unknown as Tree[]) || []
|
||||
let curSortType = sortList[Number(wsCache.get('TreeSort-backend')) ?? 1]
|
||||
curSortType = wsCache.get('TreeSort-dataset') ?? curSortType
|
||||
originResourceTree.value = cloneDeep(unref(datasetTree))
|
||||
datasetTree.value = treeSort(originResourceTree.value, curSortType)
|
||||
})
|
||||
getListCopilot().then(res => {
|
||||
const allList = (res as unknown as { history: object }[]) || []
|
||||
historyBack = allList[allList.length - 1]?.history || []
|
||||
historyArr.value = cloneDeep(allList).map(ele => ({ ...ele, loading: false }))
|
||||
if (!!allList.length) {
|
||||
datasetId.value = allList[0].datasetGroupId
|
||||
oldId = datasetId.value
|
||||
datasetId.value && getOptions(datasetId.value)
|
||||
if (oldId && !oldName) {
|
||||
nextTick(() => {
|
||||
dfsName(computedTree.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const treeSelectRef = ref()
|
||||
let oldId = ''
|
||||
let currentId = ''
|
||||
let oldName = ''
|
||||
|
||||
const copilotDialogueComputed = computed(() => {
|
||||
if (embeddedStore.baseUrl) {
|
||||
return { height: `100%` }
|
||||
}
|
||||
return { height: `calc(100vh - ${height + 152}px)` }
|
||||
})
|
||||
const dfsName = arr => {
|
||||
return arr.filter(ele => {
|
||||
if (ele.id === oldId) {
|
||||
oldName = ele.name
|
||||
}
|
||||
if (!!ele.children?.length && !ele.leaf) {
|
||||
ele.children = dfsName(ele.children)
|
||||
return !!ele.children?.length
|
||||
}
|
||||
return ele.leaf
|
||||
})
|
||||
}
|
||||
const handleDatasetChange = () => {
|
||||
if (!!oldId && !!historyArr.value.length) {
|
||||
currentId = datasetId.value
|
||||
datasetId.value = oldId
|
||||
const msg = t('copilot.ds_prefix') + oldName + t('copilot.ds_suffix')
|
||||
ElMessageBox.confirm(t('copilot.confirm'), {
|
||||
confirmButtonType: 'primary',
|
||||
type: 'warning',
|
||||
tip: msg,
|
||||
autofocus: false,
|
||||
showClose: false
|
||||
}).then(() => {
|
||||
datasetId.value = currentId
|
||||
oldId = datasetId.value
|
||||
oldName = treeSelectRef.value.getCurrentNode().name
|
||||
getOptions(datasetId.value)
|
||||
clearAllCopilot().then(() => {
|
||||
historyArr.value = []
|
||||
historyBack = []
|
||||
})
|
||||
})
|
||||
} else {
|
||||
oldId = datasetId.value
|
||||
oldName = treeSelectRef.value.getCurrentNode().name
|
||||
getOptions(datasetId.value)
|
||||
}
|
||||
}
|
||||
const getOptions = id => {
|
||||
copilotFields(id).then(res => {
|
||||
dimensions.value = res.data?.dimensionList || []
|
||||
quota.value = res.data?.quotaList || []
|
||||
})
|
||||
}
|
||||
initDataset()
|
||||
let historyBack = []
|
||||
|
||||
const questionInputRef = ref()
|
||||
const overHeight = ref(false)
|
||||
const { height } = useElementSize(questionInputRef)
|
||||
watch(
|
||||
() => height.value,
|
||||
val => {
|
||||
overHeight.value = val > 48
|
||||
}
|
||||
)
|
||||
|
||||
const handleShowLeft = val => {
|
||||
showLeft.value = val
|
||||
historyArr.value.forEach(ele => {
|
||||
ele.loading = true
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
historyArr.value.forEach(ele => {
|
||||
ele.loading = false
|
||||
})
|
||||
}, 300)
|
||||
}
|
||||
const copilotChatLoading = ref(false)
|
||||
const inputRef = ref()
|
||||
const queryAnswer = (event?: KeyboardEvent) => {
|
||||
if (event?.keyCode === 229) {
|
||||
return
|
||||
}
|
||||
|
||||
if (event?.keyCode === 13) {
|
||||
event.preventDefault()
|
||||
}
|
||||
let copyAuestionInput = questionInput.value
|
||||
if (!isActive.value || copilotChatLoading.value) return
|
||||
questionInput.value = ''
|
||||
inputRef.value.blur()
|
||||
nextTick(() => {
|
||||
overHeight.value = false
|
||||
})
|
||||
historyArr.value.push({
|
||||
msgType: 'user',
|
||||
chart: {},
|
||||
id: `${+new Date()}`,
|
||||
question: copyAuestionInput,
|
||||
chartData: {
|
||||
data: {},
|
||||
title: ''
|
||||
},
|
||||
msgStatus: 1
|
||||
})
|
||||
copilotChatLoading.value = true
|
||||
copilotChat({
|
||||
datasetGroupId: datasetId.value,
|
||||
question: copyAuestionInput,
|
||||
history: historyBack
|
||||
})
|
||||
.then(res => {
|
||||
historyArr.value.push({ ...(res || {}), loading: false })
|
||||
historyBack = res.history || []
|
||||
})
|
||||
.finally(() => {
|
||||
copilotChatLoading.value = false
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="copilot">
|
||||
<div class="copilot-analysis">
|
||||
<el-icon style="margin-right: 8px; font-size: 24px">
|
||||
<Icon name="copilot"><copilot class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
{{ t('copilot.talking_analysis') }}
|
||||
</div>
|
||||
<div class="copilot-service">
|
||||
<div class="dialogue">
|
||||
<div class="copilot-dialogue" :style="copilotDialogueComputed">
|
||||
<DialogueChart key="isWelcome" isWelcome></DialogueChart>
|
||||
<DialogueChart :copilotInfo="ele" v-for="ele in historyArr" :key="ele.id"></DialogueChart>
|
||||
<DialogueChart v-if="copilotChatLoading" key="isAnswer" isAnswer></DialogueChart>
|
||||
</div>
|
||||
<div class="question-input" :class="overHeight && 'over-height'" ref="questionInputRef">
|
||||
<el-input
|
||||
v-model="questionInput"
|
||||
@keydown.stop
|
||||
ref="inputRef"
|
||||
@keydown.enter="queryAnswer"
|
||||
:autosize="{ minRows: 1, maxRows: 8 }"
|
||||
type="textarea"
|
||||
:placeholder="$t('common.inputText')"
|
||||
>
|
||||
</el-input>
|
||||
<el-icon v-if="copilotChatLoading" class="copilot-icon circular-input_icon">
|
||||
<Icon name="icon_loading_outlined"><icon_loading_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
<el-icon v-else class="copilot-icon" @click="queryAnswer" :class="isActive && 'active'">
|
||||
<Icon
|
||||
><component
|
||||
class="svg-icon"
|
||||
:is="isActive ? activeBtn_copilot : btn_copilot"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dataset-select" :style="{ width: showLeft ? 0 : '280px' }">
|
||||
<el-tooltip effect="dark" :content="t('relation.retract')" placement="left">
|
||||
<p v-show="!showLeft" class="arrow-right" @click="handleShowLeft(true)">
|
||||
<el-icon>
|
||||
<Icon name="icon_right_outlined"><icon_right_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</p>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="t('relation.expand')" placement="left">
|
||||
<p v-show="showLeft" class="left-outlined" @click="handleShowLeft(false)">
|
||||
<el-icon>
|
||||
<Icon name="icon_left_outlined"><icon_left_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</p>
|
||||
</el-tooltip>
|
||||
|
||||
<div style="width: 100%; height: calc(100% - 16px)" v-show="!showLeft">
|
||||
<div class="title-dataset_select">{{ t('copilot.choose_dataset') }}</div>
|
||||
<div style="margin: 0 16px" class="tree-select">
|
||||
<el-tree-select
|
||||
v-model="datasetId"
|
||||
:data="computedTree"
|
||||
:placeholder="t('copilot.pls_choose_dataset')"
|
||||
@change="handleDatasetChange"
|
||||
:props="dsSelectProps"
|
||||
style="width: 100%"
|
||||
node-key="id"
|
||||
ref="treeSelectRef"
|
||||
placement="bottom"
|
||||
:render-after-expand="false"
|
||||
filterable
|
||||
popper-class="dataset-tree"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="content">
|
||||
<el-icon size="18px" v-if="!data.leaf">
|
||||
<Icon name="dv-folder"><dvFolder class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
<el-icon size="18px" v-if="data.leaf">
|
||||
<Icon name="icon_dataset"><icon_dataset class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
<span class="label ellipsis" style="margin-left: 8px" :title="node.label">{{
|
||||
node.label
|
||||
}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</div>
|
||||
<div class="preview-field">
|
||||
<div :class="['field-d', { open: expandedD }]">
|
||||
<div :class="['title', { expanded: expandedD }]" @click="expandedD = !expandedD">
|
||||
<ElIcon class="expand">
|
||||
<Icon><icon_expandRight_filled class="svg-icon" /></Icon>
|
||||
</ElIcon>
|
||||
{{ $t('chart.dimension') }}
|
||||
</div>
|
||||
<el-tree v-if="expandedD" :data="dimensions" :props="defaultProps">
|
||||
<template #default="{ data }">
|
||||
<span class="custom-tree-node father">
|
||||
<el-icon>
|
||||
<Icon
|
||||
><component
|
||||
class="svg-icon"
|
||||
:class="`field-icon-${
|
||||
fieldType[[2, 3].includes(data.deExtractType) ? 2 : 0]
|
||||
}`"
|
||||
:is="iconFieldMap[fieldType[data.deExtractType]]"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
<span :title="data.name" class="label-tooltip">{{ data.name }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
<div class="line-bottom"></div>
|
||||
<div :class="['field-q', { open: expandedQ }]">
|
||||
<div :class="['title', { expanded: expandedQ }]" @click="expandedQ = !expandedQ">
|
||||
<ElIcon class="expand">
|
||||
<Icon name="icon_expand-right_filled"
|
||||
><icon_expandRight_filled class="svg-icon"
|
||||
/></Icon>
|
||||
</ElIcon>
|
||||
{{ $t('chart.quota') }}
|
||||
</div>
|
||||
<el-tree v-if="expandedQ" :data="quota" :props="defaultProps">
|
||||
<template #default="{ data }">
|
||||
<span class="custom-tree-node father">
|
||||
<el-icon>
|
||||
<Icon
|
||||
><component
|
||||
class="svg-icon"
|
||||
:class="`field-icon-${
|
||||
fieldType[[2, 3].includes(data.deExtractType) ? 2 : 0]
|
||||
}`"
|
||||
:is="iconFieldMap[fieldType[data.deExtractType]]"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
<span :title="data.name" class="label-tooltip">{{ data.name }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.copilot {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 56px);
|
||||
|
||||
.copilot-analysis {
|
||||
background-color: #fff;
|
||||
padding: 16px 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
border-bottom: 1px solid #1f232926;
|
||||
}
|
||||
|
||||
.copilot-service {
|
||||
width: 100%;
|
||||
height: calc(100% - 58px);
|
||||
display: flex;
|
||||
overflow-y: auto;
|
||||
.dialogue {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
max-height: 100%;
|
||||
|
||||
.copilot-dialogue {
|
||||
padding: 0 160px;
|
||||
padding-top: 24px;
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 60px;
|
||||
max-height: calc(100% - 75px);
|
||||
}
|
||||
.question-input {
|
||||
min-height: 47px;
|
||||
width: calc(100% - 360px);
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
border: 1px solid #fff;
|
||||
bottom: 25px;
|
||||
border-radius: 8px;
|
||||
left: 180px;
|
||||
z-index: 100;
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
box-shadow: 0px 6px 24px 0px #1f232914;
|
||||
&:hover {
|
||||
border: 1px solid var(--ed-color-primary);
|
||||
}
|
||||
|
||||
&:has(.ed-textarea__inner:focus) {
|
||||
border: 1px solid var(--ed-color-primary);
|
||||
}
|
||||
|
||||
:deep(.ed-textarea__inner) {
|
||||
border-radius: 8px !important;
|
||||
box-shadow: none;
|
||||
resize: none;
|
||||
padding: 12px 16px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
&.over-height :deep(.ed-textarea__inner) {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.copilot-icon {
|
||||
position: absolute !important;
|
||||
bottom: 12px;
|
||||
right: 16px;
|
||||
font-size: 24px;
|
||||
cursor: not-allowed;
|
||||
position: relative;
|
||||
&.active {
|
||||
cursor: pointer;
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
border-radius: 8px;
|
||||
display: none;
|
||||
background: #3370ff1a;
|
||||
}
|
||||
&:hover {
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes circular {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.circular-input_icon {
|
||||
animation: circular 1s infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dataset-select {
|
||||
width: 280px;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
border-left: 1px solid #1f232926;
|
||||
position: relative;
|
||||
|
||||
.left-outlined {
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
left: -20px;
|
||||
top: 16px;
|
||||
width: 20px;
|
||||
height: 24px;
|
||||
border-top-left-radius: 50%;
|
||||
border-bottom-left-radius: 50%;
|
||||
box-shadow: 0px 4px 8px 0px #0000001a;
|
||||
border: 1px solid #dee0e3;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
& > .ed-icon {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
width: 24px;
|
||||
left: -24px;
|
||||
color: var(--ed-color-primary, #3370ff);
|
||||
& > .ed-icon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-right {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
left: -12px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #dee0e3;
|
||||
background: #fff;
|
||||
font-size: 12px;
|
||||
border-radius: 50%;
|
||||
&:hover {
|
||||
color: var(--ed-color-primary, #3370ff);
|
||||
}
|
||||
}
|
||||
|
||||
.title-dataset_select {
|
||||
width: 100%;
|
||||
margin: 16px 16px 12px 0;
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.preview-field {
|
||||
padding: 0 8px;
|
||||
width: 100%;
|
||||
height: calc(100% - 100px);
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
|
||||
:deep(.ed-tree-node__content) {
|
||||
border-radius: 4px;
|
||||
&:hover {
|
||||
background: #1f23291a;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ed-tree-node.is-current > .ed-tree-node__content:not(.is-menu):after) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.custom-tree-node {
|
||||
width: calc(100% - 32px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 8px;
|
||||
box-sizing: content-box;
|
||||
|
||||
.label-tooltip {
|
||||
margin-left: 5.33px;
|
||||
width: 70%;
|
||||
font-size: 14px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.field-d,
|
||||
.field-q {
|
||||
position: relative;
|
||||
height: 49px;
|
||||
padding: 0 8px;
|
||||
|
||||
&.open {
|
||||
max-height: 50%;
|
||||
height: 50%;
|
||||
}
|
||||
.title {
|
||||
cursor: pointer;
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
height: 49px;
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: #1f2329;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 9;
|
||||
background-color: #fff;
|
||||
|
||||
.expand {
|
||||
font-size: 10px;
|
||||
color: #646a73;
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
.expand {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.field-d {
|
||||
max-height: calc(100% - 52px);
|
||||
}
|
||||
|
||||
.line-bottom {
|
||||
background: rgba(31, 35, 41, 0.15);
|
||||
height: 1px;
|
||||
width: calc(100% - 16px);
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user