From 92a3d407a75a5032e33436dbe73c3d0fcf078b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=E9=87=8C=E7=9A=84=E6=B0=B8?= =?UTF-8?q?=E5=B9=B3?= Date: Thu, 17 Jul 2025 10:22:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9C=AC=E6=AC=A1=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E5=A6=82=E4=B8=8B=20?= =?UTF-8?q?=E5=AE=9A=E7=89=88=E6=9C=AC=E8=BD=AC=E7=A7=BB2025=E5=B9=B47?= =?UTF-8?q?=E6=9C=8817=E6=97=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/.babelrc | 3 - Cunkebao/.eslintrc.json | 18 - Cunkebao/.gitignore | 26 +- Cunkebao/.htaccess | 1 - ...KNDFrnOs9-cf7FZzW7Cg4MpIxhtE8pZ1etiT_7NPWA | 1 - Cunkebao/README.md | 233 +- Cunkebao/api/devices.ts | 192 - Cunkebao/api/route.ts | 74 - Cunkebao/api/scenarios.ts | 126 - Cunkebao/api/wechat-accounts.ts | 203 - Cunkebao/app/admin/accounts/mobile/page.tsx | 250 - .../app/admin/accounts/operators/page.tsx | 197 - .../app/admin/components/AdminSidebar.tsx | 88 - Cunkebao/app/admin/layout.tsx | 28 - Cunkebao/app/admin/page.tsx | 66 - .../api/acquisition/[planId]/orders/route.ts | 19 - Cunkebao/app/api/auth.ts | 68 - Cunkebao/app/api/devices/route.ts | 81 - .../docs/scenarios/[channel]/[id]/page.tsx | 377 - Cunkebao/app/api/docs/scenarios/page.tsx | 405 - Cunkebao/app/api/scenarios/route.ts | 73 - Cunkebao/app/api/users/route.ts | 272 - Cunkebao/app/clientLayout.tsx | 1 - Cunkebao/app/components-demo/loading.tsx | 34 - Cunkebao/app/components-demo/page.tsx | 493 - Cunkebao/app/components-docs/loading.tsx | 32 - Cunkebao/app/components-docs/page.tsx | 375 - Cunkebao/app/components/AIRewriteModal.tsx | 53 - Cunkebao/app/components/AdaptiveLayout.tsx | 22 - Cunkebao/app/components/ApiTester.tsx | 80 - Cunkebao/app/components/AuthProvider.tsx | 148 - Cunkebao/app/components/BindDouyinQRCode.tsx | 31 - Cunkebao/app/components/BottomNav.tsx | 55 - Cunkebao/app/components/Charts.tsx | 84 - Cunkebao/app/components/ChatMessage.tsx | 39 - .../components/CircleSync/ContentSelector.tsx | 105 - .../components/CircleSync/DeviceSelector.tsx | 122 - .../app/components/CircleSync/TaskSetup.tsx | 100 - Cunkebao/app/components/DeviceSelector.tsx | 257 - Cunkebao/app/components/ErrorBoundary.tsx | 46 - Cunkebao/app/components/FileUploader.tsx | 149 - Cunkebao/app/components/LayoutWrapper.tsx | 40 - Cunkebao/app/components/LoginErrorHandler.tsx | 68 - Cunkebao/app/components/SideNav.tsx | 6 - .../app/components/SpeechToTextProcessor.tsx | 71 - .../app/components/TrafficTeamSettings.tsx | 176 - .../app/components/VideoTutorialButton.tsx | 63 - Cunkebao/app/components/VoiceRecognition.tsx | 62 - .../acquisition/AcquisitionPlanChart.tsx | 98 - .../acquisition/DailyAcquisitionChart.tsx | 54 - .../acquisition/DeviceTreeChart.tsx | 74 - .../acquisition/ExpandableAcquisitionCard.tsx | 204 - .../acquisition/NewAcquisitionPlanForm.tsx | 96 - .../acquisition/ScenarioAcquisitionCard.tsx | 209 - Cunkebao/app/components/auth-check.tsx | 27 - .../app/components/common/AddDeviceDialog.tsx | 242 - Cunkebao/app/components/common/CardGrid.tsx | 155 - Cunkebao/app/components/common/Charts.tsx | 242 - .../app/components/common/ContentSelector.tsx | 287 - Cunkebao/app/components/common/DataTable.tsx | 363 - .../app/components/common/DeviceFilter.tsx | 320 - .../app/components/common/DeviceSelector.tsx | 537 - .../app/components/common/FileUploader.tsx | 373 - Cunkebao/app/components/common/FormLayout.tsx | 207 - Cunkebao/app/components/common/LazyLoad.tsx | 137 - .../components/common/NotificationSystem.tsx | 182 - Cunkebao/app/components/common/PageHeader.tsx | 59 - .../app/components/common/SearchFilter.tsx | 169 - Cunkebao/app/components/common/StatCard.tsx | 76 - Cunkebao/app/components/common/TagManager.tsx | 193 - .../app/components/common/VirtualizedList.tsx | 110 - Cunkebao/app/components/common/Wizard.tsx | 243 - Cunkebao/app/components/device-grid.tsx | 206 - .../components/device-selection-dialog.tsx | 154 - Cunkebao/app/components/poster-selector.tsx | 93 - .../app/components/traffic-pool-selector.tsx | 99 - .../app/components/ui-templates/card-grid.tsx | 42 - .../app/components/ui-templates/cards.tsx | 138 - .../components/ui-templates/form-layout.tsx | 87 - .../app/components/ui-templates/forms.tsx | 273 - .../app/components/ui-templates/index.tsx | 12 - .../app/components/ui-templates/layouts.tsx | 119 - .../components/ui-templates/page-header.tsx | 49 - .../ui-templates/responsive-table.tsx | 103 - .../app/components/ui-templates/selectors.tsx | 130 - .../app/components/ui-templates/stats.tsx | 58 - .../ui-templates/step-indicator.tsx | 46 - .../app/components/ui-templates/tables.tsx | 198 - Cunkebao/app/components/ui/accordion.tsx | 56 - Cunkebao/app/components/ui/avatar.tsx | 40 - Cunkebao/app/components/ui/badge.tsx | 30 - Cunkebao/app/components/ui/button.tsx | 59 - Cunkebao/app/components/ui/calendar.tsx | 54 - Cunkebao/app/components/ui/card.tsx | 43 - Cunkebao/app/components/ui/chart.tsx | 69 - Cunkebao/app/components/ui/checkbox.tsx | 28 - Cunkebao/app/components/ui/collapsible.tsx | 11 - Cunkebao/app/components/ui/dialog.tsx | 97 - Cunkebao/app/components/ui/dropdown-menu.tsx | 181 - Cunkebao/app/components/ui/input.tsx | 22 - Cunkebao/app/components/ui/label.tsx | 19 - Cunkebao/app/components/ui/pagination.tsx | 81 - Cunkebao/app/components/ui/popover.tsx | 6 - Cunkebao/app/components/ui/preview-dialog.tsx | 34 - Cunkebao/app/components/ui/progress.tsx | 25 - Cunkebao/app/components/ui/radio-group.tsx | 38 - Cunkebao/app/components/ui/scroll-area.tsx | 40 - Cunkebao/app/components/ui/select.tsx | 103 - Cunkebao/app/components/ui/skeleton.tsx | 8 - Cunkebao/app/components/ui/step-indicator.tsx | 157 - Cunkebao/app/components/ui/steps.tsx | 67 - Cunkebao/app/components/ui/switch.tsx | 29 - Cunkebao/app/components/ui/table.tsx | 72 - Cunkebao/app/components/ui/tabs.tsx | 55 - Cunkebao/app/components/ui/textarea.tsx | 21 - Cunkebao/app/components/ui/toast.ts | 14 - Cunkebao/app/components/ui/toast.tsx | 111 - Cunkebao/app/components/ui/tooltip.tsx | 107 - Cunkebao/app/components/ui/use-toast.ts | 186 - Cunkebao/app/contact-import/page.tsx | 332 - Cunkebao/app/content/[id]/edit/page.tsx | 492 - .../[id]/materials/edit/[materialId]/page.tsx | 533 - .../app/content/[id]/materials/new/page.tsx | 130 - Cunkebao/app/content/[id]/materials/page.tsx | 184 - Cunkebao/app/content/[id]/page.tsx | 289 - Cunkebao/app/content/loading.tsx | 3 - Cunkebao/app/content/new/device-selector.tsx | 116 - Cunkebao/app/content/new/page.tsx | 153 - .../app/content/new/steps/basic-settings.tsx | 150 - .../content/new/steps/content-settings.tsx | 150 - .../app/content/new/steps/preview-confirm.tsx | 244 - .../content/new/steps/source-selection.tsx | 259 - .../app/content/new/steps/tag-settings.tsx | 151 - Cunkebao/app/content/page.tsx | 315 - Cunkebao/app/devices/[id]/page.tsx | 410 - Cunkebao/app/devices/loading.tsx | 3 - Cunkebao/app/devices/page.tsx | 669 - Cunkebao/app/globals.css | 167 - Cunkebao/app/hooks/useDeviceStatusPolling.ts | 80 - Cunkebao/app/layout.tsx | 33 - Cunkebao/app/lib/date-utils.ts | 33 - Cunkebao/app/lib/toast.ts | 22 - Cunkebao/app/lib/utils.ts | 29 - Cunkebao/app/login/page.tsx | 239 - Cunkebao/app/orders/submit/[planId]/page.tsx | 151 - Cunkebao/app/page.tsx | 454 - Cunkebao/app/plans/new/loading.tsx | 3 - Cunkebao/app/plans/new/page.tsx | 117 - .../app/plans/new/steps/BasicSettings.tsx | 1081 - .../plans/new/steps/FriendRequestSettings.tsx | 277 - .../app/plans/new/steps/MessageSettings.tsx | 554 - Cunkebao/app/profile/devices/loading.tsx | 3 - Cunkebao/app/profile/devices/page.tsx | 371 - Cunkebao/app/profile/page.tsx | 189 - .../app/scenarios/[channel]/[id]/page.tsx | 372 - .../app/scenarios/[channel]/acquired/page.tsx | 114 - .../app/scenarios/[channel]/added/page.tsx | 118 - Cunkebao/app/scenarios/[channel]/api/page.tsx | 391 - .../scenarios/[channel]/devices/loading.tsx | 3 - .../app/scenarios/[channel]/devices/page.tsx | 77 - .../scenarios/[channel]/edit/[id]/page.tsx | 234 - Cunkebao/app/scenarios/[channel]/page.tsx | 643 - .../scenarios/[channel]/traffic/loading.tsx | 3 - .../app/scenarios/[channel]/traffic/page.tsx | 235 - Cunkebao/app/scenarios/api/page.tsx | 373 - Cunkebao/app/scenarios/api/route.ts | 5 - Cunkebao/app/scenarios/douyin/page.tsx | 122 - .../app/scenarios/haibao/edit/[id]/page.tsx | 129 - Cunkebao/app/scenarios/loading.tsx | 3 - Cunkebao/app/scenarios/new/loading.tsx | 3 - Cunkebao/app/scenarios/new/page.tsx | 252 - .../app/scenarios/new/steps/BasicSettings.tsx | 1460 - .../new/steps/FriendRequestSettings.tsx | 251 - .../scenarios/new/steps/MessageSettings.tsx | 650 - .../app/scenarios/new/steps/PosterEditor.tsx | 479 - .../new/steps/TrafficChannelSettings | 209 - Cunkebao/app/scenarios/page.tsx | 253 - Cunkebao/app/scenarios/payment/[id]/page.tsx | 377 - .../payment/[id]/payments/loading.tsx | 3 - .../scenarios/payment/[id]/payments/page.tsx | 263 - Cunkebao/app/scenarios/payment/new/page.tsx | 307 - Cunkebao/app/scenarios/payment/page.tsx | 278 - Cunkebao/app/scenarios/payment/stats/page.tsx | 260 - .../app/scenarios/phone/acquired/loading.tsx | 3 - .../app/scenarios/phone/acquired/page.tsx | 178 - .../app/scenarios/phone/added/loading.tsx | 3 - Cunkebao/app/scenarios/phone/added/page.tsx | 132 - Cunkebao/app/scenarios/phone/devices/page.tsx | 186 - .../app/scenarios/phone/edit/[id]/page.tsx | 401 - .../app/scenarios/phone/new/basic/page.tsx | 333 - .../phone/new/components/AIFilterSettings.tsx | 76 - .../new/components/DeviceConfigDialog.tsx | 137 - .../new/components/DistributionSettings.tsx | 92 - .../phone/new/components/FollowUpSettings.tsx | 123 - .../new/components/PhoneImportDialog.tsx | 138 - .../new/components/RedPacketSettings.tsx | 83 - Cunkebao/app/scenarios/phone/new/page.tsx | 254 - Cunkebao/app/scenarios/phone/page.tsx | 122 - Cunkebao/app/scenarios/weixinqun/page.tsx | 233 - .../components/analytics-dashboard.tsx | 311 - .../components/date-range-picker.tsx | 53 - .../components/multi-device-selector.tsx | 309 - .../components/pool-management.tsx | 420 - .../components/pool-usage-chart.tsx | 32 - Cunkebao/app/traffic-pool/loading.tsx | 3 - Cunkebao/app/traffic-pool/page.tsx | 1514 -- Cunkebao/app/types/wechat.ts | 1 - Cunkebao/app/wechat-accounts/[id]/page.tsx | 296 - Cunkebao/app/wechat-accounts/loading.tsx | 3 - Cunkebao/app/wechat-accounts/page.tsx | 348 - .../app/workspace/ai-analyzer/[id]/page.tsx | 463 - .../components/analysis-settings.tsx | 282 - .../components/confirm-analysis.tsx | 179 - .../components/device-selection.tsx | 214 - .../ai-analyzer/components/step-indicator.tsx | 42 - .../create/components/basic-settings.tsx | 164 - .../create/components/target-selection.tsx | 396 - .../app/workspace/ai-analyzer/create/page.tsx | 102 - .../new/components/basic-settings.tsx | 123 - .../new/components/target-selection.tsx | 396 - .../app/workspace/ai-analyzer/new/page.tsx | 116 - Cunkebao/app/workspace/ai-analyzer/page.tsx | 367 - .../ai-assistant/knowledge-base/page.tsx | 283 - Cunkebao/app/workspace/ai-assistant/page.tsx | 272 - .../app/workspace/ai-strategy/[id]/page.tsx | 343 - .../components/confirm-strategy.tsx | 234 - .../components/execution-setup.tsx | 202 - .../ai-strategy/components/step-indicator.tsx | 57 - .../components/strategy-selection.tsx | 321 - .../components/traffic-pool-selection.tsx | 293 - .../app/workspace/ai-strategy/new/page.tsx | 128 - Cunkebao/app/workspace/ai-strategy/page.tsx | 370 - .../components/StepByStepPlanForm.tsx | 186 - .../components/auto-group-service.ts | 84 - .../auto-group/components/columns.tsx | 128 - .../auto-group/components/data-table.tsx | 95 - .../components/device-selection.tsx | 280 - .../auto-group/components/device-selector.tsx | 67 - .../auto-group/components/group-assistant.tsx | 126 - .../components/group-creation-progress.tsx | 126 - .../auto-group/components/group-preview.tsx | 96 - .../auto-group/components/group-settings.tsx | 581 - .../auto-group/components/new-plan-form.tsx | 284 - .../auto-group/components/step-indicator.tsx | 62 - .../auto-group/components/tag-selection.tsx | 274 - .../components/traffic-pool-selector.tsx | 193 - .../components/wechat-account-selector.tsx | 168 - Cunkebao/app/workspace/auto-group/loading.tsx | 3 - .../app/workspace/auto-group/new/loading.tsx | 42 - .../app/workspace/auto-group/new/page.tsx | 136 - Cunkebao/app/workspace/auto-group/page.tsx | 307 - .../workspace/auto-like/[id]/edit/page.tsx | 281 - .../app/workspace/auto-like/[id]/page.tsx | 283 - .../auto-like/components/audience-tags.tsx | 161 - .../auto-like/components/basic-settings.tsx | 201 - .../components/device-selection-dialog.tsx | 145 - .../auto-like/components/device-selection.tsx | 228 - .../auto-like/components/like-config.tsx | 262 - .../auto-like/components/like-rules.tsx | 329 - .../auto-like/components/step-indicator.tsx | 51 - .../auto-like/components/tag-selector.tsx | 251 - .../auto-like/components/time-settings.tsx | 242 - Cunkebao/app/workspace/auto-like/loading.tsx | 3 - .../app/workspace/auto-like/new/loading.tsx | 3 - Cunkebao/app/workspace/auto-like/new/page.tsx | 144 - Cunkebao/app/workspace/auto-like/page.tsx | 330 - .../workspace/group-push/[id]/edit/page.tsx | 192 - .../group-push/components/basic-settings.tsx | 218 - .../components/content-selector.tsx | 223 - .../group-push/components/friend-selector.tsx | 346 - .../group-push/components/group-selector.tsx | 253 - .../group-push/components/message-editor.tsx | 229 - .../group-push/components/step-indicator.tsx | 80 - Cunkebao/app/workspace/group-push/loading.tsx | 63 - .../app/workspace/group-push/new/loading.tsx | 84 - .../app/workspace/group-push/new/page.tsx | 138 - Cunkebao/app/workspace/group-push/page.tsx | 251 - .../group-sync/auto-group/loading.tsx | 51 - .../workspace/group-sync/auto-group/page.tsx | 68 - .../components/auto-group-creator.tsx | 150 - .../group-sync/components/basic-settings.tsx | 207 - .../components/content-selector.tsx | 210 - .../group-sync/components/group-selector.tsx | 241 - .../group-sync/components/step-indicator.tsx | 62 - Cunkebao/app/workspace/group-sync/loading.tsx | 3 - .../app/workspace/group-sync/new/loading.tsx | 46 - .../app/workspace/group-sync/new/page.tsx | 133 - Cunkebao/app/workspace/group-sync/page.tsx | 202 - .../workspace/moments-sync/[id]/edit/page.tsx | 142 - .../moments-sync/[id]/edit/step-indicator.tsx | 38 - .../[id]/edit/steps/basic-settings.tsx | 100 - .../edit/steps/content-library-selection.tsx | 39 - .../[id]/edit/steps/device-selection.tsx | 34 - .../app/workspace/moments-sync/[id]/page.tsx | 107 - .../workspace/moments-sync/[id]/view/page.tsx | 129 - .../components/basic-settings.tsx | 164 - .../content-library-selection-dialog.tsx | 198 - .../components/content-selector.tsx | 17 - .../components/content-viewer.tsx | 102 - .../components/device-selection-dialog.tsx | 145 - .../components/step-indicator.tsx | 51 - .../moments-sync/components/tag-editor.tsx | 155 - .../app/workspace/moments-sync/new/page.tsx | 148 - .../moments-sync/new/steps/BasicSettings.tsx | 139 - .../new/steps/ContentSelector.tsx | 279 - .../moments-sync/new/steps/DeviceSelector.tsx | 274 - Cunkebao/app/workspace/moments-sync/page.tsx | 168 - Cunkebao/app/workspace/page.tsx | 194 - .../app/workspace/pricing/edit/[id]/page.tsx | 533 - Cunkebao/app/workspace/pricing/new/page.tsx | 419 - Cunkebao/app/workspace/pricing/page.tsx | 121 - .../traffic-distribution/[id]/edit/page.tsx | 87 - .../traffic-distribution/[id]/loading.tsx | 98 - .../traffic-distribution/[id]/page.tsx | 282 - .../components/distribution-rule-card.tsx | 161 - .../components/distribution-rule-form.tsx | 280 - .../components/keyword-selector.tsx | 179 - .../components/traffic-pool-selector.tsx | 104 - .../traffic-distribution/loading.tsx | 87 - .../new/components/basic-info-step.tsx | 161 - .../new/components/step-indicator.tsx | 36 - .../new/components/target-settings-step.tsx | 180 - .../new/components/traffic-pool-step.tsx | 122 - .../traffic-distribution/new/loading.tsx | 61 - .../traffic-distribution/new/page.tsx | 107 - .../workspace/traffic-distribution/page.tsx | 254 - .../app/workspace/traffic-pricing/loading.tsx | 3 - .../app/workspace/traffic-pricing/page.tsx | 164 - Cunkebao/app/开发文档.md | 197 - Cunkebao/components.json | 21 - Cunkebao/components/AIAssistant.tsx | 110 - Cunkebao/components/AuthCheck.tsx | 43 - Cunkebao/components/BindDouyinQRCode.tsx | 31 - Cunkebao/components/Charts.tsx | 47 - Cunkebao/components/ClientOnly.tsx | 18 - Cunkebao/components/ExcelImporter.tsx | 384 - Cunkebao/components/ImeiDisplay.tsx | 140 - Cunkebao/components/TrafficTeamSettings.tsx | 149 - Cunkebao/components/VideoTutorialButton.tsx | 63 - Cunkebao/components/WechatFriendSelector.tsx | 117 - .../components/WechatGroupMemberSelector.tsx | 260 - Cunkebao/components/WechatGroupSelector.tsx | 110 - .../acquisition/ExpandableAcquisitionCard.tsx | 114 - .../acquisition/PlanSettingsDialog.tsx | 102 - .../components/api-documentation-tooltip.tsx | 25 - Cunkebao/components/common/DeviceSelector.tsx | 187 - Cunkebao/components/device-grid.tsx | 104 - Cunkebao/components/device-table.tsx | 98 - Cunkebao/components/icons/apple-icon.tsx | 11 - Cunkebao/components/icons/wechat-icon.tsx | 12 - Cunkebao/components/login-form.tsx | 325 - Cunkebao/components/poster-selector.tsx | 84 - Cunkebao/components/settings-dropdown.tsx | 45 - Cunkebao/components/theme-provider.tsx | 11 - Cunkebao/components/ui/accordion.tsx | 51 - Cunkebao/components/ui/alert-dialog.tsx | 141 - Cunkebao/components/ui/alert.tsx | 59 - Cunkebao/components/ui/aspect-ratio.tsx | 7 - Cunkebao/components/ui/avatar.tsx | 40 - Cunkebao/components/ui/badge.tsx | 29 - Cunkebao/components/ui/breadcrumb.tsx | 115 - Cunkebao/components/ui/button.tsx | 59 - Cunkebao/components/ui/calendar.tsx | 59 - Cunkebao/components/ui/card.tsx | 52 - Cunkebao/components/ui/carousel.tsx | 262 - Cunkebao/components/ui/chart.tsx | 204 - Cunkebao/components/ui/checkbox.tsx | 26 - Cunkebao/components/ui/code.tsx | 20 - Cunkebao/components/ui/collapsible.tsx | 10 - Cunkebao/components/ui/command.tsx | 153 - Cunkebao/components/ui/context-menu.tsx | 200 - Cunkebao/components/ui/date-picker.tsx | 87 - Cunkebao/components/ui/date-range-picker.tsx | 57 - Cunkebao/components/ui/dialog.tsx | 95 - Cunkebao/components/ui/drawer.tsx | 118 - Cunkebao/components/ui/dropdown-menu.tsx | 180 - Cunkebao/components/ui/form.tsx | 178 - Cunkebao/components/ui/hover-card.tsx | 29 - Cunkebao/components/ui/input-otp.tsx | 71 - Cunkebao/components/ui/input.tsx | 22 - Cunkebao/components/ui/label.tsx | 17 - Cunkebao/components/ui/menubar.tsx | 236 - Cunkebao/components/ui/navigation-menu.tsx | 128 - Cunkebao/components/ui/pagination.tsx | 81 - Cunkebao/components/ui/popover.tsx | 29 - Cunkebao/components/ui/preview-dialog.tsx | 34 - Cunkebao/components/ui/progress.tsx | 35 - Cunkebao/components/ui/radio-group.tsx | 36 - Cunkebao/components/ui/resizable.tsx | 45 - Cunkebao/components/ui/scroll-area.tsx | 38 - Cunkebao/components/ui/select.tsx | 101 - Cunkebao/components/ui/separator.tsx | 23 - Cunkebao/components/ui/sheet.tsx | 140 - Cunkebao/components/ui/sidebar.tsx | 763 - Cunkebao/components/ui/skeleton.tsx | 8 - Cunkebao/components/ui/slider.tsx | 25 - Cunkebao/components/ui/sonner.tsx | 31 - Cunkebao/components/ui/steps.tsx | 54 - Cunkebao/components/ui/switch.tsx | 27 - Cunkebao/components/ui/table.tsx | 69 - Cunkebao/components/ui/tabs.tsx | 53 - Cunkebao/components/ui/textarea.tsx | 21 - Cunkebao/components/ui/toast.ts | 114 - Cunkebao/components/ui/toast.tsx | 113 - Cunkebao/components/ui/toaster.tsx | 24 - Cunkebao/components/ui/toggle-group.tsx | 61 - Cunkebao/components/ui/toggle.tsx | 45 - Cunkebao/components/ui/tooltip.tsx | 107 - Cunkebao/components/ui/use-mobile.tsx | 19 - Cunkebao/components/ui/use-toast.ts | 188 - {nkebao => Cunkebao}/craco.config.js | 0 Cunkebao/docs/API对接指南.md | 180 - Cunkebao/docs/README.md | 29 - Cunkebao/docs/api-guide.ts | 295 - Cunkebao/docs/api-guide.tsx | 413 - Cunkebao/docs/home/README.md | 10 - Cunkebao/docs/home/data-overview.md | 28 - Cunkebao/docs/home/quick-access.md | 29 - Cunkebao/docs/home/recent-activities.md | 31 - Cunkebao/docs/scenarios/README.md | 11 - Cunkebao/docs/scenarios/douyin-acquisition.md | 44 - Cunkebao/docs/scenarios/new-scenario.md | 47 - Cunkebao/docs/scenarios/phone-acquisition.md | 44 - Cunkebao/docs/scenarios/poster-acquisition.md | 44 - Cunkebao/docs/workspace/README.md | 16 - Cunkebao/docs/workspace/auto-group.md | 47 - Cunkebao/docs/workspace/auto-like.md | 45 - Cunkebao/docs/workspace/group-push.md | 46 - Cunkebao/docs/workspace/group-sync.md | 46 - Cunkebao/docs/workspace/moments-sync.md | 44 - .../docs/workspace/traffic-distribution.md | 64 - Cunkebao/hooks/use-debounce.ts | 17 - Cunkebao/hooks/use-mobile.tsx | 28 - Cunkebao/hooks/use-toast.ts | 188 - Cunkebao/hooks/useAuth.ts | 46 - Cunkebao/hooks/useDeviceStatusPolling.ts | 46 - Cunkebao/lib/actions/auth-actions.ts | 30 - Cunkebao/lib/api.ts | 251 - Cunkebao/lib/api/auth.ts | 222 - Cunkebao/lib/api/client.ts | 244 - Cunkebao/lib/api/config.ts | 132 - Cunkebao/lib/api/content.ts | 156 - Cunkebao/lib/api/dashboard.ts | 150 - Cunkebao/lib/api/devices.ts | 178 - Cunkebao/lib/api/github-integration.ts | 98 - Cunkebao/lib/api/index.ts | 7 - Cunkebao/lib/api/scenarios-mobile.ts | 305 - Cunkebao/lib/api/scenarios.ts | 165 - Cunkebao/lib/api/traffic.ts | 131 - Cunkebao/lib/api/users.ts | 90 - Cunkebao/lib/api/wechat.ts | 186 - Cunkebao/lib/api/workspace.ts | 270 - Cunkebao/lib/http-interceptors.ts | 64 - Cunkebao/lib/migration/github-adapter.ts | 232 - Cunkebao/lib/migration/integration-checker.ts | 351 - Cunkebao/lib/migration/migration-guide.ts | 247 - Cunkebao/lib/toast.ts | 57 - Cunkebao/lib/tutorials.ts | 59 - Cunkebao/lib/utils.ts | 19 - Cunkebao/next.config.js | 99 - Cunkebao/next.config.mjs | 142 - Cunkebao/package-lock.json | 21971 +++++++++++++--- Cunkebao/package.json | 115 +- Cunkebao/pnpm-lock.yaml | 7349 ------ {nkebao => Cunkebao}/postcss.config.js | 0 Cunkebao/postcss.config.mjs | 8 - Cunkebao/public/device-management-design.png | Bin 419100 -> 0 bytes Cunkebao/public/diverse-avatars.png | Bin 681174 -> 0 bytes Cunkebao/public/diverse-group-avatars.png | Bin 442826 -> 0 bytes {nkebao => Cunkebao}/public/favicon.ico | Bin {nkebao => Cunkebao}/public/index.html | 0 Cunkebao/public/interface-design.png | Bin 98323 -> 0 bytes {nkebao => Cunkebao}/public/logo192.png | Bin {nkebao => Cunkebao}/public/logo512.png | Bin {nkebao => Cunkebao}/public/manifest.json | 0 Cunkebao/public/mobile-device-management.png | Bin 129624 -> 0 bytes .../public/mobile-traffic-pool-design.png | Bin 187800 -> 0 bytes Cunkebao/public/placeholder-logo.png | Bin 568 -> 0 bytes Cunkebao/public/placeholder-logo.svg | 1 - Cunkebao/public/placeholder-user.jpg | Bin 1635 -> 0 bytes Cunkebao/public/placeholder.jpg | Bin 1064 -> 0 bytes Cunkebao/public/placeholder.svg | 1 - Cunkebao/public/profile-design.png | Bin 166755 -> 0 bytes Cunkebao/public/profile-functions.png | Bin 81228 -> 0 bytes {nkebao => Cunkebao}/public/robots.txt | 0 Cunkebao/public/scenario-cards.png | Bin 79740 -> 0 bytes Cunkebao/public/wechat-detail.png | Bin 31166 -> 0 bytes Cunkebao/public/wechat-management-design.png | Bin 671613 -> 0 bytes Cunkebao/public/workspace-design.png | Bin 195534 -> 0 bytes Cunkebao/public/workspace-stats.png | Bin 42930 -> 0 bytes Cunkebao/public/场景获客.png | Bin 565198 -> 0 bytes Cunkebao/public/订单导入模板.csv | 0 Cunkebao/scripts/api-test.sh | 96 - Cunkebao/scripts/migration-setup.sh | 279 - .../scripts/update-page-headers.js | 0 {nkebao => Cunkebao}/src/App.css | 0 {nkebao => Cunkebao}/src/App.test.tsx | 0 {nkebao => Cunkebao}/src/App.tsx | 0 {nkebao => Cunkebao}/src/api/auth.ts | 0 {nkebao => Cunkebao}/src/api/autoLike.ts | 0 {nkebao => Cunkebao}/src/api/content.ts | 0 {nkebao => Cunkebao}/src/api/devices.ts | 0 {nkebao => Cunkebao}/src/api/groupPush.ts | 0 {nkebao => Cunkebao}/src/api/index.ts | 0 {nkebao => Cunkebao}/src/api/interceptors.ts | 0 {nkebao => Cunkebao}/src/api/momentsSync.ts | 0 {nkebao => Cunkebao}/src/api/request.ts | 0 {nkebao => Cunkebao}/src/api/scenarios.ts | 0 .../src/api/trafficDistribution.ts | 0 {nkebao => Cunkebao}/src/api/upload.ts | 0 {nkebao => Cunkebao}/src/api/utils.ts | 0 .../src/api/wechat-accounts.ts | 0 .../src/components/BackButton.tsx | 0 .../src/components/BottomNav.tsx | 0 .../ContentLibrarySelectionDialog.tsx | 0 .../src/components/DeviceSelection.tsx | 0 .../src/components/DeviceSelectionDialog.tsx | 0 .../src/components/FriendSelection.tsx | 0 .../src/components/GroupSelection.tsx | 0 .../src/components/Layout.css | 0 .../src/components/Layout.tsx | 0 .../src/components/LayoutWrapper.tsx | 0 .../src/components/PageHeader.tsx | 0 .../src/components/ProtectedRoute.tsx | 0 .../components/ScenarioAcquisitionCard.tsx | 0 .../src/components/TestComponent.tsx | 0 .../src/components/ThrottledButton.tsx | 0 .../src/components/TrafficPoolSelection.tsx | 0 .../src/components/UnifiedHeader.tsx | 0 .../src/components/UploadImage.tsx | 0 .../src/components/UploadVideo.tsx | 0 .../src/components/icons/AppleIcon.tsx | 0 .../src/components/icons/EyeIcon.tsx | 0 .../src/components/icons/WeChatIcon.tsx | 0 .../src/components/ui/alert.tsx | 0 .../src/components/ui/avatar.tsx | 0 .../src/components/ui/badge.tsx | 0 .../src/components/ui/button.tsx | 0 .../src/components/ui/card.tsx | 0 .../src/components/ui/checkbox.tsx | 0 .../src/components/ui/dialog.tsx | 0 .../src/components/ui/dropdown-menu.tsx | 0 .../src/components/ui/input.tsx | 0 .../src/components/ui/label.tsx | 0 .../src/components/ui/progress.tsx | 0 .../src/components/ui/radio-group.tsx | 0 .../src/components/ui/scroll-area.tsx | 0 .../src/components/ui/select.tsx | 0 .../src/components/ui/separator.tsx | 0 .../src/components/ui/skeleton.tsx | 0 .../src/components/ui/switch.tsx | 0 .../src/components/ui/table.tsx | 0 .../src/components/ui/tabs.tsx | 0 .../src/components/ui/textarea.tsx | 0 .../src/components/ui/toast.tsx | 0 .../src/components/ui/tooltip.tsx | 0 .../src/components/ui/use-toast.ts | 0 .../src/contexts/AuthContext.tsx | 0 .../src/contexts/WechatAccountContext.tsx | 0 .../src/hooks/use-debounce.ts | 0 .../src/hooks/useAuthGuard.ts | 0 .../src/hooks/useBackNavigation.ts | 0 .../src/hooks/useThrottledRequest.ts | 0 {nkebao => Cunkebao}/src/index.css | 0 {nkebao => Cunkebao}/src/index.tsx | 0 {nkebao => Cunkebao}/src/logo.svg | 0 {nkebao => Cunkebao}/src/pages/Home.tsx | 0 .../pages/contact-import/ContactImport.tsx | 0 .../src/pages/content/Content.tsx | 0 .../src/pages/content/NewContent.tsx | 0 .../src/pages/content/materials/List.tsx | 0 .../src/pages/content/materials/New.tsx | 0 .../src/pages/devices/DeviceDetail.tsx | 0 .../src/pages/devices/Devices.tsx | 0 .../src/pages/login/Login.tsx | 0 .../src/pages/orders/Orders.tsx | 0 .../src/pages/plans/PlanDetail.tsx | 0 .../src/pages/plans/Plans.tsx | 0 .../src/pages/profile/Profile.tsx | 0 .../src/pages/scenarios/ScenarioList.tsx | 0 .../src/pages/scenarios/Scenarios.tsx | 0 .../src/pages/scenarios/new/page.tsx | 0 .../scenarios/new/steps/BasicSettings.tsx | 0 .../new/steps/FriendRequestSettings.tsx | 0 .../scenarios/new/steps/MessageSettings.tsx | 0 .../scenarios}/new/steps/TagSettings.tsx | 0 .../src/pages/traffic-pool/TrafficPool.tsx | 0 .../pages/traffic-pool/TrafficPoolDetail.tsx | 0 .../wechat-accounts/WechatAccountDetail.tsx | 0 .../pages/wechat-accounts/WechatAccounts.tsx | 0 .../src/pages/workspace/Workspace.tsx | 0 .../workspace/ai-assistant/AIAssistant.tsx | 0 .../pages/workspace/auto-group/AutoGroup.tsx | 0 .../src/pages/workspace/auto-group/Detail.tsx | 0 .../pages/workspace/auto-like/AutoLike.tsx | 0 .../workspace/auto-like/AutoLikeDetail.tsx | 0 .../pages/workspace/auto-like/NewAutoLike.tsx | 0 .../pages/workspace/group-push/GroupPush.tsx | 0 .../group-push/components/BasicSettings.tsx | 0 .../group-push/components/ContentSelector.tsx | 0 .../group-push/components/GroupSelector.tsx | 0 .../group-push/components/StepIndicator.tsx | 0 .../src/pages/workspace/group-push/new.tsx | 0 .../pages/workspace/moments-sync/Detail.tsx | 0 .../workspace/moments-sync/MomentsSync.tsx | 0 .../pages/workspace/moments-sync/index.tsx | 0 .../src/pages/workspace/moments-sync/new.tsx | 0 .../workspace/traffic-distribution/Detail.tsx | 0 .../traffic-distribution/NewDistribution.tsx | 0 .../TrafficDistribution.tsx | 0 {nkebao => Cunkebao}/src/react-app-env.d.ts | 0 {nkebao => Cunkebao}/src/reportWebVitals.ts | 0 {nkebao => Cunkebao}/src/setupTests.ts | 0 {nkebao => Cunkebao}/src/types/auto-like.ts | 0 {nkebao => Cunkebao}/src/types/common.ts | 0 {nkebao => Cunkebao}/src/types/device.ts | 0 .../src/types/moments-sync.ts | 0 Cunkebao/{ => src}/types/wechat.ts | 0 {nkebao => Cunkebao}/src/utils/index.ts | 0 Cunkebao/styles/globals.css | 94 - Cunkebao/tailwind.config.js | 91 +- Cunkebao/tsconfig.json | 35 +- Cunkebao/types/acquisition.ts | 28 - Cunkebao/types/auto-group.ts | 40 - Cunkebao/types/common.ts | 43 - Cunkebao/types/content-library.ts | 29 - Cunkebao/types/content.ts | 41 - Cunkebao/types/device.ts | 155 - Cunkebao/types/group-push.ts | 39 - Cunkebao/types/group-sync.ts | 35 - Cunkebao/types/scenario.ts | 111 - Cunkebao/types/traffic.ts | 14 - Cunkebao/types/tutorial.ts | 12 - Cunkebao/types/wechat-account.ts | 114 - Cunkebao/types/xlsx.d.ts | 6 - Cunkebao/yarn.lock | 14422 ++++++++-- nkebao/.gitignore | 23 - nkebao/README.md | 266 - nkebao/package-lock.json | 21347 --------------- nkebao/package.json | 106 - .../pages/scenarios/new/steps/TagSettings.tsx | 205 - nkebao/src/types/wechat.ts | 35 - nkebao/tailwind.config.js | 56 - nkebao/tsconfig.json | 37 - nkebao/yarn.lock | 11943 --------- 645 files changed, 30755 insertions(+), 118800 deletions(-) delete mode 100644 Cunkebao/.babelrc delete mode 100644 Cunkebao/.eslintrc.json delete mode 100644 Cunkebao/.htaccess delete mode 100644 Cunkebao/.well-known/acme-challenge/nKNDFrnOs9-cf7FZzW7Cg4MpIxhtE8pZ1etiT_7NPWA delete mode 100644 Cunkebao/api/devices.ts delete mode 100644 Cunkebao/api/route.ts delete mode 100644 Cunkebao/api/scenarios.ts delete mode 100644 Cunkebao/api/wechat-accounts.ts delete mode 100644 Cunkebao/app/admin/accounts/mobile/page.tsx delete mode 100644 Cunkebao/app/admin/accounts/operators/page.tsx delete mode 100644 Cunkebao/app/admin/components/AdminSidebar.tsx delete mode 100644 Cunkebao/app/admin/layout.tsx delete mode 100644 Cunkebao/app/admin/page.tsx delete mode 100644 Cunkebao/app/api/acquisition/[planId]/orders/route.ts delete mode 100644 Cunkebao/app/api/auth.ts delete mode 100644 Cunkebao/app/api/devices/route.ts delete mode 100644 Cunkebao/app/api/docs/scenarios/[channel]/[id]/page.tsx delete mode 100644 Cunkebao/app/api/docs/scenarios/page.tsx delete mode 100644 Cunkebao/app/api/scenarios/route.ts delete mode 100644 Cunkebao/app/api/users/route.ts delete mode 100644 Cunkebao/app/clientLayout.tsx delete mode 100644 Cunkebao/app/components-demo/loading.tsx delete mode 100644 Cunkebao/app/components-demo/page.tsx delete mode 100644 Cunkebao/app/components-docs/loading.tsx delete mode 100644 Cunkebao/app/components-docs/page.tsx delete mode 100644 Cunkebao/app/components/AIRewriteModal.tsx delete mode 100644 Cunkebao/app/components/AdaptiveLayout.tsx delete mode 100644 Cunkebao/app/components/ApiTester.tsx delete mode 100644 Cunkebao/app/components/AuthProvider.tsx delete mode 100644 Cunkebao/app/components/BindDouyinQRCode.tsx delete mode 100644 Cunkebao/app/components/BottomNav.tsx delete mode 100644 Cunkebao/app/components/Charts.tsx delete mode 100644 Cunkebao/app/components/ChatMessage.tsx delete mode 100644 Cunkebao/app/components/CircleSync/ContentSelector.tsx delete mode 100644 Cunkebao/app/components/CircleSync/DeviceSelector.tsx delete mode 100644 Cunkebao/app/components/CircleSync/TaskSetup.tsx delete mode 100644 Cunkebao/app/components/DeviceSelector.tsx delete mode 100644 Cunkebao/app/components/ErrorBoundary.tsx delete mode 100644 Cunkebao/app/components/FileUploader.tsx delete mode 100644 Cunkebao/app/components/LayoutWrapper.tsx delete mode 100644 Cunkebao/app/components/LoginErrorHandler.tsx delete mode 100644 Cunkebao/app/components/SideNav.tsx delete mode 100644 Cunkebao/app/components/SpeechToTextProcessor.tsx delete mode 100644 Cunkebao/app/components/TrafficTeamSettings.tsx delete mode 100644 Cunkebao/app/components/VideoTutorialButton.tsx delete mode 100644 Cunkebao/app/components/VoiceRecognition.tsx delete mode 100644 Cunkebao/app/components/acquisition/AcquisitionPlanChart.tsx delete mode 100644 Cunkebao/app/components/acquisition/DailyAcquisitionChart.tsx delete mode 100644 Cunkebao/app/components/acquisition/DeviceTreeChart.tsx delete mode 100644 Cunkebao/app/components/acquisition/ExpandableAcquisitionCard.tsx delete mode 100644 Cunkebao/app/components/acquisition/NewAcquisitionPlanForm.tsx delete mode 100644 Cunkebao/app/components/acquisition/ScenarioAcquisitionCard.tsx delete mode 100644 Cunkebao/app/components/auth-check.tsx delete mode 100644 Cunkebao/app/components/common/AddDeviceDialog.tsx delete mode 100644 Cunkebao/app/components/common/CardGrid.tsx delete mode 100644 Cunkebao/app/components/common/Charts.tsx delete mode 100644 Cunkebao/app/components/common/ContentSelector.tsx delete mode 100644 Cunkebao/app/components/common/DataTable.tsx delete mode 100644 Cunkebao/app/components/common/DeviceFilter.tsx delete mode 100644 Cunkebao/app/components/common/DeviceSelector.tsx delete mode 100644 Cunkebao/app/components/common/FileUploader.tsx delete mode 100644 Cunkebao/app/components/common/FormLayout.tsx delete mode 100644 Cunkebao/app/components/common/LazyLoad.tsx delete mode 100644 Cunkebao/app/components/common/NotificationSystem.tsx delete mode 100644 Cunkebao/app/components/common/PageHeader.tsx delete mode 100644 Cunkebao/app/components/common/SearchFilter.tsx delete mode 100644 Cunkebao/app/components/common/StatCard.tsx delete mode 100644 Cunkebao/app/components/common/TagManager.tsx delete mode 100644 Cunkebao/app/components/common/VirtualizedList.tsx delete mode 100644 Cunkebao/app/components/common/Wizard.tsx delete mode 100644 Cunkebao/app/components/device-grid.tsx delete mode 100644 Cunkebao/app/components/device-selection-dialog.tsx delete mode 100644 Cunkebao/app/components/poster-selector.tsx delete mode 100644 Cunkebao/app/components/traffic-pool-selector.tsx delete mode 100644 Cunkebao/app/components/ui-templates/card-grid.tsx delete mode 100644 Cunkebao/app/components/ui-templates/cards.tsx delete mode 100644 Cunkebao/app/components/ui-templates/form-layout.tsx delete mode 100644 Cunkebao/app/components/ui-templates/forms.tsx delete mode 100644 Cunkebao/app/components/ui-templates/index.tsx delete mode 100644 Cunkebao/app/components/ui-templates/layouts.tsx delete mode 100644 Cunkebao/app/components/ui-templates/page-header.tsx delete mode 100644 Cunkebao/app/components/ui-templates/responsive-table.tsx delete mode 100644 Cunkebao/app/components/ui-templates/selectors.tsx delete mode 100644 Cunkebao/app/components/ui-templates/stats.tsx delete mode 100644 Cunkebao/app/components/ui-templates/step-indicator.tsx delete mode 100644 Cunkebao/app/components/ui-templates/tables.tsx delete mode 100644 Cunkebao/app/components/ui/accordion.tsx delete mode 100644 Cunkebao/app/components/ui/avatar.tsx delete mode 100644 Cunkebao/app/components/ui/badge.tsx delete mode 100644 Cunkebao/app/components/ui/button.tsx delete mode 100644 Cunkebao/app/components/ui/calendar.tsx delete mode 100644 Cunkebao/app/components/ui/card.tsx delete mode 100644 Cunkebao/app/components/ui/chart.tsx delete mode 100644 Cunkebao/app/components/ui/checkbox.tsx delete mode 100644 Cunkebao/app/components/ui/collapsible.tsx delete mode 100644 Cunkebao/app/components/ui/dialog.tsx delete mode 100644 Cunkebao/app/components/ui/dropdown-menu.tsx delete mode 100644 Cunkebao/app/components/ui/input.tsx delete mode 100644 Cunkebao/app/components/ui/label.tsx delete mode 100644 Cunkebao/app/components/ui/pagination.tsx delete mode 100644 Cunkebao/app/components/ui/popover.tsx delete mode 100644 Cunkebao/app/components/ui/preview-dialog.tsx delete mode 100644 Cunkebao/app/components/ui/progress.tsx delete mode 100644 Cunkebao/app/components/ui/radio-group.tsx delete mode 100644 Cunkebao/app/components/ui/scroll-area.tsx delete mode 100644 Cunkebao/app/components/ui/select.tsx delete mode 100644 Cunkebao/app/components/ui/skeleton.tsx delete mode 100644 Cunkebao/app/components/ui/step-indicator.tsx delete mode 100644 Cunkebao/app/components/ui/steps.tsx delete mode 100644 Cunkebao/app/components/ui/switch.tsx delete mode 100644 Cunkebao/app/components/ui/table.tsx delete mode 100644 Cunkebao/app/components/ui/tabs.tsx delete mode 100644 Cunkebao/app/components/ui/textarea.tsx delete mode 100644 Cunkebao/app/components/ui/toast.ts delete mode 100644 Cunkebao/app/components/ui/toast.tsx delete mode 100644 Cunkebao/app/components/ui/tooltip.tsx delete mode 100644 Cunkebao/app/components/ui/use-toast.ts delete mode 100644 Cunkebao/app/contact-import/page.tsx delete mode 100644 Cunkebao/app/content/[id]/edit/page.tsx delete mode 100644 Cunkebao/app/content/[id]/materials/edit/[materialId]/page.tsx delete mode 100644 Cunkebao/app/content/[id]/materials/new/page.tsx delete mode 100644 Cunkebao/app/content/[id]/materials/page.tsx delete mode 100644 Cunkebao/app/content/[id]/page.tsx delete mode 100644 Cunkebao/app/content/loading.tsx delete mode 100644 Cunkebao/app/content/new/device-selector.tsx delete mode 100644 Cunkebao/app/content/new/page.tsx delete mode 100644 Cunkebao/app/content/new/steps/basic-settings.tsx delete mode 100644 Cunkebao/app/content/new/steps/content-settings.tsx delete mode 100644 Cunkebao/app/content/new/steps/preview-confirm.tsx delete mode 100644 Cunkebao/app/content/new/steps/source-selection.tsx delete mode 100644 Cunkebao/app/content/new/steps/tag-settings.tsx delete mode 100644 Cunkebao/app/content/page.tsx delete mode 100644 Cunkebao/app/devices/[id]/page.tsx delete mode 100644 Cunkebao/app/devices/loading.tsx delete mode 100644 Cunkebao/app/devices/page.tsx delete mode 100644 Cunkebao/app/globals.css delete mode 100644 Cunkebao/app/hooks/useDeviceStatusPolling.ts delete mode 100644 Cunkebao/app/layout.tsx delete mode 100644 Cunkebao/app/lib/date-utils.ts delete mode 100644 Cunkebao/app/lib/toast.ts delete mode 100644 Cunkebao/app/lib/utils.ts delete mode 100644 Cunkebao/app/login/page.tsx delete mode 100644 Cunkebao/app/orders/submit/[planId]/page.tsx delete mode 100644 Cunkebao/app/page.tsx delete mode 100644 Cunkebao/app/plans/new/loading.tsx delete mode 100644 Cunkebao/app/plans/new/page.tsx delete mode 100644 Cunkebao/app/plans/new/steps/BasicSettings.tsx delete mode 100644 Cunkebao/app/plans/new/steps/FriendRequestSettings.tsx delete mode 100644 Cunkebao/app/plans/new/steps/MessageSettings.tsx delete mode 100644 Cunkebao/app/profile/devices/loading.tsx delete mode 100644 Cunkebao/app/profile/devices/page.tsx delete mode 100644 Cunkebao/app/profile/page.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/[id]/page.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/acquired/page.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/added/page.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/api/page.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/devices/loading.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/devices/page.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/edit/[id]/page.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/page.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/traffic/loading.tsx delete mode 100644 Cunkebao/app/scenarios/[channel]/traffic/page.tsx delete mode 100644 Cunkebao/app/scenarios/api/page.tsx delete mode 100644 Cunkebao/app/scenarios/api/route.ts delete mode 100644 Cunkebao/app/scenarios/douyin/page.tsx delete mode 100644 Cunkebao/app/scenarios/haibao/edit/[id]/page.tsx delete mode 100644 Cunkebao/app/scenarios/loading.tsx delete mode 100644 Cunkebao/app/scenarios/new/loading.tsx delete mode 100644 Cunkebao/app/scenarios/new/page.tsx delete mode 100644 Cunkebao/app/scenarios/new/steps/BasicSettings.tsx delete mode 100644 Cunkebao/app/scenarios/new/steps/FriendRequestSettings.tsx delete mode 100644 Cunkebao/app/scenarios/new/steps/MessageSettings.tsx delete mode 100644 Cunkebao/app/scenarios/new/steps/PosterEditor.tsx delete mode 100644 Cunkebao/app/scenarios/new/steps/TrafficChannelSettings delete mode 100644 Cunkebao/app/scenarios/page.tsx delete mode 100644 Cunkebao/app/scenarios/payment/[id]/page.tsx delete mode 100644 Cunkebao/app/scenarios/payment/[id]/payments/loading.tsx delete mode 100644 Cunkebao/app/scenarios/payment/[id]/payments/page.tsx delete mode 100644 Cunkebao/app/scenarios/payment/new/page.tsx delete mode 100644 Cunkebao/app/scenarios/payment/page.tsx delete mode 100644 Cunkebao/app/scenarios/payment/stats/page.tsx delete mode 100644 Cunkebao/app/scenarios/phone/acquired/loading.tsx delete mode 100644 Cunkebao/app/scenarios/phone/acquired/page.tsx delete mode 100644 Cunkebao/app/scenarios/phone/added/loading.tsx delete mode 100644 Cunkebao/app/scenarios/phone/added/page.tsx delete mode 100644 Cunkebao/app/scenarios/phone/devices/page.tsx delete mode 100644 Cunkebao/app/scenarios/phone/edit/[id]/page.tsx delete mode 100644 Cunkebao/app/scenarios/phone/new/basic/page.tsx delete mode 100644 Cunkebao/app/scenarios/phone/new/components/AIFilterSettings.tsx delete mode 100644 Cunkebao/app/scenarios/phone/new/components/DeviceConfigDialog.tsx delete mode 100644 Cunkebao/app/scenarios/phone/new/components/DistributionSettings.tsx delete mode 100644 Cunkebao/app/scenarios/phone/new/components/FollowUpSettings.tsx delete mode 100644 Cunkebao/app/scenarios/phone/new/components/PhoneImportDialog.tsx delete mode 100644 Cunkebao/app/scenarios/phone/new/components/RedPacketSettings.tsx delete mode 100644 Cunkebao/app/scenarios/phone/new/page.tsx delete mode 100644 Cunkebao/app/scenarios/phone/page.tsx delete mode 100644 Cunkebao/app/scenarios/weixinqun/page.tsx delete mode 100644 Cunkebao/app/traffic-pool/components/analytics-dashboard.tsx delete mode 100644 Cunkebao/app/traffic-pool/components/date-range-picker.tsx delete mode 100644 Cunkebao/app/traffic-pool/components/multi-device-selector.tsx delete mode 100644 Cunkebao/app/traffic-pool/components/pool-management.tsx delete mode 100644 Cunkebao/app/traffic-pool/components/pool-usage-chart.tsx delete mode 100644 Cunkebao/app/traffic-pool/loading.tsx delete mode 100644 Cunkebao/app/traffic-pool/page.tsx delete mode 100644 Cunkebao/app/types/wechat.ts delete mode 100644 Cunkebao/app/wechat-accounts/[id]/page.tsx delete mode 100644 Cunkebao/app/wechat-accounts/loading.tsx delete mode 100644 Cunkebao/app/wechat-accounts/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/[id]/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/components/analysis-settings.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/components/confirm-analysis.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/components/device-selection.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/components/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/create/components/basic-settings.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/create/components/target-selection.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/create/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/new/components/basic-settings.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/new/components/target-selection.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/new/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-analyzer/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-assistant/knowledge-base/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-assistant/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-strategy/[id]/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-strategy/components/confirm-strategy.tsx delete mode 100644 Cunkebao/app/workspace/ai-strategy/components/execution-setup.tsx delete mode 100644 Cunkebao/app/workspace/ai-strategy/components/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/ai-strategy/components/strategy-selection.tsx delete mode 100644 Cunkebao/app/workspace/ai-strategy/components/traffic-pool-selection.tsx delete mode 100644 Cunkebao/app/workspace/ai-strategy/new/page.tsx delete mode 100644 Cunkebao/app/workspace/ai-strategy/page.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/StepByStepPlanForm.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/auto-group-service.ts delete mode 100644 Cunkebao/app/workspace/auto-group/components/columns.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/data-table.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/device-selection.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/device-selector.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/group-assistant.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/group-creation-progress.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/group-preview.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/group-settings.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/new-plan-form.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/tag-selection.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/traffic-pool-selector.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/components/wechat-account-selector.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/loading.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/new/loading.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/new/page.tsx delete mode 100644 Cunkebao/app/workspace/auto-group/page.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/[id]/edit/page.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/[id]/page.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/audience-tags.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/basic-settings.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/device-selection-dialog.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/device-selection.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/like-config.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/like-rules.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/tag-selector.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/components/time-settings.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/loading.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/new/loading.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/new/page.tsx delete mode 100644 Cunkebao/app/workspace/auto-like/page.tsx delete mode 100644 Cunkebao/app/workspace/group-push/[id]/edit/page.tsx delete mode 100644 Cunkebao/app/workspace/group-push/components/basic-settings.tsx delete mode 100644 Cunkebao/app/workspace/group-push/components/content-selector.tsx delete mode 100644 Cunkebao/app/workspace/group-push/components/friend-selector.tsx delete mode 100644 Cunkebao/app/workspace/group-push/components/group-selector.tsx delete mode 100644 Cunkebao/app/workspace/group-push/components/message-editor.tsx delete mode 100644 Cunkebao/app/workspace/group-push/components/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/group-push/loading.tsx delete mode 100644 Cunkebao/app/workspace/group-push/new/loading.tsx delete mode 100644 Cunkebao/app/workspace/group-push/new/page.tsx delete mode 100644 Cunkebao/app/workspace/group-push/page.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/auto-group/loading.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/auto-group/page.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/components/auto-group-creator.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/components/basic-settings.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/components/content-selector.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/components/group-selector.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/components/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/loading.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/new/loading.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/new/page.tsx delete mode 100644 Cunkebao/app/workspace/group-sync/page.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/[id]/edit/page.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/[id]/edit/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/[id]/edit/steps/basic-settings.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/[id]/edit/steps/content-library-selection.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/[id]/edit/steps/device-selection.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/[id]/page.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/[id]/view/page.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/components/basic-settings.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/components/content-library-selection-dialog.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/components/content-selector.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/components/content-viewer.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/components/device-selection-dialog.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/components/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/components/tag-editor.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/new/page.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/new/steps/BasicSettings.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/new/steps/ContentSelector.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/new/steps/DeviceSelector.tsx delete mode 100644 Cunkebao/app/workspace/moments-sync/page.tsx delete mode 100644 Cunkebao/app/workspace/page.tsx delete mode 100644 Cunkebao/app/workspace/pricing/edit/[id]/page.tsx delete mode 100644 Cunkebao/app/workspace/pricing/new/page.tsx delete mode 100644 Cunkebao/app/workspace/pricing/page.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/[id]/edit/page.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/[id]/loading.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/[id]/page.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/components/distribution-rule-card.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/components/distribution-rule-form.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/components/keyword-selector.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/components/traffic-pool-selector.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/loading.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/new/components/basic-info-step.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/new/components/step-indicator.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/new/components/target-settings-step.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/new/components/traffic-pool-step.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/new/loading.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/new/page.tsx delete mode 100644 Cunkebao/app/workspace/traffic-distribution/page.tsx delete mode 100644 Cunkebao/app/workspace/traffic-pricing/loading.tsx delete mode 100644 Cunkebao/app/workspace/traffic-pricing/page.tsx delete mode 100644 Cunkebao/app/开发文档.md delete mode 100644 Cunkebao/components.json delete mode 100644 Cunkebao/components/AIAssistant.tsx delete mode 100644 Cunkebao/components/AuthCheck.tsx delete mode 100644 Cunkebao/components/BindDouyinQRCode.tsx delete mode 100644 Cunkebao/components/Charts.tsx delete mode 100644 Cunkebao/components/ClientOnly.tsx delete mode 100644 Cunkebao/components/ExcelImporter.tsx delete mode 100644 Cunkebao/components/ImeiDisplay.tsx delete mode 100644 Cunkebao/components/TrafficTeamSettings.tsx delete mode 100644 Cunkebao/components/VideoTutorialButton.tsx delete mode 100644 Cunkebao/components/WechatFriendSelector.tsx delete mode 100644 Cunkebao/components/WechatGroupMemberSelector.tsx delete mode 100644 Cunkebao/components/WechatGroupSelector.tsx delete mode 100644 Cunkebao/components/acquisition/ExpandableAcquisitionCard.tsx delete mode 100644 Cunkebao/components/acquisition/PlanSettingsDialog.tsx delete mode 100644 Cunkebao/components/api-documentation-tooltip.tsx delete mode 100644 Cunkebao/components/common/DeviceSelector.tsx delete mode 100644 Cunkebao/components/device-grid.tsx delete mode 100644 Cunkebao/components/device-table.tsx delete mode 100644 Cunkebao/components/icons/apple-icon.tsx delete mode 100644 Cunkebao/components/icons/wechat-icon.tsx delete mode 100644 Cunkebao/components/login-form.tsx delete mode 100644 Cunkebao/components/poster-selector.tsx delete mode 100644 Cunkebao/components/settings-dropdown.tsx delete mode 100644 Cunkebao/components/theme-provider.tsx delete mode 100644 Cunkebao/components/ui/accordion.tsx delete mode 100644 Cunkebao/components/ui/alert-dialog.tsx delete mode 100644 Cunkebao/components/ui/alert.tsx delete mode 100644 Cunkebao/components/ui/aspect-ratio.tsx delete mode 100644 Cunkebao/components/ui/avatar.tsx delete mode 100644 Cunkebao/components/ui/badge.tsx delete mode 100644 Cunkebao/components/ui/breadcrumb.tsx delete mode 100644 Cunkebao/components/ui/button.tsx delete mode 100644 Cunkebao/components/ui/calendar.tsx delete mode 100644 Cunkebao/components/ui/card.tsx delete mode 100644 Cunkebao/components/ui/carousel.tsx delete mode 100644 Cunkebao/components/ui/chart.tsx delete mode 100644 Cunkebao/components/ui/checkbox.tsx delete mode 100644 Cunkebao/components/ui/code.tsx delete mode 100644 Cunkebao/components/ui/collapsible.tsx delete mode 100644 Cunkebao/components/ui/command.tsx delete mode 100644 Cunkebao/components/ui/context-menu.tsx delete mode 100644 Cunkebao/components/ui/date-picker.tsx delete mode 100644 Cunkebao/components/ui/date-range-picker.tsx delete mode 100644 Cunkebao/components/ui/dialog.tsx delete mode 100644 Cunkebao/components/ui/drawer.tsx delete mode 100644 Cunkebao/components/ui/dropdown-menu.tsx delete mode 100644 Cunkebao/components/ui/form.tsx delete mode 100644 Cunkebao/components/ui/hover-card.tsx delete mode 100644 Cunkebao/components/ui/input-otp.tsx delete mode 100644 Cunkebao/components/ui/input.tsx delete mode 100644 Cunkebao/components/ui/label.tsx delete mode 100644 Cunkebao/components/ui/menubar.tsx delete mode 100644 Cunkebao/components/ui/navigation-menu.tsx delete mode 100644 Cunkebao/components/ui/pagination.tsx delete mode 100644 Cunkebao/components/ui/popover.tsx delete mode 100644 Cunkebao/components/ui/preview-dialog.tsx delete mode 100644 Cunkebao/components/ui/progress.tsx delete mode 100644 Cunkebao/components/ui/radio-group.tsx delete mode 100644 Cunkebao/components/ui/resizable.tsx delete mode 100644 Cunkebao/components/ui/scroll-area.tsx delete mode 100644 Cunkebao/components/ui/select.tsx delete mode 100644 Cunkebao/components/ui/separator.tsx delete mode 100644 Cunkebao/components/ui/sheet.tsx delete mode 100644 Cunkebao/components/ui/sidebar.tsx delete mode 100644 Cunkebao/components/ui/skeleton.tsx delete mode 100644 Cunkebao/components/ui/slider.tsx delete mode 100644 Cunkebao/components/ui/sonner.tsx delete mode 100644 Cunkebao/components/ui/steps.tsx delete mode 100644 Cunkebao/components/ui/switch.tsx delete mode 100644 Cunkebao/components/ui/table.tsx delete mode 100644 Cunkebao/components/ui/tabs.tsx delete mode 100644 Cunkebao/components/ui/textarea.tsx delete mode 100644 Cunkebao/components/ui/toast.ts delete mode 100644 Cunkebao/components/ui/toast.tsx delete mode 100644 Cunkebao/components/ui/toaster.tsx delete mode 100644 Cunkebao/components/ui/toggle-group.tsx delete mode 100644 Cunkebao/components/ui/toggle.tsx delete mode 100644 Cunkebao/components/ui/tooltip.tsx delete mode 100644 Cunkebao/components/ui/use-mobile.tsx delete mode 100644 Cunkebao/components/ui/use-toast.ts rename {nkebao => Cunkebao}/craco.config.js (100%) delete mode 100644 Cunkebao/docs/API对接指南.md delete mode 100644 Cunkebao/docs/README.md delete mode 100644 Cunkebao/docs/api-guide.ts delete mode 100644 Cunkebao/docs/api-guide.tsx delete mode 100644 Cunkebao/docs/home/README.md delete mode 100644 Cunkebao/docs/home/data-overview.md delete mode 100644 Cunkebao/docs/home/quick-access.md delete mode 100644 Cunkebao/docs/home/recent-activities.md delete mode 100644 Cunkebao/docs/scenarios/README.md delete mode 100644 Cunkebao/docs/scenarios/douyin-acquisition.md delete mode 100644 Cunkebao/docs/scenarios/new-scenario.md delete mode 100644 Cunkebao/docs/scenarios/phone-acquisition.md delete mode 100644 Cunkebao/docs/scenarios/poster-acquisition.md delete mode 100644 Cunkebao/docs/workspace/README.md delete mode 100644 Cunkebao/docs/workspace/auto-group.md delete mode 100644 Cunkebao/docs/workspace/auto-like.md delete mode 100644 Cunkebao/docs/workspace/group-push.md delete mode 100644 Cunkebao/docs/workspace/group-sync.md delete mode 100644 Cunkebao/docs/workspace/moments-sync.md delete mode 100644 Cunkebao/docs/workspace/traffic-distribution.md delete mode 100644 Cunkebao/hooks/use-debounce.ts delete mode 100644 Cunkebao/hooks/use-mobile.tsx delete mode 100644 Cunkebao/hooks/use-toast.ts delete mode 100644 Cunkebao/hooks/useAuth.ts delete mode 100644 Cunkebao/hooks/useDeviceStatusPolling.ts delete mode 100644 Cunkebao/lib/actions/auth-actions.ts delete mode 100644 Cunkebao/lib/api.ts delete mode 100644 Cunkebao/lib/api/auth.ts delete mode 100644 Cunkebao/lib/api/client.ts delete mode 100644 Cunkebao/lib/api/config.ts delete mode 100644 Cunkebao/lib/api/content.ts delete mode 100644 Cunkebao/lib/api/dashboard.ts delete mode 100644 Cunkebao/lib/api/devices.ts delete mode 100644 Cunkebao/lib/api/github-integration.ts delete mode 100644 Cunkebao/lib/api/index.ts delete mode 100644 Cunkebao/lib/api/scenarios-mobile.ts delete mode 100644 Cunkebao/lib/api/scenarios.ts delete mode 100644 Cunkebao/lib/api/traffic.ts delete mode 100644 Cunkebao/lib/api/users.ts delete mode 100644 Cunkebao/lib/api/wechat.ts delete mode 100644 Cunkebao/lib/api/workspace.ts delete mode 100644 Cunkebao/lib/http-interceptors.ts delete mode 100644 Cunkebao/lib/migration/github-adapter.ts delete mode 100644 Cunkebao/lib/migration/integration-checker.ts delete mode 100644 Cunkebao/lib/migration/migration-guide.ts delete mode 100644 Cunkebao/lib/toast.ts delete mode 100644 Cunkebao/lib/tutorials.ts delete mode 100644 Cunkebao/lib/utils.ts delete mode 100644 Cunkebao/next.config.js delete mode 100644 Cunkebao/next.config.mjs delete mode 100644 Cunkebao/pnpm-lock.yaml rename {nkebao => Cunkebao}/postcss.config.js (100%) delete mode 100644 Cunkebao/postcss.config.mjs delete mode 100644 Cunkebao/public/device-management-design.png delete mode 100644 Cunkebao/public/diverse-avatars.png delete mode 100644 Cunkebao/public/diverse-group-avatars.png rename {nkebao => Cunkebao}/public/favicon.ico (100%) rename {nkebao => Cunkebao}/public/index.html (100%) delete mode 100644 Cunkebao/public/interface-design.png rename {nkebao => Cunkebao}/public/logo192.png (100%) rename {nkebao => Cunkebao}/public/logo512.png (100%) rename {nkebao => Cunkebao}/public/manifest.json (100%) delete mode 100644 Cunkebao/public/mobile-device-management.png delete mode 100644 Cunkebao/public/mobile-traffic-pool-design.png delete mode 100644 Cunkebao/public/placeholder-logo.png delete mode 100644 Cunkebao/public/placeholder-logo.svg delete mode 100644 Cunkebao/public/placeholder-user.jpg delete mode 100644 Cunkebao/public/placeholder.jpg delete mode 100644 Cunkebao/public/placeholder.svg delete mode 100644 Cunkebao/public/profile-design.png delete mode 100644 Cunkebao/public/profile-functions.png rename {nkebao => Cunkebao}/public/robots.txt (100%) delete mode 100644 Cunkebao/public/scenario-cards.png delete mode 100644 Cunkebao/public/wechat-detail.png delete mode 100644 Cunkebao/public/wechat-management-design.png delete mode 100644 Cunkebao/public/workspace-design.png delete mode 100644 Cunkebao/public/workspace-stats.png delete mode 100644 Cunkebao/public/场景获客.png delete mode 100644 Cunkebao/public/订单导入模板.csv delete mode 100644 Cunkebao/scripts/api-test.sh delete mode 100644 Cunkebao/scripts/migration-setup.sh rename {nkebao => Cunkebao}/scripts/update-page-headers.js (100%) rename {nkebao => Cunkebao}/src/App.css (100%) rename {nkebao => Cunkebao}/src/App.test.tsx (100%) rename {nkebao => Cunkebao}/src/App.tsx (100%) rename {nkebao => Cunkebao}/src/api/auth.ts (100%) rename {nkebao => Cunkebao}/src/api/autoLike.ts (100%) rename {nkebao => Cunkebao}/src/api/content.ts (100%) rename {nkebao => Cunkebao}/src/api/devices.ts (100%) rename {nkebao => Cunkebao}/src/api/groupPush.ts (100%) rename {nkebao => Cunkebao}/src/api/index.ts (100%) rename {nkebao => Cunkebao}/src/api/interceptors.ts (100%) rename {nkebao => Cunkebao}/src/api/momentsSync.ts (100%) rename {nkebao => Cunkebao}/src/api/request.ts (100%) rename {nkebao => Cunkebao}/src/api/scenarios.ts (100%) rename {nkebao => Cunkebao}/src/api/trafficDistribution.ts (100%) rename {nkebao => Cunkebao}/src/api/upload.ts (100%) rename {nkebao => Cunkebao}/src/api/utils.ts (100%) rename {nkebao => Cunkebao}/src/api/wechat-accounts.ts (100%) rename {nkebao => Cunkebao}/src/components/BackButton.tsx (100%) rename {nkebao => Cunkebao}/src/components/BottomNav.tsx (100%) rename {nkebao => Cunkebao}/src/components/ContentLibrarySelectionDialog.tsx (100%) rename {nkebao => Cunkebao}/src/components/DeviceSelection.tsx (100%) rename {nkebao => Cunkebao}/src/components/DeviceSelectionDialog.tsx (100%) rename {nkebao => Cunkebao}/src/components/FriendSelection.tsx (100%) rename {nkebao => Cunkebao}/src/components/GroupSelection.tsx (100%) rename {nkebao => Cunkebao}/src/components/Layout.css (100%) rename {nkebao => Cunkebao}/src/components/Layout.tsx (100%) rename {nkebao => Cunkebao}/src/components/LayoutWrapper.tsx (100%) rename {nkebao => Cunkebao}/src/components/PageHeader.tsx (100%) rename {nkebao => Cunkebao}/src/components/ProtectedRoute.tsx (100%) rename {nkebao => Cunkebao}/src/components/ScenarioAcquisitionCard.tsx (100%) rename {nkebao => Cunkebao}/src/components/TestComponent.tsx (100%) rename {nkebao => Cunkebao}/src/components/ThrottledButton.tsx (100%) rename {nkebao => Cunkebao}/src/components/TrafficPoolSelection.tsx (100%) rename {nkebao => Cunkebao}/src/components/UnifiedHeader.tsx (100%) rename {nkebao => Cunkebao}/src/components/UploadImage.tsx (100%) rename {nkebao => Cunkebao}/src/components/UploadVideo.tsx (100%) rename {nkebao => Cunkebao}/src/components/icons/AppleIcon.tsx (100%) rename {nkebao => Cunkebao}/src/components/icons/EyeIcon.tsx (100%) rename {nkebao => Cunkebao}/src/components/icons/WeChatIcon.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/alert.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/avatar.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/badge.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/button.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/card.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/checkbox.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/dialog.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/dropdown-menu.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/input.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/label.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/progress.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/radio-group.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/scroll-area.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/select.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/separator.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/skeleton.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/switch.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/table.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/tabs.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/textarea.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/toast.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/tooltip.tsx (100%) rename {nkebao => Cunkebao}/src/components/ui/use-toast.ts (100%) rename {nkebao => Cunkebao}/src/contexts/AuthContext.tsx (100%) rename {nkebao => Cunkebao}/src/contexts/WechatAccountContext.tsx (100%) rename {nkebao => Cunkebao}/src/hooks/use-debounce.ts (100%) rename {nkebao => Cunkebao}/src/hooks/useAuthGuard.ts (100%) rename {nkebao => Cunkebao}/src/hooks/useBackNavigation.ts (100%) rename {nkebao => Cunkebao}/src/hooks/useThrottledRequest.ts (100%) rename {nkebao => Cunkebao}/src/index.css (100%) rename {nkebao => Cunkebao}/src/index.tsx (100%) rename {nkebao => Cunkebao}/src/logo.svg (100%) rename {nkebao => Cunkebao}/src/pages/Home.tsx (100%) rename {nkebao => Cunkebao}/src/pages/contact-import/ContactImport.tsx (100%) rename {nkebao => Cunkebao}/src/pages/content/Content.tsx (100%) rename {nkebao => Cunkebao}/src/pages/content/NewContent.tsx (100%) rename {nkebao => Cunkebao}/src/pages/content/materials/List.tsx (100%) rename {nkebao => Cunkebao}/src/pages/content/materials/New.tsx (100%) rename {nkebao => Cunkebao}/src/pages/devices/DeviceDetail.tsx (100%) rename {nkebao => Cunkebao}/src/pages/devices/Devices.tsx (100%) rename {nkebao => Cunkebao}/src/pages/login/Login.tsx (100%) rename {nkebao => Cunkebao}/src/pages/orders/Orders.tsx (100%) rename {nkebao => Cunkebao}/src/pages/plans/PlanDetail.tsx (100%) rename {nkebao => Cunkebao}/src/pages/plans/Plans.tsx (100%) rename {nkebao => Cunkebao}/src/pages/profile/Profile.tsx (100%) rename {nkebao => Cunkebao}/src/pages/scenarios/ScenarioList.tsx (100%) rename {nkebao => Cunkebao}/src/pages/scenarios/Scenarios.tsx (100%) rename {nkebao => Cunkebao}/src/pages/scenarios/new/page.tsx (100%) rename {nkebao => Cunkebao}/src/pages/scenarios/new/steps/BasicSettings.tsx (100%) rename {nkebao => Cunkebao}/src/pages/scenarios/new/steps/FriendRequestSettings.tsx (100%) rename {nkebao => Cunkebao}/src/pages/scenarios/new/steps/MessageSettings.tsx (100%) rename Cunkebao/{app/plans => src/pages/scenarios}/new/steps/TagSettings.tsx (100%) rename {nkebao => Cunkebao}/src/pages/traffic-pool/TrafficPool.tsx (100%) rename {nkebao => Cunkebao}/src/pages/traffic-pool/TrafficPoolDetail.tsx (100%) rename {nkebao => Cunkebao}/src/pages/wechat-accounts/WechatAccountDetail.tsx (100%) rename {nkebao => Cunkebao}/src/pages/wechat-accounts/WechatAccounts.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/Workspace.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/ai-assistant/AIAssistant.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/auto-group/AutoGroup.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/auto-group/Detail.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/auto-like/AutoLike.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/auto-like/AutoLikeDetail.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/auto-like/NewAutoLike.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/group-push/GroupPush.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/group-push/components/BasicSettings.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/group-push/components/ContentSelector.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/group-push/components/GroupSelector.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/group-push/components/StepIndicator.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/group-push/new.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/moments-sync/Detail.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/moments-sync/MomentsSync.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/moments-sync/index.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/moments-sync/new.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/traffic-distribution/Detail.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/traffic-distribution/NewDistribution.tsx (100%) rename {nkebao => Cunkebao}/src/pages/workspace/traffic-distribution/TrafficDistribution.tsx (100%) rename {nkebao => Cunkebao}/src/react-app-env.d.ts (100%) rename {nkebao => Cunkebao}/src/reportWebVitals.ts (100%) rename {nkebao => Cunkebao}/src/setupTests.ts (100%) rename {nkebao => Cunkebao}/src/types/auto-like.ts (100%) rename {nkebao => Cunkebao}/src/types/common.ts (100%) rename {nkebao => Cunkebao}/src/types/device.ts (100%) rename {nkebao => Cunkebao}/src/types/moments-sync.ts (100%) rename Cunkebao/{ => src}/types/wechat.ts (100%) rename {nkebao => Cunkebao}/src/utils/index.ts (100%) delete mode 100644 Cunkebao/styles/globals.css delete mode 100644 Cunkebao/types/acquisition.ts delete mode 100644 Cunkebao/types/auto-group.ts delete mode 100644 Cunkebao/types/common.ts delete mode 100644 Cunkebao/types/content-library.ts delete mode 100644 Cunkebao/types/content.ts delete mode 100644 Cunkebao/types/device.ts delete mode 100644 Cunkebao/types/group-push.ts delete mode 100644 Cunkebao/types/group-sync.ts delete mode 100644 Cunkebao/types/scenario.ts delete mode 100644 Cunkebao/types/traffic.ts delete mode 100644 Cunkebao/types/tutorial.ts delete mode 100644 Cunkebao/types/wechat-account.ts delete mode 100644 Cunkebao/types/xlsx.d.ts delete mode 100644 nkebao/.gitignore delete mode 100644 nkebao/README.md delete mode 100644 nkebao/package-lock.json delete mode 100644 nkebao/package.json delete mode 100644 nkebao/src/pages/scenarios/new/steps/TagSettings.tsx delete mode 100644 nkebao/src/types/wechat.ts delete mode 100644 nkebao/tailwind.config.js delete mode 100644 nkebao/tsconfig.json delete mode 100644 nkebao/yarn.lock diff --git a/Cunkebao/.babelrc b/Cunkebao/.babelrc deleted file mode 100644 index 1ff94f7ed..000000000 --- a/Cunkebao/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["next/babel"] -} diff --git a/Cunkebao/.eslintrc.json b/Cunkebao/.eslintrc.json deleted file mode 100644 index d7ffa2789..000000000 --- a/Cunkebao/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "root": true, - "extends": [ - "next/core-web-vitals", - "eslint:recommended", - "plugin:@typescript-eslint/recommended" - ], - "plugins": ["@typescript-eslint"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2020, - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/no-unused-vars": ["warn"], - "react/react-in-jsx-scope": "off" - } -} \ No newline at end of file diff --git a/Cunkebao/.gitignore b/Cunkebao/.gitignore index f650315f3..4d29575de 100644 --- a/Cunkebao/.gitignore +++ b/Cunkebao/.gitignore @@ -2,26 +2,22 @@ # dependencies /node_modules +/.pnp +.pnp.js -# next.js -/.next/ -/out/ +# testing +/coverage # production /build -# debug +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + npm-debug.log* yarn-debug.log* yarn-error.log* -.pnpm-debug.log* - -# env files -.env* - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts \ No newline at end of file diff --git a/Cunkebao/.htaccess b/Cunkebao/.htaccess deleted file mode 100644 index 0c54fb9f0..000000000 --- a/Cunkebao/.htaccess +++ /dev/null @@ -1 +0,0 @@ -# 请将伪静态规则或自定义Apache配置填写到此处 diff --git a/Cunkebao/.well-known/acme-challenge/nKNDFrnOs9-cf7FZzW7Cg4MpIxhtE8pZ1etiT_7NPWA b/Cunkebao/.well-known/acme-challenge/nKNDFrnOs9-cf7FZzW7Cg4MpIxhtE8pZ1etiT_7NPWA deleted file mode 100644 index 2f056a639..000000000 --- a/Cunkebao/.well-known/acme-challenge/nKNDFrnOs9-cf7FZzW7Cg4MpIxhtE8pZ1etiT_7NPWA +++ /dev/null @@ -1 +0,0 @@ -nKNDFrnOs9-cf7FZzW7Cg4MpIxhtE8pZ1etiT_7NPWA.2wKeISBpPoGcCt72TdgVrBMxtnnieXof2OZkRdHKCJI \ No newline at end of file diff --git a/Cunkebao/README.md b/Cunkebao/README.md index 0532c5f34..be60268f4 100644 --- a/Cunkebao/README.md +++ b/Cunkebao/README.md @@ -1,73 +1,123 @@ -# 存客宝 - 智能获客管理平台 +# 内客宝 - 智能获客管理平台 ## 📋 项目简介 -存客宝是一个专业的微信获客和流量管理平台,提供智能化的客户获取、管理和运营解决方案。平台集成了多种自动化工具,帮助企业高效管理微信营销活动。 +内客宝是一个专业的微信获客和流量管理平台,基于 React 技术栈构建。平台提供智能化的客户获取、管理和运营解决方案,集成了多种自动化工具,帮助企业高效管理微信营销活动。 -## 🚀 技术栈 +## 🚀 技术栈详解 -### 前端框架 -- **Next.js 15.3.5** - React 全栈框架,支持 SSR/SSG -- **React 19.1.0** - 用户界面库 -- **TypeScript 5** - 类型安全的 JavaScript 超集 +### 核心框架 +- **React 18.2.0** - 现代化的用户界面库 +- **TypeScript 4.9.5** - 类型安全的 JavaScript 超集 +- **Create React App (CRA) 5.0.1** - React 应用脚手架 +- **React Router DOM 6.20.0** - 客户端路由管理 + +### 构建工具 +- **CRACO 7.1.0** - Create React App Configuration Override + - 支持自定义 webpack 配置 + - 路径别名配置 + - 构建优化 ### UI 组件库 -- **shadcn/ui** - 基于 Radix UI 的现代化组件库 +- **Radix UI** - 无样式的可访问组件库 + - 完整的组件生态系统(30+ 组件) + - 优秀的无障碍访问支持 + - 高度可定制 - **Tailwind CSS 3.4.17** - 实用优先的 CSS 框架 -- **Lucide React** - 精美的图标库 -- **Framer Motion** - 动画库 + - 响应式设计支持 + - 自定义主题配置 + - 原子化 CSS 类 -### 状态管理与表单 -- **React Hook Form** - 高性能表单库 -- **Zod** - TypeScript 优先的模式验证 -- **@hookform/resolvers** - 表单验证解析器 +### 图标和样式 +- **Lucide React 0.454.0** - 精美的图标库 +- **Tailwind CSS Animate** - CSS 动画库 +- **Class Variance Authority** - 组件变体管理 +- **Tailwind Merge** - Tailwind 类名合并工具 + +### 状态管理和表单 +- **React Hook Form 7.54.1** - 高性能表单库 +- **Zod 3.24.1** - TypeScript 优先的模式验证 +- **@hookform/resolvers 3.9.1** - 表单验证解析器 ### 数据可视化 - **Recharts** - 基于 React 的图表库 -- **Chart.js** - 灵活的图表库 +- **Chart.js 4.5.0** - 灵活的图表库 +- **@ant-design/plots** - Ant Design 图表组件 + +### HTTP 请求和数据处理 +- **Axios 1.6.0** - HTTP 客户端 +- **Crypto-js 4.2.0** - 加密库 +- **Date-fns** - 日期处理库 +- **XLSX 0.18.5** - Excel 文件处理 + +### 通知和反馈 +- **React Hot Toast 2.5.2** - 轻量级通知库 +- **Sonner 1.7.4** - 现代化 Toast 组件 + +### 高级组件 +- **@tanstack/react-table** - 功能强大的表格组件 +- **Embla Carousel React 8.5.1** - 轮播组件 +- **React Resizable Panels 2.1.7** - 可调整大小的面板 +- **Vaul 0.9.6** - 抽屉组件 +- **Input OTP 1.4.1** - OTP 输入组件 +- **React Day Picker** - 日期选择器 ### 开发工具 +- **PostCSS 8** - CSS 后处理器 +- **Autoprefixer 10.4.20** - CSS 前缀自动添加 - **ESLint** - 代码质量检查 -- **PostCSS** - CSS 后处理器 -- **Autoprefixer** - CSS 前缀自动添加 +- **Jest** - 单元测试框架 +- **Testing Library** - React 测试工具 ## 📁 项目结构 ``` -Cunkebao/ -├── app/ # Next.js App Router 页面 -│ ├── api/ # API 路由 -│ ├── components/ # 页面级组件 -│ ├── workspace/ # 工作台模块 -│ ├── scenarios/ # 场景管理 -│ ├── devices/ # 设备管理 -│ ├── content/ # 内容管理 -│ └── ... -├── components/ # 全局组件 -│ ├── ui/ # shadcn/ui 组件 -│ └── ... -├── lib/ # 工具库 -│ ├── api/ # API 封装 -│ └── utils.ts # 通用工具函数 -├── hooks/ # 自定义 Hooks -├── types/ # TypeScript 类型定义 -└── public/ # 静态资源 +nkebao/ +├── public/ # 静态资源 +├── src/ # 源代码 +│ ├── api/ # API 接口封装 +│ ├── components/ # 全局组件 +│ │ ├── ui/ # UI 基础组件 +│ │ └── icons/ # 图标组件 +│ ├── config/ # 配置文件 +│ ├── contexts/ # React Context +│ ├── hooks/ # 自定义 Hooks +│ ├── pages/ # 页面组件 +│ │ ├── workspace/ # 工作台模块 +│ │ │ ├── auto-like/ # 自动点赞 +│ │ │ ├── auto-group/ # 自动建群 +│ │ │ ├── group-push/ # 群消息推送 +│ │ │ ├── moments-sync/ # 朋友圈同步 +│ │ │ ├── ai-assistant/ # AI 对话助手 +│ │ │ └── traffic-distribution/ # 流量分发 +│ │ ├── devices/ # 设备管理 +│ │ ├── scenarios/ # 场景管理 +│ │ ├── content/ # 内容管理 +│ │ └── ... +│ ├── types/ # TypeScript 类型定义 +│ ├── utils/ # 工具函数 +│ ├── App.tsx # 应用根组件 +│ └── index.tsx # 应用入口 +├── craco.config.js # CRACO 配置 +├── tailwind.config.js # Tailwind CSS 配置 +├── tsconfig.json # TypeScript 配置 +└── package.json # 项目依赖 ``` ## 🎯 核心功能模块 ### 工作台 (Workspace) -- **自动点赞** - 智能点赞管理 -- **朋友圈同步** - 内容同步工具 -- **群消息推送** - 群组消息管理 -- **AI 对话助手** - 智能客服系统 -- **自动建群** - 群组自动化管理 -- **流量分发** - 流量分配策略 +- **自动点赞** - 智能点赞管理和配置 +- **自动建群** - 群组自动化创建和管理 +- **群消息推送** - 群组消息批量发送 +- **朋友圈同步** - 内容同步和发布 +- **AI 对话助手** - 智能客服和对话管理 +- **流量分发** - 流量分配和策略管理 ### 设备管理 (Devices) -- 设备状态监控 -- 设备配置管理 +- 设备状态监控和配置 - 设备性能分析 +- 设备权限管理 ### 场景管理 (Scenarios) - 营销场景配置 @@ -79,61 +129,78 @@ Cunkebao/ - 内容模板管理 - 内容发布调度 -### 用户管理 (Users) -- 用户权限管理 -- 角色分配 -- 用户行为分析 +### 其他模块 +- 用户管理 (Users) +- 订单管理 (Orders) +- 流量池管理 (Traffic Pool) +- 联系人导入 (Contact Import) ## 🛠️ 开发指南 ### 环境要求 -- Node.js 18+ -- npm 或 pnpm +- **Node.js** 16+ +- **npm** 或 **yarn** ### 安装依赖 ```bash +# 使用 npm npm install -# 或 -pnpm install + +# 使用 yarn +yarn install ``` ### 开发环境启动 ```bash -npm run dev -# 或 -pnpm dev +# 使用 npm +npm start + +# 使用 yarn +yarn start ``` ### 构建生产版本 ```bash +# 使用 npm npm run build -npm start + +# 使用 yarn +yarn build ``` -### 代码检查 +### 运行测试 ```bash -npm run lint +# 使用 npm +npm test + +# 使用 yarn +yarn test ``` ## 🔧 配置说明 -### 环境变量 -创建 `.env.local` 文件: -```env -NEXT_PUBLIC_API_BASE_URL=your_api_base_url -CUSTOM_KEY=your_custom_key +### 路径别名配置 +项目使用 CRACO 配置了路径别名: +```javascript +'@': path.resolve(__dirname, 'src'), +'@/components': path.resolve(__dirname, 'src/components'), +'@/api': path.resolve(__dirname, 'src/api'), +'@/types': path.resolve(__dirname, 'src/types'), +'@/hooks': path.resolve(__dirname, 'src/hooks'), +'@/utils': path.resolve(__dirname, 'src/utils'), +'@/styles': path.resolve(__dirname, 'src/styles'), +'@/pages': path.resolve(__dirname, 'src/pages'), ``` -### Next.js 配置 -- 支持图片优化和多种格式 -- 配置了 API 代理和 CORS -- 启用了 SWC 压缩 -- 支持包分析工具 - ### Tailwind CSS 配置 -- 支持暗色模式 -- 自定义颜色系统 -- 响应式设计支持 +- 自定义字体大小和间距 +- 响应式断点配置 +- 主题颜色系统 + +### TypeScript 配置 +- 严格模式启用 +- 路径映射配置 +- JSX 支持 ## 📱 响应式设计 @@ -149,9 +216,9 @@ CUSTOM_KEY=your_custom_key - 一致的用户体验 - 无障碍访问支持 -### 组件库 -- 50+ 个预构建组件 -- 完整的表单组件 +### 组件库特点 +- 基于 Radix UI 的高质量组件 +- 完整的表单组件系统 - 数据展示组件 - 导航和布局组件 @@ -160,21 +227,27 @@ CUSTOM_KEY=your_custom_key - 身份验证和授权 - API 请求拦截 - 数据验证和清理 -- CORS 配置 +- 加密功能支持 ## 📊 性能优化 - 代码分割和懒加载 -- 图片优化 +- 组件优化 - 缓存策略 - 包大小优化 +## 🧪 测试策略 + +- 单元测试 (Jest + Testing Library) +- 组件测试 +- 集成测试支持 + ## 🤝 贡献指南 1. Fork 项目 -2. 创建功能分支 -3. 提交更改 -4. 推送到分支 +2. 创建功能分支 (`git checkout -b feature/AmazingFeature`) +3. 提交更改 (`git commit -m 'Add some AmazingFeature'`) +4. 推送到分支 (`git push origin feature/AmazingFeature`) 5. 创建 Pull Request ## 📄 许可证 @@ -187,5 +260,7 @@ CUSTOM_KEY=your_custom_key --- +**项目名称**: 内客宝 (nkebao2) **版本**: 0.1.0 +**技术栈**: React + TypeScript + CRA + Tailwind CSS **最后更新**: 2024年12月 \ No newline at end of file diff --git a/Cunkebao/api/devices.ts b/Cunkebao/api/devices.ts deleted file mode 100644 index 64da66da3..000000000 --- a/Cunkebao/api/devices.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { api } from "@/lib/api"; -import type { - ApiResponse, - Device, - DeviceStats, - DeviceTaskRecord, - PaginatedResponse, - QueryDeviceParams, - CreateDeviceParams, - UpdateDeviceParams, - DeviceStatus, - ServerDevice, - ServerDevicesResponse -} from "@/types/device" - -const API_BASE = "/api/devices" - -// 获取设备列表 - 连接到服务器/v1/devices接口 -export const fetchDeviceList = async (page: number = 1, limit: number = 20, keyword?: string): Promise => { - const params = new URLSearchParams(); - params.append('page', page.toString()); - params.append('limit', limit.toString()); - - if (keyword) { - params.append('keyword', keyword); - } - - return api.get(`/v1/devices?${params.toString()}`); -}; - -// 获取设备详情 - 连接到服务器/v1/devices/:id接口 -export const fetchDeviceDetail = async (id: string | number): Promise> => { - return api.get>(`/v1/devices/${id}`); -}; - -// 获取设备关联的微信账号 -export const fetchDeviceRelatedAccounts = async (id: string | number): Promise> => { - return api.get>(`/v1/wechats/related-device/${id}`); -}; - -// 获取设备操作记录 -export const fetchDeviceHandleLogs = async (id: string | number, page: number = 1, limit: number = 10): Promise> => { - return api.get>(`/v1/devices/${id}/handle-logs?page=${page}&limit=${limit}`); -}; - -// 更新设备任务配置 -export const updateDeviceTaskConfig = async ( - config: { - deviceId: string | number; - autoAddFriend?: boolean; - autoReply?: boolean; - momentsSync?: boolean; - aiChat?: boolean; - } -): Promise> => { - return api.post>(`/v1/devices/task-config`, { - ...config - }); -}; - -// 删除设备 -export const deleteDevice = async (id: number): Promise> => { - return api.delete>(`/v1/devices/${id}`); -}; - -// 设备管理API -export const deviceApi = { - // 创建设备 - async create(params: CreateDeviceParams): Promise> { - const response = await fetch(`${API_BASE}`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(params), - }) - return response.json() - }, - - // 更新设备 - async update(params: UpdateDeviceParams): Promise> { - const response = await fetch(`${API_BASE}/${params.id}`, { - method: "PUT", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(params), - }) - return response.json() - }, - - // 获取设备详情 - async getById(id: string): Promise> { - const response = await fetch(`${API_BASE}/${id}`) - return response.json() - }, - - // 查询设备列表 - async query(params: QueryDeviceParams): Promise>> { - // 创建一个新对象,用于构建URLSearchParams - const queryParams: Record = {}; - - // 按需将params中的属性添加到queryParams - if (params.keyword) queryParams.keyword = params.keyword; - if (params.status) queryParams.status = params.status; - if (params.type) queryParams.type = params.type; - if (params.page) queryParams.page = params.page.toString(); - if (params.pageSize) queryParams.pageSize = params.pageSize.toString(); - - // 特殊处理需要JSON序列化的属性 - if (params.tags) queryParams.tags = JSON.stringify(params.tags); - if (params.dateRange) queryParams.dateRange = JSON.stringify(params.dateRange); - - // 构建查询字符串 - const queryString = new URLSearchParams(queryParams).toString(); - const response = await fetch(`${API_BASE}?${queryString}`) - return response.json() - }, - - // 删除设备 - async delete(id: string): Promise> { - const response = await fetch(`${API_BASE}/${id}`, { - method: "DELETE", - }) - return response.json() - }, - - // 重启设备 - async restart(id: string): Promise> { - const response = await fetch(`${API_BASE}/${id}/restart`, { - method: "POST", - }) - return response.json() - }, - - // 解绑设备 - async unbind(id: string): Promise> { - const response = await fetch(`${API_BASE}/${id}/unbind`, { - method: "POST", - }) - return response.json() - }, - - // 获取设备统计数据 - async getStats(id: string): Promise> { - const response = await fetch(`${API_BASE}/${id}/stats`) - return response.json() - }, - - // 获取设备任务记录 - async getTaskRecords(id: string, page = 1, pageSize = 20): Promise>> { - const response = await fetch(`${API_BASE}/${id}/tasks?page=${page}&pageSize=${pageSize}`) - return response.json() - }, - - // 批量更新设备标签 - async updateTags(ids: string[], tags: string[]): Promise> { - const response = await fetch(`${API_BASE}/tags`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ deviceIds: ids, tags }), - }) - return response.json() - }, - - // 批量导出设备数据 - async exportDevices(ids: string[]): Promise { - const response = await fetch(`${API_BASE}/export`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ deviceIds: ids }), - }) - return response.blob() - }, - - // 检查设备在线状态 - async checkStatus(ids: string[]): Promise>> { - const response = await fetch(`${API_BASE}/status`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ deviceIds: ids }), - }) - return response.json() - }, -} - diff --git a/Cunkebao/api/route.ts b/Cunkebao/api/route.ts deleted file mode 100644 index f82d21d8b..000000000 --- a/Cunkebao/api/route.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { NextResponse } from "next/server" -import type { CreateScenarioParams, QueryScenarioParams, ScenarioBase, ApiResponse } from "@/types/scenario" - -// 获客场景路由处理 -export async function POST(request: Request) { - try { - const body: CreateScenarioParams = await request.json() - - // TODO: 实现创建场景的具体逻辑 - const scenario: ScenarioBase = { - id: "generated-id", - ...body, - status: "draft", - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - creator: "current-user-id", - } - - const response: ApiResponse = { - code: 0, - message: "创建成功", - data: scenario, - } - - return NextResponse.json(response) - } catch (error) { - return NextResponse.json( - { - code: 500, - message: "创建失败", - data: null, - }, - { status: 500 }, - ) - } -} - -export async function GET(request: Request) { - try { - const { searchParams } = new URL(request.url) - const params: QueryScenarioParams = { - type: searchParams.get("type") as any, - status: searchParams.get("status") as any, - keyword: searchParams.get("keyword") || undefined, - dateRange: searchParams.get("dateRange") ? JSON.parse(searchParams.get("dateRange")!) : undefined, - page: Number(searchParams.get("page")) || 1, - pageSize: Number(searchParams.get("pageSize")) || 20, - } - - // TODO: 实现查询场景列表的具体逻辑 - - return NextResponse.json({ - code: 0, - message: "查询成功", - data: { - items: [], - total: 0, - page: params.page, - pageSize: params.pageSize, - totalPages: 0, - }, - }) - } catch (error) { - return NextResponse.json( - { - code: 500, - message: "查询失败", - data: null, - }, - { status: 500 }, - ) - } -} - diff --git a/Cunkebao/api/scenarios.ts b/Cunkebao/api/scenarios.ts deleted file mode 100644 index ed77aeb53..000000000 --- a/Cunkebao/api/scenarios.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { request } from "@/lib/api" - -export interface ApiResponse { - code: number; - msg: string; - data: T | null; -} - -// 服务器返回的场景数据类型 -export interface SceneItem { - id: number; - name: string; - image: string; - status: number; - createTime: number; - updateTime: number | null; - deleteTime: number | null; -} - -// 服务器返回的场景列表响应类型 -export interface ScenesResponse { - code: number; - msg: string; - data: SceneItem[]; -} - -// 前端使用的场景数据类型 -export interface Channel { - id: string; - name: string; - icon: string; - stats: { - daily: number; - growth: number; - }; - link?: string; - plans?: Plan[]; -} - -// 计划类型 -export interface Plan { - id: string; - name: string; - isNew?: boolean; - status: "active" | "paused" | "completed"; - acquisitionCount: number; -} - -/** - * 获取获客场景列表 - * - * @param params 查询参数 - * @returns 获客场景列表 - */ -export const fetchScenes = async (params: { - page?: number; - limit?: number; - keyword?: string; -} = {}): Promise => { - const { page = 1, limit = 10, keyword = "" } = params; - - const queryParams = new URLSearchParams(); - queryParams.append("page", String(page)); - queryParams.append("limit", String(limit)); - - if (keyword) { - queryParams.append("keyword", keyword); - } - - try { - return await request(`/v1/plan/scenes?${queryParams.toString()}`); - } catch (error) { - console.error("Error fetching scenes:", error); - // 返回一个错误响应 - return { - code: 500, - msg: "获取场景列表失败", - data: [] - }; - } -}; - -/** - * 将服务器返回的场景数据转换为前端展示需要的格式 - * - * @param item 服务器返回的场景数据 - * @returns 前端展示的场景数据 - */ -export const transformSceneItem = (item: SceneItem): Channel => { - // 为每个场景生成随机的"今日"数据和"增长百分比" - const dailyCount = Math.floor(Math.random() * 100); - const growthPercent = Math.floor(Math.random() * 40) - 10; // -10% 到 30% 的随机值 - - // 默认图标(如果服务器没有返回) - const defaultIcon = "/assets/icons/poster-icon.svg"; - - return { - id: String(item.id), - name: item.name, - icon: item.image || defaultIcon, - stats: { - daily: dailyCount, - growth: growthPercent - } - }; -}; - -/** - * 获取场景详情 - * - * @param id 场景ID - * @returns 场景详情 - */ -export const fetchSceneDetail = async (id: string | number): Promise> => { - try { - return await request>(`/v1/plan/scenes/${id}`); - } catch (error) { - console.error("Error fetching scene detail:", error); - return { - code: 500, - msg: "获取场景详情失败", - data: null - }; - } -}; - diff --git a/Cunkebao/api/wechat-accounts.ts b/Cunkebao/api/wechat-accounts.ts deleted file mode 100644 index 393e1d8b9..000000000 --- a/Cunkebao/api/wechat-accounts.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { api } from "@/lib/api"; -import { - ServerWechatAccountsResponse, - QueryWechatAccountParams, -} from "@/types/wechat-account"; - -// 添加接口返回数据类型定义 -interface WechatAccountSummary { - accountAge: string; - activityLevel: { - allTimes: number; - dayTimes: number; - }; - accountWeight: { - scope: number; - ageWeight: number; - activityWeigth: number; - restrictWeight: number; - realNameWeight: number; - }; - statistics: { - todayAdded: number; - addLimit: number; - }; - restrictions: { - id: number; - level: string; - reason: string; - date: string; - }[]; -} - -interface WechatAccountSummaryResponse { - code: number; - msg: string; - data: WechatAccountSummary; -} - -/** - * 获取微信账号列表 - * @param params 查询参数 - * @returns 微信账号列表响应 - */ -export const fetchWechatAccountList = async (params: QueryWechatAccountParams = {}): Promise => { - const queryParams = new URLSearchParams(); - - // 添加查询参数 - if (params.page) queryParams.append('page', params.page.toString()); - if (params.limit) queryParams.append('limit', params.limit.toString()); - if (params.keyword) queryParams.append('nickname', params.keyword); // 使用nickname作为关键词搜索参数 - if (params.sort) queryParams.append('sort', params.sort); - if (params.order) queryParams.append('order', params.order); - - // 发起API请求 - return api.get(`/v1/wechats?${queryParams.toString()}`); -}; - -/** - * 刷新微信账号状态 - * @returns 刷新结果 - */ -export const refreshWechatAccounts = async (): Promise<{ code: number; msg: string; data: any }> => { - return api.put<{ code: number; msg: string; data: any }>('/v1/wechats/refresh', {}); -}; - -/** - * 执行微信好友转移 - * @param sourceId 源微信账号ID - * @param targetId 目标微信账号ID - * @returns 转移结果 - */ -export const transferWechatFriends = async (sourceId: string | number, targetId: string | number): Promise<{ code: number; msg: string; data: any }> => { - return api.post<{ code: number; msg: string; data: any }>('/v1/wechats/transfer-friends', { - source_id: sourceId, - target_id: targetId - }); -}; - -/** - * 将服务器返回的微信账号数据转换为前端使用的格式 - * @param serverAccount 服务器返回的微信账号数据 - * @returns 前端使用的微信账号数据 - */ -export const transformWechatAccount = (serverAccount: any): import("@/types/wechat-account").WechatAccount => { - // 从deviceInfo中提取设备信息 - let deviceId = ''; - let deviceName = ''; - - if (serverAccount.deviceInfo) { - // 尝试解析设备信息字符串 - const deviceInfo = serverAccount.deviceInfo.split(' '); - if (deviceInfo.length > 0) { - // 提取数字部分作为设备ID,确保是整数 - const possibleId = deviceInfo[0].trim(); - // 验证是否为数字 - deviceId = /^\d+$/.test(possibleId) ? possibleId : ''; - - // 提取设备名称 - if (deviceInfo.length > 1) { - deviceName = deviceInfo[1] ? deviceInfo[1].replace(/[()]/g, '').trim() : ''; - } - } - } - - // 如果从deviceInfo无法获取有效的设备ID,使用imei作为备选 - if (!deviceId && serverAccount.imei) { - deviceId = serverAccount.imei; - } - - // 如果仍然没有设备ID,使用微信账号的ID作为最后的备选 - if (!deviceId && serverAccount.id) { - deviceId = serverAccount.id.toString(); - } - - // 如果没有设备名称,使用备用名称 - if (!deviceName) { - deviceName = serverAccount.deviceMemo || '未命名设备'; - } - - // 假设每天最多可添加20个好友 - const maxDailyAdds = 20; - const todayAdded = serverAccount.todayNewFriendCount || 0; - - return { - id: serverAccount.id.toString(), - avatar: serverAccount.avatar || '', - nickname: serverAccount.nickname || serverAccount.accountNickname || '未命名', - wechatId: serverAccount.wechatId || '', - deviceId, - deviceName, - friendCount: serverAccount.totalFriend || 0, - todayAdded, - remainingAdds: serverAccount.canAddFriendCount || (maxDailyAdds - todayAdded), - maxDailyAdds, - status: serverAccount.wechatAlive === 1 ? "normal" : "abnormal" as "normal" | "abnormal", - lastActive: new Date().toLocaleString() // 服务端未提供,使用当前时间 - }; -}; - -/** - * 获取微信好友列表 - * @param wechatId 微信账号ID - * @param page 页码 - * @param pageSize 每页数量 - * @param searchQuery 搜索关键词 - * @returns 好友列表数据 - */ -export const fetchWechatFriends = async (wechatId: string, page: number = 1, pageSize: number = 20, searchQuery: string = '') => { - try { - return api.get(`/v1/wechats/${wechatId}/friends?page=${page}&limit=${pageSize}${searchQuery ? `&search=${searchQuery}` : ''}`, true); - } catch (error) { - console.error("获取好友列表失败:", error); - throw error; - } -}; - -/** - * 获取微信账号概览信息 - * @param id 微信账号ID - * @returns 微信账号概览信息 - */ -export const fetchWechatAccountSummary = async (wechatIdid: string): Promise => { - try { - return api.get(`/v1/wechats/${wechatIdid}/summary`); - } catch (error) { - console.error("获取账号概览失败:", error); - throw error; - } -}; - -/** - * 获取好友详情信息 - * @param wechatId 微信账号ID - * @param friendId 好友ID - * @returns 好友详情信息 - */ -export interface WechatFriendDetail { - id: number; - avatar: string; - nickname: string; - region: string; - wechatId: string; - addDate: string; - tags: string[]; - playDate: string; - memo: string; - source: string; -} - -interface WechatFriendDetailResponse { - code: number; - msg: string; - data: WechatFriendDetail; -} - -export const fetchWechatFriendDetail = async (wechatId: string): Promise => { - try { - return api.get(`/v1/wechats/${wechatId}`); - } catch (error) { - console.error("获取好友详情失败:", error); - throw error; - } -}; \ No newline at end of file diff --git a/Cunkebao/app/admin/accounts/mobile/page.tsx b/Cunkebao/app/admin/accounts/mobile/page.tsx deleted file mode 100644 index 69b99964b..000000000 --- a/Cunkebao/app/admin/accounts/mobile/page.tsx +++ /dev/null @@ -1,250 +0,0 @@ -"use client" - -import { useState } from "react" -import { Pencil, Trash2, Plus } from "lucide-react" -import { Button } from "@/components/ui/button" -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" -import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog" -import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" -import { Checkbox } from "@/components/ui/checkbox" -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" -import { Badge } from "@/components/ui/badge" - -interface MobileAccount { - id: string - name: string - phone: string - createdAt: string - status: "active" | "inactive" -} - -export default function MobileAccountsPage() { - const [accounts, setAccounts] = useState([ - { - id: "1", - name: "用户1", - phone: "13809076043", - createdAt: "2023-01-15", - status: "active", - }, - { - id: "2", - name: "用户2", - phone: "13819176143", - createdAt: "2023-02-15", - status: "inactive", - }, - { - id: "3", - name: "用户3", - phone: "13829276243", - createdAt: "2023-03-15", - status: "active", - }, - { - id: "4", - name: "用户4", - phone: "13839376343", - createdAt: "2023-04-15", - status: "inactive", - }, - { - id: "5", - name: "用户5", - phone: "13849476443", - createdAt: "2023-05-15", - status: "active", - }, - ]) - - const [isDialogOpen, setIsDialogOpen] = useState(false) - const [newAccount, setNewAccount] = useState({ - name: "", - password: "", - phone: "", - role: "", - permissions: { - notifications: false, - dataView: false, - remoteControl: false, - }, - }) - - const handleCreateAccount = () => { - // 这里应该有API调用来创建账号 - const newId = (accounts.length + 1).toString() - setAccounts([ - ...accounts, - { - id: newId, - name: newAccount.name, - phone: newAccount.phone, - createdAt: new Date().toISOString().split("T")[0], - status: "active", - }, - ]) - setIsDialogOpen(false) - setNewAccount({ - name: "", - password: "", - phone: "", - role: "", - permissions: { - notifications: false, - dataView: false, - remoteControl: false, - }, - }) - } - - const handleDeleteAccount = (id: string) => { - setAccounts(accounts.filter((account) => account.id !== id)) - } - - return ( -
-
-

手机端账号列表

- -
- -
- - - - 账号名称 - 手机号码 - 创建时间 - 状态 - 操作 - - - - {accounts.map((account) => ( - - {account.name} - {account.phone} - {account.createdAt} - - - {account.status === "active" ? "活跃" : "非活跃"} - - - - - - - - ))} - -
-
- - - - - 新增手机端账号 - -
-
- - setNewAccount({ ...newAccount, name: e.target.value })} - placeholder="请输入账号名称" - /> -
-
- - setNewAccount({ ...newAccount, password: e.target.value })} - placeholder="请输入初始密码" - /> -
-
- - setNewAccount({ ...newAccount, phone: e.target.value })} - placeholder="请输入手机号码" - /> -
-
- - -
-
- -
-
- - setNewAccount({ - ...newAccount, - permissions: { ...newAccount.permissions, notifications: !!checked }, - }) - } - /> - -
-
- - setNewAccount({ - ...newAccount, - permissions: { ...newAccount.permissions, dataView: !!checked }, - }) - } - /> - -
-
- - setNewAccount({ - ...newAccount, - permissions: { ...newAccount.permissions, remoteControl: !!checked }, - }) - } - /> - -
-
-
-
-
- -
-
-
-
- ) -} diff --git a/Cunkebao/app/admin/accounts/operators/page.tsx b/Cunkebao/app/admin/accounts/operators/page.tsx deleted file mode 100644 index 30f695c2f..000000000 --- a/Cunkebao/app/admin/accounts/operators/page.tsx +++ /dev/null @@ -1,197 +0,0 @@ -"use client" - -import { useState } from "react" -import { Pencil, Trash2, Plus } from "lucide-react" -import { Button } from "@/components/ui/button" -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" -import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog" -import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" -import { Badge } from "@/components/ui/badge" - -interface OperatorAccount { - id: string - phone: string - nickname: string - deviceCount: number - friendCount: number - createdAt: string - status: "active" | "inactive" -} - -export default function OperatorAccountsPage() { - const [accounts, setAccounts] = useState([ - { - id: "1", - phone: "13809076043", - nickname: "操盘手1", - deviceCount: 1, - friendCount: 25, - createdAt: "2023-01-15", - status: "active", - }, - { - id: "2", - phone: "13819176143", - nickname: "操盘手2", - deviceCount: 2, - friendCount: 50, - createdAt: "2023-02-15", - status: "inactive", - }, - { - id: "3", - phone: "13829276243", - nickname: "操盘手3", - deviceCount: 3, - friendCount: 75, - createdAt: "2023-03-15", - status: "active", - }, - { - id: "4", - phone: "13839376343", - nickname: "操盘手4", - deviceCount: 4, - friendCount: 100, - createdAt: "2023-04-15", - status: "inactive", - }, - { - id: "5", - phone: "13849476443", - nickname: "操盘手5", - deviceCount: 5, - friendCount: 125, - createdAt: "2023-05-15", - status: "active", - }, - ]) - - const [isDialogOpen, setIsDialogOpen] = useState(false) - const [newAccount, setNewAccount] = useState({ - phone: "", - nickname: "", - password: "", - }) - - const handleCreateAccount = () => { - // 这里应该有API调用来创建账号 - const newId = (accounts.length + 1).toString() - setAccounts([ - ...accounts, - { - id: newId, - phone: newAccount.phone, - nickname: newAccount.nickname, - deviceCount: 0, - friendCount: 0, - createdAt: new Date().toISOString().split("T")[0], - status: "active", - }, - ]) - setIsDialogOpen(false) - setNewAccount({ - phone: "", - nickname: "", - password: "", - }) - } - - const handleDeleteAccount = (id: string) => { - setAccounts(accounts.filter((account) => account.id !== id)) - } - - return ( -
-
-

