gs-ai-assistant 1.0.0-beta.0

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/README.md ADDED
@@ -0,0 +1,115 @@
1
+ ---
2
+
3
+ <h1 align="center">谷信软件科技有限公司</h1>
4
+
5
+ <p align="center">轻量、定制的现代化企业级前端框架</p>
6
+
7
+ ---
8
+
9
+ ### 介绍
10
+
11
+ 这是一套**轻量、定制的现代化前端开发架构**,自 2023 年起从头开始构建,并在实践中不断迭代优化。最初的技术探索过程中,曾涉及低代码平台的研究,随着开发的深入,该架构逐步演化为公司前端项目的标准开发模式。
12
+
13
+ 该架构基于 [Vue 3](https://cn.vuejs.org/guide/introduction)、[Ant Design Vue 4](https://www.antdv.com/components/overview-cn)和[Bootstrap 5](https://getbootstrap.com/docs/5.3/customize/optimize/),结合模块化设计思想,提供了一种 高效、灵活、可扩展 的前端开发方案。
14
+
15
+ ## 核心特点
16
+ • 渐进式架构:采用 Vue 3 组合式 API,降低组件复杂度,提升代码复用性。
17
+ • 统一规范(UI):结合 Antdv 4 提供一致的设计语言,确保界面美观、交互流畅。
18
+ • 性能优化(CSS):基于 Bootstrap 5 现代化样式体系,提高样式复用性,减少兼容性适配成本,提升开发效率。
19
+ • 跨平台兼容:内置响应式布局,自适应平板和移动端,提供一致的用户体验。**基础布局支持,实际页面需要适配调整**
20
+ • 模块化设计:鼓励封装和复用,每个功能块作为独立模块,便于维护和扩展。
21
+ • 面向企业应用:专为公司内部系统和新项目定制,支持灵活配置,满足不同业务需求。
22
+
23
+ ## 特性
24
+
25
+ - 快速组件
26
+ - 📖 提供 EList 组件和示例
27
+ - 📖 提供 ETree 组件和示例
28
+ - 📖 提供 ETable 组件和示例
29
+ - 📖 提供 ESelect 组件和示例
30
+ - Antdv4
31
+ - 🍭 支持 定制主题(全局)
32
+ - 🍭 支持 局部主题 (弃用 tailwindcss, 使用局部主题实现按钮换色)
33
+ - 🍭 支持 动态主题(低代码)
34
+ - 🍭 支持 深色模式
35
+
36
+ ## **📌 快速组件**
37
+ | **组件** | **功能** |
38
+ |----------|-------------|
39
+ | **EList** | 卡片展示,支持 增/删/改/查 |
40
+ | **ETree** | 组织机构,支持 增/删/改/查 |
41
+ | **ETable** | 表格展示,支持 增/删/改/查 |
42
+ | **ESelect** | 组织机构选择,支持 联动/搜索/增/删/改/等 |
43
+ | **EModal** | 弹窗 |
44
+ | **EDrawer** | 侧窗 |
45
+
46
+ ## **📌 结构说明**
47
+ - `EList`、`ETree`、`ETable`
48
+ - **统一使用 `CResponsiveHeader` 组件**,提供:
49
+ - `left` 插槽:用于头部左侧筛选 & 操作。
50
+ - `right` 插槽:用于头部右侧筛选 & 操作。
51
+ - `header` 插槽:头部自定义内容。
52
+ - `tag` 插槽:用于过滤器。
53
+ - `content` 插槽:用于展示补充内容。
54
+ - **`ESelect` 组件扩展**:支持 `dropdownRender`,可自定义下拉框内容。
55
+
56
+ ## **📌 其他优化**
57
+ | **优化项** | **说明** |
58
+ |------------|----------|
59
+ | **数据库支持** | PostgreSQL、Oracle 适配尚未完成,老版本支持双数据库 |
60
+ | **长耗时导入** | 进度反馈 + 动态分页查询 (`dao.getListWithPagination`) |
61
+ | **图片支持** | SM4 加密(仅供参考) |
62
+ | **图片压缩** | 有点击压缩功能(仅供参考) |
63
+ | **WebSocket** | 支持实时数据交互 |
64
+
65
+ ## 浏览器兼容性
66
+
67
+ 支持所有符合 ES5 的浏览器(不支持 IE8 及以下版本)。
68
+
69
+ ## 社区生态
70
+
71
+ 由社区维护的项目如下:
72
+
73
+ | Project | Status | 描述 |
74
+ | --------------------- | ------------------------------------------------------------ | ------------------------------------------------------- |
75
+ | [ant-design-vue] | [![ant-design-vue-status]][ant-design-vue-package] | 基于 Ant Design 设计体系的 Vue 组件库 |
76
+ | [axios] | [![axios-status]][axios-package] | 基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js |
77
+ | [core-js] | [![core-js-status]][core-js-package] | ECMAScript 规范的 polyfill,提供兼容性支持 |
78
+ | [nprogress] | [![nprogress-status]][nprogress-package] | 轻量级的页面加载进度条组件 |
79
+ | [qs] | [![qs-status]][qs-package] | 强大的查询字符串解析和序列化工具 |
80
+ | [vue] | [![vue-status]][vue-package] | 渐进式 JavaScript 框架,用于构建用户界面 |
81
+ | [vue-request] | [![vue-request-status]][vue-request-package] | 基于 Vue 3 的请求管理库,简化数据请求和状态管理 |
82
+ | [vue-router] | [![vue-router-status]][vue-router-package] | Vue.js 的官方路由库,支持单页面应用的路由管理 |
83
+ | [vuedraggable] | [![vuedraggable-status]][vuedraggable-package] | Vue 的拖拽排序组件,基于 Sortable.js |
84
+ | [vuex] | [![vuex-status]][vuex-package] | Vue.js 的状态管理模式,适用于大型应用 |
85
+
86
+ [ant-design-vue]: https://github.com/vueComponent/ant-design-vue
87
+ [axios]: https://github.com/axios/axios
88
+ [core-js]: https://github.com/zloirock/core-js
89
+ [nprogress]: https://github.com/rstacruz/nprogress
90
+ [qs]: https://github.com/ljharb/qs
91
+ [vue]: https://github.com/vuejs/core
92
+ [vue-request]: https://github.com/AttoJS/vue-request
93
+ [vue-router]: https://github.com/vuejs/vue-router
94
+ [vuedraggable]: https://github.com/SortableJS/Vue.Draggable
95
+ [vuex]: https://github.com/vuejs/vuex
96
+ [ant-design-vue-status]: https://img.shields.io/npm/v/ant-design-vue.svg
97
+ [axios-status]: https://img.shields.io/npm/v/axios.svg
98
+ [core-js-status]: https://img.shields.io/npm/v/core-js.svg
99
+ [nprogress-status]: https://img.shields.io/npm/v/nprogress.svg
100
+ [qs-status]: https://img.shields.io/npm/v/qs.svg
101
+ [vue-status]: https://img.shields.io/npm/v/vue.svg
102
+ [vue-request-status]: https://img.shields.io/npm/v/vue-request.svg
103
+ [vue-router-status]: https://img.shields.io/npm/v/vue-router.svg
104
+ [vuedraggable-status]: https://img.shields.io/npm/v/vuedraggable.svg
105
+ [vuex-status]: https://img.shields.io/npm/v/vuex.svg
106
+ [ant-design-vue-package]: https://npmjs.com/package/ant-design-vue
107
+ [axios-package]: https://npmjs.com/package/axios
108
+ [core-js-package]: https://npmjs.com/package/core-js
109
+ [nprogress-package]: https://npmjs.com/package/nprogress
110
+ [qs-package]: https://npmjs.com/package/qs
111
+ [vue-package]: https://npmjs.com/package/vue
112
+ [vue-request-package]: https://npmjs.com/package/vue-request
113
+ [vue-router-package]: https://npmjs.com/package/vue-router
114
+ [vuedraggable-package]: https://npmjs.com/package/vuedraggable
115
+ [vuex-package]: https://npmjs.com/package/vuex
@@ -0,0 +1 @@
1
+ .ai-chat-sidebar[data-v-ff65b680]{width:248px;flex:0 0 248px;background:#f5f6f8}.ai-sidebar-nav[data-v-ff65b680]{padding-bottom:22px}.ai-sidebar-nav-item[data-v-ff65b680],.ai-session-item[data-v-ff65b680]{width:100%;border:0;color:#24272d;background:transparent;text-align:left;transition:background-color .2s ease,color .2s ease,transform .2s ease}.ai-sidebar-nav-item[data-v-ff65b680]{display:flex;align-items:center;gap:12px;min-height:42px;padding:0 14px;border-radius:14px;font-size:15px;font-weight:500}.ai-sidebar-nav-item[data-v-ff65b680]:hover,.ai-session-item[data-v-ff65b680]:hover{background:#fff}.ai-sidebar-nav-item[data-v-ff65b680]:active,.ai-session-item[data-v-ff65b680]:active{transform:scale(.98)}.ai-sidebar-nav-item.active[data-v-ff65b680],.ai-session-item.active[data-v-ff65b680]{background:#fff;color:#1677ff;box-shadow:0 8px 20px #0f172a0f}.ai-sidebar-section-title[data-v-ff65b680]{color:#7b818d;font-size:13px;font-weight:600}.ai-session-item[data-v-ff65b680]{min-height:38px;padding:0 8px 0 14px;border-radius:12px;font-size:14px;cursor:pointer}.ai-session-delete[data-v-ff65b680]{width:24px;height:24px;border-radius:8px;color:#9aa1ad;opacity:0;transition:opacity .2s ease,background-color .2s ease,color .2s ease}.ai-session-item:hover .ai-session-delete[data-v-ff65b680]{opacity:1}.ai-session-delete[data-v-ff65b680]:hover{color:#cf1322!important;background:#fff1f0}.ai-session-collapse[data-v-ff65b680]{min-height:0}.ai-session-collapse[data-v-ff65b680] .ant-collapse-header{align-items:center!important;padding:0 14px 8px!important}.ai-session-collapse[data-v-ff65b680] .ant-collapse-content-box{padding:0!important}.ai-instruction-card[data-v-85d5df68]{min-height:112px;border:1px solid #edf0f5;transition:border-color .2s ease,box-shadow .2s ease}.ai-instruction-card[data-v-85d5df68]:hover{border-color:#1677ff;box-shadow:0 8px 24px #0f172a14}.ai-message-bubble[data-v-de55b932]{max-width:78%;line-height:1.75;font-size:14px}.ai-pre-wrap[data-v-de55b932]{white-space:pre-wrap;word-break:break-word}.ai-chat-messages[data-v-8bae25ad]{min-height:220px;padding:20px 24px 24px}.ai-message-bubble[data-v-8bae25ad]{max-width:78%;line-height:1.75;font-size:14px}.ai-pre-wrap[data-v-8bae25ad]{white-space:pre-wrap;word-break:break-word}.ai-thinking-collapse[data-v-8bae25ad]{margin-bottom:8px;color:#6b7280}.ai-thinking-collapse[data-v-8bae25ad] .ant-collapse-header{display:inline-flex!important;align-items:center!important;gap:6px;padding:0!important;color:#6b7280!important;font-size:13px}.ai-thinking-collapse[data-v-8bae25ad] .ant-collapse-content-box{padding:8px 0 0 16px!important;border-left:2px solid #e5e7eb}.ai-thinking-content[data-v-8bae25ad]{margin:0;white-space:pre-wrap;word-break:break-word;color:#6b7280;font-family:inherit;line-height:1.65}.ai-input-box[data-v-e63f761d]{border:1px solid #dfe3ea;border-radius:18px;box-shadow:0 10px 28px #0f172a14}.ai-input-box[data-v-e63f761d] textarea.ant-input{width:100%;border:none;box-shadow:none;resize:none;padding:0;font-size:14px}.ai-model-select[data-v-e63f761d]{width:160px}.ai-action-type-select[data-v-e63f761d]{width:96px}.ai-send-btn[data-v-e63f761d]{flex:0 0 auto}.ai-chat-wrap[data-v-0a4b31b9]{height:70vh;min-height:460px;max-height:760px}.floating-ai[data-v-83236aae]{position:fixed;pointer-events:auto;touch-action:none;-webkit-user-select:none;user-select:none}.tool-btn[data-v-83236aae]{box-shadow:0 6px 20px #00000026}.ai-btn[data-v-83236aae]{width:58px;height:132px;border:none;border-radius:30px;background:#fff;color:#b30000;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:0}.ai-mark[data-v-83236aae]{font-size:20px;line-height:1;font-weight:700;color:#5b7cff;font-style:italic}.ai-label[data-v-83236aae]{font-size:20px;line-height:1;font-weight:600;color:#b30000;writing-mode:vertical-rl;text-orientation:upright;letter-spacing:1px}.ai-btn[data-v-83236aae]:hover,.ai-btn[data-v-83236aae]:focus{color:#b30000;background:#fff}.ai-btn[data-v-83236aae]:active{background:#f8f9ff}
@@ -0,0 +1,714 @@
1
+ import { onMounted as pe, nextTick as ve, getCurrentInstance as oe, watch as Q, getCurrentScope as ye, hasInjectionContext as me, inject as T, shallowRef as U, computed as A, toValue as Y, watchEffect as be, unref as K, ref as p, resolveComponent as $, createElementBlock as w, openBlock as d, createElementVNode as v, createVNode as M, normalizeClass as Z, withCtx as L, createBlock as F, createCommentVNode as O, Fragment as P, renderList as B, toDisplayString as S, withModifiers as fe, createTextVNode as ae, withKeys as we, isRef as ce, provide as J, normalizeStyle as xe } from "vue";
2
+ import { useStore as ee } from "vuex";
3
+ const te = /* @__PURE__ */ new WeakMap(), ke = /* @__NO_SIDE_EFFECTS__ */ (...e) => {
4
+ var t;
5
+ const s = e[0], o = (t = oe()) === null || t === void 0 ? void 0 : t.proxy, n = o ?? ye();
6
+ if (n == null && !me()) throw new Error("injectLocal must be called in setup");
7
+ return n && te.has(n) && s in te.get(n) ? te.get(n)[s] : T(...e);
8
+ }, Ae = typeof window < "u" && typeof document < "u";
9
+ typeof WorkerGlobalScope < "u" && globalThis instanceof WorkerGlobalScope;
10
+ const Se = Object.prototype.toString, Ie = (e) => Se.call(e) === "[object Object]";
11
+ function ue(e) {
12
+ return e.endsWith("rem") ? Number.parseFloat(e) * 16 : Number.parseFloat(e);
13
+ }
14
+ function se(e) {
15
+ return Array.isArray(e) ? e : [e];
16
+ }
17
+ function Me(e) {
18
+ return oe();
19
+ }
20
+ function Ce(e, t = !0, s) {
21
+ Me() ? pe(e, s) : t ? e() : ve(e);
22
+ }
23
+ function $e(e, t, s) {
24
+ return Q(e, t, {
25
+ ...s,
26
+ immediate: !0
27
+ });
28
+ }
29
+ const le = Ae ? window : void 0;
30
+ function Te(e) {
31
+ var t;
32
+ const s = Y(e);
33
+ return (t = s?.$el) !== null && t !== void 0 ? t : s;
34
+ }
35
+ function ne(...e) {
36
+ const t = (o, n, c, a) => (o.addEventListener(n, c, a), () => o.removeEventListener(n, c, a)), s = A(() => {
37
+ const o = se(Y(e[0])).filter((n) => n != null);
38
+ return o.every((n) => typeof n != "string") ? o : void 0;
39
+ });
40
+ return $e(() => {
41
+ var o, n;
42
+ return [
43
+ (o = (n = s.value) === null || n === void 0 ? void 0 : n.map((c) => Te(c))) !== null && o !== void 0 ? o : [le].filter((c) => c != null),
44
+ se(Y(s.value ? e[1] : e[0])),
45
+ se(K(s.value ? e[2] : e[1])),
46
+ Y(s.value ? e[3] : e[2])
47
+ ];
48
+ }, ([o, n, c, a], l, g) => {
49
+ if (!o?.length || !n?.length || !c?.length) return;
50
+ const f = Ie(a) ? { ...a } : a, m = o.flatMap((i) => n.flatMap((k) => c.map((h) => t(i, k, h, f))));
51
+ g(() => {
52
+ m.forEach((i) => i());
53
+ });
54
+ }, { flush: "post" });
55
+ }
56
+ // @__NO_SIDE_EFFECTS__
57
+ function Le() {
58
+ const e = U(!1), t = oe();
59
+ return t && pe(() => {
60
+ e.value = !0;
61
+ }, t), e;
62
+ }
63
+ // @__NO_SIDE_EFFECTS__
64
+ function Ve(e) {
65
+ const t = /* @__PURE__ */ Le();
66
+ return A(() => (t.value, !!e()));
67
+ }
68
+ const We = Symbol("vueuse-ssr-width");
69
+ // @__NO_SIDE_EFFECTS__
70
+ function Ee() {
71
+ const e = me() ? /* @__PURE__ */ ke(We, null) : null;
72
+ return typeof e == "number" ? e : void 0;
73
+ }
74
+ function Ne(e, t = {}) {
75
+ const { window: s = le, ssrWidth: o = /* @__PURE__ */ Ee() } = t, n = /* @__PURE__ */ Ve(() => s && "matchMedia" in s && typeof s.matchMedia == "function"), c = U(typeof o == "number"), a = U(), l = U(!1), g = (f) => {
76
+ l.value = f.matches;
77
+ };
78
+ return be(() => {
79
+ if (c.value) {
80
+ c.value = !n.value, l.value = Y(e).split(",").some((f) => {
81
+ const m = f.includes("not all"), i = f.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/), k = f.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);
82
+ let h = !!(i || k);
83
+ return i && h && (h = o >= ue(i[1])), k && h && (h = o <= ue(k[1])), m ? !h : h;
84
+ });
85
+ return;
86
+ }
87
+ n.value && (a.value = s.matchMedia(Y(e)), l.value = a.value.matches);
88
+ }), ne(a, "change", g, { passive: !0 }), A(() => l.value);
89
+ }
90
+ // @__NO_SIDE_EFFECTS__
91
+ function Oe(e = {}) {
92
+ const { window: t = le, initialWidth: s = Number.POSITIVE_INFINITY, initialHeight: o = Number.POSITIVE_INFINITY, listenOrientation: n = !0, includeScrollbar: c = !0, type: a = "inner" } = e, l = U(s), g = U(o), f = () => {
93
+ if (t) if (a === "outer")
94
+ l.value = t.outerWidth, g.value = t.outerHeight;
95
+ else if (a === "visual" && t.visualViewport) {
96
+ const { width: i, height: k, scale: h } = t.visualViewport;
97
+ l.value = Math.round(i * h), g.value = Math.round(k * h);
98
+ } else c ? (l.value = t.innerWidth, g.value = t.innerHeight) : (l.value = t.document.documentElement.clientWidth, g.value = t.document.documentElement.clientHeight);
99
+ };
100
+ f(), Ce(f);
101
+ const m = { passive: !0 };
102
+ return ne("resize", f, m), t && a === "visual" && t.visualViewport && ne(t.visualViewport, "resize", f, m), n && Q(Ne("(orientation: portrait)"), () => f()), {
103
+ width: l,
104
+ height: g
105
+ };
106
+ }
107
+ const z = (e, t) => {
108
+ const s = e.__vccOpts || e;
109
+ for (const [o, n] of t)
110
+ s[o] = n;
111
+ return s;
112
+ }, qe = { class: "ai-chat-sidebar border-end p-3 d-flex flex-column" }, Fe = { class: "ai-sidebar-nav d-flex flex-column gap-1" }, Re = { class: "ai-sidebar-section-title d-flex align-items-center gap-2" }, De = { class: "d-flex flex-column gap-2" }, je = ["onClick"], Ke = { class: "text-truncate flex-fill" }, Pe = {
113
+ __name: "AiAssistantSidebar",
114
+ setup(e) {
115
+ const t = T("aiCurrentView", p("draft")), s = T("aiSessions", p([])), o = T("aiActiveSessionId", p("")), n = T("aiInputMessage", p("")), c = p(["recent"]), a = A(() => [...s.value].sort((m, i) => i.updatedAt - m.updatedAt)), l = () => {
116
+ t.value = "draft", n.value = "";
117
+ }, g = (m) => {
118
+ o.value = m, t.value = "chat";
119
+ }, f = (m) => {
120
+ s.value = s.value.filter((i) => i.id !== m), o.value === m && (o.value = "", t.value = "draft", n.value = "");
121
+ };
122
+ return (m, i) => {
123
+ const k = $("a-icon"), h = $("a-empty"), x = $("a-button"), V = $("a-collapse-panel"), b = $("a-collapse");
124
+ return d(), w("aside", qe, [
125
+ v("div", Fe, [
126
+ v("button", {
127
+ class: Z(["ai-sidebar-nav-item", { active: K(t) === "draft" }]),
128
+ onClick: l
129
+ }, [
130
+ M(k, { type: "icon-edit" }),
131
+ i[2] || (i[2] = v("span", null, "新对话", -1))
132
+ ], 2),
133
+ v("button", {
134
+ class: Z(["ai-sidebar-nav-item", { active: K(t) === "library" }]),
135
+ onClick: i[0] || (i[0] = (I) => t.value = "library")
136
+ }, [
137
+ M(k, { type: "icon-appstore" }),
138
+ i[3] || (i[3] = v("span", null, "AI 指令库", -1))
139
+ ], 2)
140
+ ]),
141
+ M(b, {
142
+ activeKey: c.value,
143
+ "onUpdate:activeKey": i[1] || (i[1] = (I) => c.value = I),
144
+ ghost: "",
145
+ class: "ai-session-collapse flex-fill overflow-auto"
146
+ }, {
147
+ default: L(() => [
148
+ M(V, { key: "recent" }, {
149
+ header: L(() => [
150
+ v("div", Re, [
151
+ M(k, { type: "icon-history" }),
152
+ i[4] || (i[4] = v("span", null, "最近会话", -1))
153
+ ])
154
+ ]),
155
+ default: L(() => [
156
+ v("div", De, [
157
+ a.value.length === 0 ? (d(), F(h, {
158
+ key: 0,
159
+ description: "暂无会话"
160
+ })) : O("", !0),
161
+ (d(!0), w(P, null, B(a.value, (I) => (d(), w("div", {
162
+ key: I.id,
163
+ class: Z(["ai-session-item d-flex align-items-center gap-2", { active: K(t) === "chat" && I.id === K(o) }]),
164
+ onClick: (W) => g(I.id)
165
+ }, [
166
+ v("span", Ke, S(I.title), 1),
167
+ M(x, {
168
+ type: "text",
169
+ size: "small",
170
+ class: "ai-session-delete",
171
+ onClick: fe((W) => f(I.id), ["stop"])
172
+ }, {
173
+ default: L(() => [
174
+ M(k, { type: "icon-delete" })
175
+ ]),
176
+ _: 1
177
+ }, 8, ["onClick"])
178
+ ], 10, je))), 128))
179
+ ])
180
+ ]),
181
+ _: 1
182
+ })
183
+ ]),
184
+ _: 1
185
+ }, 8, ["activeKey"])
186
+ ]);
187
+ };
188
+ }
189
+ }, ze = /* @__PURE__ */ z(Pe, [["__scopeId", "data-v-ff65b680"]]), He = { class: "ai-instruction-library flex-fill overflow-auto bg-white p-4" }, Ue = { class: "row g-3 mt-2" }, Ye = ["onClick"], Be = { class: "fw-semibold mb-2" }, Qe = { class: "small text-muted" }, Xe = {
190
+ __name: "AiInstructionLibrary",
191
+ setup(e) {
192
+ const t = ee(), s = p(""), o = T("aiInputMessage", p("")), n = T("aiActionType", p("chat")), c = T("aiCurrentView", p("draft")), a = A(() => t.state.app.aiAssistantConfig || {}), l = A(() => {
193
+ const m = a.value.instructions;
194
+ return Array.isArray(m) ? m : [];
195
+ }), g = A(() => {
196
+ const m = l.value || [], i = m.find((k) => k.label === s.value) || m[0];
197
+ return Array.isArray(i?.items) ? i.items : [];
198
+ }), f = (m) => {
199
+ o.value = m.prompt || "", n.value = m.actionType || "chat", c.value = "draft";
200
+ };
201
+ return Q(l, (m = []) => {
202
+ m.some((i) => i.label === s.value) || (s.value = m[0]?.label || "");
203
+ }, { immediate: !0 }), (m, i) => {
204
+ const k = $("a-tab-pane"), h = $("a-tabs");
205
+ return d(), w("div", He, [
206
+ i[1] || (i[1] = v("div", { class: "text-center mb-4" }, [
207
+ v("h3", { class: "mb-2" }, "AI 指令库"),
208
+ v("div", { class: "text-muted" }, "选择一个指令模板,快速开始当前系统的 AI 任务")
209
+ ], -1)),
210
+ M(h, {
211
+ activeKey: s.value,
212
+ "onUpdate:activeKey": i[0] || (i[0] = (x) => s.value = x),
213
+ centered: ""
214
+ }, {
215
+ default: L(() => [
216
+ (d(!0), w(P, null, B(l.value, (x) => (d(), F(k, {
217
+ key: x.label,
218
+ tab: x.label
219
+ }, null, 8, ["tab"]))), 128))
220
+ ]),
221
+ _: 1
222
+ }, 8, ["activeKey"]),
223
+ v("div", Ue, [
224
+ (d(!0), w(P, null, B(g.value, (x) => (d(), w("div", {
225
+ key: x.prompt,
226
+ class: "col-6 col-xl-4"
227
+ }, [
228
+ v("button", {
229
+ class: "ai-instruction-card w-100 h-100 text-start bg-white rounded p-3",
230
+ onClick: (V) => f(x)
231
+ }, [
232
+ v("div", Be, S(x.title), 1),
233
+ v("div", Qe, S(x.description), 1)
234
+ ], 8, Ye)
235
+ ]))), 128))
236
+ ])
237
+ ]);
238
+ };
239
+ }
240
+ }, Ge = /* @__PURE__ */ z(Xe, [["__scopeId", "data-v-85d5df68"]]), Je = { class: "ai-message-bubble bg-light rounded p-3" }, Ze = { class: "fw-semibold mb-2" }, et = {
241
+ key: 0,
242
+ class: "mb-2"
243
+ }, tt = {
244
+ key: 1,
245
+ class: "small text-muted mb-2"
246
+ }, st = { class: "ai-pre-wrap mb-0" }, at = {
247
+ __name: "AiTableResultMessage",
248
+ props: {
249
+ message: {
250
+ type: Object,
251
+ required: !0
252
+ }
253
+ },
254
+ setup(e) {
255
+ const t = e, s = A(() => (Array.isArray(t.message.columns) ? t.message.columns : []).map((a) => {
256
+ const l = typeof a == "string" ? a : a.key || a.dataIndex || a.title;
257
+ return {
258
+ title: typeof a == "string" ? a : a.title || l,
259
+ dataIndex: typeof a == "string" ? a : a.dataIndex || l,
260
+ key: l
261
+ };
262
+ })), o = A(() => (Array.isArray(t.message.rows) ? t.message.rows : []).map((a, l) => ({
263
+ key: l,
264
+ ...a
265
+ }))), n = A(() => JSON.stringify({
266
+ columns: t.message.columns,
267
+ rows: t.message.rows
268
+ }, null, 2));
269
+ return (c, a) => {
270
+ const l = $("a-table");
271
+ return d(), w("div", Je, [
272
+ v("div", Ze, S(e.message.title || "表格结果"), 1),
273
+ e.message.summary ? (d(), w("div", et, S(e.message.summary), 1)) : O("", !0),
274
+ e.message.sql ? (d(), w("div", tt, "SQL:" + S(e.message.sql), 1)) : O("", !0),
275
+ M(l, {
276
+ class: "mb-3",
277
+ size: "small",
278
+ bordered: "",
279
+ columns: s.value,
280
+ "data-source": o.value,
281
+ pagination: !1,
282
+ scroll: { x: !0 }
283
+ }, null, 8, ["columns", "data-source"]),
284
+ v("pre", st, S(n.value), 1)
285
+ ]);
286
+ };
287
+ }
288
+ }, nt = /* @__PURE__ */ z(at, [["__scopeId", "data-v-de55b932"]]), ot = { class: "small text-muted mb-2" }, lt = {
289
+ key: 0,
290
+ class: "ai-message-bubble bg-light rounded p-3"
291
+ }, it = { class: "ai-pre-wrap text-warning-emphasis mb-3" }, rt = {
292
+ key: 1,
293
+ class: "ai-message-bubble bg-warning-subtle rounded p-3"
294
+ }, ct = { class: "ai-pre-wrap text-warning-emphasis mb-0" }, ut = {
295
+ key: 3,
296
+ class: "ai-message-bubble bg-light rounded p-3"
297
+ }, dt = { class: "fw-semibold mb-2" }, pt = {
298
+ key: 0,
299
+ class: "mb-2"
300
+ }, vt = { class: "small text-muted mb-2" }, mt = { key: 0 }, ft = { key: 1 }, _t = {
301
+ key: 1,
302
+ class: "small text-muted mb-2"
303
+ }, gt = { class: "ai-pre-wrap mb-0" }, ht = {
304
+ key: 4,
305
+ class: "ai-message-bubble bg-transparent p-0"
306
+ }, yt = { class: "ai-thinking-content" }, bt = { class: "ai-thinking-content" }, wt = {
307
+ key: 0,
308
+ class: "h-100 d-flex align-items-center justify-content-center text-muted"
309
+ }, xt = {
310
+ __name: "AiChatMessages",
311
+ setup(e) {
312
+ const t = ee(), s = T("aiSessions", p([])), o = T("aiActiveSessionId", p("")), n = T("aiCurrentView", p("draft")), c = A(() => t.state.app.aiAssistantConfig || {}), a = A(() => c.value.title || "AI 小助手"), l = A(() => c.value.welcomeMessage || ""), g = p(), f = A(() => {
313
+ if (n.value === "draft") return [];
314
+ const b = s.value.find((I) => I.id === o.value);
315
+ return Array.isArray(b?.messages) ? b.messages : [];
316
+ });
317
+ Q([o, () => f.value.length], async () => {
318
+ await ve(), g.value.scrollTop = g.value.scrollHeight;
319
+ });
320
+ const m = (b = {}) => (Array.isArray(b.columns) ? b.columns : []).map((W) => ({
321
+ title: W,
322
+ dataIndex: W,
323
+ key: W
324
+ })), i = (b = {}) => (Array.isArray(b.rows) ? b.rows : []).map((W, R) => ({
325
+ key: R,
326
+ ...W
327
+ })), k = (b) => `Thinking ${b || 8}s`, h = (b) => JSON.stringify(b.data || [], null, 2), x = (b) => Array.isArray(b) ? b.join("、") : b, V = (b) => b.role === "user" ? "bg-primary-subtle text-dark p-3" : b.type === "error" ? "bg-danger-subtle text-danger border border-danger-subtle p-3" : b.role === "assistant" ? "bg-transparent p-0" : "bg-light p-3";
328
+ return (b, I) => {
329
+ const W = $("a-table"), R = $("a-collapse-panel"), j = $("a-collapse");
330
+ return d(), w("div", {
331
+ ref_key: "messageWrapRef",
332
+ ref: g,
333
+ class: "ai-chat-messages flex-fill overflow-auto bg-white"
334
+ }, [
335
+ (d(!0), w(P, null, B(f.value, (_, X) => (d(), w("div", {
336
+ key: X,
337
+ class: Z(["d-flex flex-column mb-4", [
338
+ _.role === "user" ? "align-items-end" : "align-items-start",
339
+ _.type
340
+ ]])
341
+ }, [
342
+ v("div", ot, S(_.role === "user" ? "我" : a.value), 1),
343
+ _.type === "sql_result" ? (d(), w("div", lt, [
344
+ I[0] || (I[0] = v("div", { class: "fw-semibold mb-2" }, "执行 SQL:", -1)),
345
+ v("pre", it, S(_.sql), 1),
346
+ M(W, {
347
+ size: "small",
348
+ bordered: "",
349
+ columns: m(_.result),
350
+ "data-source": i(_.result),
351
+ pagination: !1,
352
+ scroll: { x: !0 }
353
+ }, null, 8, ["columns", "data-source"])
354
+ ])) : _.type === "sql_preview" ? (d(), w("div", rt, [
355
+ I[1] || (I[1] = v("div", { class: "fw-semibold mb-2" }, "SQL 预览:", -1)),
356
+ v("pre", ct, S(_.content), 1)
357
+ ])) : _.type === "table_result" ? (d(), F(nt, {
358
+ key: 2,
359
+ message: _
360
+ }, null, 8, ["message"])) : _.type === "chart_result" ? (d(), w("div", ut, [
361
+ v("div", dt, S(_.title || "图表结果"), 1),
362
+ _.summary ? (d(), w("div", pt, S(_.summary), 1)) : O("", !0),
363
+ v("div", vt, [
364
+ ae(" 图表类型:" + S(_.chartType || "未指定") + " ", 1),
365
+ _.xField ? (d(), w("span", mt, "|X 轴:" + S(_.xField), 1)) : O("", !0),
366
+ _.yFields ? (d(), w("span", ft, "|指标:" + S(x(_.yFields)), 1)) : O("", !0)
367
+ ]),
368
+ _.sql ? (d(), w("div", _t, "SQL:" + S(_.sql), 1)) : O("", !0),
369
+ v("pre", gt, S(h(_)), 1)
370
+ ])) : _.type === "thinking" ? (d(), w("div", ht, [
371
+ M(j, {
372
+ ghost: "",
373
+ class: "ai-thinking-collapse"
374
+ }, {
375
+ default: L(() => [
376
+ M(R, {
377
+ key: "thinking",
378
+ header: k(_.thinkingSeconds)
379
+ }, {
380
+ default: L(() => [
381
+ v("pre", yt, S(_.content), 1)
382
+ ]),
383
+ _: 2
384
+ }, 1032, ["header"])
385
+ ]),
386
+ _: 2
387
+ }, 1024)
388
+ ])) : (d(), w("div", {
389
+ key: 5,
390
+ class: Z(["ai-message-bubble ai-pre-wrap rounded", V(_)])
391
+ }, [
392
+ _.thinking ? (d(), F(j, {
393
+ key: 0,
394
+ ghost: "",
395
+ class: "ai-thinking-collapse"
396
+ }, {
397
+ default: L(() => [
398
+ M(R, {
399
+ key: "thinking",
400
+ header: k(_.thinkingSeconds)
401
+ }, {
402
+ default: L(() => [
403
+ v("pre", bt, S(_.thinking), 1)
404
+ ]),
405
+ _: 2
406
+ }, 1032, ["header"])
407
+ ]),
408
+ _: 2
409
+ }, 1024)) : O("", !0),
410
+ v("div", null, S(_.content), 1)
411
+ ], 2))
412
+ ], 2))), 128)),
413
+ f.value.length === 0 ? (d(), w("div", wt, S(l.value || "开始一个新的 AI 对话"), 1)) : O("", !0)
414
+ ], 512);
415
+ };
416
+ }
417
+ }, kt = /* @__PURE__ */ z(xt, [["__scopeId", "data-v-8bae25ad"]]), At = { class: "border-top px-4 py-3" }, St = { class: "ai-input-box d-flex flex-column gap-3 p-3 bg-white" }, It = { class: "d-flex align-items-center justify-content-between gap-3 w-100" }, Mt = { class: "d-flex align-items-center gap-2 min-w-0" }, Ct = {
418
+ key: 0,
419
+ class: "small text-muted text-nowrap"
420
+ }, $t = { class: "d-flex align-items-center gap-2" }, Tt = {
421
+ __name: "AiChatInput",
422
+ setup(e) {
423
+ const t = ee(), s = T("aiSessions", p([])), o = T("aiActiveSessionId", p("")), n = T("aiCurrentView", p("draft")), c = T("aiInputMessage", p("")), a = T("aiActionType", p("chat")), l = p(!1), g = p(""), f = A(() => t.state.app.aiAssistantConfig), m = A(() => f.value.title || "AI 小助手"), i = A(() => f.value.chatUrl), k = [
424
+ { label: "聊天", value: "chat" },
425
+ { label: "SQL", value: "sql" },
426
+ { label: "表格", value: "table" },
427
+ { label: "图表", value: "chart" }
428
+ ], h = A(() => f.value.models.map((u) => {
429
+ const y = u.source || u.model_source || f.value.defaultModelSource || "online";
430
+ return {
431
+ ...u,
432
+ source: y,
433
+ key: `${y}::${u.value}`
434
+ };
435
+ })), V = p((() => {
436
+ const u = f.value.defaultModelSource || "online", y = f.value.defaultModel;
437
+ return h.value.find((r) => r.source === u && r.value === y).key;
438
+ })()), b = A(() => h.value.find((u) => u.key === V.value)), I = A(() => n.value === "draft" ? "" : s.value.find((y) => y.id === o.value).debugLine), W = () => "s_" + Date.now().toString(36) + "_" + Math.random().toString(36).slice(2, 8), R = () => ({
439
+ id: W(),
440
+ title: "新对话",
441
+ messages: [],
442
+ debugLine: "",
443
+ updatedAt: Date.now()
444
+ }), j = () => s.value.find((u) => u.id === o.value), _ = () => {
445
+ const u = R();
446
+ return s.value.unshift(u), o.value = u.id, n.value = "chat", j();
447
+ }, X = (u, y) => {
448
+ u.messages.push({ role: "user", content: y }), u.title === "新对话" && (u.title = y), u.updatedAt = Date.now();
449
+ }, C = (u, y) => {
450
+ u.messages.push({ role: "assistant", content: y }), u.updatedAt = Date.now();
451
+ }, q = (u, y, E) => {
452
+ for (const r of y)
453
+ r.type === "ai" && r.content ? u.messages.push({
454
+ role: "assistant",
455
+ type: "ai",
456
+ content: r.content,
457
+ thinking: r.thinking,
458
+ thinkingSeconds: E
459
+ }) : ["thinking", "thought", "reasoning"].includes(r.type) && r.content ? u.messages.push({ role: "assistant", type: "thinking", content: r.content, thinkingSeconds: E }) : r.type === "sql_preview" && r.content ? u.messages.push({ role: "assistant", type: "sql_preview", content: r.content }) : r.type === "sql_result" ? u.messages.push({
460
+ role: "assistant",
461
+ type: "sql_result",
462
+ sql: r.sql,
463
+ result: r.result
464
+ }) : r.type === "table_result" ? u.messages.push({
465
+ role: "assistant",
466
+ type: "table_result",
467
+ title: r.title,
468
+ sql: r.sql,
469
+ columns: r.columns,
470
+ rows: r.rows,
471
+ summary: r.summary
472
+ }) : r.type === "chart_result" ? u.messages.push({
473
+ role: "assistant",
474
+ type: "chart_result",
475
+ title: r.title,
476
+ sql: r.sql,
477
+ chartType: r.chart_type,
478
+ xField: r.x_field,
479
+ yFields: r.y_fields,
480
+ data: r.data,
481
+ summary: r.summary
482
+ }) : r.type === "error" && r.content && u.messages.push({ role: "assistant", type: "error", content: r.content });
483
+ u.updatedAt = Date.now();
484
+ }, H = async () => {
485
+ const u = c.value.trim();
486
+ if (!u || l.value) return;
487
+ const y = n.value === "draft" ? _() : j();
488
+ X(y, u), c.value = "", g.value = "", l.value = !0;
489
+ try {
490
+ const E = await fetch("http://localhost:5011" + i.value, {
491
+ method: "POST",
492
+ headers: { "Content-Type": "application/json" },
493
+ body: JSON.stringify({
494
+ message: u,
495
+ session_id: y.id,
496
+ // 后端接口读取 action_type,前端内部变量仍用 actionType 对应配置字段。
497
+ action_type: a.value,
498
+ // 后端按 model_source + model 切换实际模型。
499
+ model_source: b.value.source,
500
+ model: b.value.value
501
+ })
502
+ });
503
+ if (!E.ok)
504
+ throw new Error(`HTTP ${E.status}`);
505
+ const r = await E.json();
506
+ y.debugLine = _e(r);
507
+ const G = r.steps || [];
508
+ if (G.length > 0) {
509
+ q(y, G, ie(r));
510
+ return;
511
+ }
512
+ C(y, r.reply);
513
+ } catch (E) {
514
+ g.value = `请求失败:${E.message}`;
515
+ } finally {
516
+ l.value = !1;
517
+ }
518
+ }, ie = (u) => Math.max(1, Math.round(u.usage.eval_count / 8)), _e = (u) => {
519
+ const y = u.usage, E = u.debug, r = `${(y.context_usage_ratio * 100).toFixed(1)}%`;
520
+ return `上下文:${y.prompt_eval_count} / ${y.context_limit}(${r})|回复:${y.eval_count}|历史:${E.history_message_count}`;
521
+ };
522
+ return (u, y) => {
523
+ const E = $("a-alert"), r = $("a-textarea"), G = $("a-select-option"), re = $("a-select"), ge = $("a-icon"), he = $("a-button");
524
+ return d(), w("div", At, [
525
+ g.value ? (d(), F(E, {
526
+ key: 0,
527
+ class: "mb-3",
528
+ message: g.value,
529
+ type: "error",
530
+ "show-icon": ""
531
+ }, null, 8, ["message"])) : O("", !0),
532
+ v("div", St, [
533
+ M(r, {
534
+ value: K(c),
535
+ "onUpdate:value": y[0] || (y[0] = (N) => ce(c) ? c.value = N : null),
536
+ placeholder: `给 ${m.value} 发送消息`,
537
+ "auto-size": { minRows: 2, maxRows: 5 },
538
+ onKeydown: we(fe(H, ["exact", "prevent"]), ["enter"])
539
+ }, null, 8, ["value", "placeholder", "onKeydown"]),
540
+ v("div", It, [
541
+ v("div", Mt, [
542
+ M(re, {
543
+ value: K(a),
544
+ "onUpdate:value": y[1] || (y[1] = (N) => ce(a) ? a.value = N : null),
545
+ size: "small",
546
+ class: "ai-action-type-select"
547
+ }, {
548
+ default: L(() => [
549
+ (d(), w(P, null, B(k, (N) => M(G, {
550
+ key: N.value,
551
+ value: N.value
552
+ }, {
553
+ default: L(() => [
554
+ ae(S(N.label), 1)
555
+ ]),
556
+ _: 2
557
+ }, 1032, ["value"])), 64))
558
+ ]),
559
+ _: 1
560
+ }, 8, ["value"]),
561
+ I.value ? (d(), w("span", Ct, S(I.value), 1)) : O("", !0)
562
+ ]),
563
+ v("div", $t, [
564
+ M(re, {
565
+ value: V.value,
566
+ "onUpdate:value": y[2] || (y[2] = (N) => V.value = N),
567
+ size: "small",
568
+ class: "ai-model-select"
569
+ }, {
570
+ default: L(() => [
571
+ (d(!0), w(P, null, B(h.value, (N) => (d(), F(G, {
572
+ key: N.key,
573
+ value: N.key
574
+ }, {
575
+ default: L(() => [
576
+ ae(S(N.label), 1)
577
+ ]),
578
+ _: 2
579
+ }, 1032, ["value"]))), 128))
580
+ ]),
581
+ _: 1
582
+ }, 8, ["value"]),
583
+ M(he, {
584
+ type: "primary",
585
+ shape: "circle",
586
+ class: "ai-send-btn",
587
+ loading: l.value,
588
+ onClick: H
589
+ }, {
590
+ default: L(() => [
591
+ l.value ? O("", !0) : (d(), F(ge, {
592
+ key: 0,
593
+ type: "icon-send"
594
+ }))
595
+ ]),
596
+ _: 1
597
+ }, 8, ["loading"])
598
+ ])
599
+ ])
600
+ ])
601
+ ]);
602
+ };
603
+ }
604
+ }, Lt = /* @__PURE__ */ z(Tt, [["__scopeId", "data-v-e63f761d"]]), Vt = { class: "ai-chat-wrap flex-fill d-flex bg-white" }, Wt = { class: "flex-fill d-flex flex-column min-w-0" }, Et = {
605
+ __name: "AiAssistantModal",
606
+ props: {
607
+ open: {
608
+ type: Boolean,
609
+ default: !1
610
+ }
611
+ },
612
+ emits: ["close"],
613
+ setup(e, { emit: t }) {
614
+ const s = t, o = ee(), n = A(() => o.state.app.aiAssistantConfig || {}), c = A(() => n.value.title || "AI 小助手"), a = A(() => `gs-eant-comp:ai-assistant:${c.value}`), l = p([]), g = p(""), f = p("draft"), m = p(""), i = p("chat");
615
+ return (() => {
616
+ try {
617
+ const h = localStorage.getItem(a.value);
618
+ if (!h) return;
619
+ const x = JSON.parse(h);
620
+ Array.isArray(x.sessions) && (l.value = x.sessions), x.activeSessionId && (g.value = x.activeSessionId), g.value && l.value.some((V) => V.id === g.value) && (f.value = "chat");
621
+ } catch (h) {
622
+ console.warn("[gs-eant-comp] AI assistant storage parse failed:", h);
623
+ }
624
+ })(), Q([l, g], () => {
625
+ localStorage.setItem(a.value, JSON.stringify({
626
+ activeSessionId: g.value,
627
+ sessions: l.value
628
+ }));
629
+ }, { deep: !0 }), J("aiSessions", l), J("aiActiveSessionId", g), J("aiCurrentView", f), J("aiInputMessage", m), J("aiActionType", i), (h, x) => {
630
+ const V = $("a-modal");
631
+ return d(), F(V, {
632
+ open: e.open,
633
+ title: c.value,
634
+ width: "76vw",
635
+ footer: null,
636
+ "mask-closable": !0,
637
+ "body-style": { padding: 0 },
638
+ "wrap-class-name": "vh-90",
639
+ onCancel: x[0] || (x[0] = (b) => s("close"))
640
+ }, {
641
+ default: L(() => [
642
+ v("div", Vt, [
643
+ M(ze),
644
+ v("main", Wt, [
645
+ f.value === "library" ? (d(), F(Ge, { key: 0 })) : (d(), w(P, { key: 1 }, [
646
+ M(kt),
647
+ M(Lt)
648
+ ], 64))
649
+ ])
650
+ ])
651
+ ]),
652
+ _: 1
653
+ }, 8, ["open", "title"]);
654
+ };
655
+ }
656
+ }, Nt = /* @__PURE__ */ z(Et, [["__scopeId", "data-v-0a4b31b9"]]), de = 58, Ot = 132, D = 16, qt = {
657
+ __name: "AiAssistantTool",
658
+ setup(e) {
659
+ const t = ee(), s = p(!1), o = p(null), n = p(!1), c = p(null), a = p(!1), l = p(0), g = p(0), f = p(0), m = p(0), { width: i, height: k } = /* @__PURE__ */ Oe(), h = p(Math.max(D, window.innerWidth - de - 24)), x = p(Math.max(D, Math.round(window.innerHeight * 0.7))), V = (C, q, H) => Math.min(Math.max(C, q), H), b = () => {
660
+ const C = Math.max(D, i.value - de - D), q = Math.max(D, k.value - Ot - D);
661
+ h.value = V(h.value, D, C), x.value = V(x.value, D, q);
662
+ }, I = (C) => {
663
+ !a.value || c.value !== C.pointerId || (h.value = f.value + C.clientX - l.value, x.value = m.value + C.clientY - g.value, b());
664
+ }, W = (C) => {
665
+ if (c.value !== C.pointerId) return;
666
+ (Math.abs(C.clientX - l.value) > 3 || Math.abs(C.clientY - g.value) > 3) && (n.value = !0, window.setTimeout(() => {
667
+ n.value = !1;
668
+ }, 0)), a.value = !1, c.value = null, window.removeEventListener("pointermove", I), window.removeEventListener("pointerup", W);
669
+ }, R = (C) => {
670
+ C.button === 0 && (c.value = C.pointerId, a.value = !0, l.value = C.clientX, g.value = C.clientY, f.value = h.value, m.value = x.value, window.addEventListener("pointermove", I), window.addEventListener("pointerup", W));
671
+ }, j = () => {
672
+ n.value || (s.value = !0);
673
+ };
674
+ Q([i, k], b, { immediate: !0 });
675
+ const _ = A(() => !!t.state.app.aiAssistantConfig?.enabled), X = A(() => ({
676
+ left: `${h.value}px`,
677
+ top: `${x.value}px`
678
+ }));
679
+ return (C, q) => {
680
+ const H = $("a-button");
681
+ return _.value ? (d(), w("div", {
682
+ key: 0,
683
+ ref_key: "aiFloatingRef",
684
+ ref: o,
685
+ class: "floating-ai",
686
+ style: xe(X.value),
687
+ onPointerdown: R
688
+ }, [
689
+ M(H, {
690
+ class: "tool-btn ai-btn",
691
+ onClick: j
692
+ }, {
693
+ default: L(() => [...q[1] || (q[1] = [
694
+ v("span", { class: "ai-mark" }, "Ai", -1),
695
+ v("span", { class: "ai-label" }, "小助手", -1)
696
+ ])]),
697
+ _: 1
698
+ }),
699
+ M(Nt, {
700
+ open: s.value,
701
+ onClose: q[0] || (q[0] = (ie) => s.value = !1)
702
+ }, null, 8, ["open"])
703
+ ], 36)) : O("", !0);
704
+ };
705
+ }
706
+ }, Ft = /* @__PURE__ */ z(qt, [["__scopeId", "data-v-83236aae"]]), Rt = (e) => {
707
+ e.component("AiAssistantTool", Ft);
708
+ }, Kt = {
709
+ install: Rt
710
+ };
711
+ export {
712
+ Ft as AiAssistantTool,
713
+ Kt as default
714
+ };
@@ -0,0 +1 @@
1
+ (function(E,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue"),require("vuex")):typeof define=="function"&&define.amd?define(["exports","vue","vuex"],e):(E=typeof globalThis<"u"?globalThis:E||self,e(E.GsAiAssistant={},E.Vue,E.Vuex))})(this,(function(E,e,D){"use strict";const F=new WeakMap,U=(...t)=>{var n;const s=t[0],l=(n=e.getCurrentInstance())===null||n===void 0?void 0:n.proxy,a=l??e.getCurrentScope();if(a==null&&!e.hasInjectionContext())throw new Error("injectLocal must be called in setup");return a&&F.has(a)&&s in F.get(a)?F.get(a)[s]:e.inject(...t)},Y=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const G=Object.prototype.toString,Q=t=>G.call(t)==="[object Object]";function q(t){return t.endsWith("rem")?Number.parseFloat(t)*16:Number.parseFloat(t)}function R(t){return Array.isArray(t)?t:[t]}function X(t){return e.getCurrentInstance()}function J(t,n=!0,s){X()?e.onMounted(t,s):n?t():e.nextTick(t)}function Z(t,n,s){return e.watch(t,n,{...s,immediate:!0})}const W=Y?window:void 0;function v(t){var n;const s=e.toValue(t);return(n=s?.$el)!==null&&n!==void 0?n:s}function O(...t){const n=(l,a,d,o)=>(l.addEventListener(a,d,o),()=>l.removeEventListener(a,d,o)),s=e.computed(()=>{const l=R(e.toValue(t[0])).filter(a=>a!=null);return l.every(a=>typeof a!="string")?l:void 0});return Z(()=>{var l,a;return[(l=(a=s.value)===null||a===void 0?void 0:a.map(d=>v(d)))!==null&&l!==void 0?l:[W].filter(d=>d!=null),R(e.toValue(s.value?t[1]:t[0])),R(e.unref(s.value?t[2]:t[1])),e.toValue(s.value?t[3]:t[2])]},([l,a,d,o],i,_)=>{if(!l?.length||!a?.length||!d?.length)return;const u=Q(o)?{...o}:o,m=l.flatMap(r=>a.flatMap(k=>d.map(g=>n(r,k,g,u))));_(()=>{m.forEach(r=>r())})},{flush:"post"})}function ee(){const t=e.shallowRef(!1),n=e.getCurrentInstance();return n&&e.onMounted(()=>{t.value=!0},n),t}function te(t){const n=ee();return e.computed(()=>(n.value,!!t()))}const ne=Symbol("vueuse-ssr-width");function se(){const t=e.hasInjectionContext()?U(ne,null):null;return typeof t=="number"?t:void 0}function oe(t,n={}){const{window:s=W,ssrWidth:l=se()}=n,a=te(()=>s&&"matchMedia"in s&&typeof s.matchMedia=="function"),d=e.shallowRef(typeof l=="number"),o=e.shallowRef(),i=e.shallowRef(!1),_=u=>{i.value=u.matches};return e.watchEffect(()=>{if(d.value){d.value=!a.value,i.value=e.toValue(t).split(",").some(u=>{const m=u.includes("not all"),r=u.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/),k=u.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);let g=!!(r||k);return r&&g&&(g=l>=q(r[1])),k&&g&&(g=l<=q(k[1])),m?!g:g});return}a.value&&(o.value=s.matchMedia(e.toValue(t)),i.value=o.value.matches)}),O(o,"change",_,{passive:!0}),e.computed(()=>i.value)}function ae(t={}){const{window:n=W,initialWidth:s=Number.POSITIVE_INFINITY,initialHeight:l=Number.POSITIVE_INFINITY,listenOrientation:a=!0,includeScrollbar:d=!0,type:o="inner"}=t,i=e.shallowRef(s),_=e.shallowRef(l),u=()=>{if(n)if(o==="outer")i.value=n.outerWidth,_.value=n.outerHeight;else if(o==="visual"&&n.visualViewport){const{width:r,height:k,scale:g}=n.visualViewport;i.value=Math.round(r*g),_.value=Math.round(k*g)}else d?(i.value=n.innerWidth,_.value=n.innerHeight):(i.value=n.document.documentElement.clientWidth,_.value=n.document.documentElement.clientHeight)};u(),J(u);const m={passive:!0};return O("resize",u,m),n&&o==="visual"&&n.visualViewport&&O(n.visualViewport,"resize",u,m),a&&e.watch(oe("(orientation: portrait)"),()=>u()),{width:i,height:_}}const M=(t,n)=>{const s=t.__vccOpts||t;for(const[l,a]of n)s[l]=a;return s},le={class:"ai-chat-sidebar border-end p-3 d-flex flex-column"},ie={class:"ai-sidebar-nav d-flex flex-column gap-1"},re={class:"ai-sidebar-section-title d-flex align-items-center gap-2"},ce={class:"d-flex flex-column gap-2"},de=["onClick"],pe={class:"text-truncate flex-fill"},me=M({__name:"AiAssistantSidebar",setup(t){const n=e.inject("aiCurrentView",e.ref("draft")),s=e.inject("aiSessions",e.ref([])),l=e.inject("aiActiveSessionId",e.ref("")),a=e.inject("aiInputMessage",e.ref("")),d=e.ref(["recent"]),o=e.computed(()=>[...s.value].sort((m,r)=>r.updatedAt-m.updatedAt)),i=()=>{n.value="draft",a.value=""},_=m=>{l.value=m,n.value="chat"},u=m=>{s.value=s.value.filter(r=>r.id!==m),l.value===m&&(l.value="",n.value="draft",a.value="")};return(m,r)=>{const k=e.resolveComponent("a-icon"),g=e.resolveComponent("a-empty"),b=e.resolveComponent("a-button"),C=e.resolveComponent("a-collapse-panel"),y=e.resolveComponent("a-collapse");return e.openBlock(),e.createElementBlock("aside",le,[e.createElementVNode("div",ie,[e.createElementVNode("button",{class:e.normalizeClass(["ai-sidebar-nav-item",{active:e.unref(n)==="draft"}]),onClick:i},[e.createVNode(k,{type:"icon-edit"}),r[2]||(r[2]=e.createElementVNode("span",null,"新对话",-1))],2),e.createElementVNode("button",{class:e.normalizeClass(["ai-sidebar-nav-item",{active:e.unref(n)==="library"}]),onClick:r[0]||(r[0]=w=>n.value="library")},[e.createVNode(k,{type:"icon-appstore"}),r[3]||(r[3]=e.createElementVNode("span",null,"AI 指令库",-1))],2)]),e.createVNode(y,{activeKey:d.value,"onUpdate:activeKey":r[1]||(r[1]=w=>d.value=w),ghost:"",class:"ai-session-collapse flex-fill overflow-auto"},{default:e.withCtx(()=>[e.createVNode(C,{key:"recent"},{header:e.withCtx(()=>[e.createElementVNode("div",re,[e.createVNode(k,{type:"icon-history"}),r[4]||(r[4]=e.createElementVNode("span",null,"最近会话",-1))])]),default:e.withCtx(()=>[e.createElementVNode("div",ce,[o.value.length===0?(e.openBlock(),e.createBlock(g,{key:0,description:"暂无会话"})):e.createCommentVNode("",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.value,w=>(e.openBlock(),e.createElementBlock("div",{key:w.id,class:e.normalizeClass(["ai-session-item d-flex align-items-center gap-2",{active:e.unref(n)==="chat"&&w.id===e.unref(l)}]),onClick:V=>_(w.id)},[e.createElementVNode("span",pe,e.toDisplayString(w.title),1),e.createVNode(b,{type:"text",size:"small",class:"ai-session-delete",onClick:e.withModifiers(V=>u(w.id),["stop"])},{default:e.withCtx(()=>[e.createVNode(k,{type:"icon-delete"})]),_:1},8,["onClick"])],10,de))),128))])]),_:1})]),_:1},8,["activeKey"])])}}},[["__scopeId","data-v-ff65b680"]]),ue={class:"ai-instruction-library flex-fill overflow-auto bg-white p-4"},fe={class:"row g-3 mt-2"},_e=["onClick"],ge={class:"fw-semibold mb-2"},he={class:"small text-muted"},ye=M({__name:"AiInstructionLibrary",setup(t){const n=D.useStore(),s=e.ref(""),l=e.inject("aiInputMessage",e.ref("")),a=e.inject("aiActionType",e.ref("chat")),d=e.inject("aiCurrentView",e.ref("draft")),o=e.computed(()=>n.state.app.aiAssistantConfig||{}),i=e.computed(()=>{const m=o.value.instructions;return Array.isArray(m)?m:[]}),_=e.computed(()=>{const m=i.value||[],r=m.find(k=>k.label===s.value)||m[0];return Array.isArray(r?.items)?r.items:[]}),u=m=>{l.value=m.prompt||"",a.value=m.actionType||"chat",d.value="draft"};return e.watch(i,(m=[])=>{m.some(r=>r.label===s.value)||(s.value=m[0]?.label||"")},{immediate:!0}),(m,r)=>{const k=e.resolveComponent("a-tab-pane"),g=e.resolveComponent("a-tabs");return e.openBlock(),e.createElementBlock("div",ue,[r[1]||(r[1]=e.createElementVNode("div",{class:"text-center mb-4"},[e.createElementVNode("h3",{class:"mb-2"},"AI 指令库"),e.createElementVNode("div",{class:"text-muted"},"选择一个指令模板,快速开始当前系统的 AI 任务")],-1)),e.createVNode(g,{activeKey:s.value,"onUpdate:activeKey":r[0]||(r[0]=b=>s.value=b),centered:""},{default:e.withCtx(()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(i.value,b=>(e.openBlock(),e.createBlock(k,{key:b.label,tab:b.label},null,8,["tab"]))),128))]),_:1},8,["activeKey"]),e.createElementVNode("div",fe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(_.value,b=>(e.openBlock(),e.createElementBlock("div",{key:b.prompt,class:"col-6 col-xl-4"},[e.createElementVNode("button",{class:"ai-instruction-card w-100 h-100 text-start bg-white rounded p-3",onClick:C=>u(b)},[e.createElementVNode("div",ge,e.toDisplayString(b.title),1),e.createElementVNode("div",he,e.toDisplayString(b.description),1)],8,_e)]))),128))])])}}},[["__scopeId","data-v-85d5df68"]]),be={class:"ai-message-bubble bg-light rounded p-3"},ke={class:"fw-semibold mb-2"},we={key:0,class:"mb-2"},xe={key:1,class:"small text-muted mb-2"},Ce={class:"ai-pre-wrap mb-0"},Ve=M({__name:"AiTableResultMessage",props:{message:{type:Object,required:!0}},setup(t){const n=t,s=e.computed(()=>(Array.isArray(n.message.columns)?n.message.columns:[]).map(o=>{const i=typeof o=="string"?o:o.key||o.dataIndex||o.title;return{title:typeof o=="string"?o:o.title||i,dataIndex:typeof o=="string"?o:o.dataIndex||i,key:i}})),l=e.computed(()=>(Array.isArray(n.message.rows)?n.message.rows:[]).map((o,i)=>({key:i,...o}))),a=e.computed(()=>JSON.stringify({columns:n.message.columns,rows:n.message.rows},null,2));return(d,o)=>{const i=e.resolveComponent("a-table");return e.openBlock(),e.createElementBlock("div",be,[e.createElementVNode("div",ke,e.toDisplayString(t.message.title||"表格结果"),1),t.message.summary?(e.openBlock(),e.createElementBlock("div",we,e.toDisplayString(t.message.summary),1)):e.createCommentVNode("",!0),t.message.sql?(e.openBlock(),e.createElementBlock("div",xe,"SQL:"+e.toDisplayString(t.message.sql),1)):e.createCommentVNode("",!0),e.createVNode(i,{class:"mb-3",size:"small",bordered:"",columns:s.value,"data-source":l.value,pagination:!1,scroll:{x:!0}},null,8,["columns","data-source"]),e.createElementVNode("pre",Ce,e.toDisplayString(a.value),1)])}}},[["__scopeId","data-v-de55b932"]]),Se={class:"small text-muted mb-2"},Ne={key:0,class:"ai-message-bubble bg-light rounded p-3"},Ae={class:"ai-pre-wrap text-warning-emphasis mb-3"},Ee={key:1,class:"ai-message-bubble bg-warning-subtle rounded p-3"},Be={class:"ai-pre-wrap text-warning-emphasis mb-0"},Ie={key:3,class:"ai-message-bubble bg-light rounded p-3"},Me={class:"fw-semibold mb-2"},$e={key:0,class:"mb-2"},Te={class:"small text-muted mb-2"},De={key:0},je={key:1},Le={key:1,class:"small text-muted mb-2"},Fe={class:"ai-pre-wrap mb-0"},Re={key:4,class:"ai-message-bubble bg-transparent p-0"},We={class:"ai-thinking-content"},Oe={class:"ai-thinking-content"},qe={key:0,class:"h-100 d-flex align-items-center justify-content-center text-muted"},ze=M({__name:"AiChatMessages",setup(t){const n=D.useStore(),s=e.inject("aiSessions",e.ref([])),l=e.inject("aiActiveSessionId",e.ref("")),a=e.inject("aiCurrentView",e.ref("draft")),d=e.computed(()=>n.state.app.aiAssistantConfig||{}),o=e.computed(()=>d.value.title||"AI 小助手"),i=e.computed(()=>d.value.welcomeMessage||""),_=e.ref(),u=e.computed(()=>{if(a.value==="draft")return[];const y=s.value.find(w=>w.id===l.value);return Array.isArray(y?.messages)?y.messages:[]});e.watch([l,()=>u.value.length],async()=>{await e.nextTick(),_.value.scrollTop=_.value.scrollHeight});const m=(y={})=>(Array.isArray(y.columns)?y.columns:[]).map(V=>({title:V,dataIndex:V,key:V})),r=(y={})=>(Array.isArray(y.rows)?y.rows:[]).map((V,I)=>({key:I,...V})),k=y=>`Thinking ${y||8}s`,g=y=>JSON.stringify(y.data||[],null,2),b=y=>Array.isArray(y)?y.join("、"):y,C=y=>y.role==="user"?"bg-primary-subtle text-dark p-3":y.type==="error"?"bg-danger-subtle text-danger border border-danger-subtle p-3":y.role==="assistant"?"bg-transparent p-0":"bg-light p-3";return(y,w)=>{const V=e.resolveComponent("a-table"),I=e.resolveComponent("a-collapse-panel"),$=e.resolveComponent("a-collapse");return e.openBlock(),e.createElementBlock("div",{ref_key:"messageWrapRef",ref:_,class:"ai-chat-messages flex-fill overflow-auto bg-white"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(u.value,(f,j)=>(e.openBlock(),e.createElementBlock("div",{key:j,class:e.normalizeClass(["d-flex flex-column mb-4",[f.role==="user"?"align-items-end":"align-items-start",f.type]])},[e.createElementVNode("div",Se,e.toDisplayString(f.role==="user"?"我":o.value),1),f.type==="sql_result"?(e.openBlock(),e.createElementBlock("div",Ne,[w[0]||(w[0]=e.createElementVNode("div",{class:"fw-semibold mb-2"},"执行 SQL:",-1)),e.createElementVNode("pre",Ae,e.toDisplayString(f.sql),1),e.createVNode(V,{size:"small",bordered:"",columns:m(f.result),"data-source":r(f.result),pagination:!1,scroll:{x:!0}},null,8,["columns","data-source"])])):f.type==="sql_preview"?(e.openBlock(),e.createElementBlock("div",Ee,[w[1]||(w[1]=e.createElementVNode("div",{class:"fw-semibold mb-2"},"SQL 预览:",-1)),e.createElementVNode("pre",Be,e.toDisplayString(f.content),1)])):f.type==="table_result"?(e.openBlock(),e.createBlock(Ve,{key:2,message:f},null,8,["message"])):f.type==="chart_result"?(e.openBlock(),e.createElementBlock("div",Ie,[e.createElementVNode("div",Me,e.toDisplayString(f.title||"图表结果"),1),f.summary?(e.openBlock(),e.createElementBlock("div",$e,e.toDisplayString(f.summary),1)):e.createCommentVNode("",!0),e.createElementVNode("div",Te,[e.createTextVNode(" 图表类型:"+e.toDisplayString(f.chartType||"未指定")+" ",1),f.xField?(e.openBlock(),e.createElementBlock("span",De,"|X 轴:"+e.toDisplayString(f.xField),1)):e.createCommentVNode("",!0),f.yFields?(e.openBlock(),e.createElementBlock("span",je,"|指标:"+e.toDisplayString(b(f.yFields)),1)):e.createCommentVNode("",!0)]),f.sql?(e.openBlock(),e.createElementBlock("div",Le,"SQL:"+e.toDisplayString(f.sql),1)):e.createCommentVNode("",!0),e.createElementVNode("pre",Fe,e.toDisplayString(g(f)),1)])):f.type==="thinking"?(e.openBlock(),e.createElementBlock("div",Re,[e.createVNode($,{ghost:"",class:"ai-thinking-collapse"},{default:e.withCtx(()=>[e.createVNode(I,{key:"thinking",header:k(f.thinkingSeconds)},{default:e.withCtx(()=>[e.createElementVNode("pre",We,e.toDisplayString(f.content),1)]),_:2},1032,["header"])]),_:2},1024)])):(e.openBlock(),e.createElementBlock("div",{key:5,class:e.normalizeClass(["ai-message-bubble ai-pre-wrap rounded",C(f)])},[f.thinking?(e.openBlock(),e.createBlock($,{key:0,ghost:"",class:"ai-thinking-collapse"},{default:e.withCtx(()=>[e.createVNode(I,{key:"thinking",header:k(f.thinkingSeconds)},{default:e.withCtx(()=>[e.createElementVNode("pre",Oe,e.toDisplayString(f.thinking),1)]),_:2},1032,["header"])]),_:2},1024)):e.createCommentVNode("",!0),e.createElementVNode("div",null,e.toDisplayString(f.content),1)],2))],2))),128)),u.value.length===0?(e.openBlock(),e.createElementBlock("div",qe,e.toDisplayString(i.value||"开始一个新的 AI 对话"),1)):e.createCommentVNode("",!0)],512)}}},[["__scopeId","data-v-8bae25ad"]]),Pe={class:"border-top px-4 py-3"},Ke={class:"ai-input-box d-flex flex-column gap-3 p-3 bg-white"},He={class:"d-flex align-items-center justify-content-between gap-3 w-100"},Ue={class:"d-flex align-items-center gap-2 min-w-0"},Ye={key:0,class:"small text-muted text-nowrap"},Ge={class:"d-flex align-items-center gap-2"},Qe=M({__name:"AiChatInput",setup(t){const n=D.useStore(),s=e.inject("aiSessions",e.ref([])),l=e.inject("aiActiveSessionId",e.ref("")),a=e.inject("aiCurrentView",e.ref("draft")),d=e.inject("aiInputMessage",e.ref("")),o=e.inject("aiActionType",e.ref("chat")),i=e.ref(!1),_=e.ref(""),u=e.computed(()=>n.state.app.aiAssistantConfig),m=e.computed(()=>u.value.title||"AI 小助手"),r=e.computed(()=>u.value.chatUrl),k=[{label:"聊天",value:"chat"},{label:"SQL",value:"sql"},{label:"表格",value:"table"},{label:"图表",value:"chart"}],g=e.computed(()=>u.value.models.map(p=>{const h=p.source||p.model_source||u.value.defaultModelSource||"online";return{...p,source:h,key:`${h}::${p.value}`}})),b=()=>{const p=u.value.defaultModelSource||"online",h=u.value.defaultModel;return g.value.find(c=>c.source===p&&c.value===h).key},C=e.ref(b()),y=e.computed(()=>g.value.find(p=>p.key===C.value)),w=e.computed(()=>a.value==="draft"?"":s.value.find(h=>h.id===l.value).debugLine),V=()=>"s_"+Date.now().toString(36)+"_"+Math.random().toString(36).slice(2,8),I=()=>({id:V(),title:"新对话",messages:[],debugLine:"",updatedAt:Date.now()}),$=()=>s.value.find(p=>p.id===l.value),f=()=>{const p=I();return s.value.unshift(p),l.value=p.id,a.value="chat",$()},j=(p,h)=>{p.messages.push({role:"user",content:h}),p.title==="新对话"&&(p.title=h),p.updatedAt=Date.now()},x=(p,h)=>{p.messages.push({role:"assistant",content:h}),p.updatedAt=Date.now()},A=(p,h,S)=>{for(const c of h)c.type==="ai"&&c.content?p.messages.push({role:"assistant",type:"ai",content:c.content,thinking:c.thinking,thinkingSeconds:S}):["thinking","thought","reasoning"].includes(c.type)&&c.content?p.messages.push({role:"assistant",type:"thinking",content:c.content,thinkingSeconds:S}):c.type==="sql_preview"&&c.content?p.messages.push({role:"assistant",type:"sql_preview",content:c.content}):c.type==="sql_result"?p.messages.push({role:"assistant",type:"sql_result",sql:c.sql,result:c.result}):c.type==="table_result"?p.messages.push({role:"assistant",type:"table_result",title:c.title,sql:c.sql,columns:c.columns,rows:c.rows,summary:c.summary}):c.type==="chart_result"?p.messages.push({role:"assistant",type:"chart_result",title:c.title,sql:c.sql,chartType:c.chart_type,xField:c.x_field,yFields:c.y_fields,data:c.data,summary:c.summary}):c.type==="error"&&c.content&&p.messages.push({role:"assistant",type:"error",content:c.content});p.updatedAt=Date.now()},T=async()=>{const p=d.value.trim();if(!p||i.value)return;const h=a.value==="draft"?f():$();j(h,p),d.value="",_.value="",i.value=!0;try{const S=await fetch("http://localhost:5011"+r.value,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:p,session_id:h.id,action_type:o.value,model_source:y.value.source,model:y.value.value})});if(!S.ok)throw new Error(`HTTP ${S.status}`);const c=await S.json();h.debugLine=tt(c);const L=c.steps||[];if(L.length>0){A(h,L,K(c));return}x(h,c.reply)}catch(S){_.value=`请求失败:${S.message}`}finally{i.value=!1}},K=p=>Math.max(1,Math.round(p.usage.eval_count/8)),tt=p=>{const h=p.usage,S=p.debug,c=`${(h.context_usage_ratio*100).toFixed(1)}%`;return`上下文:${h.prompt_eval_count} / ${h.context_limit}(${c})|回复:${h.eval_count}|历史:${S.history_message_count}`};return(p,h)=>{const S=e.resolveComponent("a-alert"),c=e.resolveComponent("a-textarea"),L=e.resolveComponent("a-select-option"),H=e.resolveComponent("a-select"),nt=e.resolveComponent("a-icon"),st=e.resolveComponent("a-button");return e.openBlock(),e.createElementBlock("div",Pe,[_.value?(e.openBlock(),e.createBlock(S,{key:0,class:"mb-3",message:_.value,type:"error","show-icon":""},null,8,["message"])):e.createCommentVNode("",!0),e.createElementVNode("div",Ke,[e.createVNode(c,{value:e.unref(d),"onUpdate:value":h[0]||(h[0]=N=>e.isRef(d)?d.value=N:null),placeholder:`给 ${m.value} 发送消息`,"auto-size":{minRows:2,maxRows:5},onKeydown:e.withKeys(e.withModifiers(T,["exact","prevent"]),["enter"])},null,8,["value","placeholder","onKeydown"]),e.createElementVNode("div",He,[e.createElementVNode("div",Ue,[e.createVNode(H,{value:e.unref(o),"onUpdate:value":h[1]||(h[1]=N=>e.isRef(o)?o.value=N:null),size:"small",class:"ai-action-type-select"},{default:e.withCtx(()=>[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(k,N=>e.createVNode(L,{key:N.value,value:N.value},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(N.label),1)]),_:2},1032,["value"])),64))]),_:1},8,["value"]),w.value?(e.openBlock(),e.createElementBlock("span",Ye,e.toDisplayString(w.value),1)):e.createCommentVNode("",!0)]),e.createElementVNode("div",Ge,[e.createVNode(H,{value:C.value,"onUpdate:value":h[2]||(h[2]=N=>C.value=N),size:"small",class:"ai-model-select"},{default:e.withCtx(()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(g.value,N=>(e.openBlock(),e.createBlock(L,{key:N.key,value:N.key},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(N.label),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value"]),e.createVNode(st,{type:"primary",shape:"circle",class:"ai-send-btn",loading:i.value,onClick:T},{default:e.withCtx(()=>[i.value?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(nt,{key:0,type:"icon-send"}))]),_:1},8,["loading"])])])])])}}},[["__scopeId","data-v-e63f761d"]]),Xe={class:"ai-chat-wrap flex-fill d-flex bg-white"},Je={class:"flex-fill d-flex flex-column min-w-0"},Ze=M({__name:"AiAssistantModal",props:{open:{type:Boolean,default:!1}},emits:["close"],setup(t,{emit:n}){const s=n,l=D.useStore(),a=e.computed(()=>l.state.app.aiAssistantConfig||{}),d=e.computed(()=>a.value.title||"AI 小助手"),o=e.computed(()=>`gs-eant-comp:ai-assistant:${d.value}`),i=e.ref([]),_=e.ref(""),u=e.ref("draft"),m=e.ref(""),r=e.ref("chat");return(()=>{try{const g=localStorage.getItem(o.value);if(!g)return;const b=JSON.parse(g);Array.isArray(b.sessions)&&(i.value=b.sessions),b.activeSessionId&&(_.value=b.activeSessionId),_.value&&i.value.some(C=>C.id===_.value)&&(u.value="chat")}catch(g){console.warn("[gs-eant-comp] AI assistant storage parse failed:",g)}})(),e.watch([i,_],()=>{localStorage.setItem(o.value,JSON.stringify({activeSessionId:_.value,sessions:i.value}))},{deep:!0}),e.provide("aiSessions",i),e.provide("aiActiveSessionId",_),e.provide("aiCurrentView",u),e.provide("aiInputMessage",m),e.provide("aiActionType",r),(g,b)=>{const C=e.resolveComponent("a-modal");return e.openBlock(),e.createBlock(C,{open:t.open,title:d.value,width:"76vw",footer:null,"mask-closable":!0,"body-style":{padding:0},"wrap-class-name":"vh-90",onCancel:b[0]||(b[0]=y=>s("close"))},{default:e.withCtx(()=>[e.createElementVNode("div",Xe,[e.createVNode(me),e.createElementVNode("main",Je,[u.value==="library"?(e.openBlock(),e.createBlock(ye,{key:0})):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createVNode(ze),e.createVNode(Qe)],64))])])]),_:1},8,["open","title"])}}},[["__scopeId","data-v-0a4b31b9"]]),z=58,ve=132,B=16,P=M({__name:"AiAssistantTool",setup(t){const n=D.useStore(),s=e.ref(!1),l=e.ref(null),a=e.ref(!1),d=e.ref(null),o=e.ref(!1),i=e.ref(0),_=e.ref(0),u=e.ref(0),m=e.ref(0),{width:r,height:k}=ae(),g=e.ref(Math.max(B,window.innerWidth-z-24)),b=e.ref(Math.max(B,Math.round(window.innerHeight*.7))),C=(x,A,T)=>Math.min(Math.max(x,A),T),y=()=>{const x=Math.max(B,r.value-z-B),A=Math.max(B,k.value-ve-B);g.value=C(g.value,B,x),b.value=C(b.value,B,A)},w=x=>{!o.value||d.value!==x.pointerId||(g.value=u.value+x.clientX-i.value,b.value=m.value+x.clientY-_.value,y())},V=x=>{if(d.value!==x.pointerId)return;(Math.abs(x.clientX-i.value)>3||Math.abs(x.clientY-_.value)>3)&&(a.value=!0,window.setTimeout(()=>{a.value=!1},0)),o.value=!1,d.value=null,window.removeEventListener("pointermove",w),window.removeEventListener("pointerup",V)},I=x=>{x.button===0&&(d.value=x.pointerId,o.value=!0,i.value=x.clientX,_.value=x.clientY,u.value=g.value,m.value=b.value,window.addEventListener("pointermove",w),window.addEventListener("pointerup",V))},$=()=>{a.value||(s.value=!0)};e.watch([r,k],y,{immediate:!0});const f=e.computed(()=>!!n.state.app.aiAssistantConfig?.enabled),j=e.computed(()=>({left:`${g.value}px`,top:`${b.value}px`}));return(x,A)=>{const T=e.resolveComponent("a-button");return f.value?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"aiFloatingRef",ref:l,class:"floating-ai",style:e.normalizeStyle(j.value),onPointerdown:I},[e.createVNode(T,{class:"tool-btn ai-btn",onClick:$},{default:e.withCtx(()=>[...A[1]||(A[1]=[e.createElementVNode("span",{class:"ai-mark"},"Ai",-1),e.createElementVNode("span",{class:"ai-label"},"小助手",-1)])]),_:1}),e.createVNode(Ze,{open:s.value,onClose:A[0]||(A[0]=K=>s.value=!1)},null,8,["open"])],36)):e.createCommentVNode("",!0)}}},[["__scopeId","data-v-83236aae"]]),et={install:t=>{t.component("AiAssistantTool",P)}};E.AiAssistantTool=P,E.default=et,Object.defineProperties(E,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
package/dist/vite.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
package/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ declare module 'gs-ai-assistant';
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "gs-ai-assistant",
3
+ "private": false,
4
+ "version": "1.0.0-beta.0",
5
+ "main": "dist/gs-eant-comp.umd.cjs",
6
+ "module": "dist/gs-eant-comp.js",
7
+ "types": "index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "index.d.ts"
11
+ ],
12
+ "type": "module",
13
+ "scripts": {
14
+ "dev": "vite",
15
+ "build": "vite build",
16
+ "preview": "vite preview",
17
+ "gusean": "vite build",
18
+ "test": "vitest"
19
+ },
20
+ "dependencies": {
21
+ "@vueuse/core": "^14.3.0",
22
+ "ant-design-vue": "^4.2.6",
23
+ "axios": "^1.13.2",
24
+ "grid-layout-plus": "^1.1.1",
25
+ "gs-eant-comp": "^3.1.8-beta.9",
26
+ "gs-flow-engine": "^2.2.6",
27
+ "nprogress": "^0.2.0",
28
+ "qs": "^6.14.0",
29
+ "vue": "^3.5.25",
30
+ "vue-request": "^2.0.4",
31
+ "vue-router": "^4.6.3",
32
+ "vue3-colorpicker": "^2.3.0",
33
+ "vue3-slide-verify": "^1.1.8",
34
+ "vuedraggable": "^4.1.0",
35
+ "vuex": "^4.1.0"
36
+ },
37
+ "devDependencies": {
38
+ "@vitejs/plugin-vue": "^6.0.1",
39
+ "bootstrap": "^5.3.8",
40
+ "less": "^4.4.2",
41
+ "vite": "^7.2.4"
42
+ }
43
+ }