[关闭]
@jtahstu 2016-10-26T14:39:17.000000Z 字数 19472 阅读 2797

iTool 说明文档

注意:本文不讲解php、css、js等语言的语法,不讲解laravel框架的用法,不讲解代码运行的机制,只是讲解网站的架构、功能和设计等。作者认为这些代码你都是看得懂和会写的。

一、iTool功能图和页面组成结构

手稿
手稿

iTool功能图
iTool功能图

iTool页面组成结构
iTool页面组成结构

二、从页面视图说开去

可能一般应该从路由开始说起,然后到控制器,然后到视图,这是这个网站运行的顺序。但如果这样说的话,显然不够形象,难于理解。

那么我们从每一个页面来说,或者从每一个部分来说,相信你能很快上手,如果你依然很难与理解这个网站的架构,那么好好去看看 Laravel文档 吧。

或许你应该先用Laravel开发一个网站后,这样会更容易理解这种模式。

2.1、头部

ok,看了上面的图,如果你经验丰富,肯定已经一眼看穿,“哦,原来这个网站这么简单”,那么下面的东西你基本可以跳过了。如果你只是个小白,好好学习,天天向上。

第一,我们从页面的最开始,头部开始说

  1. <meta charset="UTF-8" />
  2. <title>{!! htmlspecialchars_decode($config['title']) !!} </title>
  3. <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" />
  4. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  5. <meta name="Keywords" content="{!! htmlspecialchars_decode($config['keyword']) !!}" />
  6. <meta name="Description" content="{!! htmlspecialchars_decode($config['des']) !!}" />
  7. <meta name="author" content="jtahstu" />
  8. <link rel="icon" href="{!! htmlspecialchars_decode($config['icon']) !!}" />
  9. <link href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
  10. <link rel="stylesheet" type="text/css" href="{{asset('public/css/header.css')}}" />
  11. <link rel="stylesheet" type="text/css" href="{{asset('public/css/tool.css')}}" />
  12. <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  13. <script src="{{asset('public/js/tool.js')}}"></script>
  14. {!! htmlspecialchars_decode($config['headAddCode']) !!}
  15. {{--注意这里只要有html标签的,请一定要使用上面的写法,不要用{{}}或不解码,原因嘛,你懂的. --}}

上面这段就会生成下面的页面代码

  1. <title>iTool - 代码编辑神器 </title>
  2. <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" />
  3. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  4. <meta name="Keywords" content="itool,在线代码编辑器,在线运行,在线编译,ischool,jtahstu,666啊" />
  5. <meta name="Description" content="这么叼?我都不知道呢。" />
  6. <meta name="author" content="jtahstu" />
  7. <link rel="icon" href="http://cdn.jtahstu.com/editor.ico" />
  8. <link href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
  9. <link rel="stylesheet" type="text/css" href="http://tool.usta.wiki/public/css/header.css" />
  10. <link rel="stylesheet" type="text/css" href="http://tool.usta.wiki/public/css/tool.css" />
  11. <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  12. <script src="http://tool.usta.wiki/public/js/tool.js"></script>

采用Blade模板引擎的语法,生成链接和载入变量值

注意:这里配置里包含有html或js代码的,显示时需要特殊字符解码

因为在配置提交时,会进行html特殊字符编码,然后保存到数据库中,以防止一些sql注入攻击,所以在从数据库中拿出来时需要解码,这个请参考2.8、后台管理的代码说明

需要什么:$config,即网站的配置数组

从哪来:控制器返回视图时带来的,也就是从数据库中读出来的

干什么:当然是显示喽,视图不就是呈现的嘛

2.2、导航栏

2.2.1、电脑浏览器显示的导航栏

该导航栏使用的是网上仿阿里云前下拉模式导航栏,目前阿里云导航栏已改版,效果看上去还是过得去的。

需要什么:分页对象,即$shareList= DB::table('tool_share')->paginate($paginateCount)

从哪来:控制器以参数形式传入