操盘手账号列表

- -
- -
- - - - 登录手机号 - 备注 (昵称) - 关联设备数量 - 微信好友数量 - 创建时间 - 状态 - 操作 - - - - {accounts.map((account) => ( - - {account.phone} - {account.nickname} - {account.deviceCount} - {account.friendCount} - {account.createdAt} - - - {account.status === "active" ? "活跃" : "非活跃"} - - - - - - - - ))} - -
-
- - - - - 新增操盘手账号 - -
-
- - setNewAccount({ ...newAccount, phone: e.target.value })} - placeholder="请输入手机号" - /> -
-
- - setNewAccount({ ...newAccount, nickname: e.target.value })} - placeholder="请输入昵称" - /> -
-
- - setNewAccount({ ...newAccount, password: e.target.value })} - placeholder="请输入初始密码" - /> -
-
-
- -
-
-
-
- ) -} diff --git a/Cunkebao/app/admin/components/AdminSidebar.tsx b/Cunkebao/app/admin/components/AdminSidebar.tsx deleted file mode 100644 index 52dba01a1..000000000 --- a/Cunkebao/app/admin/components/AdminSidebar.tsx +++ /dev/null @@ -1,88 +0,0 @@ -"use client" - -import { useState } from "react" -import Link from "next/link" -import { usePathname } from "next/navigation" -import { ChevronDown, Users, MessageSquare } from "lucide-react" - -export default function AdminSidebar() { - const pathname = usePathname() - const [expandedItems, setExpandedItems] = useState>({ - 账号管理: true, - }) - - const toggleExpand = (key: string) => { - setExpandedItems((prev) => ({ - ...prev, - [key]: !prev[key], - })) - } - - const isActive = (path: string) => pathname === path - - return ( -
-
-

存客宝管理系统

-
- -
- ) -} diff --git a/Cunkebao/app/admin/layout.tsx b/Cunkebao/app/admin/layout.tsx deleted file mode 100644 index 6b21f7179..000000000 --- a/Cunkebao/app/admin/layout.tsx +++ /dev/null @@ -1,28 +0,0 @@ -"use client" - -import type React from "react" -import { Bell, User } from "lucide-react" -import { Button } from "@/components/ui/button" -import AdminSidebar from "./components/AdminSidebar" - -export default function AdminLayout({ children }: { children: React.ReactNode }) { - return ( -
- -
-
-

运营端后台

-
- - -
-
-
{children}
-
-
- ) -} diff --git a/Cunkebao/app/admin/page.tsx b/Cunkebao/app/admin/page.tsx deleted file mode 100644 index 4ace7fdce..000000000 --- a/Cunkebao/app/admin/page.tsx +++ /dev/null @@ -1,66 +0,0 @@ -"use client" - -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -import { Button } from "@/components/ui/button" -import { ArrowRight } from "lucide-react" -import Link from "next/link" - -export default function AdminDashboard() { - const stats = [ - { title: "总账号数", value: "42" }, - { title: "手机端账号", value: "28" }, - { title: "操盘手账号", value: "14" }, - { title: "今日活跃", value: "18" }, - ] - - return ( -
-

存客宝管理后台

- -
- {stats.map((stat, index) => ( - - - {stat.title} - - -

{stat.value}

-
-
- ))} -
- -
- - - 手机端账号管理 - - -

管理存客宝手机端的用户账号,设置权限和功能。

- - - -
-
- - - - 操盘手账号管理 - - -

管理操盘手账号,查看关联设备和微信好友数量。

- - - -
-
-
-
- ) -} diff --git a/Cunkebao/app/api/acquisition/[planId]/orders/route.ts b/Cunkebao/app/api/acquisition/[planId]/orders/route.ts deleted file mode 100644 index 08bc6bc4f..000000000 --- a/Cunkebao/app/api/acquisition/[planId]/orders/route.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { NextResponse } from "next/server" -import type { OrderFormData } from "@/types/acquisition" - -export async function POST(request: Request, { params }: { params: { planId: string } }) { - try { - const data: OrderFormData = await request.json() - - // 这里应该添加实际的数据库存储逻辑 - console.log("Received order:", data, "for plan:", params.planId) - - // 模拟成功响应 - return NextResponse.json({ - success: true, - message: "订单已成功提交", - }) - } catch (error) { - return NextResponse.json({ success: false, message: "订单提交失败" }, { status: 500 }) - } -} diff --git a/Cunkebao/app/api/auth.ts b/Cunkebao/app/api/auth.ts deleted file mode 100644 index 529d07d2f..000000000 --- a/Cunkebao/app/api/auth.ts +++ /dev/null @@ -1,68 +0,0 @@ -// API请求工具函数 -import { toast } from "@/components/ui/use-toast" - -const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.example.com" - -// 带有认证的请求函数 -export async function authFetch(url: string, options: RequestInit = {}) { - const token = localStorage.getItem("token") - - // 合并headers - let headers = { ...options.headers } - - // 如果有token,添加到请求头 - if (token) { - headers = { - ...headers, - Token: `${token}`, - } - } - - try { - const response = await fetch(`${API_BASE_URL}${url}`, { - ...options, - headers, - }) - - const data = await response.json() - - // 检查token是否过期(仅当有token时) - if (token && (data.code === 401 || data.code === 403)) { - // 清除token - localStorage.removeItem("token") - - // 暂时不重定向到登录页 - // if (typeof window !== "undefined") { - // window.location.href = "/login" - // } - - console.warn("登录已过期") - } - - return data - } catch (error) { - console.error("API请求错误:", error) - toast({ - variant: "destructive", - title: "请求失败", - description: error instanceof Error ? error.message : "网络错误,请稍后重试", - }) - throw error - } -} - -// 不需要认证的请求函数 -export async function publicFetch(url: string, options: RequestInit = {}) { - try { - const response = await fetch(`${API_BASE_URL}${url}`, options) - return await response.json() - } catch (error) { - console.error("API请求错误:", error) - toast({ - variant: "destructive", - title: "请求失败", - description: error instanceof Error ? error.message : "网络错误,请稍后重试", - }) - throw error - } -} diff --git a/Cunkebao/app/api/devices/route.ts b/Cunkebao/app/api/devices/route.ts deleted file mode 100644 index c7a1de4db..000000000 --- a/Cunkebao/app/api/devices/route.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { NextResponse } from "next/server" -import type { - CreateDeviceParams, - QueryDeviceParams, - Device, - ApiResponse, - DeviceStatus, - DeviceType, -} from "@/types/device" - -// 设备管理路由处理 -export async function POST(request: Request) { - try { - const body: CreateDeviceParams = await request.json() - - // TODO: 实现创建设备的具体逻辑 - const device: Device = { - id: "generated-id", - ...body, - status: DeviceStatus.OFFLINE, - lastOnlineTime: new Date().toISOString(), - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - } - - const response: ApiResponse = { - code: 0, - message: "创建成功", - data: device, - } - - return NextResponse.json(response) - } catch (error) { - return NextResponse.json( - { - code: 500, - message: "创建失败", - data: null, - }, - { status: 500 }, - ) - } -} - -export async function GET(request: Request) { - try { - const { searchParams } = new URL(request.url) - const params: QueryDeviceParams = { - keyword: searchParams.get("keyword") || undefined, - status: (searchParams.get("status") as DeviceStatus) || undefined, - type: (searchParams.get("type") as DeviceType) || undefined, - tags: searchParams.get("tags") ? JSON.parse(searchParams.get("tags")!) : undefined, - dateRange: searchParams.get("dateRange") ? JSON.parse(searchParams.get("dateRange")!) : undefined, - page: Number(searchParams.get("page")) || 1, - pageSize: Number(searchParams.get("pageSize")) || 20, - } - - // TODO: 实现查询设备列表的具体逻辑 - - return NextResponse.json({ - code: 0, - message: "查询成功", - data: { - items: [], - total: 0, - page: params.page, - pageSize: params.pageSize, - totalPages: 0, - }, - }) - } catch (error) { - return NextResponse.json( - { - code: 500, - message: "查询失败", - data: null, - }, - { status: 500 }, - ) - } -} diff --git a/Cunkebao/app/api/docs/scenarios/[channel]/[id]/page.tsx b/Cunkebao/app/api/docs/scenarios/[channel]/[id]/page.tsx deleted file mode 100644 index b37bd496a..000000000 --- a/Cunkebao/app/api/docs/scenarios/[channel]/[id]/page.tsx +++ /dev/null @@ -1,377 +0,0 @@ -"use client" - -import { useState } from "react" -import { ChevronLeft, Copy, Check, Info } from "lucide-react" -import { Button } from "@/components/ui/button" -import { useRouter } from "next/navigation" -import { useToast } from "@/components/ui/use-toast" -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { getApiGuideForScenario } from "@/docs/api-guide" -import { Badge } from "@/components/ui/badge" -import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" - -export default function ApiDocPage({ params }: { params: { channel: string; id: string } }) { - const router = useRouter() - const { toast } = useToast() - const [copiedExample, setCopiedExample] = useState(null) - - const apiGuide = getApiGuideForScenario(params.id, params.channel) - - const copyToClipboard = (text: string, exampleId: string) => { - navigator.clipboard.writeText(text) - setCopiedExample(exampleId) - - toast({ - title: "已复制代码", - description: "代码示例已复制到剪贴板", - }) - - setTimeout(() => { - setCopiedExample(null) - }, 2000) - } - - return ( -
-
-
-
- -
-

{apiGuide.title}

-

API接口文档

-
-
-
- -
-
-
- -
- {/* API密钥卡片 */} - - -
-
- -
-
- API密钥 - 用于身份验证,请妥善保管,不要在客户端代码中暴露它 -
-
-
- -
-
-
- api_1_xqbint74 - -
-
- -
-
- -
-

安全提示

-

- 请妥善保管您的API密钥,不要在客户端代码中暴露它。建议在服务器端使用该接口。 -

-
-
-
-
-
-
- - {/* 接口地址卡片 */} - - - 接口地址 - 使用此接口直接导入客户资料到该获客计划,支持多种编程语言 - - -
-
-
- POST 请求地址 - -
- - https://kzminfd0rplrm7owmj4b.lite.vusercontent.net/api/scenarios/post - -
- -
-
-

必要参数

-
- - name (姓名) - - - phone (电话) - -
-
-
-

可选参数

-
- - source (来源) - - - remark (备注) - - - tags (标签) - -
-
-
-
-
-
- - {/* 接口文档卡片 */} - - - 接口文档 - 详细的API规范和集成指南 - - -
- - -
-
-
- - {/* 快速测试卡片 */} - - - 快速测试 - 使用以下URL可以快速测试接口是否正常工作 - - -
-
- 测试URL - -
- - https://kzminfd0rplrm7owmj4b.lite.vusercontent.net/api/scenarios/poster/1/webhook?name=测试客户&phone=13800138000 - -
-
-

💡 点击上方链接或复制到浏览器中访问,即可快速测试接口连通性

-
-
-
- - {/* 详细文档手风琴 */} -
- - {apiGuide.endpoints.map((endpoint, index) => ( - - -
- {endpoint.method} - {endpoint.url} -
-
- -
-

{endpoint.description}

- -
-

请求头

-
- {endpoint.headers.map((header, i) => ( -
- - {header.required ? "*" : ""} - {header.name} - -
-

{header.value}

-

{header.description}

-
-
- ))} -
-
- -
-

请求参数

-
- {endpoint.parameters.map((param, i) => ( -
- - {param.required ? "*" : ""} - {param.name} - -
-

- {param.type} -

-

{param.description}

-
-
- ))} -
-
- -
-

响应示例

-
-                        {JSON.stringify(endpoint.response, null, 2)}
-                      
-
-
-
-
- ))} -
-
- - {/* 代码示例 */} - - - 代码示例 - 以下是不同编程语言的接口调用示例 - - - - - {apiGuide.examples.map((example) => ( - - {example.title} - - ))} - - - {apiGuide.examples.map((example) => ( - -
-
{example.code}
- -
-
- ))} -
-
-
- - {/* 集成指南 */} -
-

集成指南

- - - - 集简云平台集成 - - -
    -
  1. 登录集简云平台
  2. -
  3. 导航至"应用集成" > "外部接口"
  4. -
  5. 选择"添加新接口",输入存客宝接口信息
  6. -
  7. 配置回调参数,将"X-API-KEY"设置为您的API密钥
  8. -
  9. - 设置接口URL为: - {apiGuide.endpoints[0].url} -
  10. -
  11. 映射必要字段(name, phone等)
  12. -
  13. 保存并启用集成
  14. -
-
-
- - - - 问题排查 - - -
-

接口认证失败

-

- 请确保X-API-KEY正确无误,此密钥区分大小写。如需重置密钥,请联系管理员。 -

-
- -
-

数据格式错误

-

- 确保所有必填字段已提供,并且字段类型正确。特别是电话号码格式需符合标准。 -

-
- -
-

请求频率限制

-

- 单个API密钥每分钟最多可发送30个请求,超过限制将被暂时限制。对于大批量数据,请使用批量接口。 -

-
-
-
-
-
-
- ) -} diff --git a/Cunkebao/app/api/docs/scenarios/page.tsx b/Cunkebao/app/api/docs/scenarios/page.tsx deleted file mode 100644 index f53009ef4..000000000 --- a/Cunkebao/app/api/docs/scenarios/page.tsx +++ /dev/null @@ -1,405 +0,0 @@ -"use client" - -import { useState } from "react" -import { ChevronLeft, Copy, Check, Info } from "lucide-react" -import { Button } from "@/components/ui/button" -import { useRouter } from "next/navigation" -import { useToast } from "@/components/ui/use-toast" -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { getApiGuideForScenario } from "@/docs/api-guide" -import { Badge } from "@/components/ui/badge" -import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" - -const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || 'https://yishi.com' - -export default function ApiDocPage({ params }: { params: { channel: string; id: string } }) { - const router = useRouter() - const { toast } = useToast() - const [copiedExample, setCopiedExample] = useState(null) - - const apiGuide = getApiGuideForScenario(params.id, params.channel) - - // 假设 fullUrl 和 apiKey 可通过 props 或接口获取,这里用演示值 - const [apiKey] = useState("naxf1-82h2f-vdwcm-rrhpm-q9hd1") - const [fullUrl] = useState("/v1/api/scenarios") - const testUrl = fullUrl.startsWith("http") ? fullUrl : `${API_BASE_URL}${fullUrl}` - - const copyToClipboard = (text: string, exampleId: string) => { - navigator.clipboard.writeText(text) - setCopiedExample(exampleId) - - toast({ - title: "已复制代码", - description: "代码示例已复制到剪贴板", - }) - - setTimeout(() => { - setCopiedExample(null) - }, 2000) - } - - return ( -
-
-
-
- -

