提交 720efbf6 编写于 作者: D DCloud_LXH

wip: search page

上级 73bf1739
......@@ -36,7 +36,7 @@ const config = {
apiKey: '2fdcc4e76c8e260671ad70065e60b2e7',
indexName: 'zh-uniapp',
appId: 'PQIR5NL8CZ',
searchParameters: { hitsPerPage: 80 }
searchParameters: { hitsPerPage: 40 }
}
},
markdown: {
......
<template>
<div id="docsearch"></div>
<div id="docsearch">
<button type="button" class="DocSearch DocSearch-Button" aria-label="搜索文档" @click="openSearch">
<span class="DocSearch-Button-Container">
<svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20">
<path
d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
stroke="currentColor"
fill="none"
fill-rule="evenodd"
stroke-linecap="round"
stroke-linejoin="round"
></path>
</svg>
<span class="DocSearch-Button-Placeholder">搜索文档</span>
</span>
<span class="DocSearch-Button-Keys">
<span class="DocSearch-Button-Key">
<svg width="15" height="15" class="DocSearch-Control-Key-Icon">
<path
d="M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953"
stroke-width="1.2"
stroke="currentColor"
fill="none"
stroke-linecap="square"
></path>
</svg>
</span>
<span class="DocSearch-Button-Key">K</span>
</span>
</button>
</div>
</template>
<script>
import '@docsearch/css';
import { createElement } from 'preact';
const resolveRoutePathFromUrl = (url, base = '/') =>
url
// remove url origin
.replace(/^(https?:)?\/\/[^/]*/, '')
// remove site base
.replace(new RegExp(`^${base}`), '/');
const loadDocsearch = async () => {
const docsearch = await import('@docsearch/js');
return docsearch.default;
};
const isSpecialClick = event => {
return event.button === 1 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
};
const translations = {
button: {
buttonText: '搜索文档',
buttonAriaLabel: '搜索文档',
},
modal: {
searchBox: {
resetButtonTitle: '清除查询条件',
resetButtonAriaLabel: '清除查询条件',
cancelButtonText: '取消',
cancelButtonAriaLabel: '取消',
},
startScreen: {
recentSearchesTitle: '搜索历史',
noRecentSearchesText: '搜索历史为空',
saveRecentSearchButtonTitle: '收藏',
removeRecentSearchButtonTitle: '从搜索记录中移除',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除',
},
errorScreen: {
titleText: '无法获取结果',
helpText: '请检查一下网络连接',
},
footer: {
selectText: '选择',
navigateText: '切换',
closeText: '关闭',
searchByText: '搜索提供者',
},
noResultsScreen: {
noResultsText: '无法找到相关结果',
suggestedQueryText: '你可以尝试查询',
reportMissingResultsText: '你认为查询该有结果?',
reportMissingResultsLinkText: '点击反馈',
},
},
};
export default {
name: 'AlgoliaSearchBox',
props: ['options'],
watch: {},
watch: {
$lang(newValue) {
this.update(this.options, newValue);
},
options(newValue) {
this.update(newValue, this.$lang);
},
},
mounted() {
this.initialize(this.options, this.$lang);
},
mounted() {},
methods: {
initialize(userOptions, lang) {
loadDocsearch().then(docsearch => {
const { searchParameters = {} } = userOptions;
docsearch(
Object.assign({}, userOptions, {
placeholder: '搜索',
translations,
container: '#docsearch',
// #697 Make docsearch work well at i18n mode.
searchParameters: {
...searchParameters,
facetFilters: [`lang:${lang}`].concat(searchParameters.facetFilters || []),
},
navigator: {
// when pressing Enter without metaKey
navigate: ({ itemUrl }) => {
this.$router.push(itemUrl);
},
},
/* getMissingResultsUrl: ({ query }) =>
`https://github.com/dcloudio/uni-app/issues/new?title=${query}`, */
// transform full url to route path
transformItems: items =>
items.map(item => {
// the `item.url` is full url with protocol and hostname
// so we have to transform it to vue-router path
return {
...item,
url: resolveRoutePathFromUrl(item.url, this.$site.base),
};
}),
// handle `onClick` by `this.$routerpush`
hitComponent: ({ hit, children }) =>
createElement(
'a',
{
href: hit.url,
onClick: event => {
if (isSpecialClick(event)) {
return;
}
event.preventDefault();
this.$router.push(hit.url);
},
},
children
),
})
);
});
},
update(options, lang) {
this.$el.innerHTML = '<div id="docsearch"></div>';
this.initialize(options, lang);
},
openSearch(){
this.$parent.$refs.dcloudSearchPage.onSearchOpen()
}
},
};
</script>
......
<template>
<li :class="li_class">
<a :href="item.url" @click="onSearchClose">
<div class="DocSearch-Hit-Container">
<div
class="DocSearch-Hit-content-wrapper"
v-if="item.hierarchy[item.type] && item.type === 'lvl1'"
>
<span class="DocSearch-Hit-title" v-html="snippetResultContent('hierarchy.lvl1')" />
<span
v-if="item.content"
class="DocSearch-Hit-path"
v-html="snippetResultContent('content')"
/>
</div>
<div v-else-if="isContent" class="DocSearch-Hit-content-wrapper">
<span class="DocSearch-Hit-title" v-html="snippetResultContent('content')" />
<span class="DocSearch-Hit-path" v-html="snippetResultContent('hierarchy.lvl1')" />
</div>
<div v-else class="DocSearch-Hit-content-wrapper">
<span
class="DocSearch-Hit-title"
v-html="snippetResultContent(`hierarchy.${item.type}`)"
/>
<span class="DocSearch-Hit-path" v-html="snippetResultContent('hierarchy.lvl1')" />
</div>
</div>
</a>
</li>
</template>
<script>
function getPropertyByPath(object, path) {
const parts = path.split('.');
return parts.reduce((prev, current) => {
if (prev?.[current]) return prev[current];
return null;
}, object);
}
export default {
data() {
return {};
},
inject: ['onSearchClose'],
props: {
item: {
type: Object,
default: () => ({}),
},
index: {
type: Number,
default: 0,
},
},
computed: {
li_class() {
return ['DocSearch-Hit', this.item.__docsearch_parent && 'DocSearch-Hit--Child']
.filter(Boolean)
.join(' ');
},
isContent() {
return this.item.type === 'content';
},
},
methods: {
snippetResultContent(attribute) {
return (
getPropertyByPath(this.item, `_snippetResult.${attribute}.value`) ||
getPropertyByPath(this.item, attribute)
);
},
},
};
</script>
<style lang="stylus">
.DocSearch-Hit
border-radius 4px
display flex
padding-bottom 4px
position relative
a
background var(--docsearch-hit-background)
border-radius 4px
box-shadow var(--docsearch-hit-shadow)
display block
padding-left var(--docsearch-spacing)
width 100%
.DocSearch-Hit-Container
align-items center
color #444950
display flex
flex-direction row
height 56px
padding 0 12px 0 0
.DocSearch-Hit-content-wrapper
overflow hidden
display flex
flex 1 1 auto
flex-direction column
font-weight 500
justify-content center
line-height 1.2em
margin 0 8px
overflow-x hidden
position relative
text-overflow ellipsis
white-space nowrap
width 80%
.DocSearch-Hit-title
font-size 0.9em
.DocSearch-Hit-path
color $accentColor
font-size 0.75em
</style>
<template>
<section class="DocSearch-Hits">
<div class="DocSearch-Hit-source">{{ title }}</div>
<ul id="docsearch-list">
<template v-for="(item, index) in results">
<Result :key="[title, item.objectID].join(':')" :item="item" :index="index" />
</template>
</ul>
</section>
</template>
<script>
import Result from './Result.vue';
export default {
components: { Result },
data() {
return {};
},
props: {
title: {
type: String,
default: '文档',
},
results: {
type: Array,
default: [],
},
},
methods: {},
};
</script>
<style lang="stylus">
.DocSearch-Hits mark {
background: none;
color: $accentColor;
}
.DocSearch-Hit-source {
background-color $search-container-color;
color: $accentColor;
}
</style>
<template>
<!-- 分页结构 -->
<div class="page-bar">
<ul>
<li v-if="cur > 1"><a class="clearfix" v-on:click="cur--, pageClick()">上一页</a></li>
<li v-if="cur == 1"><a class="banclick clearfix">上一页</a></li>
<template v-for="index in indexs">
<li :key="index" :class="{ active: cur == index }">
<a class="clearfix" v-on:click="btnClick(index)">{{ index }}</a>
</li>
</template>
<li v-if="cur != all"><a class="clearfix" v-on:click="cur++, pageClick()">下一页</a></li>
<li v-if="cur == all"><a class="banclick clearfix">下一页</a></li>
<li>
<span>
<i>{{ all }}</i>
</span>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
all: 10, //总页数
cur: 1, //当前页码
// totalPage: 0, //当前条数
};
},
props: {
curPage: {
type: Number,
default: 1,
},
totalPage: {
type: Number,
default: 0,
},
},
created() {
this.all = this.totalPage;
this.cur = this.curPage;
},
watch: {
curPage: {
immediate: true,
handler(val) {
this.cur = val;
},
},
totalPage: {
immediate: true,
handler(val) {
this.all = val;
},
},
},
methods: {
//请求数据
dataListFn: function (index) {
this.$emit('research', index);
},
//分页
btnClick: function (data) {
if (data != this.cur) {
this.cur = data;
this.dataListFn(this.cur);
}
},
pageClick: function () {
this.dataListFn(this.cur);
},
},
computed: {
//分页
indexs: function () {
var left = 1;
var right = this.all;
var ar = [];
if (this.all >= 5) {
if (this.cur > 3 && this.cur < this.all - 2) {
left = this.cur - 2;
right = this.cur + 2;
} else {
if (this.cur <= 3) {
left = 1;
right = 5;
} else {
right = this.all;
left = this.all - 4;
}
}
}
while (left <= right) {
ar.push(left);
left++;
}
return ar;
},
},
};
</script>
<style lang="stylus" scoped>
.page-bar
display flex
justify-content center
margin 10px
ul, li
margin 0px
padding 0px
user-select none
li
display inline-block
list-style none
overflow hidden
.page-bar li:first-child > a
margin-left 0px
.page-bar a
border 1px solid #ddd
text-decoration none
position relative
float left
padding 2px 10px
margin-left -1px
line-height 1.42857143
color #5d6062
cursor pointer
margin-right 20px
background-color #fff
.page-bar a:hover
background-color #eee
.page-bar a.banclick
cursor not-allowed
.page-bar .active a
color #fff
cursor default
background-color $accentColor
border-color $accentColor
.page-bar i
font-style normal
color $accentColor
margin 0px 4px
font-size 12px
</style>
$svg-color = #b1b2b3
$svg-hover-color = #9b9b9b
#search-container
overflow auto
position fixed
width 100vw
height 100vh
left 0
top 0
z-index 200
background-color $search-container-color
.sub-navbar, .result-wrap
width 80%
max-width 960px
margin 0 auto
.search-wrap
width 100%
display inline-block
vertical-align middle
position relative
.input-wrap
margin-top 24px
position relative
display flex
align-items center
box-sizing border-box
.search-input-btn
display flex
flex-direction column
justify-content center
padding 0
font-size 0
background-color #fff
button
width 40px
font-family inherit
font-size 100%
margin 0
outline 0
background-color transparent
padding 0
border-width 0
vertical-align middle
cursor pointer
svg
fill $svg-color
&:hover
fill $svg-hover-color
.search-input
width 100%
height 56px
font-size 16px
border none
box-sizing border-box
outline none
padding 1px 10px
border-radius 4px
.search-input-btn
height 56px
.search-back__btn
display block !important
font-size 17px
color #576b95
line-height 24px
padding 10px 16px
white-space nowrap
.search-category
.navbar
border none
.main-navbar
box-shadow none
.main-navbar-links
width 100%
padding 0
.main-navbar-item
padding 0 6%
.result-number
display flex
justify-content center
margin-top 20px
font-size 20px
.search-result
box-sizing border-box
.result-wrap
ul
list-style none
margin 0
padding 0
@media (max-width $MQMobile)
#search-container
.search-navbar-header>.main-navbar
display none !important
.search-navbar>.navbar, .search-category>.navbar
line-height 3rem
height auto
position static !important
.sub-navbar, .result-wrap
width 100% !important
.input-wrap
padding-left 5px
margin-top 5px !important
.search-input, .search-input-btn
height 32px !important
.search-result
padding 0 10px
\ No newline at end of file
<template>
<div id="search-container">
<div v-if="openSearch" id="search-container" ref="pageContainer">
<div class="search-navbar">
<div class="search-navbar-wrap">
<div class="search-navbar-header navbar">
<div class="main-navbar">
<NavbarLogo />
<div class="main-navbar-links can-hide">
<div class="main-navbar-item active"></div>
</div>
<div class="search-navbar-header navbar">
<div class="main-navbar">
<NavbarLogo />
<div class="main-navbar-links can-hide">
<div class="main-navbar-item active"></div>
</div>
<div class="sub-navbar">
<div class="search-wrap">
<div class="input-wrap">
<input
class="search-input"
:placeholder="placeholder"
type="text"
v-model="searchValue"
/>
<span class="search-input-btn">
<button @click="search">
<svg
width="16"
height="16"
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.33 10.007l4.273 4.273a.502.502 0 0 1 .005.709l-.585.584a.499.499 0 0 1-.709-.004L10.046 11.3a6.278 6.278 0 1 1 1.284-1.294zm.012-3.729a5.063 5.063 0 1 0-10.127 0 5.063 5.063 0 0 0 10.127 0z"
></path>
</svg>
</button>
</span>
</div>
</div>
<div class="sub-navbar">
<div class="search-wrap">
<div class="input-wrap">
<input
ref="searchInput"
class="search-input"
:placeholder="placeholder"
type="text"
@keydown.enter="search"
v-model="searchValue"
/>
<span class="search-input-btn">
<button @click="search">
<svg
width="16"
height="16"
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.33 10.007l4.273 4.273a.502.502 0 0 1 .005.709l-.585.584a.499.499 0 0 1-.709-.004L10.046 11.3a6.278 6.278 0 1 1 1.284-1.294zm.012-3.729a5.063 5.063 0 1 0-10.127 0 5.063 5.063 0 0 0 10.127 0z"
></path>
</svg>
</button>
</span>
<a href="javascript:;" class="search-back__btn" @click="onSearchClose">取消</a>
</div>
<div class="search-category">
<div class="navbar">
<div class="main-navbar">
<div class="main-navbar-links">
<template v-for="(item, index) in category">
<div :class="mainNavLinkClass(index)" :key="item.text">
<a href="javascript:;" @click="categoryIndex = index">
{{ item.text }}
</a>
</div>
</template>
</div>
<div class="search-category">
<div class="navbar">
<div class="main-navbar">
<div class="main-navbar-links">
<template v-for="(item, index) in category">
<div :class="mainNavLinkClass(index)" :key="item.text">
<a href="javascript:;" @click="categoryIndex = index">
{{ item.text }}
</a>
</div>
</template>
</div>
</div>
</div>
......@@ -55,14 +56,38 @@
</div>
</div>
<div class="search-result"></div>
<div class="result-number">
<span>共{{ curHits }}个相关结果</span>
</div>
<div class="search-result">
<div class="result-wrap">
<template v-if="resultList.length">
<template v-for="item in resultList">
<Results :key="item.id" :title="item.title" :results="item.items" />
</template>
</template>
</div>
<div class="search-pagination">
<pagination
v-show="showPagination"
@research="research"
:totalPage="totalPage"
:curPage="curPage"
:pageSize="pageSize"
/>
</div>
</div>
</div>
</template>
<script>
import NavbarLogo from '../NavbarLogo.vue';
import Results from './components/Results.vue';
import pagination from './components/pagination.vue';
import { search as searchClient } from './searchClient';
import { forbidScroll } from '../../util';
import { forbidScroll, removeHighlightTags, debounce, isEditingContent } from '../../util';
const resolveRoutePathFromUrl = (url, base = '/') =>
url
......@@ -76,44 +101,114 @@
props: ['options'],
components: { NavbarLogo },
components: { NavbarLogo, Results, pagination },
provide() {
return {
onSearchClose: this.onSearchClose,
};
},
data() {
return {
openSearch: false,
placeholder: '搜索内容',
snippetLength: 10,
snippetLength: 30,
searchValue: '',
category: Object.freeze([
{
text: 'uni-app',
},
{
text: 'uniCloud',
text: 'uni',
type: 'algolia',
},
{
text: '问答社区',
type: 'server',
},
{
text: '插件市场',
type: 'server',
},
]),
categoryIndex: 0,
resultList: [],
searchPage: 0, // 跳转页数
curHits: 0, // 当前搜索条数
totalPage: 0, // 搜索结果总共条数
curPage: 1, // 当前页
pageSize: 0, // 每页条数
};
},
computed: {
showPagination() {
return !!(this.resultList.length && this.totalPage > 1);
},
},
mounted() {
this.$nextTick(forbidScroll);
window.addEventListener('keydown', this.onKeyDown);
window.addEventListener('resize', this.initSnippetLength);
},
watch: {
resultList() {
this.$refs.pageContainer.scrollTop = 0;
},
const isMobileMediaQuery = window.matchMedia('(max-width: 750px)');
openSearch(val) {
this.$nextTick(() => {
if (val) {
this.$nextTick(forbidScroll);
document.body.appendChild(this.$el);
this.$nextTick(() => this.$refs.searchInput.focus());
} else {
this.cancel();
forbidScroll(false);
document.body.removeChild(this.$el);
// window.removeEventListener('keydown', this.onKeyDown);
}
});
},
if (isMobileMediaQuery.matches) {
this.snippetLength = 5;
}
searchValue: debounce(function () {
this.searchPage = 0;
this.search();
}, 300),
},
methods: {
research(curPage) {
this.searchPage = curPage - 1;
this.search();
},
search() {
this.searchByAlgolia(this.searchValue);
if (!this.searchValue) return;
const { text, type } = this.category[this.categoryIndex];
switch (type) {
case 'algolia':
this.searchByAlgolia(this.searchValue, this.searchPage).then(
({ hitsPerPage, nbHits, nbPages, page, hits }) => {
this.resultList = hits.map(item => {
const items = item.getItems();
return {
id: item.sourceId,
title: removeHighlightTags(items[0]),
items,
};
});
this.curHits = nbHits;
this.pageSize = hitsPerPage;
this.totalPage = nbPages;
this.curPage = page + 1;
}
);
break;
case 'server':
console.log('从服务端搜索');
break;
}
},
searchByAlgolia(query = '', page = 0) {
......@@ -143,100 +238,54 @@
mainNavLinkClass(index) {
return ['main-navbar-item', this.categoryIndex === index ? 'active' : ''];
},
},
};
</script>
<style lang="stylus">
$svg-color = #b1b2b3;
$svg-hover-color = #9b9b9b;
#search-container{
position fixed
width 100vw
height 100vh
left 0
top 0
z-index 200
background-color #fff
.sub-navbar {
width: 80%;
max-width: 960px;
min-width: 720px;
margin: 0 auto;
.search-wrap {
width: 100%;
display: inline-block;
vertical-align: middle;
position: relative;
}
.input-wrap {
margin-top: 24px;
position: relative;
display: flex;
align-items: center;
.search-input-btn {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0;
font-size: 0;
background-color: #fff;
button {
width: 40px;
font-family: inherit;
font-size: 100%;
margin: 0;
outline: 0;
background-color: transparent;
padding: 0;
border-width: 0;
vertical-align: middle;
cursor: pointer;
svg {
fill: $svg-color;
&:hover {
fill: $svg-hover-color;
}
}
}
initSnippetLength() {
if (window.matchMedia('(max-width: 980px)').matches) {
this.snippetLength = 20;
}
.search-input {
width: 100%;
height: 56px;
font-size: 16px;
border: none;
box-sizing: border-box;
outline: none;
padding: 1px 10px;
border-radius: 4px;
if (window.matchMedia('(max-width: 600px)').matches) {
this.snippetLength = 15;
}
},
.search-input-btn {
height: 56px;
}
}
cancel() {
this.resultList.length = 0;
this.searchValue = '';
this.curHits = 0;
this.totalPage = 0;
},
.search-category {
onSearchOpen() {
this.openSearch = true;
},
onSearchClose() {
this.openSearch = false;
},
.main-navbar-links {
width: 100%;
padding: 0;
onKeyDown(event) {
if (
(event.keyCode === 27 && this.openSearch) ||
// The `Cmd+K` shortcut both opens and closes the modal.
(event.key === 'k' && (event.metaKey || event.ctrlKey)) ||
// The `/` shortcut opens but doesn't close the modal because it's
// a character.
(!isEditingContent(event) && event.key === '/' && !this.openSearch)
) {
event.preventDefault();
.main-navbar-item {
padding: 0 6%;
if (this.openSearch) {
this.onSearchClose();
} else {
this.onSearchOpen();
}
}
}
},
},
};
</script>
}
}
<style lang="stylus">
@import './index'
</style>
......@@ -42,8 +42,8 @@ export function search({ query, indexName, appId, apiKey, searchParameters = {},
highlightPreTag: '<mark>',
highlightPostTag: '</mark>',
hitsPerPage: 20,
...args,
...searchParameters,
...args,
},
},
])
......@@ -51,46 +51,48 @@ export function search({ query, indexName, appId, apiKey, searchParameters = {},
throw error;
})
.then(({ results }) => {
const { hits, nbHits } = results[0];
const { hits, hitsPerPage, nbHits, nbPages, page } = results[0];
const sources = groupBy(hits, (hit) => removeHighlightTags(hit));
return {
hitsPerPage, nbHits, nbPages, page,
hits: Object.values(sources).map(
(items, index) => {
return {
sourceId: `hits${index}`,
onSelect({ item, event }) {
// saveRecentSearch(item);
return Object.values(sources).map(
(items, index) => {
return {
sourceId: `hits${index}`,
onSelect({ item, event }) {
// saveRecentSearch(item);
// if (!event.shiftKey && !event.ctrlKey && !event.metaKey) {
// onClose();
// }
},
getItemUrl({ item }) {
return item.url;
},
getItems() {
return Object.values(
groupBy(items, (item) => item.hierarchy.lvl1)
)
.map(transformItems)
.map((groupedHits) =>
groupedHits.map((item) => {
return {
...item,
__docsearch_parent:
item.type !== 'lvl1' &&
groupedHits.find(
(siblingItem) =>
siblingItem.type === 'lvl1' &&
siblingItem.hierarchy.lvl1 ===
item.hierarchy.lvl1
),
};
})
).flat();
},
};
}
);
// if (!event.shiftKey && !event.ctrlKey && !event.metaKey) {
// onClose();
// }
},
getItemUrl({ item }) {
return item.url;
},
getItems() {
return Object.values(
groupBy(items, (item) => item.hierarchy.lvl1)
)
.map(transformItems)
.map((groupedHits) =>
groupedHits.map((item) => {
return {
...item,
__docsearch_parent:
item.type !== 'lvl1' &&
groupedHits.find(
(siblingItem) =>
siblingItem.type === 'lvl1' &&
siblingItem.hierarchy.lvl1 ===
item.hierarchy.lvl1
),
};
})
).flat();
},
};
}
)
}
});
}
\ No newline at end of file
......@@ -35,6 +35,7 @@
} : {}"
>
<a class="switch-version" href="javascript:void(0)" @click="switchVersion">回到旧版</a>
<DcloudSearchPage ref="dcloudSearchPage" v-if="isAlgoliaSearch" :options="algolia"/>
<AlgoliaSearchBox
v-if="isAlgoliaSearch"
:options="algolia"
......@@ -61,6 +62,7 @@ import SidebarButton from '@theme/components/SidebarButton.vue'
import NavLinks from '@theme/components/NavLinks.vue'
import MainNavbarLink from './MainNavbarLink.vue';
import NavbarLogo from './NavbarLogo.vue';
import DcloudSearchPage from './DcloudSearchPage';
import navInject from '../mixin/navInject';
import { forbidScroll, os } from '../util';
......@@ -75,7 +77,8 @@ export default {
MainNavbarLink,
SearchBox,
AlgoliaSearchBox,
NavbarLogo
NavbarLogo,
DcloudSearchPage
},
data () {
......
......@@ -4,6 +4,7 @@
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
@keydown.ctrl="openSearch = true"
>
<Navbar
v-if="shouldShowNavbar"
......@@ -42,8 +43,6 @@
<Footer />
</template>
</Page>
<DcloudSearchPage :options="algolia"/>
</div>
</template>
......@@ -54,7 +53,6 @@ import Page from '@theme/components/Page.vue'
import Sidebar from '@theme/components/Sidebar.vue'
import Footer from '@theme/components/Footer.vue';
import SiderBarBottom from '../components/SiderBarBottom.vue';
import DcloudSearchPage from '../components/DcloudSearchPage';
import { resolveSidebarItems, forbidScroll, BaiduStat } from '../util'
import navProvider from '../mixin/navProvider';
......@@ -67,8 +65,7 @@ export default {
Sidebar,
Navbar,
Footer,
SiderBarBottom,
DcloudSearchPage
SiderBarBottom
},
data () {
return {
......@@ -118,9 +115,6 @@ export default {
},
userPageClass
]
},
algolia () {
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
}
},
mounted () {
......
......@@ -3,4 +3,5 @@ $accentColor = #42b983
$contentWidth = 1200px
$navbarHeight = 9rem
$navbar-sub-navbar-height = 5rem
$navbar-background-color = #f7f7f7
\ No newline at end of file
$navbar-background-color = #f7f7f7
$search-container-color = #f5f6f7
\ No newline at end of file
......@@ -289,4 +289,17 @@ export const BaiduStat = () => {
hm.src = "https://hm.baidu.com/hm.js?fe3b7a223fc08c795f0f4b6350703e6f";
const s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
}
export function debounce (fn, delay) {
let timeout
const newFn = function () {
clearTimeout(timeout)
const timerFn = () => fn.apply(this, arguments)
timeout = setTimeout(timerFn, delay)
}
newFn.cancel = function () {
clearTimeout(timeout)
}
return newFn
}
\ No newline at end of file
......@@ -37,3 +37,15 @@ export function removeHighlightTags(hit) {
? value.replace(regexHighlightTags, '')
: value;
}
export function isEditingContent(event) {
const element = event.target;
const tagName = element.tagName;
return (
element.isContentEditable ||
tagName === 'INPUT' ||
tagName === 'SELECT' ||
tagName === 'TEXTAREA'
);
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册