mirror of
https://github.com/ctwj/urldb.git
synced 2025-11-25 19:37:33 +08:00
update: ui
This commit is contained in:
@@ -1,27 +1,88 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="text-gray-700 dark:text-gray-300 text-sm">
|
<div class="text-gray-700 dark:text-gray-300 text-sm">
|
||||||
<p>你可以通过API批量添加资源:</p>
|
<p class="mb-4">你可以通过API批量添加资源到待处理列表:</p>
|
||||||
<pre class="bg-gray-100 dark:bg-gray-800 p-3 rounded text-xs overflow-x-auto mt-2">
|
|
||||||
POST /api/resources/batch
|
<div class="bg-gray-50 dark:bg-gray-800 p-4 rounded-lg mb-4">
|
||||||
|
<h4 class="font-semibold mb-2">单个资源添加:</h4>
|
||||||
|
<pre class="bg-white dark:bg-gray-900 p-3 rounded text-xs overflow-x-auto">
|
||||||
|
POST /api/ready-resources
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Body:
|
Authorization: Bearer YOUR_TOKEN
|
||||||
[
|
|
||||||
{ "title": "资源A", "url": "https://a.com", "file_type": "pan", ... },
|
{
|
||||||
{ "title": "资源B", "url": "https://b.com", ... }
|
"title": "资源标题",
|
||||||
]
|
"url": "https://pan.baidu.com/s/123456",
|
||||||
</pre>
|
"category": "电影",
|
||||||
<p>参数说明:<br/>
|
"tags": "动作,科幻,2024",
|
||||||
title: 标题<br/>
|
"img": "https://example.com/cover.jpg",
|
||||||
url: 资源链接<br/>
|
"source": "手动添加",
|
||||||
file_type: 类型(pan/link/other)<br/>
|
"extra": "{\"size\": \"2GB\", \"quality\": \"1080p\"}"
|
||||||
tags: 标签数组(可选)<br/>
|
}
|
||||||
description: 描述(可选)<br/>
|
</pre>
|
||||||
... 其他字段参考文档
|
</div>
|
||||||
</p>
|
|
||||||
|
<div class="bg-gray-50 dark:bg-gray-800 p-4 rounded-lg mb-4">
|
||||||
|
<h4 class="font-semibold mb-2">批量资源添加:</h4>
|
||||||
|
<pre class="bg-white dark:bg-gray-900 p-3 rounded text-xs overflow-x-auto">
|
||||||
|
POST /api/ready-resources/batch
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer YOUR_TOKEN
|
||||||
|
|
||||||
|
{
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"title": "资源A",
|
||||||
|
"url": "https://pan.baidu.com/s/123456",
|
||||||
|
"category": "电影",
|
||||||
|
"tags": "动作,科幻",
|
||||||
|
"img": "https://example.com/cover1.jpg",
|
||||||
|
"source": "API导入",
|
||||||
|
"extra": "{\"size\": \"2GB\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "资源B",
|
||||||
|
"url": "https://pan.baidu.com/s/789012",
|
||||||
|
"category": "电视剧",
|
||||||
|
"tags": "悬疑,犯罪",
|
||||||
|
"source": "API导入"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-gray-50 dark:bg-gray-800 p-4 rounded-lg mb-4">
|
||||||
|
<h4 class="font-semibold mb-2">从文本批量添加:</h4>
|
||||||
|
<pre class="bg-white dark:bg-gray-900 p-3 rounded text-xs overflow-x-auto">
|
||||||
|
POST /api/ready-resources/text
|
||||||
|
Content-Type: multipart/form-data
|
||||||
|
Authorization: Bearer YOUR_TOKEN
|
||||||
|
|
||||||
|
Form Data:
|
||||||
|
text: |
|
||||||
|
电影标题1
|
||||||
|
https://pan.baidu.com/s/123456
|
||||||
|
电影标题2
|
||||||
|
https://pan.baidu.com/s/789012
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-blue-50 dark:bg-blue-900/20 p-4 rounded-lg">
|
||||||
|
<h4 class="font-semibold mb-2 text-blue-800 dark:text-blue-200">字段说明:</h4>
|
||||||
|
<ul class="space-y-1 text-xs">
|
||||||
|
<li><strong>title</strong>: 资源标题(可选,留空则自动从URL提取)</li>
|
||||||
|
<li><strong>url</strong>: 资源链接(必填,支持百度网盘、阿里云盘等)</li>
|
||||||
|
<li><strong>category</strong>: 资源分类(可选,如:电影、电视剧、动漫等)</li>
|
||||||
|
<li><strong>tags</strong>: 资源标签(可选,多个标签用逗号分隔)</li>
|
||||||
|
<li><strong>img</strong>: 封面图片链接(可选)</li>
|
||||||
|
<li><strong>source</strong>: 数据来源(可选,如:手动添加、API导入、爬虫等)</li>
|
||||||
|
<li><strong>extra</strong>: 额外数据(可选,JSON格式字符串)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end space-x-3 pt-4">
|
<div class="flex justify-end space-x-3 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||||
<button type="button" @click="$emit('cancel')" class="btn-secondary">关闭</button>
|
<button type="button" @click="$emit('cancel')" class="btn-secondary">关闭</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,41 +1,119 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
|
<!-- 标题 -->
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">标题</label>
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
<input v-model="form.title" class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700" placeholder="输入标题" />
|
标题 <span class="text-gray-400 text-xs">(可选)</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
v-model="form.title"
|
||||||
|
class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700"
|
||||||
|
placeholder="输入资源标题,留空则自动从URL提取"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- URL -->
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">描述</label>
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
<textarea v-model="form.description" rows="3" class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700" placeholder="输入资源描述"></textarea>
|
URL <span class="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
v-model="form.url"
|
||||||
|
rows="3"
|
||||||
|
class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700"
|
||||||
|
placeholder="请输入资源链接,支持多行,每行一个链接"
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">
|
||||||
|
支持百度网盘、阿里云盘、夸克网盘等链接
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 分类 -->
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">类型</label>
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
<select v-model="form.file_type" class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700">
|
分类 <span class="text-gray-400 text-xs">(可选)</span>
|
||||||
<option value="">选择类型</option>
|
</label>
|
||||||
<option value="pan">网盘</option>
|
<input
|
||||||
<option value="link">直链</option>
|
v-model="form.category"
|
||||||
<option value="other">其他</option>
|
class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700"
|
||||||
</select>
|
placeholder="如:电影、电视剧、动漫、音乐等"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 标签 -->
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">标签</label>
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
|
标签 <span class="text-gray-400 text-xs">(可选)</span>
|
||||||
|
</label>
|
||||||
<div class="flex flex-wrap gap-2 mb-2">
|
<div class="flex flex-wrap gap-2 mb-2">
|
||||||
<span v-for="tag in form.tags" :key="tag" class="bg-blue-100 text-blue-700 px-2 py-1 rounded text-xs flex items-center">
|
<span
|
||||||
|
v-for="tag in form.tags"
|
||||||
|
:key="tag"
|
||||||
|
class="bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-300 px-2 py-1 rounded text-xs flex items-center"
|
||||||
|
>
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
<button type="button" class="ml-1 text-xs" @click="removeTag(tag)">×</button>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="ml-1 text-xs hover:text-red-500"
|
||||||
|
@click="removeTag(tag)"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model="newTag" @keyup.enter.prevent="addTag" class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700" placeholder="输入标签后回车添加" />
|
<input
|
||||||
|
v-model="newTag"
|
||||||
|
@keyup.enter.prevent="addTag"
|
||||||
|
class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700"
|
||||||
|
placeholder="输入标签后回车添加,多个标签用逗号分隔"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 封面图片 -->
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">链接(可多行,每行一个链接)</label>
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
<textarea v-model="form.url" rows="3" class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700" placeholder="https://a.com https://b.com"></textarea>
|
封面图片 <span class="text-gray-400 text-xs">(可选)</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
v-model="form.img"
|
||||||
|
class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700"
|
||||||
|
placeholder="封面图片链接"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据来源 -->
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
|
数据来源 <span class="text-gray-400 text-xs">(可选)</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
v-model="form.source"
|
||||||
|
class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700"
|
||||||
|
placeholder="如:手动添加、API导入、爬虫等"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 额外数据 -->
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
|
额外数据 <span class="text-gray-400 text-xs">(可选)</span>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
v-model="form.extra"
|
||||||
|
rows="3"
|
||||||
|
class="input-field dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700"
|
||||||
|
placeholder="JSON格式的额外数据,如:{'size': '2GB', 'quality': '1080p'}"
|
||||||
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end space-x-3 pt-4">
|
<!-- 按钮区域 -->
|
||||||
<button type="button" @click="$emit('cancel')" class="btn-secondary">取消</button>
|
<div class="flex justify-end space-x-3 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||||
|
<button type="button" @click="$emit('cancel')" class="btn-secondary">
|
||||||
|
取消
|
||||||
|
</button>
|
||||||
<button type="button" @click="handleSubmit" class="btn-primary" :disabled="loading">
|
<button type="button" @click="handleSubmit" class="btn-primary" :disabled="loading">
|
||||||
{{ loading ? '保存中...' : '添加' }}
|
{{ loading ? '保存中...' : '添加资源' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -43,25 +121,23 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useResourceStore } from '~/stores/resource'
|
import { useReadyResourceApi } from '~/composables/useApi'
|
||||||
|
|
||||||
const emit = defineEmits(['success', 'error', 'cancel'])
|
const emit = defineEmits(['success', 'error', 'cancel'])
|
||||||
|
|
||||||
const store = useResourceStore()
|
const readyResourceApi = useReadyResourceApi()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const newTag = ref('')
|
const newTag = ref('')
|
||||||
|
|
||||||
// 单个添加表单
|
// 根据 ready_resource 表字段定义表单
|
||||||
const form = ref({
|
const form = ref({
|
||||||
title: '',
|
title: '',
|
||||||
description: '',
|
url: '',
|
||||||
url: '', // 多行
|
category: '',
|
||||||
category_id: '',
|
|
||||||
tags: [] as string[],
|
tags: [] as string[],
|
||||||
file_path: '',
|
img: '',
|
||||||
file_type: '',
|
source: '',
|
||||||
file_size: 0,
|
extra: '',
|
||||||
is_public: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const addTag = () => {
|
const addTag = () => {
|
||||||
@@ -79,27 +155,63 @@ const removeTag = (tag: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证表单
|
||||||
|
const validateForm = () => {
|
||||||
|
if (!form.value.url.trim()) {
|
||||||
|
throw new Error('请输入至少一个URL')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证URL格式
|
||||||
|
const urls = form.value.url.split(/\r?\n/).map(l => l.trim()).filter(Boolean)
|
||||||
|
for (const url of urls) {
|
||||||
|
try {
|
||||||
|
new URL(url)
|
||||||
|
} catch {
|
||||||
|
throw new Error(`无效的URL格式: ${url}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空表单
|
||||||
|
const clearForm = () => {
|
||||||
|
form.value = {
|
||||||
|
title: '',
|
||||||
|
url: '',
|
||||||
|
category: '',
|
||||||
|
tags: [],
|
||||||
|
img: '',
|
||||||
|
source: '',
|
||||||
|
extra: '',
|
||||||
|
}
|
||||||
|
newTag.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
// 单个添加提交
|
// 单个添加提交
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
// 多行链接
|
validateForm()
|
||||||
|
|
||||||
|
// 多行链接处理
|
||||||
const urls = form.value.url.split(/\r?\n/).map(l => l.trim()).filter(Boolean)
|
const urls = form.value.url.split(/\r?\n/).map(l => l.trim()).filter(Boolean)
|
||||||
if (!urls.length) throw new Error('请输入至少一个链接')
|
|
||||||
|
// 为每个URL创建一个资源
|
||||||
for (const url of urls) {
|
for (const url of urls) {
|
||||||
await store.createResource({
|
const resourceData = {
|
||||||
...form.value,
|
title: form.value.title || undefined, // 如果为空则传undefined
|
||||||
url,
|
url: url,
|
||||||
tags: [...form.value.tags],
|
category: form.value.category || '',
|
||||||
})
|
tags: form.value.tags.join(','), // 转换为逗号分隔的字符串
|
||||||
|
img: form.value.img || '',
|
||||||
|
source: form.value.source || '手动添加',
|
||||||
|
extra: form.value.extra || '',
|
||||||
|
}
|
||||||
|
|
||||||
|
await readyResourceApi.createReadyResource(resourceData)
|
||||||
}
|
}
|
||||||
emit('success', '资源已进入待处理列表,处理完成后会自动入库')
|
|
||||||
// 清空表单
|
emit('success', `成功添加 ${urls.length} 个资源到待处理列表`)
|
||||||
form.value.title = ''
|
clearForm()
|
||||||
form.value.description = ''
|
|
||||||
form.value.url = ''
|
|
||||||
form.value.tags = []
|
|
||||||
form.value.file_type = ''
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
emit('error', e.message || '添加失败')
|
emit('error', e.message || '添加失败')
|
||||||
} finally {
|
} finally {
|
||||||
@@ -110,11 +222,11 @@ const handleSubmit = async () => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.input-field {
|
.input-field {
|
||||||
@apply w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500;
|
@apply w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
@apply px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md transition-colors disabled:opacity-50;
|
@apply px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md transition-colors disabled:opacity-50 disabled:cursor-not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary {
|
.btn-secondary {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// 统一响应解析函数
|
// 统一响应解析函数
|
||||||
export const parseApiResponse = <T>(response: any): T => {
|
export const parseApiResponse = <T>(response: any): T => {
|
||||||
|
console.log('parseApiResponse - 原始响应:', response)
|
||||||
|
|
||||||
// 检查是否是新的统一响应格式
|
// 检查是否是新的统一响应格式
|
||||||
if (response && typeof response === 'object' && 'code' in response && 'data' in response) {
|
if (response && typeof response === 'object' && 'code' in response && 'data' in response) {
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
@@ -12,6 +14,16 @@ export const parseApiResponse = <T>(response: any): T => {
|
|||||||
throw new Error(response.message || '请求失败')
|
throw new Error(response.message || '请求失败')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否是包含success字段的响应格式(如登录接口)
|
||||||
|
if (response && typeof response === 'object' && 'success' in response && 'data' in response) {
|
||||||
|
if (response.success) {
|
||||||
|
return response.data
|
||||||
|
} else {
|
||||||
|
throw new Error(response.message || '请求失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 兼容旧格式,直接返回响应
|
// 兼容旧格式,直接返回响应
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,69 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 自动处理配置状态 -->
|
||||||
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 mb-6">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center space-x-3">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<i class="fas fa-cog text-gray-600 dark:text-gray-400"></i>
|
||||||
|
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">自动处理配置:</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<div
|
||||||
|
:class="[
|
||||||
|
'w-3 h-3 rounded-full',
|
||||||
|
systemConfig?.auto_process_ready_resources
|
||||||
|
? 'bg-green-500 animate-pulse'
|
||||||
|
: 'bg-red-500'
|
||||||
|
]"
|
||||||
|
></div>
|
||||||
|
<span
|
||||||
|
:class="[
|
||||||
|
'text-sm font-medium',
|
||||||
|
systemConfig?.auto_process_ready_resources
|
||||||
|
? 'text-green-600 dark:text-green-400'
|
||||||
|
: 'text-red-600 dark:text-red-400'
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
{{ systemConfig?.auto_process_ready_resources ? '已开启' : '已关闭' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center space-x-3">
|
||||||
|
<div class="text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
<i class="fas fa-info-circle mr-1"></i>
|
||||||
|
{{ systemConfig?.auto_process_ready_resources
|
||||||
|
? '系统会自动处理待处理资源并入库'
|
||||||
|
: '需要手动处理待处理资源'
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
@click="refreshConfig"
|
||||||
|
:disabled="updatingConfig"
|
||||||
|
class="px-2 py-1 text-xs bg-gray-100 hover:bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600 rounded-md transition-colors"
|
||||||
|
title="刷新配置"
|
||||||
|
>
|
||||||
|
<i class="fas fa-sync-alt"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="toggleAutoProcess"
|
||||||
|
:disabled="updatingConfig"
|
||||||
|
:class="[
|
||||||
|
'px-3 py-1 text-xs rounded-md transition-colors flex items-center gap-1',
|
||||||
|
systemConfig?.auto_process_ready_resources
|
||||||
|
? 'bg-red-100 hover:bg-red-200 text-red-700 dark:bg-red-900/20 dark:text-red-400'
|
||||||
|
: 'bg-green-100 hover:bg-green-200 text-green-700 dark:bg-green-900/20 dark:text-green-400'
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<i v-if="updatingConfig" class="fas fa-spinner fa-spin"></i>
|
||||||
|
<i v-else :class="systemConfig?.auto_process_ready_resources ? 'fas fa-pause' : 'fas fa-play'"></i>
|
||||||
|
{{ systemConfig?.auto_process_ready_resources ? '关闭' : '开启' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 批量添加模态框 -->
|
<!-- 批量添加模态框 -->
|
||||||
<div v-if="showAddModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div v-if="showAddModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div class="bg-white dark:bg-gray-900 rounded-lg shadow-xl p-6 max-w-4xl w-full mx-4 max-h-[90vh] overflow-y-auto text-gray-900 dark:text-gray-100">
|
<div class="bg-white dark:bg-gray-900 rounded-lg shadow-xl p-6 max-w-4xl w-full mx-4 max-h-[90vh] overflow-y-auto text-gray-900 dark:text-gray-100">
|
||||||
@@ -81,16 +144,24 @@ https://pan.baidu.com/s/345678</pre>
|
|||||||
|
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex justify-between items-center mb-4">
|
||||||
<button
|
<div class="flex gap-2">
|
||||||
@click="showAddModal = true"
|
<NuxtLink
|
||||||
|
to="/add-resource"
|
||||||
class="w-full sm:w-auto px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md transition-colors text-center flex items-center justify-center gap-2"
|
class="w-full sm:w-auto px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md transition-colors text-center flex items-center justify-center gap-2"
|
||||||
>
|
>
|
||||||
<i class="fas fa-plus"></i> 批量添加
|
<i class="fas fa-plus"></i> 添加资源
|
||||||
|
</NuxtLink>
|
||||||
|
<button
|
||||||
|
@click="showAddModal = true"
|
||||||
|
class="w-full sm:w-auto px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded-md transition-colors text-center flex items-center justify-center gap-2"
|
||||||
|
>
|
||||||
|
<i class="fas fa-list"></i> 批量添加
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<button
|
<button
|
||||||
@click="refreshData"
|
@click="refreshData"
|
||||||
class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center gap-2"
|
class="px-4 py-2 bg-gray-600 text-white rounded-md hover:bg-gray-700 flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<i class="fas fa-refresh"></i> 刷新
|
<i class="fas fa-refresh"></i> 刷新
|
||||||
</button>
|
</button>
|
||||||
@@ -131,7 +202,21 @@ https://pan.baidu.com/s/345678</pre>
|
|||||||
<path d="M16 24h16M24 16v16" stroke-width="3" stroke-linecap="round" />
|
<path d="M16 24h16M24 16v16" stroke-width="3" stroke-linecap="round" />
|
||||||
</svg>
|
</svg>
|
||||||
<div class="text-lg font-semibold text-gray-400 dark:text-gray-500 mb-2">暂无待处理资源</div>
|
<div class="text-lg font-semibold text-gray-400 dark:text-gray-500 mb-2">暂无待处理资源</div>
|
||||||
<div class="text-sm text-gray-400 dark:text-gray-600">你可以点击上方"批量添加"按钮快速导入资源</div>
|
<div class="text-sm text-gray-400 dark:text-gray-600 mb-4">你可以点击上方"添加资源"按钮快速导入资源</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<NuxtLink
|
||||||
|
to="/add-resource"
|
||||||
|
class="px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-md transition-colors text-sm flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<i class="fas fa-plus"></i> 添加资源
|
||||||
|
</NuxtLink>
|
||||||
|
<button
|
||||||
|
@click="showAddModal = true"
|
||||||
|
class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md transition-colors text-sm flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<i class="fas fa-list"></i> 批量添加
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -263,6 +348,22 @@ const totalPages = ref(0)
|
|||||||
const { useReadyResourceApi } = await import('~/composables/useApi')
|
const { useReadyResourceApi } = await import('~/composables/useApi')
|
||||||
const readyResourceApi = useReadyResourceApi()
|
const readyResourceApi = useReadyResourceApi()
|
||||||
|
|
||||||
|
// 获取系统配置API
|
||||||
|
const { useSystemConfigApi } = await import('~/composables/useApi')
|
||||||
|
const systemConfigApi = useSystemConfigApi()
|
||||||
|
|
||||||
|
// 获取系统配置
|
||||||
|
const systemConfig = ref<any>(null)
|
||||||
|
const updatingConfig = ref(false) // 添加配置更新状态
|
||||||
|
const fetchSystemConfig = async () => {
|
||||||
|
try {
|
||||||
|
const response = await systemConfigApi.getSystemConfig()
|
||||||
|
systemConfig.value = response
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取系统配置失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取数据
|
// 获取数据
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -272,12 +373,27 @@ const fetchData = async () => {
|
|||||||
page_size: pageSize.value
|
page_size: pageSize.value
|
||||||
}) as any
|
}) as any
|
||||||
|
|
||||||
// 使用标准化的接口返回格式
|
// 适配后端API响应格式
|
||||||
readyResources.value = response.data
|
if (response && response.data) {
|
||||||
totalCount.value = response.pagination.total
|
readyResources.value = response.data
|
||||||
totalPages.value = response.pagination.total_pages
|
// 后端返回格式: {data: [...], page: 1, page_size: 100, total: 123}
|
||||||
|
totalCount.value = response.total || 0
|
||||||
|
totalPages.value = Math.ceil((response.total || 0) / pageSize.value)
|
||||||
|
} else if (Array.isArray(response)) {
|
||||||
|
// 如果直接返回数组
|
||||||
|
readyResources.value = response
|
||||||
|
totalCount.value = response.length
|
||||||
|
totalPages.value = 1
|
||||||
|
} else {
|
||||||
|
readyResources.value = []
|
||||||
|
totalCount.value = 0
|
||||||
|
totalPages.value = 1
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取待处理资源失败:', error)
|
console.error('获取待处理资源失败:', error)
|
||||||
|
readyResources.value = []
|
||||||
|
totalCount.value = 0
|
||||||
|
totalPages.value = 1
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
@@ -337,6 +453,11 @@ const refreshData = () => {
|
|||||||
fetchData()
|
fetchData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 刷新配置
|
||||||
|
const refreshConfig = () => {
|
||||||
|
fetchSystemConfig()
|
||||||
|
}
|
||||||
|
|
||||||
// 关闭模态框
|
// 关闭模态框
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
showAddModal.value = false
|
showAddModal.value = false
|
||||||
@@ -428,10 +549,55 @@ const checkUrlSafety = (url: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 切换自动处理配置
|
||||||
|
const toggleAutoProcess = async () => {
|
||||||
|
if (updatingConfig.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updatingConfig.value = true
|
||||||
|
try {
|
||||||
|
const newValue = !systemConfig.value?.auto_process_ready_resources
|
||||||
|
console.log('当前配置:', systemConfig.value)
|
||||||
|
console.log('新值:', newValue)
|
||||||
|
|
||||||
|
// 先获取当前配置,然后只更新需要的字段
|
||||||
|
const currentConfig = await systemConfigApi.getSystemConfig() as any
|
||||||
|
console.log('获取到的当前配置:', currentConfig)
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
site_title: currentConfig.site_title || '',
|
||||||
|
site_description: currentConfig.site_description || '',
|
||||||
|
keywords: currentConfig.keywords || '',
|
||||||
|
author: currentConfig.author || '',
|
||||||
|
copyright: currentConfig.copyright || '',
|
||||||
|
auto_process_ready_resources: newValue,
|
||||||
|
auto_process_interval: currentConfig.auto_process_interval || 30,
|
||||||
|
auto_transfer_enabled: currentConfig.auto_transfer_enabled || false,
|
||||||
|
auto_fetch_hot_drama_enabled: currentConfig.auto_fetch_hot_drama_enabled || false,
|
||||||
|
page_size: currentConfig.page_size || 100,
|
||||||
|
maintenance_mode: currentConfig.maintenance_mode || false
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('更新数据:', updateData)
|
||||||
|
const response = await systemConfigApi.updateSystemConfig(updateData)
|
||||||
|
console.log('更新响应:', response)
|
||||||
|
|
||||||
|
systemConfig.value = response
|
||||||
|
alert(`自动处理配置已${newValue ? '开启' : '关闭'}`)
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('切换自动处理配置失败:', error)
|
||||||
|
console.error('错误详情:', error.response || error)
|
||||||
|
alert('切换自动处理配置失败')
|
||||||
|
} finally {
|
||||||
|
updatingConfig.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 页面加载时获取数据
|
// 页面加载时获取数据
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
await fetchData()
|
await fetchData()
|
||||||
|
await fetchSystemConfig()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('页面初始化失败:', error)
|
console.error('页面初始化失败:', error)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -439,6 +605,11 @@ onMounted(async () => {
|
|||||||
pageLoading.value = false
|
pageLoading.value = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 设置页面标题
|
||||||
|
useHead({
|
||||||
|
title: '待处理资源管理 - 网盘资源管理系统'
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user