干什么:以判断导航栏需要显示几个第多少多少页。

2.2.2、移动端显示的导航栏

该导航栏使用的是Bootstrap的原生导航栏,由于其框架的适应性,在移动端显示体验还是可以的。

2.3、脚部

脚部也是有两种的,移动端访问就只有脚部声明,显示会相当简洁。

  1. <footer id="footer">
  2. <div class="container" id="footer-main">
  3. <div class="col-md-4">
  4. ……
  5. </div>
  6. <div class="col-md-4">
  7. <div id="footer-3" class="layer">
  8. <h2>社交账号</h2>
  9. <img src="{{asset('public/img/qq.jpg')}}"/>
  10. <img src="{{asset('public/img/weixin.jpg')}}"/>
  11. <h2><a href="{{URL::to('/login')}}" target="_blank">
  12. su - root
  13. </a></h2>
  14. </div>
  15. </div>
  16. </div>
  17. <div class="col-md-12 center" id="footer-state">
  18. <p>
  19. iTool &copy;
  20. <?php echo date('Y'); ?>
  21. . {!! htmlspecialchars_decode($config['footCopy']) !!}
  22. </p>
  23. </div>
  24. </footer>
  25. <script src="{{asset('public/js/layer.js')}}"></script>
  26. <script>
  27. $(function() {
  28. layer.ready(function() {
  29. //使用相册
  30. layer.photos({
  31. photos: '.layer'
  32. });
  33. });
  34. });
  35. </script>
  36. <!--统计代码-->
  37. {!! htmlspecialchars_decode($config['cnzz']) !!}
  38. <?php
  39. if(isset($_GET['user'])||isset($_GET['page']))
  40. $jumpLink=Request::getRequestUri().'&m=m';
  41. else
  42. $jumpLink=Request::getRequestUri().'?m=m';
  43. ?>
  44. <script src="http://siteapp.baidu.com/static/webappservice/uaredirect.js" type="text/javascript"></script>
  45. <script type="text/javascript">uaredirect("{!! $jumpLink !!}");</script>
  46. {{-- 判断移动端访问 --}}

2.3.1、脚部分为三个部分

2.3.2、脚部客户端类型验证

  1. <?php
  2. if(isset($_GET['user'])||isset($_GET['page']))
  3. $jumpLink=Request::getRequestUri().'&m=m';
  4. else
  5. $jumpLink=Request::getRequestUri().'?m=m';
  6. ?>
  7. <script src="http://siteapp.baidu.com/static/webappservice/uaredirect.js" type="text/javascript"></script>
  8. <script type="text/javascript">uaredirect("{!! $jumpLink !!}");</script>
  9. {{-- 判断移动端访问 --}}

由于js加载应该放在网页的最后,又由于每个页面都要判断,所以验证就放在了脚部里。

实际上是放头部Request::getRequestUri()会运行不正常,不用太在意,放这里是对的。

js实现客户端的类型判断,如果是移动端则跳转到当前链接并添加标记m=m,说明是移动端访问,此标记用与页面显示时到底是加载移动端的头部和脚部,还是加载正常的浏览器头部和脚部。

由于管理后台和分页时链接中已经有变量了,所以需要判断一下,一个是?一个是&

注意:在一开始访问网站的页面时是不带m=m标记的,验证如果是移动端访问,则会刷新页面,也就是说,移动端访问会加载两次页面。

页面中的判断代码

  1. @if(isset($_GET['m']))
  2. @include('Mobile.header')
  3. @else
  4. @include('Compile.header')
  5. @endif
  6. @if(isset($_GET['m']))
  7. @include('Mobile.footer')
  8. @else
  9. @include('Compile.footer')
  10. @endif

其中,脚部使用了

  1. layer.ready(function() {
  2. //使用相册
  3. layer.photos({
  4. photos: '.layer'
  5. });
  6. });

后两个功能是先写好的,调用是在配置项中脚部的站点声明中。

