Merge pull request #330 from wikrin/template

feat(setting): 添加消息推送自定义选项
This commit is contained in:
jxxghp
2025-05-05 19:30:42 +08:00
committed by GitHub
4 changed files with 153 additions and 0 deletions

View File

@@ -1116,6 +1116,14 @@ export default {
notification: {
channels: 'Notification Channels',
channelsDesc: 'Set message sending channel parameters.',
organizeSuccess: 'Media Import',
downloadAdded: 'Download Added',
subscribeAdded: 'Subscribe Added',
subscribeComplete: 'Subscribe Complete',
templateConfig: 'Template Configuration',
templateSaveFailed: 'Failed to save template!',
templateSaveSuccess: 'Template saved successfully',
templateLoadFailed: 'Failed to load template!',
scope: 'Notification Scope',
scopeDesc: 'Corresponding message types will only be sent to specified users.',
messageType: 'Message Type',

View File

@@ -1104,6 +1104,14 @@ export default {
notification: {
channels: '通知渠道',
channelsDesc: '设置消息发送渠道参数。',
organizeSuccess: '资源入库',
downloadAdded: '资源下载',
subscribeAdded: '订阅添加',
subscribeComplete: '订阅完成',
templateConfig: '模板格式配置',
templateSaveFailed: '模板保存失败!',
templateSaveSuccess: '模板保存成功',
templateLoadFailed: '模板加载失败!',
scope: '通知发送范围',
scopeDesc: '对应消息类型只会发送给设定的用户。',
messageType: '消息类型',

View File

@@ -1106,6 +1106,14 @@ export default {
notification: {
channels: '通知渠道',
channelsDesc: '設置消息發送渠道參數。',
organizeSuccess: '資源入庫',
downloadAdded: '資源下載',
subscribeAdded: '訂閱添加',
subscribeComplete: '訂閱完成',
templateConfig: '消息模板配置',
templateSaveFailed: '模板保存失敗!',
templateSaveSuccess: '模板保存成功',
templateLoadFailed: '模板載入失敗!',
scope: '通知發送範圍',
scopeDesc: '對應消息類型只會發送給設定的用戶。',
messageType: '消息類型',

View File

@@ -11,6 +11,34 @@ import { notificationSwitchDict } from '@/api/constants'
// 国际化
const { t } = useI18n()
// 初始化模板配置字典
const templateConfigs = ref<Record<string, string>>({
organizeSuccess: '{}',
downloadAdded: '{}',
subscribeAdded: '{}',
subscribeComplete: '{}'
})
// 模板类型配置
const templateTypes = ref([
{
type: 'organizeSuccess',
label: t('setting.notification.organizeSuccess')
},
{
type: 'downloadAdded',
label: t('setting.notification.downloadAdded')
},
{
type: 'subscribeAdded',
label: t('setting.notification.subscribeAdded')
},
{
type: 'subscribeComplete',
label: t('setting.notification.subscribeComplete')
}
])
// 所有消息渠道
const notifications = ref<NotificationConf[]>([])
@@ -19,6 +47,9 @@ const $toast = useToast()
// 进度框
const progressDialog = ref(false)
const editorVisible = ref(false)
const currentTemplate = ref('')
const editorContent = ref('')
// 消息类型开关
const notificationSwitchs = ref<NotificationSwitchConf[]>([
@@ -105,6 +136,43 @@ async function loadNotificationSetting() {
}
}
async function openEditor(type: string) {
try {
currentTemplate.value = type
const result: { [key: string]: any } = await api.get('system/setting/NotificationTemplates')
templateConfigs.value = result.data?.value || {}
editorContent.value = templateConfigs.value[type] || '{}'
editorVisible.value = true
} catch (error) {
console.error(error)
$toast.error(t('setting.notification.templateLoadFailed'))
}
}
async function saveTemplate() {
try {
await api.post('system/setting/NotificationTemplates', {
...templateConfigs.value,
[currentTemplate.value]: editorContent.value
})
$toast.success(t('setting.notification.templateSaveSuccess'))
editorVisible.value = false
} catch (error) {
console.error(error)
$toast.error(t('setting.notification.templateSaveFailed'))
}
}
async function loadTemplateConfigs() {
try {
const result: { [key: string]: any } = await api.get('system/setting/NotificationTemplates')
templateConfigs.value = result.data?.value || {}
} catch (error) {
console.error(error)
$toast.error(t('setting.notification.templateLoadFailed'))
}
}
// 调用API查询通知发送时间设置
async function loadNotificationTime() {
try {
@@ -182,6 +250,7 @@ onMounted(() => {
loadNotificationSetting()
loadNotificationSwitchs()
loadNotificationTime()
loadTemplateConfigs()
})
</script>
@@ -246,6 +315,33 @@ onMounted(() => {
</VCard>
</VCol>
</VRow>
<VCard>
<VCardItem>
<VCardTitle>{{ t('setting.notification.templateConfig') }}</VCardTitle>
</VCardItem>
<VCardText>
<VRow>
<VCol
v-for="item in templateTypes"
:key="item.type"
cols="12"
sm="6"
lg="3"
>
<VCard
variant="tonal"
@click="openEditor(item.type)"
>
<VCardText>
<div class="text-h6 align-center">
{{ item.label }}
</div>
</VCardText>
</VCard>
</VCol>
</VRow>
</VCardText>
</VCard>
<VRow>
<VCol cols="12">
<VCard>
@@ -321,4 +417,37 @@ onMounted(() => {
:text="t('setting.system.reloading')"
:indeterminate="true"
/>
<!-- 模板编辑器对话框 -->
<VDialog v-model="editorVisible" max-width="800">
<VCard>
<VCardTitle>{{ templateTypes.find(t => t.type === currentTemplate)?.label }}</VCardTitle>
<VCardText>
<VAceEditor
v-model:value="editorContent"
lang="json"
theme="monokai"
style="block-size: 30rem"
class="rounded"
/>
</VCardText>
<VCardActions>
<VSpacer />
<VBtn color="primary" @click="saveTemplate">
{{ t('common.save') }}
</VBtn>
<VBtn @click="editorVisible = false">
{{ t('common.cancel') }}
</VBtn>
</VCardActions>
</VCard>
</VDialog>
</template>
<style scoped>
/* Monaco编辑器容器样式 */
.monaco-editor-container {
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
border-radius: 8px;
overflow: hidden;
margin-top: 1rem;
}
</style>