mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-08-27 11:10:12 +08:00
feat: add wechat clawbot notification setup UI
This commit is contained in:
BIN
src/assets/images/logos/clawbot.png
Normal file
BIN
src/assets/images/logos/clawbot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
@@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import api from '@/api'
|
||||||
import { NotificationConf } from '@/api/types'
|
import { NotificationConf } from '@/api/types'
|
||||||
import { getLogoUrl } from '@/utils/imageUtils'
|
import { getLogoUrl } from '@/utils/imageUtils'
|
||||||
import { useToast } from 'vue-toastification'
|
import { useToast } from 'vue-toastification'
|
||||||
@@ -45,6 +46,7 @@ const notificationInfo = ref<NotificationConf>({
|
|||||||
// 各通知类型的名称字典
|
// 各通知类型的名称字典
|
||||||
const notificationTypeNames: { [key: string]: string } = {
|
const notificationTypeNames: { [key: string]: string } = {
|
||||||
wechat: t('notification.wechat.name'),
|
wechat: t('notification.wechat.name'),
|
||||||
|
wechatclawbot: t('notification.wechatclawbot.name'),
|
||||||
telegram: t('notification.telegram.name'),
|
telegram: t('notification.telegram.name'),
|
||||||
qqbot: t('notification.qqbot.name'),
|
qqbot: t('notification.qqbot.name'),
|
||||||
vocechat: t('notification.vocechat.name'),
|
vocechat: t('notification.vocechat.name'),
|
||||||
@@ -68,6 +70,18 @@ const notificationTypes = [
|
|||||||
{ value: '其它', title: t('notificationSwitch.other') },
|
{ value: '其它', title: t('notificationSwitch.other') },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
interface WechatClawBotStatus {
|
||||||
|
connected?: boolean
|
||||||
|
account_id?: string | null
|
||||||
|
qrcode?: string | null
|
||||||
|
qrcode_url?: string | null
|
||||||
|
qrcode_status?: string | null
|
||||||
|
qrcode_updated_at?: number | null
|
||||||
|
known_targets?: Array<{ userid: string; username: string; last_active?: number | null }>
|
||||||
|
default_target?: string | null
|
||||||
|
base_url?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
function ensureWechatConfigDefaults(notification: NotificationConf) {
|
function ensureWechatConfigDefaults(notification: NotificationConf) {
|
||||||
if (notification.type !== 'wechat') {
|
if (notification.type !== 'wechat') {
|
||||||
return
|
return
|
||||||
@@ -83,6 +97,39 @@ function ensureWechatConfigDefaults(notification: NotificationConf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ensureWechatClawBotConfigDefaults(notification: NotificationConf) {
|
||||||
|
if (notification.type !== 'wechatclawbot') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!notification.config) {
|
||||||
|
notification.config = {}
|
||||||
|
}
|
||||||
|
if (!notification.config.WECHATCLAWBOT_BASE_URL) {
|
||||||
|
notification.config.WECHATCLAWBOT_BASE_URL = 'https://ilinkai.weixin.qq.com'
|
||||||
|
}
|
||||||
|
if (!notification.config.WECHATCLAWBOT_POLL_TIMEOUT) {
|
||||||
|
notification.config.WECHATCLAWBOT_POLL_TIMEOUT = 25
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wechatClawBotLoading = ref(false)
|
||||||
|
const wechatClawBotActionLoading = ref(false)
|
||||||
|
const wechatClawBotStatus = ref<WechatClawBotStatus | null>(null)
|
||||||
|
let wechatClawBotTimer: number | null = null
|
||||||
|
|
||||||
|
function getWechatClawBotRequestParams(extraParams: Record<string, any> = {}) {
|
||||||
|
const config = notificationInfo.value.config || {}
|
||||||
|
return {
|
||||||
|
source: notificationInfo.value.name,
|
||||||
|
fallback_source: props.notification.name,
|
||||||
|
WECHATCLAWBOT_BASE_URL: config.WECHATCLAWBOT_BASE_URL,
|
||||||
|
WECHATCLAWBOT_DEFAULT_TARGET: config.WECHATCLAWBOT_DEFAULT_TARGET,
|
||||||
|
WECHATCLAWBOT_ADMINS: config.WECHATCLAWBOT_ADMINS,
|
||||||
|
WECHATCLAWBOT_POLL_TIMEOUT: config.WECHATCLAWBOT_POLL_TIMEOUT,
|
||||||
|
...extraParams,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const isWechatBotMode = computed({
|
const isWechatBotMode = computed({
|
||||||
get: () => notificationInfo.value.config?.WECHAT_MODE === 'bot',
|
get: () => notificationInfo.value.config?.WECHAT_MODE === 'bot',
|
||||||
set: value => {
|
set: value => {
|
||||||
@@ -101,7 +148,11 @@ function openNotificationInfoDialog() {
|
|||||||
// 替换成深复制,避免修改时影响原数据
|
// 替换成深复制,避免修改时影响原数据
|
||||||
notificationInfo.value = cloneDeep(props.notification)
|
notificationInfo.value = cloneDeep(props.notification)
|
||||||
ensureWechatConfigDefaults(notificationInfo.value)
|
ensureWechatConfigDefaults(notificationInfo.value)
|
||||||
|
ensureWechatClawBotConfigDefaults(notificationInfo.value)
|
||||||
notificationInfoDialog.value = true
|
notificationInfoDialog.value = true
|
||||||
|
if (notificationInfo.value.type === 'wechatclawbot') {
|
||||||
|
fetchWechatClawBotStatus(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存详情数据
|
// 保存详情数据
|
||||||
@@ -117,16 +168,137 @@ function saveNotificationInfo() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ensureWechatConfigDefaults(notificationInfo.value)
|
ensureWechatConfigDefaults(notificationInfo.value)
|
||||||
|
ensureWechatClawBotConfigDefaults(notificationInfo.value)
|
||||||
notificationInfoDialog.value = false
|
notificationInfoDialog.value = false
|
||||||
emit('change', notificationInfo.value, props.notification.name)
|
emit('change', notificationInfo.value, props.notification.name)
|
||||||
emit('done')
|
emit('done')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearWechatClawBotTimer() {
|
||||||
|
if (wechatClawBotTimer) {
|
||||||
|
window.clearTimeout(wechatClawBotTimer)
|
||||||
|
wechatClawBotTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleWechatClawBotRefresh() {
|
||||||
|
clearWechatClawBotTimer()
|
||||||
|
if (!notificationInfoDialog.value || notificationInfo.value.type !== 'wechatclawbot') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const connected = wechatClawBotStatus.value?.connected
|
||||||
|
const pendingStatus = ['waiting', 'scanned'].includes((wechatClawBotStatus.value?.qrcode_status || '').toLowerCase())
|
||||||
|
if (connected || pendingStatus) {
|
||||||
|
wechatClawBotTimer = window.setTimeout(() => {
|
||||||
|
fetchWechatClawBotStatus(false)
|
||||||
|
}, connected ? 10000 : 3000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchWechatClawBotStatus(autoGenerateQrcode = false) {
|
||||||
|
if (notificationInfo.value.type !== 'wechatclawbot' || !notificationInfo.value.name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wechatClawBotLoading.value = true
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('notification/wechatclawbot/status', {
|
||||||
|
params: getWechatClawBotRequestParams({ auto_generate_qrcode: autoGenerateQrcode }),
|
||||||
|
})
|
||||||
|
if (result.success) {
|
||||||
|
wechatClawBotStatus.value = result.data
|
||||||
|
scheduleWechatClawBotRefresh()
|
||||||
|
} else {
|
||||||
|
wechatClawBotStatus.value = null
|
||||||
|
clearWechatClawBotTimer()
|
||||||
|
$toast.error(result.message || t('notification.wechatclawbot.statusLoadFailed'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
clearWechatClawBotTimer()
|
||||||
|
$toast.error(t('notification.wechatclawbot.statusLoadFailed'))
|
||||||
|
} finally {
|
||||||
|
wechatClawBotLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshWechatClawBotQrcode() {
|
||||||
|
if (!notificationInfo.value.name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wechatClawBotActionLoading.value = true
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.post('notification/wechatclawbot/refresh', null, {
|
||||||
|
params: getWechatClawBotRequestParams(),
|
||||||
|
})
|
||||||
|
if (result.success) {
|
||||||
|
wechatClawBotStatus.value = result.data
|
||||||
|
scheduleWechatClawBotRefresh()
|
||||||
|
$toast.success(t('notification.wechatclawbot.qrcodeRefreshSuccess'))
|
||||||
|
} else {
|
||||||
|
$toast.error(result.message || t('notification.wechatclawbot.qrcodeRefreshFailed'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
$toast.error(t('notification.wechatclawbot.qrcodeRefreshFailed'))
|
||||||
|
} finally {
|
||||||
|
wechatClawBotActionLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function logoutWechatClawBot() {
|
||||||
|
if (!notificationInfo.value.name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wechatClawBotActionLoading.value = true
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.post('notification/wechatclawbot/logout', null, {
|
||||||
|
params: getWechatClawBotRequestParams(),
|
||||||
|
})
|
||||||
|
if (result.success) {
|
||||||
|
$toast.success(result.message || t('notification.wechatclawbot.logoutSuccess'))
|
||||||
|
await fetchWechatClawBotStatus(true)
|
||||||
|
} else {
|
||||||
|
$toast.error(result.message || t('notification.wechatclawbot.logoutFailed'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
$toast.error(t('notification.wechatclawbot.logoutFailed'))
|
||||||
|
} finally {
|
||||||
|
wechatClawBotActionLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatWechatClawBotTime(timestamp?: number | null) {
|
||||||
|
if (!timestamp) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return new Date(timestamp * 1000).toLocaleString()
|
||||||
|
}
|
||||||
|
|
||||||
|
const wechatClawBotStatusText = computed(() => {
|
||||||
|
const status = (wechatClawBotStatus.value?.qrcode_status || '').toLowerCase()
|
||||||
|
if (wechatClawBotStatus.value?.connected) {
|
||||||
|
return t('notification.wechatclawbot.connected')
|
||||||
|
}
|
||||||
|
if (status === 'scanned') {
|
||||||
|
return t('notification.wechatclawbot.scanned')
|
||||||
|
}
|
||||||
|
if (status === 'expired') {
|
||||||
|
return t('notification.wechatclawbot.expired')
|
||||||
|
}
|
||||||
|
if (status === 'confirmed') {
|
||||||
|
return t('notification.wechatclawbot.confirmed')
|
||||||
|
}
|
||||||
|
return t('notification.wechatclawbot.waiting')
|
||||||
|
})
|
||||||
|
|
||||||
// 根据存储类型选择图标
|
// 根据存储类型选择图标
|
||||||
const getIcon = computed(() => {
|
const getIcon = computed(() => {
|
||||||
switch (props.notification.type) {
|
switch (props.notification.type) {
|
||||||
case 'wechat':
|
case 'wechat':
|
||||||
return getLogoUrl('wechat')
|
return getLogoUrl('wechat')
|
||||||
|
case 'wechatclawbot':
|
||||||
|
return getLogoUrl('wechatclawbot')
|
||||||
case 'telegram':
|
case 'telegram':
|
||||||
return getLogoUrl('telegram')
|
return getLogoUrl('telegram')
|
||||||
case 'qqbot':
|
case 'qqbot':
|
||||||
@@ -148,8 +320,15 @@ const getIcon = computed(() => {
|
|||||||
|
|
||||||
// 按钮点击
|
// 按钮点击
|
||||||
function onClose() {
|
function onClose() {
|
||||||
|
clearWechatClawBotTimer()
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(notificationInfoDialog, value => {
|
||||||
|
if (!value) {
|
||||||
|
clearWechatClawBotTimer()
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
@@ -347,6 +526,137 @@ function onClose() {
|
|||||||
</VCol>
|
</VCol>
|
||||||
</template>
|
</template>
|
||||||
</VRow>
|
</VRow>
|
||||||
|
<VRow v-else-if="notificationInfo.type == 'wechatclawbot'">
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="notificationInfo.name"
|
||||||
|
:label="t('notification.name')"
|
||||||
|
:placeholder="t('notification.name')"
|
||||||
|
:hint="t('notification.nameHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-label"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="notificationInfo.config.WECHATCLAWBOT_BASE_URL"
|
||||||
|
:label="t('notification.wechatclawbot.baseUrl')"
|
||||||
|
:hint="t('notification.wechatclawbot.baseUrlHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-web"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="notificationInfo.config.WECHATCLAWBOT_DEFAULT_TARGET"
|
||||||
|
:label="t('notification.wechatclawbot.defaultTarget')"
|
||||||
|
:placeholder="t('notification.wechatclawbot.defaultTargetPlaceholder')"
|
||||||
|
:hint="t('notification.wechatclawbot.defaultTargetHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-account-arrow-right"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="notificationInfo.config.WECHATCLAWBOT_ADMINS"
|
||||||
|
:label="t('notification.wechatclawbot.admins')"
|
||||||
|
:placeholder="t('notification.wechatclawbot.adminsPlaceholder')"
|
||||||
|
:hint="t('notification.wechatclawbot.adminsHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-account-supervisor"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="notificationInfo.config.WECHATCLAWBOT_POLL_TIMEOUT"
|
||||||
|
:label="t('notification.wechatclawbot.pollTimeout')"
|
||||||
|
:hint="t('notification.wechatclawbot.pollTimeoutHint')"
|
||||||
|
persistent-hint
|
||||||
|
type="number"
|
||||||
|
prepend-inner-icon="mdi-timer-outline"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VCard variant="tonal" class="pa-4">
|
||||||
|
<div class="d-flex flex-wrap align-center justify-space-between gap-3 mb-3">
|
||||||
|
<div>
|
||||||
|
<div class="text-subtitle-1 font-weight-medium">{{ t('notification.wechatclawbot.loginStatus') }}</div>
|
||||||
|
<div class="text-body-2 text-medium-emphasis">{{ wechatClawBotStatusText }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-wrap gap-2">
|
||||||
|
<VBtn
|
||||||
|
size="small"
|
||||||
|
variant="tonal"
|
||||||
|
:loading="wechatClawBotLoading"
|
||||||
|
@click.stop="fetchWechatClawBotStatus(true)"
|
||||||
|
>
|
||||||
|
{{ t('common.refresh') }}
|
||||||
|
</VBtn>
|
||||||
|
<VBtn
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
variant="tonal"
|
||||||
|
:loading="wechatClawBotActionLoading"
|
||||||
|
@click.stop="refreshWechatClawBotQrcode"
|
||||||
|
>
|
||||||
|
{{ t('notification.wechatclawbot.refreshQrcode') }}
|
||||||
|
</VBtn>
|
||||||
|
<VBtn
|
||||||
|
size="small"
|
||||||
|
color="error"
|
||||||
|
variant="tonal"
|
||||||
|
:loading="wechatClawBotActionLoading"
|
||||||
|
:disabled="!wechatClawBotStatus?.connected"
|
||||||
|
@click.stop="logoutWechatClawBot"
|
||||||
|
>
|
||||||
|
{{ t('notification.wechatclawbot.logout') }}
|
||||||
|
</VBtn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<VRow>
|
||||||
|
<VCol cols="12" md="5">
|
||||||
|
<div class="rounded text-center p-3 border h-100 d-flex align-center justify-center min-h-[16rem]">
|
||||||
|
<VImg
|
||||||
|
v-if="wechatClawBotStatus?.qrcode_url"
|
||||||
|
:src="wechatClawBotStatus.qrcode_url"
|
||||||
|
width="220"
|
||||||
|
height="220"
|
||||||
|
class="mx-auto"
|
||||||
|
/>
|
||||||
|
<VProgressCircular v-else-if="wechatClawBotLoading" indeterminate color="primary" />
|
||||||
|
<div v-else class="text-body-2 text-medium-emphasis">
|
||||||
|
{{ t('notification.wechatclawbot.noQrcode') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="7">
|
||||||
|
<VAlert variant="tonal" :type="wechatClawBotStatus?.connected ? 'success' : 'info'" class="mb-3">
|
||||||
|
<div class="text-body-2">{{ t('notification.wechatclawbot.scanHint') }}</div>
|
||||||
|
<div v-if="wechatClawBotStatus?.account_id" class="mt-2">
|
||||||
|
{{ t('notification.wechatclawbot.accountId') }}: {{ wechatClawBotStatus.account_id }}
|
||||||
|
</div>
|
||||||
|
<div v-if="wechatClawBotStatus?.qrcode_updated_at" class="mt-2">
|
||||||
|
{{ t('notification.wechatclawbot.qrcodeUpdatedAt') }}:
|
||||||
|
{{ formatWechatClawBotTime(wechatClawBotStatus.qrcode_updated_at) }}
|
||||||
|
</div>
|
||||||
|
</VAlert>
|
||||||
|
<div class="text-subtitle-2 mb-2">{{ t('notification.wechatclawbot.knownTargets') }}</div>
|
||||||
|
<VList v-if="wechatClawBotStatus?.known_targets?.length" density="compact" class="border rounded">
|
||||||
|
<VListItem
|
||||||
|
v-for="item in wechatClawBotStatus.known_targets"
|
||||||
|
:key="item.userid"
|
||||||
|
:title="item.username || item.userid"
|
||||||
|
:subtitle="`${item.userid}${item.last_active ? ` · ${formatWechatClawBotTime(item.last_active)}` : ''}`"
|
||||||
|
/>
|
||||||
|
</VList>
|
||||||
|
<div v-else class="text-body-2 text-medium-emphasis">
|
||||||
|
{{ t('notification.wechatclawbot.noKnownTargets') }}
|
||||||
|
</div>
|
||||||
|
</VCol>
|
||||||
|
</VRow>
|
||||||
|
</VCard>
|
||||||
|
</VCol>
|
||||||
|
</VRow>
|
||||||
<VRow v-else-if="notificationInfo.type == 'telegram'">
|
<VRow v-else-if="notificationInfo.type == 'telegram'">
|
||||||
<VCol cols="12" md="6">
|
<VCol cols="12" md="6">
|
||||||
<VTextField
|
<VTextField
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ const userForm = ref<ExtendedUser>({
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
wechat_userid: null,
|
wechat_userid: null,
|
||||||
|
wechatclawbot_userid: null,
|
||||||
telegram_userid: null,
|
telegram_userid: null,
|
||||||
slack_userid: null,
|
slack_userid: null,
|
||||||
discord_userid: null,
|
discord_userid: null,
|
||||||
@@ -503,6 +504,15 @@ onMounted(() => {
|
|||||||
prepend-inner-icon="mdi-wechat"
|
prepend-inner-icon="mdi-wechat"
|
||||||
/>
|
/>
|
||||||
</VCol>
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="userForm.settings.wechatclawbot_userid"
|
||||||
|
density="comfortable"
|
||||||
|
clearable
|
||||||
|
:label="t('dialog.userAddEdit.wechatClawBot')"
|
||||||
|
prepend-inner-icon="mdi-robot-happy-outline"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
<VCol cols="12" md="6">
|
<VCol cols="12" md="6">
|
||||||
<VTextField
|
<VTextField
|
||||||
v-model="userForm.settings.telegram_userid"
|
v-model="userForm.settings.telegram_userid"
|
||||||
|
|||||||
@@ -329,6 +329,7 @@ export function useSetupWizard() {
|
|||||||
notification: {
|
notification: {
|
||||||
'telegram': 'TelegramModule',
|
'telegram': 'TelegramModule',
|
||||||
'wechat': 'WechatModule',
|
'wechat': 'WechatModule',
|
||||||
|
'wechatclawbot': 'WechatClawBotModule',
|
||||||
'slack': 'SlackModule',
|
'slack': 'SlackModule',
|
||||||
'synologychat': 'SynologyChatModule',
|
'synologychat': 'SynologyChatModule',
|
||||||
'qqbot': 'QQBotModule',
|
'qqbot': 'QQBotModule',
|
||||||
@@ -423,7 +424,17 @@ export function useSetupWizard() {
|
|||||||
wizardData.value.notification.type = type
|
wizardData.value.notification.type = type
|
||||||
// 如果名称为空或为默认名称,则设置默认名称
|
// 如果名称为空或为默认名称,则设置默认名称
|
||||||
if (!wizardData.value.notification.name || wizardData.value.notification.name.includes('通知')) {
|
if (!wizardData.value.notification.name || wizardData.value.notification.name.includes('通知')) {
|
||||||
wizardData.value.notification.name = `${type} 通知`
|
const displayNameMap: Record<string, string> = {
|
||||||
|
wechat: '企业微信',
|
||||||
|
wechatclawbot: '微信 ClawBot',
|
||||||
|
telegram: 'Telegram',
|
||||||
|
slack: 'Slack',
|
||||||
|
synologychat: 'SynologyChat',
|
||||||
|
qqbot: 'QQ',
|
||||||
|
vocechat: 'VoceChat',
|
||||||
|
webpush: 'WebPush',
|
||||||
|
}
|
||||||
|
wizardData.value.notification.name = `${displayNameMap[type] || type} 通知`
|
||||||
}
|
}
|
||||||
wizardData.value.notification.enabled = true
|
wizardData.value.notification.enabled = true
|
||||||
// 不清空config和switchs,保留用户已输入的值
|
// 不清空config和switchs,保留用户已输入的值
|
||||||
@@ -656,6 +667,8 @@ export function useSetupWizard() {
|
|||||||
validationErrors.value.notification.WECHAT_APP_SECRET = true
|
validationErrors.value.notification.WECHAT_APP_SECRET = true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case 'wechatclawbot':
|
||||||
|
break
|
||||||
case 'telegram':
|
case 'telegram':
|
||||||
if (!config.TELEGRAM_TOKEN?.trim()) {
|
if (!config.TELEGRAM_TOKEN?.trim()) {
|
||||||
errors.push(t('notification.telegram.tokenRequired'))
|
errors.push(t('notification.telegram.tokenRequired'))
|
||||||
@@ -854,7 +867,7 @@ export function useSetupWizard() {
|
|||||||
case 5: // 媒体服务器测试 - 只有选择了媒体服务器才测试
|
case 5: // 媒体服务器测试 - 只有选择了媒体服务器才测试
|
||||||
return !!wizardData.value.mediaServer.type
|
return !!wizardData.value.mediaServer.type
|
||||||
case 6: // 消息通知测试 - 只有选择了通知才测试
|
case 6: // 消息通知测试 - 只有选择了通知才测试
|
||||||
return !!wizardData.value.notification.type
|
return !!wizardData.value.notification.type && wizardData.value.notification.type !== 'wechatclawbot'
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -353,7 +353,8 @@ export default {
|
|||||||
},
|
},
|
||||||
notification: {
|
notification: {
|
||||||
title: 'Notifications',
|
title: 'Notifications',
|
||||||
description: 'Notification channels (WeChat, Telegram, Slack, SynologyChat, VoceChat, WebPush), message scope',
|
description:
|
||||||
|
'Notification channels (WeChat Work, WeChat ClawBot, Telegram, Slack, SynologyChat, VoceChat, WebPush), message scope',
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
title: 'About',
|
title: 'About',
|
||||||
@@ -472,6 +473,38 @@ export default {
|
|||||||
adminsHint: 'User IDs that can use admin menu and commands, separated by commas',
|
adminsHint: 'User IDs that can use admin menu and commands, separated by commas',
|
||||||
adminsPlaceholder: 'User IDs list, separated by commas',
|
adminsPlaceholder: 'User IDs list, separated by commas',
|
||||||
},
|
},
|
||||||
|
wechatclawbot: {
|
||||||
|
name: 'WeChat ClawBot',
|
||||||
|
baseUrl: 'iLink Base URL',
|
||||||
|
baseUrlHint: 'iLink service URL for WeChat ClawBot, keep default in most cases',
|
||||||
|
defaultTarget: 'Default Target',
|
||||||
|
defaultTargetHint: 'Optional target userid; leave empty to notify interacted users',
|
||||||
|
defaultTargetPlaceholder: 'userid (optional)',
|
||||||
|
admins: 'Admin Whitelist',
|
||||||
|
adminsHint: 'User IDs allowed to run slash commands, separated by commas',
|
||||||
|
adminsPlaceholder: 'User IDs list, separated by commas',
|
||||||
|
pollTimeout: 'Poll Timeout (seconds)',
|
||||||
|
pollTimeoutHint: 'Long polling timeout, recommended 20-30 seconds',
|
||||||
|
loginStatus: 'Login Status',
|
||||||
|
connected: 'Connected',
|
||||||
|
waiting: 'Waiting for QR scan',
|
||||||
|
scanned: 'Scanned, waiting for confirmation',
|
||||||
|
confirmed: 'Confirmed, establishing connection',
|
||||||
|
expired: 'QR code expired',
|
||||||
|
refreshQrcode: 'Refresh QR Code',
|
||||||
|
logout: 'Logout',
|
||||||
|
noQrcode: 'No QR code yet. Refresh or save config first.',
|
||||||
|
scanHint: 'Scan with WeChat to bind. Save and enable this channel before first use.',
|
||||||
|
accountId: 'Account ID',
|
||||||
|
qrcodeUpdatedAt: 'QR Updated At',
|
||||||
|
knownTargets: 'Recent Interacted Users',
|
||||||
|
noKnownTargets: 'No interaction records yet',
|
||||||
|
statusLoadFailed: 'Failed to load WeChat ClawBot status',
|
||||||
|
qrcodeRefreshSuccess: 'WeChat ClawBot QR code refreshed',
|
||||||
|
qrcodeRefreshFailed: 'Failed to refresh WeChat ClawBot QR code',
|
||||||
|
logoutSuccess: 'WeChat ClawBot logged out',
|
||||||
|
logoutFailed: 'Failed to logout WeChat ClawBot',
|
||||||
|
},
|
||||||
telegram: {
|
telegram: {
|
||||||
name: 'Telegram',
|
name: 'Telegram',
|
||||||
token: 'Bot Token',
|
token: 'Bot Token',
|
||||||
@@ -1732,7 +1765,8 @@ export default {
|
|||||||
timeSaveSuccess: 'Notification send time saved successfully',
|
timeSaveSuccess: 'Notification send time saved successfully',
|
||||||
timeSaveFailed: 'Failed to save notification send time!',
|
timeSaveFailed: 'Failed to save notification send time!',
|
||||||
channel: 'Notification',
|
channel: 'Notification',
|
||||||
wechat: 'WeChat',
|
wechat: 'WeChat Work',
|
||||||
|
wechatClawBot: 'WeChat ClawBot',
|
||||||
resourceDownload: 'Resource Download',
|
resourceDownload: 'Resource Download',
|
||||||
mediaImport: 'Media Import',
|
mediaImport: 'Media Import',
|
||||||
subscription: 'Subscription',
|
subscription: 'Subscription',
|
||||||
@@ -1816,7 +1850,7 @@ export default {
|
|||||||
animeCategory: 'Anime',
|
animeCategory: 'Anime',
|
||||||
downloadUser: 'Remote Search Auto Download User List',
|
downloadUser: 'Remote Search Auto Download User List',
|
||||||
downloadUserHint:
|
downloadUserHint:
|
||||||
'Whether to automatically download when searching with Telegram, WeChat, etc., comma separated, set to all to represent all users auto-download',
|
'Whether to auto-download when searching with Telegram, WeChat Work, etc., comma separated, set to all for all users',
|
||||||
multipleNameSearch: 'Multiple Name Resource Search',
|
multipleNameSearch: 'Multiple Name Resource Search',
|
||||||
multipleNameSearchHint:
|
multipleNameSearchHint:
|
||||||
'Search site resources using multiple names (Chinese, English, etc.) and merge search results, will increase site access frequency',
|
'Search site resources using multiple names (Chinese, English, etc.) and merge search results, will increase site access frequency',
|
||||||
@@ -2061,7 +2095,8 @@ export default {
|
|||||||
resetDefaultAvatar: 'Reset Default Avatar',
|
resetDefaultAvatar: 'Reset Default Avatar',
|
||||||
restoreCurrentAvatar: 'Restore Current Avatar',
|
restoreCurrentAvatar: 'Restore Current Avatar',
|
||||||
notifications: 'Notifications',
|
notifications: 'Notifications',
|
||||||
wechat: 'WeChat UserID',
|
wechat: 'WeChat Work UserID',
|
||||||
|
wechatClawBot: 'WeChat ClawBot UserID',
|
||||||
telegram: 'Telegram UserID',
|
telegram: 'Telegram UserID',
|
||||||
slack: 'Slack UserID',
|
slack: 'Slack UserID',
|
||||||
discord: 'Discord UserID',
|
discord: 'Discord UserID',
|
||||||
@@ -2787,7 +2822,8 @@ export default {
|
|||||||
nickname: 'Nickname',
|
nickname: 'Nickname',
|
||||||
nicknamePlaceholder: 'Display nickname, takes precedence over username',
|
nicknamePlaceholder: 'Display nickname, takes precedence over username',
|
||||||
accountBinding: 'Account Binding',
|
accountBinding: 'Account Binding',
|
||||||
wechatUser: 'WeChat User',
|
wechatUser: 'WeChat Work User',
|
||||||
|
wechatClawBotUser: 'WeChat ClawBot User',
|
||||||
telegramUser: 'Telegram User',
|
telegramUser: 'Telegram User',
|
||||||
slackUser: 'Slack User',
|
slackUser: 'Slack User',
|
||||||
discordUser: 'Discord User',
|
discordUser: 'Discord User',
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ export default {
|
|||||||
},
|
},
|
||||||
notification: {
|
notification: {
|
||||||
title: '通知',
|
title: '通知',
|
||||||
description: '通知渠道(微信、Telegram、Slack、SynologyChat、VoceChat、WebPush)、消息发送范围',
|
description: '通知渠道(企业微信、微信 ClawBot、Telegram、Slack、SynologyChat、VoceChat、WebPush)、消息发送范围',
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
title: '关于',
|
title: '关于',
|
||||||
@@ -468,6 +468,38 @@ export default {
|
|||||||
adminsHint: '可使用管理菜单及命令的用户ID列表,多个ID使用,分隔',
|
adminsHint: '可使用管理菜单及命令的用户ID列表,多个ID使用,分隔',
|
||||||
adminsPlaceholder: '用户ID列表,多个ID使用,分隔',
|
adminsPlaceholder: '用户ID列表,多个ID使用,分隔',
|
||||||
},
|
},
|
||||||
|
wechatclawbot: {
|
||||||
|
name: '微信 ClawBot',
|
||||||
|
baseUrl: 'iLink 地址',
|
||||||
|
baseUrlHint: '微信 ClawBot iLink 服务地址,通常使用默认值',
|
||||||
|
defaultTarget: '默认通知目标',
|
||||||
|
defaultTargetHint: '可填写用户 userid;不填则默认发给已互动用户',
|
||||||
|
defaultTargetPlaceholder: '用户 userid(可选)',
|
||||||
|
admins: '管理员白名单',
|
||||||
|
adminsHint: '允许执行斜杠命令的用户ID列表,多个ID使用,分隔',
|
||||||
|
adminsPlaceholder: '用户ID列表,多个ID使用,分隔',
|
||||||
|
pollTimeout: '轮询超时(秒)',
|
||||||
|
pollTimeoutHint: '长轮询请求超时时间,建议 20-30 秒',
|
||||||
|
loginStatus: '登录状态',
|
||||||
|
connected: '已连接',
|
||||||
|
waiting: '等待扫码',
|
||||||
|
scanned: '已扫码,待确认',
|
||||||
|
confirmed: '已确认,正在建立连接',
|
||||||
|
expired: '二维码已过期',
|
||||||
|
refreshQrcode: '刷新二维码',
|
||||||
|
logout: '退出登录',
|
||||||
|
noQrcode: '暂无二维码,请先刷新或保存配置后重试',
|
||||||
|
scanHint: '使用微信扫码绑定后,状态会自动刷新。首次使用请先保存并启用该通知渠道。',
|
||||||
|
accountId: '账号ID',
|
||||||
|
qrcodeUpdatedAt: '二维码更新时间',
|
||||||
|
knownTargets: '最近互动用户',
|
||||||
|
noKnownTargets: '暂无互动用户记录',
|
||||||
|
statusLoadFailed: '获取微信 ClawBot 状态失败',
|
||||||
|
qrcodeRefreshSuccess: '微信 ClawBot 二维码已刷新',
|
||||||
|
qrcodeRefreshFailed: '刷新微信 ClawBot 二维码失败',
|
||||||
|
logoutSuccess: '微信 ClawBot 已退出登录',
|
||||||
|
logoutFailed: '微信 ClawBot 退出登录失败',
|
||||||
|
},
|
||||||
telegram: {
|
telegram: {
|
||||||
name: 'Telegram',
|
name: 'Telegram',
|
||||||
token: 'Bot Token',
|
token: 'Bot Token',
|
||||||
@@ -1703,7 +1735,8 @@ export default {
|
|||||||
timeSaveSuccess: '通知发送时间保存成功',
|
timeSaveSuccess: '通知发送时间保存成功',
|
||||||
timeSaveFailed: '通知发送时间保存失败!',
|
timeSaveFailed: '通知发送时间保存失败!',
|
||||||
channel: '通知',
|
channel: '通知',
|
||||||
wechat: '微信',
|
wechat: '企业微信',
|
||||||
|
wechatClawBot: '微信 ClawBot',
|
||||||
resourceDownload: '资源下载',
|
resourceDownload: '资源下载',
|
||||||
mediaImport: '整理入库',
|
mediaImport: '整理入库',
|
||||||
subscription: '订阅',
|
subscription: '订阅',
|
||||||
@@ -1781,7 +1814,7 @@ export default {
|
|||||||
tvCategory: '电视剧',
|
tvCategory: '电视剧',
|
||||||
animeCategory: '动漫',
|
animeCategory: '动漫',
|
||||||
downloadUser: '远程搜索自动下载用户',
|
downloadUser: '远程搜索自动下载用户',
|
||||||
downloadUserHint: '使用Telegram、微信等搜索时是否自动下载,使用逗号分割,设置为 all 代表所有用户自动择优下载',
|
downloadUserHint: '使用Telegram、企业微信等搜索时是否自动下载,使用逗号分割,设置为 all 代表所有用户自动择优下载',
|
||||||
multipleNameSearch: '多名称资源搜索',
|
multipleNameSearch: '多名称资源搜索',
|
||||||
multipleNameSearchHint: '使用多个名称(中文、英文等)搜索站点资源并合并搜索结果,会增加站点访问频率',
|
multipleNameSearchHint: '使用多个名称(中文、英文等)搜索站点资源并合并搜索结果,会增加站点访问频率',
|
||||||
downloadSubtitle: '下载站点字幕',
|
downloadSubtitle: '下载站点字幕',
|
||||||
@@ -2021,7 +2054,8 @@ export default {
|
|||||||
resetDefaultAvatar: '重置默认头像',
|
resetDefaultAvatar: '重置默认头像',
|
||||||
restoreCurrentAvatar: '还原当前头像',
|
restoreCurrentAvatar: '还原当前头像',
|
||||||
notifications: '通知',
|
notifications: '通知',
|
||||||
wechat: '微信ID',
|
wechat: '企业微信ID',
|
||||||
|
wechatClawBot: '微信 ClawBot ID',
|
||||||
telegram: 'Telegram ID',
|
telegram: 'Telegram ID',
|
||||||
slack: 'Slack ID',
|
slack: 'Slack ID',
|
||||||
discord: 'Discord ID',
|
discord: 'Discord ID',
|
||||||
@@ -2740,7 +2774,8 @@ export default {
|
|||||||
nickname: '昵称',
|
nickname: '昵称',
|
||||||
nicknamePlaceholder: '显示昵称,优先于用户名显示',
|
nicknamePlaceholder: '显示昵称,优先于用户名显示',
|
||||||
accountBinding: '账号绑定',
|
accountBinding: '账号绑定',
|
||||||
wechatUser: '微信用户',
|
wechatUser: '企业微信用户',
|
||||||
|
wechatClawBotUser: '微信 ClawBot 用户',
|
||||||
telegramUser: 'Telegram用户',
|
telegramUser: 'Telegram用户',
|
||||||
slackUser: 'Slack用户',
|
slackUser: 'Slack用户',
|
||||||
discordUser: 'Discord用户',
|
discordUser: 'Discord用户',
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ export default {
|
|||||||
},
|
},
|
||||||
notification: {
|
notification: {
|
||||||
title: '通知',
|
title: '通知',
|
||||||
description: '通知渠道(微信、Telegram、Slack、SynologyChat、VoceChat、WebPush)、消息發送範圍',
|
description: '通知渠道(企業微信、微信 ClawBot、Telegram、Slack、SynologyChat、VoceChat、WebPush)、消息發送範圍',
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
title: '關於',
|
title: '關於',
|
||||||
@@ -469,6 +469,38 @@ export default {
|
|||||||
adminsHint: '可使用管理菜單及命令的用戶ID列表,多個ID使用,分隔',
|
adminsHint: '可使用管理菜單及命令的用戶ID列表,多個ID使用,分隔',
|
||||||
adminsPlaceholder: '用戶ID列表,多個ID使用,分隔',
|
adminsPlaceholder: '用戶ID列表,多個ID使用,分隔',
|
||||||
},
|
},
|
||||||
|
wechatclawbot: {
|
||||||
|
name: '微信 ClawBot',
|
||||||
|
baseUrl: 'iLink 地址',
|
||||||
|
baseUrlHint: '微信 ClawBot iLink 服務地址,通常使用預設值',
|
||||||
|
defaultTarget: '預設通知目標',
|
||||||
|
defaultTargetHint: '可填寫使用者 userid;不填則預設發給已互動使用者',
|
||||||
|
defaultTargetPlaceholder: '使用者 userid(可選)',
|
||||||
|
admins: '管理員白名單',
|
||||||
|
adminsHint: '允許執行斜線命令的用戶ID列表,多個ID使用,分隔',
|
||||||
|
adminsPlaceholder: '用戶ID列表,多個ID使用,分隔',
|
||||||
|
pollTimeout: '輪詢超時(秒)',
|
||||||
|
pollTimeoutHint: '長輪詢請求超時時間,建議 20-30 秒',
|
||||||
|
loginStatus: '登入狀態',
|
||||||
|
connected: '已連線',
|
||||||
|
waiting: '等待掃碼',
|
||||||
|
scanned: '已掃碼,待確認',
|
||||||
|
confirmed: '已確認,正在建立連線',
|
||||||
|
expired: '二維碼已過期',
|
||||||
|
refreshQrcode: '刷新二維碼',
|
||||||
|
logout: '退出登入',
|
||||||
|
noQrcode: '暫無二維碼,請先刷新或保存配置後再試',
|
||||||
|
scanHint: '使用微信掃碼綁定後,狀態會自動刷新。首次使用請先保存並啟用該通知渠道。',
|
||||||
|
accountId: '帳號ID',
|
||||||
|
qrcodeUpdatedAt: '二維碼更新時間',
|
||||||
|
knownTargets: '最近互動用戶',
|
||||||
|
noKnownTargets: '暫無互動用戶記錄',
|
||||||
|
statusLoadFailed: '獲取微信 ClawBot 狀態失敗',
|
||||||
|
qrcodeRefreshSuccess: '微信 ClawBot 二維碼已刷新',
|
||||||
|
qrcodeRefreshFailed: '刷新微信 ClawBot 二維碼失敗',
|
||||||
|
logoutSuccess: '微信 ClawBot 已退出登入',
|
||||||
|
logoutFailed: '微信 ClawBot 退出登入失敗',
|
||||||
|
},
|
||||||
telegram: {
|
telegram: {
|
||||||
name: 'Telegram',
|
name: 'Telegram',
|
||||||
token: 'Bot Token',
|
token: 'Bot Token',
|
||||||
@@ -1705,7 +1737,8 @@ export default {
|
|||||||
timeSaveSuccess: '通知發送時間保存成功',
|
timeSaveSuccess: '通知發送時間保存成功',
|
||||||
timeSaveFailed: '通知發送時間保存失敗!',
|
timeSaveFailed: '通知發送時間保存失敗!',
|
||||||
channel: '通知',
|
channel: '通知',
|
||||||
wechat: '微信',
|
wechat: '企業微信',
|
||||||
|
wechatClawBot: '微信 ClawBot',
|
||||||
resourceDownload: '資源下載',
|
resourceDownload: '資源下載',
|
||||||
mediaImport: '整理入庫',
|
mediaImport: '整理入庫',
|
||||||
subscription: '訂閱',
|
subscription: '訂閱',
|
||||||
@@ -1791,7 +1824,7 @@ export default {
|
|||||||
mediaSourceHint: '搜索媒體信息時使用的數據源以及排序',
|
mediaSourceHint: '搜索媒體信息時使用的數據源以及排序',
|
||||||
filterRuleGroupHint: '搜索媒體信息時按選定的過濾規則組對結果進行過濾',
|
filterRuleGroupHint: '搜索媒體信息時按選定的過濾規則組對結果進行過濾',
|
||||||
downloadUserPlaceholder: '用戶ID1,用戶ID2',
|
downloadUserPlaceholder: '用戶ID1,用戶ID2',
|
||||||
downloadUserHint: '使用Telegram、微信等搜索時是否自動下載,使用逗號分割,設置為 all 代表所有用戶自動擇優下載',
|
downloadUserHint: '使用Telegram、企業微信等搜索時是否自動下載,使用逗號分割,設置為 all 代表所有用戶自動擇優下載',
|
||||||
downloadLabelPlaceholder: 'MOVIEPILOT',
|
downloadLabelPlaceholder: 'MOVIEPILOT',
|
||||||
},
|
},
|
||||||
directory: {
|
directory: {
|
||||||
@@ -2023,7 +2056,8 @@ export default {
|
|||||||
resetDefaultAvatar: '重置默認頭像',
|
resetDefaultAvatar: '重置默認頭像',
|
||||||
restoreCurrentAvatar: '還原當前頭像',
|
restoreCurrentAvatar: '還原當前頭像',
|
||||||
notifications: '通知',
|
notifications: '通知',
|
||||||
wechat: '微信UserID',
|
wechat: '企業微信 UserID',
|
||||||
|
wechatClawBot: '微信 ClawBot ID',
|
||||||
telegram: 'Telegram UserID',
|
telegram: 'Telegram UserID',
|
||||||
slack: 'Slack UserID',
|
slack: 'Slack UserID',
|
||||||
discord: 'Discord UserID',
|
discord: 'Discord UserID',
|
||||||
@@ -2742,7 +2776,8 @@ export default {
|
|||||||
nickname: '暱稱',
|
nickname: '暱稱',
|
||||||
nicknamePlaceholder: '顯示暱稱,優先於用戶名顯示',
|
nicknamePlaceholder: '顯示暱稱,優先於用戶名顯示',
|
||||||
accountBinding: '賬號綁定',
|
accountBinding: '賬號綁定',
|
||||||
wechatUser: '微信用戶',
|
wechatUser: '企業微信用戶',
|
||||||
|
wechatClawBotUser: '微信 ClawBot 用戶',
|
||||||
telegramUser: 'Telegram用戶',
|
telegramUser: 'Telegram用戶',
|
||||||
slackUser: 'Slack用戶',
|
slackUser: 'Slack用戶',
|
||||||
discordUser: 'Discord用戶',
|
discordUser: 'Discord用戶',
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import plexLogo from '@/assets/images/logos/plex.png'
|
|||||||
import trimemediaLogo from '@/assets/images/logos/trimemedia.png'
|
import trimemediaLogo from '@/assets/images/logos/trimemedia.png'
|
||||||
import ugreenLogo from '@/assets/images/logos/ugreen.png'
|
import ugreenLogo from '@/assets/images/logos/ugreen.png'
|
||||||
import wechatLogo from '@/assets/images/logos/wechat.png'
|
import wechatLogo from '@/assets/images/logos/wechat.png'
|
||||||
|
import clawbotLogo from '@/assets/images/logos/clawbot.png'
|
||||||
import telegramLogo from '@/assets/images/logos/telegram.webp'
|
import telegramLogo from '@/assets/images/logos/telegram.webp'
|
||||||
import slackLogo from '@/assets/images/logos/slack.webp'
|
import slackLogo from '@/assets/images/logos/slack.webp'
|
||||||
import discordLogo from '@/assets/images/logos/discord.png'
|
import discordLogo from '@/assets/images/logos/discord.png'
|
||||||
@@ -44,6 +45,7 @@ const logoMap: Record<string, string> = {
|
|||||||
trimemedia: trimemediaLogo,
|
trimemedia: trimemediaLogo,
|
||||||
ugreen: ugreenLogo,
|
ugreen: ugreenLogo,
|
||||||
wechat: wechatLogo,
|
wechat: wechatLogo,
|
||||||
|
wechatclawbot: clawbotLogo,
|
||||||
telegram: telegramLogo,
|
telegram: telegramLogo,
|
||||||
slack: slackLogo,
|
slack: slackLogo,
|
||||||
discord: discordLogo,
|
discord: discordLogo,
|
||||||
|
|||||||
@@ -299,12 +299,15 @@ onMounted(() => {
|
|||||||
<VIcon icon="mdi-plus" />
|
<VIcon icon="mdi-plus" />
|
||||||
<VMenu :activator="'parent'" :close-on-content-click="true">
|
<VMenu :activator="'parent'" :close-on-content-click="true">
|
||||||
<VList>
|
<VList>
|
||||||
<VListItem @click="addNotification('wechat')">
|
<VListItem @click="addNotification('wechat')">
|
||||||
<VListItemTitle>{{ t('setting.notification.wechat') }}</VListItemTitle>
|
<VListItemTitle>{{ t('setting.notification.wechat') }}</VListItemTitle>
|
||||||
</VListItem>
|
</VListItem>
|
||||||
<VListItem @click="addNotification('telegram')">
|
<VListItem @click="addNotification('wechatclawbot')">
|
||||||
<VListItemTitle>{{ t('setting.notification.telegram') }}</VListItemTitle>
|
<VListItemTitle>{{ t('setting.notification.wechatClawBot') }}</VListItemTitle>
|
||||||
</VListItem>
|
</VListItem>
|
||||||
|
<VListItem @click="addNotification('telegram')">
|
||||||
|
<VListItemTitle>{{ t('setting.notification.telegram') }}</VListItemTitle>
|
||||||
|
</VListItem>
|
||||||
<VListItem @click="addNotification('slack')">
|
<VListItem @click="addNotification('slack')">
|
||||||
<VListItemTitle>{{ t('setting.notification.slack') }}</VListItemTitle>
|
<VListItemTitle>{{ t('setting.notification.slack') }}</VListItemTitle>
|
||||||
</VListItem>
|
</VListItem>
|
||||||
|
|||||||
@@ -49,7 +49,20 @@ const notificationTypes = [
|
|||||||
>
|
>
|
||||||
<VCardText class="text-center">
|
<VCardText class="text-center">
|
||||||
<VImg :src="getLogoUrl('wechat')" height="48" width="48" class="mx-auto mb-2" />
|
<VImg :src="getLogoUrl('wechat')" height="48" width="48" class="mx-auto mb-2" />
|
||||||
<div class="text-h6">微信</div>
|
<div class="text-h6">企业微信</div>
|
||||||
|
</VCardText>
|
||||||
|
</VCard>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="3">
|
||||||
|
<VCard
|
||||||
|
:color="wizardData.notification.type === 'wechatclawbot' ? 'primary' : 'default'"
|
||||||
|
:variant="wizardData.notification.type === 'wechatclawbot' ? 'tonal' : 'outlined'"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="selectNotification('wechatclawbot')"
|
||||||
|
>
|
||||||
|
<VCardText class="text-center">
|
||||||
|
<VImg :src="getLogoUrl('wechatclawbot')" height="48" width="48" class="mx-auto mb-2" />
|
||||||
|
<div class="text-h6">WeChat ClawBot</div>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
</VCol>
|
</VCol>
|
||||||
@@ -251,6 +264,50 @@ const notificationTypes = [
|
|||||||
/>
|
/>
|
||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
|
<VRow v-else-if="wizardData.notification.type === 'wechatclawbot'">
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="wizardData.notification.name"
|
||||||
|
:label="t('notification.name')"
|
||||||
|
:placeholder="t('notification.name')"
|
||||||
|
:hint="t('notification.nameHint')"
|
||||||
|
:error="validationErrors.notification.name"
|
||||||
|
:error-messages="validationErrors.notification.name ? [t('notification.nameRequired')] : []"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-label"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="wizardData.notification.config.WECHATCLAWBOT_BASE_URL"
|
||||||
|
:label="t('notification.wechatclawbot.baseUrl')"
|
||||||
|
:hint="t('notification.wechatclawbot.baseUrlHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-web"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="wizardData.notification.config.WECHATCLAWBOT_DEFAULT_TARGET"
|
||||||
|
:label="t('notification.wechatclawbot.defaultTarget')"
|
||||||
|
:placeholder="t('notification.wechatclawbot.defaultTargetPlaceholder')"
|
||||||
|
:hint="t('notification.wechatclawbot.defaultTargetHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-account-arrow-right"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="wizardData.notification.config.WECHATCLAWBOT_ADMINS"
|
||||||
|
:label="t('notification.wechatclawbot.admins')"
|
||||||
|
:placeholder="t('notification.wechatclawbot.adminsPlaceholder')"
|
||||||
|
:hint="t('notification.wechatclawbot.adminsHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-account-supervisor"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
</VRow>
|
||||||
<VRow v-else-if="wizardData.notification.type === 'telegram'">
|
<VRow v-else-if="wizardData.notification.type === 'telegram'">
|
||||||
<VCol cols="12" md="6">
|
<VCol cols="12" md="6">
|
||||||
<VTextField
|
<VTextField
|
||||||
|
|||||||
@@ -436,6 +436,15 @@ watch(
|
|||||||
prepend-inner-icon="mdi-wechat"
|
prepend-inner-icon="mdi-wechat"
|
||||||
/>
|
/>
|
||||||
</VCol>
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="accountInfo.settings.wechatclawbot_userid"
|
||||||
|
density="comfortable"
|
||||||
|
clearable
|
||||||
|
:label="t('profile.wechatClawBotUser')"
|
||||||
|
prepend-inner-icon="mdi-robot-happy-outline"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
<VCol cols="12" md="6">
|
<VCol cols="12" md="6">
|
||||||
<VTextField
|
<VTextField
|
||||||
v-model="accountInfo.settings.telegram_userid"
|
v-model="accountInfo.settings.telegram_userid"
|
||||||
|
|||||||
Reference in New Issue
Block a user