计划接口文档

-
-
-
- -
- - - 接口说明 - 本接口用于将外部客户数据导入到存客宝计划。请使用 apiKey 进行身份认证,建议仅在服务端调用。 - - -
-
- -

- 支持多种编程语言和平台集成。接口地址和参数请参考下方说明。 -

-
-
-

- 安全提示: 请妥善保管您的API密钥,不要在客户端代码中暴露它。建议在服务器端使用该接口。 -

-
-
-
-
- - - - 签名规则 - - -
-
- 签名参数: sign -
-
- 签名算法: 将所有请求参数(排除 sign 和 apiKey)按参数名升序排序,直接拼接参数值(不含等号和&),对该字符串进行 MD5 加密,得到中间串,再拼接 apiKey,最后再进行一次 MD5 加密,结果作为 sign 参数传递。 -
-
- 签名步骤: -
    -
  1. 去除 sign 和 apiKey 参数,将其余所有参数(如 name、phone、timestamp、source、remark、tags)按参数名升序排序
  2. -
  3. 直接拼接参数值,如 value1value2value3...
  4. -
  5. 对拼接后的字符串进行 MD5 加密,得到中间串
  6. -
  7. 将中间串与 apiKey 直接拼接
  8. -
  9. 对拼接后的字符串再进行一次 MD5 加密,结果即为 sign
  10. -
