484 lines
10 KiB
Vue
Executable File
484 lines
10 KiB
Vue
Executable File
<script lang="ts" setup>
|
|
import {Check, ChevronRight, Settings} from "lucide-vue-next"
|
|
import {charts} from "~/config/charts";
|
|
import {type cardConfigType, type IGridItem, useMainLayoutStore} from "~/strores/UseMainLayoutStore";
|
|
import {v4 as uuidv4} from 'uuid';
|
|
|
|
const mainLayoutStore = useMainLayoutStore()
|
|
const select = ref(0)
|
|
export type serverValueItem = {
|
|
dataName: string,
|
|
dataType: string,
|
|
serverId:string
|
|
}
|
|
const props = defineProps({
|
|
closeCallback: {
|
|
type: Function,
|
|
required: true
|
|
},
|
|
isSetting: {
|
|
type: Boolean,
|
|
},
|
|
cardId: {
|
|
type: String,
|
|
}
|
|
})
|
|
const steps = ref([
|
|
{
|
|
label: '图表',
|
|
}, {
|
|
label: '数据',
|
|
}, {
|
|
label: '设置',
|
|
},
|
|
{
|
|
label: '预览',
|
|
end: true,
|
|
}
|
|
])
|
|
const ServerValues = ref<serverValueItem[]>([])
|
|
const ServerSelect = ref<serverValueItem[]>([])
|
|
const CardSettings = ref<cardConfigType>({
|
|
name: {
|
|
label: '卡片名称',
|
|
value: '默认卡片名称',
|
|
type: 'text',
|
|
},
|
|
description: {
|
|
label: '卡片描述',
|
|
value: '这是一张默认的卡片',
|
|
type: 'text',
|
|
},
|
|
foreground: {
|
|
label: '卡片前景色',
|
|
value: 'ffffff',
|
|
type: 'color',
|
|
},
|
|
color: {
|
|
label: '图表主色',
|
|
value: '002EA6',
|
|
type: 'color',
|
|
}
|
|
})
|
|
const ValueIds = ref<string[]>([])
|
|
const stepNext = () => {
|
|
if (select.value === 2) {
|
|
ValueIds.value = ServerSelect.value.map(item => item.dataType)
|
|
}
|
|
select.value++
|
|
}
|
|
|
|
const stepPrev = () => {
|
|
select.value--
|
|
}
|
|
|
|
const stepFinish = () => {
|
|
if (props.isSetting) {
|
|
for (const configKey in mainLayoutStore.LayoutsConfig) {
|
|
let config = mainLayoutStore.LayoutsConfig[configKey].find(x => x.i === props.cardId)
|
|
if (!config) return;
|
|
config = config as IGridItem
|
|
config.serverValues = ServerSelect.value
|
|
config.cardConfig = CardSettings.value
|
|
config.selectChart = charts[selectChart.value].id
|
|
}
|
|
props.closeCallback()
|
|
return
|
|
}
|
|
const newItem: IGridItem = {
|
|
type: "chart",
|
|
chartRage: 6,
|
|
serverValues: ServerSelect.value.filter(i => i.dataName && i.dataName !== ''),
|
|
i: uuidv4(),
|
|
x: 1,
|
|
y: 1,
|
|
h: 5,
|
|
w: 5,
|
|
selectChart: charts[selectChart.value].id,
|
|
cardConfig: CardSettings.value
|
|
};
|
|
console.log(newItem)
|
|
mainLayoutStore.addLayout(newItem)
|
|
props.closeCallback()
|
|
}
|
|
|
|
const addServerValue = () => {
|
|
console.log(ServerSelect.value)
|
|
ServerSelect.value.push(<serverValueItem>{});
|
|
}
|
|
const removeServerValue = (index: number) => {
|
|
// 从索引 index 开始删除 1 个元素
|
|
ServerSelect.value.splice(index, 1);
|
|
};
|
|
const selectChart = ref<number>(0);
|
|
onMounted(() => {
|
|
$fetch('/Api/Job/GetJobList', {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': 'Bearer ' + useCookie('token').value
|
|
},
|
|
params: {
|
|
serverId: mainLayoutStore.SelectServer.id
|
|
},
|
|
baseURL: useRuntimeConfig().public.baseUrl
|
|
}).then(res => {
|
|
console.log(res)
|
|
ServerValues.value = res as serverValueItem[];
|
|
//排序
|
|
ServerValues.value.sort((a, b) => {
|
|
return a.dataName.localeCompare(b.dataName);
|
|
})
|
|
})
|
|
})
|
|
onMounted(() => {
|
|
if (!props.isSetting) {
|
|
return
|
|
}
|
|
select.value = 2
|
|
let config = mainLayoutStore.LayoutsConfig.lg.find(x => x.i === props.cardId)
|
|
// 断言config类型
|
|
if (!config) return;
|
|
config = config as IGridItem
|
|
if (!config.serverValues) return;
|
|
ServerSelect.value = config.serverValues.map(x => {
|
|
return x
|
|
})
|
|
if (!config.cardConfig) return;
|
|
CardSettings.value = config.cardConfig
|
|
if (!config.selectChart) return;
|
|
selectChart.value = charts.findIndex(x => x.id == config.selectChart)
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="setting-card-layout">
|
|
<div class="card-top">
|
|
<template v-for="(step, index) in steps">
|
|
<div
|
|
:class="{'card-step-item':true,'card-step-item-active':select===index,'card-step-item-activated':select>index}">
|
|
<div><p v-if="select<=index">{{ index + 1 }}</p>
|
|
<Check v-else :size="18"/>
|
|
</div>
|
|
<h3>{{ step.label }}</h3>
|
|
</div>
|
|
<ChevronRight v-if="!step.end"/>
|
|
</template>
|
|
</div>
|
|
<div class="card-split"></div>
|
|
<div class="card-container">
|
|
<div v-if="select===0" class="step1-box">
|
|
<div v-for="(chart,index) in charts" :class="{'chart-box':true,'chart-box-active':selectChart===index}">
|
|
<NuxtImg v-tooltip="chart.description" :src="chart.image" draggable="false" @click="selectChart=index"/>
|
|
</div>
|
|
</div>
|
|
<div v-if="select===1" class="step2-box">
|
|
<div v-for="(chart,index) in ServerSelect" class="Select-box">
|
|
<p>数据槽 {{ index + 1 }}</p>
|
|
<Dropdown v-model="ServerSelect[index]" :highlightOnSelect="false" :options="ServerValues" :pt="{
|
|
root:{
|
|
style:'background:#eee'
|
|
}
|
|
}"
|
|
checkmark optionLabel="dataName" placeholder="选择一个数据来源"/>
|
|
<Icon :size="20" :stroke-width="0.7" name="X" @click="removeServerValue(index)"/>
|
|
</div>
|
|
<Button icon="pi pi-plus" label="添加一个数据槽" @click="addServerValue"/>
|
|
</div>
|
|
<div v-if="select===2" class="step3-box">
|
|
<div v-for="setting in CardSettings" class="setting-box">
|
|
<p>{{ setting.label }}</p>
|
|
<InputText v-if="setting.type==='text'" id="username" v-model="setting.value"/>
|
|
<ColorPicker v-if="setting.type==='color'" v-model="setting.value"/>
|
|
</div>
|
|
</div>
|
|
<div v-if="select===3" class="step4-box">
|
|
<div class="card-layout">
|
|
<div class="card-title">
|
|
<div></div>
|
|
<h3>{{ CardSettings['name'].value }}</h3>
|
|
</div>
|
|
<component :is="charts[selectChart].component" :valueIds="ValueIds"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-action">
|
|
<button :style="{visibility:select>0?'visible':'hidden'}" @click="stepPrev">后退</button>
|
|
<button v-if="select<3" @click="stepNext">前进</button>
|
|
<button v-else @click="stepFinish">完成</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "base";
|
|
|
|
.setting-card-layout {
|
|
width: 100%;
|
|
display: grid;
|
|
padding: $padding*2;
|
|
grid-template-rows: auto auto 1fr auto;
|
|
gap: $gap*4;
|
|
background: $light-bg-color;
|
|
border-radius: $radius*2;
|
|
|
|
.dark-mode & {
|
|
background: $dark-bg-color;
|
|
}
|
|
}
|
|
|
|
.card-top {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
gap: $gap*2;
|
|
}
|
|
|
|
.card-step-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: $gap;
|
|
|
|
div {
|
|
display: flex;
|
|
width: 28px;
|
|
height: 28px;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 10px;
|
|
border-radius: 100px;
|
|
font-size: 14px;
|
|
font-style: normal;
|
|
font-weight: 700;
|
|
color: #8D8D99;
|
|
background: #E1E1E6;
|
|
}
|
|
|
|
h3 {
|
|
color: #8D8D99;
|
|
font-size: 16px;
|
|
font-style: normal;
|
|
font-weight: 700;
|
|
line-height: 150%; /* 24px */
|
|
}
|
|
}
|
|
|
|
.card-step-item-active {
|
|
|
|
div {
|
|
color: #FFFFFF;
|
|
background: $primary-color;
|
|
}
|
|
|
|
h3 {
|
|
color: $light-text-color;
|
|
|
|
.dark-mode & {
|
|
color: $dark-text-color;
|
|
}
|
|
}
|
|
}
|
|
|
|
.card-step-item-activated {
|
|
div {
|
|
background: #1D8841;
|
|
|
|
svg {
|
|
stroke: #FFF;
|
|
margin-top: 2.5px;
|
|
}
|
|
}
|
|
|
|
h3 {
|
|
color: $light-text-color;
|
|
|
|
.dark-mode & {
|
|
color: $dark-text-color;
|
|
}
|
|
}
|
|
}
|
|
|
|
.card-split {
|
|
width: 95%;
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
height: 1px;
|
|
background: $unfocused-color;
|
|
|
|
}
|
|
|
|
.card-container {
|
|
min-height: 200px;
|
|
height: 100%;
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
|
|
&::-webkit-scrollbar {
|
|
width: 0;
|
|
}
|
|
}
|
|
|
|
.card-action {
|
|
height: 56px;
|
|
gap: $gap*4;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
|
|
button {
|
|
display: flex;
|
|
width: 158px;
|
|
padding: 16px 32px;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 16px;
|
|
font-style: normal;
|
|
font-weight: 700;
|
|
line-height: 150%; /* 24px */
|
|
text-transform: uppercase;
|
|
border: unset;
|
|
outline: unset;
|
|
background: unset;
|
|
cursor: pointer;
|
|
border-radius: 6px;
|
|
}
|
|
|
|
button:first-of-type {
|
|
|
|
color: $primary-color;
|
|
|
|
border: 2px solid $primary-color;
|
|
}
|
|
|
|
button:last-of-type {
|
|
background: $primary-color;
|
|
color: #FFF;
|
|
}
|
|
}
|
|
|
|
.step1-box {
|
|
display: grid;
|
|
width: 100%;
|
|
height: 100%;
|
|
grid-template-columns: 1fr 1fr 1fr;
|
|
gap: $gap*2;
|
|
grid-template-rows: repeat(auto-fit, auto);
|
|
|
|
.chart-box {
|
|
min-width: 120px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $gap;
|
|
border: 1px solid #E1E1E6;
|
|
height: min-content;
|
|
border-radius: $radius*2;
|
|
padding: $padding;
|
|
background: #f4f4f4;
|
|
|
|
.dark-mode & {
|
|
background: $dark-bg-underline-color;
|
|
border-color: $unfocused-color;
|
|
}
|
|
}
|
|
|
|
.chart-box-active {
|
|
border: 2px solid $primary-color;
|
|
}
|
|
}
|
|
|
|
.step2-box {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $gap*2;
|
|
padding: 0 0 $padding*4 0;
|
|
|
|
> button {
|
|
background: $primary-color;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.Select-box {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: $gap;
|
|
|
|
.p-dropdown {
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
.step3-box {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $gap*2;
|
|
|
|
|
|
.setting-box {
|
|
display: flex;
|
|
gap: $gap;
|
|
align-items: center;
|
|
|
|
.p-inputtext {
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
:deep(.p-inputtext) {
|
|
color: $light-text-color;
|
|
}
|
|
|
|
|
|
.step4-box {
|
|
background: $light-bg-underline-color;
|
|
padding: $padding;
|
|
height: 100%;
|
|
border-radius: $radius*2;
|
|
|
|
.dark-mode & {
|
|
background: $dark-bg-underline-color;
|
|
}
|
|
}
|
|
|
|
.card-layout {
|
|
width: 100%;
|
|
height: 100%;
|
|
min-height: 250px;
|
|
background: $light-bg-color;
|
|
border-radius: $radius*2;
|
|
box-shadow: 0 10px 30px 0 rgba(17, 38, 146, 0.05);
|
|
padding: $padding*1.5;
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $gap*2;
|
|
|
|
&:hover {
|
|
cursor: move;
|
|
}
|
|
|
|
.dark-mode & {
|
|
background: $dark-bg-color;
|
|
}
|
|
}
|
|
|
|
.card-title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: $gap;
|
|
color: $light-text-color;
|
|
|
|
.dark-mode & {
|
|
color: $dark-text-color;
|
|
}
|
|
|
|
div {
|
|
width: 6px;
|
|
height: 20px;
|
|
border-radius: $radius;
|
|
background: $primary-color;
|
|
}
|
|
}
|
|
</style> |