2.4、首页

前面介绍了头部、导航栏和脚部,你会发现每个页面都有这三个部分,在结构图里也能轻易的看出来,每个页面不同的仅仅是中间的那一部分。

2.4.1、图标

首页的中间部分是网上借鉴的,改了文字和图标,图标采用的是阿里矢量图标库www.iconfont.cn里的图标

这里可不是使用的图片,有好多人都问我你这用的图片吧,this is 矢量图

CDN加载css文件

  1. <link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_1475409244_4673653.css" />

代码中引用

  1. <i class="icon iconfont">&#xe609;</i>

就是这么简单,这个图标的写法有好几种,自己去阿里矢量图标库看看吧

目前这个项目的所有图标有
iTool首页图标

如果你也需要,直接加载css,然后调用即可,简单、方便、快速

2.4.2、网页弹幕

网页弹幕使用的是barrager.js插件,Github地址:https://github.com/yaseng/jquery.barrager.js

或者参考这篇文章和演示 jquery.barrager.js专业的网页弹幕插件

  1. <script src=" http://cdn.jtahstu.com/jquery.barrager.min.js"></script>
  2. var item = {
  3. img: "{{$config['indexBarragerImg']}}", //图片
  4. info: "{{$config['indexBarragerInfo']}}", //文字
  5. href: "{{$config['indexBarragerLink']}}", //链接
  6. speed: 6, //延迟,单位秒,默认6
  7. // bottom:70, //距离底部高度,单位px,默认随机
  8. color: '#fff', //颜色,默认白色
  9. old_ie_color: '#000000', //ie低版兼容色,不能与网页背景相同,默认黑色
  10. }
  11. $('body').barrager(item);

本人这里也就是用到了一些基本的功能,这里的文字,图片地址和链接采用的是配置项,方便以后的修改。

2.4.3、通知提示框

该通知提示框采用的是overhang.js插件,Github地址:https://github.com/paulkr/overhang.js

你也可以参考这篇文章和演示 jQuery通知提示插件overhang.js

  1. <script type="text/javascript" src="http://tool.usta.wiki/public/js/overhang.min.js"></script>
  1. $('body').overhang({
  2. type: 'success',
  3. message: "{{$config['indexMessage']}}",
  4. duration: 5,
  5. upper: true,
  6. });

2.4.4、首页控制器代码

  1. /*
  2. * 路由过来的/
  3. * 功能:处理首页显示
  4. * 返回:首页视图
  5. */
  6. function index(){
  7. $sharePaginate=$this->getSharePaginate();
  8. return view('Compile/index',['config'=>$this->getConfig(),'sharePaginate'=>$sharePaginate]);
  9. }

这里所带的两个参数,在每个视图里都得有,一个是整个网站的配置项,一个是导航栏的分页对象

2.5、代码编辑页

这个页面包括,上半部分的代码编辑器和下半部分的结果显示域

2.5.1、代码编辑页控制器代码

  1. /*
  2. * 路由过来的/compile/{id},由该函数处理
  3. * 功能:处理显示编辑器页面所需的数据
  4. * 1、动态生成生成代码模板
  5. * 2、这里对第二种,即html/css/js特殊处理,因为该视图处理方式不同于其他页面
  6. * 返回:代码编辑视图
  7. */
  8. function solve($id){
  9. $sharePaginate=$this->getSharePaginate();
  10. $lang=$this->getLanguage($id);
  11. $template=$this->getTemplate($id);
  12. $realTemplate=str_replace('{{date}}',date('Y年m月d日 H:i:s'),$template[0]->template);
  13. $realTemplate=str_replace('{{year}}',date('Y'),$realTemplate);
  14. if($id=='2'){
  15. return view('Compile/html',['config'=>$this->getConfig(),'sharePaginate'=>$sharePaginate,'value'=>$lang[0]->value,'lang'=>$lang[0]->language,'mode'=>$lang[0]->mode,'template'=>$realTemplate]);
  16. }else{
  17. return view('Compile/editor',['config'=>$this->getConfig(),'sharePaginate'=>$sharePaginate,'value'=>$lang[0]->value,'lang'=>$lang[0]->language,'mode'=>$lang[0]->mode,'template'=>$realTemplate]);
  18. }
  19. }
  20. //根据id获取语言
  21. function getLanguage($id){
  22. $language = DB::select('select * from tool_lang where id = ?', [$id]);
  23. return $language;
  24. }
  25. //获取各语言的默认模板
  26. function getTemplate($id){
  27. $template = DB::select('select * from tool_temp where id = ?',[$id]);
  28. return $template;
  29. }

