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