ai-error-assistant-mobile 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -120,4 +120,20 @@ export async function sendMessageEventSource(params, signal, onmessage) {
120
120
  body: JSON.stringify(params),
121
121
  onmessage,
122
122
  });
123
- }
123
+ }
124
+
125
+ /**
126
+ * 提交意见反馈
127
+ * @param {FormData} formData
128
+ * @param {string} token
129
+ * @returns {Promise}
130
+ */
131
+ export const submitFeedback = (formData, token) => {
132
+ return request({
133
+ url: prefix + '/assistant/tools/feedback',
134
+ method: 'post',
135
+ headers: { 'Content-Type': 'multipart/form-data' },
136
+ data: formData,
137
+ });
138
+ }
139
+
@@ -74,7 +74,7 @@
74
74
  </div>
75
75
  <div class="answer-content" v-if="businessSource !== '2' ">
76
76
  <div v-for="(list,index) in analysisData.recommend" :key="index" style="margin-bottom: 8px">
77
- <a :href="'https://ai-yuliao.hep.com.cn' + list.url"
77
+ <a :href="seeDetail(list.pageIndex, list.url)"
78
78
  target="_blank"
79
79
  v-if="!list.title.startsWith(chatMajorId)">{{ list.title }}
80
80
  </a>
@@ -89,7 +89,7 @@
89
89
  </template>
90
90
  <script>
91
91
  import ChatTools from './chat-tools.vue';
92
- import {erranalysis, retryAnalysis} from '../api/index'
92
+ import {erranalysis, retryAnalysis,pdfUrlBase} from '../api/index'
93
93
 
94
94
  export default {
95
95
  name: 'ErrorChart',
@@ -166,6 +166,10 @@ export default {
166
166
  throw new Error(e);
167
167
  }
168
168
  },
