ibc-ai-web-sdk 2.0.2 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -225,7 +225,8 @@ class AIChatClient {
225
225
  return token;
226
226
  }).catch(error => {
227
227
  if (silent) {
228
- console.warn('[AIChatClient] Silent token refresh failed (reason=' + reason + '):', error.message);
228
+ const errMsg = error && (error.message || String(error)) || 'unknown error';
229
+ console.warn('[AIChatClient] Silent token refresh failed (reason=' + reason + '):', errMsg);
229
230
  return this.config.token || '';
230
231
  }
231
232
  this.stopBackgroundRefresh();
@@ -633,8 +634,9 @@ class AIChatClient {
633
634
  return;
634
635
  }
635
636
  if (MESSAGE_EVENTS.has(event)) {
636
- if (!data || isRuntimePlaceholder(data) || this.isEventLike(data)) return;
637
- handlers.onMessage?.(data);
637
+ // 后端通过空 data 块表示逻辑换行,空字符串需保留传递给上层处理
638
+ if (isRuntimePlaceholder(data) || this.isEventLike(data)) return;
639
+ handlers.onMessage?.(data || '\n');
638
640
  return;
639
641
  }
640
642
  if (DONE_EVENTS.has(event)) {
@@ -2718,6 +2720,849 @@ function createDOMPurify() {
2718
2720
  }
2719
2721
  var purify = createDOMPurify();
2720
2722
 
2723
+ /**
2724
+ * 预设主题配置
2725
+ * 提供多种常用主题,用户可以直接使用或自定义
2726
+ */
2727
+
2728
+ /**
2729
+ * 默认主题(蓝色渐变)
2730
+ */
2731
+ const DEFAULT_THEME = {
2732
+ name: 'default',
2733
+ label: '默认主题',
2734
+ colors: {
2735
+ primary: '#1890ff',
2736
+ primaryLight: '#40a9ff',
2737
+ primaryDark: '#096dd9',
2738
+ secondary: '#722ed1',
2739
+ background: '#ffffff',
2740
+ backgroundGradient: '#f8fafc',
2741
+ text: '#1e293b',
2742
+ textSecondary: '#64748b',
2743
+ userBubble: 'linear-gradient(135deg, #1890ff, #40a9ff)',
2744
+ aiBubble: '#ffffff',
2745
+ headerGradient: 'linear-gradient(90deg, rgba(24, 144, 255, 0.08), rgba(114, 46, 209, 0.08))',
2746
+ border: 'rgba(24, 144, 255, 0.15)',
2747
+ shadow: 'rgba(24, 144, 255, 0.12)',
2748
+ inputBackground: '#f8fafc',
2749
+ inputBorder: '#e2e8f0',
2750
+ loading: '#64748b',
2751
+ success: '#52c41a',
2752
+ error: '#ff4d4f',
2753
+ warning: '#faad14'
2754
+ },
2755
+ borderRadius: {
2756
+ dialog: '16px',
2757
+ bubble: '12px',
2758
+ button: '50%',
2759
+ input: '28px',
2760
+ small: '6px',
2761
+ medium: '12px'
2762
+ },
2763
+ fontSize: {
2764
+ title: '15px',
2765
+ welcomeText: '17px',
2766
+ welcomeDesc: '13px',
2767
+ message: '14px',
2768
+ time: '11px',
2769
+ small: '11px'
2770
+ },
2771
+ boxShadow: {
2772
+ dialog: '0 0 30px rgba(24, 144, 255, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
2773
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
2774
+ userBubble: '0 4px 12px rgba(24, 144, 255, 0.25)',
2775
+ button: '0 4px 12px rgba(24, 144, 255, 0.35)'
2776
+ }
2777
+ };
2778
+
2779
+ /**
2780
+ * 深色主题
2781
+ */
2782
+ const DARK_THEME = {
2783
+ name: 'dark',
2784
+ label: '深色主题',
2785
+ colors: {
2786
+ primary: '#40a9ff',
2787
+ primaryLight: '#69c0ff',
2788
+ primaryDark: '#1890ff',
2789
+ secondary: '#9254de',
2790
+ background: '#0f172a',
2791
+ backgroundGradient: '#1e293b',
2792
+ text: '#f1f5f9',
2793
+ textSecondary: '#94a3b8',
2794
+ userBubble: 'linear-gradient(135deg, #1890ff, #40a9ff)',
2795
+ aiBubble: '#1e293b',
2796
+ headerGradient: 'linear-gradient(90deg, rgba(64, 169, 255, 0.15), rgba(146, 84, 222, 0.15))',
2797
+ border: 'rgba(64, 169, 255, 0.3)',
2798
+ shadow: 'rgba(0, 0, 0, 0.3)',
2799
+ inputBackground: '#1e293b',
2800
+ inputBorder: '#334155',
2801
+ loading: '#94a3b8',
2802
+ success: '#73d13d',
2803
+ error: '#ff7875',
2804
+ warning: '#ffd666'
2805
+ },
2806
+ borderRadius: {
2807
+ dialog: '16px',
2808
+ bubble: '12px',
2809
+ button: '50%',
2810
+ input: '28px',
2811
+ small: '6px',
2812
+ medium: '12px'
2813
+ },
2814
+ fontSize: {
2815
+ title: '15px',
2816
+ welcomeText: '17px',
2817
+ welcomeDesc: '13px',
2818
+ message: '14px',
2819
+ time: '11px',
2820
+ small: '11px'
2821
+ },
2822
+ boxShadow: {
2823
+ dialog: '0 0 30px rgba(64, 169, 255, 0.15), 0 8px 32px rgba(0, 0, 0, 0.4)',
2824
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.2)',
2825
+ userBubble: '0 4px 12px rgba(24, 144, 255, 0.3)',
2826
+ button: '0 4px 12px rgba(24, 144, 255, 0.4)'
2827
+ }
2828
+ };
2829
+
2830
+ /**
2831
+ * 清新主题(绿色系)
2832
+ */
2833
+ const FRESH_THEME = {
2834
+ name: 'fresh',
2835
+ label: '清新主题',
2836
+ colors: {
2837
+ primary: '#52c41a',
2838
+ primaryLight: '#73d13d',
2839
+ primaryDark: '#389e0d',
2840
+ secondary: '#1890ff',
2841
+ background: '#ffffff',
2842
+ backgroundGradient: '#f6ffed',
2843
+ text: '#1e293b',
2844
+ textSecondary: '#64748b',
2845
+ userBubble: 'linear-gradient(135deg, #52c41a, #73d13d)',
2846
+ aiBubble: '#ffffff',
2847
+ headerGradient: 'linear-gradient(90deg, rgba(82, 196, 26, 0.08), rgba(24, 144, 255, 0.08))',
2848
+ border: 'rgba(82, 196, 26, 0.15)',
2849
+ shadow: 'rgba(82, 196, 26, 0.12)',
2850
+ inputBackground: '#f6ffed',
2851
+ inputBorder: '#d9f7be',
2852
+ loading: '#64748b',
2853
+ success: '#52c41a',
2854
+ error: '#ff4d4f',
2855
+ warning: '#faad14'
2856
+ },
2857
+ borderRadius: {
2858
+ dialog: '20px',
2859
+ bubble: '16px',
2860
+ button: '50%',
2861
+ input: '32px',
2862
+ small: '8px',
2863
+ medium: '16px'
2864
+ },
2865
+ fontSize: {
2866
+ title: '15px',
2867
+ welcomeText: '17px',
2868
+ welcomeDesc: '13px',
2869
+ message: '14px',
2870
+ time: '11px',
2871
+ small: '11px'
2872
+ },
2873
+ boxShadow: {
2874
+ dialog: '0 0 30px rgba(82, 196, 26, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
2875
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
2876
+ userBubble: '0 4px 12px rgba(82, 196, 26, 0.25)',
2877
+ button: '0 4px 12px rgba(82, 196, 26, 0.35)'
2878
+ }
2879
+ };
2880
+
2881
+ /**
2882
+ * 活力主题(橙色系)
2883
+ */
2884
+ const VIBRANT_THEME = {
2885
+ name: 'vibrant',
2886
+ label: '活力主题',
2887
+ colors: {
2888
+ primary: '#fa8c16',
2889
+ primaryLight: '#ffa940',
2890
+ primaryDark: '#d46b08',
2891
+ secondary: '#f5222d',
2892
+ background: '#ffffff',
2893
+ backgroundGradient: '#fff7e6',
2894
+ text: '#1e293b',
2895
+ textSecondary: '#64748b',
2896
+ userBubble: 'linear-gradient(135deg, #fa8c16, #ffa940)',
2897
+ aiBubble: '#ffffff',
2898
+ headerGradient: 'linear-gradient(90deg, rgba(250, 140, 22, 0.08), rgba(245, 34, 45, 0.08))',
2899
+ border: 'rgba(250, 140, 22, 0.15)',
2900
+ shadow: 'rgba(250, 140, 22, 0.12)',
2901
+ inputBackground: '#fff7e6',
2902
+ inputBorder: '#ffd591',
2903
+ loading: '#64748b',
2904
+ success: '#52c41a',
2905
+ error: '#ff4d4f',
2906
+ warning: '#faad14'
2907
+ },
2908
+ borderRadius: {
2909
+ dialog: '12px',
2910
+ bubble: '10px',
2911
+ button: '50%',
2912
+ input: '24px',
2913
+ small: '4px',
2914
+ medium: '10px'
2915
+ },
2916
+ fontSize: {
2917
+ title: '15px',
2918
+ welcomeText: '17px',
2919
+ welcomeDesc: '13px',
2920
+ message: '14px',
2921
+ time: '11px',
2922
+ small: '11px'
2923
+ },
2924
+ boxShadow: {
2925
+ dialog: '0 0 30px rgba(250, 140, 22, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
2926
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
2927
+ userBubble: '0 4px 12px rgba(250, 140, 22, 0.25)',
2928
+ button: '0 4px 12px rgba(250, 140, 22, 0.35)'
2929
+ }
2930
+ };
2931
+
2932
+ /**
2933
+ * 浪漫主题(粉色系)
2934
+ */
2935
+ const ROMANTIC_THEME = {
2936
+ name: 'romantic',
2937
+ label: '浪漫主题',
2938
+ colors: {
2939
+ primary: '#eb2f96',
2940
+ primaryLight: '#fb6f92',
2941
+ primaryDark: '#c41d7f',
2942
+ secondary: '#722ed1',
2943
+ background: '#ffffff',
2944
+ backgroundGradient: '#fff0f6',
2945
+ text: '#1e293b',
2946
+ textSecondary: '#64748b',
2947
+ userBubble: 'linear-gradient(135deg, #eb2f96, #fb6f92)',
2948
+ aiBubble: '#ffffff',
2949
+ headerGradient: 'linear-gradient(90deg, rgba(235, 47, 150, 0.08), rgba(114, 46, 209, 0.08))',
2950
+ border: 'rgba(235, 47, 150, 0.15)',
2951
+ shadow: 'rgba(235, 47, 150, 0.12)',
2952
+ inputBackground: '#fff0f6',
2953
+ inputBorder: '#ffadd2',
2954
+ loading: '#64748b',
2955
+ success: '#52c41a',
2956
+ error: '#ff4d4f',
2957
+ warning: '#faad14'
2958
+ },
2959
+ borderRadius: {
2960
+ dialog: '24px',
2961
+ bubble: '16px',
2962
+ button: '50%',
2963
+ input: '32px',
2964
+ small: '8px',
2965
+ medium: '16px'
2966
+ },
2967
+ fontSize: {
2968
+ title: '15px',
2969
+ welcomeText: '17px',
2970
+ welcomeDesc: '13px',
2971
+ message: '14px',
2972
+ time: '11px',
2973
+ small: '11px'
2974
+ },
2975
+ boxShadow: {
2976
+ dialog: '0 0 30px rgba(235, 47, 150, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
2977
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
2978
+ userBubble: '0 4px 12px rgba(235, 47, 150, 0.25)',
2979
+ button: '0 4px 12px rgba(235, 47, 150, 0.35)'
2980
+ }
2981
+ };
2982
+
2983
+ /**
2984
+ * 紫色主题(优雅神秘)
2985
+ */
2986
+ const PURPLE_THEME = {
2987
+ name: 'purple',
2988
+ label: '紫色主题',
2989
+ colors: {
2990
+ primary: '#722ed1',
2991
+ primaryLight: '#9254de',
2992
+ primaryDark: '#531dab',
2993
+ secondary: '#1890ff',
2994
+ background: '#ffffff',
2995
+ backgroundGradient: '#f9f0ff',
2996
+ text: '#1e293b',
2997
+ textSecondary: '#64748b',
2998
+ userBubble: 'linear-gradient(135deg, #722ed1, #9254de)',
2999
+ aiBubble: '#ffffff',
3000
+ headerGradient: 'linear-gradient(90deg, rgba(114, 46, 209, 0.08), rgba(24, 144, 255, 0.08))',
3001
+ border: 'rgba(114, 46, 209, 0.15)',
3002
+ shadow: 'rgba(114, 46, 209, 0.12)',
3003
+ inputBackground: '#f9f0ff',
3004
+ inputBorder: '#d3adf7',
3005
+ loading: '#64748b',
3006
+ success: '#52c41a',
3007
+ error: '#ff4d4f',
3008
+ warning: '#faad14'
3009
+ },
3010
+ borderRadius: {
3011
+ dialog: '16px',
3012
+ bubble: '12px',
3013
+ button: '50%',
3014
+ input: '28px',
3015
+ small: '6px',
3016
+ medium: '12px'
3017
+ },
3018
+ fontSize: {
3019
+ title: '15px',
3020
+ welcomeText: '17px',
3021
+ welcomeDesc: '13px',
3022
+ message: '14px',
3023
+ time: '11px',
3024
+ small: '11px'
3025
+ },
3026
+ boxShadow: {
3027
+ dialog: '0 0 30px rgba(114, 46, 209, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3028
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3029
+ userBubble: '0 4px 12px rgba(114, 46, 209, 0.25)',
3030
+ button: '0 4px 12px rgba(114, 46, 209, 0.35)'
3031
+ }
3032
+ };
3033
+
3034
+ /**
3035
+ * 海洋主题(深蓝深海)
3036
+ */
3037
+ const OCEAN_THEME = {
3038
+ name: 'ocean',
3039
+ label: '海洋主题',
3040
+ colors: {
3041
+ primary: '#0077b6',
3042
+ primaryLight: '#00b4d8',
3043
+ primaryDark: '#023e8a',
3044
+ secondary: '#00b4d8',
3045
+ background: '#ffffff',
3046
+ backgroundGradient: '#f0f9ff',
3047
+ text: '#1e293b',
3048
+ textSecondary: '#64748b',
3049
+ userBubble: 'linear-gradient(135deg, #0077b6, #00b4d8)',
3050
+ aiBubble: '#ffffff',
3051
+ headerGradient: 'linear-gradient(90deg, rgba(0, 119, 182, 0.08), rgba(0, 180, 216, 0.08))',
3052
+ border: 'rgba(0, 119, 182, 0.15)',
3053
+ shadow: 'rgba(0, 119, 182, 0.12)',
3054
+ inputBackground: '#f0f9ff',
3055
+ inputBorder: '#bae6fd',
3056
+ loading: '#64748b',
3057
+ success: '#52c41a',
3058
+ error: '#ff4d4f',
3059
+ warning: '#faad14'
3060
+ },
3061
+ borderRadius: {
3062
+ dialog: '14px',
3063
+ bubble: '10px',
3064
+ button: '50%',
3065
+ input: '28px',
3066
+ small: '6px',
3067
+ medium: '12px'
3068
+ },
3069
+ fontSize: {
3070
+ title: '15px',
3071
+ welcomeText: '17px',
3072
+ welcomeDesc: '13px',
3073
+ message: '14px',
3074
+ time: '11px',
3075
+ small: '11px'
3076
+ },
3077
+ boxShadow: {
3078
+ dialog: '0 0 30px rgba(0, 119, 182, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3079
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3080
+ userBubble: '0 4px 12px rgba(0, 119, 182, 0.25)',
3081
+ button: '0 4px 12px rgba(0, 119, 182, 0.35)'
3082
+ }
3083
+ };
3084
+
3085
+ /**
3086
+ * 暮光主题(紫罗兰渐变)
3087
+ */
3088
+ const TWILIGHT_THEME = {
3089
+ name: 'twilight',
3090
+ label: '暮光主题',
3091
+ colors: {
3092
+ primary: '#9333ea',
3093
+ primaryLight: '#a855f7',
3094
+ primaryDark: '#7e22ce',
3095
+ secondary: '#ec4899',
3096
+ background: '#ffffff',
3097
+ backgroundGradient: '#faf5ff',
3098
+ text: '#1e293b',
3099
+ textSecondary: '#64748b',
3100
+ userBubble: 'linear-gradient(135deg, #9333ea, #ec4899)',
3101
+ aiBubble: '#ffffff',
3102
+ headerGradient: 'linear-gradient(90deg, rgba(147, 51, 234, 0.08), rgba(236, 72, 153, 0.08))',
3103
+ border: 'rgba(147, 51, 234, 0.15)',
3104
+ shadow: 'rgba(147, 51, 234, 0.12)',
3105
+ inputBackground: '#faf5ff',
3106
+ inputBorder: '#e9d5ff',
3107
+ loading: '#64748b',
3108
+ success: '#52c41a',
3109
+ error: '#ff4d4f',
3110
+ warning: '#faad14'
3111
+ },
3112
+ borderRadius: {
3113
+ dialog: '18px',
3114
+ bubble: '14px',
3115
+ button: '50%',
3116
+ input: '30px',
3117
+ small: '8px',
3118
+ medium: '14px'
3119
+ },
3120
+ fontSize: {
3121
+ title: '15px',
3122
+ welcomeText: '17px',
3123
+ welcomeDesc: '13px',
3124
+ message: '14px',
3125
+ time: '11px',
3126
+ small: '11px'
3127
+ },
3128
+ boxShadow: {
3129
+ dialog: '0 0 30px rgba(147, 51, 234, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3130
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3131
+ userBubble: '0 4px 12px rgba(147, 51, 234, 0.25)',
3132
+ button: '0 4px 12px rgba(147, 51, 234, 0.35)'
3133
+ }
3134
+ };
3135
+
3136
+ /**
3137
+ * 薄荷主题(青绿色)
3138
+ */
3139
+ const MINT_THEME = {
3140
+ name: 'mint',
3141
+ label: '薄荷主题',
3142
+ colors: {
3143
+ primary: '#14b8a6',
3144
+ primaryLight: '#2dd4bf',
3145
+ primaryDark: '#0d9488',
3146
+ secondary: '#06b6d4',
3147
+ background: '#ffffff',
3148
+ backgroundGradient: '#f0fdfa',
3149
+ text: '#1e293b',
3150
+ textSecondary: '#64748b',
3151
+ userBubble: 'linear-gradient(135deg, #14b8a6, #2dd4bf)',
3152
+ aiBubble: '#ffffff',
3153
+ headerGradient: 'linear-gradient(90deg, rgba(20, 184, 166, 0.08), rgba(6, 182, 212, 0.08))',
3154
+ border: 'rgba(20, 184, 166, 0.15)',
3155
+ shadow: 'rgba(20, 184, 166, 0.12)',
3156
+ inputBackground: '#f0fdfa',
3157
+ inputBorder: '#99f6e4',
3158
+ loading: '#64748b',
3159
+ success: '#52c41a',
3160
+ error: '#ff4d4f',
3161
+ warning: '#faad14'
3162
+ },
3163
+ borderRadius: {
3164
+ dialog: '16px',
3165
+ bubble: '12px',
3166
+ button: '50%',
3167
+ input: '28px',
3168
+ small: '6px',
3169
+ medium: '12px'
3170
+ },
3171
+ fontSize: {
3172
+ title: '15px',
3173
+ welcomeText: '17px',
3174
+ welcomeDesc: '13px',
3175
+ message: '14px',
3176
+ time: '11px',
3177
+ small: '11px'
3178
+ },
3179
+ boxShadow: {
3180
+ dialog: '0 0 30px rgba(20, 184, 166, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3181
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3182
+ userBubble: '0 4px 12px rgba(20, 184, 166, 0.25)',
3183
+ button: '0 4px 12px rgba(20, 184, 166, 0.35)'
3184
+ }
3185
+ };
3186
+
3187
+ /**
3188
+ * 玫瑰主题(深红色)
3189
+ */
3190
+ const ROSE_THEME = {
3191
+ name: 'rose',
3192
+ label: '玫瑰主题',
3193
+ colors: {
3194
+ primary: '#e11d48',
3195
+ primaryLight: '#fb7185',
3196
+ primaryDark: '#be123c',
3197
+ secondary: '#f43f5e',
3198
+ background: '#ffffff',
3199
+ backgroundGradient: '#fff1f2',
3200
+ text: '#1e293b',
3201
+ textSecondary: '#64748b',
3202
+ userBubble: 'linear-gradient(135deg, #e11d48, #fb7185)',
3203
+ aiBubble: '#ffffff',
3204
+ headerGradient: 'linear-gradient(90deg, rgba(225, 29, 72, 0.08), rgba(244, 63, 94, 0.08))',
3205
+ border: 'rgba(225, 29, 72, 0.15)',
3206
+ shadow: 'rgba(225, 29, 72, 0.12)',
3207
+ inputBackground: '#fff1f2',
3208
+ inputBorder: '#fecdd3',
3209
+ loading: '#64748b',
3210
+ success: '#52c41a',
3211
+ error: '#ff4d4f',
3212
+ warning: '#faad14'
3213
+ },
3214
+ borderRadius: {
3215
+ dialog: '16px',
3216
+ bubble: '12px',
3217
+ button: '50%',
3218
+ input: '28px',
3219
+ small: '6px',
3220
+ medium: '12px'
3221
+ },
3222
+ fontSize: {
3223
+ title: '15px',
3224
+ welcomeText: '17px',
3225
+ welcomeDesc: '13px',
3226
+ message: '14px',
3227
+ time: '11px',
3228
+ small: '11px'
3229
+ },
3230
+ boxShadow: {
3231
+ dialog: '0 0 30px rgba(225, 29, 72, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3232
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3233
+ userBubble: '0 4px 12px rgba(225, 29, 72, 0.25)',
3234
+ button: '0 4px 12px rgba(225, 29, 72, 0.35)'
3235
+ }
3236
+ };
3237
+
3238
+ /**
3239
+ * 极光主题(蓝绿渐变)
3240
+ */
3241
+ const AURORA_THEME = {
3242
+ name: 'aurora',
3243
+ label: '极光主题',
3244
+ colors: {
3245
+ primary: '#0ea5e9',
3246
+ primaryLight: '#38bdf8',
3247
+ primaryDark: '#0284c7',
3248
+ secondary: '#10b981',
3249
+ background: '#ffffff',
3250
+ backgroundGradient: '#f0f9ff',
3251
+ text: '#1e293b',
3252
+ textSecondary: '#64748b',
3253
+ userBubble: 'linear-gradient(135deg, #0ea5e9, #10b981)',
3254
+ aiBubble: '#ffffff',
3255
+ headerGradient: 'linear-gradient(90deg, rgba(14, 165, 233, 0.08), rgba(16, 185, 129, 0.08))',
3256
+ border: 'rgba(14, 165, 233, 0.15)',
3257
+ shadow: 'rgba(14, 165, 233, 0.12)',
3258
+ inputBackground: '#f0f9ff',
3259
+ inputBorder: '#bae6fd',
3260
+ loading: '#64748b',
3261
+ success: '#52c41a',
3262
+ error: '#ff4d4f',
3263
+ warning: '#faad14'
3264
+ },
3265
+ borderRadius: {
3266
+ dialog: '20px',
3267
+ bubble: '14px',
3268
+ button: '50%',
3269
+ input: '30px',
3270
+ small: '8px',
3271
+ medium: '14px'
3272
+ },
3273
+ fontSize: {
3274
+ title: '15px',
3275
+ welcomeText: '17px',
3276
+ welcomeDesc: '13px',
3277
+ message: '14px',
3278
+ time: '11px',
3279
+ small: '11px'
3280
+ },
3281
+ boxShadow: {
3282
+ dialog: '0 0 30px rgba(14, 165, 233, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3283
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3284
+ userBubble: '0 4px 12px rgba(14, 165, 233, 0.25)',
3285
+ button: '0 4px 12px rgba(14, 165, 233, 0.35)'
3286
+ }
3287
+ };
3288
+
3289
+ /**
3290
+ * 薰衣草主题(淡紫色)
3291
+ */
3292
+ const LAVENDER_THEME = {
3293
+ name: 'lavender',
3294
+ label: '薰衣草主题',
3295
+ colors: {
3296
+ primary: '#8b5cf6',
3297
+ primaryLight: '#a78bfa',
3298
+ primaryDark: '#7c3aed',
3299
+ secondary: '#c084fc',
3300
+ background: '#ffffff',
3301
+ backgroundGradient: '#faf5ff',
3302
+ text: '#1e293b',
3303
+ textSecondary: '#64748b',
3304
+ userBubble: 'linear-gradient(135deg, #8b5cf6, #c084fc)',
3305
+ aiBubble: '#ffffff',
3306
+ headerGradient: 'linear-gradient(90deg, rgba(139, 92, 246, 0.08), rgba(192, 132, 252, 0.08))',
3307
+ border: 'rgba(139, 92, 246, 0.15)',
3308
+ shadow: 'rgba(139, 92, 246, 0.12)',
3309
+ inputBackground: '#faf5ff',
3310
+ inputBorder: '#ddd6fe',
3311
+ loading: '#64748b',
3312
+ success: '#52c41a',
3313
+ error: '#ff4d4f',
3314
+ warning: '#faad14'
3315
+ },
3316
+ borderRadius: {
3317
+ dialog: '22px',
3318
+ bubble: '16px',
3319
+ button: '50%',
3320
+ input: '32px',
3321
+ small: '8px',
3322
+ medium: '16px'
3323
+ },
3324
+ fontSize: {
3325
+ title: '15px',
3326
+ welcomeText: '17px',
3327
+ welcomeDesc: '13px',
3328
+ message: '14px',
3329
+ time: '11px',
3330
+ small: '11px'
3331
+ },
3332
+ boxShadow: {
3333
+ dialog: '0 0 30px rgba(139, 92, 246, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3334
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3335
+ userBubble: '0 4px 12px rgba(139, 92, 246, 0.25)',
3336
+ button: '0 4px 12px rgba(139, 92, 246, 0.35)'
3337
+ }
3338
+ };
3339
+
3340
+ /**
3341
+ * 珊瑚主题(粉橙色)
3342
+ */
3343
+ const CORAL_THEME = {
3344
+ name: 'coral',
3345
+ label: '珊瑚主题',
3346
+ colors: {
3347
+ primary: '#f97316',
3348
+ primaryLight: '#fb923c',
3349
+ primaryDark: '#ea580c',
3350
+ secondary: '#f43f5e',
3351
+ background: '#ffffff',
3352
+ backgroundGradient: '#fff7ed',
3353
+ text: '#1e293b',
3354
+ textSecondary: '#64748b',
3355
+ userBubble: 'linear-gradient(135deg, #f97316, #fb923c)',
3356
+ aiBubble: '#ffffff',
3357
+ headerGradient: 'linear-gradient(90deg, rgba(249, 115, 22, 0.08), rgba(244, 63, 94, 0.08))',
3358
+ border: 'rgba(249, 115, 22, 0.15)',
3359
+ shadow: 'rgba(249, 115, 22, 0.12)',
3360
+ inputBackground: '#fff7ed',
3361
+ inputBorder: '#fed7aa',
3362
+ loading: '#64748b',
3363
+ success: '#52c41a',
3364
+ error: '#ff4d4f',
3365
+ warning: '#faad14'
3366
+ },
3367
+ borderRadius: {
3368
+ dialog: '14px',
3369
+ bubble: '10px',
3370
+ button: '50%',
3371
+ input: '26px',
3372
+ small: '6px',
3373
+ medium: '10px'
3374
+ },
3375
+ fontSize: {
3376
+ title: '15px',
3377
+ welcomeText: '17px',
3378
+ welcomeDesc: '13px',
3379
+ message: '14px',
3380
+ time: '11px',
3381
+ small: '11px'
3382
+ },
3383
+ boxShadow: {
3384
+ dialog: '0 0 30px rgba(249, 115, 22, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3385
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3386
+ userBubble: '0 4px 12px rgba(249, 115, 22, 0.25)',
3387
+ button: '0 4px 12px rgba(249, 115, 22, 0.35)'
3388
+ }
3389
+ };
3390
+
3391
+ /**
3392
+ * 翡翠主题(深绿色)
3393
+ */
3394
+ const JADE_THEME = {
3395
+ name: 'jade',
3396
+ label: '翡翠主题',
3397
+ colors: {
3398
+ primary: '#059669',
3399
+ primaryLight: '#10b981',
3400
+ primaryDark: '#047857',
3401
+ secondary: '#34d399',
3402
+ background: '#ffffff',
3403
+ backgroundGradient: '#f0fdf4',
3404
+ text: '#1e293b',
3405
+ textSecondary: '#64748b',
3406
+ userBubble: 'linear-gradient(135deg, #059669, #10b981)',
3407
+ aiBubble: '#ffffff',
3408
+ headerGradient: 'linear-gradient(90deg, rgba(5, 150, 105, 0.08), rgba(52, 211, 153, 0.08))',
3409
+ border: 'rgba(5, 150, 105, 0.15)',
3410
+ shadow: 'rgba(5, 150, 105, 0.12)',
3411
+ inputBackground: '#f0fdf4',
3412
+ inputBorder: '#bbf7d0',
3413
+ loading: '#64748b',
3414
+ success: '#52c41a',
3415
+ error: '#ff4d4f',
3416
+ warning: '#faad14'
3417
+ },
3418
+ borderRadius: {
3419
+ dialog: '16px',
3420
+ bubble: '12px',
3421
+ button: '50%',
3422
+ input: '28px',
3423
+ small: '6px',
3424
+ medium: '12px'
3425
+ },
3426
+ fontSize: {
3427
+ title: '15px',
3428
+ welcomeText: '17px',
3429
+ welcomeDesc: '13px',
3430
+ message: '14px',
3431
+ time: '11px',
3432
+ small: '11px'
3433
+ },
3434
+ boxShadow: {
3435
+ dialog: '0 0 30px rgba(5, 150, 105, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3436
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3437
+ userBubble: '0 4px 12px rgba(5, 150, 105, 0.25)',
3438
+ button: '0 4px 12px rgba(5, 150, 105, 0.35)'
3439
+ }
3440
+ };
3441
+
3442
+ /**
3443
+ * 星空主题(深蓝紫色)
3444
+ */
3445
+ const STARSKY_THEME = {
3446
+ name: 'starsky',
3447
+ label: '星空主题',
3448
+ colors: {
3449
+ primary: '#6366f1',
3450
+ primaryLight: '#818cf8',
3451
+ primaryDark: '#4f46e5',
3452
+ secondary: '#a855f7',
3453
+ background: '#0f172a',
3454
+ backgroundGradient: '#1e1b4b',
3455
+ text: '#e2e8f0',
3456
+ textSecondary: '#94a3b8',
3457
+ userBubble: 'linear-gradient(135deg, #6366f1, #a855f7)',
3458
+ aiBubble: '#1e1b4b',
3459
+ headerGradient: 'linear-gradient(90deg, rgba(99, 102, 241, 0.15), rgba(168, 85, 247, 0.15))',
3460
+ border: 'rgba(99, 102, 241, 0.3)',
3461
+ shadow: 'rgba(0, 0, 0, 0.3)',
3462
+ inputBackground: '#1e1b4b',
3463
+ inputBorder: '#312e81',
3464
+ loading: '#94a3b8',
3465
+ success: '#34d399',
3466
+ error: '#f87171',
3467
+ warning: '#fbbf24'
3468
+ },
3469
+ borderRadius: {
3470
+ dialog: '18px',
3471
+ bubble: '14px',
3472
+ button: '50%',
3473
+ input: '30px',
3474
+ small: '8px',
3475
+ medium: '14px'
3476
+ },
3477
+ fontSize: {
3478
+ title: '15px',
3479
+ welcomeText: '17px',
3480
+ welcomeDesc: '13px',
3481
+ message: '14px',
3482
+ time: '11px',
3483
+ small: '11px'
3484
+ },
3485
+ boxShadow: {
3486
+ dialog: '0 0 30px rgba(99, 102, 241, 0.2), 0 8px 32px rgba(0, 0, 0, 0.4)',
3487
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.2)',
3488
+ userBubble: '0 4px 12px rgba(99, 102, 241, 0.3)',
3489
+ button: '0 4px 12px rgba(99, 102, 241, 0.4)'
3490
+ }
3491
+ };
3492
+
3493
+ /**
3494
+ * 日落主题(暖色调)
3495
+ */
3496
+ const SUNSET_THEME = {
3497
+ name: 'sunset',
3498
+ label: '日落主题',
3499
+ colors: {
3500
+ primary: '#ea580c',
3501
+ primaryLight: '#f97316',
3502
+ primaryDark: '#c2410c',
3503
+ secondary: '#dc2626',
3504
+ background: '#ffffff',
3505
+ backgroundGradient: '#fff8f0',
3506
+ text: '#1e293b',
3507
+ textSecondary: '#64748b',
3508
+ userBubble: 'linear-gradient(135deg, #ea580c, #dc2626)',
3509
+ aiBubble: '#ffffff',
3510
+ headerGradient: 'linear-gradient(90deg, rgba(234, 88, 12, 0.08), rgba(220, 38, 38, 0.08))',
3511
+ border: 'rgba(234, 88, 12, 0.15)',
3512
+ shadow: 'rgba(234, 88, 12, 0.12)',
3513
+ inputBackground: '#fff8f0',
3514
+ inputBorder: '#fed7aa',
3515
+ loading: '#64748b',
3516
+ success: '#52c41a',
3517
+ error: '#ff4d4f',
3518
+ warning: '#faad14'
3519
+ },
3520
+ borderRadius: {
3521
+ dialog: '16px',
3522
+ bubble: '12px',
3523
+ button: '50%',
3524
+ input: '28px',
3525
+ small: '6px',
3526
+ medium: '12px'
3527
+ },
3528
+ fontSize: {
3529
+ title: '15px',
3530
+ welcomeText: '17px',
3531
+ welcomeDesc: '13px',
3532
+ message: '14px',
3533
+ time: '11px',
3534
+ small: '11px'
3535
+ },
3536
+ boxShadow: {
3537
+ dialog: '0 0 30px rgba(234, 88, 12, 0.12), 0 8px 32px rgba(0, 0, 0, 0.1)',
3538
+ bubble: '0 2px 8px rgba(0, 0, 0, 0.06)',
3539
+ userBubble: '0 4px 12px rgba(234, 88, 12, 0.25)',
3540
+ button: '0 4px 12px rgba(234, 88, 12, 0.35)'
3541
+ }
3542
+ };
3543
+
3544
+ /**
3545
+ * 所有预设主题列表
3546
+ */
3547
+ const PRESET_THEMES = {
3548
+ DEFAULT: DEFAULT_THEME,
3549
+ DARK: DARK_THEME,
3550
+ FRESH: FRESH_THEME,
3551
+ VIBRANT: VIBRANT_THEME,
3552
+ ROMANTIC: ROMANTIC_THEME,
3553
+ PURPLE: PURPLE_THEME,
3554
+ OCEAN: OCEAN_THEME,
3555
+ TWILIGHT: TWILIGHT_THEME,
3556
+ MINT: MINT_THEME,
3557
+ ROSE: ROSE_THEME,
3558
+ AURORA: AURORA_THEME,
3559
+ LAVENDER: LAVENDER_THEME,
3560
+ CORAL: CORAL_THEME,
3561
+ JADE: JADE_THEME,
3562
+ STARSKY: STARSKY_THEME,
3563
+ SUNSET: SUNSET_THEME
3564
+ };
3565
+
2721
3566
  /**
2722
3567
  * AIChatDialog - 纯JavaScript实现的AI对话组件 (Web Components)
2723
3568
  * 样式与功能完全对齐 Vue 版本(1:1 复刻)
@@ -2772,312 +3617,6 @@ const THEME_COLOR_KEY_MAP = {
2772
3617
  };
2773
3618
 
2774
3619
  // ========== 16种预设主题(与Vue版themes.js完全一致) ==========
2775
- const PRESET_THEMES = {
2776
- DEFAULT: {
2777
- colors: {
2778
- primary: '#1890ff',
2779
- primaryLight: '#40a9ff',
2780
- primaryDark: '#096dd9',
2781
- secondary: '#722ed1',
2782
- background: '#ffffff',
2783
- backgroundGradient: '#f8fafc',
2784
- text: '#1e293b',
2785
- textSecondary: '#64748b',
2786
- userBubble: 'linear-gradient(135deg, #1890ff, #40a9ff)',
2787
- aiBubble: '#ffffff',
2788
- headerGradient: 'linear-gradient(90deg, rgba(24,144,255,0.08), rgba(114,46,209,0.08))',
2789
- border: 'rgba(24,144,255,0.15)',
2790
- shadow: 'rgba(24,144,255,0.12)',
2791
- inputBackground: '#f8fafc',
2792
- inputBorder: '#e2e8f0'
2793
- }
2794
- },
2795
- DARK: {
2796
- colors: {
2797
- primary: '#40a9ff',
2798
- primaryLight: '#69c0ff',
2799
- primaryDark: '#1890ff',
2800
- secondary: '#9254de',
2801
- background: '#0f172a',
2802
- backgroundGradient: '#1e293b',
2803
- text: '#f1f5f9',
2804
- textSecondary: '#94a3b8',
2805
- userBubble: 'linear-gradient(135deg, #1890ff, #40a9ff)',
2806
- aiBubble: '#1e293b',
2807
- headerGradient: 'linear-gradient(90deg, rgba(64,169,255,0.15), rgba(146,84,222,0.15))',
2808
- border: 'rgba(64,169,255,0.3)',
2809
- shadow: 'rgba(0,0,0,0.3)',
2810
- inputBackground: '#1e293b',
2811
- inputBorder: '#334155'
2812
- }
2813
- },
2814
- FRESH: {
2815
- colors: {
2816
- primary: '#52c41a',
2817
- primaryLight: '#73d13d',
2818
- primaryDark: '#389e0d',
2819
- secondary: '#1890ff',
2820
- background: '#ffffff',
2821
- backgroundGradient: '#f6ffed',
2822
- text: '#1e293b',
2823
- textSecondary: '#64748b',
2824
- userBubble: 'linear-gradient(135deg, #52c41a, #73d13d)',
2825
- aiBubble: '#ffffff',
2826
- headerGradient: 'linear-gradient(90deg, rgba(82,196,26,0.08), rgba(24,144,255,0.08))',
2827
- border: 'rgba(82,196,26,0.15)',
2828
- shadow: 'rgba(82,196,26,0.12)',
2829
- inputBackground: '#f6ffed',
2830
- inputBorder: '#d9f7be'
2831
- }
2832
- },
2833
- VIBRANT: {
2834
- colors: {
2835
- primary: '#fa8c16',
2836
- primaryLight: '#ffa940',
2837
- primaryDark: '#d46b08',
2838
- secondary: '#f5222d',
2839
- background: '#ffffff',
2840
- backgroundGradient: '#fff7e6',
2841
- text: '#1e293b',
2842
- textSecondary: '#64748b',
2843
- userBubble: 'linear-gradient(135deg, #fa8c16, #ffa940)',
2844
- aiBubble: '#ffffff',
2845
- headerGradient: 'linear-gradient(90deg, rgba(250,140,22,0.08), rgba(245,34,45,0.08))',
2846
- border: 'rgba(250,140,22,0.15)',
2847
- shadow: 'rgba(250,140,22,0.12)',
2848
- inputBackground: '#fff7e6',
2849
- inputBorder: '#ffd591'
2850
- }
2851
- },
2852
- ROMANTIC: {
2853
- colors: {
2854
- primary: '#eb2f96',
2855
- primaryLight: '#fb6f92',
2856
- primaryDark: '#c41d7f',
2857
- secondary: '#722ed1',
2858
- background: '#ffffff',
2859
- backgroundGradient: '#fff0f6',
2860
- text: '#1e293b',
2861
- textSecondary: '#64748b',
2862
- userBubble: 'linear-gradient(135deg, #eb2f96, #fb6f92)',
2863
- aiBubble: '#ffffff',
2864
- headerGradient: 'linear-gradient(90deg, rgba(235,47,150,0.08), rgba(114,46,209,0.08))',
2865
- border: 'rgba(235,47,150,0.15)',
2866
- shadow: 'rgba(235,47,150,0.12)',
2867
- inputBackground: '#fff0f6',
2868
- inputBorder: '#ffadd2'
2869
- }
2870
- },
2871
- PURPLE: {
2872
- colors: {
2873
- primary: '#722ed1',
2874
- primaryLight: '#9254de',
2875
- primaryDark: '#531dab',
2876
- secondary: '#1890ff',
2877
- background: '#ffffff',
2878
- backgroundGradient: '#f9f0ff',
2879
- text: '#1e293b',
2880
- textSecondary: '#64748b',
2881
- userBubble: 'linear-gradient(135deg, #722ed1, #9254de)',
2882
- aiBubble: '#ffffff',
2883
- headerGradient: 'linear-gradient(90deg, rgba(114,46,209,0.08), rgba(24,144,255,0.08))',
2884
- border: 'rgba(114,46,209,0.15)',
2885
- shadow: 'rgba(114,46,209,0.12)',
2886
- inputBackground: '#f9f0ff',
2887
- inputBorder: '#d3adf7'
2888
- }
2889
- },
2890
- OCEAN: {
2891
- colors: {
2892
- primary: '#0077b6',
2893
- primaryLight: '#00b4d8',
2894
- primaryDark: '#023e8a',
2895
- secondary: '#00b4d8',
2896
- background: '#ffffff',
2897
- backgroundGradient: '#f0f9ff',
2898
- text: '#1e293b',
2899
- textSecondary: '#64748b',
2900
- userBubble: 'linear-gradient(135deg, #0077b6, #00b4d8)',
2901
- aiBubble: '#ffffff',
2902
- headerGradient: 'linear-gradient(90deg, rgba(0,119,182,0.08), rgba(0,180,216,0.08))',
2903
- border: 'rgba(0,119,182,0.15)',
2904
- shadow: 'rgba(0,119,182,0.12)',
2905
- inputBackground: '#f0f9ff',
2906
- inputBorder: '#bae6fd'
2907
- }
2908
- },
2909
- TWILIGHT: {
2910
- colors: {
2911
- primary: '#9333ea',
2912
- primaryLight: '#a855f7',
2913
- primaryDark: '#7e22ce',
2914
- secondary: '#ec4899',
2915
- background: '#ffffff',
2916
- backgroundGradient: '#faf5ff',
2917
- text: '#1e293b',
2918
- textSecondary: '#64748b',
2919
- userBubble: 'linear-gradient(135deg, #9333ea, #ec4899)',
2920
- aiBubble: '#ffffff',
2921
- headerGradient: 'linear-gradient(90deg, rgba(147,51,234,0.08), rgba(236,72,153,0.08))',
2922
- border: 'rgba(147,51,234,0.15)',
2923
- shadow: 'rgba(147,51,234,0.12)',
2924
- inputBackground: '#faf5ff',
2925
- inputBorder: '#e9d5ff'
2926
- }
2927
- },
2928
- MINT: {
2929
- colors: {
2930
- primary: '#14b8a6',
2931
- primaryLight: '#2dd4bf',
2932
- primaryDark: '#0d9488',
2933
- secondary: '#06b6d4',
2934
- background: '#ffffff',
2935
- backgroundGradient: '#f0fdfa',
2936
- text: '#1e293b',
2937
- textSecondary: '#64748b',
2938
- userBubble: 'linear-gradient(135deg, #14b8a6, #2dd4bf)',
2939
- aiBubble: '#ffffff',
2940
- headerGradient: 'linear-gradient(90deg, rgba(20,184,166,0.08), rgba(6,182,212,0.08))',
2941
- border: 'rgba(20,184,166,0.15)',
2942
- shadow: 'rgba(20,184,166,0.12)',
2943
- inputBackground: '#f0fdfa',
2944
- inputBorder: '#99f6e4'
2945
- }
2946
- },
2947
- ROSE: {
2948
- colors: {
2949
- primary: '#e11d48',
2950
- primaryLight: '#fb7185',
2951
- primaryDark: '#be123c',
2952
- secondary: '#f43f5e',
2953
- background: '#ffffff',
2954
- backgroundGradient: '#fff1f2',
2955
- text: '#1e293b',
2956
- textSecondary: '#64748b',
2957
- userBubble: 'linear-gradient(135deg, #e11d48, #fb7185)',
2958
- aiBubble: '#ffffff',
2959
- headerGradient: 'linear-gradient(90deg, rgba(225,29,72,0.08), rgba(244,63,94,0.08))',
2960
- border: 'rgba(225,29,72,0.15)',
2961
- shadow: 'rgba(225,29,72,0.12)',
2962
- inputBackground: '#fff1f2',
2963
- inputBorder: '#fecdd3'
2964
- }
2965
- },
2966
- AURORA: {
2967
- colors: {
2968
- primary: '#0ea5e9',
2969
- primaryLight: '#38bdf8',
2970
- primaryDark: '#0284c7',
2971
- secondary: '#10b981',
2972
- background: '#ffffff',
2973
- backgroundGradient: '#f0f9ff',
2974
- text: '#1e293b',
2975
- textSecondary: '#64748b',
2976
- userBubble: 'linear-gradient(135deg, #0ea5e9, #10b981)',
2977
- aiBubble: '#ffffff',
2978
- headerGradient: 'linear-gradient(90deg, rgba(14,165,233,0.08), rgba(16,185,129,0.08))',
2979
- border: 'rgba(14,165,233,0.15)',
2980
- shadow: 'rgba(14,165,233,0.12)',
2981
- inputBackground: '#f0f9ff',
2982
- inputBorder: '#bae6fd'
2983
- }
2984
- },
2985
- LAVENDER: {
2986
- colors: {
2987
- primary: '#8b5cf6',
2988
- primaryLight: '#a78bfa',
2989
- primaryDark: '#7c3aed',
2990
- secondary: '#c084fc',
2991
- background: '#ffffff',
2992
- backgroundGradient: '#faf5ff',
2993
- text: '#1e293b',
2994
- textSecondary: '#64748b',
2995
- userBubble: 'linear-gradient(135deg, #8b5cf6, #c084fc)',
2996
- aiBubble: '#ffffff',
2997
- headerGradient: 'linear-gradient(90deg, rgba(139,92,246,0.08), rgba(192,132,252,0.08))',
2998
- border: 'rgba(139,92,246,0.15)',
2999
- shadow: 'rgba(139,92,246,0.12)',
3000
- inputBackground: '#faf5ff',
3001
- inputBorder: '#ddd6fe'
3002
- }
3003
- },
3004
- CORAL: {
3005
- colors: {
3006
- primary: '#f97316',
3007
- primaryLight: '#fb923c',
3008
- primaryDark: '#ea580c',
3009
- secondary: '#f43f5e',
3010
- background: '#ffffff',
3011
- backgroundGradient: '#fff7ed',
3012
- text: '#1e293b',
3013
- textSecondary: '#64748b',
3014
- userBubble: 'linear-gradient(135deg, #f97316, #fb923c)',
3015
- aiBubble: '#ffffff',
3016
- headerGradient: 'linear-gradient(90deg, rgba(249,115,22,0.08), rgba(244,63,94,0.08))',
3017
- border: 'rgba(249,115,22,0.15)',
3018
- shadow: 'rgba(249,115,22,0.12)',
3019
- inputBackground: '#fff7ed',
3020
- inputBorder: '#fed7aa'
3021
- }
3022
- },
3023
- JADE: {
3024
- colors: {
3025
- primary: '#059669',
3026
- primaryLight: '#10b981',
3027
- primaryDark: '#047857',
3028
- secondary: '#34d399',
3029
- background: '#ffffff',
3030
- backgroundGradient: '#f0fdf4',
3031
- text: '#1e293b',
3032
- textSecondary: '#64748b',
3033
- userBubble: 'linear-gradient(135deg, #059669, #10b981)',
3034
- aiBubble: '#ffffff',
3035
- headerGradient: 'linear-gradient(90deg, rgba(5,150,105,0.08), rgba(52,211,153,0.08))',
3036
- border: 'rgba(5,150,105,0.15)',
3037
- shadow: 'rgba(5,150,105,0.12)',
3038
- inputBackground: '#f0fdf4',
3039
- inputBorder: '#bbf7d0'
3040
- }
3041
- },
3042
- STARSKY: {
3043
- colors: {
3044
- primary: '#6366f1',
3045
- primaryLight: '#818cf8',
3046
- primaryDark: '#4f46e5',
3047
- secondary: '#a855f7',
3048
- background: '#0f172a',
3049
- backgroundGradient: '#1e1b4b',
3050
- text: '#e2e8f0',
3051
- textSecondary: '#94a3b8',
3052
- userBubble: 'linear-gradient(135deg, #6366f1, #a855f7)',
3053
- aiBubble: '#1e1b4b',
3054
- headerGradient: 'linear-gradient(90deg, rgba(99,102,241,0.15), rgba(168,85,247,0.15))',
3055
- border: 'rgba(99,102,241,0.3)',
3056
- shadow: 'rgba(0,0,0,0.3)',
3057
- inputBackground: '#1e1b4b',
3058
- inputBorder: '#312e81'
3059
- }
3060
- },
3061
- SUNSET: {
3062
- colors: {
3063
- primary: '#ea580c',
3064
- primaryLight: '#f97316',
3065
- primaryDark: '#c2410c',
3066
- secondary: '#dc2626',
3067
- background: '#ffffff',
3068
- backgroundGradient: '#fff8f0',
3069
- text: '#1e293b',
3070
- textSecondary: '#64748b',
3071
- userBubble: 'linear-gradient(135deg, #ea580c, #dc2626)',
3072
- aiBubble: '#ffffff',
3073
- headerGradient: 'linear-gradient(90deg, rgba(234,88,12,0.08), rgba(220,38,38,0.08))',
3074
- border: 'rgba(234,88,12,0.15)',
3075
- shadow: 'rgba(234,88,12,0.12)',
3076
- inputBackground: '#fff8f0',
3077
- inputBorder: '#fed7aa'
3078
- }
3079
- }
3080
- };
3081
3620
  class AIChatDialog extends HTMLElement {
3082
3621
  static get observedAttributes() {
3083
3622
  return ['visible'];
@@ -3248,6 +3787,8 @@ class AIChatDialog extends HTMLElement {
3248
3787
  // P2-17: 应用移动端/桌面端布局(自动全屏或恢复浮动气泡)
3249
3788
  _applyMobileLayout() {
3250
3789
  if (!this._dialog) return;
3790
+ // 行内嵌入模式跳过,保持 CSS 控制的布局
3791
+ if (this.getAttribute('mode') === 'inline') return;
3251
3792
  if (this._isMobile) {
3252
3793
  // 移动端:强制全屏(与Vue版 dialogStyle 一致)
3253
3794
  this._dialog.style.width = '100vw';
@@ -3509,11 +4050,11 @@ class AIChatDialog extends HTMLElement {
3509
4050
  /* ====== 对话框主体(与Vue .ai-chat-dialog 完全一致) ====== */
3510
4051
  .ai-chat-dialog {
3511
4052
  position: fixed;
3512
- top: 96px;
3513
- right: 24px;
4053
+ top: var(--ai-dialog-top, 96px);
4054
+ right: var(--ai-dialog-right, 24px);
3514
4055
  bottom: auto;
3515
- width: min(420px, calc(100vw - 48px));
3516
- height: min(640px, 80vh);
4056
+ width: var(--ai-dialog-width, min(420px, calc(100vw - 48px)));
4057
+ height: var(--ai-dialog-height, min(640px, 80vh));
3517
4058
  background: var(--ai-bg);
3518
4059
  border-radius: 16px;
3519
4060
  border: 1px solid rgba(226, 232, 240, 0.78);
@@ -4503,6 +5044,27 @@ class AIChatDialog extends HTMLElement {
4503
5044
  .action-icon { width: 30px; height: 30px; }
4504
5045
  }
4505
5046
 
5047
+ /* ========== 行内嵌入模式(mode="inline",挂载到用户指定容器) ========== */
5048
+ :host([mode="inline"]) { position: relative; top: auto; right: auto; bottom: auto; z-index: auto; width: 100%; height: 100%; }
5049
+ :host([mode="inline"]) .ai-float-container { height: 100%; }
5050
+ :host([mode="inline"]) .float-button { display: none; }
5051
+ :host([mode="inline"]) .ai-chat-dialog {
5052
+ position: relative;
5053
+ top: auto;
5054
+ right: auto;
5055
+ width: 100%;
5056
+ height: 100%;
5057
+ border-radius: 0;
5058
+ box-shadow: none;
5059
+ border: 1px solid var(--ai-border);
5060
+ opacity: 1;
5061
+ transform: none;
5062
+ pointer-events: auto;
5063
+ }
5064
+ :host([mode="inline"]) .dialog-header { cursor: default; }
5065
+ :host([mode="inline"]) .close-btn,
5066
+ :host([mode="inline"]) .expand-btn { display: none; }
5067
+
4506
5068
  /* ========== 暗色主题覆盖(theme: 'dark') ========== */
4507
5069
  :host(.dark-theme) .ai-chat-dialog {
4508
5070
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);
@@ -4648,8 +5210,8 @@ class AIChatDialog extends HTMLElement {
4648
5210
  });
4649
5211
  }
