使 hexo icarus 主题支持拼音搜索

:::success
在最新的 5.0 版本已经支持拼音搜索,请升级体验

本篇文章直击如何使到 icarus 升级到可以支持拼音搜索

前期准备

  • Icarus 主题版本 3.0 以上
  • 搜索插件使用的是 Insight

操作方法

  1. 另存为下面的文件到  themes/icarus/source/js

pinyin.js

  1. 另存为下面的文件到  themes/icarus/layout/search

insight.jsx

  1. 另存为下面的文件到  themes/icarus/source/js

insight.js


  1. 修改  themes/icarus/layout/search/insight.jsx,加入拼音检索开关和依赖的 <font style="color:#4A4A4A;">pinyin.js</font>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* Insight search plugin JSX component.
* @module view/search/insight
*/
--- a/src/view/search/insight.jsx
+++ b/src/view/search/insight.jsx
@@ -3,7 +3,7 @@
const { Component, Fragment } = require('inferno');
-const { cacheComponent } = require('../../util/cache');
+const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');

/**
* Algolia search engine JSX component.
@@ -36,11 +36,18 @@ class Insight extends Component {
<div class="searchbox-input-container">
<input type="text" class="searchbox-input" placeholder={translation.hint}/>
</div>
+ <div class="searchbox-pinyin">
+ <label class="checkbox">
+ <input id="search-by-pinyin" type="checkbox" checked="checked"/>
+ <span> 拼音检索</span>
+ </label>
+ </div>
<a class="searchbox-close" href="javascript:;">×</a>
</div>
<div class="searchbox-body"></div>
</div>
</div>
+ <script src="/js/pinyin.js" defer={true}></script>
<script src={jsUrl} defer={true}></script>
<script dangerouslySetInnerHTML={{ __html: js }}></script>
</Fragment>;
  1. 修改  themes/icarus/source/js/insight.js,在原有匹配代码基础上增加拼音匹配代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
diff --git a/asset/js/insight.js b/asset/js/insight.js
index 33150b3..205a096 100644
--- a/asset/js/insight.js
+++ b/asset/js/insight.js
@@ -6,6 +6,19 @@ function loadInsight(config, translation) { // eslint-disable-line no-unused-var
const $main = $('.searchbox');
const $input = $main.find('.searchbox-input');
const $container = $main.find('.searchbox-body');
+ const $searchByPinyin = $main.find('#search-by-pinyin');
+
+ /**
+ * 查询匹配拼音的数据。性能低于普通匹配,如果未启用拼音检索模式,直接返回 false。
+ * https://github.com/xmflswood/pinyin-match
+ * @param input {string} 目标字符串
+ * @param keyword {string} 输入的拼音或其他关键词
+ * @returns {[Array]|{Boolean}} 找到返回出现位置,未找到 / 未启用返回 false
+ */
+ function pinyinMatch(input, keyword) {
+ if (!$searchByPinyin.prop("checked")) return false;
+ return PinyinMatch.match(input, keyword);
+ }

