181 lines
6.8 KiB
Vue
181 lines
6.8 KiB
Vue
<script lang="ts">
|
||
import { ref, defineComponent } from 'vue'
|
||
import { toast } from 'vue-sonner'
|
||
import { Button } from '@/components/ui/button'
|
||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||
import { Badge } from '@/components/ui/badge'
|
||
// @ts-ignore
|
||
import { TemplateApiStrGenerate } from '@/util/viewApi'
|
||
|
||
export default defineComponent({
|
||
name: 'TemplateApiViewer',
|
||
components: {
|
||
Button,
|
||
Dialog,
|
||
DialogContent,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
Tabs,
|
||
TabsContent,
|
||
TabsList,
|
||
TabsTrigger,
|
||
Badge
|
||
},
|
||
props: {
|
||
open: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
templateData: {
|
||
type: Object,
|
||
default: null
|
||
}
|
||
},
|
||
emits: ['update:open'],
|
||
setup(props, { emit }) {
|
||
// 处理关闭事件
|
||
const handleUpdateOpen = (value: boolean) => {
|
||
emit('update:open', value)
|
||
}
|
||
|
||
// 当前选中的标签
|
||
const activeTab = ref('curl')
|
||
|
||
// 代码语言选项
|
||
const codeLanguages = [
|
||
{ value: 'curl', label: 'cURL', icon: '🌐' },
|
||
{ value: 'javascript', label: 'JS', icon: '🟨' },
|
||
{ value: 'python', label: 'Python', icon: '🐍' },
|
||
{ value: 'php', label: 'PHP', icon: '🐘' },
|
||
{ value: 'golang', label: 'Go', icon: '🐹' },
|
||
{ value: 'java', label: 'Java', icon: '☕' },
|
||
{ value: 'rust', label: 'Rust', icon: '🦀' }
|
||
]
|
||
|
||
// 生成API代码示例
|
||
const generateApiCode = (language: string) => {
|
||
const templateId = props.templateData?.id || 'TEMPLATE_ID'
|
||
const placeholders = props.templateData?.placeholders || '[]'
|
||
|
||
switch (language) {
|
||
case 'curl':
|
||
return TemplateApiStrGenerate.getCurlString(templateId, placeholders)
|
||
case 'javascript':
|
||
return TemplateApiStrGenerate.getNodeString(templateId, placeholders)
|
||
case 'python':
|
||
return TemplateApiStrGenerate.getPythonString(templateId, placeholders)
|
||
case 'php':
|
||
return TemplateApiStrGenerate.getPHPString(templateId, placeholders)
|
||
case 'golang':
|
||
return TemplateApiStrGenerate.getGolangString(templateId, placeholders)
|
||
case 'java':
|
||
return TemplateApiStrGenerate.getJavaString(templateId, placeholders)
|
||
case 'rust':
|
||
return TemplateApiStrGenerate.getRustString(templateId, placeholders)
|
||
default:
|
||
return '// 请选择一种编程语言查看示例代码'
|
||
}
|
||
}
|
||
|
||
// 复制代码到剪贴板
|
||
const copyToClipboard = async (text: string) => {
|
||
try {
|
||
await navigator.clipboard.writeText(text)
|
||
toast.success('复制成功')
|
||
} catch (err) {
|
||
toast.error('复制失败')
|
||
}
|
||
}
|
||
|
||
return {
|
||
handleUpdateOpen,
|
||
activeTab,
|
||
codeLanguages,
|
||
generateApiCode,
|
||
copyToClipboard
|
||
}
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<Dialog :open="open" @update:open="handleUpdateOpen">
|
||
<DialogContent class="w-[800px] sm:w-[900px] lg:w-[1000px] max-w-[90vw] max-h-[90vh] overflow-y-auto">
|
||
<DialogHeader>
|
||
<DialogTitle class="flex items-center gap-2">
|
||
<span>模板API接口</span>
|
||
<Badge v-if="templateData" variant="outline">{{ templateData.name }}</Badge>
|
||
</DialogTitle>
|
||
</DialogHeader>
|
||
|
||
<div class="space-y-4">
|
||
<!-- API 信息概览 -->
|
||
<div class="border rounded-lg p-4 space-y-2 bg-white dark:bg-slate-900">
|
||
<div class="flex items-center gap-2">
|
||
<Badge variant="default">POST</Badge>
|
||
<code class="text-sm bg-gray-100 dark:bg-slate-800 px-2 py-1 rounded">/api/v2/message/send</code>
|
||
</div>
|
||
<p class="text-sm text-gray-600 dark:text-gray-400">使用模板发送消息(V2接口)</p>
|
||
<div class="mt-3 space-y-1 text-xs text-gray-500 dark:text-gray-400">
|
||
<p><strong>模板ID:</strong> <code class="bg-gray-100 dark:bg-slate-800 px-1 py-0.5 rounded">{{ templateData?.id }}</code></p>
|
||
<p><strong>必填参数:</strong> token (加密token), title (消息标题), placeholders (占位符键值对)</p>
|
||
<p><strong>可选参数:</strong> 根据模板配置的@提醒字段自动应用</p>
|
||
<p class="text-amber-600 dark:text-amber-400"><strong>⚠️ 注意:</strong> V2接口使用加密token,不支持明文ID</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 代码示例 -->
|
||
<div class="space-y-4">
|
||
<h3 class="font-semibold">代码示例</h3>
|
||
|
||
<Tabs v-model="activeTab" class="w-full">
|
||
<TabsList class="grid w-full grid-cols-7 gap-1">
|
||
<TabsTrigger v-for="lang in codeLanguages" :key="lang.value" :value="lang.value"
|
||
class="flex items-center gap-1 px-2 py-1 text-xs">
|
||
<span>{{ lang.icon }}</span>
|
||
<span class="hidden sm:inline">{{ lang.label }}</span>
|
||
<span class="sm:hidden">{{ lang.label.slice(0, 3) }}</span>
|
||
</TabsTrigger>
|
||
</TabsList>
|
||
|
||
<TabsContent v-for="lang in codeLanguages" :key="lang.value" :value="lang.value" class="mt-4">
|
||
<div class="relative">
|
||
<Button size="sm" variant="outline" class="absolute top-2 right-2 z-10"
|
||
@click="copyToClipboard(generateApiCode(lang.value))">
|
||
复制代码
|
||
</Button>
|
||
<pre
|
||
class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-xs leading-relaxed max-w-full whitespace-pre-wrap break-words"><code class="text-xs font-mono">{{ generateApiCode(lang.value) }}</code></pre>
|
||
</div>
|
||
</TabsContent>
|
||
</Tabs>
|
||
</div>
|
||
|
||
<!-- 说明 -->
|
||
<div class="border-l-4 border-blue-500 bg-blue-50 dark:bg-blue-950 p-3 rounded text-sm space-y-1">
|
||
<p class="font-semibold text-blue-900 dark:text-blue-200">💡 使用说明</p>
|
||
<ul class="text-blue-800 dark:text-blue-300 space-y-1 ml-4 list-disc">
|
||
<li><strong>token 参数:</strong>需要使用加密后的 token,不能直接使用明文模板ID(安全考虑)</li>
|
||
<li><strong>placeholders 参数:</strong>用于替换模板中的占位符,格式为 <code class="bg-blue-100 dark:bg-blue-900 px-1 rounded">{"key": "value"}</code></li>
|
||
<li>如果模板配置了@提醒,会自动应用到发送的消息中</li>
|
||
<li>支持 Text、HTML、Markdown 三种格式,根据实例配置精确发送对应类型</li>
|
||
<li>系统会自动遍历所有启用的实例进行发送</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</DialogContent>
|
||
</Dialog>
|
||
</template>
|
||
|
||
<style scoped>
|
||
/* 代码块样式优化 */
|
||
pre {
|
||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||
}
|
||
|
||
code {
|
||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||
}
|
||
</style>
|