-
-
- 示例: -
-{`参数:
-  name=张三
-  phone=18888888888
-  timestamp=1700000000
-  apiKey=naxf1-82h2f-vdwcm-rrhpm-q9hd1
-
-排序后拼接(排除apiKey,直接拼接值):
-  张三188888888881700000000
-
-第一步MD5:
-  md5(张三188888888881700000000) = 123456abcdef...
-
-拼接apiKey:
-  123456abcdef...naxf1-82h2f-vdwcm-rrhpm-q9hd1
-
-第二步MD5:
-  sign=md5(123456abcdef...naxf1-82h2f-vdwcm-rrhpm-q9hd1)`}
-                
-
-
注意:所有参数均需参与签名(除 sign 和 apiKey),且参数值需为原始值(不可 URL 编码)。
-
-
-
- - - - 接口地址 - - -
- {testUrl} -
-
-
必要参数: phone (电话), timestamp (时间戳), apiKey (接口密钥)
-
可选参数: name (姓名), source (来源), remark (备注), tags (标签)
-
请求方式: POSTGET
-
-
-
- - - - 请求参数 - - -
-
phone (string, 必填): 客户电话
-
timestamp (int, 必填): 当前时间戳,精确到秒(如 1700000000,建议用 Math.floor(Date.now() / 1000) 获取)
-
apiKey (string, 必填): 接口密钥
-
name (string, 可选): 客户姓名
-
source (string, 可选): 来源
-
remark (string, 可选): 备注
-
tags (string, 可选): 标签
-
-
-
- - - - 响应示例 - - -
-{`{
-  "code": 200,
-  "msg": "导入成功",
-  "data": {
-    "customerId": "123456"
-  }
-}`}
-            
-
-
- - - - - - 代码示例 - 以下是不同编程语言的接口调用示例 - - - - - cURL - Python - Node.js - PHP - Java - - -
{`curl -X POST 'http://yishi.com/v1/plan/api/scenariosz' \
-  -d "phone=18888888888" \
-  -d "timestamp=1700000000" \
-  -d "name=张三" \
-  -d "apiKey=naxf1-82h2f-vdwcm-rrhpm-q9hd1" \
-  -d "sign=请用签名算法生成"`}
-
- -
{`import hashlib
-import time
-import requests
-
-def gen_sign(params, api_key):
-    data = {k: v for k, v in params.items() if k not in ('sign', 'apiKey')}
-    s = ''.join([str(data[k]) for k in sorted(data)])
-    first = hashlib.md5(s.encode('utf-8')).hexdigest()
-    return hashlib.md5((first + api_key).encode('utf-8')).hexdigest()
-
-api_key = 'naxf1-82h2f-vdwcm-rrhpm-q9hd1'
-params = {
-    'phone': '18888888888',
-    'timestamp': int(time.time()),
-    'name': '张三',
-}
-params['apiKey'] = api_key
-params['sign'] = gen_sign(params, api_key)
-resp = requests.post('http://yishi.com/v1/plan/api/scenariosz', data=params)
-print(resp.json())`}
-
- -
{`const axios = require('axios');
-const crypto = require('crypto');
-
-function genSign(params, apiKey) {
-  const data = {...params};
-  delete data.sign;
-  delete data.apiKey;
-  const keys = Object.keys(data).sort();
-  let str = '';
-  keys.forEach(k => { str += data[k]; });
-  const first = crypto.createHash('md5').update(str).digest('hex');
-  return crypto.createHash('md5').update(first + apiKey).digest('hex');
-}
-
-const apiKey = 'naxf1-82h2f-vdwcm-rrhpm-q9hd1';
-const params = {
-  phone: '18888888888',
-  timestamp: Math.floor(Date.now() / 1000),
-  name: '张三',
-};
-params.apiKey = apiKey;
-params.sign = genSign(params, apiKey);
-
-axios.post('http://yishi.com/v1/plan/api/scenariosz', params)
-  .then(res => console.log(res.data));`}
-
- -
{` '18888888888',
-    'timestamp' => time(),
-    'name' => '张三',
-    // 'source' => '', 'remark' => '', 'tags' => ''
-];
-$apiKey = 'naxf1-82h2f-vdwcm-rrhpm-q9hd1';
-$params['apiKey'] = $apiKey;
-$params['sign'] = md5_sign($params, $apiKey);
-
-$url = '${API_BASE_URL}/v1/api/scenarios';
-
-$ch = curl_init();
-curl_setopt($ch, CURLOPT_URL, $url);
-curl_setopt($ch, CURLOPT_POST, 1);
-curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
-curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-$response = curl_exec($ch);
-curl_close($ch);
-echo $response;
-?>`}
-
- -
{`import java.security.MessageDigest;
-import java.util.*;
-import java.net.*;
-import java.io.*;
-
-public class ApiSignDemo {
-    public static String md5(String s) throws Exception {
-        MessageDigest md = MessageDigest.getInstance("MD5");
-        byte[] array = md.digest(s.getBytes("UTF-8"));
-        StringBuilder sb = new StringBuilder();
-        for (byte b : array) sb.append(String.format("%02x", b));
-        return sb.toString();
-    }
-    public static void main(String[] args) throws Exception {
-        Map params = new HashMap<>();
-        params.put("phone", "18888888888");
-        params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
-        params.put("name", "张三");
-        // params.put("source", ""); params.put("remark", ""); params.put("tags", "");
-        String apiKey = "naxf1-82h2f-vdwcm-rrhpm-q9hd1";
-        // 排序并拼接
-        List keys = new ArrayList<>(params.keySet());
-        keys.remove("sign");
-        keys.remove("apiKey");
-        Collections.sort(keys);
-        StringBuilder sb = new StringBuilder();
-        for (String k : keys) {
-            sb.append(params.get(k));
-        }
-        String first = md5(sb.toString());
-        String sign = md5(first + apiKey);
-        params.put("apiKey", apiKey);
-        params.put("sign", sign);
-        // 发送POST请求
-        StringBuilder postData = new StringBuilder();
-        for (Map.Entry entry : params.entrySet()) {
-            if (postData.length() > 0) postData.append("&");
-            postData.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
-            postData.append("=");
-            postData.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
-        }
-        URL url = new URL("${API_BASE_URL}/v1/api/scenarios");
-        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-        conn.setRequestMethod("POST");
-        conn.setDoOutput(true);
-        OutputStream os = conn.getOutputStream();
-        os.write(postData.toString().getBytes("UTF-8"));
-        os.flush(); os.close();
-        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
-        String line; StringBuilder resp = new StringBuilder();
-        while ((line = in.readLine()) != null) resp.append(line);
-        in.close();
-        System.out.println(resp.toString());
-    }
-}`}
-
-
-
-
- -
-

