Commit 6eb1ff55 by Jony.L

大屏页面和后台管理调整1.0

parent 71ffe7d8
import request from '@/config/axios'
import type { Dayjs } from 'dayjs';
/** 首页大屏模拟数据配置信息 */
export interface HomeDashboardMock {
id: number; // 主键ID
configKey?: string; // 配置key
configType?: string; // 配置类型:switch开关/data数据
configValue: string; // 配置值
description: string; // 配置描述
}
// 首页大屏模拟数据配置 API
export const HomeDashboardMockApi = {
// 查询首页大屏模拟数据配置分页
getHomeDashboardMockPage: async (params: any) => {
return await request.get({ url: `/biz/home-dashboard-mock/page`, params })
},
// 查询首页大屏模拟数据配置详情
getHomeDashboardMock: async (id: number) => {
return await request.get({ url: `/biz/home-dashboard-mock/get?id=` + id })
},
// 新增首页大屏模拟数据配置
createHomeDashboardMock: async (data: HomeDashboardMock) => {
return await request.post({ url: `/biz/home-dashboard-mock/create`, data })
},
// 修改首页大屏模拟数据配置
updateHomeDashboardMock: async (data: HomeDashboardMock) => {
return await request.put({ url: `/biz/home-dashboard-mock/update`, data })
},
// 删除首页大屏模拟数据配置
deleteHomeDashboardMock: async (id: number) => {
return await request.delete({ url: `/biz/home-dashboard-mock/delete?id=` + id })
},
/** 批量删除首页大屏模拟数据配置 */
deleteHomeDashboardMockList: async (ids: number[]) => {
return await request.delete({ url: `/biz/home-dashboard-mock/delete-list?ids=${ids.join(',')}` })
},
// 导出首页大屏模拟数据配置 Excel
exportHomeDashboardMock: async (params) => {
return await request.download({ url: `/biz/home-dashboard-mock/export-excel`, params })
}
}
\ No newline at end of file
......@@ -4,7 +4,7 @@
</template>
<script setup>
import { onBeforeUnmount, onMounted, ref, nextTick } from 'vue'
import { onBeforeUnmount, onMounted, ref, nextTick, inject, watch } from 'vue'
import * as echarts from 'echarts/core'
import { TooltipComponent, VisualMapComponent, GeoComponent, GridComponent, LegendComponent } from 'echarts/components'
import {
......@@ -18,6 +18,9 @@ import geoJson from '@/assets/mapJson/china.json'
import labelGreen from '@/assets/images/label-green.png'
import labelRed from '@/assets/images/label-red.png'
// 从父组件获取统一数据
const dashboardData = inject('dashboardData', {})
echarts.use([
GridComponent,
LegendComponent,
......@@ -33,14 +36,40 @@ echarts.use([
])
const geoCoordMap = ref({
浙江省: [120.153576, 30.287459],
上海市: [121.472644, 31.231706],
江苏省: [87.617733, 43.792818],
辽宁省: [123.429096, 41.796767],
湖南省: [112.982279, 28.19409],
北京市: [116.403874, 39.914885],
天津市: [117.190182, 39.125523],
河北省: [114.502462, 38.045494],
山西省: [112.549248, 37.857014],
内蒙古自治区: [111.751990, 40.841470],
辽宁省: [123.429096, 41.796767],
吉林省: [125.324498, 43.886845],
黑龙江省: [126.642464, 45.802755],
上海市: [121.472644, 31.231706],
江苏省: [118.783957, 32.062785],
浙江省: [120.153576, 30.287459],
安徽省: [117.283447, 31.861193],
福建省: [119.306239, 26.075302],
江西省: [115.892151, 28.676461],
山东省: [117.000923, 36.675807],
河南省: [113.625367, 34.746570],
湖北省: [114.305539, 30.593098],
湖南省: [112.982279, 28.194090],
广东省: [113.264385, 23.129110],
广西壮族自治区: [108.320004, 22.824018],
海南省: [110.198289, 20.044008],
重庆市: [106.551559, 29.563010],
四川省: [104.065735, 30.659462],
贵州省: [106.707221, 26.598278],
云南省: [102.712251, 25.040609],
西藏自治区: [91.132212, 29.660359],
陕西省: [108.939838, 34.341275],
甘肃省: [103.823557, 36.058039],
福建省: [119.306239, 26.075302]
青海省: [101.777820, 36.616990],
宁夏回族自治区: [106.278080, 38.466370],
新疆维吾尔自治区: [87.617733, 43.792818],
台湾省: [121.520076, 25.047310],
香港特别行政区: [114.165460, 22.275345],
澳门特别行政区: [113.549148, 22.198755]
})
const mapData = ref([
......@@ -62,28 +91,7 @@ const mapData = ref([
// }
])
const mapData2 = ref([
{
name: '浙江省',
value: 12.4920
},
{
name: '山西省',
value: 1.7948
},
{
name: '江苏省',
value: 19.0543
},
{
name: '福建省',
value: 7.4283
},
{
name: '甘肃省',
value: 3.5283
}
])
const mapData2 = ref([])
const convertData = function (data) {
const res = []
......@@ -174,7 +182,7 @@ function initMapChart (el) {
label: {
show: true,
position: [-25, -80],
width: 360,
width: 420,
height: 72,
color: '#FFFFFF',
backgroundColor: { image: labelGreen },
......@@ -218,8 +226,8 @@ function initMapChart (el) {
symbolSize: 0,
label: {
show: true,
position: [-25, -80],
width: 360,
position: [-40, -80],
width: 500,
height: 72,
color: '#FFFFFF',
backgroundColor: { image: labelRed },
......@@ -228,12 +236,12 @@ function initMapChart (el) {
rich: {
txt: {
align: 'left',
padding: [40, 0, 0, 130],
padding: [40, 60, 0, 130],
fontSize: 22
},
txt2: {
fontSize: 36,
padding: [38, 0, 0, 10]
padding: [38, 20, 0, 10]
},
txt3: {
fontSize: 24,
......@@ -246,7 +254,7 @@ function initMapChart (el) {
data
} = params
if (data && data.value) {
return `{txt|${' 算力资源'}}{txt2|${data.value[2]}}{txt3|${'P'}}`
return `{txt|${' 算力资源'}}{txt2|${data.value[2]}}{txt3|${'PTOPS'}}`
}
return 'data'
}
......@@ -270,6 +278,8 @@ const resize = () => {
onMounted(async () => {
await nextTick()
// 从 dashboardData 初始化地图数据
mapData2.value = dashboardData.value.mapData || []
if (mapRef.value) {
chartInst = initMapChart(mapRef.value)
window.addEventListener('resize', resize)
......@@ -277,6 +287,23 @@ onMounted(async () => {
}
})
// 监听数据变化
watch(() => dashboardData.value.mapData, (newData) => {
mapData2.value = newData || []
if (chartInst) {
chartInst.setOption({
series: [
{
data: convertData(mapData.value)
},
{
data: convertData(mapData2.value)
}
]
})
}
}, { deep: true })
onBeforeUnmount(() => {
window.removeEventListener('resize', resize)
document.removeEventListener('fullscreenchange', resize)
......
......@@ -10,7 +10,7 @@
</template>
<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'
import { ref, watch, onMounted, onBeforeUnmount, inject } from 'vue'
import * as echarts from 'echarts/core'
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { PieChart } from 'echarts/charts'
......@@ -23,22 +23,21 @@ let chart = null
const dim = ref('gpu')
const datasets = {
gpu: [
{ value: 45.11, name: '4090' },
{ value: 29.88, name: 'A100' },
{ value: 25, name: 'H100' }
],
source: [
{ value: 50, name: '自有' },
{ value: 30, name: '合作' },
{ value: 20, name: '社会' }
],
resource: [
{ value: 40, name: '裸金属' },
{ value: 35, name: 'VM' },
{ value: 25, name: '容器' }
]
// 从父组件获取统一数据
const dashboardData = inject('dashboardData', {})
const datasets = ref({
gpu: [],
source: [],
resource: []
})
// 获取算力资源分布数据
const fetchComputeDistribution = () => {
const data = dashboardData.value.computeDistribution || { gpu: [], source: [], resource: [] }
datasets.value.gpu = data.gpu || []
datasets.value.source = data.source || []
datasets.value.resource = data.resource || []
}
const titles = {
......@@ -50,7 +49,7 @@ const titles = {
const baseColors = ['#16FCFF', '#39E9D5', '#1DBAFF', '#77CCFF', '#E99102', '#3AEDCE']
const getOption = (which) => {
const data = datasets[which]
const data = datasets.value[which] || []
const total = data.reduce((s, i) => s + Number(i.value || 0), 0)
const dataMap = data.reduce((acc, i) => ((acc[i.name] = Number(i.value || 0)), acc), {})
return {
......@@ -139,10 +138,19 @@ watch(dim, () => {
})
onMounted(() => {
fetchComputeDistribution()
render()
window.addEventListener('resize', resize)
})
// 监听数据变化
watch(() => dashboardData.value.computeDistribution, () => {
fetchComputeDistribution()
if (chart) {
chart.setOption(getOption(dim.value), true)
}
}, { deep: true })
onBeforeUnmount(() => {
window.removeEventListener('resize', resize)
if (chart) {
......
......@@ -2,7 +2,7 @@
<div id="nvestment" class="echart-wrap"></div>
</template>
<script setup>
import { onMounted } from 'vue'
import { onMounted, inject, watch } from 'vue'
import * as echarts from 'echarts/core'
import {
TitleComponent,
......@@ -27,9 +27,23 @@ echarts.use([
UniversalTransition
])
// 从父组件获取统一数据
const dashboardData = inject('dashboardData', {})
let myChart = null
function init () {
const chartDom = document.getElementById('nvestment')
const myChart = echarts.init(chartDom)
if (!myChart) {
myChart = echarts.init(chartDom)
}
// 从 dashboardData 获取服务能力数据
const serviceCapability = dashboardData.value.serviceCapability || {}
const years = serviceCapability.years || []
const appOnline = serviceCapability.appOnline || []
const apiOnline = serviceCapability.apiOnline || []
const option = {
tooltip: {
trigger: 'axis',
......@@ -41,7 +55,7 @@ function init () {
}
},
legend: {
data: ['水能消耗', '电能消耗'],
data: ['上线应用', '上线API'],
show: false,
right: '2%',
top: 30,
......@@ -63,7 +77,7 @@ function init () {
{
type: 'category',
boundaryGap: true,
data: ['2018', '2019', '2020', '2021', '2022'],
data: years,
axisLabel: {
fontSize: 24,
color: '#ffffff'
......@@ -133,7 +147,7 @@ function init () {
}
])
},
data: [10.19, 189.61, 120.4, 75.14, '']
data: appOnline
},
{
name: '上线API',
......@@ -150,7 +164,7 @@ function init () {
emphasis: {
// focus: 'series'
},
data: [23.22, 12027.48, 75935.47, 195109.5381, '']
data: apiOnline
}
]
}
......@@ -160,6 +174,11 @@ function init () {
onMounted(() => {
init()
})
// 监听数据变化
watch(() => dashboardData.value.serviceCapability, () => {
init()
}, { deep: true })
</script>
<style scoped lang="scss">
......
......@@ -29,7 +29,7 @@
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { ref, onMounted, onBeforeUnmount, inject, watch } from 'vue'
import * as echarts from 'echarts/core'
import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { LineChart } from 'echarts/charts'
......@@ -43,78 +43,99 @@ let chart = null
// 维度切换:d=日, m=月, y=年
const rangeType = ref('m')
// 从父组件获取统一数据
const dashboardData = inject('dashboardData', {})
// 嵌入 iframe 和全屏自适应
const inIframe = ref(false)
const isFullscreen = ref(false)
const outerPadding = ref('0px')
// 模拟接口:返回近 N 个月的请求量
function mockFetchApiTrend(months = 6) {
return new Promise((resolve) => {
setTimeout(() => {
const now = new Date()
const items = []
for (let i = months - 1; i >= 0; i--) {
const d = new Date(now.getFullYear(), now.getMonth() - i, 1)
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
// 构造一个看起来合理的请求数:基础值 + 波动
const base = 20000 + (i * 1500)
const noise = Math.floor(Math.random() * 4000) - 2000 // ±2000 波动
const value = Math.max(0, base + noise)
items.push({ month: `${y}-${m}`, requests: value })
}
resolve({ code: 0, data: items })
}, 500)
})
}
// 原始生成模拟数据的方式(备份)
// function mockFetchApiTrend(months = 6) {
// return new Promise((resolve) => {
// setTimeout(() => {
// const now = new Date()
// const items = []
// for (let i = months - 1; i >= 0; i--) {
// const d = new Date(now.getFullYear(), now.getMonth() - i, 1)
// const y = d.getFullYear()
// const m = String(d.getMonth() + 1).padStart(2, '0')
// const base = 20000 + (i * 1500)
// const noise = Math.floor(Math.random() * 4000) - 2000
// const value = Math.max(0, base + noise)
// items.push({ month: `${y}-${m}`, requests: value })
// }
// resolve({ code: 0, data: items })
// }, 500)
// })
// }
// 生成不同维度的数据
function genDaySeries(days = 7) {
const now = new Date()
const x = []
const y = []
for (let i = days - 1; i >= 0; i--) {
const d = new Date(now)
d.setDate(now.getDate() - i)
const mm = String(d.getMonth() + 1).padStart(2, '0')
const dd = String(d.getDate()).padStart(2, '0')
x.push(`${mm}-${dd}`)
// 日数据:较小基数 + 波动
const base = 800 + (days - i) * 30
const noise = Math.floor(Math.random() * 200) - 100
y.push(Math.max(0, base + noise))
}
return { x, y }
}
// 生成不同维度的数据(备份)
// function genDaySeries(days = 7) {
// const now = new Date()
// const x = []
// const y = []
// for (let i = days - 1; i >= 0; i--) {
// const d = new Date(now)
// d.setDate(now.getDate() - i)
// const mm = String(d.getMonth() + 1).padStart(2, '0')
// const dd = String(d.getDate()).padStart(2, '0')
// x.push(`${mm}-${dd}`)
// const base = 800 + (days - i) * 30
// const noise = Math.floor(Math.random() * 200) - 100
// y.push(Math.max(0, base + noise))
// }
// return { x, y }
// }
function genMonthSeries(months = 12) {
const now = new Date()
const x = []
const y = []
for (let i = months - 1; i >= 0; i--) {
const d = new Date(now.getFullYear(), now.getMonth() - i, 1)
const m = d.getMonth() + 1
x.push(`${m}月`)
const base = 20000 + (months - i) * 1500
const noise = Math.floor(Math.random() * 4000) - 2000
y.push(Math.max(0, base + noise))
}
return { x, y }
}
// function genMonthSeries(months = 12) {
// const now = new Date()
// const x = []
// const y = []
// for (let i = months - 1; i >= 0; i--) {
// const d = new Date(now.getFullYear(), now.getMonth() - i, 1)
// const m = d.getMonth() + 1
// x.push(`${m}月`)
// const base = 20000 + (months - i) * 1500
// const noise = Math.floor(Math.random() * 4000) - 2000
// y.push(Math.max(0, base + noise))
// }
// return { x, y }
// }
// function genYearSeries(years = 5) {
// const now = new Date()
// const x = []
// const y = []
// for (let i = years - 1; i >= 0; i--) {
// const d = new Date(now.getFullYear() - i, 0, 1)
// const yr = d.getFullYear()
// x.push(`${yr}`)
// const base = 200000 + (years - i) * 30000
// const noise = Math.floor(Math.random() * 40000) - 20000
// y.push(Math.max(0, base + noise))
// }
// return { x, y }
// }
function genYearSeries(years = 5) {
const now = new Date()
const x = []
const y = []
for (let i = years - 1; i >= 0; i--) {
const d = new Date(now.getFullYear() - i, 0, 1)
const yr = d.getFullYear()
x.push(`${yr}`)
const base = 200000 + (years - i) * 30000
const noise = Math.floor(Math.random() * 40000) - 20000
y.push(Math.max(0, base + noise))
// 从 dashboardData 获取图表数据
const getChartData = () => {
const data = dashboardData.value.apiCalls || []
if (!Array.isArray(data)) {
return { x: [], y: [] }
}
// 根据数据格式转换为图表数据
// apiCalls 格式: [{countDate: "2025-01-01", callsCount: 1202}, ...]
const x = data.map(item => {
const date = new Date(item.countDate)
const m = String(date.getMonth() + 1).padStart(2, '0')
const d = String(date.getDate()).padStart(2, '0')
return `${m}-${d}`
})
const y = data.map(item => item.callsCount)
return { x, y }
}
......@@ -173,16 +194,7 @@ function getOption(x, y) {
}
async function render() {
let x = []
let y = []
// 按维度生成数据
if (rangeType.value === 'd') {
;({ x, y } = genDaySeries(7))
} else if (rangeType.value === 'm') {
;({ x, y } = genMonthSeries(12))
} else {
;({ x, y } = genYearSeries(5))
}
const { x, y } = getChartData()
if (!chart) chart = echarts.init(chartRef.value)
chart.setOption(getOption(x, y), true)
......@@ -237,6 +249,11 @@ onMounted(() => {
document.addEventListener('MSFullscreenChange', onFsChange)
})
// 监听数据变化
watch(() => dashboardData.value.apiCalls, () => {
render()
}, { deep: true })
onBeforeUnmount(() => {
window.removeEventListener('resize', onResize)
document.removeEventListener('fullscreenchange', onFsChange)
......
......@@ -22,17 +22,19 @@
</template>
<script setup lang="ts">
import { inject, computed, onMounted, onBeforeUnmount, ref } from 'vue'
import { inject, computed, onMounted, onBeforeUnmount, ref, watch } from 'vue'
import * as echarts from 'echarts/core'
import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { LineChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
import { useI18n } from 'vue-i18n'
import type { EChartsOption } from 'echarts'
import * as IndexCountApi from '@/api/Home/count'
echarts.use([GridComponent, TooltipComponent, LegendComponent, LineChart, CanvasRenderer])
// 从父组件获取统一数据
const dashboardData = inject('dashboardData', {})
// 从父组件(Home.vue)注入全屏状态与方法
const fs = inject('fsState', null) as null | { isFullscreen: any; toggleFullscreen: () => void }
const fsIsFullscreen = computed(() => !!(fs && fs.isFullscreen && fs.isFullscreen.value))
......@@ -138,12 +140,14 @@ function getOption(xData: string[], seriesData: {
}
async function render() {
const res = await IndexCountApi.getOrdersData(dateType.value)
const x = (res || []).map((item: any) => t(item.countDate))
const computeCount = (res || []).map((item: any) => item.computeOrdersCount || 0)
const apiCount = (res || []).map((item: any) => item.apiOrdersCount || 0)
const computeAmount = (res || []).map((item: any) => Number(((item.computeOrdersAmount || 0) / 100).toFixed(2)))
const apiAmount = (res || []).map((item: any) => Number(((item.apiOrdersAmount || 0) / 100).toFixed(2)))
const orders = dashboardData.value.orders || {}
const res = orders[dateType.value] || []
const x = res.map((item: any) => t(item.countDate))
const computeCount = res.map((item: any) => item.computeOrdersCount || 0)
const apiCount = res.map((item: any) => item.apiOrdersCount || 0)
const computeAmount = res.map((item: any) => Number(((item.computeOrdersAmount || 0) / 100).toFixed(2)))
const apiAmount = res.map((item: any) => Number(((item.apiOrdersAmount || 0) / 100).toFixed(2)))
if (!chart) {
const el = document.getElementById('energyManage') as HTMLElement | null
......@@ -161,6 +165,11 @@ function changeType(t: 'd' | 'm' | 'y') {
const onResize = () => chart && chart.resize()
// 监听数据变化
watch(() => dashboardData.value.orders, () => {
render()
}, { deep: true })
onMounted(() => {
render()
window.addEventListener('resize', onResize)
......
......@@ -12,17 +12,19 @@
</template>
<script setup lang="ts">
import { inject, computed, onMounted, onBeforeUnmount, ref } from 'vue'
import { inject, computed, onMounted, onBeforeUnmount, ref, watch } from 'vue'
import * as echarts from 'echarts/core'
import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { LineChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
import { useI18n } from 'vue-i18n'
import type { EChartsOption } from 'echarts'
import * as IndexCountApi from '@/api/Home/count'
echarts.use([GridComponent, TooltipComponent, LegendComponent, LineChart, CanvasRenderer])
// 从父组件获取统一数据
const dashboardData = inject('dashboardData', {})
// 从父组件(Home.vue)注入全屏状态与方法
const fs = inject('fsState', null) as null | { isFullscreen: any; toggleFullscreen: () => void }
const fsIsFullscreen = computed(() => !!(fs && fs.isFullscreen && fs.isFullscreen.value))
......@@ -88,8 +90,9 @@ function getOption(xData: string[], growth: number[], active: number[]): ECharts
}
async function render() {
const res = await IndexCountApi.getUsersData(dateType.value)
const arr = Array.isArray(res) ? res : []
// 直接从 dashboardData 获取数据
const arr = dashboardData.value.users || []
const x = arr.map((item: any) => t(item.countDate))
const growth = arr.map((item: any) => item.growthUsersCount ?? item.usersCount ?? 0)
const active = arr.map((item: any, idx: number) =>
......@@ -112,6 +115,11 @@ function changeType(t: 'd' | 'm' | 'y') {
const onResize = () => chart && chart.resize()
// 监听数据变化
watch(() => dashboardData.value.users, () => {
render()
}, { deep: true })
onMounted(() => {
render()
window.addEventListener('resize', onResize)
......
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="配置key" prop="configKey">
<el-input v-model="formData.configKey" placeholder="请输入配置key" />
</el-form-item>
<el-form-item label="配置类型" prop="configType">
<el-select v-model="formData.configType" placeholder="请选择配置类型" :disabled="formType === 'update'">
<el-option label="开关 (switch)" value="switch" />
<el-option label="数据 (data)" value="data" />
</el-select>
</el-form-item>
<el-form-item label="配置值" prop="configValue">
<el-input
v-model="formData.configValue"
type="textarea"
:rows="10"
placeholder="请输入配置值,JSON格式"
v-if="formData.configType === 'data'"
/>
<el-switch
v-model="switchValue"
active-text="开启"
inactive-text="关闭"
v-else
/>
</el-form-item>
<el-form-item v-if="formData.configType === 'data'">
<el-button @click="formatJson" type="primary" size="small">格式化 JSON</el-button>
<el-button @click="validateJson" type="success" size="small">校验 JSON</el-button>
</el-form-item>
<el-form-item label="配置描述" prop="description">
<Editor v-model="formData.description" height="150px" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { HomeDashboardMockApi, HomeDashboardMock } from '@/api/biz/home'
/** 首页大屏模拟数据配置 表单 */
defineOptions({ name: 'HomeDashboardMockForm' })
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
id: undefined,
configKey: undefined,
configType: undefined,
configValue: undefined,
description: undefined
})
const formRules = reactive({
configKey: [{ required: true, message: '配置key不能为空', trigger: 'blur' }],
configType: [{ required: true, message: '配置类型不能为空', trigger: 'change' }],
configValue: [{ required: true, message: '配置值不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
// 开关类型的值处理
const switchValue = computed({
get: () => formData.value.configValue === 'true',
set: (val) => {
formData.value.configValue = val ? 'true' : 'false'
}
})
// 格式化JSON
const formatJson = () => {
try {
const parsed = JSON.parse(formData.value.configValue)
formData.value.configValue = JSON.stringify(parsed, null, 2)
message.success('JSON格式化成功')
} catch (e) {
message.error('JSON格式错误,无法格式化')
}
}
// 校验JSON
const validateJson = () => {
try {
JSON.parse(formData.value.configValue)
message.success('JSON格式正确')
} catch (e) {
message.error('JSON格式错误:' + e.message)
}
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await HomeDashboardMockApi.getHomeDashboardMock(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as HomeDashboardMock
if (formType.value === 'create') {
await HomeDashboardMockApi.createHomeDashboardMock(data)
message.success(t('common.createSuccess'))
} else {
await HomeDashboardMockApi.updateHomeDashboardMock(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
configKey: undefined,
configType: undefined,
configValue: undefined,
description: undefined
}
formRef.value?.resetFields()
}
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment