fastadmin+xunsearch题库系统搭建教程

  • 前言
  • 一、开始整活
  • 二、开始搭建
    • 1.fastadmin配置
    • 2.xunsearch服务端安装
      • (一).openssl的版本与libevent版本不对应
        • 解决方案
    • 2.安装完成后配置
    • 3.数据库搭建
    • 4.fastadmin生成与代码修改
      • (一).fastadmin数据表、控制器、菜单创建与生成
      • (二).fastadmin控制器修改,调用api添加索引数据库
      • (三).接口搭建
      • (四).接口测试
        • 1.插入题目
        • 2.查询题目
  • 总结

前言

因为前段时间需要搭建一套题库系统,但是网上并没有很好的开源题库
机缘巧合之下,看到fastadmin整合的xunsearch插件(提供了很好的搜索引擎)
由此我决定尝试使用fastadmin来搭建一套题库系统,而且fastadmin便捷的api给了搜题系统很大的接口支持。可以很简单的写出需要的接口,还不用担心鉴权的问题(接口收费、接口鉴权等各种功能都很好写,都有对应的插件,简化接口搭建时间)

本文利用fastadmin后台框架 + xunsearch插件,快速搭建题库系统

一、开始整活

服务器使用的是腾讯云的99一年的服务器
本文搭建基于CentOS8.0(xunsearch服务器端必须使用linux系统,官网也是强烈推荐)
服务器环境使用宝塔搭建


提示:xunsearch服务端可以和题库系统分开部署在不同服务器上(作者并未尝试),有需求可以自己探究,本文仅展示fastadmin框架与xunsearch插件同时部署在一台服务器上。

二、开始搭建

宝塔与fastadmin的搭建就不再介绍了,这两个搭建很简单,网上都有教程。
fastadmin关于xunsearch文档的文档(你也可以根据此文档完成配置)

1.fastadmin配置

我们要将fastadmin插件市场中xunsearch插件安装进我们的框架

2.xunsearch服务端安装

离线安装:讯搜官网
在线安装(Linux系统下):

curl -O http://www.xunsearch.com/download/xunsearch-full-latest.tar.bz2
tar -xvf xunsearch-full-latest.tar.bz2

安装 1.4.15版本

cd xunsearch-full-1.4.15
sh setup.sh

接下来就是等待安装完成
安装出现的问题:

(一).openssl的版本与libevent版本不对应



在centos8中升级了openssl,导致xunseach内libevent版本对应不上导致报错

解决方案

手动替换libevent文件
下载libevent文件2.1.12版本(我替换了这个版本解决了这个问题,其他版本尚未确认)

wget https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz

将下载的文件打包

tar -zxvf libevent-2.1.12-stable.tar.gz

复制一份到xunsearch的packages文件夹内(删除旧版本的libevent)

cp libevent-2.1.12-stable.tar.bz2  packages/

替换后

这样重新安装就不会出现版本不一致导致libevent出现问题

2.安装完成后配置

启动服务
当安装完成Xunsearch后,我们可以通过以下命令进行启动服务

cd xunsearch-full-1.4.15
cd bin
./xs-ctl.sh start

启动完成后就可以和我们的fastadmin进行交互了(使用fastadmin默认配置即可)
接下来我们进入fastadmin添加一个项目

字段配置
必须要添加(id/title/body)这三个类型,不创建将导致配置生成失败

接下来我们生成一下配置

这时我们的题库已经搭建完成了,我们点击前台即可进入搜索页面.


但是这个时候我们的题库并没有数据,别着急请接着完成下面数据库的搭建!

3.数据库搭建

我们进入宝塔管理面板,去创建一个新的数据库

数据表创建与字段设置(请与上方fastadmin里xunsearch项目字段保持一致)

这时候请不要把题库导入该数据库

4.fastadmin生成与代码修改

(一).fastadmin数据表、控制器、菜单创建与生成

这时我们来到最后一步
用fastadmin中的在线命令管理(这个也是个插件,需要在插件市场安装后使用),生成该数据表的控制器


菜单创建

我们就可以看到菜单出现(如果没有多出一个菜单请刷新缓存)

我这个是修改过菜单名称的,初始名称并不是这样,不过这个并不重要
搭建到这个步骤可以看到使用这个菜单可以往数据库中加入数据,但是这样并不会往搜索引擎中加入索引数据

