diff --git a/app/api/evaluation_points/rule-groups.ts b/app/api/evaluation_points/rule-groups.ts index 86e30e8..768b1e8 100644 --- a/app/api/evaluation_points/rule-groups.ts +++ b/app/api/evaluation_points/rule-groups.ts @@ -45,6 +45,39 @@ interface ApiResponse { data: T; } +/** 文档类型信息(用于删除换绑) */ +export interface DocTypeInfo { + id: number; + name: string; +} + +/** 删除分组响应 */ +export interface DeleteGroupResponse { + success: boolean; + message?: string; + deleted_count?: number; + deleted_groups?: number; + deleted_points?: number; + /** 是否需要换绑(仅删除一级分组时) */ + need_rebind?: boolean; + /** 关联的评查点数量 */ + points_count?: number; + /** 只绑定当前分组的文档类型(换绑时替换) */ + single_bound_doc_types?: DocTypeInfo[]; + /** 绑定多个分组的文档类型(换绑时移除) */ + multi_bound_doc_types?: DocTypeInfo[]; + error?: string; + status?: number; +} + +/** 换绑响应 */ +export interface RebindResponse { + success: boolean; + message: string; + rebind_count: number; + doc_types_updated: number; +} + /** @@ -520,13 +553,18 @@ export async function updateEvaluationPointGroup( export async function deleteEvaluationPointGroup( id: string, token?: string -): Promise<{success: boolean; message?: string; deleted_groups?: number; deleted_points?: number; error?: never} | {success: false; error: string; status?: number}> { +): Promise { try { const response = await apiRequest<{ success: boolean; message: string; - deleted_groups: number; - deleted_points: number; + deleted_count?: number; + deleted_groups?: number; + deleted_points?: number; + need_rebind?: boolean; + points_count?: number; + single_bound_doc_types?: DocTypeInfo[]; + multi_bound_doc_types?: DocTypeInfo[]; }>( `/api/v3/evaluation-point-groups/${id}`, { @@ -543,8 +581,13 @@ export async function deleteEvaluationPointGroup( return { success: response.data.success, message: response.data.message, - deleted_groups: response.data.deleted_groups, - deleted_points: response.data.deleted_points + deleted_count: response.data.deleted_count || 0, + deleted_groups: response.data.deleted_groups || 0, + deleted_points: response.data.deleted_points || 0, + need_rebind: response.data.need_rebind || false, + points_count: response.data.points_count || 0, + single_bound_doc_types: response.data.single_bound_doc_types || [], + multi_bound_doc_types: response.data.multi_bound_doc_types || [] }; } @@ -559,6 +602,55 @@ export async function deleteEvaluationPointGroup( } } +/** + * 7.1 换绑一级分组(FastAPI v3) + * @param oldGroupId 要删除的一级分组ID + * @param newParentId 新的一级分组ID + * @param token JWT token + * @returns 换绑结果 + */ +export async function rebindEvaluationPointGroup( + oldGroupId: string, + newParentId: string, + token?: string +): Promise<{success: boolean; message?: string; rebind_count?: number; doc_types_updated?: number; error?: never} | {success: false; error: string; status?: number}> { + try { + const response = await apiRequest( + `/api/v3/evaluation-point-groups/${oldGroupId}/rebind`, + { + method: 'PUT', + body: JSON.stringify({ new_parent_id: Number(newParentId) }), + headers: { + 'Content-Type': 'application/json', + ...(token ? { 'Authorization': `Bearer ${token}` } : {}) + } + } + ); + + if (response.error) { + return { success: false, error: response.error, status: response.status }; + } + + if (response.data) { + return { + success: response.data.success, + message: response.data.message, + rebind_count: response.data.rebind_count, + doc_types_updated: response.data.doc_types_updated + }; + } + + return { success: false, error: '换绑失败:返回数据格式不正确', status: 500 }; + } catch (error) { + console.error('❌ 换绑分组出错:', error); + return { + success: false, + error: error instanceof Error ? error.message : '换绑分组失败', + status: 500 + }; + } +} + /** * 8. 批量更新分组启用状态(FastAPI v3) * @param ids 分组ID列表 diff --git a/app/api/evaluation_points/rules.ts b/app/api/evaluation_points/rules.ts index 6aa2c9e..aa1f9b0 100644 --- a/app/api/evaluation_points/rules.ts +++ b/app/api/evaluation_points/rules.ts @@ -314,7 +314,7 @@ export async function getRulesList(params: RulesQueryParams): Promise<{data: Rul area: point.area || '' }; }); - console.log('✅ [getRulesList] 成功映射评查点列表数据', response.data.data[0]); + // console.log('✅ [getRulesList] 成功映射评查点列表数据', response.data.data[0]); return { data: { @@ -486,6 +486,8 @@ export async function deleteRule(id: string, token?: string): Promise<{data: {su */ export interface RuleType { id: string; + pid?: string; + code?: string; name: string; description?: string; isEnabled: boolean; @@ -703,6 +705,7 @@ export async function getRuleGroupsByType(typeId: string, token?: string): Promi if(response.data && 'code' in response.data && response.data.data){ if(Array.isArray(response.data.data) && response.data.data.length > 0){ // 将API返回的数据映射到前端模型 + // console.log("评查点类型列表",response.data); const ruleGroups = response.data.data.map(item => ({ id: item.id.toString(), name: item.name, diff --git a/app/components/cross-checking/DocumentListModal.tsx b/app/components/cross-checking/DocumentListModal.tsx index 521430e..bd7005e 100644 --- a/app/components/cross-checking/DocumentListModal.tsx +++ b/app/components/cross-checking/DocumentListModal.tsx @@ -1,5 +1,4 @@ import { useState, useRef, useCallback, useEffect } from "react"; -import { Link } from "@remix-run/react"; import { Modal } from '../ui/Modal'; import { FileTag } from '../ui/FileTag'; import { FileTypeTag } from '../ui/FileTypeTag'; @@ -368,18 +367,20 @@ export function DocumentListModal({
- {/* 查看按钮 */} - historyDoc.status === 'Processed' && handleViewClickDebounced(historyDoc.id.toString())} + disabled={historyDoc.status !== 'Processed'} > - 查看 - + {isNavigating ? '跳转中...' : '查看'} + {/* 追加附件按钮 - 仅当 type_name 包含"合同"时显示 */} {historyDoc.status === 'Processed' && taskId && parentDoc.type_name?.includes('合同') && ( +
+ + {/* 主体内容 */} +
+ {/* 提示信息 */} +
+
+ +
+

+ 一级分组「{groupName}」下有 {pointsCount} 个评查点 +

+

+ 请选择新的一级分组进行换绑后,才能删除该分组。 +

+
+
+
+ + {/* 两栏布局 */} +
+ {/* 左侧:需要更换绑定的文档类型 */} +
+

+ + 需要更换绑定的文档类型 +

+ {singleBoundDocTypes.length > 0 ? ( + <> +

+ 以下文档类型只绑定了当前分组,换绑后将绑定到新选择的分组: +

+
+ {singleBoundDocTypes.map(docType => ( + + + {docType.name} + + ))} +
+ + ) : ( +

无需要更换绑定的文档类型

+ )} +
+ + {/* 右侧:选择新的一级分组 */} +
+

+ + 选择新的一级分组 +

+

+ 请选择一个一级分组作为换绑目标(单选): +

+ {availableGroups.length > 0 ? ( +
+ {availableGroups.map(group => ( + + ))} +
+ ) : ( +

暂无可选的一级分组

+ )} +
+
+ + {/* 下方:会移除绑定的文档类型 */} + {multiBoundDocTypes.length > 0 && ( +
+

+ + 会移除当前分组绑定的文档类型 +

+

+ 以下文档类型绑定了多个一级分组,换绑后将移除当前分组的绑定关系: +

+
+ {multiBoundDocTypes.map(docType => ( + + + {docType.name} + + ))} +
+
+ )} +
+ + {/* 底部按钮 */} +
+ + +
+ + + ); +} + +export default RebindModal; diff --git a/app/components/rules/new/BasicInfo.tsx b/app/components/rules/new/BasicInfo.tsx index 9ae05c8..b1d1893 100644 --- a/app/components/rules/new/BasicInfo.tsx +++ b/app/components/rules/new/BasicInfo.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import type { EvaluationPoint } from '~/models/evaluation_points'; import type { EvaluationPointGroup } from '~/models/evaluation_point_groups'; -import { getRulesList } from '~/api/evaluation_points/rules'; +import { getRulesList, getRuleTypes, type RuleType } from '~/api/evaluation_points/rules'; interface BasicInfoProps { onChange?: (data: Record) => void; @@ -77,8 +77,15 @@ export function BasicInfo({ const getCheckpointTypeCode = () => { if (!formData.evaluation_point_groups_pid) return ""; + // 优先从 API 返回的 filteredRuleTypes 中查找 + const fromApi = filteredRuleTypes.find( + ruleType => Number(ruleType.id) === formData.evaluation_point_groups_pid + ); + if (fromApi?.code) return fromApi.code; + + // 兜底:从 evaluationPointGroups 中查找 const typeGroup = evaluationPointGroups.find( - group => group.id === formData.evaluation_point_groups_pid && (!group.pid || group.pid === 0) // 🆕 NULL或0都表示顶级分组 + group => group.id === formData.evaluation_point_groups_pid && (!group.pid || group.pid === 0) ); return typeGroup?.code || ""; @@ -86,10 +93,53 @@ export function BasicInfo({ // 评查点描述与法律依据 展开状态 const [isDescExpanded, setIsDescExpanded] = useState(false); - + // 条款号临时输入字符串(不会触发自动分割) const [lawArticlesText, setLawArticlesText] = useState(''); + // 从 API 获取的评查点类型列表(根据 documentTypeIds 过滤) + const [filteredRuleTypes, setFilteredRuleTypes] = useState([]); + const [ruleTypesLoading, setRuleTypesLoading] = useState(false); + + // 从 Session Storage 获取 documentTypeIds 并调用 API 获取评查点类型 + useEffect(() => { + const fetchRuleTypes = async () => { + try { + const storedIds = sessionStorage.getItem('documentTypeIds'); + if (!storedIds) { + setFilteredRuleTypes([]); + return; + } + + const parsedIds = JSON.parse(storedIds); + if (!Array.isArray(parsedIds) || parsedIds.length === 0) { + setFilteredRuleTypes([]); + return; + } + + const documentTypeIds = parsedIds.map(id => Number(id)); + setRuleTypesLoading(true); + + // 调用 getRuleTypes API 获取过滤后的评查点类型 + const response = await getRuleTypes(documentTypeIds, frontendJWT); + + if (response.data) { + setFilteredRuleTypes(response.data); + } else { + console.error('获取评查点类型失败:', response.error); + setFilteredRuleTypes([]); + } + } catch (error) { + console.error('获取评查点类型失败:', error); + setFilteredRuleTypes([]); + } finally { + setRuleTypesLoading(false); + } + }; + + fetchRuleTypes(); + }, [frontendJWT]); + // 根据选择的评查点类型筛选可用的规则组 const filteredRuleGroups = evaluationPointGroups.filter(group => formData.evaluation_point_groups_pid && @@ -97,8 +147,31 @@ export function BasicInfo({ group.is_enabled ); - // 🆕 获取评查点类型选项(pid为NULL或0的数据) + // 🆕 获取评查点类型选项(使用 API 返回的过滤后数据) const getCheckpointTypeOptions = () => { + if (ruleTypesLoading) { + return ( + <> + + + ); + } + + // 如果 API 返回了数据,使用 API 数据 + if (filteredRuleTypes.length > 0) { + return ( + <> + + {filteredRuleTypes.map(ruleType => ( + + ))} + + ); + } + + // 兜底:如果 API 没有返回数据,使用 evaluationPointGroups 中的一级分组 if (!evaluationPointGroups || evaluationPointGroups.length === 0) { return ( <> @@ -107,7 +180,9 @@ export function BasicInfo({ ); } - const typeGroups = evaluationPointGroups.filter(group => (!group.pid || group.pid === 0) && group.is_enabled); + const typeGroups = evaluationPointGroups.filter(group => + (!group.pid || group.pid === 0) && group.is_enabled + ); return ( <> @@ -177,10 +252,16 @@ export function BasicInfo({ case 'checkpoint-type': // 处理评查点类型选择 if (value) { - // 🆕 找到选中的类型组(pid为NULL或0表示顶级分组) - const selectedType = evaluationPointGroups.find(group => group.code === value && (!group.pid || group.pid === 0)); - if (selectedType) { - newData.evaluation_point_groups_pid = selectedType.id; + // 优先从 API 返回的 filteredRuleTypes 中查找 + const selectedFromApi = filteredRuleTypes.find(ruleType => ruleType.code === value); + if (selectedFromApi) { + newData.evaluation_point_groups_pid = Number(selectedFromApi.id); + } else { + // 兜底:从 evaluationPointGroups 中查找(pid为NULL或0表示顶级分组) + const selectedType = evaluationPointGroups.find(group => group.code === value && (!group.pid || group.pid === 0)); + if (selectedType) { + newData.evaluation_point_groups_pid = selectedType.id; + } } } else { newData.evaluation_point_groups_pid = null; diff --git a/app/config/api-config.ts b/app/config/api-config.ts index e558bcd..abf38af 100644 --- a/app/config/api-config.ts +++ b/app/config/api-config.ts @@ -147,7 +147,7 @@ const configs: Record = { documentUrl: 'http://172.16.0.55:8073/docauditai/', uploadUrl: 'http://172.16.0.55:8073/api/v2/documents', - collaboraUrl: 'http://172.16.0.81:9980', + collaboraUrl: 'http://172.16.0.58:9980', appUrl: 'http://172.16.0.34:5173', oauth: { diff --git a/app/routes/api.pdf-proxy.tsx b/app/routes/api.pdf-proxy.tsx index f26f6ab..dea54ed 100644 --- a/app/routes/api.pdf-proxy.tsx +++ b/app/routes/api.pdf-proxy.tsx @@ -28,6 +28,7 @@ export async function loader({ request }: LoaderFunctionArgs) { // 构建完整的文件 URL const fileUrl = `${DOCUMENT_URL}${filePath}`; + // console.log('fileUrl:', fileUrl) // 使用 JWT 认证获取文件 const response = await fetch(fileUrl, { diff --git a/app/routes/document-types._index.tsx b/app/routes/document-types._index.tsx index 2676c26..e9b0c11 100644 --- a/app/routes/document-types._index.tsx +++ b/app/routes/document-types._index.tsx @@ -173,7 +173,7 @@ export default function DocumentTypesList() { // 处理测试loader返回的信息 useEffect(() => { - console.log('返回的父级评查点分组数据',parentGroups) + // console.log('返回的父级评查点分组数据',parentGroups) }, [parentGroups]) // 处理loader加载数据的时候的错误 diff --git a/app/routes/documents.list.tsx b/app/routes/documents.list.tsx index 10fc265..5f5d7b1 100644 --- a/app/routes/documents.list.tsx +++ b/app/routes/documents.list.tsx @@ -575,42 +575,24 @@ export default function DocumentsIndex() { }; // 下载文档 - const handleDownload = async (path: string) => { - try { - // 使用 PDF 代理路由获取文件,自动添加 JWT 认证 - const downloadUrl = `/api/pdf-proxy?path=${encodeURIComponent(path)}`; + const handleDownload = (path: string) => { + // 使用 PDF 代理路由获取文件,自动添加 JWT 认证 + const downloadUrl = `/api/pdf-proxy?path=${encodeURIComponent(path)}`; - // 使用fetch获取文件内容 - const response = await fetch(downloadUrl); - if (!response.ok) { - throw new Error(`下载失败: ${response.status} ${response.statusText}`); - } + // 直接使用链接下载,避免 fetch + blob 在生产环境下对 PDF 的兼容问题 + const a = document.createElement('a'); + a.style.display = 'none'; + a.href = downloadUrl; + // 从路径中获取文件名 + const fileName = path.split('/').pop() || 'document'; + a.download = decodeURIComponent(fileName); + document.body.appendChild(a); + a.click(); - // 将响应转换为Blob - const blob = await response.blob(); - - // 创建Blob URL - const blobUrl = URL.createObjectURL(blob); - - // 创建一个隐藏的a标签并点击它 - const a = document.createElement('a'); - a.style.display = 'none'; - a.href = blobUrl; - // 从路径中获取文件名 - const fileName = path.split('/').pop() || 'document'; - a.download = decodeURIComponent(fileName); - document.body.appendChild(a); - a.click(); - - // 清理 - setTimeout(() => { - document.body.removeChild(a); - URL.revokeObjectURL(blobUrl); - }, 100); - } catch (error) { - console.error('下载文件失败:', error); - toastService.error(`下载文件失败: ${error instanceof Error ? error.message : '未知错误'}`); - } + // 清理 + setTimeout(() => { + document.body.removeChild(a); + }, 100); }; // 删除文档 diff --git a/app/routes/rule-groups._index.tsx b/app/routes/rule-groups._index.tsx index b127976..daf27cf 100644 --- a/app/routes/rule-groups._index.tsx +++ b/app/routes/rule-groups._index.tsx @@ -12,10 +12,13 @@ import { getEvaluationPointGroups, getChildGroups, type RuleGroup, + type DocTypeInfo, deleteEvaluationPointGroup, + rebindEvaluationPointGroup, batchUpdateEvaluationPointGroupStatus, batchDeleteEvaluationPointGroups } from "~/api/evaluation_points/rule-groups"; +import { RebindModal } from "~/components/rule-groups/RebindModal"; import { toastService, messageService } from "~/components/ui"; import { usePermission } from "~/hooks/usePermission"; @@ -90,6 +93,17 @@ export default function RuleGroupsIndex() { const [initialLoading, setInitialLoading] = useState(true); const [selectedIds, setSelectedIds] = useState([]); // 🆕 批量选择状态 + // 换绑弹窗状态 + const [rebindModalVisible, setRebindModalVisible] = useState(false); + const [rebindModalData, setRebindModalData] = useState<{ + groupId: string; + groupName: string; + pointsCount: number; + singleBoundDocTypes: DocTypeInfo[]; + multiBoundDocTypes: DocTypeInfo[]; + } | null>(null); + const [rebindLoading, setRebindLoading] = useState(false); + // ✅ 使用权限 Hook const { canCreate, canUpdate, canDelete, canBatch } = usePermission(); const canCreateGroup = canCreate('evaluation_group'); @@ -252,13 +266,29 @@ export default function RuleGroupsIndex() { return; } + // 检查是否是一级分组 + const parentGroup = groups.find(g => g.id === groupId); + const isFirstLevel = !!parentGroup; + + // 如果是一级分组,检查是否还有二级分组 + if (isFirstLevel && parentGroup.children && parentGroup.children.length > 0) { + messageService.show({ + title: "无法删除", + message: "尚未完全删除该一级分组下的所有二级分组,不可进行删除操作,请检查。", + type: "error", + confirmText: "知道了" + }); + return; + } + + // 一级分组无子分组 或 二级分组,显示确认删除提示 messageService.show({ title: "确认删除", - message: "确定要删除该分组吗?此操作将同时删除该分组下的所有评查点,且不可恢复。", + message: "确定要删除该分组吗?此操作将同时解除该分组下的已绑定的所有评查点。", type: "warning", confirmText: "删除", cancelText: "取消", - confirmDelay: 4, + confirmDelay: 2, onConfirm: async () => { try { const result = await deleteEvaluationPointGroup(groupId, frontendJWT); @@ -285,9 +315,19 @@ export default function RuleGroupsIndex() { // 显示成功消息 toastService.success('删除成功') + } else if (result.need_rebind) { + // 需要换绑,打开换绑弹窗 + setRebindModalData({ + groupId: groupId, + groupName: parentGroup?.name || '未知分组', + pointsCount: result.points_count || 0, + singleBoundDocTypes: result.single_bound_doc_types || [], + multiBoundDocTypes: result.multi_bound_doc_types || [] + }); + setRebindModalVisible(true); } else { - toastService.error(`删除失败: ${result.error}`); - console.error(`删除失败: ${result.error}`); + // 其他失败情况(如有二级分组) + toastService.error(result.message || result.error || '删除失败'); } } catch (error) { console.error('删除分组失败:', error); @@ -297,6 +337,49 @@ export default function RuleGroupsIndex() { }); }; + // 处理换绑确认 + const handleRebindConfirm = async (newGroupId: string) => { + if (!rebindModalData) return; + + setRebindLoading(true); + try { + // 1. 执行换绑 + const rebindResult = await rebindEvaluationPointGroup( + rebindModalData.groupId, + newGroupId, + frontendJWT + ); + + if (!rebindResult.success) { + toastService.error(rebindResult.error || '换绑失败'); + return; + } + + toastService.success(rebindResult.message || '换绑成功'); + + // 2. 换绑成功后,再次调用删除 + const deleteResult = await deleteEvaluationPointGroup(rebindModalData.groupId, frontendJWT); + + if (deleteResult.success) { + toastService.success(deleteResult.message || '删除成功'); + + // 关闭弹窗 + setRebindModalVisible(false); + setRebindModalData(null); + + // 刷新页面 + window.location.reload(); + } else { + toastService.error(deleteResult.message || deleteResult.error || '删除失败'); + } + } catch (error) { + console.error('换绑并删除失败:', error); + toastService.error('操作失败,请稍后重试'); + } finally { + setRebindLoading(false); + } + }; + // 🆕 批量启用/禁用 const handleBatchEnable = async (enable: boolean) => { // ✅ 检查更新权限 @@ -317,7 +400,8 @@ export default function RuleGroupsIndex() { // 刷新页面以重新加载数据 window.location.reload(); } else { - toastService.error(`批量操作失败:${result.failed_ids.length} 个分组操作失败`); + // toastService.error(`批量操作失败:${result.failed_ids.length} 个分组操作失败`); + toastService.error(`批量操作失败`); } } catch (error) { console.error('批量操作失败:', error); @@ -338,9 +422,23 @@ export default function RuleGroupsIndex() { return; } + // 检查选中的分组中是否存在一级分组 - 完全禁止批量删除一级分组 + const selectedFirstLevelGroups = groups.filter(g => selectedIds.includes(g.id)); + + if (selectedFirstLevelGroups.length > 0) { + messageService.show({ + title: "无法批量删除", + message: "批量删除不支持删除一级分组,请单独删除一级分组或仅选择二级分组进行批量删除。", + type: "error", + confirmText: "知道了" + }); + return; + } + + // 只允许批量删除二级分组 messageService.show({ title: "确认批量删除", - message: `确定要删除选中的 ${selectedIds.length} 个分组吗?此操作不可恢复。`, + message: `确定要删除选中的 ${selectedIds.length} 个二级分组吗?此操作将同时解除这些分组下的已绑定的所有评查点。`, type: "warning", confirmText: "删除", cancelText: "取消", @@ -872,6 +970,23 @@ export default function RuleGroupsIndex() { )} + + {/* 换绑弹窗 */} + { + setRebindModalVisible(false); + setRebindModalData(null); + }} + onConfirm={handleRebindConfirm} + /> ); } \ No newline at end of file diff --git a/app/routes/rules.list.tsx b/app/routes/rules.list.tsx index 9f8e254..8b612ae 100644 --- a/app/routes/rules.list.tsx +++ b/app/routes/rules.list.tsx @@ -293,7 +293,7 @@ export default function RulesIndex() { if (typeResponse.data) { loadedRuleTypes = typeResponse.data; setRuleTypes(loadedRuleTypes); - console.log("📋 [fetchData] 获取到评查点类型:", loadedRuleTypes); + // console.log("📋 [fetchData] 获取到评查点类型:", loadedRuleTypes); } } catch (error) { console.error('加载评查点类型失败:', error); @@ -308,7 +308,7 @@ export default function RulesIndex() { } else if (loadedRuleTypes && loadedRuleTypes.length > 0) { // 选择"全部"或未选择,使用刚加载的评查点类型的 id finalRuleType = loadedRuleTypes.map(type => type.id).join(','); - console.log("📋 [fetchData] 选择全部类型,使用 loadedRuleTypes 的 id 组合:", finalRuleType); + // console.log("📋 [fetchData] 选择全部类型,使用 loadedRuleTypes 的 id 组合:", finalRuleType); } const queryParams = { diff --git a/app/styles/components/message-modal.css b/app/styles/components/message-modal.css index 6de38df..1c5c49a 100644 --- a/app/styles/components/message-modal.css +++ b/app/styles/components/message-modal.css @@ -15,7 +15,7 @@ display: flex; align-items: center; justify-content: center; - z-index: 1000; + z-index: 99999; /* 比 Modal (9999) 更高,确保提示框显示在最顶层 */ opacity: 0; animation: fadeIn 0.3s ease forwards; } diff --git a/nginx/conf.d/app.conf b/nginx/conf.d/app.conf index a61da9c..c94fdac 100644 --- a/nginx/conf.d/app.conf +++ b/nginx/conf.d/app.conf @@ -1,32 +1,32 @@ # 基于 state 参数端口分发的 OAuth2 回调配置 -# 1. 端口白名单映射(只允许指定端口) -map $arg_state $target_port { - default ""; - ~^login(51703)_ 51703; - ~^login(51704)_ 51704; - ~^login(51705)_ 51705; - ~^login(51706)_ 51706; - ~^login(51707)_ 51707; - ~^login(51708)_ 51708; -} +# # 1. 端口白名单映射(只允许指定端口) +# map $arg_state $target_port { +# default ""; +# ~^login(51703)_ 51703; +# ~^login(51704)_ 51704; +# ~^login(51705)_ 51705; +# ~^login(51706)_ 51706; +# ~^login(51707)_ 51707; +# ~^login(51708)_ 51708; +# } -# 2. 统一回调入口,根据 state 分发到对应端口 -server { - listen 80; - server_name 10.79.97.17; +# # 2. 统一回调入口,根据 state 分发到对应端口 +# server { +# listen 80; +# server_name 10.79.97.17; - location /callback { - # 未匹配到允许端口直接返回 400 - if ($target_port = "") { - return 400 "Invalid or unsupported state/port"; - } +# location /callback { +# # 未匹配到允许端口直接返回 400 +# if ($target_port = "") { +# return 400 "Invalid or unsupported state/port"; +# } - # 反向代理到本地对应端口的 /callback - proxy_pass http://10.79.97.17:$target_port/callback$is_args$args; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } -} \ No newline at end of file +# # 反向代理到本地对应端口的 /callback +# proxy_pass http://10.79.97.17:$target_port/callback$is_args$args; +# proxy_set_header Host $host; +# proxy_set_header X-Real-IP $remote_addr; +# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +# proxy_set_header X-Forwarded-Proto $scheme; +# } +# } \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf index d5675fc..1c0c7d2 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -1,28 +1,28 @@ -user nginx; -worker_processes auto; -error_log /var/log/nginx/error.log notice; -pid /var/run/nginx.pid; +# user nginx; +# worker_processes auto; +# error_log /var/log/nginx/error.log notice; +# pid /var/run/nginx.pid; -events { - worker_connections 1024; -} +# events { +# worker_connections 1024; +# } -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; +# http { +# include /etc/nginx/mime.types; +# default_type application/octet-stream; - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; +# log_format main '$remote_addr - $remote_user [$time_local] "$request" ' +# '$status $body_bytes_sent "$http_referer" ' +# '"$http_user_agent" "$http_x_forwarded_for"'; - access_log /var/log/nginx/access.log main; +# access_log /var/log/nginx/access.log main; - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; +# sendfile on; +# tcp_nopush on; +# tcp_nodelay on; +# keepalive_timeout 65; +# types_hash_max_size 2048; - # 包含conf.d目录中的配置文件 - include /etc/nginx/conf.d/*.conf; -} \ No newline at end of file +# # 包含conf.d目录中的配置文件 +# include /etc/nginx/conf.d/*.conf; +# } \ No newline at end of file