4650
5212
 
4651
- // 拖拽
4652
- if (this._dialog && this._config?.enableDrag !== false) this.initDraggable();
5213
+ // 拖拽(内嵌模式禁用)
5214
+ if (this._dialog && this._config?.enableDrag !== false && this.getAttribute('mode') !== 'inline') this.initDraggable();
4653
5215
  });
4654
5216
  }
4655
5217
 
@@ -5250,10 +5812,20 @@ class AIChatDialog extends HTMLElement {
5250
5812
  }));
5251
5813
  this.setLoading(true);
5252
5814
  try {
5815
+ // 上传附件并收集 attachmentId
5816
+ const attachmentIds = [];
5253
5817
  for (const file of attachments) {
5254
- await this.uploadAttachment(file).catch(err => console.warn('[AIChatDialog] 附件上传失败:', err));
5818
+ const res = await this.uploadAttachment(file).catch(err => {
5819
+ console.warn('[AIChatDialog] 附件上传失败:', err);
5820
+ return null;
5821
+ });
5822
+ if (res?.success && res.data?.attachmentId) {
5823
+ attachmentIds.push(res.data.attachmentId);
5824
+ }
5255
5825
  }
5256
- await this.sendMessageToAI(content || attachmentText);
5826
+ await this.sendMessageToAI(content || attachmentText, {
5827
+ attachmentIds
5828
+ });
5257
5829
  } catch (err) {
5258
5830
  console.error('[AIChatDialog] Error:', err);
5259
5831
  this.handleError(err);
@@ -5282,7 +5854,11 @@ class AIChatDialog extends HTMLElement {
5282
5854
  this._streaming = true;
5283
5855
  this.setLoading(false); // 关掉全局 loading,用消息级 loading 替代
5284
5856
  this.updateLoadingUI(); // re-lock input via _streaming flag
5285
- await this._directApiCallStream(msgId, content, options.streamOptions || {});
5857
+ const streamOpts = {
5858
+ ...(options.streamOptions || {})
5859
+ };
5860
+ if (options.attachmentIds?.length) streamOpts.attachmentIds = options.attachmentIds;
5861
+ await this._directApiCallStream(msgId, content, streamOpts);
5286
5862
  }
5287
5863
  }
