225 lines
8.5 KiB
HTML
225 lines
8.5 KiB
HTML
|
|
{% extends 'admin/model/create.html' %}
|
||
|
|
|
||
|
|
{% block tail %}
|
||
|
|
{{ super() }}
|
||
|
|
<style>
|
||
|
|
.auto-fetch-btn {
|
||
|
|
margin-top: 10px;
|
||
|
|
margin-bottom: 15px;
|
||
|
|
}
|
||
|
|
.fetch-status {
|
||
|
|
margin-top: 10px;
|
||
|
|
padding: 10px;
|
||
|
|
border-radius: 8px;
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
.fetch-status.success {
|
||
|
|
background-color: rgba(34, 197, 94, 0.1);
|
||
|
|
border: 1px solid rgba(34, 197, 94, 0.3);
|
||
|
|
color: #4ade80;
|
||
|
|
}
|
||
|
|
.fetch-status.error {
|
||
|
|
background-color: rgba(239, 68, 68, 0.1);
|
||
|
|
border: 1px solid rgba(239, 68, 68, 0.3);
|
||
|
|
color: #f87171;
|
||
|
|
}
|
||
|
|
.logo-preview {
|
||
|
|
margin-top: 10px;
|
||
|
|
max-width: 100px;
|
||
|
|
max-height: 100px;
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
.logo-preview img {
|
||
|
|
max-width: 100%;
|
||
|
|
max-height: 80px;
|
||
|
|
object-fit: contain;
|
||
|
|
border-radius: 8px;
|
||
|
|
border: 1px solid #ddd;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
{% endblock %}
|
||
|
|
|
||
|
|
{% block header %}
|
||
|
|
<h2>添加 Skill</h2>
|
||
|
|
{% endblock %}
|
||
|
|
|
||
|
|
{% block form %}
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="github_url">GitHub 仓库 URL <span style="color: #999; font-weight: normal;">(可选,填写后自动获取信息)</span></label>
|
||
|
|
<div style="display: flex; gap: 10px; align-items: flex-start;">
|
||
|
|
<input type="text" class="form-control" id="github_url" placeholder="例如: https://github.com/anthropics/claude-code" style="flex: 1;">
|
||
|
|
<button type="button" class="auto-fetch-btn btn btn-info" id="fetchSkillBtn">
|
||
|
|
<span class="material-symbols-outlined" style="vertical-align: middle;">auto_awesome</span>
|
||
|
|
自动识别
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
<div class="fetch-status" id="fetchStatus"></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="name">Skill 名称 <span style="color: #e74c3c;">*</span></label>
|
||
|
|
<input type="text" class="form-control" name="name" id="name" required placeholder="例如: PDF Helper">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="short_desc">简短描述</label>
|
||
|
|
<input type="text" class="form-control" name="short_desc" id="short_desc" placeholder="一句话描述这个 Skill 的用途">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="description">详细介绍</label>
|
||
|
|
<textarea class="form-control" name="description" id="description" rows="4" placeholder="详细介绍这个 Skill 的功能和使用场景"></textarea>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="logo">Logo 图片路径</label>
|
||
|
|
<input type="text" class="form-control" name="logo" id="logo" placeholder="/static/logos/xxx.png">
|
||
|
|
<div class="logo-preview" id="logoPreview">
|
||
|
|
<img id="logoImg" src="" alt="Logo预览">
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="github_url_field">GitHub 链接</label>
|
||
|
|
<input type="text" class="form-control" name="github_url" id="github_url_field" placeholder="https://github.com/...">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="source_type">来源类型</label>
|
||
|
|
<select class="form-control" name="source_type" id="source_type">
|
||
|
|
<option value="manual" selected>手动添加</option>
|
||
|
|
<option value="github">GitHub</option>
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="source_repo">来源仓库</label>
|
||
|
|
<input type="text" class="form-control" name="source_repo" id="source_repo" placeholder="owner/repo">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="usage">包含内容 / 应用场景</label>
|
||
|
|
<textarea class="form-control" name="usage" id="usage" rows="4" placeholder="这个 skills 仓库主要包含哪些内容、适合什么场景"></textarea>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="examples">来源链接 / 示例</label>
|
||
|
|
<textarea class="form-control" name="examples" id="examples" rows="4" placeholder="主要来源链接或示例链接"></textarea>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<div class="form-check">
|
||
|
|
<input type="checkbox" class="form-check-input" name="is_active" id="is_active" checked>
|
||
|
|
<label class="form-check-label" for="is_active">启用</label>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<div class="form-check">
|
||
|
|
<input type="checkbox" class="form-check-input" name="is_featured" id="is_featured">
|
||
|
|
<label class="form-check-label" for="is_featured">推荐</label>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="sort_order">排序权重</label>
|
||
|
|
<input type="number" class="form-control" name="sort_order" id="sort_order" value="0" placeholder="数字越大越靠前">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-group">
|
||
|
|
<button type="submit" class="btn btn-primary">保存</button>
|
||
|
|
<a href="{{ url_for('skills.index_view') }}" class="btn btn-secondary">取消</a>
|
||
|
|
</div>
|
||
|
|
{% endblock %}
|
||
|
|
|
||
|
|
{% block tail2 %}
|
||
|
|
<script>
|
||
|
|
document.addEventListener('DOMContentLoaded', function() {
|
||
|
|
const fetchBtn = document.getElementById('fetchSkillBtn');
|
||
|
|
const urlInput = document.getElementById('github_url');
|
||
|
|
const statusDiv = document.getElementById('fetchStatus');
|
||
|
|
const logoInput = document.getElementById('logo');
|
||
|
|
const logoPreview = document.getElementById('logoPreview');
|
||
|
|
const logoImg = document.getElementById('logoImg');
|
||
|
|
|
||
|
|
function showStatus(message, type) {
|
||
|
|
statusDiv.textContent = message;
|
||
|
|
statusDiv.className = 'fetch-status ' + type;
|
||
|
|
statusDiv.style.display = 'block';
|
||
|
|
}
|
||
|
|
|
||
|
|
if (logoInput) {
|
||
|
|
logoInput.addEventListener('input', function() {
|
||
|
|
if (this.value) {
|
||
|
|
logoImg.src = this.value;
|
||
|
|
logoPreview.style.display = 'block';
|
||
|
|
} else {
|
||
|
|
logoPreview.style.display = 'none';
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (fetchBtn && urlInput) {
|
||
|
|
fetchBtn.addEventListener('click', function() {
|
||
|
|
const url = urlInput.value.trim();
|
||
|
|
|
||
|
|
if (!url) {
|
||
|
|
showStatus('请先输入 GitHub 仓库 URL', 'error');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!url.includes('github.com')) {
|
||
|
|
showStatus('请输入有效的 GitHub 仓库 URL', 'error');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
fetchBtn.disabled = true;
|
||
|
|
statusDiv.style.display = 'none';
|
||
|
|
|
||
|
|
fetch('/api/fetch-skill-info', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json',
|
||
|
|
},
|
||
|
|
body: JSON.stringify({ url: url })
|
||
|
|
})
|
||
|
|
.then(response => response.json())
|
||
|
|
.then(data => {
|
||
|
|
if (!data.success) {
|
||
|
|
showStatus('✗ ' + (data.message || '获取失败,请手动填写'), 'error');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const nameField = document.querySelector('input[name="name"]');
|
||
|
|
const shortDescField = document.querySelector('input[name="short_desc"]');
|
||
|
|
const descriptionField = document.querySelector('textarea[name="description"]');
|
||
|
|
const githubUrlField = document.querySelector('input[name="github_url"]');
|
||
|
|
const sourceRepoField = document.querySelector('input[name="source_repo"]');
|
||
|
|
const sourceTypeField = document.querySelector('select[name="source_type"]');
|
||
|
|
const usageField = document.querySelector('textarea[name="usage"]');
|
||
|
|
const examplesField = document.querySelector('textarea[name="examples"]');
|
||
|
|
|
||
|
|
if (nameField && data.data.name) nameField.value = data.data.name;
|
||
|
|
if (shortDescField && data.data.short_desc) shortDescField.value = data.data.short_desc.substring(0, 100);
|
||
|
|
if (descriptionField && data.data.description) descriptionField.value = data.data.description;
|
||
|
|
if (githubUrlField && data.data.github_url) githubUrlField.value = data.data.github_url;
|
||
|
|
if (sourceRepoField && data.data.source_repo) sourceRepoField.value = data.data.source_repo;
|
||
|
|
if (sourceTypeField && data.data.source_type) sourceTypeField.value = data.data.source_type;
|
||
|
|
if (usageField && data.data.usage) usageField.value = data.data.usage;
|
||
|
|
if (examplesField && data.data.examples) examplesField.value = data.data.examples;
|
||
|
|
|
||
|
|
showStatus('✓ Skill 信息获取成功!已自动填充标题、简介、应用场景和来源链接', 'success');
|
||
|
|
})
|
||
|
|
.catch(error => {
|
||
|
|
console.error('Error:', error);
|
||
|
|
showStatus('✗ 网络请求失败,请手动填写', 'error');
|
||
|
|
})
|
||
|
|
.finally(() => {
|
||
|
|
fetchBtn.disabled = false;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
{% endblock %}
|