2.5.2、16种编程语言的模板页

这里16种编程语言(除html/css/js)的页面都是采用的这一模板,依据不同的链接,加载不同的语言模块和代码模板

  1. <div class="container">
  2. <div id="compile-lang" align="center">
  3. {{$config['editorTitle']}}
  4. <span id=""> @yield('lang') </span>
  5. <button type="button" class="btn btn-success col-md-offset-2" id="compile-run">
  6. <i class="glyphicon glyphicon-play"></i>&nbsp;运行
  7. </button>
  8. <button type="button" class="btn btn-info" id="compile-share">
  9. <i class="glyphicon glyphicon-share"></i>&nbsp;分享
  10. </button>
  11. <button type="button" class="btn btn-success" id="compile-share-again">
  12. <i class="glyphicon glyphicon-share"></i>&nbsp;确认分享
  13. </button>
  14. </div>
  15. <div class="col-md-8 col-md-offset-2" id="compile-share-title">
  16. <input type="text" class="form-control" id="compile-share-title-input" placeholder="请输入标题...">
  17. </div>
  18. <div class="" id="compile-editor-div">
  19. <div id="compile-editor" name="" class=" form-control">@yield('content')</div>
  20. </div>
  21. <div id="tishi"></div>
  22. <div class="">
  23. <textarea name="" id="compile-output" class="form-control"></textarea>
  24. </div>
  25. </div>
  1. <?php
  2. if (isset($_GET['h'])) $editorHeight = $_GET['h'];
  3. else $editorHeight = $config['editorHeight'];
  4. ?>
  5. $('#compile-editor').height(<?php echo $editorHeight; ?>);
  6. require("ace/ext/old_ie");
  7. ace.require("ace/ext/language_tools");
  8. var editor = ace.edit("compile-editor");
  9. editor.$blockScrolling = Infinity;
  10. editor.setFontSize(14);
  11. editor.session.setMode("ace/mode/@yield('mode')");
  12. editor.setOptions({
  13. enableBasicAutocompletion: true,
  14. enableSnippets: true,
  15. enableLiveAutocompletion: true
  16. });
  17. //editor.setShowInvisibles(true);
  18. editor.setTheme("ace/theme/{{$config['editorTheme']}}");

有关于ace.js的用法,请参考本人写的另一篇wiki ACE Editor接入指南

js代码中采用配置项,设置编辑器高度,主题等

2.5.2、HTML/CSS/JS的模板页

该页面需要独立出来,是因为代码运行机制不同

其他部分都是一样的,所以如果你要改页面,两个都要一起改,别忘了

  1. function show() {
  2. code = editor.getValue();
  3. testwin = open("", "testwin", "status=no,menubar=yes,toolbar=no");
  4. testwin.document.open();
  5. testwin.document.write(code);
  6. testwin.document.close();
  7. }

点击运行按钮,触发事件,获取到编辑器的代码,新打开个页面,把代码加进去即可显示运行

2.5.3、运行

