|
1 |
| -import { commands, ExtensionContext, window } from 'vscode'; |
| 1 | +import { commands, ExtensionContext, window, workspace, Uri } from 'vscode'; |
| 2 | +import * as os from 'os'; |
| 3 | +import * as path from 'path'; |
| 4 | + |
| 5 | +/** |
| 6 | + * 获取设置文件的默认路径 |
| 7 | + * 优先选择当前工作区目录,如果没有工作区则选择下载目录 |
| 8 | + */ |
| 9 | +function getDefaultSettingsPath(filename: string = 'leek-fund.settings.json'): string { |
| 10 | + const workspaceFolders = workspace.workspaceFolders; |
| 11 | + |
| 12 | + if (workspaceFolders && workspaceFolders.length > 0) { |
| 13 | + // 使用当前工作区目录 |
| 14 | + return path.join(workspaceFolders[0].uri.fsPath, filename); |
| 15 | + } else { |
| 16 | + // 使用下载目录作为备选 |
| 17 | + return path.join(os.homedir(), 'Downloads', filename); |
| 18 | + } |
| 19 | +} |
2 | 20 | import fundSuggestList from './data/fundSuggestData';
|
3 | 21 | import { BinanceProvider } from './explorer/binanceProvider';
|
4 | 22 | import BinanceService from './explorer/binanceService';
|
@@ -367,9 +385,7 @@ export function registerViewEvent(
|
367 | 385 |
|
368 | 386 | /* 点击交易对 */
|
369 | 387 | context.subscriptions.push(
|
370 |
| - commands.registerCommand('leek-fund.binanceItemClick', (code, name) => |
371 |
| - binanceTrend(name) |
372 |
| - ) |
| 388 | + commands.registerCommand('leek-fund.binanceItemClick', (code, name) => binanceTrend(name)) |
373 | 389 | );
|
374 | 390 |
|
375 | 391 | /**
|
@@ -450,6 +466,14 @@ export function registerViewEvent(
|
450 | 466 | label: globalState.stockHeldTipShow ? '关闭持仓高亮' : '开启持仓高亮',
|
451 | 467 | description: 'stockHeldTipShow',
|
452 | 468 | },
|
| 469 | + { |
| 470 | + label: '📤 导出设置', |
| 471 | + description: 'exportSettings', |
| 472 | + }, |
| 473 | + { |
| 474 | + label: '📥 导入设置', |
| 475 | + description: 'importSettings', |
| 476 | + }, |
453 | 477 | ],
|
454 | 478 | {
|
455 | 479 | placeHolder: '第一步:选择设置项',
|
@@ -541,6 +565,10 @@ export function registerViewEvent(
|
541 | 565 | commands.executeCommand('leek-fund.toggleKLineChartSwitch');
|
542 | 566 | } else if (type === 'stockHeldTipShow') {
|
543 | 567 | commands.executeCommand('leek-fund.toggleStockHeldTipShow');
|
| 568 | + } else if (type === 'exportSettings') { |
| 569 | + commands.executeCommand('leek-fund.exportSettings'); |
| 570 | + } else if (type === 'importSettings') { |
| 571 | + commands.executeCommand('leek-fund.importSettings'); |
544 | 572 | }
|
545 | 573 | });
|
546 | 574 | })
|
@@ -633,6 +661,165 @@ export function registerViewEvent(
|
633 | 661 | globalState.immersiveBackground = isChecked;
|
634 | 662 | })
|
635 | 663 | );
|
| 664 | + |
| 665 | + // Settings Import/Export Commands |
| 666 | + context.subscriptions.push( |
| 667 | + commands.registerCommand('leek-fund.exportSettings', async () => { |
| 668 | + try { |
| 669 | + const workspaceConfig = workspace.getConfiguration(); |
| 670 | + const allSettings: any = {}; |
| 671 | + |
| 672 | + // Get all leek-fund settings dynamically from extension context |
| 673 | + const extensionManifest = globalState.context.extension.packageJSON; |
| 674 | + const configurationProperties = extensionManifest.contributes?.configuration?.properties || {}; |
| 675 | + |
| 676 | + // Filter to only leek-fund configuration keys |
| 677 | + const leekFundConfigKeys = Object.keys(configurationProperties).filter(key => |
| 678 | + key.startsWith('leek-fund.') |
| 679 | + ); |
| 680 | + |
| 681 | + // Get all leek-fund settings that have actual values |
| 682 | + leekFundConfigKeys.forEach(key => { |
| 683 | + const value = workspaceConfig.get(key); |
| 684 | + if (value !== undefined) { |
| 685 | + allSettings[key] = value; |
| 686 | + } |
| 687 | + }); |
| 688 | + |
| 689 | + // Additional inspection method as fallback to catch any dynamically created settings |
| 690 | + const leekFundInspection = workspaceConfig.inspect('leek-fund'); |
| 691 | + const inspectionSources = [ |
| 692 | + leekFundInspection?.globalValue, |
| 693 | + leekFundInspection?.workspaceValue, |
| 694 | + leekFundInspection?.workspaceFolderValue |
| 695 | + ]; |
| 696 | + |
| 697 | + inspectionSources.forEach(source => { |
| 698 | + if (source && typeof source === 'object') { |
| 699 | + Object.keys(source).forEach(key => { |
| 700 | + const fullKey = `leek-fund.${key}`; |
| 701 | + if (!allSettings[fullKey]) { |
| 702 | + const value = workspaceConfig.get(fullKey); |
| 703 | + if (value !== undefined) { |
| 704 | + allSettings[fullKey] = value; |
| 705 | + } |
| 706 | + } |
| 707 | + }); |
| 708 | + } |
| 709 | + }); |
| 710 | + |
| 711 | + if (Object.keys(allSettings).length === 0) { |
| 712 | + window.showInformationMessage('没有找到任何以 "leek-fund." 开头的设置'); |
| 713 | + return; |
| 714 | + } |
| 715 | + |
| 716 | + // Show save dialog |
| 717 | + const uri = await window.showSaveDialog({ |
| 718 | + defaultUri: Uri.file(getDefaultSettingsPath()), |
| 719 | + filters: { |
| 720 | + 'JSON files': ['json'], |
| 721 | + 'All files': ['*'], |
| 722 | + }, |
| 723 | + }); |
| 724 | + |
| 725 | + if (uri) { |
| 726 | + const settingsJson = JSON.stringify(allSettings, null, 2); |
| 727 | + await workspace.fs.writeFile(uri, Buffer.from(settingsJson)); |
| 728 | + window.showInformationMessage(`设置已导出到: ${uri.fsPath}`); |
| 729 | + } |
| 730 | + } catch (error) { |
| 731 | + window.showErrorMessage(`导出设置失败: ${error}`); |
| 732 | + } |
| 733 | + }) |
| 734 | + ); |
| 735 | + |
| 736 | + context.subscriptions.push( |
| 737 | + commands.registerCommand('leek-fund.importSettings', async () => { |
| 738 | + try { |
| 739 | + // Show open dialog |
| 740 | + const uris = await window.showOpenDialog({ |
| 741 | + defaultUri: Uri.file(getDefaultSettingsPath()), |
| 742 | + canSelectFiles: true, |
| 743 | + canSelectFolders: false, |
| 744 | + canSelectMany: false, |
| 745 | + filters: { |
| 746 | + 'JSON files': ['json'], |
| 747 | + 'All files': ['*'], |
| 748 | + }, |
| 749 | + }); |
| 750 | + |
| 751 | + if (!uris || uris.length === 0) { |
| 752 | + return; |
| 753 | + } |
| 754 | + |
| 755 | + const uri = uris[0]; |
| 756 | + const content = await workspace.fs.readFile(uri); |
| 757 | + const settingsText = Buffer.from(content).toString('utf8'); |
| 758 | + |
| 759 | + let importedSettings: any; |
| 760 | + try { |
| 761 | + importedSettings = JSON.parse(settingsText); |
| 762 | + } catch (parseError) { |
| 763 | + window.showErrorMessage('无法解析 JSON 文件,请检查文件格式'); |
| 764 | + return; |
| 765 | + } |
| 766 | + |
| 767 | + // Filter settings that start with 'leek-fund.' |
| 768 | + const leekFundSettings: any = {}; |
| 769 | + Object.keys(importedSettings).forEach((key) => { |
| 770 | + if (key.startsWith('leek-fund.')) { |
| 771 | + leekFundSettings[key] = importedSettings[key]; |
| 772 | + } |
| 773 | + }); |
| 774 | + |
| 775 | + if (Object.keys(leekFundSettings).length === 0) { |
| 776 | + window.showInformationMessage('文件中没有找到任何以 "leek-fund." 开头的设置'); |
| 777 | + return; |
| 778 | + } |
| 779 | + |
| 780 | + // Confirm import |
| 781 | + const result = await window.showInformationMessage( |
| 782 | + `将导入 ${Object.keys(leekFundSettings).length} 个设置项,这将覆盖现有的设置。是否继续?`, |
| 783 | + '确认导入', |
| 784 | + '取消' |
| 785 | + ); |
| 786 | + |
| 787 | + if (result !== '确认导入') { |
| 788 | + return; |
| 789 | + } |
| 790 | + |
| 791 | + // Import settings |
| 792 | + const workspaceConfig = workspace.getConfiguration(); |
| 793 | + let successCount = 0; |
| 794 | + let failCount = 0; |
| 795 | + |
| 796 | + for (const [key, value] of Object.entries(leekFundSettings)) { |
| 797 | + try { |
| 798 | + await workspaceConfig.update(key, value, true); |
| 799 | + successCount++; |
| 800 | + } catch (error) { |
| 801 | + console.error(`Failed to import setting ${key}:`, error); |
| 802 | + failCount++; |
| 803 | + } |
| 804 | + } |
| 805 | + |
| 806 | + if (successCount > 0) { |
| 807 | + window.showInformationMessage( |
| 808 | + `设置导入完成:成功 ${successCount} 项${failCount > 0 ? `,失败 ${failCount} 项` : ''}` |
| 809 | + ); |
| 810 | + |
| 811 | + // Refresh the extension state |
| 812 | + commands.executeCommand('leek-fund.refreshFund'); |
| 813 | + commands.executeCommand('leek-fund.refreshStock'); |
| 814 | + } else { |
| 815 | + window.showErrorMessage('导入设置失败'); |
| 816 | + } |
| 817 | + } catch (error) { |
| 818 | + window.showErrorMessage(`导入设置失败: ${error}`); |
| 819 | + } |
| 820 | + }) |
| 821 | + ); |
| 822 | + |
636 | 823 | // checkForUpdate();
|
637 | 824 | }
|
638 | 825 |
|
|
0 commit comments