feat: initial commit for HookPilot
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import type { HookDetail, HookForm } from '../../api/types';
|
||||
import { toast } from '../../composables/toast';
|
||||
import { copyText, formatTime, webhookUrl } from '../../utils/format';
|
||||
|
||||
const props = defineProps<{ form: HookForm; hook: HookDetail | null; groups: string[] }>();
|
||||
const emit = defineEmits<{ regenerateToken: [] }>();
|
||||
|
||||
const url = computed(() => webhookUrl(props.form.slug));
|
||||
const slugChanged = computed(() => props.hook !== null && props.hook.slug !== props.form.slug);
|
||||
const hasBodyParams = computed(() => props.form.params.some((p) => p.source === 'json' || p.source === 'form'));
|
||||
|
||||
async function copyUrl() {
|
||||
if (await copyText(url.value)) toast.success('调用地址已复制');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="form-grid">
|
||||
<div class="field">
|
||||
<label class="required">接口名称</label>
|
||||
<input v-model="form.name" maxlength="100" placeholder="如:更新家庭 IP" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>分组</label>
|
||||
<input v-model="form.group" list="hook-groups" maxlength="50" placeholder="可选,用于在列表中归类" />
|
||||
<datalist id="hook-groups">
|
||||
<option v-for="g in groups" :key="g" :value="g" />
|
||||
</datalist>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="required">接口标识</label>
|
||||
<input v-model="form.slug" maxlength="64" placeholder="如:home-ip" class="mono" />
|
||||
<div class="hint">小写字母、数字、下划线和连字符,以字母或数字开头。</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="required">请求方式</label>
|
||||
<select v-model="form.method">
|
||||
<option value="POST">POST</option>
|
||||
<option value="GET">GET</option>
|
||||
</select>
|
||||
<div v-if="form.method === 'GET' && hasBodyParams" class="hint" style="color: var(--danger)">
|
||||
GET 接口只能从 Query 或 Header 提取参数,请调整参数配置。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field full">
|
||||
<label>调用地址</label>
|
||||
<div class="row">
|
||||
<div class="input-group" style="flex: 1">
|
||||
<span class="addon">{{ form.method }}</span>
|
||||
<input :value="url" readonly class="mono" />
|
||||
</div>
|
||||
<button class="btn" :disabled="!form.slug" @click="copyUrl">复制</button>
|
||||
</div>
|
||||
<div v-if="slugChanged" class="hint" style="color: var(--warning)">
|
||||
修改标识后原地址 /hooks/{{ hook!.slug }} 将失效,调用方需同步更新。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field full">
|
||||
<label>描述</label>
|
||||
<textarea v-model="form.description" rows="3" maxlength="1000" placeholder="接口用途、调用方等说明" />
|
||||
</div>
|
||||
|
||||
<div class="field full">
|
||||
<label>接口 Token</label>
|
||||
<template v-if="hook">
|
||||
<div class="row">
|
||||
<input :value="`hp_••••••••••••••••••••••••${hook.tokenHint}`" readonly class="mono" style="max-width: 360px" />
|
||||
<button class="btn btn-danger-outline" @click="emit('regenerateToken')">重新生成</button>
|
||||
</div>
|
||||
<div class="hint">
|
||||
Token 仅在创建或重新生成时完整显示一次。调用时通过 <code>Authorization: Bearer <token></code> 或
|
||||
<code>X-Hook-Token</code> 请求头传递。
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="hint">创建接口后自动生成,届时只显示一次,请妥善保存。</div>
|
||||
</div>
|
||||
|
||||
<div v-if="hook" class="field full">
|
||||
<div class="small faint">创建于 {{ formatTime(hook.createdAt) }} · 最后修改 {{ formatTime(hook.updatedAt) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user