Laravel 教程延伸 - 使用 textcomplete 标记用户 (支援中文)
实作了几次的 Laravel 教程后,该是导入一些功能的时候了
于是想练习一下标记用户的功能,网上搜寻了几个套件
发现 textcomplete 符合我的需求
请搭配第二本教程使用 《L02 Laravel 进阶课程 - 从零开始构建论坛系统》
准备
首先下载套件 : textcomplete
我们只需要用到
- jquery.overlay.min.js
- jquery.textcomplete.min.js
- jquery.textcomplete.css
这三个档案,我将套件放在 assets 的 textcomplete 目录内
动手做
赋予 textarea 一个 id : reply_box
以便操作
resources/views\topics_reply_box.blade.php
.
.
.
<div class="form-group">
<textarea class="form-control" rows="3" placeholder="分享你的想法" name="content" id="reply_box"></textarea>
</div>
.
.
.
然后引入资源档案及操作
触发条件为 : 空一格后输入@及字触发搜寻
resources/views/topics/show.blade.php
.
.
.
@section('styles')
<link rel=stylesheet type="text/css" href="{{asset('assets/textcomplete/jquery.textcomplete.css')}}">
@stop
@section('scripts')
<script src="{{asset('assets/textcomplete/jquery.textcomplete.min.js')}}"></script>
<script src="{{asset('assets/textcomplete/jquery.overlay.min.js')}}"></script>
<script>
$('#reply_box').textcomplete([
{
id: 'reply_box',
match: /\B@([\u4e00-\u9fa5a-zA-Z0-9]+)$/,
search: function (term, callback) {
$.ajax({
url: '{{route('users.json')}}',
type: 'post',
data: {
searchkey : term,
text : $('textarea[name="content"]').val(),
},
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
dataType: 'json',
success: function (r) {
callback($.map(r , function (v, i) {
return (v.name.toLowerCase().indexOf(term.toLowerCase()) >= 0 ) ? v : null;
}));
},
error: function (r) {
},
});
},
template: function (value) {
return '<img style="margin-right:0.7em" width="30" height="30" src="'+value.picture+'"></img>' + value.name;
},
replace: function (value, term) {
return '['+value.id+':'+value.name+'] ';
},
context : function(value) {
return value;
},
index: 1,
},
], {
onKeydown: function (e, commands) {
if (e.ctrlKey && e.keyCode === 74) {
return commands.KEY_ENTER;
}
}
}, {appendTo: 'body'}).overlay([
{
match: /(\[{1}[0-9]+:{1}[^\[\]:]+\]{1})/g,
css: {
'background-color': '#d8dfea'
}
}
]);
</script>
@stop
接着新增一个路由接收这个请求
web.php
.
.
.
Route::post('usersjson','UsersController@usersjson')->name('users.json');
轮到控制器了,新增一个方法来搜寻用户
app/Http/Controllers/UsersController.php
.
.
.
public function usersjson(Request $request)
{
$searchkey = $request->searchkey;
$text = $request->text;
if(trim($searchkey)) {
$object_user = [];
// 略过已被tag的id
preg_match_all("/\[(.+?)\]/", $text, $match);
$listedId = array_map(function($v){
return substr($v, 0, strpos($v, ':'));
}, $match[1]);
// 略过本人
$listedId[] = Auth::user()->id;
$users_id = User::where('name', 'like', "%" . $searchkey . "%")->pluck('id')->toArray();
$listIds = array_diff($users_id, $listedId);
// 送给前端选单的用户清单
if($listIds) {
$users = User::whereIn('id', $listIds)->get(['id', 'name', 'avatar']);
foreach ($users as $user) {
$object_user[] = [
'id' => $user['id'],
'name' => $user['name'],
'picture' => $user['avatar'],
];
}
}
return response()->json($object_user);
}
}
至此,在回复栏位应该可以出现相关条件下拉选单了。
您会发现标记后,在输入框内的格式为 : [id:name]
这是我设计用来辨识已被 Tag 的人员用的,如果各位有其他方式欢迎留言给我
优化
接着我们希望可以在回复清单上连结至被标记人名的个人页面
我们必须先对取出来的内容做处理
新增一个处理连结的函式
bootstrap/helpers.php
.
.
.
function make_mention_link($mention) {
preg_match_all("/\[(.+?)\]/", $mention, $match);
if($match[1]) {
foreach ($match[1] as $k0 => $v0) {
// 用户 id
$mentionUserId = substr($v0, 0, strpos($v0, ':'));
// 用户名稱
$mentionUserName = substr($v0, strpos($v0, ':')+1, strlen($v0));
// 组出连结
$replace = '<span class="mention"><a target="_blank" href="'.route('users.show', [$mentionUserId]).'">'.$mentionUserName.'</a></span>';
$mention = str_replace($match[0][$k0], $replace, $mention);
}
}
return $mention;
}
resources/views/topics/_reply_list.blade.php
.
.
.
<div class="reply-content">
{!! make_mention_link($reply->content) !!}
</div>
.
.
.
这样便可以连结至该人的个人页面。
下一个目标是送出评论后,可以通知被标记的人。
还有许多不足之处,如果有建议或指教,请您一定要留言给我让我学习,
谢谢大家了。
本作品采用《CC 协议》,转载必须注明作者和本文链接
这样是不是好一点
@doobi 好方法,学习了。