点击右上角的运行按钮时,会触发.click()事件,发送ajax请求给控制器

  1. $("#compile-run").click(function() {
  2. layer.ready(function() {
  3. layer.msg("玩命运行中 <(^-^)>");
  4. });
  5. $("#compile-output").val('程序正在提交...');
  6. var code = editor.getValue();
  7. var value = @yield('value');
  8. $.ajax({
  9. type: "post",
  10. url: "{{URL::to('compiles')}}",
  11. data: {
  12. 'code': code,
  13. 'language': value
  14. },
  15. dataType: 'json',
  16. success: function(msg) {
  17. layer.ready(function() {
  18. layer.msg("结果出来啦 (*^-^*)");
  19. });
  20. $("#compile-output").val(msg);
  21. },
  22. error:function(){
  23. layer.ready(function() {
  24. layer.msg("运行发生错误 ╭∩╮(︶︿︶)╭∩╮");
  25. });
  26. }
  27. });
  28. });

把代码发送给控制器,控制器获得代码返回执行结果,然后显示在结果域中

中间会有个layer.js的弹出层提示,一般像下面这样使用

  1. <script src="http://tool.usta.wiki/public/js/layer.js"></script>
  2. layer.ready(function() {
  3. layer.msg("玩命运行中 <(^-^)>");
  4. });

该插件官网地址:layer官方演示与讲解(jQuery弹出层插件)

2.5.4、分享代码

代码分享前需要补全标题,这里使用的jquery show()和hide()方法,分享成功后异步显示分享链接

  1. $("#compile-share-title").hide();
  2. $("#compile-share-again").hide();
  3. $("#compile-share").click(function(){
  4. $("#compile-share").hide('2000');
  5. $("#compile-share-again").show('4000');
  6. $("#compile-share-title").show('4000');
  7. });
  8. $("#compile-share-again").click(function() {
  9. var title=$("#compile-share-title-input").val();
  10. // alert(title);
  11. var code = editor.getValue();
  12. var value = @yield('value');
  13. $.ajax({
  14. type: "post",
  15. url: "{{URL::to('share')}}",
  16. data: {
  17. 'title':title,
  18. 'code': code,
  19. 'value': value
  20. },
  21. dataType: 'json',
  22. success: function(msg) {
  23. layer.ready(function() {
  24. layer.msg("分享成功,赶紧复制链接分享给你的小伙伴吧 (*^-^*)");
  25. });
  26. $("#tishi").html("<div class='alert alert-success' style='text-align: center;margin-top: 10px;'>分享成功,链接为 <b>{{URL::to('share')}}/" + msg + "</b></div>");
  27. },
  28. error:function(){
  29. layer.ready(function() {
  30. layer.msg("啊哦,分享失败了,再试一次吧 (*^-^*)");
  31. });
  32. }
  33. });
  34. });

2.5.5、分享代码时的控制器代码

  1. /*
  2. * 路由post过来的/share,由该函数处理
  3. * 功能:当ajax请求分享代码时,我们需要存储代码到数据库中,并补全其他相关信息
  4. * 并返回分享的linkid,由前端js补全完整的链接
  5. * 返回:ajax代码分享的链接linkid
  6. */
  7. function share(Request $request){
  8. $data=Input::all();
  9. $config=$this->getConfig();
  10. $defaultTitle=$config['defaultTitle'];
  11. $title=trim($data['title'])==""?$defaultTitle:trim($data['title']);
  12. $code=$data['code'];
  13. $value=$data['value'];
  14. $linkid=$this->getShareCount()+1;
  15. $time=date('Y-m-d H:i:s');
  16. $res=$this->saveShareCode($linkid,$title,$code,$value,$time);
  17. if($res){
  18. echo json_encode($linkid);
  19. }else{
  20. echo json_encode('errors');
  21. }
  22. }
  23. //获取数据库中已经存储有多少分享代码了
  24. function getShareCount(){
  25. $count=DB::select('select count(id) as count from tool_share');
  26. return $count[0]->count;
  27. }
  28. //保存分享的代码
  29. function saveShareCode($linkid,$title,$code,$value,$time){
  30. $res=DB::insert("insert into tool_share(id,linkid,title,code,value,time,view) values('',?,?,?,?,?,0)",[$linkid,$title,$code,$value,$time]);
  31. return $res;
  32. }

