ai问片增加权限开关
This commit is contained in:
@@ -7676,6 +7676,9 @@ const AIConfigComponent = ({
|
||||
const [enableVideoCardEntry, setEnableVideoCardEntry] = useState(true);
|
||||
const [enablePlayPageEntry, setEnablePlayPageEntry] = useState(true);
|
||||
|
||||
// 权限控制
|
||||
const [allowRegularUsers, setAllowRegularUsers] = useState(true);
|
||||
|
||||
// 高级设置
|
||||
const [temperature, setTemperature] = useState(0.7);
|
||||
const [maxTokens, setMaxTokens] = useState(1000);
|
||||
@@ -7697,6 +7700,7 @@ const AIConfigComponent = ({
|
||||
setEnableHomepageEntry(config.AIConfig.EnableHomepageEntry !== false);
|
||||
setEnableVideoCardEntry(config.AIConfig.EnableVideoCardEntry !== false);
|
||||
setEnablePlayPageEntry(config.AIConfig.EnablePlayPageEntry !== false);
|
||||
setAllowRegularUsers(config.AIConfig.AllowRegularUsers !== false);
|
||||
setTemperature(config.AIConfig.Temperature ?? 0.7);
|
||||
setMaxTokens(config.AIConfig.MaxTokens ?? 1000);
|
||||
setSystemPrompt(config.AIConfig.SystemPrompt || '');
|
||||
@@ -7726,6 +7730,7 @@ const AIConfigComponent = ({
|
||||
EnableHomepageEntry: enableHomepageEntry,
|
||||
EnableVideoCardEntry: enableVideoCardEntry,
|
||||
EnablePlayPageEntry: enablePlayPageEntry,
|
||||
AllowRegularUsers: allowRegularUsers,
|
||||
Temperature: temperature,
|
||||
MaxTokens: maxTokens,
|
||||
SystemPrompt: systemPrompt,
|
||||
@@ -8014,6 +8019,33 @@ const AIConfigComponent = ({
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 权限控制 */}
|
||||
<div className='space-y-3 p-4 border border-gray-200 dark:border-gray-700 rounded-lg'>
|
||||
<h4 className='text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3'>
|
||||
权限控制
|
||||
</h4>
|
||||
|
||||
<div className='flex items-center justify-between py-2'>
|
||||
<div>
|
||||
<div className='text-sm font-medium text-gray-900 dark:text-gray-100'>
|
||||
允许普通用户使用
|
||||
</div>
|
||||
<div className='text-xs text-gray-500 dark:text-gray-400'>
|
||||
关闭后仅站长和管理员可使用AI问片功能
|
||||
</div>
|
||||
</div>
|
||||
<label className='relative inline-flex items-center cursor-pointer'>
|
||||
<input
|
||||
type='checkbox'
|
||||
checked={allowRegularUsers}
|
||||
onChange={(e) => setAllowRegularUsers(e.target.checked)}
|
||||
className='sr-only peer'
|
||||
/>
|
||||
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-yellow-300 dark:peer-focus:ring-yellow-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-green-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 高级设置 */}
|
||||
<details className='p-4 border border-gray-200 dark:border-gray-700 rounded-lg'>
|
||||
<summary className='text-sm font-semibold text-gray-900 dark:text-gray-100 cursor-pointer'>
|
||||
|
||||
@@ -57,6 +57,7 @@ export async function POST(request: NextRequest) {
|
||||
EnableHomepageEntry,
|
||||
EnableVideoCardEntry,
|
||||
EnablePlayPageEntry,
|
||||
AllowRegularUsers,
|
||||
Temperature,
|
||||
MaxTokens,
|
||||
SystemPrompt,
|
||||
@@ -89,6 +90,7 @@ export async function POST(request: NextRequest) {
|
||||
EnableHomepageEntry: boolean;
|
||||
EnableVideoCardEntry: boolean;
|
||||
EnablePlayPageEntry: boolean;
|
||||
AllowRegularUsers: boolean;
|
||||
Temperature?: number;
|
||||
MaxTokens?: number;
|
||||
SystemPrompt?: string;
|
||||
@@ -124,6 +126,7 @@ export async function POST(request: NextRequest) {
|
||||
typeof EnableHomepageEntry !== 'boolean' ||
|
||||
typeof EnableVideoCardEntry !== 'boolean' ||
|
||||
typeof EnablePlayPageEntry !== 'boolean' ||
|
||||
typeof AllowRegularUsers !== 'boolean' ||
|
||||
(Temperature !== undefined && typeof Temperature !== 'number') ||
|
||||
(MaxTokens !== undefined && typeof MaxTokens !== 'number') ||
|
||||
(SystemPrompt !== undefined && typeof SystemPrompt !== 'string')
|
||||
@@ -171,6 +174,7 @@ export async function POST(request: NextRequest) {
|
||||
EnableHomepageEntry,
|
||||
EnableVideoCardEntry,
|
||||
EnablePlayPageEntry,
|
||||
AllowRegularUsers,
|
||||
Temperature,
|
||||
MaxTokens,
|
||||
SystemPrompt,
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
VideoContext,
|
||||
} from '@/lib/ai-orchestrator';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { db } from '@/lib/db';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -72,9 +73,6 @@ async function streamClaudeChat(
|
||||
maxTokens: number;
|
||||
}
|
||||
): Promise<ReadableStream> {
|
||||
// Claude API格式: 移除system消息,单独传递
|
||||
const userMessages = messages.filter((m) => m.role !== 'system');
|
||||
|
||||
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -87,7 +85,7 @@ async function streamClaudeChat(
|
||||
max_tokens: config.maxTokens,
|
||||
temperature: config.temperature,
|
||||
system: systemPrompt,
|
||||
messages: userMessages,
|
||||
messages: messages,
|
||||
stream: true,
|
||||
}),
|
||||
});
|
||||
@@ -187,7 +185,23 @@ export async function POST(request: NextRequest) {
|
||||
);
|
||||
}
|
||||
|
||||
// 3. 解析请求参数
|
||||
// 3. 权限检查:如果不允许普通用户使用,检查用户角色
|
||||
if (!aiConfig.AllowRegularUsers) {
|
||||
const username = authInfo.username;
|
||||
// 站长始终有权限
|
||||
if (username !== process.env.USERNAME) {
|
||||
// 检查是否为管理员
|
||||
const userInfo = await db.getUserInfoV2(username);
|
||||
if (!userInfo || (userInfo.role !== 'admin' && userInfo.role !== 'owner') || userInfo.banned) {
|
||||
return NextResponse.json(
|
||||
{ error: '该功能仅限站长和管理员使用' },
|
||||
{ status: 403 }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 解析请求参数
|
||||
const body = (await request.json()) as ChatRequest;
|
||||
const { message, context, history = [] } = body;
|
||||
|
||||
@@ -214,11 +228,11 @@ export async function POST(request: NextRequest) {
|
||||
tavilyApiKey: aiConfig.TavilyApiKey,
|
||||
serperApiKey: aiConfig.SerperApiKey,
|
||||
serpApiKey: aiConfig.SerpApiKey,
|
||||
// 决策模型配置(固定使用自定义provider)
|
||||
// 决策模型配置(固定使用自定义provider,复用主模型的API配置)
|
||||
enableDecisionModel: aiConfig.EnableDecisionModel,
|
||||
decisionProvider: 'custom',
|
||||
decisionApiKey: aiConfig.DecisionCustomApiKey,
|
||||
decisionBaseURL: aiConfig.DecisionCustomBaseURL,
|
||||
decisionApiKey: aiConfig.CustomApiKey,
|
||||
decisionBaseURL: aiConfig.CustomBaseURL,
|
||||
decisionModel: aiConfig.DecisionCustomModel,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -114,7 +114,6 @@ export async function POST(request: NextRequest) {
|
||||
metaInfo.folders[key] = {
|
||||
folderName: folderName,
|
||||
tmdb_id: tmdbId || null,
|
||||
douban_id: doubanId || null,
|
||||
title: title,
|
||||
poster_path: posterPath,
|
||||
release_date: releaseDate || '',
|
||||
|
||||
@@ -130,7 +130,6 @@ export async function GET(request: NextRequest) {
|
||||
id: key,
|
||||
folder: info.folderName,
|
||||
tmdbId: info.tmdb_id,
|
||||
doubanId: info.douban_id,
|
||||
title: info.title,
|
||||
poster: getTMDBImageUrl(info.poster_path),
|
||||
releaseDate: info.release_date,
|
||||
|
||||
@@ -5641,8 +5641,6 @@ function PlayPageClient() {
|
||||
title: detail.title,
|
||||
year: detail.year,
|
||||
douban_id: videoDoubanId !== 0 ? videoDoubanId : undefined,
|
||||
tmdb_id: detail.tmdb_id,
|
||||
type: detail.type === 'movie' ? 'movie' : 'tv',
|
||||
currentEpisode: currentEpisodeIndex + 1,
|
||||
}}
|
||||
welcomeMessage={`想了解《${detail.title}》的更多信息吗?我可以帮你查询剧情、演员、评价等。`}
|
||||
|
||||
@@ -147,6 +147,8 @@ export interface AdminConfig {
|
||||
EnableHomepageEntry: boolean; // 首页入口开关
|
||||
EnableVideoCardEntry: boolean; // VideoCard入口开关
|
||||
EnablePlayPageEntry: boolean; // 播放页入口开关
|
||||
// 权限控制
|
||||
AllowRegularUsers: boolean; // 是否允许普通用户使用AI问片(关闭后仅站长和管理员可用)
|
||||
// 高级设置
|
||||
Temperature?: number; // AI温度参数(0-2),默认0.7
|
||||
MaxTokens?: number; // 最大回复token数,默认1000
|
||||
|
||||
Reference in New Issue
Block a user