diff --git a/src/assets/QRCode/wx.png b/src/assets/QRCode/wx.png
new file mode 100644
index 0000000..d642075
Binary files /dev/null and b/src/assets/QRCode/wx.png differ
diff --git a/src/constants/toolIcons.ts b/src/constants/toolIcons.ts
index dc24f97..f685412 100644
--- a/src/constants/toolIcons.ts
+++ b/src/constants/toolIcons.ts
@@ -184,4 +184,9 @@ export const userAvatarIconSvg = ``;
+export const updateStageIconSvg = ``;
+
+/**
+ * 更多的图标svg
+ */
+export const moreIconSvg = ``;
diff --git a/src/panels/ICHelperPanel.ts b/src/panels/ICHelperPanel.ts
index 03285f8..a0731c3 100644
--- a/src/panels/ICHelperPanel.ts
+++ b/src/panels/ICHelperPanel.ts
@@ -131,13 +131,19 @@ export async function showICHelperPanel(
vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "Max.png")
);
+ // 获取二维码图片URI
+ const qrCodeUri = panel.webview.asWebviewUri(
+ vscode.Uri.joinPath(context.extensionUri, "src", "assets", "QRCode", "wx.png")
+ );
+
// 设置HTML内容
panel.webview.html = getWebviewContent(
iconUri.toString(),
autoIconUri.toString(),
liteIconUri.toString(),
syIconUri.toString(),
- maxIconUri.toString()
+ maxIconUri.toString(),
+ qrCodeUri.toString()
);
// 获取并发送用户信息到 webview
@@ -344,6 +350,16 @@ export async function showICHelperPanel(
// 退出登录
vscode.commands.executeCommand("ic-coder.logout");
break;
+ case "openUserManual":
+ // 打开用户手册
+ vscode.env.openExternal(vscode.Uri.parse("https://www.iccoder.com"));
+ break;
+ case "openUserFeedback":
+ // 打开用户反馈二维码弹窗
+ panel.webview.postMessage({
+ command: "showFeedbackQRCode"
+ });
+ break;
// 处理计划操作(只做模式切换,响应已通过 submitAnswer 发送)
case "planAction":
if (message.action === "confirm") {
diff --git a/src/views/conversationHistoryBar.ts b/src/views/conversationHistoryBar.ts
index 80e5785..fb79ecd 100644
--- a/src/views/conversationHistoryBar.ts
+++ b/src/views/conversationHistoryBar.ts
@@ -3,7 +3,12 @@ import {
getUserInfoComponentStyles,
getUserInfoComponentScript,
} from "./userInfoComponent";
-import { userAvatarIconSvg } from "../constants/toolIcons";
+import {
+ getMoreOptionsComponentContent,
+ getMoreOptionsComponentStyles,
+ getMoreOptionsComponentScript,
+} from "./moreOptionsComponent";
+import { userAvatarIconSvg, moreIconSvg } from "../constants/toolIcons";
/**
* 获取会话历史栏的 HTML 内容
@@ -39,6 +44,13 @@ export function getConversationHistoryBarContent(): string {
${getUserInfoComponentContent()}
+
+
+
+ ${getMoreOptionsComponentContent()}
+
`;
@@ -111,6 +123,41 @@ export function getConversationHistoryBarStyles(): string {
${getUserInfoComponentStyles()}
+ .more-container {
+ position: relative;
+ }
+
+ .more-button {
+ width: 36px;
+ height: 36px;
+ padding: 0;
+ background: transparent;
+ color: var(--vscode-foreground);
+ border: none;
+ border-radius: 50%;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.2s ease;
+ flex-shrink: 0;
+ }
+
+ .more-button:hover {
+ background: var(--vscode-toolbar-hoverBackground);
+ transform: scale(1.1);
+ }
+
+ .more-button:active {
+ transform: scale(0.95);
+ }
+
+ .more-button.active {
+ background: var(--vscode-toolbar-hoverBackground);
+ }
+
+ ${getMoreOptionsComponentStyles()}
+
.history-dropdown-button {
display: inline-flex;
align-items: center;
@@ -275,6 +322,8 @@ export function getConversationHistoryBarScript(): string {
return `
${getUserInfoComponentScript()}
+ ${getMoreOptionsComponentScript()}
+
// 更新用户头像图标按钮显示
function updateUserAvatarIconButton(userInfo) {
const userAvatarIconButton = document.getElementById('userAvatarIconButton');
diff --git a/src/views/moreOptionsComponent.ts b/src/views/moreOptionsComponent.ts
new file mode 100644
index 0000000..655372b
--- /dev/null
+++ b/src/views/moreOptionsComponent.ts
@@ -0,0 +1,394 @@
+/**
+ * 更多选项组件
+ * 包含用户手册和用户反馈入口
+ */
+
+/**
+ * 获取更多选项组件的 HTML 内容
+ */
+export function getMoreOptionsComponentContent(): string {
+ return `
+
+
+
+
+
+
+
+
+
+
+
![微信二维码]()
+
扫描二维码添加微信反馈
+
+
+
+
+ `;
+}
+
+/**
+ * 获取更多选项组件的 CSS 样式
+ */
+export function getMoreOptionsComponentStyles(): string {
+ return `
+ .more-options-wrapper {
+ position: relative;
+ }
+
+ /* 更多选项下拉面板 */
+ .more-options-dropdown {
+ display: none;
+ position: absolute;
+ top: calc(100% + 8px);
+ right: 0;
+ z-index: 10000;
+ min-width: 200px;
+ }
+
+ .more-options-dropdown.active {
+ display: block;
+ animation: dropdownSlideIn 0.15s ease-out;
+ }
+
+ @keyframes dropdownSlideIn {
+ from {
+ opacity: 0;
+ transform: translateY(-8px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+
+ .more-options-content {
+ background: var(--vscode-dropdown-background);
+ border: 1px solid var(--vscode-dropdown-border);
+ border-radius: 6px;
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
+ overflow: hidden;
+ }
+
+ .more-options-header {
+ display: none;
+ }
+
+ .more-options-body {
+ padding: 4px;
+ }
+
+ .more-option-item {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 10px 12px;
+ cursor: pointer;
+ transition: background 0.15s ease;
+ border-radius: 4px;
+ }
+
+ .more-option-item:hover {
+ background: var(--vscode-list-hoverBackground);
+ }
+
+ .more-option-item:active {
+ background: var(--vscode-list-activeSelectionBackground);
+ }
+
+ .option-icon {
+ width: 16px;
+ height: 16px;
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ opacity: 0.8;
+ }
+
+ .option-icon svg {
+ width: 16px;
+ height: 16px;
+ color: var(--vscode-foreground);
+ }
+
+ .option-text {
+ flex: 1;
+ }
+
+ .option-label {
+ font-size: 13px;
+ color: var(--vscode-foreground);
+ }
+
+ .option-desc {
+ display: none;
+ }
+
+ /* 用户反馈二维码弹窗 */
+ .feedback-qrcode-modal {
+ display: none;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 20000;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .feedback-qrcode-modal.active {
+ display: flex;
+ animation: fadeIn 0.2s ease-out;
+ }
+
+ @keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+ }
+
+ .feedback-qrcode-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.6);
+ cursor: pointer;
+ }
+
+ .feedback-qrcode-content {
+ position: relative;
+ background: var(--vscode-editor-background);
+ border: 1px solid var(--vscode-widget-border);
+ border-radius: 8px;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
+ max-width: 400px;
+ width: 90%;
+ animation: slideUp 0.2s ease-out;
+ }
+
+ @keyframes slideUp {
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+
+ .feedback-qrcode-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px 20px;
+ border-bottom: 1px solid var(--vscode-widget-border);
+ }
+
+ .feedback-qrcode-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--vscode-foreground);
+ }
+
+ .feedback-qrcode-close {
+ width: 28px;
+ height: 28px;
+ padding: 0;
+ background: transparent;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background 0.15s ease;
+ }
+
+ .feedback-qrcode-close:hover {
+ background: var(--vscode-toolbar-hoverBackground);
+ }
+
+ .feedback-qrcode-close svg {
+ width: 16px;
+ height: 16px;
+ color: var(--vscode-foreground);
+ }
+
+ .feedback-qrcode-body {
+ padding: 24px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 16px;
+ }
+
+ .feedback-qrcode-image {
+ width: 200px;
+ height: 200px;
+ border: 1px solid var(--vscode-widget-border);
+ border-radius: 8px;
+ }
+
+ .feedback-qrcode-text {
+ margin: 0;
+ font-size: 13px;
+ color: var(--vscode-descriptionForeground);
+ text-align: center;
+ }
+ `;
+}
+
+/**
+ * 获取更多选项组件的 JavaScript 脚本
+ */
+export function getMoreOptionsComponentScript(): string {
+ return `
+ // 切换更多选项下拉面板
+ function toggleMoreOptionsDropdown() {
+ const dropdown = document.getElementById('moreOptionsDropdown');
+ const moreButton = document.querySelector('.more-button');
+
+ if (dropdown) {
+ const isActive = dropdown.classList.contains('active');
+ if (isActive) {
+ dropdown.classList.remove('active');
+ if (moreButton) {
+ moreButton.classList.remove('active');
+ }
+ } else {
+ dropdown.classList.add('active');
+ if (moreButton) {
+ moreButton.classList.add('active');
+ }
+ }
+ }
+ }
+
+ // 关闭更多选项下拉面板
+ function closeMoreOptionsDropdown() {
+ const dropdown = document.getElementById('moreOptionsDropdown');
+ const moreButton = document.querySelector('.more-button');
+
+ if (dropdown) {
+ dropdown.classList.remove('active');
+ }
+ if (moreButton) {
+ moreButton.classList.remove('active');
+ }
+ }
+
+ // 打开用户手册
+ function openUserManual() {
+ console.log('打开用户手册');
+ vscode.postMessage({ command: 'openUserManual' });
+ closeMoreOptionsDropdown();
+ }
+
+ // 打开用户反馈
+ function openUserFeedback() {
+ console.log('打开用户反馈');
+ vscode.postMessage({ command: 'openUserFeedback' });
+ closeMoreOptionsDropdown();
+ }
+
+ // 显示用户反馈二维码弹窗
+ function showFeedbackQRCode() {
+ const modal = document.getElementById('feedbackQRCodeModal');
+ if (modal) {
+ modal.classList.add('active');
+ }
+ }
+
+ // 关闭用户反馈二维码弹窗
+ function closeFeedbackQRCode() {
+ const modal = document.getElementById('feedbackQRCodeModal');
+ if (modal) {
+ modal.classList.remove('active');
+ }
+ }
+
+ // 绑定更多选项事件
+ document.addEventListener('DOMContentLoaded', () => {
+ // 绑定用户手册选项
+ const userManualOption = document.getElementById('userManualOption');
+ if (userManualOption) {
+ userManualOption.addEventListener('click', openUserManual);
+ }
+
+ // 绑定用户反馈选项
+ const userFeedbackOption = document.getElementById('userFeedbackOption');
+ if (userFeedbackOption) {
+ userFeedbackOption.addEventListener('click', openUserFeedback);
+ }
+
+ // 点击页面其他地方关闭下拉面板
+ document.addEventListener('click', (e) => {
+ const dropdown = document.getElementById('moreOptionsDropdown');
+ const moreButton = document.querySelector('.more-button');
+ const moreContainer = document.querySelector('.more-container');
+
+ if (dropdown && dropdown.classList.contains('active')) {
+ // 如果点击的不是更多按钮和下拉面板内容,则关闭
+ if (!moreContainer?.contains(e.target)) {
+ closeMoreOptionsDropdown();
+ }
+ }
+ });
+
+ // 阻止下拉面板内容点击事件冒泡
+ const dropdownContent = document.querySelector('.more-options-content');
+ if (dropdownContent) {
+ dropdownContent.addEventListener('click', (e) => {
+ e.stopPropagation();
+ });
+ }
+ });
+ `;
+}
diff --git a/src/views/webviewContent.ts b/src/views/webviewContent.ts
index 83b0bf6..260d72e 100644
--- a/src/views/webviewContent.ts
+++ b/src/views/webviewContent.ts
@@ -33,7 +33,8 @@ export function getWebviewContent(
autoIconUri?: string,
liteIconUri?: string,
syIconUri?: string,
- maxIconUri?: string
+ maxIconUri?: string,
+ qrCodeUri?: string
): string {
// 获取当前环境,只在 dev 和 test 环境下显示快速操作按钮
const currentEnv = getCurrentEnv();
@@ -439,6 +440,12 @@ export function getWebviewContent(
let loadingIndicator = null;
let currentSegmentedMessage = null; // 当前分段消息容器
+ // 设置二维码图片
+ const feedbackQRCodeImage = document.getElementById('feedbackQRCodeImage');
+ if (feedbackQRCodeImage && '${qrCodeUri}') {
+ feedbackQRCodeImage.src = '${qrCodeUri}';
+ }
+
// ========== 模式选择器脚本(直接内联,避免模板字符串嵌套问题)==========
let currentMode = 'agent';
@@ -612,6 +619,14 @@ export function getWebviewContent(
}
break;
+ case 'showFeedbackQRCode':
+ // 显示用户反馈二维码弹窗
+ console.log('[WebView] 显示用户反馈二维码弹窗');
+ if (typeof showFeedbackQRCode === 'function') {
+ showFeedbackQRCode();
+ }
+ break;
+
case 'resetSegmentedMessage':
// 重置分段消息容器(停止对话时调用)
console.log('[WebView] 重置分段消息容器');