byt-lingxiao-ai 0.2.5 → 0.2.6

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.
@@ -0,0 +1,109 @@
1
+ <template>
2
+ <div class="chat-window-message-ai">
3
+ <div class="ai-render">
4
+ <div class="ai-thinking" @click="$emit('thinking-click')">
5
+ <div class="ai-thinking-time">思考用时{{ message.time }}秒</div>
6
+ <div class="ai-thinking-content" v-if="thinkStatus">{{ message.thinking }}</div>
7
+ </div>
8
+ <div class="ai-content">{{ message.content }}</div>
9
+ </div>
10
+ </div>
11
+ </template>
12
+
13
+ <script>
14
+ export default {
15
+ name: 'AiMessage',
16
+ props: {
17
+ message: {
18
+ type: Object,
19
+ required: true
20
+ },
21
+ thinkStatus: {
22
+ type: Boolean,
23
+ default: true
24
+ }
25
+ }
26
+ }
27
+ </script>
28
+
29
+ <style scoped>
30
+ .chat-window-message-ai {
31
+ display: flex;
32
+ gap: 12px;
33
+ align-items: flex-start;
34
+ max-width: 100%;
35
+ border-radius: 12px;
36
+ background: #f6f8fc;
37
+ padding: 8px 12px;
38
+ }
39
+
40
+ .ai-render {
41
+ width: 100%;
42
+ }
43
+
44
+ .ai-thinking {
45
+ margin-bottom: 8px;
46
+ }
47
+
48
+ .ai-thinking-time {
49
+ border-radius: 9px;
50
+ background: #ECEDF4;
51
+ color: #86909C;
52
+ font-family: "Alibaba PuHuiTi 2.0";
53
+ font-size: 16px;
54
+ font-style: normal;
55
+ font-weight: 500;
56
+ padding: 0 30px 0 30px;
57
+ height: 28px;
58
+ box-sizing: border-box;
59
+ display: inline-flex;
60
+ align-items: center;
61
+ position: relative;
62
+ user-select: none;
63
+ cursor: pointer;
64
+ }
65
+
66
+ .ai-thinking-time::before {
67
+ content: '';
68
+ position: absolute;
69
+ left: 6px;
70
+ top: 50%;
71
+ transform: translateY(-50%);
72
+ width: 16px;
73
+ height: 16px;
74
+ background: url('./assets/think.png') no-repeat;
75
+ background-size: cover;
76
+ }
77
+
78
+ .ai-thinking-time::after {
79
+ content: '';
80
+ position: absolute;
81
+ right: 6px;
82
+ top: 50%;
83
+ transform: translateY(-50%);
84
+ width: 16px;
85
+ height: 16px;
86
+ background: url('./assets/arrow.png') no-repeat;
87
+ background-size: cover;
88
+ }
89
+
90
+ .ai-thinking-content {
91
+ color: #86909C;
92
+ font-family: "Alibaba PuHuiTi 2.0";
93
+ font-size: 14px;
94
+ font-style: normal;
95
+ font-weight: 400;
96
+ line-height: 24px;
97
+ padding: 8px 0 8px 12px;
98
+ }
99
+
100
+ .ai-content {
101
+ color: #4E5969;
102
+ text-align: justify;
103
+ font-family: "Alibaba PuHuiTi 2.0";
104
+ font-size: 16px;
105
+ font-style: normal;
106
+ font-weight: 400;
107
+ line-height: 24px;
108
+ }
109
+ </style>
@@ -0,0 +1,86 @@
1
+ <template>
2
+ <div class="chat-ai" @click="$emit('click')">
3
+ <div :class="['chat-ai-avater', status]"></div>
4
+ <div class="chat-ai-text">{{ statusText }}</div>
5
+ </div>
6
+ </template>
7
+
8
+ <script>
9
+ export default {
10
+ name: 'ChatAvatar',
11
+ props: {
12
+ status: {
13
+ type: String,
14
+ required: true,
15
+ validator: (value) => ['normal', 'thinking', 'output'].includes(value)
16
+ }
17
+ },
18
+ computed: {
19
+ statusText() {
20
+ const textMap = {
21
+ 'normal': '凌霄AI',
22
+ 'thinking': '思考中',
23
+ 'output': '语音中'
24
+ }
25
+ return textMap[this.status]
26
+ }
27
+ }
28
+ }
29
+ </script>
30
+
31
+ <style scoped>
32
+ .chat-ai {
33
+ display: flex;
34
+ width: 38px;
35
+ padding: 2px 2px 9px 2px;
36
+ flex-direction: column;
37
+ align-items: center;
38
+ gap: 6px;
39
+ border-radius: 40px;
40
+ background: linear-gradient(180deg, #3e5beb 0%, #5ca5f9 100%);
41
+ box-shadow: 0 2px 11.6px 0 rgba(0, 0, 0, 0.1);
42
+ cursor: pointer;
43
+ user-select: none;
44
+ }
45
+
46
+ .chat-ai-avater {
47
+ border-radius: 67px;
48
+ border: 1px solid #0f66e4;
49
+ background: #124087;
50
+ display: flex;
51
+ width: 34px;
52
+ height: 33px;
53
+ padding: 2px 2px 1px 2px;
54
+ justify-content: center;
55
+ align-items: center;
56
+ background-size: cover;
57
+ background-position: center;
58
+ }
59
+
60
+ .chat-ai-avater.normal {
61
+ background-image: url('./assets/normal.png');
62
+ }
63
+
64
+ .chat-ai-avater.thinking {
65
+ background-image: url('./assets/thinking.png');
66
+ }
67
+
68
+ .chat-ai-avater.output {
69
+ background-image: url('./assets/output.png');
70
+ }
71
+
72
+ .chat-ai-text {
73
+ color: #fff;
74
+ font-family: 'PingFang SC';
75
+ font-size: 16px;
76
+ font-style: normal;
77
+ font-weight: 500;
78
+ line-height: 20px;
79
+ align-self: stretch;
80
+ display: flex;
81
+ align-items: center;
82
+ width: 20px;
83
+ margin: 0 auto;
84
+ text-align: center;
85
+ }
86
+ </style>
@@ -0,0 +1,127 @@
1
+ <template>
2
+ <div class="chat-window-footer">
3
+ <div class="chat-window-textarea">
4
+ <el-input
5
+ type="textarea"
6
+ class="chat-window-input"
7
+ placeholder="有什么我能帮您的吗?"
8
+ rows="2"
9
+ resize="none"
10
+ :value="value"
11
+ @input="$emit('input', $event)"
12
+ @keydown.native="handleKeyDown"
13
+ ></el-input>
14
+ <div class="chat-window-bar">
15
+ <div class="chat-window-send" @click="$emit('send')">
16
+ <svg
17
+ xmlns="http://www.w3.org/2000/svg"
18
+ width="20"
19
+ height="20"
20
+ viewBox="0 0 20 20"
21
+ fill="none"
22
+ >
23
+ <g clip-path="url(#clip0_640_2107)">
24
+ <path
25
+ d="M18.6427 2.37822C19.3253 2.47432 19.8025 3.10738 19.7065 3.79002C19.6871 3.97072 19.5381 4.41327 19.5403 4.41161L14.9673 17.8079L14.9632 17.8093C14.7858 18.3838 14.212 18.7607 13.5971 18.6744C13.4173 18.6492 13.2504 18.5862 13.1055 18.4949L13.0973 18.4977L9.83449 16.3686C9.58371 16.2584 9.4276 15.9939 9.46729 15.7115C9.5154 15.3691 9.83278 15.1317 10.1751 15.1798C10.293 15.1964 10.3988 15.2448 10.4853 15.3161L13.4054 17.2314L13.4073 17.2317C13.4452 17.2566 13.4882 17.2746 13.5364 17.2814C13.6911 17.3029 13.8371 17.2052 13.8793 17.0593L18.0469 4.89796L8.27396 14.3367L7.77435 17.8916C7.72706 18.2281 7.41369 18.464 7.07727 18.4169C6.74073 18.3696 6.50469 18.0564 6.55198 17.7198L7.07633 13.9889C7.08231 13.9464 7.09382 13.9066 7.10727 13.867C7.13549 13.7645 7.19079 13.6657 7.27291 13.5866L17.0754 4.12041L2.68514 8.17767L2.68487 8.1796C2.58481 8.21873 2.50686 8.31058 2.49042 8.42643C2.47412 8.5424 2.52417 8.65007 2.6093 8.71729L2.60903 8.71922L3.28261 9.16101L3.28013 9.16461C3.47505 9.29254 3.58819 9.52563 3.55386 9.77111C3.50575 10.1134 3.18836 10.3509 2.84602 10.3028C2.75512 10.29 2.6708 10.2584 2.59833 10.2127L2.59806 10.2147L1.37843 9.42001L1.37951 9.41227C1.02215 9.14901 0.816644 8.70195 0.882687 8.23203C0.951867 7.74096 1.29791 7.35545 1.73968 7.21445L1.73995 7.21251L17.7833 2.57104C18.0287 2.41036 18.3294 2.3342 18.6427 2.37822Z"
26
+ fill="#013378"
27
+ />
28
+ <path
29
+ d="M3.1309 10.9936C3.2178 10.5684 3.82528 10.5684 3.91218 10.9936C4.10411 11.9326 4.83794 12.6664 5.77697 12.8584C6.20213 12.9453 6.20213 13.5527 5.77697 13.6397C4.83794 13.8316 4.10411 14.5654 3.91218 15.5044C3.82528 15.9296 3.2178 15.9296 3.1309 15.5044C2.93897 14.5654 2.20513 13.8316 1.26611 13.6397C0.840944 13.5527 0.840944 12.9453 1.26611 12.8584C2.20513 12.6664 2.93897 11.9326 3.1309 10.9936Z"
30
+ fill="#2B80F6"
31
+ />
32
+ <path
33
+ d="M6.20382 8.56242C6.25596 8.30732 6.62045 8.30732 6.67259 8.56242C6.78775 9.12583 7.22805 9.56613 7.79146 9.68129C8.04656 9.73343 8.04656 10.0979 7.79146 10.1501C7.22805 10.2652 6.78775 10.7055 6.67259 11.2689C6.62045 11.524 6.25596 11.524 6.20382 11.2689C6.08866 10.7055 5.64836 10.2652 5.08495 10.1501C4.82985 10.0979 4.82985 9.73343 5.08495 9.68129C5.64836 9.56613 6.08866 9.12583 6.20382 8.56242Z"
34
+ fill="#2B80F6"
35
+ />
36
+ </g>
37
+ <defs>
38
+ <clipPath id="clip0_640_2107">
39
+ <rect width="20" height="20" fill="white" />
40
+ </clipPath>
41
+ </defs>
42
+ </svg>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </template>
48
+
49
+ <script>
50
+ export default {
51
+ name: 'ChatInputBox',
52
+ props: {
53
+ value: {
54
+ type: String,
55
+ default: ''
56
+ }
57
+ },
58
+ methods: {
59
+ handleKeyDown(e) {
60
+ if (e.key === 'Enter' && !e.shiftKey) {
61
+ e.preventDefault()
62
+ this.$emit('send')
63
+ }
64
+ }
65
+ }
66
+ }
67
+ </script>
68
+
69
+ <style scoped>
70
+ ::v-deep .el-textarea__inner {
71
+ border: none !important;
72
+ padding: 0 5px;
73
+ font-family: 'PingFang SC' !important;
74
+ }
75
+
76
+ ::v-deep .el-textarea__inner::-webkit-scrollbar {
77
+ width: 6px;
78
+ height: 6px;
79
+ }
80
+
81
+ ::v-deep .el-textarea__inner::-webkit-scrollbar-thumb {
82
+ background: rgba(0, 0, 0, 0.1);
83
+ border-radius: 3px;
84
+ }
85
+
86
+ ::v-deep .el-textarea__inner::-webkit-scrollbar-track {
87
+ background: transparent;
88
+ }
89
+
90
+ .chat-window-footer {
91
+ padding: 16px;
92
+ }
93
+
94
+ .chat-window-textarea {
95
+ min-height: 99px;
96
+ max-height: 180px;
97
+ border-radius: 8px;
98
+ border: 1px solid #f2f2f2;
99
+ background: #fff;
100
+ display: flex;
101
+ flex-direction: column;
102
+ }
103
+
104
+ .chat-window-input {
105
+ padding: 10px 12px;
106
+ font-size: 16px;
107
+ font-family: 'PingFang SC';
108
+ }
109
+
110
+ .chat-window-bar {
111
+ display: flex;
112
+ justify-content: flex-end;
113
+ padding: 8px;
114
+ }
115
+
116
+ .chat-window-send {
117
+ width: 70px;
118
+ height: 36px;
119
+ flex-shrink: 0;
120
+ border-radius: 6px;
121
+ background: rgba(43, 128, 246, 0.1);
122
+ display: flex;
123
+ align-items: center;
124
+ justify-content: center;
125
+ cursor: pointer;
126
+ }
127
+ </style>
@@ -0,0 +1,81 @@
1
+ <template>
2
+ <div ref="chatArea" class="chat-window-content scrollbar-hide">
3
+ <div
4
+ class="chat-window-message"
5
+ v-for="message in messages"
6
+ :key="message.id"
7
+ >
8
+ <UserMessage
9
+ v-if="message.type === 'user'"
10
+ :content="message.content"
11
+ />
12
+ <AiMessage
13
+ v-else
14
+ :message="message"
15
+ :think-status="thinkStatus"
16
+ @thinking-click="$emit('thinking-click')"
17
+ />
18
+ </div>
19
+ </div>
20
+ </template>
21
+
22
+ <script>
23
+ import UserMessage from './UserMessage.vue'
24
+ import AiMessage from './AiMessage.vue'
25
+
26
+ export default {
27
+ name: 'ChatMessageList',
28
+ components: {
29
+ UserMessage,
30
+ AiMessage
31
+ },
32
+ props: {
33
+ messages: {
34
+ type: Array,
35
+ required: true
36
+ },
37
+ thinkStatus: {
38
+ type: Boolean,
39
+ default: true
40
+ }
41
+ },
42
+ methods: {
43
+ scrollToBottom() {
44
+ this.$nextTick(() => {
45
+ const chatArea = this.$refs.chatArea
46
+ if (chatArea) {
47
+ chatArea.scrollTop = chatArea.scrollHeight
48
+ }
49
+ })
50
+ }
51
+ },
52
+ watch: {
53
+ messages: {
54
+ handler() {
55
+ this.scrollToBottom()
56
+ },
57
+ deep: true
58
+ }
59
+ }
60
+ }
61
+ </script>
62
+
63
+ <style scoped>
64
+ .chat-window-content {
65
+ flex: 1;
66
+ padding: 16px;
67
+ overflow-y: auto;
68
+ display: flex;
69
+ flex-direction: column;
70
+ gap: 8px;
71
+ }
72
+
73
+ .scrollbar-hide::-webkit-scrollbar {
74
+ display: none;
75
+ }
76
+
77
+ .scrollbar-hide {
78
+ -ms-overflow-style: none;
79
+ scrollbar-width: none;
80
+ }
81
+ </style>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <div :class="['chat-robot', status]"></div>
3
+ </template>
4
+
5
+ <script>
6
+ export default {
7
+ name: 'ChatRobot',
8
+ props: {
9
+ status: {
10
+ type: String,
11
+ required: true,
12
+ validator: (value) => ['entering', 'waiting', 'speaking'].includes(value)
13
+ }
14
+ }
15
+ }
16
+ </script>
17
+
18
+ <style scoped>
19
+ .chat-robot {
20
+ width: 150px;
21
+ height: 200px;
22
+ }
23
+
24
+ .chat-robot.entering {
25
+ background-image: url('./assets/entering.png');
26
+ background-size: cover;
27
+ }
28
+
29
+ .chat-robot.waiting {
30
+ background-image: url('./assets/waiting.png');
31
+ background-size: cover;
32
+ }
33
+
34
+ .chat-robot.speaking {
35
+ background-image: url('./assets/speaking.png');
36
+ background-size: cover;
37
+ }
38
+ </style>