vuepress-theme-uniapp-official 1.6.2 → 1.6.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.
@@ -0,0 +1,61 @@
1
+ .ai-answer-card
2
+ padding 14px 16px
3
+ margin-top 12px
4
+ background #fff
5
+ border-radius 12px
6
+ border 1px solid rgba(0,0,0,0.06)
7
+ box-shadow 0 2px 8px rgba(0,0,0,0.04)
8
+ transition box-shadow .25s, transform .2s
9
+ cursor pointer
10
+
11
+ &:hover
12
+ box-shadow 0 4px 14px rgba(0,0,0,0.08)
13
+ transform translateY(-1px)
14
+ /* 重置部分元素样式,防止样式冲突 */
15
+ pre
16
+ margin: 0
17
+ padding: 5px
18
+ border-radius 10px
19
+ background #f6f8fa
20
+ & + pre
21
+ margin-top 8px
22
+ pre, code
23
+ white-space: pre-wrap; /* 允许换行 */
24
+ word-wrap: break-word; /* 允许长行断开 */
25
+ word-break: break-word;
26
+ h1, h2, h3, h4, h5, h6, p, ul, ol, dl, figure, blockquote
27
+ line-height: normal
28
+ margin: 0
29
+ padding: 0
30
+ ul, ol
31
+ list-style: none
32
+
33
+ .ai-answer-header
34
+ display flex
35
+ align-items center
36
+ margin-bottom 8px
37
+
38
+ .ai-answer-icon
39
+ font-size 18px
40
+ margin-right 6px
41
+
42
+ .ai-answer-title
43
+ font-weight 600
44
+ font-size 15px
45
+ color #333
46
+
47
+ .ai-answer-msg
48
+ font-size 14px
49
+ line-height normal
50
+ color #555
51
+ // white-space pre-wrap
52
+ word-break break-word
53
+ animation fadeIn .3s ease
54
+
55
+ @keyframes fadeIn
56
+ from
57
+ opacity 0
58
+ transform translateY(4px)
59
+ to
60
+ opacity 1
61
+ transform translateY(0)
@@ -28,14 +28,7 @@
28
28
  </div>
29
29
  </transition-group>
30
30
 
31
- <div v-if="sending" class="chat-skeleton chat-skeleton-left">
32
- <div class="content">
33
- <div class="line"></div>
34
- <div class="line"></div>
35
- <div class="line short"></div>
36
- </div>
37
- </div>
38
-
31
+ <Skeleton style="width: 60%" v-if="sending" />
39
32
  </main>
40
33
 
41
34
  <footer class="chat-input-bar">
@@ -52,14 +45,14 @@
52
45
  </template>
53
46
 
54
47
  <script setup>
55
- import { ref, nextTick, watchEffect, onMounted, onActivated, watch } from 'vue'
48
+ import { ref, nextTick, watchEffect, onMounted } from 'vue'
56
49
  import { renderMarkdown } from "./markdown-loader";
57
- import 'highlight.js/styles/github.min.css'
58
50
  import SelectPlatform from './SelectPlatform.vue';
59
51
  import { ajax } from '../../utils/postDcloudServer';
60
52
  import searchPageConfig from '@theme-config/searchPage';
53
+ import Skeleton from '../Skeleton';
61
54
 
62
- const { aiPlatforms = [], aiChatForDocSearch } = searchPageConfig;
55
+ const { aiPlatforms = [], aiChatForDocSearch = 'https://ai-assist-api.dcloud.net.cn/tbox/chatForDocSearch' } = searchPageConfig;
63
56
 
