@seer-ai/seer-vue 0.1.0-beta.11 → 0.1.0-beta.13
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 +22 -0
- package/dist/client.d.ts +34 -0
- package/dist/components/SeerChat.vue.d.ts +1 -0
- package/dist/components/SeerOrderCard.vue.d.ts +13 -0
- package/dist/content.d.ts +6 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +334 -226
- package/dist/useSeerChat.d.ts +75 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,6 +60,28 @@ app.use(SeerChatPlugin, {
|
|
|
60
60
|
|
|
61
61
|
插件在建会话时发 `X-Seer-Org-Owner`。seer 不校验这个值,只用于补报价客户编码,不参与订单归属。
|
|
62
62
|
|
|
63
|
+
## Order estimate card
|
|
64
|
+
|
|
65
|
+
客户发下单模板、估价成功后,回复附带 `order_card`,`<SeerChat>` 在消息下方画「物流费用智能核算」卡片(渠道、
|
|
66
|
+
官网指导价 / 补贴价、计费重、各项费用、已补贴、预估总金额、「提交订单」按钮),正文里同一份费用的文字版自动去掉。
|
|
67
|
+
自定义 UI:助手消息上有 `message.orderCard`,可用导出的 `<SeerOrderCard :card="card" @submit="send" />`,
|
|
68
|
+
正文用 `withoutCardText(content, card)` 去掉重复的文字版。`toContentLines()` 会把行首「标签:」切成 `label` 段。
|
|
69
|
+
|
|
70
|
+
## Ordering with the customer's login token (`sellerToken`)
|
|
71
|
+
|
|
72
|
+
和 `orgOwner` 同一处取已登录用户的多发货登录 token 传进来,客户在聊天里回「确认下单」后,seer 用它调多发货
|
|
73
|
+
`/seller/order/create` 直接下单并回订单号;不传就转客服下单。插件把它放在每条聊天请求的请求头
|
|
74
|
+
`X-DFH-Seller-Token`(不进会话 token,不发给上传接口)。登录态会变时传函数,每次发消息都现取。
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
app.use(SeerChatPlugin, {
|
|
78
|
+
sessionEndpoint: 'https://seer.example.com/v1/browser/session',
|
|
79
|
+
endpoint: 'https://seer.example.com/v1/browser/chat/completions',
|
|
80
|
+
orgOwner: () => currentUser.value?.orgOwner,
|
|
81
|
+
sellerToken: () => currentUser.value?.token,
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
|
|
63
85
|
## Use custom UI
|
|
64
86
|
|
|
65
87
|
自定义 UI 时**不要**直接把 `message.content` 当纯文本渲染——回复里的下载/截图链接是裸
|
package/dist/client.d.ts
CHANGED
|
@@ -3,6 +3,34 @@ export interface SeerChatMessage {
|
|
|
3
3
|
role: SeerChatRole;
|
|
4
4
|
content: string;
|
|
5
5
|
name?: string;
|
|
6
|
+
/** 助手消息附带的下单估价卡片;只用于显示,不随历史发回服务端。 */
|
|
7
|
+
orderCard?: SeerOrderCard;
|
|
8
|
+
}
|
|
9
|
+
export interface SeerOrderCardItem {
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
/** 有补贴价时官网指导价划线 */
|
|
13
|
+
struck?: boolean;
|
|
14
|
+
detail?: string;
|
|
15
|
+
}
|
|
16
|
+
/** 「物流费用智能核算」卡片:行已经按多发货卖家端「下单详情」规则排好,照着画就行。 */
|
|
17
|
+
export interface SeerOrderCard {
|
|
18
|
+
type: 'order_estimate';
|
|
19
|
+
title: string;
|
|
20
|
+
channel_name: string;
|
|
21
|
+
rows: SeerOrderCardItem[];
|
|
22
|
+
subsidy: SeerOrderCardItem | null;
|
|
23
|
+
coupon: SeerOrderCardItem | null;
|
|
24
|
+
total: SeerOrderCardItem;
|
|
25
|
+
note: string;
|
|
26
|
+
/** 正文里同一份费用的文字版;画了卡片时从正文里去掉它(`withoutCardText`),免得显示两遍 */
|
|
27
|
+
panel_text: string;
|
|
28
|
+
/** 能下单时有:按钮文案和点了要发的消息(「确认下单」);不能下单时为 null,看 blocked_reason。 */
|
|
29
|
+
action: {
|
|
30
|
+
label: string;
|
|
31
|
+
message: string;
|
|
32
|
+
} | null;
|
|
33
|
+
blocked_reason: string;
|
|
6
34
|
}
|
|
7
35
|
export type SeerOrgOwner = string | (() => string | undefined);
|
|
8
36
|
export interface SeerClientOptions {
|
|
@@ -14,6 +42,11 @@ export interface SeerClientOptions {
|
|
|
14
42
|
challengeTokenProvider?: () => Promise<string>;
|
|
15
43
|
/** 已登录用户的多发货 orgOwner;报价时自动当作客户编码。登录态会变时传函数。 */
|
|
16
44
|
orgOwner?: SeerOrgOwner;
|
|
45
|
+
/**
|
|
46
|
+
* 已登录用户的多发货登录 token(和 orgOwner 同一处取)。随每条聊天消息放在请求头
|
|
47
|
+
* X-DFH-Seller-Token,客户确认后 AI 用它估价和下单;不传时确认下单转客服。登录态会变时传函数。
|
|
48
|
+
*/
|
|
49
|
+
sellerToken?: SeerOrgOwner;
|
|
17
50
|
model?: string;
|
|
18
51
|
fetcher?: typeof fetch;
|
|
19
52
|
now?: () => number;
|
|
@@ -50,6 +83,7 @@ export interface SeerChatResult {
|
|
|
50
83
|
citations: string[];
|
|
51
84
|
handoffRequested: boolean;
|
|
52
85
|
finishReason?: string;
|
|
86
|
+
orderCard?: SeerOrderCard;
|
|
53
87
|
}
|
|
54
88
|
export interface SeerClient {
|
|
55
89
|
transcriptionEnabled: boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SeerOrderCard } from "../client";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
card: SeerOrderCard;
|
|
4
|
+
/** 不是最新一张卡、或正在回复时,按钮不可点 */
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
+
submit: (message: string) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onSubmit?: ((message: string) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
package/dist/content.d.ts
CHANGED
|
@@ -15,6 +15,9 @@ export type ContentSegment = {
|
|
|
15
15
|
} | {
|
|
16
16
|
kind: 'strong';
|
|
17
17
|
value: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'label';
|
|
20
|
+
value: string;
|
|
18
21
|
};
|
|
19
22
|
export interface ContentOptions {
|
|
20
23
|
complete?: boolean;
|
|
@@ -22,3 +25,6 @@ export interface ContentOptions {
|
|
|
22
25
|
export declare function linkAnchorLabel(prefix: string): string | null;
|
|
23
26
|
export declare function toContentSegments(content: string, options?: ContentOptions): ContentSegment[];
|
|
24
27
|
export declare function toContentLines(content: string, options?: ContentOptions): ContentSegment[][];
|
|
28
|
+
export declare function withoutCardText(content: string, card?: {
|
|
29
|
+
panel_text?: string;
|
|
30
|
+
} | null): string;
|
package/dist/index.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.seer-chat[data-v-
|
|
1
|
+
.seer-order-card[data-v-17d9e82e]{background:linear-gradient(#eef1fb,#fff 56px);border:1px solid #7f8faa38;border-radius:16px;margin-top:8px;padding:14px 14px 12px}.seer-order-card__title[data-v-17d9e82e]{color:#1d2129;margin:0 0 10px;font-size:18px;font-weight:800}.seer-order-card__panel[data-v-17d9e82e]{background:#fff;border-radius:12px;gap:10px;padding:12px;display:grid}.seer-order-card__channel[data-v-17d9e82e]{color:#1d2129;margin:0;font-size:14px;font-weight:600}.seer-order-card__rows[data-v-17d9e82e]{border:1px solid #e5e6eb;border-radius:10px;margin:0;overflow:hidden}.seer-order-card__row[data-v-17d9e82e]{grid-template-columns:1fr auto;gap:12px;padding:9px 12px;display:grid}.seer-order-card__row+.seer-order-card__row[data-v-17d9e82e]{border-top:1px solid #e5e6eb}.seer-order-card__label[data-v-17d9e82e]{color:#4e5969;font-weight:700}.seer-order-card__value[data-v-17d9e82e]{color:#1d2129;text-align:right;margin:0;font-weight:400}.seer-order-card__value--struck[data-v-17d9e82e]{text-decoration:line-through}.seer-order-card__subsidy[data-v-17d9e82e]{color:#c4161c;border:1px solid #c4161c;border-radius:10px;gap:2px;padding:8px 12px;font-size:13px;display:grid}.seer-order-card__total[data-v-17d9e82e]{justify-content:space-between;align-items:baseline;display:flex}.seer-order-card__total-value[data-v-17d9e82e]{color:#1d2129;font-size:20px;font-weight:800}.seer-order-card__submit[data-v-17d9e82e]{color:#1d2129;cursor:pointer;background:#fc0;border:0;border-radius:10px;padding:11px 0;font-size:16px;font-weight:700}.seer-order-card__submit[data-v-17d9e82e]:disabled{cursor:not-allowed;opacity:.5}.seer-order-card__blocked[data-v-17d9e82e]{color:#c4161c;margin:0;font-size:13px}.seer-chat[data-v-4cdc6832]{color:#18212f;background:radial-gradient(circle at 18% 0,#476aff24,#0000 32%),linear-gradient(#fff 0%,#f7f9fd 100%);border:1px solid #7f8faa47;border-radius:28px;gap:18px;max-width:720px;min-height:640px;padding:0;display:grid;overflow:hidden;box-shadow:0 24px 70px #151f3429}.seer-chat__header[data-v-4cdc6832]{color:#fff;background:linear-gradient(135deg,#141f34f5,#243f76f0),#172033;justify-content:space-between;align-items:flex-start;gap:16px;padding:22px 22px 18px;display:flex}.seer-chat__header h2[data-v-4cdc6832]{letter-spacing:-.03em;margin:0;font-size:22px}.seer-chat__header p[data-v-4cdc6832],.seer-chat__empty[data-v-4cdc6832],.seer-chat__status[data-v-4cdc6832]{color:#5f6f89;margin:4px 0 0;font-size:14px}.seer-chat__header p[data-v-4cdc6832]{color:#ffffffb8;max-width:34ch}.seer-chat__messages[data-v-4cdc6832]{align-content:start;gap:12px;min-height:330px;max-height:470px;padding:18px 18px 4px;display:grid;overflow-y:auto}.seer-chat__empty[data-v-4cdc6832]{color:#66748a;text-align:center;background:#ffffff9e;border:1px dashed #7f8faa61;border-radius:22px;place-items:center;min-height:260px;padding:0 28px;display:grid}.seer-chat__message[data-v-4cdc6832]{background:#ffffffe0;border:1px solid #7f8faa29;border-radius:18px 18px 18px 6px;gap:6px;max-width:min(86%,520px);padding:13px 15px;display:grid;box-shadow:0 12px 28px #151f3414}.seer-chat__message--user[data-v-4cdc6832]{color:#fff;background:linear-gradient(135deg,#285cff,#1d45c9);border-color:#0000;border-radius:18px 18px 6px;justify-self:end;box-shadow:0 14px 30px #1f5eff3d}.seer-chat__role[data-v-4cdc6832]{opacity:.75;font-size:12px;font-weight:700}.seer-chat__body[data-v-4cdc6832]{flex-direction:column;display:flex}.seer-chat__line[data-v-4cdc6832]{white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.seer-chat__line[data-v-4cdc6832]:not(:last-child){margin-bottom:5px}.seer-chat__line[data-v-4cdc6832]:empty{height:7px}.seer-chat__strong[data-v-4cdc6832]{font-weight:700}.seer-chat__message--assistant .seer-chat__line[data-v-4cdc6832]:has(.seer-chat__label-text){color:#1d2129}.seer-chat__label-text[data-v-4cdc6832]{color:#4e5969;font-weight:700}.seer-chat__message--user .seer-chat__label-text[data-v-4cdc6832]{color:inherit}.seer-chat__price[data-v-4cdc6832]{color:#e0331d;font-weight:600}.seer-chat__message--user .seer-chat__price[data-v-4cdc6832]{color:#ffe2dc}.seer-chat__link[data-v-4cdc6832]{color:#1f5eff;text-underline-offset:2px;overflow-wrap:anywhere;font-weight:600;text-decoration:underline}.seer-chat__link[data-v-4cdc6832]:hover{color:#173fb3}.seer-chat__message--user .seer-chat__link[data-v-4cdc6832]{color:#fff}.seer-chat__image-button[data-v-4cdc6832]{cursor:zoom-in;background:0 0;border:0;padding:0;display:block}.seer-chat__image-button[data-v-4cdc6832]:not(:disabled):hover{transform:none}.seer-chat__image[data-v-4cdc6832]{border:1px solid #7f8faa38;border-radius:12px;max-width:100%;margin:6px 0;transition:filter .16s;display:block}.seer-chat__image-button:hover .seer-chat__image[data-v-4cdc6832]{filter:brightness(.96)}.seer-chat__lightbox[data-v-4cdc6832]{z-index:1000;cursor:zoom-out;background:#0a0f1ad1;place-items:center;padding:32px;animation:.14s seer-chat__fade-in-4cdc6832;display:grid;position:fixed;inset:0}.seer-chat__lightbox-image[data-v-4cdc6832]{object-fit:contain;border-radius:12px;max-width:min(92vw,1200px);max-height:90vh;box-shadow:0 30px 80px #00000080}.seer-chat__lightbox-close[data-v-4cdc6832]{color:#fff;background:#ffffff24;border-radius:50%;place-items:center;width:40px;height:40px;font-size:26px;line-height:1;display:grid;position:fixed;top:18px;right:22px}.seer-chat__lightbox-close[data-v-4cdc6832]:not(:disabled):hover{background:#ffffff3d}@keyframes seer-chat__fade-in-4cdc6832{0%{opacity:0}to{opacity:1}}.seer-chat__error[data-v-4cdc6832],.seer-chat__handoff[data-v-4cdc6832]{border-radius:14px;margin:0 18px;padding:10px 12px}.seer-chat__error[data-v-4cdc6832]{color:#8a1f11;background:#fff0ed}.seer-chat__handoff[data-v-4cdc6832]{color:#704600;background:#fff7db}.seer-chat__form[data-v-4cdc6832]{background:#fff;border:1px solid #7f8faa42;border-radius:22px;gap:11px;margin:0 18px 18px;padding:14px;display:grid;box-shadow:0 18px 38px #151f3417}.seer-chat__form--dragging[data-v-4cdc6832]{background:#f3f6ff;border:1px dashed #285cff}.seer-chat__label[data-v-4cdc6832]{font-size:13px;font-weight:700}.seer-chat textarea[data-v-4cdc6832]{box-sizing:border-box;width:100%;min-height:92px;color:inherit;resize:vertical;background:#f8fafd;border:1px solid #0000;border-radius:16px;outline:none;padding:14px;line-height:1.55;transition:background .16s,border-color .16s,box-shadow .16s}.seer-chat button[data-v-4cdc6832]{color:inherit;cursor:pointer;border:0;font-weight:700;transition:transform .16s,box-shadow .16s,opacity .16s}.seer-chat button[data-v-4cdc6832]:not(:disabled):hover{transform:translateY(-1px)}.seer-chat button[data-v-4cdc6832]:disabled{cursor:not-allowed;opacity:.5}.seer-chat button[data-v-4cdc6832]:focus-visible,.seer-chat textarea[data-v-4cdc6832]:focus-visible{border-color:#1f5eff6b;box-shadow:0 0 0 4px #1f5eff21}.seer-chat__clear-button[data-v-4cdc6832]{color:#ffffffc7;background:0 0;border-radius:12px;flex:none;padding:8px 11px;font-size:12px;border:1px solid #ffffff2e!important}.seer-chat__clear-button[data-v-4cdc6832]:not(:disabled):hover{color:#fff;box-shadow:none;background:#ffffff1a}.seer-chat__stop-button[data-v-4cdc6832]{color:#6c3b12;background:#fff1df;border-radius:12px;padding:8px 11px;font-size:12px}.seer-chat__mic-button[data-v-4cdc6832],.seer-chat__attach-button[data-v-4cdc6832]{color:#285cff;background:#edf2ff;border-radius:50%;flex:none;place-items:center;width:40px;height:40px;padding:0;display:grid}.seer-chat__mic-button[data-v-4cdc6832]:not(:disabled):hover,.seer-chat__attach-button[data-v-4cdc6832]:not(:disabled):hover{background:#dfe8ff}.seer-chat__file-input[data-v-4cdc6832]{display:none}.seer-chat__attachments[data-v-4cdc6832]{flex-wrap:wrap;gap:6px;margin:0 0 8px;padding:0;list-style:none;display:flex}.seer-chat__attachment[data-v-4cdc6832]{color:#1f2a44;background:#edf2ff;border-radius:999px;align-items:center;gap:4px;max-width:100%;padding:4px 6px 4px 10px;font-size:13px;display:inline-flex}.seer-chat__attachment-name[data-v-4cdc6832]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.seer-chat__attachment-remove[data-v-4cdc6832]{color:#4b5878;background:0 0;border-radius:50%;width:20px;height:20px;padding:0;line-height:1}.seer-chat__attachment-remove[data-v-4cdc6832]:hover{background:#dfe8ff}.seer-chat__mic-button--recording[data-v-4cdc6832]{color:#fff;background:#d9342b;animation:1.4s ease-in-out infinite seer-chat__recording-pulse-4cdc6832;box-shadow:0 0 0 5px #d9342b24}.seer-chat__mic-button--recording[data-v-4cdc6832]:not(:disabled):hover{background:#bd271f}.seer-chat__stop-icon[data-v-4cdc6832]{background:currentColor;border-radius:3px;width:12px;height:12px}@keyframes seer-chat__recording-pulse-4cdc6832{50%{box-shadow:0 0 0 9px #d9342b14}}.seer-chat__send-button[data-v-4cdc6832]{color:#fff;background:linear-gradient(135deg,#1f5eff,#173fb3);border-radius:14px;justify-content:center;align-items:center;gap:8px;min-width:86px;padding:10px 14px;display:inline-flex;box-shadow:0 12px 24px #1f5eff38}.seer-chat__send-button[data-v-4cdc6832]:not(:disabled):hover{box-shadow:0 14px 28px #1f5eff47}.seer-chat__hint[data-v-4cdc6832]{color:#7a879a;margin-right:auto;font-size:12px}.seer-chat__composer-footer[data-v-4cdc6832]{justify-content:flex-end;align-items:center;gap:8px;display:flex}
|
|
2
2
|
/*$vite$:1*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { createSeerClient } from './client';
|
|
2
|
-
export { linkAnchorLabel, toContentLines, toContentSegments, type ContentOptions, type ContentSegment, } from './content';
|
|
2
|
+
export { linkAnchorLabel, toContentLines, toContentSegments, withoutCardText, type ContentOptions, type ContentSegment, } from './content';
|
|
3
3
|
export { SeerChatPlugin } from './plugin';
|
|
4
4
|
export { useSeerChat } from './useSeerChat';
|
|
5
5
|
export { default as SeerChat } from './components/SeerChat.vue';
|
|
6
|
-
export
|
|
6
|
+
export { default as SeerOrderCard } from './components/SeerOrderCard.vue';
|
|
7
|
+
export type { SeerChatCallbacks, SeerChatMessage, SeerChatRequest, SeerChatResult, SeerChatRole, SeerClient, SeerClientOptions, SeerOrderCard as SeerOrderCardData, SeerOrderCardItem, SeerTranscriptionCallbacks, SeerTranscriptionResult, SeerUploadedFile, } from './client';
|
|
7
8
|
export type { SeerChatPluginOptions } from './plugin';
|
|
8
9
|
export type { UseSeerChatOptions } from './useSeerChat';
|
package/dist/index.js
CHANGED
|
@@ -1,28 +1,37 @@
|
|
|
1
|
-
import { Fragment as e, computed as t,
|
|
1
|
+
import { Fragment as e, computed as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, defineComponent as o, hasInjectionContext as s, inject as c, normalizeClass as l, onBeforeUnmount as u, openBlock as d, ref as f, renderList as p, toDisplayString as m, unref as h, vModelText as g, withDirectives as _, withKeys as v, withModifiers as y } from "vue";
|
|
2
2
|
// src/client.ts
|
|
3
|
-
function
|
|
4
|
-
let t = e.fetcher ?? fetch, n = e.model ?? "seer", r =
|
|
3
|
+
function b(e) {
|
|
4
|
+
let t = e.fetcher ?? fetch, n = e.model ?? "seer", r = S(e.endpoint, e.transcriptionEndpoint, "/v1/browser/audio/transcriptions"), i = S(e.endpoint, e.uploadEndpoint, "/v1/browser/files"), a = e.now ?? (() => Math.floor(Date.now() / 1e3)), o, s = 0, c;
|
|
5
5
|
return {
|
|
6
6
|
transcriptionEnabled: !!r,
|
|
7
7
|
uploadEnabled: !!i,
|
|
8
8
|
async chat(r, i = {}) {
|
|
9
9
|
let a = r.stream ?? !1, o = await l(), s = { "Content-Type": "application/json" };
|
|
10
10
|
o && (s.Authorization = `Bearer ${o}`);
|
|
11
|
-
let c =
|
|
11
|
+
let c = x(e.sellerToken);
|
|
12
|
+
c && (s["X-DFH-Seller-Token"] = c);
|
|
13
|
+
let u = await t(e.endpoint, {
|
|
12
14
|
method: "POST",
|
|
13
15
|
headers: s,
|
|
14
16
|
signal: i.signal,
|
|
15
17
|
body: JSON.stringify({
|
|
16
18
|
model: r.model ?? n,
|
|
17
|
-
messages: r.messages,
|
|
19
|
+
messages: r.messages.map(({ role: e, content: t, name: n }) => n ? {
|
|
20
|
+
role: e,
|
|
21
|
+
content: t,
|
|
22
|
+
name: n
|
|
23
|
+
} : {
|
|
24
|
+
role: e,
|
|
25
|
+
content: t
|
|
26
|
+
}),
|
|
18
27
|
stream: a,
|
|
19
28
|
conversation_id: r.conversationId,
|
|
20
29
|
metadata: r.metadata,
|
|
21
30
|
...r.attachments?.length ? { attachments: r.attachments } : {}
|
|
22
31
|
})
|
|
23
32
|
});
|
|
24
|
-
if (!
|
|
25
|
-
return a ?
|
|
33
|
+
if (!u.ok) throw Error(await E(u));
|
|
34
|
+
return a ? w(u, i.onDelta) : C(await u.json());
|
|
26
35
|
},
|
|
27
36
|
async transcribe(e, n, i = {}) {
|
|
28
37
|
if (!r) throw Error("Seer audio transcription endpoint is not configured");
|
|
@@ -36,7 +45,7 @@ function y(e) {
|
|
|
36
45
|
signal: i.signal,
|
|
37
46
|
body: s
|
|
38
47
|
});
|
|
39
|
-
if (!c.ok) throw Error(await
|
|
48
|
+
if (!c.ok) throw Error(await E(c));
|
|
40
49
|
let u = await c.json(), d = typeof u.text == "string" ? u.text.trim() : "";
|
|
41
50
|
if (!d) throw Error("Seer audio transcription returned empty text");
|
|
42
51
|
return { text: d };
|
|
@@ -53,7 +62,7 @@ function y(e) {
|
|
|
53
62
|
signal: r.signal,
|
|
54
63
|
body: s
|
|
55
64
|
});
|
|
56
|
-
if (!c.ok) throw Error(await
|
|
65
|
+
if (!c.ok) throw Error(await E(c));
|
|
57
66
|
let u = await c.json();
|
|
58
67
|
if (!u.file_id) throw Error("Seer file upload returned no file_id");
|
|
59
68
|
return {
|
|
@@ -67,13 +76,13 @@ function y(e) {
|
|
|
67
76
|
};
|
|
68
77
|
async function l() {
|
|
69
78
|
if (!e.sessionEndpoint) return;
|
|
70
|
-
let n = a(), r =
|
|
79
|
+
let n = a(), r = x(e.orgOwner);
|
|
71
80
|
if (o && c === r && s - 30 > n) return o;
|
|
72
81
|
let i = await t(e.sessionEndpoint, {
|
|
73
82
|
method: "GET",
|
|
74
83
|
headers: await u(r)
|
|
75
84
|
});
|
|
76
|
-
if (!i.ok) throw Error(await
|
|
85
|
+
if (!i.ok) throw Error(await E(i));
|
|
77
86
|
let l = await i.json();
|
|
78
87
|
return o = l.token, s = l.expires_at, c = r, o;
|
|
79
88
|
}
|
|
@@ -82,57 +91,59 @@ function y(e) {
|
|
|
82
91
|
return e.challengeTokenProvider && (n["X-Seer-Challenge-Token"] = await e.challengeTokenProvider()), t && (n["X-Seer-Org-Owner"] = t), n;
|
|
83
92
|
}
|
|
84
93
|
}
|
|
85
|
-
function
|
|
94
|
+
function x(e) {
|
|
86
95
|
return (typeof e == "function" ? e() : e)?.trim() || void 0;
|
|
87
96
|
}
|
|
88
|
-
function
|
|
97
|
+
function S(e, t, n) {
|
|
89
98
|
if (t !== void 0) return t || void 0;
|
|
90
99
|
if (e.endsWith("/v1/browser/chat/completions")) return `${e.slice(0, -28)}${n}`;
|
|
91
100
|
}
|
|
92
|
-
function
|
|
101
|
+
function C(e) {
|
|
93
102
|
let t = e.choices?.[0];
|
|
94
103
|
return {
|
|
95
104
|
content: t?.message?.content ?? t?.delta?.content ?? "",
|
|
96
105
|
conversationId: e.conversation_id,
|
|
97
106
|
citations: e.citations ?? [],
|
|
98
107
|
handoffRequested: e.handoff_requested ?? !1,
|
|
99
|
-
finishReason: t?.finish_reason
|
|
108
|
+
finishReason: t?.finish_reason,
|
|
109
|
+
...e.order_card ? { orderCard: e.order_card } : {}
|
|
100
110
|
};
|
|
101
111
|
}
|
|
102
|
-
async function
|
|
103
|
-
if (!e.body) return
|
|
104
|
-
let n = e.body.getReader(), r = new TextDecoder(), i = "", a = "", o, s = [], c = !1, l, u = !1;
|
|
112
|
+
async function w(e, t) {
|
|
113
|
+
if (!e.body) return C({});
|
|
114
|
+
let n = e.body.getReader(), r = new TextDecoder(), i = "", a = "", o, s = [], c = !1, l, u, d = !1;
|
|
105
115
|
for (;;) {
|
|
106
|
-
let { done: e, value:
|
|
116
|
+
let { done: e, value: f } = await n.read();
|
|
107
117
|
if (e) break;
|
|
108
|
-
i += r.decode(
|
|
109
|
-
let
|
|
110
|
-
i =
|
|
111
|
-
for (let e of
|
|
112
|
-
let n =
|
|
118
|
+
i += r.decode(f, { stream: !0 });
|
|
119
|
+
let p = i.split("\n\n");
|
|
120
|
+
i = p.pop() ?? "";
|
|
121
|
+
for (let e of p) {
|
|
122
|
+
let n = T(e);
|
|
113
123
|
if (!n) continue;
|
|
114
124
|
if (n === "[DONE]") {
|
|
115
|
-
|
|
125
|
+
d = !0;
|
|
116
126
|
continue;
|
|
117
127
|
}
|
|
118
|
-
let r = JSON.parse(n), i = r.choices?.[0],
|
|
119
|
-
|
|
128
|
+
let r = JSON.parse(n), i = r.choices?.[0], f = i?.delta?.content ?? i?.message?.content ?? "";
|
|
129
|
+
f && (a += f, t?.(f)), o = r.conversation_id ?? o, s = r.citations ?? s, c = r.handoff_requested ?? c, l = i?.finish_reason ?? l, u = r.order_card ?? u;
|
|
120
130
|
}
|
|
121
131
|
}
|
|
122
|
-
if (!
|
|
132
|
+
if (!d) throw Error("seer chat stream ended before [DONE]");
|
|
123
133
|
return {
|
|
124
134
|
content: a,
|
|
125
135
|
conversationId: o,
|
|
126
136
|
citations: s,
|
|
127
137
|
handoffRequested: c,
|
|
128
|
-
finishReason: l
|
|
138
|
+
finishReason: l,
|
|
139
|
+
...u ? { orderCard: u } : {}
|
|
129
140
|
};
|
|
130
141
|
}
|
|
131
|
-
function
|
|
142
|
+
function T(e) {
|
|
132
143
|
let t = e.split("\n").map((e) => e.trim()).filter((e) => e.startsWith("data:")).map((e) => e.slice(5).trim());
|
|
133
144
|
return t.length === 0 ? null : t.join("\n");
|
|
134
145
|
}
|
|
135
|
-
async function
|
|
146
|
+
async function E(e) {
|
|
136
147
|
let t = e.statusText || "unknown error";
|
|
137
148
|
try {
|
|
138
149
|
let n = await e.json();
|
|
@@ -144,12 +155,12 @@ async function T(e) {
|
|
|
144
155
|
return `seer chat request failed with status ${e.status}: ${t}`;
|
|
145
156
|
}
|
|
146
157
|
// src/content.ts
|
|
147
|
-
var
|
|
148
|
-
function
|
|
158
|
+
var D = /https?:\/\/[^\s)\u3000-\u303f\u4e00-\u9fff\uff00-\uffef]+/g, O = /\.(png|jpe?g|gif|webp|bmp|svg)$/i, k = "链接生成中…", A = "图片加载中…", j = /* @__PURE__ */ RegExp("(单价\\s*\\d[\\d.]*\\s*[A-Za-z]+\\/(?:kg|方))|(按当前信息为您筛选出[^\\n:]*推荐方案[^\\n:]*:)|(方案PK|时效最快|价格最低)", "g");
|
|
159
|
+
function M(e) {
|
|
149
160
|
let t = [];
|
|
150
|
-
|
|
161
|
+
j.lastIndex = 0;
|
|
151
162
|
let n = 0, r;
|
|
152
|
-
for (; (r =
|
|
163
|
+
for (; (r = j.exec(e)) !== null;) {
|
|
153
164
|
r.index > n && t.push({
|
|
154
165
|
kind: "text",
|
|
155
166
|
value: e.slice(n, r.index)
|
|
@@ -168,74 +179,100 @@ function j(e) {
|
|
|
168
179
|
value: e.slice(n)
|
|
169
180
|
}), t;
|
|
170
181
|
}
|
|
171
|
-
var
|
|
172
|
-
function
|
|
182
|
+
var N = /标签|箱唛|唛头|入库单|交接单|入仓单|面单|下载/;
|
|
183
|
+
function P(e, t) {
|
|
173
184
|
if (/方案|截图|报价图|效果图|示意图|图片/.test(t)) return !0;
|
|
174
|
-
if (
|
|
185
|
+
if (N.test(t)) return !1;
|
|
175
186
|
let n = e.split(/[?#]/)[0];
|
|
176
|
-
return
|
|
187
|
+
return O.test(n);
|
|
177
188
|
}
|
|
178
|
-
function
|
|
189
|
+
function F(e) {
|
|
179
190
|
return /方案|报价|截图|PK/.test(e) ? "方案PK" : "图片";
|
|
180
191
|
}
|
|
181
|
-
function
|
|
192
|
+
function I(e) {
|
|
182
193
|
return /标签|箱唛/.test(e) ? "点击下载箱唛" : /入库单|交接单/.test(e) ? "点击下载入库单" : /面单/.test(e) ? "点击下载面单" : /截图|方案/.test(e) ? "点击查看方案PK" : /下载链接|labelUrl|下载/.test(e) ? "点击下载" : /链接/.test(e) ? "点击查看" : null;
|
|
183
194
|
}
|
|
184
|
-
function
|
|
195
|
+
function L(e, t = {}) {
|
|
185
196
|
let n = [];
|
|
186
|
-
|
|
197
|
+
D.lastIndex = 0;
|
|
187
198
|
let r = 0, i;
|
|
188
|
-
for (; (i =
|
|
189
|
-
let a = i[0], o = i.index, s = e.lastIndexOf("\n", o - 1) + 1, c = e.slice(s, o), l =
|
|
199
|
+
for (; (i = D.exec(e)) !== null;) {
|
|
200
|
+
let a = i[0], o = i.index, s = e.lastIndexOf("\n", o - 1) + 1, c = e.slice(s, o), l = P(a, c), u = !t.complete && o + a.length === e.length;
|
|
190
201
|
if (o > r) {
|
|
191
202
|
let t = e.slice(r, o);
|
|
192
|
-
l && (t = t.replace(/链接([::])\s*$/, "$1")), n.push(...
|
|
203
|
+
l && (t = t.replace(/链接([::])\s*$/, "$1")), n.push(...M(t));
|
|
193
204
|
}
|
|
194
205
|
u ? n.push({
|
|
195
206
|
kind: "text",
|
|
196
|
-
value: l ?
|
|
207
|
+
value: l ? A : k
|
|
197
208
|
}) : l ? n.push({
|
|
198
209
|
kind: "image",
|
|
199
210
|
href: a,
|
|
200
|
-
alt:
|
|
211
|
+
alt: F(c)
|
|
201
212
|
}) : n.push({
|
|
202
213
|
kind: "link",
|
|
203
214
|
href: a,
|
|
204
|
-
label:
|
|
215
|
+
label: I(c) ?? a
|
|
205
216
|
}), r = o + a.length;
|
|
206
217
|
}
|
|
207
|
-
return r < e.length && n.push(...
|
|
218
|
+
return r < e.length && n.push(...M(e.slice(r))), n;
|
|
208
219
|
}
|
|
209
|
-
function
|
|
220
|
+
function R(e, t = {}) {
|
|
210
221
|
let n = e.split("\n");
|
|
211
|
-
return n.map((e, r) =>
|
|
222
|
+
return n.map((e, r) => {
|
|
223
|
+
let i = L(e, { complete: t.complete || r < n.length - 1 }), a = B.exec(e);
|
|
224
|
+
return a ? z(i, a[0]) : i;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function z(e, t) {
|
|
228
|
+
let n = t.length, r = [];
|
|
229
|
+
for (let t of e) {
|
|
230
|
+
if (n === 0 || !("value" in t)) {
|
|
231
|
+
r.push(t);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
let e = Math.min(n, t.value.length);
|
|
235
|
+
n -= e, e < t.value.length && r.push({
|
|
236
|
+
...t,
|
|
237
|
+
value: t.value.slice(e)
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return [{
|
|
241
|
+
kind: "label",
|
|
242
|
+
value: t
|
|
243
|
+
}, ...r];
|
|
244
|
+
}
|
|
245
|
+
var B = /^[\u4e00-\u9fffA-Za-z0-9()()/-]{1,14}:(?=\S)/;
|
|
246
|
+
function V(e, t) {
|
|
247
|
+
return t?.panel_text ? e.replace(t.panel_text, "").replace(/\n{3,}/g, "\n\n") : e;
|
|
212
248
|
}
|
|
213
249
|
// src/plugin.ts
|
|
214
|
-
var
|
|
215
|
-
e.provide(
|
|
250
|
+
var H = Symbol("seer-chat-options"), U = { install(e, t) {
|
|
251
|
+
e.provide(H, t);
|
|
216
252
|
} };
|
|
217
253
|
// src/useSeerChat.ts
|
|
218
|
-
function
|
|
219
|
-
let t =
|
|
254
|
+
function ee(e = {}) {
|
|
255
|
+
let t = s() ? c(H, void 0) : void 0, n = Object.fromEntries(Object.entries(e).filter(([, e]) => e !== void 0)), r = {
|
|
220
256
|
...t,
|
|
221
257
|
...n
|
|
222
258
|
};
|
|
223
259
|
if (!r.endpoint) throw Error("Seer chat endpoint is required. Pass it to app.use() or useSeerChat().");
|
|
224
|
-
let i =
|
|
260
|
+
let i = b({
|
|
225
261
|
endpoint: r.endpoint,
|
|
226
262
|
sessionEndpoint: r.sessionEndpoint,
|
|
227
263
|
transcriptionEndpoint: r.transcriptionEndpoint,
|
|
228
264
|
uploadEndpoint: r.uploadEndpoint,
|
|
229
265
|
challengeTokenProvider: r.challengeTokenProvider,
|
|
230
|
-
orgOwner: () =>
|
|
266
|
+
orgOwner: () => x(e.orgOwner) ?? x(t?.orgOwner),
|
|
267
|
+
sellerToken: () => x(e.sellerToken) ?? x(t?.sellerToken),
|
|
231
268
|
model: r.model,
|
|
232
269
|
fetcher: r.fetcher
|
|
233
|
-
}), a =
|
|
234
|
-
async function S(e) {
|
|
270
|
+
}), a = f([]), o = f(!1), l = f(null), u = f(), d = f([]), p = f(!1), m = r.voiceEnabled !== !1 && i.transcriptionEnabled, h = r.uploadEnabled !== !1 && i.uploadEnabled, g = r.maxRecordingSeconds ?? 60, _ = f([]), v = f(!1), y = null;
|
|
271
|
+
async function S(e, t = {}) {
|
|
235
272
|
v.value = !0, l.value = null;
|
|
236
273
|
try {
|
|
237
|
-
let
|
|
238
|
-
_.value = [..._.value,
|
|
274
|
+
let n = await i.upload(e, e.name);
|
|
275
|
+
_.value = t.replace ? [n] : [..._.value, n];
|
|
239
276
|
} catch (e) {
|
|
240
277
|
l.value = e instanceof Error ? e.message : String(e);
|
|
241
278
|
} finally {
|
|
@@ -247,17 +284,17 @@ function B(e = {}) {
|
|
|
247
284
|
}
|
|
248
285
|
async function w(e) {
|
|
249
286
|
let t = e.trim(), n = _.value;
|
|
250
|
-
if (!t && n.length === 0 ||
|
|
251
|
-
let
|
|
287
|
+
if (!t && n.length === 0 || o.value || v.value) return;
|
|
288
|
+
let s = {
|
|
252
289
|
role: "user",
|
|
253
290
|
content: [t, n.map((e) => `[附件:${e.filename}]`).join("\n")].filter(Boolean).join("\n")
|
|
254
291
|
};
|
|
255
|
-
_.value = [], a.value = [...a.value,
|
|
256
|
-
let
|
|
292
|
+
_.value = [], a.value = [...a.value, s], o.value = !0, l.value = null, y = new AbortController();
|
|
293
|
+
let c = {
|
|
257
294
|
role: "assistant",
|
|
258
295
|
content: ""
|
|
259
296
|
};
|
|
260
|
-
r.stream && (a.value = [...a.value,
|
|
297
|
+
r.stream && (a.value = [...a.value, c]);
|
|
261
298
|
try {
|
|
262
299
|
let e = await i.chat({
|
|
263
300
|
messages: a.value.filter((e) => e.content),
|
|
@@ -265,33 +302,34 @@ function B(e = {}) {
|
|
|
265
302
|
conversationId: u.value,
|
|
266
303
|
attachments: n.map((e) => e.fileId)
|
|
267
304
|
}, {
|
|
268
|
-
signal:
|
|
305
|
+
signal: y.signal,
|
|
269
306
|
onDelta(e) {
|
|
270
|
-
|
|
307
|
+
c.content += e, a.value = [...a.value];
|
|
271
308
|
}
|
|
272
309
|
});
|
|
273
|
-
r.stream
|
|
310
|
+
r.stream ? e.orderCard && (c.orderCard = e.orderCard, a.value = [...a.value]) : a.value = [...a.value, {
|
|
274
311
|
role: "assistant",
|
|
275
|
-
content: e.content
|
|
276
|
-
|
|
312
|
+
content: e.content,
|
|
313
|
+
...e.orderCard ? { orderCard: e.orderCard } : {}
|
|
314
|
+
}], u.value = e.conversationId, d.value = e.citations, p.value = e.handoffRequested;
|
|
277
315
|
} catch (e) {
|
|
278
316
|
e.name !== "AbortError" && (l.value = e instanceof Error ? e.message : String(e));
|
|
279
317
|
} finally {
|
|
280
|
-
|
|
318
|
+
o.value = !1, y = null;
|
|
281
319
|
}
|
|
282
320
|
}
|
|
283
321
|
function T() {
|
|
284
|
-
a.value = [], _.value = [], l.value = null, u.value = void 0,
|
|
322
|
+
a.value = [], _.value = [], l.value = null, u.value = void 0, d.value = [], p.value = !1;
|
|
285
323
|
}
|
|
286
324
|
function E() {
|
|
287
|
-
|
|
325
|
+
y?.abort();
|
|
288
326
|
}
|
|
289
327
|
return {
|
|
290
328
|
messages: a,
|
|
291
|
-
loading:
|
|
329
|
+
loading: o,
|
|
292
330
|
error: l,
|
|
293
331
|
conversationId: u,
|
|
294
|
-
citations:
|
|
332
|
+
citations: d,
|
|
295
333
|
handoffRequested: p,
|
|
296
334
|
transcriptionEnabled: m,
|
|
297
335
|
maxRecordingSeconds: g,
|
|
@@ -306,62 +344,107 @@ function B(e = {}) {
|
|
|
306
344
|
abort: E
|
|
307
345
|
};
|
|
308
346
|
}
|
|
309
|
-
// src/components/
|
|
310
|
-
var
|
|
347
|
+
// src/components/SeerOrderCard.vue?vue&type=script&setup=true&lang.ts
|
|
348
|
+
var W = ["aria-label"], G = { class: "seer-order-card__title" }, K = { class: "seer-order-card__panel" }, q = { class: "seer-order-card__channel" }, J = { class: "seer-order-card__rows" }, Y = { class: "seer-order-card__label" }, X = {
|
|
349
|
+
key: 0,
|
|
350
|
+
class: "seer-order-card__row"
|
|
351
|
+
}, Z = { class: "seer-order-card__label" }, Q = { class: "seer-order-card__value" }, $ = {
|
|
352
|
+
key: 0,
|
|
353
|
+
class: "seer-order-card__subsidy"
|
|
354
|
+
}, te = { class: "seer-order-card__total" }, ne = ["title"], re = { class: "seer-order-card__total-value" }, ie = ["disabled"], ae = {
|
|
355
|
+
key: 2,
|
|
356
|
+
class: "seer-order-card__blocked",
|
|
357
|
+
role: "note"
|
|
358
|
+
}, oe = /*@__PURE__*/ o({
|
|
359
|
+
__name: "SeerOrderCard",
|
|
360
|
+
props: {
|
|
361
|
+
card: {},
|
|
362
|
+
disabled: { type: Boolean }
|
|
363
|
+
},
|
|
364
|
+
emits: ["submit"],
|
|
365
|
+
setup(t, { emit: n }) {
|
|
366
|
+
let o = n;
|
|
367
|
+
return (n, s) => (d(), i("section", {
|
|
368
|
+
class: "seer-order-card",
|
|
369
|
+
"aria-label": t.card.title
|
|
370
|
+
}, [a("h3", G, m(t.card.title), 1), a("div", K, [
|
|
371
|
+
a("h4", q, m(t.card.channel_name), 1),
|
|
372
|
+
a("dl", J, [(d(!0), i(e, null, p(t.card.rows, (e) => (d(), i("div", {
|
|
373
|
+
key: e.label,
|
|
374
|
+
class: "seer-order-card__row"
|
|
375
|
+
}, [a("dt", Y, m(e.label), 1), a("dd", { class: l(["seer-order-card__value", { "seer-order-card__value--struck": e.struck }]) }, m(e.value), 3)]))), 128)), t.card.coupon ? (d(), i("div", X, [a("dt", Z, m(t.card.coupon.label), 1), a("dd", Q, m(t.card.coupon.value), 1)])) : r("", !0)]),
|
|
376
|
+
t.card.subsidy ? (d(), i("div", $, [a("strong", null, m(t.card.subsidy.label), 1), a("span", null, m(t.card.subsidy.value) + " = " + m(t.card.subsidy.detail), 1)])) : r("", !0),
|
|
377
|
+
a("div", te, [a("span", {
|
|
378
|
+
class: "seer-order-card__label",
|
|
379
|
+
title: t.card.note
|
|
380
|
+
}, m(t.card.total.label), 9, ne), a("span", re, m(t.card.total.value), 1)]),
|
|
381
|
+
t.card.action ? (d(), i("button", {
|
|
382
|
+
key: 1,
|
|
383
|
+
type: "button",
|
|
384
|
+
class: "seer-order-card__submit",
|
|
385
|
+
disabled: t.disabled,
|
|
386
|
+
onClick: s[0] ||= (e) => o("submit", t.card.action.message)
|
|
387
|
+
}, m(t.card.action.label), 9, ie)) : t.card.blocked_reason ? (d(), i("p", ae, m(t.card.blocked_reason), 1)) : r("", !0)
|
|
388
|
+
])], 8, W));
|
|
389
|
+
}
|
|
390
|
+
}), se = (e, t) => {
|
|
391
|
+
let n = e.__vccOpts || e;
|
|
392
|
+
for (let [e, r] of t) n[e] = r;
|
|
393
|
+
return n;
|
|
394
|
+
}, ce = /*#__PURE__*/ se(oe, [["__scopeId", "data-v-17d9e82e"]]), le = {
|
|
311
395
|
class: "seer-chat",
|
|
312
396
|
"aria-label": "多发货 AI 客服聊天"
|
|
313
|
-
},
|
|
397
|
+
}, ue = { class: "seer-chat__header" }, de = {
|
|
314
398
|
class: "seer-chat__messages",
|
|
315
399
|
"aria-live": "polite"
|
|
316
|
-
},
|
|
400
|
+
}, fe = {
|
|
317
401
|
key: 0,
|
|
318
402
|
class: "seer-chat__empty"
|
|
319
|
-
},
|
|
403
|
+
}, pe = { class: "seer-chat__role" }, me = { class: "seer-chat__body" }, he = ["href"], ge = ["aria-label", "onClick"], _e = ["src", "alt"], ve = {
|
|
320
404
|
key: 2,
|
|
321
405
|
class: "seer-chat__strong"
|
|
322
|
-
},
|
|
406
|
+
}, ye = {
|
|
323
407
|
key: 3,
|
|
324
408
|
class: "seer-chat__price"
|
|
325
|
-
},
|
|
409
|
+
}, be = {
|
|
410
|
+
key: 4,
|
|
411
|
+
class: "seer-chat__label-text"
|
|
412
|
+
}, xe = { key: 5 }, Se = {
|
|
326
413
|
key: 0,
|
|
327
414
|
class: "seer-chat__status"
|
|
328
|
-
},
|
|
415
|
+
}, Ce = {
|
|
329
416
|
key: 1,
|
|
330
417
|
class: "seer-chat__error",
|
|
331
418
|
role: "alert"
|
|
332
|
-
},
|
|
419
|
+
}, we = {
|
|
333
420
|
key: 2,
|
|
334
421
|
class: "seer-chat__handoff"
|
|
335
|
-
},
|
|
422
|
+
}, Te = {
|
|
336
423
|
key: 0,
|
|
337
424
|
class: "seer-chat__attachments",
|
|
338
425
|
"aria-label": "待发送的附件"
|
|
339
|
-
},
|
|
426
|
+
}, Ee = { class: "seer-chat__attachment-name" }, De = ["aria-label", "onClick"], Oe = [
|
|
340
427
|
"placeholder",
|
|
341
428
|
"disabled",
|
|
342
429
|
"onKeydown"
|
|
343
|
-
],
|
|
430
|
+
], ke = { class: "seer-chat__composer-footer" }, Ae = {
|
|
344
431
|
class: "seer-chat__hint",
|
|
345
432
|
"aria-live": "polite"
|
|
346
|
-
},
|
|
433
|
+
}, je = ["disabled"], Me = [
|
|
347
434
|
"disabled",
|
|
348
435
|
"aria-label",
|
|
349
436
|
"title"
|
|
350
|
-
],
|
|
437
|
+
], Ne = {
|
|
351
438
|
key: 0,
|
|
352
439
|
class: "seer-chat__stop-icon",
|
|
353
440
|
"aria-hidden": "true"
|
|
354
|
-
},
|
|
441
|
+
}, Pe = {
|
|
355
442
|
key: 1,
|
|
356
443
|
viewBox: "0 0 24 24",
|
|
357
444
|
width: "20",
|
|
358
445
|
height: "20",
|
|
359
446
|
"aria-hidden": "true"
|
|
360
|
-
},
|
|
361
|
-
let n = e.__vccOpts || e;
|
|
362
|
-
for (let [e, r] of t) n[e] = r;
|
|
363
|
-
return n;
|
|
364
|
-
})(/* @__PURE__ */ a({
|
|
447
|
+
}, Fe = ["disabled"], Ie = ["aria-label"], Le = ["src", "alt"], Re = ".xlsx,.xls,.csv,.png,.jpg,.jpeg,.webp,.pdf", ze = /*#__PURE__*/ se(/* @__PURE__ */ o({
|
|
365
448
|
__name: "SeerChat",
|
|
366
449
|
props: {
|
|
367
450
|
endpoint: {},
|
|
@@ -373,6 +456,7 @@ var ee = {
|
|
|
373
456
|
default: void 0
|
|
374
457
|
},
|
|
375
458
|
orgOwner: {},
|
|
459
|
+
sellerToken: {},
|
|
376
460
|
model: {},
|
|
377
461
|
stream: {
|
|
378
462
|
type: Boolean,
|
|
@@ -387,98 +471,110 @@ var ee = {
|
|
|
387
471
|
},
|
|
388
472
|
maxRecordingSeconds: {}
|
|
389
473
|
},
|
|
390
|
-
setup(
|
|
391
|
-
let o =
|
|
392
|
-
endpoint:
|
|
393
|
-
sessionEndpoint:
|
|
394
|
-
transcriptionEndpoint:
|
|
395
|
-
uploadEndpoint:
|
|
396
|
-
uploadEnabled:
|
|
397
|
-
orgOwner: () =>
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
474
|
+
setup(o) {
|
|
475
|
+
let s = o, c = Re.split(","), b = f(""), x = f(!1), S = f(!1), C = f(null), w = ee({
|
|
476
|
+
endpoint: s.endpoint,
|
|
477
|
+
sessionEndpoint: s.sessionEndpoint,
|
|
478
|
+
transcriptionEndpoint: s.transcriptionEndpoint,
|
|
479
|
+
uploadEndpoint: s.uploadEndpoint,
|
|
480
|
+
uploadEnabled: s.uploadEnabled,
|
|
481
|
+
orgOwner: () => s.orgOwner,
|
|
482
|
+
sellerToken: () => s.sellerToken,
|
|
483
|
+
model: s.model,
|
|
484
|
+
stream: s.stream,
|
|
485
|
+
fetcher: s.fetcher,
|
|
486
|
+
voiceEnabled: s.voiceEnabled,
|
|
487
|
+
maxRecordingSeconds: s.maxRecordingSeconds
|
|
488
|
+
}), T = f(null), E = f(!1), D = f(null), O = t(() => (b.value.trim().length > 0 || w.attachments.value.length > 0) && !w.loading.value && !w.uploading.value && !x.value && !S.value);
|
|
489
|
+
async function k(e) {
|
|
405
490
|
let t = e.target, n = Array.from(t.files ?? []);
|
|
406
491
|
t.value = "";
|
|
407
|
-
for (let e of n) await
|
|
492
|
+
for (let e of n) await w.attach(e);
|
|
408
493
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
e.key === "Escape" && F();
|
|
494
|
+
function A(e) {
|
|
495
|
+
w.uploadEnabled && e.dataTransfer?.types.includes("Files") && (e.preventDefault(), E.value = !0);
|
|
412
496
|
}
|
|
413
|
-
function
|
|
414
|
-
|
|
497
|
+
async function j(e) {
|
|
498
|
+
E.value = !1;
|
|
499
|
+
let t = e.dataTransfer?.files?.[0];
|
|
500
|
+
if (!w.uploadEnabled || !t) return;
|
|
501
|
+
e.preventDefault(), D.value = null;
|
|
502
|
+
let n = t.name.slice(t.name.lastIndexOf(".")).toLowerCase();
|
|
503
|
+
c.includes(n) ? w.loading.value || w.uploading.value || await w.attach(t, { replace: !0 }) : D.value = "不支持这种文件,请拖入 Excel(xlsx / xls / csv)、图片或 PDF。";
|
|
504
|
+
}
|
|
505
|
+
let M = t(() => w.transcriptionEnabled && typeof navigator < "u" && typeof navigator.mediaDevices?.getUserMedia == "function" && typeof MediaRecorder < "u"), N = null, P = null, F = [], I, L = !1, z = f(null);
|
|
506
|
+
function B(e) {
|
|
507
|
+
e.key === "Escape" && U();
|
|
508
|
+
}
|
|
509
|
+
function H(e, t) {
|
|
510
|
+
z.value = {
|
|
415
511
|
src: e,
|
|
416
512
|
alt: t
|
|
417
|
-
}, window.addEventListener("keydown",
|
|
513
|
+
}, window.addEventListener("keydown", B);
|
|
418
514
|
}
|
|
419
|
-
function
|
|
420
|
-
|
|
515
|
+
function U() {
|
|
516
|
+
z.value = null, window.removeEventListener("keydown", B);
|
|
421
517
|
}
|
|
422
|
-
|
|
423
|
-
|
|
518
|
+
u(() => {
|
|
519
|
+
L = !0, window.removeEventListener("keydown", B), Q(), N && N.state !== "inactive" && (N.ondataavailable = null, N.onstop = null, N.onerror = null, N.stop()), $();
|
|
424
520
|
});
|
|
425
|
-
async function
|
|
426
|
-
if (!
|
|
427
|
-
let e =
|
|
428
|
-
|
|
521
|
+
async function W() {
|
|
522
|
+
if (!O.value) return;
|
|
523
|
+
let e = b.value;
|
|
524
|
+
b.value = "", await w.send(e);
|
|
429
525
|
}
|
|
430
|
-
async function
|
|
431
|
-
|
|
526
|
+
async function G() {
|
|
527
|
+
x.value ? q() : await K();
|
|
432
528
|
}
|
|
433
|
-
async function
|
|
434
|
-
if (!(!
|
|
435
|
-
|
|
529
|
+
async function K() {
|
|
530
|
+
if (!(!M.value || S.value || w.loading.value)) {
|
|
531
|
+
C.value = null;
|
|
436
532
|
try {
|
|
437
|
-
if (
|
|
533
|
+
if (P = await navigator.mediaDevices.getUserMedia({
|
|
438
534
|
audio: {
|
|
439
535
|
echoCancellation: !0,
|
|
440
536
|
noiseSuppression: !0
|
|
441
537
|
},
|
|
442
538
|
video: !1
|
|
443
|
-
}),
|
|
539
|
+
}), L) {
|
|
444
540
|
$();
|
|
445
541
|
return;
|
|
446
542
|
}
|
|
447
|
-
let e =
|
|
448
|
-
|
|
543
|
+
let e = Y();
|
|
544
|
+
N = e ? new MediaRecorder(P, {
|
|
449
545
|
mimeType: e,
|
|
450
546
|
audioBitsPerSecond: 64e3
|
|
451
|
-
}) : new MediaRecorder(
|
|
452
|
-
e.data.size > 0 &&
|
|
453
|
-
},
|
|
454
|
-
|
|
455
|
-
},
|
|
456
|
-
|
|
457
|
-
},
|
|
547
|
+
}) : new MediaRecorder(P), F = [], N.ondataavailable = (e) => {
|
|
548
|
+
e.data.size > 0 && F.push(e.data);
|
|
549
|
+
}, N.onstop = () => {
|
|
550
|
+
J(N?.mimeType || e || "audio/webm");
|
|
551
|
+
}, N.onerror = () => {
|
|
552
|
+
C.value = "录音失败,请重试或用文字输入。", x.value = !1, S.value = !1, Q(), $();
|
|
553
|
+
}, N.start(), x.value = !0, I = setTimeout(q, Math.max(1, w.maxRecordingSeconds) * 1e3);
|
|
458
554
|
} catch (e) {
|
|
459
|
-
|
|
555
|
+
C.value = Z(e), $();
|
|
460
556
|
}
|
|
461
557
|
}
|
|
462
558
|
}
|
|
463
|
-
function
|
|
464
|
-
|
|
559
|
+
function q() {
|
|
560
|
+
N && N.state !== "inactive" && (x.value = !1, S.value = !0, Q(), N.stop());
|
|
465
561
|
}
|
|
466
|
-
async function
|
|
562
|
+
async function J(e) {
|
|
467
563
|
Q(), $();
|
|
468
|
-
let t =
|
|
469
|
-
if (
|
|
564
|
+
let t = F;
|
|
565
|
+
if (F = [], N = null, L) return;
|
|
470
566
|
let n = new Blob(t, { type: e });
|
|
471
|
-
if (n.size === 0)
|
|
567
|
+
if (n.size === 0) C.value = "没有录到声音,请重试。", S.value = !1;
|
|
472
568
|
else try {
|
|
473
|
-
let t = await
|
|
474
|
-
|
|
569
|
+
let t = await w.transcribe(n, X(e));
|
|
570
|
+
b.value = b.value.trim() ? `${b.value.trim()} ${t.text}` : t.text;
|
|
475
571
|
} catch {
|
|
476
|
-
|
|
572
|
+
C.value = "语音识别失败,请重试或用文字输入。";
|
|
477
573
|
} finally {
|
|
478
|
-
|
|
574
|
+
S.value = !1;
|
|
479
575
|
}
|
|
480
576
|
}
|
|
481
|
-
function
|
|
577
|
+
function Y() {
|
|
482
578
|
if (typeof MediaRecorder.isTypeSupported == "function") return [
|
|
483
579
|
"audio/webm;codecs=opus",
|
|
484
580
|
"audio/mp4",
|
|
@@ -486,149 +582,161 @@ var ee = {
|
|
|
486
582
|
"audio/webm"
|
|
487
583
|
].find((e) => MediaRecorder.isTypeSupported(e));
|
|
488
584
|
}
|
|
489
|
-
function
|
|
585
|
+
function X(e) {
|
|
490
586
|
return `recording.${{
|
|
491
587
|
"audio/mp4": "m4a",
|
|
492
588
|
"audio/ogg": "ogg",
|
|
493
589
|
"audio/webm": "webm"
|
|
494
590
|
}[e.split(";", 1)[0].toLowerCase()] || "webm"}`;
|
|
495
591
|
}
|
|
496
|
-
function
|
|
592
|
+
function Z(e) {
|
|
497
593
|
return e instanceof DOMException && e.name === "NotAllowedError" ? "请允许浏览器使用麦克风。" : e instanceof DOMException && e.name === "NotFoundError" ? "未检测到可用的麦克风。" : "无法启动麦克风,请重试或用文字输入。";
|
|
498
594
|
}
|
|
499
595
|
function Q() {
|
|
500
|
-
|
|
596
|
+
I !== void 0 && (clearTimeout(I), I = void 0);
|
|
501
597
|
}
|
|
502
598
|
function $() {
|
|
503
|
-
|
|
599
|
+
P?.getTracks().forEach((e) => e.stop()), P = null;
|
|
504
600
|
}
|
|
505
|
-
return (t,
|
|
506
|
-
|
|
601
|
+
return (t, s) => (d(), i("section", le, [
|
|
602
|
+
a("header", ue, [a("div", null, [a("h2", null, m(o.title), 1), s[5] ||= a("p", null, "可咨询渠道报价、时效、下单资料、入仓和售后问题。", -1)]), a("button", {
|
|
507
603
|
type: "button",
|
|
508
604
|
class: "seer-chat__clear-button",
|
|
509
|
-
onClick:
|
|
605
|
+
onClick: s[0] ||= (e) => h(w).reset()
|
|
510
606
|
}, " 清空对话 ")]),
|
|
511
|
-
|
|
512
|
-
key: `${t.role}-${
|
|
513
|
-
class:
|
|
514
|
-
}, [
|
|
607
|
+
a("div", de, [h(w).messages.value.length === 0 ? (d(), i("p", fe, " 直接输入问题即可,复杂查单或赔付问题会提示转人工。 ")) : r("", !0), (d(!0), i(e, null, p(h(w).messages.value, (t, o) => (d(), i("article", {
|
|
608
|
+
key: `${t.role}-${o}`,
|
|
609
|
+
class: l(["seer-chat__message", `seer-chat__message--${t.role}`])
|
|
610
|
+
}, [a("span", pe, m(t.role === "user" ? "你" : "AI 客服"), 1), a("div", me, [(d(!0), i(e, null, p(h(R)(h(V)(t.content, t.orderCard), { complete: !(h(w).loading.value && o === h(w).messages.value.length - 1) }), (t, n) => (d(), i("p", {
|
|
515
611
|
key: n,
|
|
516
612
|
class: "seer-chat__line"
|
|
517
|
-
}, [(
|
|
613
|
+
}, [(d(!0), i(e, null, p(t, (t, n) => (d(), i(e, { key: n }, [t.kind === "link" ? (d(), i("a", {
|
|
518
614
|
key: 0,
|
|
519
615
|
class: "seer-chat__link",
|
|
520
616
|
href: t.href,
|
|
521
617
|
target: "_blank",
|
|
522
618
|
rel: "noopener noreferrer"
|
|
523
|
-
},
|
|
619
|
+
}, m(t.label), 9, he)) : t.kind === "image" ? (d(), i("button", {
|
|
524
620
|
key: 1,
|
|
525
621
|
type: "button",
|
|
526
622
|
class: "seer-chat__image-button",
|
|
527
623
|
"aria-label": `放大查看${t.alt}`,
|
|
528
|
-
onClick: (e) =>
|
|
529
|
-
}, [
|
|
624
|
+
onClick: (e) => H(t.href, t.alt)
|
|
625
|
+
}, [a("img", {
|
|
530
626
|
class: "seer-chat__image",
|
|
531
627
|
src: t.href,
|
|
532
628
|
alt: t.alt,
|
|
533
629
|
loading: "lazy"
|
|
534
|
-
}, null, 8,
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
630
|
+
}, null, 8, _e)], 8, ge)) : t.kind === "strong" ? (d(), i("strong", ve, m(t.value), 1)) : t.kind === "price" ? (d(), i("span", ye, m(t.value), 1)) : t.kind === "label" ? (d(), i("span", be, m(t.value), 1)) : (d(), i("span", xe, m(t.value), 1))], 64))), 128))]))), 128)), t.orderCard ? (d(), n(ce, {
|
|
631
|
+
key: 0,
|
|
632
|
+
card: t.orderCard,
|
|
633
|
+
disabled: h(w).loading.value || o !== h(w).messages.value.length - 1,
|
|
634
|
+
onSubmit: h(w).send
|
|
635
|
+
}, null, 8, [
|
|
636
|
+
"card",
|
|
637
|
+
"disabled",
|
|
638
|
+
"onSubmit"
|
|
639
|
+
])) : r("", !0)])], 2))), 128))]),
|
|
640
|
+
h(w).loading.value ? (d(), i("p", Se, "正在回复...")) : r("", !0),
|
|
641
|
+
h(w).error.value || C.value || D.value ? (d(), i("p", Ce, m(C.value || D.value || h(w).error.value), 1)) : r("", !0),
|
|
642
|
+
h(w).handoffRequested.value ? (d(), i("p", we, " 建议转人工:请留下联系方式或等待客服接入。 ")) : r("", !0),
|
|
643
|
+
a("form", {
|
|
644
|
+
class: l(["seer-chat__form", { "seer-chat__form--dragging": E.value }]),
|
|
645
|
+
onSubmit: y(W, ["prevent"]),
|
|
646
|
+
onDragover: A,
|
|
647
|
+
onDragleave: s[4] ||= (e) => E.value = !1,
|
|
648
|
+
onDrop: j
|
|
541
649
|
}, [
|
|
542
|
-
|
|
650
|
+
s[9] ||= a("label", {
|
|
543
651
|
class: "seer-chat__label",
|
|
544
652
|
for: "seer-chat-input"
|
|
545
653
|
}, "问题", -1),
|
|
546
|
-
|
|
654
|
+
h(w).attachments.value.length > 0 ? (d(), i("ul", Te, [(d(!0), i(e, null, p(h(w).attachments.value, (e) => (d(), i("li", {
|
|
547
655
|
key: e.fileId,
|
|
548
656
|
class: "seer-chat__attachment"
|
|
549
|
-
}, [
|
|
657
|
+
}, [a("span", Ee, m(e.filename), 1), a("button", {
|
|
550
658
|
type: "button",
|
|
551
659
|
class: "seer-chat__attachment-remove",
|
|
552
660
|
"aria-label": `移除附件${e.filename}`,
|
|
553
|
-
onClick: (t) =>
|
|
554
|
-
}, " × ", 8,
|
|
555
|
-
|
|
661
|
+
onClick: (t) => h(w).removeAttachment(e.fileId)
|
|
662
|
+
}, " × ", 8, De)]))), 128))])) : r("", !0),
|
|
663
|
+
_(a("textarea", {
|
|
556
664
|
id: "seer-chat-input",
|
|
557
|
-
"onUpdate:modelValue":
|
|
558
|
-
placeholder:
|
|
559
|
-
disabled:
|
|
665
|
+
"onUpdate:modelValue": s[1] ||= (e) => b.value = e,
|
|
666
|
+
placeholder: o.placeholder,
|
|
667
|
+
disabled: h(w).loading.value || S.value,
|
|
560
668
|
rows: "3",
|
|
561
|
-
onKeydown:
|
|
562
|
-
}, null, 40,
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
669
|
+
onKeydown: v(y(W, ["exact", "prevent"]), ["enter"])
|
|
670
|
+
}, null, 40, Oe), [[g, b.value]]),
|
|
671
|
+
a("div", ke, [
|
|
672
|
+
a("span", Ae, m(x.value ? `正在录音,最长 ${h(w).maxRecordingSeconds} 秒` : S.value ? "正在识别语音..." : h(w).uploading.value ? "正在上传附件..." : E.value ? "松开即可上传(一次一个文件,会替换当前附件)" : "Enter 发送 · Shift+Enter 换行"), 1),
|
|
673
|
+
h(w).uploadEnabled ? (d(), i(e, { key: 0 }, [a("input", {
|
|
566
674
|
ref_key: "fileInput",
|
|
567
|
-
ref:
|
|
675
|
+
ref: T,
|
|
568
676
|
class: "seer-chat__file-input",
|
|
569
677
|
type: "file",
|
|
570
678
|
multiple: "",
|
|
571
|
-
accept:
|
|
572
|
-
onChange:
|
|
573
|
-
}, null, 544),
|
|
679
|
+
accept: Re,
|
|
680
|
+
onChange: k
|
|
681
|
+
}, null, 544), a("button", {
|
|
574
682
|
type: "button",
|
|
575
683
|
class: "seer-chat__attach-button",
|
|
576
|
-
disabled:
|
|
684
|
+
disabled: h(w).loading.value || h(w).uploading.value,
|
|
577
685
|
"aria-label": "上传附件",
|
|
578
686
|
title: "上传下单模板、实物图片等",
|
|
579
|
-
onClick:
|
|
580
|
-
}, [...
|
|
687
|
+
onClick: s[2] ||= (e) => T.value?.click()
|
|
688
|
+
}, [...s[6] ||= [a("svg", {
|
|
581
689
|
viewBox: "0 0 24 24",
|
|
582
690
|
width: "20",
|
|
583
691
|
height: "20",
|
|
584
692
|
"aria-hidden": "true"
|
|
585
|
-
}, [
|
|
693
|
+
}, [a("path", {
|
|
586
694
|
fill: "currentColor",
|
|
587
695
|
d: "M16.5 6.5v10a4.5 4.5 0 0 1-9 0V5a3 3 0 0 1 6 0v10.5a1.5 1.5 0 0 1-3 0V6.5H9v9a3 3 0 0 0 6 0V5a4.5 4.5 0 0 0-9 0v11.5a6 6 0 0 0 12 0v-10h-1.5Z"
|
|
588
|
-
})], -1)]], 8,
|
|
589
|
-
|
|
696
|
+
})], -1)]], 8, je)], 64)) : r("", !0),
|
|
697
|
+
M.value ? (d(), i("button", {
|
|
590
698
|
key: 1,
|
|
591
699
|
type: "button",
|
|
592
|
-
class:
|
|
593
|
-
disabled:
|
|
594
|
-
"aria-label":
|
|
595
|
-
title:
|
|
596
|
-
onClick:
|
|
597
|
-
}, [
|
|
700
|
+
class: l(["seer-chat__mic-button", { "seer-chat__mic-button--recording": x.value }]),
|
|
701
|
+
disabled: S.value || h(w).loading.value && !x.value,
|
|
702
|
+
"aria-label": x.value ? "停止录音" : "开始语音输入",
|
|
703
|
+
title: x.value ? "停止录音" : "语音输入",
|
|
704
|
+
onClick: G
|
|
705
|
+
}, [x.value ? (d(), i("span", Ne)) : (d(), i("svg", Pe, [...s[7] ||= [a("path", {
|
|
598
706
|
fill: "currentColor",
|
|
599
707
|
d: "M12 14a3 3 0 0 0 3-3V5a3 3 0 1 0-6 0v6a3 3 0 0 0 3 3Zm5-3a1 1 0 1 1 2 0 7 7 0 0 1-6 6.93V20h3a1 1 0 1 1 0 2H8a1 1 0 1 1 0-2h3v-2.07A7 7 0 0 1 5 11a1 1 0 1 1 2 0 5 5 0 0 0 10 0Z"
|
|
600
|
-
}, null, -1)]]))], 10,
|
|
601
|
-
|
|
708
|
+
}, null, -1)]]))], 10, Me)) : r("", !0),
|
|
709
|
+
h(w).loading.value ? (d(), i("button", {
|
|
602
710
|
key: 2,
|
|
603
711
|
type: "button",
|
|
604
712
|
class: "seer-chat__stop-button",
|
|
605
|
-
onClick:
|
|
606
|
-
}, " 停止 ")) :
|
|
607
|
-
|
|
713
|
+
onClick: s[3] ||= (e) => h(w).abort()
|
|
714
|
+
}, " 停止 ")) : r("", !0),
|
|
715
|
+
a("button", {
|
|
608
716
|
class: "seer-chat__send-button",
|
|
609
717
|
type: "submit",
|
|
610
|
-
disabled: !
|
|
611
|
-
}, [...
|
|
718
|
+
disabled: !O.value
|
|
719
|
+
}, [...s[8] ||= [a("span", null, "发送", -1), a("span", { "aria-hidden": "true" }, "↵", -1)]], 8, Fe)
|
|
612
720
|
])
|
|
613
|
-
],
|
|
614
|
-
|
|
721
|
+
], 34),
|
|
722
|
+
z.value ? (d(), i("div", {
|
|
615
723
|
key: 3,
|
|
616
724
|
class: "seer-chat__lightbox",
|
|
617
725
|
role: "dialog",
|
|
618
726
|
"aria-modal": "true",
|
|
619
|
-
"aria-label":
|
|
620
|
-
onClick:
|
|
621
|
-
}, [
|
|
727
|
+
"aria-label": z.value.alt,
|
|
728
|
+
onClick: U
|
|
729
|
+
}, [a("button", {
|
|
622
730
|
type: "button",
|
|
623
731
|
class: "seer-chat__lightbox-close",
|
|
624
732
|
"aria-label": "关闭",
|
|
625
|
-
onClick:
|
|
626
|
-
}, " × "),
|
|
733
|
+
onClick: U
|
|
734
|
+
}, " × "), a("img", {
|
|
627
735
|
class: "seer-chat__lightbox-image",
|
|
628
|
-
src:
|
|
629
|
-
alt:
|
|
630
|
-
}, null, 8,
|
|
736
|
+
src: z.value.src,
|
|
737
|
+
alt: z.value.alt
|
|
738
|
+
}, null, 8, Le)], 8, Ie)) : r("", !0)
|
|
631
739
|
]));
|
|
632
740
|
}
|
|
633
|
-
}), [["__scopeId", "data-v-
|
|
634
|
-
export {
|
|
741
|
+
}), [["__scopeId", "data-v-4cdc6832"]]);
|
|
742
|
+
export { ze as SeerChat, U as SeerChatPlugin, ce as SeerOrderCard, b as createSeerClient, I as linkAnchorLabel, R as toContentLines, L as toContentSegments, ee as useSeerChat, V as withoutCardText };
|
package/dist/useSeerChat.d.ts
CHANGED
|
@@ -8,10 +8,82 @@ export declare function useSeerChat(localOptions?: UseSeerChatOptions): {
|
|
|
8
8
|
role: import("./client").SeerChatRole;
|
|
9
9
|
content: string;
|
|
10
10
|
name?: string | undefined;
|
|
11
|
+
orderCard?: {
|
|
12
|
+
type: "order_estimate";
|
|
13
|
+
title: string;
|
|
14
|
+
channel_name: string;
|
|
15
|
+
rows: {
|
|
16
|
+
label: string;
|
|
17
|
+
value: string;
|
|
18
|
+
struck?: boolean | undefined;
|
|
19
|
+
detail?: string | undefined;
|
|
20
|
+
}[];
|
|
21
|
+
subsidy: {
|
|
22
|
+
label: string;
|
|
23
|
+
value: string;
|
|
24
|
+
struck?: boolean | undefined;
|
|
25
|
+
detail?: string | undefined;
|
|
26
|
+
} | null;
|
|
27
|
+
coupon: {
|
|
28
|
+
label: string;
|
|
29
|
+
value: string;
|
|
30
|
+
struck?: boolean | undefined;
|
|
31
|
+
detail?: string | undefined;
|
|
32
|
+
} | null;
|
|
33
|
+
total: {
|
|
34
|
+
label: string;
|
|
35
|
+
value: string;
|
|
36
|
+
struck?: boolean | undefined;
|
|
37
|
+
detail?: string | undefined;
|
|
38
|
+
};
|
|
39
|
+
note: string;
|
|
40
|
+
panel_text: string;
|
|
41
|
+
action: {
|
|
42
|
+
label: string;
|
|
43
|
+
message: string;
|
|
44
|
+
} | null;
|
|
45
|
+
blocked_reason: string;
|
|
46
|
+
} | undefined;
|
|
11
47
|
}[], SeerChatMessage[] | {
|
|
12
48
|
role: import("./client").SeerChatRole;
|
|
13
49
|
content: string;
|
|
14
50
|
name?: string | undefined;
|
|
51
|
+
orderCard?: {
|
|
52
|
+
type: "order_estimate";
|
|
53
|
+
title: string;
|
|
54
|
+
channel_name: string;
|
|
55
|
+
rows: {
|
|
56
|
+
label: string;
|
|
57
|
+
value: string;
|
|
58
|
+
struck?: boolean | undefined;
|
|
59
|
+
detail?: string | undefined;
|
|
60
|
+
}[];
|
|
61
|
+
subsidy: {
|
|
62
|
+
label: string;
|
|
63
|
+
value: string;
|
|
64
|
+
struck?: boolean | undefined;
|
|
65
|
+
detail?: string | undefined;
|
|
66
|
+
} | null;
|
|
67
|
+
coupon: {
|
|
68
|
+
label: string;
|
|
69
|
+
value: string;
|
|
70
|
+
struck?: boolean | undefined;
|
|
71
|
+
detail?: string | undefined;
|
|
72
|
+
} | null;
|
|
73
|
+
total: {
|
|
74
|
+
label: string;
|
|
75
|
+
value: string;
|
|
76
|
+
struck?: boolean | undefined;
|
|
77
|
+
detail?: string | undefined;
|
|
78
|
+
};
|
|
79
|
+
note: string;
|
|
80
|
+
panel_text: string;
|
|
81
|
+
action: {
|
|
82
|
+
label: string;
|
|
83
|
+
message: string;
|
|
84
|
+
} | null;
|
|
85
|
+
blocked_reason: string;
|
|
86
|
+
} | undefined;
|
|
15
87
|
}[]>;
|
|
16
88
|
loading: import("vue").Ref<boolean, boolean>;
|
|
17
89
|
error: import("vue").Ref<string | null, string | null>;
|
|
@@ -36,7 +108,9 @@ export declare function useSeerChat(localOptions?: UseSeerChatOptions): {
|
|
|
36
108
|
size: number;
|
|
37
109
|
}[]>;
|
|
38
110
|
uploading: import("vue").Ref<boolean, boolean>;
|
|
39
|
-
attach: (file: File
|
|
111
|
+
attach: (file: File, attachOptions?: {
|
|
112
|
+
replace?: boolean;
|
|
113
|
+
}) => Promise<void>;
|
|
40
114
|
removeAttachment: (fileId: string) => void;
|
|
41
115
|
send: (content: string) => Promise<void>;
|
|
42
116
|
reset: () => void;
|