2.6、代码分享页、代码归档页、讨论交流页

如果你看懂了前面介绍的首页和代码编辑页,这些页面对你也就不成问题了

一个页面包含头部、导航栏和脚部这三个固定的部分,不同的只是中间部分的代码

2.7、后台登录页

后台登录页有头部,但是没有之前页面的导航栏和脚部,所以只需要传入一个配置项即可,不需要分页对象

这里也没有真正的用户登录,只是在链接中加入明文的root和MD5加密的密码值,由后台页面去判断该密码是否正确

  1. <dl class="admin_login">
  2. <dt>
  3. <strong>iTool管理系统</strong>
  4. <em>iTool Management System</em>
  5. </dt>
  6. <dd class="user_icon">
  7. <input placeholder="账号" class="login_txtbx" type="text" id="name">
  8. </dd>
  9. <dd class="pwd_icon">
  10. <input placeholder="密码" class="login_txtbx" type="password" id="pass">
  11. </dd>
  12. <dd>
  13. <input value="立即登陆" class="submit_btn" type="button" id="login">
  14. </dd>
  15. </dl>
  16. <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  17. <script src="http://tool.usta.wiki/public/js/jQuery.md5.js"></script>
  18. <script>
  19. $(document).ready(function() {
  20. $('#login').click(function(){
  21. var name=$('#name').val();
  22. var pass=$('#pass').val();
  23. window.location.href='{{URL::to('/admin')}}?user=root&pass='+$.md5(pass);
  24. });
  25. });
  26. </script>

后台验证代码

  1. <?php
  2. if(isset($_GET['user'])&&isset($_GET['pass'])){
  3. $passMD5=$_GET['pass'];
  4. if($passMD5!=md5('你要设置的密码')){
  5. header("Location:URL::to('/login')");
  6. exit;
  7. }
  8. }else{
  9. header("Location:URL::to('/login')");
  10. exit;
  11. }
  12. ?>

因为这个只是给自己用的,就不写登录的模块了,省事。

2.8、管理后台

后台采用的是Bootstrap Affix插件来写的页面

显示所有的配置选项,然后把当前的配置加载进去,当要修改配置时,使用ajax的方式提交修改

由于Bootstrap页面缓存的问题,修改完成之后页面可能是不变的,所以需要重新打开这个页面,不是刷新哦

举一个例子来说,其他的代码省略了,如全局配置的设置
html代码

  1. <div class="col-sm-10" id="admin-section">
  2. <h2 id="section-1">全局配置</h2>
  3. <div id="admin-global">
  4. <div class="form-horizontal" role="form">
  5. <div class="form-group">
  6. <label for="" class="col-sm-2 control-label">网站标题:</label>
  7. <div class="col-sm-10">
  8. <input type="text" class="form-control" id="admin-global-title" value="{{$config['title']}}">
  9. </div>
  10. </div>
  11. <div class="form-group">
  12. <label for="" class="col-sm-2 control-label">网站关键词:</label>
  13. <div class="col-sm-10">
  14. <input type="text" class="form-control" id="admin-global-key" value="{{$config['keyword']}}">
  15. </div>
  16. </div>
  17. <div class="form-group">
  18. <label for="" class="col-sm-2 control-label">网站介绍:</label>
  19. <div class="col-sm-10">
  20. <input type="text" class="form-control" id="admin-global-des" value="{{$config['des']}}">
  21. </div>
  22. </div>
  23. <div class="form-group">
  24. <label for="" class="col-sm-2 control-label">网站图标:</label>
  25. <div class="col-sm-10">
  26. <input type="text" class="form-control" id="admin-global-icon" value="{{$config['icon']}}">
  27. </div>
  28. </div>
  29. <div class="form-group">
  30. <label for="" class="col-sm-2 control-label">当前版本:</label>
  31. <div class="col-sm-10">
  32. <input type="text" class="form-control" id="admin-global-version" value="{{$config['version']}}">
  33. </div>
  34. </div>
  35. <div class="form-group">
  36. <label for="" class="col-sm-2 control-label">统计代码:</label>
  37. <div class="col-sm-10">
  38. <textarea class="form-control" rows="3" id="admin-global-cnzz">{{$config['cnzz']}}</textarea>
  39. </div>
  40. </div>
  41. <div class="form-group">
  42. <label for="" class="col-sm-2 control-label">添加头部代码:</label>
  43. <div class="col-sm-10">
  44. <textarea class="form-control" rows="3" id="admin-global-headAddCode">{{$config['headAddCode']}}</textarea>
  45. </div>
  46. </div>
  47. <div class="form-group">
  48. <div class="col-sm-offset-2 col-sm-10">
  49. <button type="submit" class="btn btn-success" id="admin-global-submit">
  50. <i class="glyphicon glyphicon-ok"></i> 确认修改
  51. </button>
  52. </div>
  53. </div>
  54. </div>
  55. </div>
  56. </div>