5288
5864
  async mockResponse(userContent) {
@@ -5349,6 +5925,7 @@ class AIChatDialog extends HTMLElement {
5349
5925
  const response = await this._chatClient.sendMessageStream(content, {
5350
5926
  onMessage: chunk => {
5351
5927
  if (!this._isPlaceholder(chunk) && !this._isEventLike(chunk)) {
5928
+ if (!chunk) chunk = '\n';
5352
5929
  streamText += chunk;
5353
5930
  this._updateMsg(msgId, streamText);
5354
5931
  }
@@ -5568,7 +6145,7 @@ class AIChatDialog extends HTMLElement {
5568
6145
  this._messages[idx].content = content;
5569
6146
  delete this._messages[idx]._isStreaming;
5570
6147
  this._messages[idx].time = this.formatTime();
5571
- this._messages[idx]._status = content && !content.startsWith('(') ? 'completed' : 'error';
6148
+ this._messages[idx]._status = this._isErrorContent(content) ? 'error' : 'completed';
5572
6149
  if (this._streamTypeRaf) {
5573
6150
  cancelAnimationFrame(this._streamTypeRaf);
5574
6151
  this._streamTypeRaf = null;
@@ -5584,6 +6161,7 @@ class AIChatDialog extends HTMLElement {
5584
6161
  // 运行时占位符过滤(对齐 portal)
5585
6162
  _isPlaceholder(text) {
5586
6163
  if (!text || typeof text !== 'string') return false;
6164
+ if (text === '\n' || text === '\n\n') return false;
5587
6165
  const p = text.trim();
5588
6166
  if (!p) return true;
5589
6167
  return RUNTIME_PLACEHOLDERS.some(k => p.includes(k));
@@ -5599,6 +6177,13 @@ class AIChatDialog extends HTMLElement {
5599
6177
  return false;
5600
6178
  }
5601
6179
 
6180
+ // 判断错误标记内容(替换脆弱的前缀检查 startsWith('('))
6181
+ _ERROR_CONTENT_PATTERNS = ['(请求超时', '(等待AI处理', '(无回复)', '(已停止)', '(AI 处理超时', '错误:', '网络错误:', '抱歉,'];
6182
+ _isErrorContent(content) {
6183
+ if (!content) return true;
6184
+ return this._ERROR_CONTENT_PATTERNS.some(p => content.startsWith(p));
6185
+ }
6186
+
5602
6187
  // 运行时事件管理 – incremental DOM, no renderMessages
5603
6188
  _addRuntimeEvent(msgId, event) {
5604
6189
  const idx = this._messages.findIndex(m => m.id === msgId);
@@ -5607,8 +6192,6 @@ class AIChatDialog extends HTMLElement {
5607
6192
  const last = this._messages[idx]._runtimeEvents[this._messages[idx]._runtimeEvents.length - 1];
5608
6193
  if (last && last._text === event._text) return;
5609
6194
  this._messages[idx]._runtimeEvents.push(event);
5610
- !['NODE_COMPLETE', 'TOOL_END', 'TOOL_RESULT'].includes(event._type);
5611
-
5612
6195
  // Path 1: panel DOM exists and is alive – incremental append
5613
6196
  if (this._runtimeEventsContainerEl && this._body.contains(this._runtimeEventsContainerEl)) {
5614
6197
  const row = document.createElement('div');
@@ -5979,6 +6562,9 @@ class AIChatDialog extends HTMLElement {
5979
6562
  parseMarkdown(text) {
5980
6563
  if (!text) return '';
5981
6564
  try {
6565
+ // 逐行规范化标题:确保 # 后跟空格(如 "####4.2" → "#### 4.2")
6566
+ const lines = text.split('\n');
6567
+ text = lines.map(line => line.replace(/^(\s{0,3}#{1,6})([^\s#].*)$/, '$1 $2')).join('\n');
5982
6568
  // marked 解析 markdown
5983
6569
  const rawHtml = g.parse(text);
5984
6570
  // DOMPurify 净化HTML(防止XSS攻击)
@@ -6006,7 +6592,7 @@ if (typeof window !== 'undefined') {
6006
6592
  * 支持任意前端框架:Vue, React, Angular, 原生HTML等
6007
6593
  *
6008
6594
  * @author IBC AI Team
6009
- * @version 2.0.0
6595
+ * @version 2.0.4
6010
6596
  */
6011
6597
 
6012
6598
 
@@ -6018,16 +6604,53 @@ function createAIChatDialog(options = {}) {
6018
6604
  // 设置属性
6019
6605
  if (options.title) dialog.setAttribute('title', options.title);
6020
6606
  if (options.placeholder) dialog.setAttribute('placeholder', options.placeholder);
6021
- if (options.width) dialog.style.setProperty('--dialog-width', `${options.width}px`);
6022
- if (options.height) dialog.style.setProperty('--dialog-height', `${options.height}px`);
6023
-
6024
- // 添加到DOM(隐藏状态)
6025
- document.body.appendChild(dialog);
6607
+ // 对话框尺寸和位置(浮窗模式可用)
6608
+ if (options.width) dialog.style.setProperty('--ai-dialog-width', typeof options.width === 'number' ? `${options.width}px` : options.width);
6609
+ if (options.height) dialog.style.setProperty('--ai-dialog-height', typeof options.height === 'number' ? `${options.height}px` : options.height);
6610
+ if (options.top != null) dialog.style.setProperty('--ai-dialog-top', typeof options.top === 'number' ? `${options.top}px` : options.top);
6611
+ if (options.right != null) dialog.style.setProperty('--ai-dialog-right', typeof options.right === 'number' ? `${options.right}px` : options.right);
6612
+
6613
+ // 挂载到指定容器或 body
6614
+ if (options.target) {
6615
+ const container = typeof options.target === 'string' ? document.querySelector(options.target) : options.target;
6616
+ if (container) {
6617
+ dialog.setAttribute('mode', 'inline');
6618
+ container.appendChild(dialog);
6619
+ } else {
6620
+ console.warn('[AI Web SDK] target 容器未找到,回退到 body');
6621
+ document.body.appendChild(dialog);
6622
+ }
6623
+ } else {
6624
+ document.body.appendChild(dialog);
6625
+ }
6026
6626
 
6027
6627
  // 初始化配置
6028
6628
  if (Object.keys(options).length > 0) {
6029
6629
  dialog.init(options);
6030
6630
  }
6631
+
6632
+ // 行内模式:挂载到 DOM 后直接展开
6633
+ if (options.target) {
6634
+ requestAnimationFrame(() => {
6635
+ dialog.style.position = 'relative';
6636
+ dialog.style.height = '100%';
6637
+ if (dialog.shadowRoot) {
6638
+ const container = dialog.shadowRoot.querySelector('.ai-float-container');
6639
+ const dialogEl = dialog.shadowRoot.querySelector('.ai-chat-dialog');
6640
+ const btn = dialog.shadowRoot.querySelector('.float-button');
6641
+ if (container) container.style.height = '100%';
6642
+ if (btn) btn.style.display = 'none';
6643
+ if (dialogEl) {
6644
+ dialogEl.style.position = 'relative';
6645
+ dialogEl.style.top = 'auto';
6646
+ dialogEl.style.right = 'auto';
6647
+ dialogEl.style.width = '100%';
6648
+ dialogEl.style.height = '100%';
6649
+ dialogEl.classList.add('dialog-visible');
6650
+ }
6651
+ }
6652
+ });
6653
+ }
6031
6654
  return dialog;
6032
6655
  }
6033
6656
 
@@ -6212,14 +6835,14 @@ var index = {
6212
6835
  createAIChatDialog,
6213
6836
  installVuePlugin,
6214
6837
  useAIChat,
6215
- version: '2.0.0'
6838
+ version: '2.0.4'
6216
6839
  };
6217
6840
 
6218
6841
  // 全局暴露(UMD/浏览器环境)
6219
6842
  if (typeof window !== 'undefined') {
6220
6843
  window.AICreateChatDialog = createAIChatDialog;
6221
6844
  window.AIWebSDK = {
6222
- version: '2.0.0',
6845
+ version: '2.0.4',
6223
6846
  create: createAIChatDialog,
6224
6847
  AIChatDialog,
6225
6848
  AIChatClient,