Merge branch 'master' into preview

This commit is contained in:
opensnail 2025-03-31 23:10:31 +08:00
commit bb2c79afa5
6 changed files with 71 additions and 7 deletions

2
.env
View File

@ -6,7 +6,7 @@ VITE_APP_TITLE=Snail Job
VITE_APP_DESC=A flexible, reliable, and fast platform for distributed task retry and distributed task scheduling. VITE_APP_DESC=A flexible, reliable, and fast platform for distributed task retry and distributed task scheduling.
VITE_APP_VERSION=1.4.0-beta1 VITE_APP_VERSION=1.4.0
VITE_APP_DEFAULT_TOKEN=SJ_Wyz3dmsdbDOkDujOTSSoBjGQP1BMsVnj VITE_APP_DEFAULT_TOKEN=SJ_Wyz3dmsdbDOkDujOTSSoBjGQP1BMsVnj

View File

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { useClipboard } from '@vueuse/core';
import { groupConfigStatusRecord, yesOrNoRecord } from '@/constants/business'; import { groupConfigStatusRecord, yesOrNoRecord } from '@/constants/business';
import { $t } from '@/locales'; import { $t } from '@/locales';
import { tagColor } from '@/utils/common'; import { tagColor } from '@/utils/common';
defineOptions({ defineOptions({
name: 'GroupDetailDrawer' name: 'GroupDetailDrawer'
}); });
@ -17,6 +17,31 @@ defineProps<Props>();
const visible = defineModel<boolean>('visible', { const visible = defineModel<boolean>('visible', {
default: false default: false
}); });
const { copy, isSupported } = useClipboard();
async function handleCopy(source?: string) {
if (!isSupported) {
window.$message?.error('您的浏览器不支持 Clipboard API');
return;
}
if (!source) {
return;
}
if (navigator.clipboard && window.isSecureContext) {
await copy(source);
} else {
const range = document.createRange();
range.selectNode(document.getElementById('tokenDetailInput')!);
const selection = window.getSelection();
if (selection?.rangeCount) selection.removeAllRanges();
selection?.addRange(range);
document.execCommand('copy');
}
window.$message?.success('复制成功');
}
</script> </script>
<template> <template>
@ -26,7 +51,17 @@ const visible = defineModel<boolean>('visible', {
{{ rowData?.groupName }} {{ rowData?.groupName }}
</NDescriptionsItem> </NDescriptionsItem>
<NDescriptionsItem :label="$t('page.groupConfig.token')" :span="1">{{ rowData?.token }}</NDescriptionsItem> <NDescriptionsItem :span="1">
<template #label>
<div class="flex items-center gap-2">
<span>{{ $t('page.groupConfig.token') }}</span>
<NButton type="default" text @click="handleCopy(rowData?.token)">
<icon-ic:round-content-copy class="text-icon" />
</NButton>
</div>
</template>
<span id="tokenDetailInput">{{ rowData?.token }}</span>
</NDescriptionsItem>
<NDescriptionsItem :label="$t('page.groupConfig.groupStatus')" :span="1"> <NDescriptionsItem :label="$t('page.groupConfig.groupStatus')" :span="1">
<NTag :type="tagColor(rowData?.groupStatus!)">{{ $t(groupConfigStatusRecord[rowData?.groupStatus!]) }}</NTag> <NTag :type="tagColor(rowData?.groupStatus!)">{{ $t(groupConfigStatusRecord[rowData?.groupStatus!]) }}</NTag>
</NDescriptionsItem> </NDescriptionsItem>

View File

@ -172,7 +172,16 @@ async function handleCopy(source: string) {
return; return;
} }
if (navigator.clipboard && window.isSecureContext) {
await copy(source); await copy(source);
} else {
const range = document.createRange();
range.selectNode(document.getElementById('tokenOperateInput')!);
const selection = window.getSelection();
if (selection?.rangeCount) selection.removeAllRanges();
selection?.addRange(range);
document.execCommand('copy');
}
window.$message?.success('复制成功'); window.$message?.success('复制成功');
} }
</script> </script>
@ -206,6 +215,7 @@ async function handleCopy(source: string) {
<NFormItem :label="$t('page.groupConfig.token')" path="token"> <NFormItem :label="$t('page.groupConfig.token')" path="token">
<NInputGroup> <NInputGroup>
<NInput <NInput
id="tokenOperateInput"
v-model:value="model.token" v-model:value="model.token"
:maxlength="64" :maxlength="64"
:placeholder="$t('page.groupConfig.form.token')" :placeholder="$t('page.groupConfig.form.token')"

View File

@ -32,7 +32,16 @@ async function handleCopy(source: string) {
return; return;
} }
if (navigator.clipboard && window.isSecureContext) {
await copy(source); await copy(source);
} else {
const input = document.createElement('input');
input.value = source;
document.body.appendChild(input);
input.select();
document.execCommand('copy');
document.body.removeChild(input);
}
window.$message?.success('复制成功'); window.$message?.success('复制成功');
} }

View File

@ -124,7 +124,16 @@ async function handleCopy(source: string) {
return; return;
} }
if (navigator.clipboard && window.isSecureContext) {
await copy(source); await copy(source);
} else {
const range = document.createRange();
range.selectNode(document.getElementById('uniqueIdInput')!);
const selection = window.getSelection();
if (selection?.rangeCount) selection.removeAllRanges();
selection?.addRange(range);
document.execCommand('copy');
}
window.$message?.success('复制成功'); window.$message?.success('复制成功');
} }
</script> </script>
@ -135,6 +144,7 @@ async function handleCopy(source: string) {
<NFormItem :label="$t('page.namespace.uniqueId')" path="uniqueId"> <NFormItem :label="$t('page.namespace.uniqueId')" path="uniqueId">
<NInputGroup> <NInputGroup>
<NInput <NInput
id="uniqueIdInput"
v-model:value="model.uniqueId" v-model:value="model.uniqueId"
:disabled="props.operateType === 'edit'" :disabled="props.operateType === 'edit'"
:placeholder="$t('page.namespace.form.uniqueId')" :placeholder="$t('page.namespace.form.uniqueId')"

View File

@ -20,7 +20,7 @@ const visible = defineModel<boolean>('visible', {
</script> </script>
<template> <template>
<DetailDrawer v-model="visible" :title="$t('page.retryLog.detail')" :width="['50%', '90%']"> <DetailDrawer v-model="visible" :title="$t('page.retryTask.detail')" :width="['50%', '90%']">
<NTabs type="segment" animated> <NTabs type="segment" animated>
<NTabPane :name="0" :tab="$t('page.log.info')"> <NTabPane :name="0" :tab="$t('page.log.info')">
<NDescriptions label-placement="top" bordered :column="2"> <NDescriptions label-placement="top" bordered :column="2">