ajax代码

  1. $('#admin-global-submit').click(function() {
  2. var title = $('#admin-global-title').val();
  3. var key = $('#admin-global-key').val();
  4. var des = $('#admin-global-des').val();
  5. var icon = $('#admin-global-icon').val();
  6. var version = $('#admin-global-version').val();
  7. var cnzz = $('#admin-global-cnzz').val();
  8. var headAddCode = $('#admin-global-headAddCode').val();
  9. // alert(title + '\n' + key);
  10. $.ajax({
  11. type: "post",
  12. url: "{{URL::to('/admin/global')}}",
  13. data: {
  14. 'title': title,
  15. 'key': key,
  16. 'des': des,
  17. 'icon': icon,
  18. 'version': version,
  19. 'cnzz': cnzz,
  20. 'headAddCode': headAddCode
  21. },
  22. success: function(msg) {
  23. var prompt=(msg=='1')?'修改成功 (*^-^*)':'修改失败 ○| ̄|_';
  24. layer.ready(function() {
  25. layer.msg(prompt);
  26. });
  27. }
  28. });
  29. });

php代码

  1. /*
  2. * 路由post过来的/admin/{func}
  3. * 返回:ajax网站配置数据是否修改成功
  4. */
  5. function adminFunction($func){
  6. $data=Input::all();
  7. if($func=='global'){
  8. $title=htmlentities($data['title']);
  9. $key=htmlentities($data['key']);
  10. $des=htmlentities($data['des']);
  11. $icon=htmlentities($data['icon']);
  12. $version=htmlentities($data['version']);
  13. $cnzz=htmlentities($data['cnzz']);
  14. $headAddCode=htmlentities($data['headAddCode']);
  15. $res=$this->setConfigGlobal($title,$key,$des,$icon,$version,$cnzz,$headAddCode);
  16. echo $res?'1':'0';
  17. }
  18. }
  19. function setConfigGlobal($title,$key,$des,$icon,$version,$cnzz,$headAddCode){
  20. $res1=DB::table('tool_config')->where('k', 'title')->update(['value' => $title]);
  21. $res2=DB::table('tool_config')->where('k', 'keyword')->update(['value' => $key]);
  22. $res3=DB::table('tool_config')->where('k', 'des')->update(['value' => $des]);
  23. $res4=DB::table('tool_config')->where('k', 'icon')->update(['value' => $icon]);
  24. $res5=DB::table('tool_config')->where('k', 'version')->update(['value' => $version]);
  25. $res6=DB::table('tool_config')->where('k', 'cnzz')->update(['value' => $cnzz]);
  26. $res7=DB::table('tool_config')->where('k', 'headAddCode')->update(['value' => $headAddCode]);
  27. return $res1||$res2||$res3||$res4||$res5||$res6||$res7;
  28. }

