144 lines
3.2 KiB
Vue
144 lines
3.2 KiB
Vue
<template>
|
|
<n-modal
|
|
:show="show"
|
|
title="应用预设模板"
|
|
preset="dialog"
|
|
style="width: 560px;"
|
|
:show-icon="false"
|
|
@close="$emit('close')"
|
|
>
|
|
<div class="aksrt-preset-picker">
|
|
<p class="aksrt-preset-picker__hint">
|
|
选择一个预设模板快速配置首页模块。应用预设将替换当前所有模块。
|
|
</p>
|
|
|
|
<div class="aksrt-preset-picker__list">
|
|
<div
|
|
v-for="preset in presets"
|
|
:key="preset.key"
|
|
class="aksrt-preset-picker__item"
|
|
:class="{ 'aksrt-preset-picker__item--selected': selectedKey === preset.key }"
|
|
@click="selectedKey = preset.key"
|
|
>
|
|
<div class="aksrt-preset-picker__item-header">
|
|
<strong>{{ preset.label }}</strong>
|
|
<n-tag size="small" type="info">{{ preset.modules.length }} 个模块</n-tag>
|
|
</div>
|
|
<p class="aksrt-preset-picker__item-desc">{{ preset.desc }}</p>
|
|
<div class="aksrt-preset-picker__item-modules">
|
|
<n-tag
|
|
v-for="(mod, i) in preset.modules"
|
|
:key="i"
|
|
size="small"
|
|
:bordered="false"
|
|
class="aksrt-preset-picker__module-tag"
|
|
>
|
|
{{ getModuleLabel(mod.type) }}
|
|
</n-tag>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<template #action>
|
|
<n-space>
|
|
<n-button @click="$emit('close')">取消</n-button>
|
|
<n-button
|
|
type="primary"
|
|
:disabled="!selectedKey"
|
|
@click="handleApply"
|
|
>
|
|
应用预设
|
|
</n-button>
|
|
</n-space>
|
|
</template>
|
|
</n-modal>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
import { PRESET_TEMPLATES, MODULE_LIBRARY } from '@/utils/home-module-schema'
|
|
|
|
defineProps({
|
|
show: { type: Boolean, default: false },
|
|
})
|
|
|
|
const emit = defineEmits(['close', 'apply'])
|
|
const selectedKey = ref('')
|
|
const presets = PRESET_TEMPLATES
|
|
|
|
function getModuleLabel(type) {
|
|
const m = MODULE_LIBRARY.find(x => x.type === type)
|
|
return m?.label || type
|
|
}
|
|
|
|
function handleApply() {
|
|
const preset = presets.find(p => p.key === selectedKey.value)
|
|
if (preset) {
|
|
emit('apply', preset)
|
|
selectedKey.value = ''
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.aksrt-preset-picker__hint {
|
|
margin: 0 0 16px;
|
|
font-size: 13px;
|
|
color: #666;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.aksrt-preset-picker__list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.aksrt-preset-picker__item {
|
|
padding: 12px;
|
|
border: 1px solid #f0f0f0;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
}
|
|
|
|
.aksrt-preset-picker__item:hover {
|
|
border-color: #d0d0d0;
|
|
background: #fafafa;
|
|
}
|
|
|
|
.aksrt-preset-picker__item--selected {
|
|
border-color: #1890ff;
|
|
background: #e6f4ff;
|
|
}
|
|
|
|
.aksrt-preset-picker__item-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.aksrt-preset-picker__item-header strong {
|
|
font-size: 14px;
|
|
color: #333;
|
|
}
|
|
|
|
.aksrt-preset-picker__item-desc {
|
|
margin: 0 0 8px;
|
|
font-size: 12px;
|
|
color: #888;
|
|
}
|
|
|
|
.aksrt-preset-picker__item-modules {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 4px;
|
|
}
|
|
|
|
.aksrt-preset-picker__module-tag {
|
|
font-size: 11px;
|
|
}
|
|
</style>
|