169
+ seeDetail(pageIndex, url){
170
+ const baseUrl = `${pdfUrlBase}/#/pdf-view?documentUrl=${encodeURIComponent(url)}&pageIndex=${pageIndex}`;
171
+ return baseUrl
172
+ },
169
173
  async reanswer(list) {
170
174
  const cache = {...this.analysisData};
171
175
  this.analysisData = {};
@@ -0,0 +1,319 @@
1
+ <template>
2
+ <div class="feedback-drawer-wrap">
3
+ <div class="feedback-mask" @click="$emit('close')"></div>
4
+ <div class="feedback-drawer" :class="{ open: true }">
5
+ <div class="feedback-header">
6
+ <div class="header-icon-wrap">
7
+ <svg class="header-icon" width="32" height="32" viewBox="0 0 32 32"><circle cx="16" cy="16" r="16" fill="#7a8bff"/><text x="16" y="22" text-anchor="middle" font-size="20" fill="#fff">!</text></svg>
8
+ </div>
9
+ <button class="close-btn" @click="$emit('close')">×</button>
10
+ <h2>您的反馈对我们很重要</h2>
11
+ <p class="subtitle">请详细描述您遇到的问题,我们会尽快处理</p>
12
+ </div>
13
+ <el-form :model="form" :rules="rules" ref="feedbackForm" label-width="0">
14
+ <div class="feedback-form">
15
+ <div class="form-group">
16
+ <el-form-item prop="description" style="margin-bottom: 0px;">
17
+ <label for="description">问题描述</label>
18
+ <textarea
19
+ id="description"
20
+ v-model="form.description"
21
+ placeholder="请详细描述您遇到的问题,以便我们更好地帮助您"
22
+ rows="4"
23
+ />
24
+ </el-form-item>
25
+ </div>
26
+ <div class="form-group">
27
+ <el-form-item prop="phone">
28
+ <label for="phone">联系方式</label>
29
+ <input
30
+ id="phone"
31
+ v-model="form.phone"
32
+ placeholder="方便我们联系您解决问题"
33
+ />
34
+ </el-form-item>
35
+ </div>
36
+ <label class="upload-label">上传图片</label>
37
+ <div class="upload-section">
38
+
39
+ <div class="upload-row">
40
+ <el-upload
41
+ class="el-upload-feedback"
42
+ action="#"
43
+ :auto-upload="false"
44
+ :limit="1"
45
+ :on-change="onElUploadChange"
46
+ :before-upload="beforeElUpload"
47
+ :file-list="elFileList"
48
+ :show-file-list="true"
49
+ list-type="picture-card"
50
+ accept="image/*"
51
+ >
52
+ <i class="el-icon-plus"></i>
53
+ </el-upload>
54
+ </div>
55
+ <div class="upload-tip">最多上传1张图片,大小不超过10MB</div>
56
+ </div>
57
+ <div class="submit-section">
58
+ <el-button type="primary" @click="submitForm" class="submit-button" block>提交反馈</el-button>
59
+ </div>
60
+ </div>
61
+ </el-form>
62
+ </div>
63
+ </div>
64
+ </template>
65
+
66
+ <script>
67
+ import { Upload, Form, FormItem, Button } from 'element-ui';
68
+ import { submitFeedback } from '../../demo/api/index';
69
+ export default {
70
+ name: 'Feedback',
71
+ components: { Upload, ElForm: Form, ElFormItem: FormItem, ElButton: Button },
72
+ props: {
73
+ businessSource: {
74
+ type: String,
75
+ default: ''
76
+ },
77
+ },
78
+ data() {
79
+ return {
80
+ form: {
81
+ description: '',
82
+ phone: ''
83
+ },
84
+ elFileList: [],
85
+ token: '',
86
+ rules: {
87
+ description: [
88
+ { required: true, message: '请输入问题描述', trigger: 'blur' },
89
+ ],
90
+ phone: []
91
+ }
92
+ };
93
+ },
94
+ methods: {
95
+ beforeElUpload(file) {
96
+ const MAX_SIZE = 1024 * 1024 * 10;
97
+ if (file.size > MAX_SIZE) {
98
+ this.$message.warning('图片大小不能超过10MB');
99
+ return false;
100
+ }
101
+ return true;
102
+ },
103
+ onElUploadChange(file, fileList) {
104
+ this.elFileList = fileList.slice(-1); // 只保留最后一张
105
+ },
106
+ submitForm() {
107
+ this.$refs.feedbackForm.validate(valid => {
108
+ if (!valid) return;
109
+ this.onSubmit();
110
+ });
111
+ },
112
+ async onSubmit() {
113
+ const formData = new FormData();
114
+ formData.append('description', this.form.description);
115
+ if (this.form.phone) formData.append('phone', this.form.phone);
116
+ if (this.elFileList.length > 0 && this.elFileList[0].raw) {
117
+ formData.append('file', this.elFileList[0].raw);
118
+ }
119
+ try {
120
+ const response = await submitFeedback(formData, this.businessSource);
121
+ if (response === '反馈成功') {
122
+ this.$message.success('提交成功');
123
+ this.form.description = '';
124
+ this.form.phone = '';
125
+ this.elFileList = [];
126
+ } else {
127
+ this.$message.warning(response.data.message || '提交失败');
128
+ }
129
+ } catch (error) {
130
+ this.$message.closeAll && this.$message.closeAll();
131
+ this.$message.error('提交失败,请稍后重试');
132
+ }
133
+ }
134
+ },
135
+ };
136
+ </script>
137
+
138
+ <style scoped>
139
+ .feedback-drawer-wrap {
140
+ position: fixed;
141
+ z-index: 2000;
142
+ top: 0;
143
+ left: 0;
144
+ width: 100vw;
145
+ height: 100vh;
146
+ }
147
+ .feedback-mask {
148
+ position: absolute;
149
+ top: 0;
150
+ left: 0;
151
+ width: 100vw;
152
+ height: 100vh;
153
+ background: rgba(0,0,0,0.35);
154
+ z-index: 1;
155
+ }
156
+ .feedback-drawer {
157
+ position: fixed;
158
+ top: 0;
159
+ right: 0;
160
+ width: 100vw;
161
+ height: 100vh;
162
+ background: #eef2ff;
163
+ z-index: 2;
164
+ box-shadow: -2px 0 16px rgba(0,0,0,0.08);
165
+ border-radius: 0;
166
+ display: flex;
167
+ flex-direction: column;
168
+ transform: translateX(100vw);
169
+ transition: transform 0.35s cubic-bezier(0.4,0,0.2,1);
170
+ }
171
+ .feedback-drawer.open {
172
+ transform: translateX(0);
173
+ }
174
+ .close-btn {
175
+ position: absolute;
176
+ top: -15px;
177
+ right: 16px;
178
+ background: none;
179
+ border: none;
180
+ font-size: 28px;
181
+ color: #888;
182
+ cursor: pointer;
183
+ z-index: 10;
184
+ line-height: 1;
185
+ }
186
+ .feedback-header {
187
+ text-align: center;
188
+ margin: 24px 0 32px;
189
+ position: relative;
190
+ }
191
+ .header-icon-wrap {
192
+ display: flex;
193
+ justify-content: center;
194
+ margin-bottom: 12px;
195
+ }
196
+ .header-icon {
197
+ color: #7a8bff;
198
+ }
199
+ .feedback-header h2 {
200
+ font-size: 20px;
201
+ font-weight: 600;
202
+ color: #323233;
203
+ margin: 0 0 8px;
204
+ }
205
+ .feedback-header .subtitle {
206
+ font-size: 14px;
207
+ color: #8c8c8c;
208
+ margin: 0;
209
+ }
210
+ .feedback-form {
211
+ background: #fff;
212
+ border-radius: 12px;
213
+ box-shadow: 0 2px 12px rgba(100, 101, 102, 0.04);
214
+ padding: 20px;
215
+ margin: 0 16px 16px 16px;
216
+ }
217
+ .form-group {
218
+ margin-bottom: 18px;
219
+ }
220
+ .form-group label {
221
+ font-weight: 500;
222
+ color: #4a4a4a;
223
+ display: block;
224
+ }
225
+ .form-group textarea,
226
+ .form-group input {
227
+ width: 100%;
228
+ border: 1px solid #e5e5e5;
229
+ border-radius: 8px;
230
+ padding: 8px 12px;
231
+ font-size: 15px;
232
+ color: #323233;
233
+ background: #f5f7fa;
234
+ resize: none;
235
+ box-sizing: border-box;
236
+ }
237
+ .upload-section {
238
+ background-color: #ffffff;
239
+ border-radius: 12px;
240
+ box-shadow: 0 2px 12px rgba(100, 101, 102, 0.04);
241
+ }
242
+ .upload-header {
243
+ display: flex;
244
+ align-items: center;
245
+ margin-bottom: 16px;
246
+ font-size: 15px;
247
+ font-weight: 500;
248
+ color: #4a4a4a;
249
+ }
250
+ .upload-tip {
251
+ margin-top: 12px;
252
+ font-size: 12px;
253
+ color: #8c8c8c;
254
+ text-align: center;
255
+ }
256
+ .submit-section {
257
+ margin: 32px 16px 0 16px;
258
+ }
259
+ .submit-button {
260
+ width: 100%;
261
+ height: 44px;
262
+ font-size: 16px;
263
+ font-weight: 500;
264
+ background: linear-gradient(135deg, #7a8bff 0%, #a3b3ff 100%);
265
+ border: none;
266
+ border-radius: 22px;
267
+ color: #fff;
268
+ box-shadow: 0 4px 12px rgba(122, 139, 255, 0.3);
269
+ transition: all 0.3s;
270
+ }
271
+ .submit-button:active {
272
+ transform: translateY(1px);
273
+ box-shadow: 0 2px 8px rgba(122, 139, 255, 0.3);
274
+ }
275
+ .upload-label {
276
+ font-weight: 500;
277
+ color: #4a4a4a;
278
+ display: block;
279
+ line-height: 40px;
280
+ font-size: 14px;
281
+ }
282
+ .upload-row {
283
+ display: flex;
284
+ align-items: flex-start;
285
+ }
286
+ .el-upload-feedback {
287
+ margin-bottom: 8px;
288
+ display: flex;
289
+ align-items: center;
290
+ }
291
+ .el-upload-feedback .el-upload {
292
+ margin-right: 8px;
293
+ }
294
+ .el-upload-feedback .el-upload-list {
295
+ margin: 0;
296
+ display: flex;
297
+ flex-wrap: wrap;
298
+ }
299
+ .el-upload-feedback >>> .el-upload-list__item {
300
+ width: 100px !important;
301
+ height: 100px !important;
302
+ margin: 0 8px 0 0 !important;
303
+ }
304
+ .el-upload-feedback >>> .el-upload--picture-card {
305
+ width: 100px !important;
306
+ height: 100px !important;
307
+ line-height: 100px !important;
308
+ }
309
+ .el-upload-feedback >>> .el-upload-list__item-thumbnail {
310
+ width: 64px !important;
311
+ height: 64px !important;
312
+ object-fit: cover;
313
+ border-radius: 8px;
314
+ }
315
+ .el-upload-feedback >>> .el-icon-plus {
316
+ font-size: 24px !important;
317
+ line-height: 64px !important;
318
+ }
319
+ </style>
@@ -5,6 +5,11 @@
5
5
  <i class="el-icon-back" @click="closeMessage"></i>
6
6
  <span class="title-font">错题解析</span>
7
7
  </div>
8
+ <div class="header-right">
9
+ <div class="feedback-icon" @click="feedback">
10
+ <img alt="" src="../static/feedback.png" style="width: 20px; height: 20px"/>
11
+ </div>
12
+ </div>
8
13
  </div>
9
14
  <div v-if="!courseFlag" class="message-wrap">
10
15
  <div class="message-line">{{ message }}</div>
@@ -39,10 +44,22 @@
39
44
  <!-- 此功能公测期间对正式版用户开放-->
40
45
  <!-- </p>-->
41
46
  </template>
47
+ <el-drawer
48
+ :visible.sync="showFeedback"
49
+ direction="rtl"
50
+ size="100%"
51
+ :with-header="false"
52
+ custom-class="feedback-el-drawer"
53
+ :modal="false"
54
+ :close-on-click-modal="false"
55
+ >
56
+ <feedback @close="showFeedback = false" :businessSource="businessSource"/>
57
+ </el-drawer>
42
58
  </div>
43
59
  </template>
44
60
  <script>
45
61
  import Chat from './chat.vue';
62
+ import Feedback from './feedback.vue';
46
63
  import Cookies from "js-cookie";
47
64
  import {getUserInfo} from '../utils/config';
48
65
  import {checkCourseIdIsExist, queryCallWord} from '../api/index';
@@ -51,7 +68,8 @@ import cache from "../plugins/cache";
51
68
  export default {
52
69
  name: 'AiErrorAssistantMobile',
53
70
  components: {
54
- Chat
71
+ Chat,
72
+ Feedback
55
73
  },
56
74
  props: {
57
75
  visible: true,
@@ -93,6 +111,7 @@ export default {
93
111
  showMoreQA: false,
94
112
  showFile: false,
95
113
  avatarUrl: '',
114
+ showFeedback: false,
96
115
  }
97
116
  },
98
117
  mounted() {
@@ -155,6 +174,9 @@ export default {
155
174
  }
156
175
  return true;
157
176
  },
177
+ feedback() {
178
+ this.showFeedback = true;
179
+ },
158
180
  }
159
181
  }
160
182
  </script>
@@ -208,6 +230,29 @@ export default {
208
230
  }
209
231
  }
210
232
  }
233
+
234
+ .header-right {
235
+ display: flex;
236
+ align-items: center;
237
+ margin-right: 12px;
238
+ .feedback-icon {
239
+ width: 32px;
240
+ height: 32px;
241
+ border-radius: 50%;
242
+ display: flex;
243
+ align-items: center;
244
+ justify-content: center;
245
+ background: none;
246
+ cursor: pointer;
247
+ transition: background 0.2s;
248
+ &:active {
249
+ background: #ececec;
250
+ }
251
+ svg {
252
+ display: block;
253
+ }
254
+ }
255
+ }
211
256
  }
212
257
 
213
258
  .logo-title {
@@ -405,4 +450,14 @@ export default {
405
450
  }
406
451
  }
407
452
  }
453
+
454
+ .feedback-el-drawer {
455
+ z-index: 2000;
456
+ .el-drawer__body {
457
+ padding: 0;
458
+ height: 100vh;
459
+ background: #eef2ff;
460
+ overflow: auto;
461
+ }
462
+ }
408
463
  </style>