当接收post过来的配置项,在把代码存入数据库之前,会进行htmlentities特殊字符编码,以防止注入攻击
所以在视图加载配置时,但凡有html或js或者其他的有特殊字符的代码时,我们都需要解码
而且不要用{{...}},这个是默认使用htmlentities特殊字符编码的,我们使用{!!...!!}的方式
例如 {!! htmlspecialchars_decode($config['title']) !!}

三、路由

  1. <?php
  2. //show home page
  3. Route::get('/','CompileController@index');
  4. //show editor view
  5. Route::get('/compile/{id}','CompileController@solve');
  6. //run and share
  7. Route::post('/compiles','CompileController@result');
  8. Route::post('/share','CompileController@share');
  9. //show share code view
  10. Route::get('/share/{linkid}','CompileController@showShare');
  11. //show code archive
  12. Route::get('/share','CompileController@shareList');
  13. //show discuss view
  14. Route::get('/discuss','ToolController@discuss');
  15. //show login view
  16. Route::get('/login','ToolController@login');
  17. //show admin view
  18. Route::get('/admin','ToolController@admin');
  19. //admin ajax
  20. Route::post('/admin/{func}','ToolController@adminFunction');

四、数据库

MySQL数据库表结构
数据库表结构

  1. SET FOREIGN_KEY_CHECKS=0;
  2. -- ----------------------------
  3. -- Table structure for tool_code
  4. -- ----------------------------
  5. DROP TABLE IF EXISTS `tool_code`;
  6. CREATE TABLE `tool_code` (
  7. `id` int(11) NOT NULL AUTO_INCREMENT,
  8. `code` text,
  9. `type` int(11) DEFAULT NULL,
  10. `time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  11. PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB AUTO_INCREMENT=93 DEFAULT CHARSET=utf8;
  13. -- ----------------------------
  14. -- Table structure for tool_config
  15. -- ----------------------------
  16. DROP TABLE IF EXISTS `tool_config`;
  17. CREATE TABLE `tool_config` (
  18. `k` varchar(255) DEFAULT NULL,
  19. `value` varchar(1023) DEFAULT NULL
  20. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  21. -- ----------------------------
  22. -- Table structure for tool_lang
  23. -- ----------------------------
  24. DROP TABLE IF EXISTS `tool_lang`;
  25. CREATE TABLE `tool_lang` (
  26. `id` int(11) NOT NULL,
  27. `language` varchar(255) DEFAULT NULL,
  28. `value` int(11) DEFAULT NULL,
  29. `mode` varchar(255) DEFAULT NULL,
  30. PRIMARY KEY (`id`)
  31. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  32. -- ----------------------------
  33. -- Table structure for tool_share
  34. -- ----------------------------
  35. DROP TABLE IF EXISTS `tool_share`;
  36. CREATE TABLE `tool_share` (
  37. `id` int(11) NOT NULL AUTO_INCREMENT,
  38. `linkid` int(11) DEFAULT NULL,
  39. `title` varchar(255) DEFAULT NULL,
  40. `code` text,
  41. `value` int(11) DEFAULT NULL,
  42. `time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  43. `view` int(11) DEFAULT NULL,
  44. PRIMARY KEY (`id`)
  45. ) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8;
  46. -- ----------------------------
  47. -- Table structure for tool_temp
  48. -- ----------------------------
  49. DROP TABLE IF EXISTS `tool_temp`;
  50. CREATE TABLE `tool_temp` (
  51. `id` int(11) NOT NULL,
  52. `template` text,
  53. PRIMARY KEY (`id`),
  54. CONSTRAINT `lang` FOREIGN KEY (`id`) REFERENCES `tool_lang` (`id`)
  55. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  56. SET FOREIGN_KEY_CHECKS=1;

具体sql文件在项目MySQL目录里,导入最新的版本即可

ok,文档到此就告一段落了,这个小项目也到此结束了,by jtahstu at 2016/10/09 in USTA Lixing Building Lab .

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注