function section(title) {
return $('<section>').addClass('searchbox-result-section').append($('<header>').text(title));
@@ -33,10 +46,12 @@ function loadInsight(config, translation) { // eslint-disable-line no-unused-var
const testText = text.toLowerCase();
const indices = matches.map(match => {
const index = testText.indexOf(match.toLowerCase());
- if (!match || index === -1) {
- return null;
+ if (match && index !== -1) {
+ return [index, index + match.length];
}
- return [index, index + match.length];
+ // Search by pinyin
+ const pinyinIndex = pinyinMatch(testText, match.toLowerCase());
+ return pinyinIndex ? [pinyinIndex[0], pinyinIndex[1] + 1] : null;
}).filter(match => {
return match !== null;
}).sort((a, b) => {
@@ -140,6 +155,8 @@ function loadInsight(config, translation) { // eslint-disable-line no-unused-var
}
if (obj[field].toLowerCase().indexOf(keyword) > -1) {
return true;
+ } else if (pinyinMatch(obj[field].toLowerCase(), keyword)) {
+ return true;
}
return false;
});
@@ -266,10 +283,12 @@ function loadInsight(config, translation) { // eslint-disable-line no-unused-var
if (location.hash.trim() === '#insight-search') {
$main.addClass('show');
}
- $input.on('input', function() {
- const keywords = $(this).val();
+ function onInputChange() {
+ const keywords = $input.val();
searchResultToDOM(keywords, search(json, keywords));
- });
+ }
+ $input.on('input', onInputChange);
+ $searchByPinyin.on('change', onInputChange);
$input.trigger('input');
});
  1. 修改  themes/icarus/include/style/search.styl,调整拼音检索复选框大小和位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
diff --git a/include/style/search.styl b/include/style/search.styl
index 0cdedd9..02d9b5e 100644
--- a/include/style/search.styl
+++ b/include/style/search.styl
@@ -96,6 +96,16 @@ $searchbox-bg-pagination-item-disabled ?= $searchbox-bg-container
.searchbox-input
flex-grow: 1
color: inherit
box-sizing: border-box
padding: .75em 0 .75em 1.25em
background: $searchbox-bg-input

+ .searchbox-pinyin
+ display: flex
+ align-items: center
+ user-select: none
+ input
+ vertical-align: middle
+ span
+ position: relative
+ top: 1px
+
.searchbox-close
display: inline-block
font-size: 1.5em
padding: .5em .75em
cursor: pointer

致谢

感谢来自 ppoffice 的hexo-component-inferno 项目

以及 xmflswood 的 pinyin-match 项目提供支撑

MySQL数据库跨服务器数据同步

1.环境说明

MySQL 版本:5.7.20

本地数据库 A(作为 Zentao 数据库),本地数据库 B,本地程序 C;本地为 Windows 环境。

2.方案探索

方案 1:在 A 中写触发器,表中数据变化时将 ID 发给 C,由 C 在 A 中查询变化的数据,写入 B。过程中需要安装 mysql-udf-http 插件

(参考:https://www.2cto.com/database/201801/713571.html)

方案 2

在 A 中用触发器监控数据的变化,然后调用存储过程将数据推送给 B ,用 BDlink 进行数据库跨库。

DBlink 是 oracle 进行跨库访问的方法,SQL Server 可以用 linkServer。在 mysql5.0 版本以上,可以采用 FEDERATED 引擎(默认引擎为 InnoDB)。

(参考:https://blog.csdn.net/langkeziju/article/details/50462943)

所以值得注意:建表时指定引擎为 FEDERATED

ENGINE=FEDERATED CONNECTION='mysql://user:password@ip:port/test1/test_table';

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE TABLE federated_table (
id int(20) NOT NULL auto_increment,
name varchar(32) NOT NULL default '',
age varchar(4) NOT NULL default '0',
sts char(1) NOT NULL default '0',
office VARCHAR(64) NOT NULL default '0',
telephone VARCHAR(15) NOT NULL default '0',
PRIMARY KEY (id),
KEY name (name),
KEY age (age),
KEY sts (sts),
KEY telephone (telephone),
KEY office (office)

) ENGINE=FEDERATED CONNECTION='mysql://user:password@ip:port/test1/test_table';

前提条件是可以访问远程数据库,配置好读写权限,mysql 开启 FEDERATED 引擎。
建完后本地数据与远程数据一样,进行 curd 操作都可同步。

既然通过 FEDERATED 可以将数据同步过来,那么可以在 B 中建立 A 的映射。
因为映射表在程序 C 中并没有实际意义,需要将映射表的某些字段与 B 实际业务表的数据进行同步,可以采用 程序进行操作 或者 利用触发器和存储过程。

触发器示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
drop TRIGGER updateFromFed; #删除触发器,建立后需要删除才能修改


delimiter $$ #修改语句结束标志为$$
create TRIGGER insertFromFederated AFTER INSERT
on federated_table for each ROW
begin #状态=1执行插入操作
DECLARE de VARCHAR(128);
set de = CONCAT(IFNULL(new.name,''),'-',IFNULL(new.age,''),'-',IFNULL(new.office,''));
if new.sts="1" THEN

INSERT into local1(id,name,description,sts)
values (new.id,new.name,de,new.sts);
INSERT into local2(id,name,office,sts)
values (new.id,de,new.office,new.sts);
END IF;
END $$
delimiter ;

参考:https://blog.csdn.net/qq_33556185/article/details/77745449

存储过程示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#mysql 下面的例子在把select into 的ID写死的时候设置参数值为空,但是在使用传进来的ID作为参数时设置参数值不为空。
show create procedure test;#查看
CALL test();#调用
drop procedure if exists test;#删除
in id VARCHAR(32)
delimiter $$
create PROCEDURE test()
begin
DECLARE id VARCHAR(32);
set id='8302';
DECLARE v_name VARCHAR(128)

SELECT local2.name INTO v_name from local2 where id = 5;
select id,v_name;
#INSERT into local2(id,name,office,sts) VALUES (id,des,'办公室','8');
end $$
delimiter ;

show engines;

参考:http://www.shouce.ren/api/view/a/11695

MySQL安装Federated引擎

Beginning with MySQL 5.0.64, the FEDERATED storage engine is not enabled by default in the running server; to enable FEDERATED, you must start the MySQL server binary using the –federated option.

从 mysql 官方文档可以看出, 从 5.0.64 以后 Federated 存储引擎默认不开启, 但我们需要使用的时候, 需要手动开启

mysql> show engines;

显示 FEDERATED 的 Support 为 NO 即没有安装

键入开始安装

mysql> install plugin federated soname 'ha_federated.so';

配置文件开启

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
vi /etc/my.cnf

#*******************************************************#
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
federated # 指定开启

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
#*******************************************************#

启动服务

mysqld --federated

重启服务

service mysqld restart

再查看服务是否开启

mysql> show engines;