(二).fastadmin控制器修改,调用api添加索引数据库

以下内容使用到fastadmin的xunsearch文档中关于api的调用

我们打开宝塔,进入网站根目录,用默认的宝塔文件管理打开
目录为:/www/wwwroot/shouti/application/admin/controller/sou/Tiku.php
如果你一键生成的控制器不和我相同,那么最后文件目录也会有差异,这一步需要根据自己配置来找

打开后修改内容

默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改

我们可以在该文件中看到这个提示,根据提示,我们从[application/admin/library/traits/Backend.php]中找到添加、编辑、删除的代码

 /*** 添加*/public function add(){if ($this->request->isPost()) {$params = $this->request->post("row/a");if ($params) {$params = $this->preExcludeFields($params);if ($this->dataLimit && $this->dataLimitFieldAutoFill) {$params[$this->dataLimitField] = $this->auth->id;}$result = false;Db::startTrans();try {//是否采用模型验证if ($this->modelValidate) {$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;$this->model->validateFailException(true)->validate($validate);}$result = $this->model->allowField(true)->save($params);Db::commit();} catch (ValidateException $e) {Db::rollback();$this->error($e->getMessage());} catch (PDOException $e) {Db::rollback();$this->error($e->getMessage());} catch (Exception $e) {Db::rollback();$this->error($e->getMessage());}if ($result !== false) {$this->success();} else {$this->error(__('No rows were inserted'));}}$this->error(__('Parameter %s can not be empty', ''));}return $this->view->fetch();}/*** 编辑*/public function edit($ids = null){$row = $this->model->get($ids);if (!$row) {$this->error(__('No Results were found'));}$adminIds = $this->getDataLimitAdminIds();if (is_array($adminIds)) {if (!in_array($row[$this->dataLimitField], $adminIds)) {$this->error(__('You have no permission'));}}if ($this->request->isPost()) {$params = $this->request->post("row/a");if ($params) {$params = $this->preExcludeFields($params);$result = false;Db::startTrans();try {//是否采用模型验证if ($this->modelValidate) {$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;$row->validateFailException(true)->validate($validate);}$result = $row->allowField(true)->save($params);Db::commit();} catch (ValidateException $e) {Db::rollback();$this->error($e->getMessage());} catch (PDOException $e) {Db::rollback();$this->error($e->getMessage());} catch (Exception $e) {Db::rollback();$this->error($e->getMessage());}if ($result !== false) {$this->success();} else {$this->error(__('No rows were updated'));}}$this->error(__('Parameter %s can not be empty', ''));}$this->view->assign("row", $row);return $this->view->fetch();}/*** 删除*/public function del($ids = ""){if (!$this->request->isPost()) {$this->error(__("Invalid parameters"));}$ids = $ids ? $ids : $this->request->post("ids");if ($ids) {$pk = $this->model->getPk();$adminIds = $this->getDataLimitAdminIds();if (is_array($adminIds)) {$this->model->where($this->dataLimitField, 'in', $adminIds);}$list = $this->model->where($pk, 'in', $ids)->select();$count = 0;Db::startTrans();try {foreach ($list as $k => $v) {$count += $v->delete();}Db::commit();} catch (PDOException $e) {Db::rollback();$this->error($e->getMessage());} catch (Exception $e) {Db::rollback();$this->error($e->getMessage());}if ($count) {$this->success();} else {$this->error(__('No rows were deleted'));}}$this->error(__('Parameter %s can not be empty', 'ids'));}

我们将这段代码复制进刚刚打开的文件中

同时将这些方法根据fastadmin提供的api进行修改,达到添加xunsearch数据库索引的效果
添加修改后代码

/*** 添加*/public function add(){$search = \addons\xunsearch\library\Xunsearch::instance("souti");if ($this->request->isPost()) {$params = $this->request->post("row/a");if ($params) {$params = $this->preExcludeFields($params);if ($this->dataLimit && $this->dataLimitFieldAutoFill) {$params[$this->dataLimitField] = $this->auth->id;}$result = false;Db::startTrans();try {//是否采用模型验证if ($this->modelValidate) {$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;$this->model->validateFailException(true)->validate($validate);}$result = $this->model->allowField(true)->save($params);Db::commit();$lastid = Db::table('sou_tiku')->where('id>0')->max('id');$data = ['id'=>$lastid,'title'=>"[ID".$lastid."]:".$params['title'],'body'=>$params['body'],'ans'=> $params['ans']];$search->add($data);} catch (ValidateException $e) {Db::rollback();$this->error($e->getMessage());} catch (PDOException $e) {Db::rollback();$this->error($e->getMessage());} catch (Exception $e) {Db::rollback();$this->error($e->getMessage());}if ($result !== false) {$this->success();} else {$this->error(__('No rows were inserted'));}}$this->error(__('Parameter %s can not be empty', ''));}return $this->view->fetch();}

添加部分解析
我首先获取到最后一位id(添加进索引数据库必须拥有一个自己的id,通过id才可以修改此条题目状态),这个id我放到题目上,如果用户投诉答案出错,可以向开发者提供此题目id,开发者可以根据id快速定位该题目
然后接下来就是根据fastadmin写好的,获取每一条数据,根据fastadmin提供的api导入进索引数据库

$lastid = Db::table('sou_tiku')->where('id>0')->max('id');$data = ['id'=>$lastid,'title'=>"[ID".$lastid."]:".$params['title'],'body'=>$params['body'],'ans'=> $params['ans']];$search->add($data);

编辑修改后代码

/*** 编辑*/public function edit($ids = null){$search = \addons\xunsearch\library\Xunsearch::instance("souti");$row = $this->model->get($ids);if (!$row) {$this->error(__('No Results were found'));}$adminIds = $this->getDataLimitAdminIds();if (is_array($adminIds)) {if (!in_array($row[$this->dataLimitField], $adminIds)) {$this->error(__('You have no permission'));}}if ($this->request->isPost()) {$params = $this->request->post("row/a");if ($params) {$params = $this->preExcludeFields($params);$result = false;Db::startTrans();try {//是否采用模型验证if ($this->modelValidate) {$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;$row->validateFailException(true)->validate($validate);}$result = $row->allowField(true)->save($params);Db::commit();$data = ['id'=>$ids,'title'=>"[ID".$ids."]:".$params['title'],'body'=>$params['body'],'ans'=>$params['ans']];$search->update($data);} catch (ValidateException $e) {Db::rollback();$this->error($e->getMessage());} catch (PDOException $e) {Db::rollback();$this->error($e->getMessage());} catch (Exception $e) {Db::rollback();$this->error($e->getMessage());}if ($result !== false) {$this->success();} else {$this->error(__('No rows were updated'));}}$this->error(__('Parameter %s can not be empty', ''));}$this->view->assign("row", $row);return $this->view->fetch();}

编辑部分解析
编辑该数据的同时,我们将此次编辑也通过api进行修改到索引数据库

                 $data = ['id'=>$ids,'title'=>"[ID".$ids."]:".$params['title'],'body'=>$params['body'],'ans'=>$params['ans']];$search->update($data);

删除修改后代码

/*** 删除*/public function del($ids = ""){$search = \addons\xunsearch\library\Xunsearch::instance("souti");if (!$this->request->isPost()) {$this->error(__("Invalid parameters"));}$ids = $ids ? $ids : $this->request->post("ids");if ($ids) {$pk = $this->model->getPk();$adminIds = $this->getDataLimitAdminIds();if (is_array($adminIds)) {$this->model->where($this->dataLimitField, 'in', $adminIds);}$list = $this->model->where($pk, 'in', $ids)->select();$count = 0;Db::startTrans();try {foreach ($list as $k => $v) {$count += $v->delete();}Db::commit();$search->del($ids);} catch (PDOException $e) {Db::rollback();$this->error($e->getMessage());} catch (Exception $e) {Db::rollback();$this->error($e->getMessage());}if ($count) {$this->success();} else {$this->error(__('No rows were deleted'));}}$this->error(__('Parameter %s can not be empty', 'ids'));}

删除部分解析
这里是当数据表中数据删除的时候,我们也应该删除索引数据库里面的数据

$search->del($ids);

至此从fastadmin中添加/编辑/删除的操作,全部会同步到题库系统中.
重要提示:在fastadmin控制台只能一条一条的插入题库,因为导入的代码并未修改,所以导入进去的数据是无法查询的

这里id不一致是因为添加的时候id没有+1,上面代码未修改此问题,请自行修改[添加]部分代码.

(三).接口搭建

因为一个一个导入真的是太慢了.
我这边解决方案就是搭建一个接口,通过接口上传题目

我这边创建了一个新的接口,如果是小白,可以把接口搭建在demo中

同时将接口鉴权关闭
加入题目函数

public function insertans(){$search = \addons\xunsearch\library\Xunsearch::instance("souti");$title = $this->request->request('title');$body = $this->request->request('body');$ans = $this->request->request('ans');$lastid = Db::table('sou_tiku')->where('id>0')->max('id');$data = ['title' => $title, 'body' => $body , 'ans' => $ans];Db::startTrans();try {Db::table('sou_tiku')->insert($data);Db::commit();$sdata = ['id'=>$lastid,'title'=>"[ID".$lastid."]:".$title,'body'=>$body,'ans'=> $ans];$search->add($sdata);} catch (ValidateException $e) {Db::rollback();$this->error($e->getMessage());} catch (PDOException $e) {Db::rollback();$this->error($e->getMessage());} catch (Exception $e) {Db::rollback();$this->error($e->getMessage());}$this->success('返回成功',$res);//Db::table('sou_tiku')->insert($data);}

搜索题目返回函数

public function searchans(){$que = $this->request->request('q');$search = \addons\xunsearch\library\Xunsearch::instance("souti");$res = $search->search($que,1,10);$this->success('返回成功',$res); }

如果你实在不会写,请在该目录下创建sou.php
并加入以下代码

<?phpnamespace app\api\controller;use app\common\controller\Api;
use think\Db;
/*** 示例接口*/class Sou extends Api
{//如果$noNeedLogin为空表示所有接口都需要登录才能请求//如果$noNeedRight为空表示所有接口都需要验证权限才能请求//如果接口已经设置无需登录,那也就无需鉴权了//// 无需登录的接口,*表示全部protected $noNeedLogin = ['searchans','insertans'];// 无需鉴权的接口,*表示全部protected $noNeedRight = [];public function insertans(){$search = \addons\xunsearch\library\Xunsearch::instance("souti");$title = $this->request->request('title');$body = $this->request->request('body');$ans = $this->request->request('ans');$lastid = Db::table('sou_tiku')->where('id>0')->max('id');$data = ['title' => $title, 'body' => $body , 'ans' => $ans];Db::startTrans();try {Db::table('sou_tiku')->insert($data);Db::commit();$sdata = ['id'=>$lastid,'title'=>"[ID".$lastid."]:".$title,'body'=>$body,'ans'=> $ans];$search->add($sdata);} catch (ValidateException $e) {Db::rollback();$this->error($e->getMessage());} catch (PDOException $e) {Db::rollback();$this->error($e->getMessage());} catch (Exception $e) {Db::rollback();$this->error($e->getMessage());}$this->success('返回成功',$res);//Db::table('sou_tiku')->insert($data);}public function searchans(){$que = $this->request->request('q');$search = \addons\xunsearch\library\Xunsearch::instance("souti");$res = $search->search($que,1,10);$this->success('返回成功',$res); }
}

具体代码含义,请自行查询thinkphp

(四).接口测试

1.插入题目

调用网址:https://你的网站/api/sou/insertans?title=&body=&ans=
中文必须进行url编码,可以使用get或者post进行提交,title为题目,body为选项,ans为答案
具体字段可以自行修改

2.查询题目

调用网址:http://你的网站/api/sou/searchans?q="zg"
返回的是一段json代码,可以根据需求自己解析使用

总结

搭建比较繁琐,新手建议先看fastadmin官方给的教程,bilibili上也有的
小白请先看上面教程,不然会安装到你崩溃
看完前几集其实就差不多了,可以对比此教程看视频,学会控制器修改,api接口即可搭建
在thinkphp方面作者也是个小白,教程中一些地方写的并不是很标准,目的只是搭建能够查询的题库,更安全更标准的搭建方式,请自行探索

fastadmin+xunsearch题库系统搭建教程相关推荐

  1. 【搜题公众号】全网最详细搜题公众号搭建教程(附赠题库)

    上个文章反响很好,哈哈哈哈我来写一个搜题公众号搭建教程,这个适用于各位大学生创业引流使用,效果显著. 废话不多说开始我们的教程! 第一步: 注册公众号,这个百度搜索微信公众平台:微信公众平台 (qq. ...

  2. 公众号查题接口 搜题公众号 搭建教程 对接千万级别题库 不限次数接口

    今天给大家带来搜题公众号搭建教程(附赠搜题接口,接口后缀可自定义广告) 下面带大家搭建搜题公众号 教程开始,下面看我的操作 ①步骤一:进入注册公众号官网,(https://mp.weixin.qq.c ...

  3. 用 SpringBoot,亲自打造一个在线题库系统

    蓝桥云课新课<SpringBoot + ElasticSearch 打造在线题库系统>介绍: 本项目是一个基于 SpringBoot,Thymeleaf 和 ElasticSearch 开 ...

  4. 公众号网课查题-掘光者题库系统

    公众号网课查题-掘光者题库系统 本平台优点: 多题库查题.独立后台.响应速度快.全网平台可查.功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 题库:题库后台(点击跳转) 题库 ...

  5. 网课搜题API接口搭建教程

    网课搜题API接口搭建教程 本平台优点: 多题库查题.独立后台.响应速度快.全网平台可查.功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 查题校园题库:查题校园题库后台(点击 ...

  6. 公众号题库系统接口-网课答案解析接口

    公众号题库系统接口-网课答案解析接口 本平台优点: 多题库查题.独立后台.响应速度快.全网平台可查.功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 题库:题库后台(点击跳转) ...

  7. 网课答案题库系统 内含接口使用

    网课答案题库系统 内含接口使用 本平台优点: 多题库查题.独立后台.响应速度快.全网平台可查.功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 题库:题库后台(点击跳转) 题库 ...

  8. sap系统搭建教程_詹迟迟:如何搭建知识付费系统?知识付费系统搭建教程

    ​如何搭建知识付费系统? 知识付费一直很火爆,在这个不确定的时代,很多人已经明确知道,学习是终身的事情,也有人在说这只是在制造焦虑,但知识付费越来越火是个明确的事实. 这就有很多知识付费平台产生了,但 ...

  9. 探果(简称tamguo)是基于java开发的在线题库系统

    简介: 探果(简称tamguo)是基于java开发的在线题库系统 启动 tms 找到tamguo-tms下面的application.propertys. domain.name // 页面引用静态资 ...

最新文章

  1. acwing单源最短路的建图模式总结
  2. js 将时间戳转为日期格式
  3. windows 下终止指定端口的进程
  4. Why settype table is used in Genil component implementation
  5. php类使用自己的静态方法吗,php在类中使用静态方法有几种方式
  6. 【概率笔记】条件概率这样学才快啦
  7. EPS数据导入CASS中
  8. Mac部署Prometheus + Grafana监控
  9. 弹窗拦截小帮手------火绒
  10. 百度网盘助手-获取网盘文件的下载地址,破解限速
  11. app后端设计(3)--短信,邮件,推送服务(2014.12.05更新)
  12. springBoot打jar包遇到的麻烦
  13. 启用linux内核对usb摄像头的支持,linux利用USB摄像头
  14. 计算机职称考试在线软件,职称计算机考试模拟软件windowXP模块免费版
  15. 渗透测试——bluecms安装及seay代码审计
  16. 条件变量pthread_cond_t怎么用
  17. python应用之复习计划生成器
  18. 算法学习---关于哈密顿图的哈密顿通路求解问题
  19. Ubuntu 18.04上使用snort3搭建NIDS(二)| 配置篇
  20. ER/Studio-DM1转化sql语句 步骤

热门文章

  1. centOS 7 安装 CUPS 打印服务器,安装映美 FP-730K打印机共享
  2. 4.6Android灯光系统-背光灯
  3. 单片机用c语言开关点亮一盏灯,用PLC设计用一个开关控制8个灯,每5S逐个点亮,并循环...
  4. 小小军团获取服务器配置文件,小小军团2资源获得途径大全_宝石军团币荣誉币高级精华获取方法途径一览_3DM手游...
  5. 使用纵横网络QQ群成员提取器进行邮件群发
  6. Bingo说说:公众号+微信黄金搭档,造出你的个人品牌
  7. 程序坞如何在主屏幕和副屏幕中自由切换【Mac分屏】
  8. android高仿微信下拉有页面,Android——(仿微信聊天界面布局实例)
  9. 城市编码映射json格式
  10. 拼多多信誉度太低,怎么办?