集成指南

- - - - 集简云平台集成 - - -
    -
  1. 登录集简云平台
  2. -
  3. 导航至"应用集成" > "外部接口"
  4. -
  5. 选择"添加新接口",输入存客宝接口信息
  6. -
  7. 配置回调参数,将"X-API-KEY"设置为您的API密钥
  8. -
  9. - 设置接口URL为: - - {testUrl} - -
  10. -
  11. 映射必要字段(name, phone等)
  12. -
  13. 保存并启用集成
  14. -
-
-
- - - - 问题排查 - - -
-

接口认证失败

-

- 请确保X-API-KEY正确无误,此密钥区分大小写。如需重置密钥,请联系管理员。 -

-
- -
-

数据格式错误

-

- 确保所有必填字段已提供,并且字段类型正确。特别是电话号码格式需符合标准。 -

-
- -
-

请求频率限制

-

- 单个API密钥每分钟最多可发送30个请求,超过限制将被暂时限制。对于大批量数据,请使用批量接口。 -

-
-
-
-
-
-
- ) -} - diff --git a/Cunkebao/app/api/scenarios/route.ts b/Cunkebao/app/api/scenarios/route.ts deleted file mode 100644 index 7b5e7c0a6..000000000 --- a/Cunkebao/app/api/scenarios/route.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { NextResponse } from "next/server" -import type { CreateScenarioParams, QueryScenarioParams, ScenarioBase, ApiResponse } from "@/types/scenario" - -// 获客场景路由处理 -export async function POST(request: Request) { - try { - const body: CreateScenarioParams = await request.json() - - // TODO: 实现创建场景的具体逻辑 - const scenario: ScenarioBase = { - id: "generated-id", - ...body, - status: "draft", - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - creator: "current-user-id", - } - - const response: ApiResponse = { - code: 0, - message: "创建成功", - data: scenario, - } - - return NextResponse.json(response) - } catch (error) { - return NextResponse.json( - { - code: 500, - message: "创建失败", - data: null, - }, - { status: 500 }, - ) - } -} - -export async function GET(request: Request) { - try { - const { searchParams } = new URL(request.url) - const params: QueryScenarioParams = { - type: searchParams.get("type") as any, - status: searchParams.get("status") as any, - keyword: searchParams.get("keyword") || undefined, - dateRange: searchParams.get("dateRange") ? JSON.parse(searchParams.get("dateRange")!) : undefined, - page: Number(searchParams.get("page")) || 1, - pageSize: Number(searchParams.get("pageSize")) || 20, - } - - // TODO: 实现查询场景列表的具体逻辑 - - return NextResponse.json({ - code: 0, - message: "查询成功", - data: { - items: [], - total: 0, - page: params.page, - pageSize: params.pageSize, - totalPages: 0, - }, - }) - } catch (error) { - return NextResponse.json( - { - code: 500, - message: "查询失败", - data: null, - }, - { status: 500 }, - ) - } -} diff --git a/Cunkebao/app/api/users/route.ts b/Cunkebao/app/api/users/route.ts deleted file mode 100644 index ace987c7d..000000000 --- a/Cunkebao/app/api/users/route.ts +++ /dev/null @@ -1,272 +0,0 @@ -import { NextResponse } from "next/server" -import type { TrafficUser } from "@/types/traffic" - -// 中文名字生成器数据 -const familyNames = [ - "张", - "王", - "李", - "赵", - "陈", - "刘", - "杨", - "黄", - "周", - "吴", - "朱", - "孙", - "马", - "胡", - "郭", - "林", - "何", - "高", - "梁", - "郑", - "罗", - "宋", - "谢", - "唐", - "韩", - "曹", - "许", - "邓", - "萧", - "冯", -] -const givenNames1 = [ - "志", - "建", - "文", - "明", - "永", - "春", - "秀", - "金", - "水", - "玉", - "国", - "立", - "德", - "海", - "和", - "荣", - "伟", - "新", - "英", - "佳", -] -const givenNames2 = [ - "华", - "平", - "军", - "强", - "辉", - "敏", - "峰", - "磊", - "超", - "艳", - "娜", - "霞", - "燕", - "娟", - "静", - "丽", - "涛", - "洋", - "勇", - "龙", -] - -// 生成固定的用户数据池 -const userPool: TrafficUser[] = Array.from({ length: 1610 }, (_, i) => { - const familyName = familyNames[Math.floor(Math.random() * familyNames.length)] - const givenName1 = givenNames1[Math.floor(Math.random() * givenNames1.length)] - const givenName2 = givenNames2[Math.floor(Math.random() * givenNames2.length)] - const fullName = Math.random() > 0.5 ? familyName + givenName1 + givenName2 : familyName + givenName1 - - // 生成随机时间(在过去7天内) - const date = new Date() - date.setDate(date.getDate() - Math.floor(Math.random() * 7)) - - return { - id: `${Date.now()}-${i}`, - avatar: `/placeholder.svg?height=40&width=40&text=${fullName[0]}`, - nickname: fullName, - wechatId: `wxid_${Math.random().toString(36).substr(2, 8)}`, - phone: `1${["3", "5", "7", "8", "9"][Math.floor(Math.random() * 5)]}${Array.from({ length: 9 }, () => Math.floor(Math.random() * 10)).join("")}`, - region: [ - "广东深圳", - "浙江杭州", - "江苏苏州", - "北京", - "上海", - "四川成都", - "湖北武汉", - "福建厦门", - "山东青岛", - "河南郑州", - ][Math.floor(Math.random() * 10)], - note: [ - "咨询产品价格", - "对产品很感兴趣", - "准备购买", - "需要更多信息", - "想了解优惠活动", - "询问产品规格", - "要求产品demo", - "索要产品目录", - "询问售后服务", - "要求上门演示", - ][Math.floor(Math.random() * 10)], - status: ["pending", "added", "failed"][Math.floor(Math.random() * 3)] as TrafficUser["status"], - addTime: date.toISOString(), - source: ["抖音直播", "小红书", "微信朋友圈", "视频号", "公众号", "个人主页"][Math.floor(Math.random() * 6)], - assignedTo: "", - category: ["potential", "customer", "lost"][Math.floor(Math.random() * 3)] as TrafficUser["category"], - tags: [], - } -}) - -// 计算今日新增数量 -const todayStart = new Date() -todayStart.setHours(0, 0, 0, 0) -const todayUsers = userPool.filter((user) => new Date(user.addTime) >= todayStart) - -// 生成微信好友数据池 -const generateWechatFriends = (wechatId: string, count: number) => { - return Array.from({ length: count }, (_, i) => { - const familyName = familyNames[Math.floor(Math.random() * familyNames.length)] - const givenName1 = givenNames1[Math.floor(Math.random() * givenNames1.length)] - const givenName2 = givenNames2[Math.floor(Math.random() * givenNames2.length)] - const fullName = Math.random() > 0.5 ? familyName + givenName1 + givenName2 : familyName + givenName1 - - // 生成随机时间(在过去30天内) - const date = new Date() - date.setDate(date.getDate() - Math.floor(Math.random() * 30)) - - return { - id: `wechat-${wechatId}-${i}`, - avatar: `/placeholder.svg?height=40&width=40&text=${fullName[0]}`, - nickname: fullName, - wechatId: `wxid_${Math.random().toString(36).substr(2, 8)}`, - phone: `1${["3", "5", "7", "8", "9"][Math.floor(Math.random() * 5)]}${Array.from({ length: 9 }, () => Math.floor(Math.random() * 10)).join("")}`, - region: [ - "广东深圳", - "浙江杭州", - "江苏苏州", - "北京", - "上海", - "四川成都", - "湖北武汉", - "福建厦门", - "山东青岛", - "河南郑州", - ][Math.floor(Math.random() * 10)], - note: [ - "咨询产品价格", - "对产品很感兴趣", - "准备购买", - "需要更多信息", - "想了解优惠活动", - "询问产品规格", - "要求产品demo", - "索要产品目录", - "询问售后服务", - "要求上门演示", - ][Math.floor(Math.random() * 10)], - status: ["pending", "added", "failed"][Math.floor(Math.random() * 3)] as TrafficUser["status"], - addTime: date.toISOString(), - source: ["抖音直播", "小红书", "微信朋友圈", "视频号", "公众号", "个人主页", "微信好友"][ - Math.floor(Math.random() * 7) - ], - assignedTo: "", - category: ["potential", "customer", "lost"][Math.floor(Math.random() * 3)] as TrafficUser["category"], - tags: [], - } - }) -} - -// 微信好友数据缓存 -const wechatFriendsCache = new Map() - -export async function GET(request: Request) { - const { searchParams } = new URL(request.url) - const page = Number.parseInt(searchParams.get("page") || "1") - const pageSize = Number.parseInt(searchParams.get("pageSize") || "10") - const search = searchParams.get("search") || "" - const category = searchParams.get("category") || "all" - const source = searchParams.get("source") || "all" - const status = searchParams.get("status") || "all" - const startDate = searchParams.get("startDate") - const endDate = searchParams.get("endDate") - const wechatSource = searchParams.get("wechatSource") || "" - - let filteredUsers = [...userPool] - - // 如果有微信来源参数,生成或获取微信好友数据 - if (wechatSource) { - if (!wechatFriendsCache.has(wechatSource)) { - // 生成150-300个随机好友 - const friendCount = Math.floor(Math.random() * (300 - 150)) + 150 - wechatFriendsCache.set(wechatSource, generateWechatFriends(wechatSource, friendCount)) - } - filteredUsers = wechatFriendsCache.get(wechatSource) || [] - } - - // 应用过滤条件 - filteredUsers = filteredUsers.filter((user) => { - const matchesSearch = search - ? user.nickname.toLowerCase().includes(search.toLowerCase()) || - user.wechatId.toLowerCase().includes(search.toLowerCase()) || - user.phone.includes(search) - : true - - const matchesCategory = category === "all" ? true : user.category === category - const matchesSource = source === "all" ? true : user.source === source - const matchesStatus = status === "all" ? true : user.status === status - - const matchesDate = - startDate && endDate - ? new Date(user.addTime) >= new Date(startDate) && new Date(user.addTime) <= new Date(endDate) - : true - - return matchesSearch && matchesCategory && matchesSource && matchesStatus && matchesDate - }) - - // 按添加时间倒序排序 - filteredUsers.sort((a, b) => new Date(b.addTime).getTime() - new Date(a.addTime).getTime()) - - // 计算分页 - const total = filteredUsers.length - const totalPages = Math.ceil(total / pageSize) - const start = (page - 1) * pageSize - const end = start + pageSize - const users = filteredUsers.slice(start, end) - - // 计算分类统计 - const categoryStats = { - potential: userPool.filter((user) => user.category === "potential").length, - customer: userPool.filter((user) => user.category === "customer").length, - lost: userPool.filter((user) => user.category === "lost").length, - } - - // 模拟网络延迟 - await new Promise((resolve) => setTimeout(resolve, 500)) - - return NextResponse.json({ - users, - pagination: { - total, - totalPages, - currentPage: page, - pageSize, - }, - stats: { - total: wechatSource ? filteredUsers.length : userPool.length, - todayNew: wechatSource ? Math.floor(filteredUsers.length * 0.1) : todayUsers.length, - categoryStats, - }, - }) -} diff --git a/Cunkebao/app/clientLayout.tsx b/Cunkebao/app/clientLayout.tsx deleted file mode 100644 index 892511aa5..000000000 --- a/Cunkebao/app/clientLayout.tsx +++ /dev/null @@ -1 +0,0 @@ -// 这个文件不再需要,我们使用app/layout.tsx作为统一布局 diff --git a/Cunkebao/app/components-demo/loading.tsx b/Cunkebao/app/components-demo/loading.tsx deleted file mode 100644 index a69af0209..000000000 --- a/Cunkebao/app/components-demo/loading.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Card, CardContent, CardHeader } from "@/components/ui/card" - -export default function ComponentsDemoLoading() { - return ( -
-
-
-
-
- -
-
- {Array.from({ length: 6 }).map((_, i) => ( -
- ))} -
- -
- {Array.from({ length: 6 }).map((_, i) => ( - - -
-
- - -
- - - ))} -
-
-
- ) -} diff --git a/Cunkebao/app/components-demo/page.tsx b/Cunkebao/app/components-demo/page.tsx deleted file mode 100644 index 7d99363fc..000000000 --- a/Cunkebao/app/components-demo/page.tsx +++ /dev/null @@ -1,493 +0,0 @@ -"use client" - -import type React from "react" -import { useState } from "react" -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" -import { Button } from "@/components/ui/button" -import { Badge } from "@/components/ui/badge" -import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" -import { Textarea } from "@/components/ui/textarea" -import { Switch } from "@/components/ui/switch" -import { Checkbox } from "@/components/ui/checkbox" -import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" -import { Progress } from "@/components/ui/progress" -import { Slider } from "@/components/ui/slider" -import { Calendar } from "@/components/ui/calendar" -import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@/components/ui/dialog" -import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" -import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" -import { ScrollArea } from "@/components/ui/scroll-area" -import { Separator } from "@/components/ui/separator" -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" - -import { CalendarIcon, Code, Copy, Check, Smartphone, Users, TrendingUp, Activity } from "lucide-react" - -/** - * 组件库展示页面 - * 展示所有可用的UI组件和自定义组件 - */ -export default function ComponentsDemo() { - return ( -
-
-

存客宝组件库

-

展示项目中所有可用的UI组件和自定义组件,包含使用示例和代码演示

-
- - - - 基础组件 - 表单组件 - 数据展示 - 反馈组件 - 导航组件 - 自定义组件 - - - {/* 基础组件 */} - - -
- - - - - - - - -
-
- - -
- 默认 - 次要 - 边框 - 危险 - 成功 - 警告 -
-
- - -
- - - CN - - - AB - - - XY - -
-
- - -
-
水平分隔符
- -
垂直分隔符
-
- 左侧内容 - - 右侧内容 -
-
-
-
- - {/* 表单组件 */} - - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- - -
- -