64
57
  const props = defineProps({
65
58
  currentCategory: {
@@ -98,7 +91,8 @@ watchEffect(() => {
98
91
  if (props.visible) {
99
92
  nextTick(() => {
100
93
  scrollToBottom()
101
- autoGrow(true)
94
+ autoGrow()
95
+ input.value.focus()
102
96
  })
103
97
  }
104
98
  })
@@ -111,11 +105,11 @@ function formatTime() {
111
105
  .padStart(2, '0')}`
112
106
  }
113
107
 
114
- function autoGrow(clear) {
108
+ function autoGrow() {
115
109
  const el = input.value
116
110
  el.style.height = 'auto'
117
111
  scrollToBottom()
118
- if (clear === true) {
112
+ if (inputText.value.length === 0) {
119
113
  return
120
114
  }
121
115
  el.style.height = el.scrollHeight + 'px'
@@ -164,12 +158,21 @@ function platformChange(newPlatform) {
164
158
  sendPlatform.value = newPlatform
165
159
  }
166
160
 
161
+ // 限制只取最近 6 条消息
162
+ function getChatHistory() {
163
+ return messages.value.slice(-6).map(m => ({
164
+ role: m.role,
165
+ contentType: 'text',
166
+ content: m.raw
167
+ }))
168
+ }
169
+
167
170
  async function send() {
168
171
  if (!inputText.value.trim() || sending.value) return
169
172
 
170
173
  const userText = inputText.value.trim()
171
174
  inputText.value = ''
172
- autoGrow(true)
175
+ autoGrow()
173
176
 
174
177
  // 用户消息
175
178
  messages.value.push({
@@ -186,17 +189,18 @@ async function send() {
186
189
 
187
190
  let fakeReply = ''
188
191
  try {
189
- const res = await ajax(aiChatForDocSearch ? aiChatForDocSearch : 'https://ai-assist-api.dcloud.net.cn/tbox/chatForDocSearch', 'POST', {
192
+ const res = await ajax(aiChatForDocSearch, 'POST', {
190
193
  "question": userText,
191
- "group_name": sendPlatform.value
194
+ "group_name": sendPlatform.value,
195
+ "history": getChatHistory()
192
196
  })
193
197
  if (res.errorCode === 0) {
194
198
  fakeReply = res.chunk
195
199
  } else {
196
- fakeReply = `抱歉,AI 助手出错了:${res.errorMessage || '未知错误'}`
200
+ fakeReply = `抱歉,AI 助手出错了:${res.errorMsg || '未知错误'}`
197
201
  }
198
202
  } catch (error) {
199
-
203
+ fakeReply = `抱歉,AI 助手出错了:${error.message || '未知错误'}`
200
204
  }
201
205
  sending.value = false
202
206
 
@@ -210,6 +214,7 @@ async function send() {
210
214
  isTyping: false,
211
215
  like: 0
212
216
  }
217
+
213
218
  messages.value.push(aiMsg)
214
219
 
215
220
  // 动态打字
@@ -223,8 +228,6 @@ window.addEventListener('resize', scrollToBottom)
223
228
  </script>
224
229
 
225
230
  <style lang="stylus">
226
- @import './skeleton.styl'
227
-
228
231
  .chat-wrapper
229
232
  display flex
230
233
  flex-direction column
@@ -288,6 +291,8 @@ window.addEventListener('resize', scrollToBottom)
288
291
  word-break break-word
289
292
  box-shadow 0 1px 3px rgba(0,0,0,0.08)
290
293
  pre
294
+ margin: 0
295
+ padding: 5px
291
296
  border-radius 10px
292
297
  & + pre
293
298
  margin-top 8px
@@ -295,7 +300,7 @@ window.addEventListener('resize', scrollToBottom)
295
300
  white-space: pre-wrap; /* 允许换行 */
296
301
  word-wrap: break-word; /* 允许长行断开 */
297
302
  word-break: break-word;
298
- h1, h2, h3, h4, h5, h6, p, ul, ol, dl, figure, blockquote, pre
303
+ h1, h2, h3, h4, h5, h6, p, ul, ol, dl, figure, blockquote
299
304
  margin: 0
300
305
  padding: 0
301
306
  ul, ol
@@ -1,16 +1,30 @@
1
1
  // markdown-loader.js
2
2
  let markedInstance = null;
3
- let hljsInstance = null;
4
3
 
5
- function transfromLang(lang) {
6
- switch (lang) {
7
- case 'uts':
8
- return 'typescript';
9
- case 'json5':
10
- return 'json';
11
- }
12
- if (!hljsInstance) return 'plaintext';
13
- return hljsInstance.getLanguage(lang) ? lang : 'plaintext';
4
+ // `1.` 转义为 `1、`,防止 marked 解析失败
5
+ function escapeMD(str) {
6
+ return str
7
+ .replace(/(\s*\b)(\d+)\./g, '$1$2、')
8
+ }
9
+
10
+ function getLangCodeFromExtension(extension) {
11
+ const extensionMap = {
12
+ vue: 'markup',
13
+ html: 'markup',
14
+ md: 'markdown',
15
+ rb: 'ruby',
16
+ ts: 'typescript',
17
+ py: 'python',
18
+ sh: 'bash',
19
+ yml: 'yaml',
20
+ styl: 'stylus',
21
+ kt: 'kotlin',
22
+ rs: 'rust',
23
+ uts: 'typescript',
24
+ json5: 'json',
25
+ };
26
+
27
+ return extensionMap[extension] || extension;
14
28
  }
15
29
 
16
30
  export async function renderMarkdown(md) {
@@ -21,7 +35,7 @@ export async function renderMarkdown(md) {
21
35
  headerIds: false,
22
36
  mangle: false,
23
37
  highlight(code, lang) {
24
- lang = transfromLang(lang);
38
+ lang = getLangCodeFromExtension(lang);
25
39
  if (lang && hljs.getLanguage(lang)) {
26
40
  return hljs.highlight(code, { language: lang }).value;
27
41
  }
@@ -30,8 +44,6 @@ export async function renderMarkdown(md) {
30
44
  });
31
45
 
32
46
  markedInstance = marked;
33
- hljsInstance = hljs;
34
47
  }
35
-
36
- return markedInstance.parse(md || '');
48
+ return markedInstance.parse(escapeMD(md || ''));
37
49
  }
@@ -1,3 +1,14 @@
1
+ <template>
2
+ <div class="chat-skeleton chat-skeleton-left">
3
+ <div class="chat-skeleton_content">
4
+ <div class="chat-skeleton_content_line"></div>
5
+ <div class="chat-skeleton_content_line"></div>
6
+ <div class="chat-skeleton_content_line short"></div>
7
+ </div>
8
+ </div>
9
+ </template>
10
+
11
+ <style lang="stylus" scope>
1
12
  /* Skeleton base style */
2
13
  .skeleton
3
14
  background: #eee
@@ -18,13 +29,12 @@
18
29
  gap: 12px
19
30
  padding: 12px 0
20
31
 
21
- .chat-skeleton .line
32
+ .chat-skeleton .chat-skeleton_content_line
22
33
  height: 14px
23
- width: 60%
24
34
  border-radius: 6px
25
35
  @extend .skeleton
26
36
 
27
- .chat-skeleton .line.short
37
+ .chat-skeleton .chat-skeleton_content_line.short
28
38
  width: 40%
29
39
 
30
40
  /* 左侧消息骨架(AI) */
@@ -32,8 +42,10 @@
32
42
  display: flex
33
43
  flex-direction: row
34
44
  gap: 10px
35
- .content
45
+ .chat-skeleton_content
36
46
  flex: 1
37
47
  display: flex
38
48
  flex-direction: column
39
49
  gap: 10px
50
+
51
+ </style>
@@ -29,14 +29,14 @@
29
29
  <div class="input-wrap">
30
30
  <input ref="searchInput" class="search-input" :placeholder="placeholder" type="text" @keydown.enter="
31
31
  () => {
32
- resetSearchPage();
32
+ resetSearch();
33
33
  search();
34
34
  }
35
35
  " v-model="searchValue" />
36
36
  <span class="search-input-btn">
37
37
  <button @click="
38
38
  () => {
39
- resetSearchPage();
39
+ resetSearch();
40
40
  search();
41
41
  }
42
42
  ">
@@ -83,7 +83,21 @@
83
83
  <div class="result-wrap">
84
84
  <template v-if="isAlgolia">
85
85
  <template v-for="item in resultList">
86
- <Results :key="item.sourceId" :title="item.title" :results="item.items" :onSelect="item.onSelect" />
86
+ <template v-if="item">
87
+ <Results v-if="!item.isAI" :key="item.sourceId" :title="item.title" :results="item.items"
88
+ :onSelect="item.onSelect" />
89
+ <template v-else>
90
+ <div class="ai-answer-card">
91
+ <div class="ai-answer-header">
92
+ <span class="ai-answer-icon">🤖</span>
93
+ <span class="ai-answer-title">{{ item.title }}</span>
94
+ </div>
95
+
96
+ <div v-if="item.msg.length" class="ai-answer-msg" v-html="item.msg" />
97
+ <Skeleton v-else />
98
+ </div>
99
+ </template>
100
+ </template>
87
101
  </template>
88
102
  </template>
89
103
 
@@ -128,17 +142,21 @@
128
142
  </template>
129
143
 
130
144
  <script>
145
+ import searchPageConfig from '@theme-config/searchPage';
131
146
  import NavbarLogo from '../NavbarLogo.vue';
132
147
  import Results from './components/Results.vue';
133
148
  import pagination from './components/pagination.vue';
134
149
  import AIChat from './components/AIChat/index.vue';
135
150
  import MainNavbarLink from '../MainNavbarLink.vue';
151
+ import Skeleton from './components/Skeleton.vue';
136
152
  import { search as searchClient } from './utils/searchClient';
137
153
  import { postExt, postAsk } from './utils/postDcloudServer';
138
154
  import { forbidScroll, debounce } from '../../util';
139
155
  import { removeHighlightTags, isEditingContent } from './utils/searchUtils';
140
- import searchPageConfig from '@theme-config/searchPage';
141
156
  import Base64 from './utils/Base64';
157
+ import { ajax } from './utils/postDcloudServer';
158
+ import { renderMarkdown } from "./components/AIChat/markdown-loader";
159
+ import 'highlight.js/styles/github.min.css'
142
160
 
143
161
  const {
144
162
  enableAI = true,
@@ -147,9 +165,11 @@ const {
147
165
  searchBox: { placeholder, buttonText, searchBy },
148
166
  resultsScreen: { resultsText, noResultsText, askNoResultsText },
149
167
  },
150
- extraFacetFilters = []
168
+ extraFacetFilters = [],
169
+ aiChatForDocSearch = 'https://ai-assist-api.dcloud.net.cn/tbox/chatForDocSearch'
151
170
  } = searchPageConfig;
152
171
  const crawlerUrl = 'https://zh.uniapp.dcloud.io/'
172
+ const AIErrorMsg = '很抱歉,AI 助手未能找到相关答案。请尝试更换关键词进行搜索。'
153
173
 
154
174
  const resolveRoutePathFromUrl = (url, base = '/') => {
155
175
  if (url.indexOf(crawlerUrl) === 0) {
@@ -165,7 +185,7 @@ export default {
165
185
 
166
186
  props: ['options'],
167
187
 
168
- components: { NavbarLogo, Results, pagination, MainNavbarLink, AIChat },
188
+ components: { NavbarLogo, Results, pagination, MainNavbarLink, AIChat, Skeleton },
169
189
 
170
190
  data() {
171
191
  return {
@@ -191,6 +211,13 @@ export default {
191
211
  totalPage: 0, // 搜索结果总共页数
192
212
  curPage: 1, // 当前页
193
213
  pageSize: 0, // 每页条数
214
+
215
+ searchAIResult: Promise.resolve(null),
216
+ aiMessage: {
217
+ isAI: true,
218
+ title: 'AI 助手回答',
219
+ msg: ''
220
+ }
194
221
  };
195
222
  },
196
223
 
@@ -260,10 +287,10 @@ export default {
260
287
  });
261
288
  },
262
289
 
263
- searchValue: debounce(function () {
264
- this.resetSearchPage();
290
+ /* searchValue: debounce(function () {
291
+ this.resetSearch();
265
292
  this.search();
266
- }, 300),
293
+ }, 300), */
267
294
 
268
295
  $route: {
269
296
  immediate: true,
@@ -320,8 +347,20 @@ export default {
320
347
  }
321
348
  },
322
349
 
323
- resetSearchPage() {
350
+ resetSearch() {
324
351
  this.searchPage = 0;
352
+ this.resetAI();
353
+ },
354
+
355
+ resetAI() {
356
+ if (this.searchAIResult && typeof this.searchAIResult.abort === 'function') {
357
+ this.searchAIResult.abort()
358
+ }
359
+ this.aiMessage.msg = ''
360
+ this.searchAIResult = null
361
+ if (this.enableAI && this.searchValue.trim().length) {
362
+ this.searchByAI()
363
+ }
325
364
  },
326
365
 
327
366
  research(curPage) {
@@ -345,11 +384,16 @@ export default {
345
384
  items,
346
385
  };
347
386
  });
387
+
348
388
  this.noResult = !this.resultList.length;
349
389
  this.curHits = nbHits;
350
390
  this.pageSize = hitsPerPage;
351
391
  this.totalPage = nbPages;
352
392
  this.curPage = page + 1;
393
+
394
+ if (this.curPage === 1 && this.enableAI) {
395
+ this.resultList.splice(1, 0, this.aiMessage);
396
+ }
353
397
  })
354
398
  .finally(() => {
355
399
  this.showLoading = false
@@ -396,6 +440,33 @@ export default {
396
440
  );
397
441
  },
398
442
 
443
+ searchByAI() {
444
+ try {
445
+ this.searchAIResult = ajax(aiChatForDocSearch, 'POST', {
446
+ "question": this.searchValue,
447
+ "group_name": this.currentCategory.text
448
+ }).then(res => {
449
+ if (res.errorCode === 0) {
450
+ return renderMarkdown(res.chunk)
451
+ } else {
452
+ this.aiMessage.msg = res.errorMsg || AIErrorMsg;
453
+ return ''
454
+ }
455
+ })
456
+ .catch((err) => {
457
+ console.log('err :>> ', err);
458
+ return ''
459
+ })
460
+ .then(msg => {
461
+ this.aiMessage.msg = msg || AIErrorMsg;
462
+ })
463
+ } catch (err) {
464
+ console.log('err :>> ', err);
465
+ this.aiMessage.msg = err.message || AIErrorMsg;
466
+ return ''
467
+ }
468
+ },
469
+
399
470
  searchByServer(append = false) {
400
471
  const { tag } = this.currentCategory;
401
472
  const query = this.searchValue || '';
@@ -509,4 +580,5 @@ export default {
509
580
 
510
581
  <style lang="stylus">
511
582
  @import './index'
583
+ @import './ai-result.styl'
512
584
  </style>
@@ -1,74 +1,76 @@
1
- const isProduction = process.env.NODE_ENV === "production"
2
- const isMock = false
3
- import mock from './mock'
1
+ const isProduction = process.env.NODE_ENV === 'production';
2
+ const isMock = false;
3
+ import mock from './mock';
4
4
 
5
5
  export function ajax(url = '', method = 'get', data = {}) {
6
- return new Promise((resolve, reject) => {
7
- if (!url) reject('url 不可为空')
8
- const xhr = new XMLHttpRequest();
9
- xhr.open(method, url);
10
- xhr.onreadystatechange = function () {
11
- if (this.readyState == 4 && this.status == 200) {
12
- try {
13
- resolve(JSON.parse(this.response))
14
- } catch (error) {
15
- resolve(this.response)
16
- }
17
- }
18
- }
19
- if (method.toLowerCase() === 'post') {
20
- xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
21
- xhr.send(JSON.stringify(data));
22
- } else {
23
- xhr.send();
24
- }
25
- })
6
+ if (!url) return Promise.reject('url 不可为空');
7
+ const xhr = new XMLHttpRequest();
8
+ const p = new Promise((resolve, reject) => {
9
+ xhr.open(method, url);
10
+ xhr.onreadystatechange = function () {
11
+ if (this.readyState == 4 && this.status == 200) {
12
+ try {
13
+ resolve(JSON.parse(this.response));
14
+ } catch (error) {
15
+ resolve(this.response);
16
+ }
17
+ }
18
+ };
19
+ if (method.toLowerCase() === 'post') {
20
+ xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
21
+ xhr.send(JSON.stringify(data));
22
+ } else {
23
+ xhr.send();
24
+ }
25
+ });
26
+ p.abort = () => xhr.abort();
27
+ return p;
26
28
  }
27
29
 
28
30
  export async function postExt(query) {
29
- const base = isProduction ? '//ext.dcloud.net.cn' : '/ext'
30
- let extRet
31
- if (!isMock) {
32
- const extRes = await ajax(base + '/search/json?query=' + encodeURIComponent(query))
33
- extRet = JSON.parse(extRes);
34
- } else {
35
- extRet = mock.ext;
36
- }
37
-
38
- let extHtml = '';
39
- let data = extRet.data;
40
- if (extRet.ret === 0) {
41
- for (let i = 0, len = data.length; i < len; i++) {
42
- extHtml += _renderExt(data[i], query);
43
- }
44
- }
45
- return {
46
- html: extHtml,
47
- hits: data.length
48
- }
31
+ const base = isProduction ? '//ext.dcloud.net.cn' : '/ext';
32
+ let extRet;
33
+ if (!isMock) {
34
+ const extRes = await ajax(base + '/search/json?query=' + encodeURIComponent(query));
35
+ extRet = JSON.parse(extRes);
36
+ } else {
37
+ extRet = mock.ext;
38
+ }
39
+
40
+ let extHtml = '';
41
+ let data = extRet.data;
42
+ if (extRet.ret === 0) {
43
+ for (let i = 0, len = data.length; i < len; i++) {
44
+ extHtml += _renderExt(data[i], query);
45
+ }
46
+ }
47
+ return {
48
+ html: extHtml,
49
+ hits: data.length,
50
+ };
49
51
  }
50
52
 
51
53
  export async function postAsk(query, page = 1) {
52
- const base = isProduction ? '//ask.dcloud.net.cn' : '/ask'
53
- let askHtml = '';
54
-
55
- if (!isMock) {
56
- askHtml = await ajax(base + `/search/ajax/search_result/search_type-all__q-${query}__page-${page}`)
57
- if (!askHtml) {
58
- return;
59
- }
60
- } else {
61
- askHtml = mock.askHtml
62
- }
63
-
64
- return {
65
- html: askHtml,
66
- hits: 0
67
- }
54
+ const base = isProduction ? '//ask.dcloud.net.cn' : '/ask';
55
+ let askHtml = '';
56
+
57
+ if (!isMock) {
58
+ askHtml = await ajax(base + `/search/ajax/search_result/search_type-all__q-${query}__page-${page}`);
59
+ if (!askHtml) {
60
+ return;
61
+ }
62
+ } else {
63
+ askHtml = mock.askHtml;
64
+ }
65
+
66
+ return {
67
+ html: askHtml,
68
+ hits: 0,
69
+ };
68
70
  }
69
71
 
70
72
  function _renderExt(ext, keyword) {
71
- return `<div class="matching-post">
73
+ return `<div class="matching-post">
72
74
  <a href="${ext.url}" target="_blank">
73
75
  <div class="post-wrapper">
74
76
  <h2>
@@ -81,30 +83,30 @@ function _renderExt(ext, keyword) {
81
83
  <p>${ext.total_download}次下载</p>
82
84
  <p>${_handleHTMLString(ext.description, keyword)}</p>
83
85
  </a>
84
- </div>`
86
+ </div>`;
85
87
  }
86
88
 
87
89
  function _renderPost(post, value) {
88
- let html = '';
89
- let commentText = '';
90
- let tagName = '规范';
91
-
92
- // 1,问题;2,文章;默认是规范。
93
- switch (post.type) {
94
- case 'questions':
95
- tagName = '问题';
96
- break;
97
- case 'articles':
98
- tagName = '文章';
99
- break;
100
- }
101
-
102
- if (!!value) {
103
- post.title = _handleHTMLString(post.title, value);
104
- post.content = _handleHTMLString(post.content, value);
105
- }
106
-
107
- html += `<div class="matching-post">
90
+ let html = '';
91
+ let commentText = '';
92
+ let tagName = '规范';
93
+
94
+ // 1,问题;2,文章;默认是规范。
95
+ switch (post.type) {
96
+ case 'questions':
97
+ tagName = '问题';
98
+ break;
99
+ case 'articles':
100
+ tagName = '文章';
101
+ break;
102
+ }
103
+
104
+ if (!!value) {
105
+ post.title = _handleHTMLString(post.title, value);
106
+ post.content = _handleHTMLString(post.content, value);
107
+ }
108
+
109
+ html += `<div class="matching-post">
108
110
  <a href="${post.url}" target="_blank">
109
111
  <div class="post-wrapper">
110
112
  <h2>
@@ -113,38 +115,29 @@ function _renderPost(post, value) {
113
115
  </p>
114
116
  ${post.title}
115
117
  </h2>
116
- </div>`
118
+ </div>`;
117
119
 
118
- if (!!value) {
119
- commentText = post.type === 'questions' ? '回复' : '评论';
120
- html += `<p>
120
+ if (!!value) {
121
+ commentText = post.type === 'questions' ? '回复' : '评论';
122
+ html += `<p>
121
123
  ${post.comment_count}个${commentText}
122
124
  <span class="aw-text-space">-</span>
123
125
  ${post.view_count}次浏览
124
126
  </p>`;
125
- }
127
+ }
126
128
 
127
- html += `\n<p>${post.content}</p>\n</a>\n</div>`;
129
+ html += `\n<p>${post.content}</p>\n</a>\n</div>`;
128
130
 
129
- return html;
131
+ return html;
130
132
  }
131
133
 
132
134
  function _handleHTMLString(dataString, keyword) {
133
- let keywordReg = new RegExp(
134
- keyword.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'),
135
- 'gi'
136
- );
137
- let tagStartReg = new RegExp(
138
- '&lt;span style=\'font-weight:bold;color:red\'&gt;',
139
- 'g'
140
- );
141
- let tagEndReg = new RegExp(
142
- '&lt;/span&gt;',
143
- 'g'
144
- );
145
-
146
- return dataString
147
- .replace(tagStartReg, '')
148
- .replace(tagEndReg, '')
149
- .replace(keywordReg, ("<em class=\"search-keyword\">" + keyword + "</em>"));
150
- };
135
+ let keywordReg = new RegExp(keyword.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'), 'gi');
136
+ let tagStartReg = new RegExp("&lt;span style='font-weight:bold;color:red'&gt;", 'g');
137
+ let tagEndReg = new RegExp('&lt;/span&gt;', 'g');
138
+
139
+ return dataString
140
+ .replace(tagStartReg, '')
141
+ .replace(tagEndReg, '')
142
+ .replace(keywordReg, '<em class="search-keyword">' + keyword + '</em>');
143
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vuepress-theme-uniapp-official",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "uni-app official website theme for vuepress",
5
5
  "main": "index.js",
6
6
  "repository": {