根据钉钉文档《0.12.0 体验反馈》中提出的问题,本文件详细分析了每个问题的根本原因,并提供具体的解决方案和代码修改建议。
本文档共包含 6 个问题 (3 个 P1 + 3 个 P2),分为两个主要部分:
- P1 级别: 3 个问题
- P2 级别: 2 个细节问题 (共 10 个小点)
- P2 级别: 1 个命令报错问题
- 现状: 当前 MCP Management Dialog 中没有 OAuth 认证功能,用户必须使用
/mcp auth <server-name>命令进行认证 - 问题:
- Auth 功能独立于 Manage Dialog 之外,用户体验割裂
- 需要记住命令行才能认证,不够直观
- MCP 管理对话框中只能查看服务器状态和工具,无法进行认证操作
- 文档建议: Auth 应该整合到 manage dialog 中,在 UI 界面内完成所有 MCP 管理操作
// packages/cli/src/ui/commands/mcpCommand.ts
const mcpCommand: SlashCommand = {
name: 'mcp',
subCommands: [manageCommand, authCommand], // auth 作为独立子命令存在
action: async (): Promise<OpenDialogActionReturn> => ({
type: 'dialog',
dialog: 'mcp', // 默认打开管理对话框
}),
};// packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx
// 当前的步骤类型
export const MCP_MANAGEMENT_STEPS = {
SERVER_LIST: 'server-list',
SERVER_DETAIL: 'server-detail',
DISABLE_SCOPE_SELECT: 'disable-scope-select',
TOOL_LIST: 'tool-list',
TOOL_DETAIL: 'tool-detail',
} as const;
// ServerDetailStep 中的操作选项
const actions = [
{ label: 'View tools', value: 'view-tools' },
{ label: 'Reconnect', value: 'reconnect' },
{ label: 'Enable/Disable', value: 'toggle-disable' },
// ❌ 缺少 'Authenticate' 选项
];- UI 层面: MCP Management Dialog 中没有认证相关的 UI 组件和操作入口
- 代码层面: OAuth 认证逻辑只在命令行 handler 中实现 (
mcpCommand.ts的authCommand) - 体验层面: 用户需要在 TUI 和 CLI 之间切换,无法在一个界面内完成所有操作
核心思路:
- 在 Server Detail 页面添加 "Authenticate" 操作选项
- 复用现有的
MCPOAuthProvider和 OAuth 流程 - 通过事件系统显示认证过程中的提示信息
实现步骤:
// packages/cli/src/ui/components/mcp/types.ts
export const MCP_MANAGEMENT_STEPS = {
SERVER_LIST: 'server-list',
SERVER_DETAIL: 'server-detail',
DISABLE_SCOPE_SELECT: 'disable-scope-select',
TOOL_LIST: 'tool-list',
TOOL_DETAIL: 'tool-detail',
AUTHENTICATE: 'authenticate', // 新增:认证步骤
} as const;// packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx
type ServerAction =
| 'view-tools'
| 'reconnect'
| 'toggle-disable'
| 'authenticate'; // 新增
const actions = useMemo(() => {
const result: Array<{ label: string; value: ServerAction }> = [];
result.push({ label: t('View Tools'), value: 'view-tools' });
if (!server.isDisabled && server.status === MCPServerStatus.DISCONNECTED) {
result.push({ label: t('Reconnect'), value: 'reconnect' });
}
// 新增:显示认证选项的场景
const needsAuth =
server.config.oauth?.enabled ||
server.status === MCPServerStatus.DISCONNECTED ||
server.errorMessage?.includes('401') ||
server.errorMessage?.includes('OAuth');
if (needsAuth) {
result.push({
label: t('Authenticate'),
value: 'authenticate',
icon: '🔐', // 可选:添加图标增强视觉提示
});
}
result.push({
label: server.isDisabled ? t('Enable') : t('Disable'),
value: 'toggle-disable',
});
return result;
}, [server]);// packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx
import { MCPOAuthProvider, MCPOAuthConfig } from '@qwen-code/qwen-code-core';
import { appEvents, AppEvent } from '../../utils/events.js';
// 新增:处理认证
const handleAuthenticate = useCallback(async () => {
if (!config || !selectedServer) return;
try {
setIsLoading(true);
// 显示开始认证提示
context.ui.addItem(
{
type: 'info',
text: t("Starting OAuth authentication for '{{name}}'...", {
name: selectedServer.name,
}),
},
Date.now()
);
// 监听并显示认证过程中的消息
const displayListener = (message: string) => {
context.ui.addItem({ type: 'info', text: message }, Date.now());
};
appEvents.on(AppEvent.OauthDisplayMessage, displayListener);
// 准备 OAuth 配置
let oauthConfig: MCPOAuthConfig = selectedServer.config.oauth || { enabled: false };
// 执行认证
const authProvider = new MCPOAuthProvider(new MCPOAuthTokenStorage());
await authProvider.authenticate(
selectedServer.name,
oauthConfig,
selectedServer.config.httpUrl || selectedServer.config.url
);
// 认证成功
context.ui.addItem(
{
type: 'success',
text: t("✓ Authentication successful for '{{name}}'", {
name: selectedServer.name,
}),
},
Date.now()
);
// 移除消息监听器
appEvents.off(AppEvent.OauthDisplayMessage, displayListener);
// 重新加载服务器数据以更新状态
await reloadServers();
// 返回上一级
handleNavigateBack();
} catch (error) {
debugLogger.error(
`Authentication failed for '${selectedServer.name}':`,
error
);
context.ui.addItem(
{
type: 'error',
text: t("✗ Authentication failed: {{error}}", {
error: getErrorMessage(error),
}),
},
Date.now()
);
} finally {
setIsLoading(false);
}
}, [config, selectedServer, reloadServers, handleNavigateBack, context]);
// 在 renderStepContent 中添加认证步骤的处理
case MCP_MANAGEMENT_STEPS.AUTHENTICATE:
// 可以直接执行认证,或者显示一个确认对话框
void handleAuthenticate();
return <Text>{t('Authenticating...')}</Text>;// packages/cli/src/i18n/locales/en.js
{
'Authenticate': 'Authenticate',
'Authenticate with OAuth': 'Authenticate with OAuth',
"Starting OAuth authentication for '{{name}}'...": "Starting OAuth authentication for '{{name}}'...",
"✓ Authentication successful for '{{name}}'": "✓ Authentication successful for '{{name}}'",
"✗ Authentication failed: {{error}}": "✗ Authentication failed: {{error}}",
}优点:
- ✅ 用户体验统一,所有 MCP 管理操作在一个界面完成
- ✅ 复用现有 OAuth 认证逻辑,开发成本低
- ✅ 直观的视觉反馈,认证过程透明
- ✅ 符合现代 UI/UX 设计原则
缺点:
⚠️ 需要处理浏览器跳转和回调 (已有完善实现,风险低)
如果某些场景下确实需要命令行认证 (如自动化脚本),可以:
- 保留
/mcp auth命令 - 在 Dialog 中提供快速复制的命令模板
- 添加"Copy Auth Command"按钮
但这会增加复杂性,不如方案 A 简洁。
- 现象: MCP Server 被禁用后,仍然可以在 UI 中看到"查看工具"选项,点击进入后显示空列表
- 期望: 禁用后的服务器不应该显示"查看工具"选项,或者应该给出明确的提示信息
当前代码逻辑:
// packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx
const actions = useMemo(() => {
const result: Array<{ label: string; value: ServerAction }> = [];
// 无论服务器是否禁用,都添加"查看工具"选项
result.push({ label: t('View Tools'), value: 'view-tools' });
if (server.status === 'disconnected') {
result.push({ label: t('Reconnect'), value: 'reconnect' });
}
result.push({
label: server.isDisabled ? t('Enable') : t('Disable'),
value: 'toggle-disable',
});
return result;
}, [server]);问题在于:
- 没有根据
server.isDisabled状态过滤操作选项 - 禁用服务器的工具列表获取逻辑可能存在问题
- 缺少用户友好的提示信息
方案 A: 禁用时隐藏"查看工具"选项 (推荐)
代码修改:
// packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx
const actions = useMemo(() => {
const result: Array<{ label: string; value: ServerAction }> = [];
// 只在服务器启用且已连接时显示"查看工具"选项
if (!server.isDisabled && server.status === MCPServerStatus.CONNECTED) {
result.push({
label: t('View Tools'),
value: 'view-tools',
disabled: server.toolCount === 0, // 可选:工具数量为 0 时禁用
});
}
// 禁用状态下显示提示信息
if (server.isDisabled) {
result.push({
label: t('Enable to view tools'),
value: 'toggle-disable',
});
} else {
if (server.status === MCPServerStatus.DISCONNECTED) {
result.push({ label: t('Reconnect'), value: 'reconnect' });
}
result.push({
label: t('Disable'),
value: 'toggle-disable',
});
}
return result;
}, [server]);同时修改 ToolListStep:
// packages/cli/src/ui/components/mcp/steps/ToolListStep.tsx
export const ToolListStep: React.FC<ToolListStepProps> = ({
tools,
serverName,
onSelect,
onBack,
}) => {
// 添加禁用状态检查
if (tools.length === 0) {
return (
<Box flexDirection="column">
<Text color={theme.text.secondary}>
{t('No tools available for this server.')}
</Text>
{/* 添加提示:服务器可能被禁用 */}
<Text color={theme.text.warning}>
{t('Note: This server may be disabled. Please enable it in the server settings.')}
</Text>
</Box>
);
}
// ... 其余代码保持不变
};方案 B: 显示友好提示并阻止导航
在 MCPManagementDialog 中添加拦截逻辑:
// packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx
const handleViewTools = useCallback(() => {
if (!selectedServer) return;
// 检查服务器是否禁用
if (selectedServer.isDisabled) {
// 显示提示信息,不执行导航
debugLogger.warn(
`Cannot view tools for disabled server '${selectedServer.name}'`,
);
// 可选:在 UI 上显示临时消息
return;
}
// 检查是否有工具
if (selectedServer.toolCount === 0) {
debugLogger.info(`No tools available for server '${selectedServer.name}'`);
// 仍然可以进入查看,但会显示空状态提示
}
handleNavigateToStep(MCP_MANAGEMENT_STEPS.TOOL_LIST);
}, [selectedServer, handleNavigateToStep]);- 现象: MCP Server 被禁用后,仍然可以看到"重新连接"选项
- 期望: 禁用之后应该没有"重新连接"入口
- 文档建议: 禁用之后应该没有"重新连接"入口
当前代码逻辑:
// packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx
if (server.status === 'disconnected') {
result.push({ label: t('Reconnect'), value: 'reconnect' });
}问题在于:
- 只检查了连接状态,没有检查禁用状态
- 禁用的服务器不应该允许重新连接操作
- 逻辑上矛盾:既然禁用了就不应该尝试连接
代码修改:
// packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx
const actions = useMemo(() => {
const result: Array<{ label: string; value: ServerAction }> = [];
// View Tools 选项
if (!server.isDisabled && server.toolCount > 0) {
result.push({ label: t('View Tools'), value: 'view-tools' });
}
// Reconnect 选项:只在未禁用且断开连接时显示
if (!server.isDisabled && server.status === MCPServerStatus.DISCONNECTED) {
result.push({ label: t('Reconnect'), value: 'reconnect' });
}
// Enable/Disable 选项
result.push({
label: server.isDisabled ? t('Enable Server') : t('Disable Server'),
value: 'toggle-disable',
});
return result;
}, [server]);同时在 ServerListStep 中添加视觉提示:
// packages/cli/src/ui/components/mcp/steps/ServerListStep.tsx
{server.isDisabled && (
<Text color={theme.status.warning}>
{' '}
{t('(disabled - no connection possible)')}
</Text>
)}- 现象: 禁用服务器时会弹出一个对话框让用户选择禁用范围 (user/workspace)
- 问题: 这个选择让用户体验困惑,特别是当 MCP server 在项目级配置时,在用户级别禁用就有点费解
- 文档建议: MCP server 在哪里,就在哪里禁用(如果 MCP server 在项目级,在用户级别禁用就有点费解)
当前实现逻辑:
// packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx
const handleSelectDisableScope = useCallback(
async (scope: 'user' | 'workspace') => {
// 允许用户在 user 或 workspace 层面禁用服务器
// 即使服务器配置在 workspace 层面,也允许在 user 层面禁用
},
[config, selectedServer, handleNavigateBack, reloadServers],
);问题在于:
- 用户可以跨 scope 禁用服务器,造成配置混乱
- 不符合"在哪里配置就在哪里管理"的直觉
- 增加了不必要的复杂性
方案 A: 根据服务器来源自动确定禁用 scope (强烈推荐)
核心思路:
- User 级别的配置 → 只能在 User 级别禁用
- Workspace 级别的配置 → 只能在 Workspace 级别禁用
- Extension 级别的配置 → 不允许禁用 (只能卸载扩展)
代码修改:
// packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx
// 修改 handleDisable 函数
const handleDisable = useCallback(() => {
if (!selectedServer) return;
// 如果服务器已经被禁用,直接启用
if (selectedServer.isDisabled) {
void handleEnableServer();
return;
}
// Extension 提供的服务器不允许禁用
if (selectedServer.source === 'extension') {
debugLogger.warn(
`Cannot disable extension-provided server '${selectedServer.name}'`,
);
// 显示提示信息
return;
}
// 根据服务器 scope 直接禁用,不再询问
const scope =
selectedServer.scope === 'extension'
? SettingScope.User
: selectedServer.scope === 'workspace'
? SettingScope.Workspace
: SettingScope.User;
// 直接执行禁用操作
void executeDisable(scope);
}, [selectedServer, handleEnableServer]);
// 新增执行禁用函数
const executeDisable = useCallback(
async (scope: SettingScope) => {
if (!config || !selectedServer) return;
try {
setIsLoading(true);
const settings = loadSettings();
const scopeSettings = settings.forScope(scope).settings;
const currentExcluded = scopeSettings.mcp?.excluded || [];
if (!currentExcluded.includes(selectedServer.name)) {
const newExcluded = [...currentExcluded, selectedServer.name];
settings.setValue(scope, 'mcp.excluded', newExcluded);
}
const toolRegistry = config.getToolRegistry();
if (toolRegistry) {
await toolRegistry.disableMcpServer(selectedServer.name);
}
await reloadServers();
handleNavigateBack();
} catch (error) {
debugLogger.error(
`Error disabling server '${selectedServer.name}':`,
error,
);
} finally {
setIsLoading(false);
}
},
[config, selectedServer, reloadServers, handleNavigateBack],
);
// 移除 DisableScopeSelectStep 相关的代码和导航逻辑同时修改 UI 提示:
// packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx
<Box>
<Box width={LABEL_WIDTH}>
<Text color={theme.text.primary}>{t('Scope:')}</Text>
</Box>
<Box>
<Text>
{t(server.scope)}
{server.source === 'extension' && (
<Text color={theme.text.secondary}>
{' '}({t('provided by {{name}}', { name: server.config.extensionName })})
</Text>
)}
</Text>
</Box>
</Box>
// 禁用按钮文本根据 scope 调整
{server.isDisabled ? (
<Text>{t('Enable (will remove from exclusion list)')}</Text>
) : server.source === 'extension' ? (
<Text color={theme.text.secondary}>{t('Cannot disable extension server')}</Text>
) : (
<Text>{t('Disable (in {{scope}})', { scope: server.scope })}</Text>
)}方案 B: 保留选择但改进 UX
如果确实需要支持跨 scope 禁用 (考虑到某些特殊场景),至少应该:
- 明确显示当前服务器的配置位置
- 说明不同选择的影响
- 给出推荐选项
但这会增加复杂性,不如方案 A 简洁明了。
- 现象: 使用
/extension manage命令时直接报错 - 期望: 应该能正常打开 Extension Management Dialog
-
命令拼写错误 (最可能)
- 正确的命令是
/extensions manage(复数形式) - 用户可能输入了
/extension manage(单数形式)
- 正确的命令是
-
ExtensionManager 未正确初始化
// packages/cli/src/ui/commands/extensionsCommand.ts#L103-108 async function listAction(_context: CommandContext, _args: string) { const extensionManager = context.services.config?.getExtensionManager(); if (!(extensionManager instanceof ExtensionManager)) { debugLogger.error( `Cannot ${context.invocation?.name} extensions in this environment`, ); return; // ❌ 这里直接返回,没有给用户任何提示 } // ... }
-
环境限制
- 某些环境下无法加载 ExtensionManager
- 沙箱模式可能限制扩展管理功能
- 如果
getExtensionManager()返回 null 或不是 ExtensionManager 实例 - 代码只是记录 debug 日志并静默返回
- 用户看不到任何错误提示,只会感到困惑
代码修改:
// packages/cli/src/ui/commands/extensionsCommand.ts
async function listAction(context: CommandContext, _args: string) {
const extensionManager = context.services.config?.getExtensionManager();
if (!(extensionManager instanceof ExtensionManager)) {
debugLogger.error(
`Cannot ${context.invocation?.name} extensions in this environment`,
);
// ✅ 添加用户友好的错误提示
context.ui.addItem(
{
type: MessageType.ERROR,
text: t(
'Extension management is not available in the current environment. ' +
'This feature may not be supported in your current mode or configuration.',
),
},
Date.now(),
);
return;
}
return {
type: 'dialog' as const,
dialog: 'extensions_manage' as const,
};
}在命令解析层面添加提示:
// packages/cli/src/ui/commands/registry.ts 或相关位置
// 当检测到用户输入 '/extension'(单数) 时,给出提示
if (commandName === 'extension') {
context.ui.addItem(
{
type: MessageType.INFO,
text: t('Did you mean "/extensions"? (plural form)'),
},
Date.now(),
);
}为了用户体验,可以同时支持两种形式:
// packages/cli/src/ui/commands/extensionsCommand.ts
export const extensionsCommand: SlashCommand = {
name: 'extensions', // 主要命令 (复数)
aliases: ['extension'], // ✅ 添加别名 (单数)
get description() {
return t('Manage extensions');
},
kind: CommandKind.BUILT_IN,
subCommands: [
manageExtensionsCommand,
installCommand,
exploreExtensionsCommand,
],
action: async (context, args) =>
manageExtensionsCommand.action!(context, args),
};注意: 需要检查 SlashCommand 类型定义是否支持 aliases 属性
采用方案 A + 方案 C:
- 改进错误提示,让用户知道发生了什么
- 如果可能,同时支持单复数形式
-
修复问题 2.1: 禁用后可查看工具
- 修改
ServerDetailStep.tsx的操作列表逻辑 - 修改
ToolListStep.tsx添加友好提示 - 预计工时:2 小时
- 修改
-
修复问题 2.2: 禁用后可重新连接
- 修改
ServerDetailStep.tsx的 reconnect 选项条件 - 预计工时:1 小时
- 修改
- 修复问题 1: MCP Dialog 集成 OAuth 认证
- 扩展
MCP_MANAGEMENT_STEPS添加认证步骤 - 在
ServerDetailStep中添加"Authenticate"选项 - 在
MCPManagementDialog中实现认证逻辑 - 更新 i18n 翻译文件
- 预计工时:4 小时
- 扩展
- 修复问题 3: 简化禁用流程
- 移除
DisableScopeSelectStep - 实现自动 scope 判断逻辑
- 更新 UI 提示
- 预计工时:4 小时
- 移除
-
修复问题 4: Dialog 1 细节优化
- 移除重复的来源显示
- 优化错误信息显示逻辑 (只在有错误时显示)
- 移除多余的空格
- 优化布局紧凑度
- 预计工时:3 小时
-
修复问题 5: Dialog 2 细节优化
- 统一来源颜色与其他部分一致
- 添加功能说明 tooltip
- 统一选中色为 theme.text.accent
- 优化工具标注文案 (如"destructive, open-world")
- 移除不必要的序号
- 预计工时:3 小时
- 修复问题 6: Extension 命令报错
- 改进错误提示 (方案 A)
- 考虑支持单复数形式 (方案 C)
- 预计工时:2 小时
- 回归测试
- 更新所有相关测试用例
- 手动测试各个场景
- 确保没有破坏性变更
- 预计工时:4 小时
总预计工时: 约 23 小时 (约 3 个工作日)
- Breaking Changes: 无
- Deprecation: 无
- 新功能: MCP Dialog 集成 OAuth 认证功能
docs/developers/tools/mcp-server.md- 更新 MCP 管理对话框使用说明docs/users/features/mcp-servers.md- 更新用户指南docs/users/features/extensions.md- 更新扩展管理说明- 内联帮助文本和 i18n 文件
packages/cli/src/ui/commands/mcpCommand.test.tspackages/cli/src/ui/components/mcp/MCPManagementDialog.test.tsxpackages/cli/src/ui/components/mcp/steps/ServerDetailStep.test.tsxpackages/cli/src/ui/commands/extensionsCommand.test.tspackages/cli/src/ui/components/extensions/ExtensionsManagerDialog.test.tsx
- MCP Management Dialog 中显示"Authenticate"选项 (针对需要认证的服务器)
- 点击认证后能正确启动 OAuth 流程
- 认证过程中显示友好的提示信息
- 认证成功后自动刷新服务器状态
- 认证失败时显示明确的错误信息
- 保留
/mcp auth命令作为备选方案 (可选)
- 禁用的服务器不显示"查看工具"选项,或显示友好提示
- 工具列表为空时,明确提示原因
- 用户不会看到空的工具列表页面
- 禁用的服务器不显示"重新连接"选项
- UI 逻辑自洽,不会出现矛盾的操作选项
- 禁用状态下只能看到"启用"选项
- 禁用操作一键完成,无需选择 scope
- 禁用范围自动匹配配置范围
- UI 明确显示服务器的配置位置
- 用户体验流畅,无困惑点
- 移除重复的来源显示
- 只在有错误时显示"运行 qwen --debug..."提示
- 没有错误时不显示多余的空格
- 布局更加紧凑,接近 claude code 的视觉效果
- 来源颜色与其他部分统一
- 添加清晰的功能说明
- 统一选中色为 theme.text.accent
- 工具标注文案更易懂 (如改为"Destructive, Open-world")
- 移除列表项前的序号 (1、2、3...)
-
/extensions manage命令能正常工作 - 如果 ExtensionManager 不可用,显示明确的错误提示
- 考虑支持
/extension(单数) 作为别名 (可选) - 测试不同环境下的行为 (普通模式、沙箱模式等)
# MCP Management
packages/cli/src/ui/commands/mcpCommand.ts
packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx
packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx
packages/cli/src/ui/components/mcp/steps/ServerListStep.tsx
packages/cli/src/ui/components/mcp/steps/ToolListStep.tsx
packages/cli/src/ui/components/mcp/types.ts
packages/core/src/tools/mcp-client-manager.ts
packages/core/src/config/config.ts
# Extension Management
packages/cli/src/ui/commands/extensionsCommand.ts
packages/cli/src/ui/components/extensions/ExtensionsManagerDialog.tsx
packages/cli/src/ui/components/extensions/types.ts
packages/core/src/extension/extensionManager.ts
- MCP Management Dialog 依赖于 Config、ToolRegistry、PromptRegistry
- 禁用逻辑涉及 Settings 的多 scope 管理
- 状态跟踪通过
getMCPServerStatus和状态监听器实现
- OAuth 认证流程: 确保在 Dialog 中集成的认证功能不影响现有命令行认证
- 多 Scope 配置: 确保自动 scope 判断不会误删其他 scope 的配置
- Extension 集成: 确保扩展提供的服务器正确处理
- 环境兼容性: 确保 Extension Management 在不同环境下都能给出正确的错误提示
本文档针对 0.12.0 版本体验反馈中提出的 6 个问题 (3 个 P1 + 3 个 P2) 进行了详细分析,并提供了具体的解决方案。所有修改都遵循以下原则:
- 用户体验优先: 简化操作流程,减少困惑
- 逻辑一致性: 确保 UI 状态和行为逻辑自洽
- 向后兼容: 避免破坏性变更
- 代码质量: 简化代码结构,提高可维护性
- 错误友好: 提供清晰、有帮助的错误信息
建议按优先级分阶段实施,确保每个问题都得到妥善解决。