Yamecent-admin 基于Laravel框架搭建的rbac管理后台

14769055-6cdf8ab92efbd3a0.png

欢迎使用yamecent-admin后台管理

环境要求

依赖说明
PHPPHP7+

项目简介

yamecent-admin是一款基于laravel框架进行封装的后台管理系统,其中包含:

  • rbac权限管理模块
  • 完整的ui组件(外部引入)
  • 图片上传,网络请求等常用的js公共函数
  • 持续维护中...

安装教程

  • 执行安装命令 composer create-project woann/yamecent-admin 或者git clone git@github.com:woann/yamecent-admin.git
  • 配置域名(按laravel项目正常配置即可,解析到public目录)
  • 如发现权限相关问题 执行 chown -R 用户名:用户组 项目目录
  • 访问域名,登录即可进入管理系统
  • 首次访问域名时会跳转至安装页面1541490225.jpg
  • 填写完数据表配置之后,点击安装即可(有点小慢,喝口水)
  • 安装完之后就可以使用刚刚提交的管理员账号密码登录了(如果您想重新安装,要将/app/install/install.lock 文件删掉,重新访问网址即可)
  • UI参考地址: http://demo.cssmoban.com/cssthemes5/twts_141_PurpleAdmin/pages/ui-features/buttons.html

js函数列表

函数用途
myRequest(url,type,data,success,error){}发起ajax请求(包含laravel的token验证,loading等)
function myConfirm(msg,confirm){}发起询问框
checkForm(){}验证表单
cutStr(){}限制td字数

富文本

  • html

    <div class="form-group " id="text" style="display: none;">
       <label >富文本</label>
       <textarea  placeholder="请在此处编辑内容"  id="editor" style="height:400px;max-height:400px;overflow: hidden"></textarea >   
    </div>
  • javascript

    var editor = new wangEditor('editor');
    editor.config.uploadImgUrl = "/admin/wangeditor/upload";
    // 隐藏掉插入网络图片功能。该配置,只有在你正确配置了图片上传功能之后才可用。
    editor.config.hideLinkImg = false;
    editor.create();
  • 示例
    富文本编辑器

列表批量操作

  • html

       <!--按钮-->
       <button type="button" class="btn btn-sm btn-gradient-danger btn-icon-text" onclick="batch('/admin/user/del/')">
          <i class="mdi mdi-delete btn-icon-prepend"></i>批量删除
       </button>
    <!--全选复选框-->
    <tr>
        <th width="3%">
            <div class="form-check">
                <label class="form-check-label">
                    <input type="checkbox" class="form-check-input batch-all">
                </label>
            </div>
         </th>
        ...
    </tr>
    <!--列表复选框-->
    <tr>
        <td>
            <div class="form-check">
               <label class="form-check-label">
                   <input type="checkbox" class="form-check-input td-check" value="{{ $v->id }}">
               </label>
            </div>
        </td>
        ...
    </tr>
  • 示例
    批量操作

部分截图:

admin
admin
admin
admin

作者 @woann @xjj
2018 年 10月 30日

算法与数学之美-两数之和

img.jpg

注:本类文章所有算法例子均来自LeetCode平台,对算法感兴趣的小伙伴们可以考虑去学习一下,非常不错的一个网站。

两数之和

题目

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的 两个 整数。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

思路
这是一道比较简单的算法题,遍历数组每个元素x,并查找是否存在两个元素之和为x1+x2 = target的值的情况,或者查找是否存在一个值与 target - x 相等。存在则返回,不存在则抛出异常即可

题解
--暴力解法
这也是我当时做这道题的时候使用的方法。由于LeetCode平台没有提供php语言的编辑器,所以只能用java举例来说明了,主要是领会精神-。-

测试用例:
[2,7,11,15]
9

class Solution {
public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] == target - nums[i]) {
                return new int[] { i, j };
            }
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}
}

耗时:
深度截图_选择区域_20181201145531.png

复杂度分析:

  • 时间复杂度:O(n²),对于每个元素,我们试图通过遍历数组的其余部分来寻找它所对应的目标元素,这将耗费 O(n) 的时间。因此时间复杂度为 O(n²)。
  • 空间复杂度:O(1)。

复杂度优化
--两遍哈希表

再次感谢LeetCode平台提供的解法和思路,受益匪浅。

为了对运行时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找出它的索引。保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。

通过以空间换取速度的方式,我们可以将查找时间从 O(n) 降低到 O(1)。哈希表正是为此目的而构建的,它支持以 近似 恒定的时间进行快速查找。我用“近似”来描述,是因为一旦出现冲突,查找用时可能会退化到 O(n)。但只要你仔细地挑选哈希函数,在哈希表中进行查找的用时应当被摊销为 O(1)。

一个简单的实现使用了两次迭代。在第一次迭代中,我们将每个元素的值和它的索引添加到表中。然后,在第二次迭代中,我们将检查每个元素所对应的目标元素(target - nums[i])是否存在于表中。注意,该目标元素不能是 nums[i] 本身!

class Solution {
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], i);
    }
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement) && map.get(complement) != i) {
            return new int[] { i, map.get(complement) };
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}
}

耗时:
深度截图_选择区域_20181201145613.png

复杂度分析:

  • 时间复杂度:O(n), 我们把包含有 n 个元素的列表遍历两次。由于哈希表将查找时间缩短到 O(1) ,所以时间复杂度为 O(n)。
  • 空间复杂度:O(n), 所需的额外空间取决于哈希表中存储的元素数量,该表中存储了 n 个元素。

继续优化
-- 一遍哈希表
在看懂两遍哈希表的优化方法后,我们可以在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。如果它存在,那我们已经找到了对应解,并立即将其返回。

class Solution {
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[] { map.get(complement), i };
        }
        map.put(nums[i], i);
    }
    throw new IllegalArgumentException("No two sum solution");
}
}

耗时:
深度截图_选择区域_20181201145717.png

复杂度分析:

  • 时间复杂度:O(n), 我们只遍历了包含有 n 个元素的列表一次。在表中进行的每次查找只花费 O(1) 的时间。
  • 空间复杂度:O(n), 所需的额外空间取决于哈希表中存储的元素数量,该表最多需要存储 n 个元素。

到此,这道简单的算法题就结束了,用来消遣业余时间还是非常不错的。

Golang 语言基础学习总结

8bfd8a0528c0172912adb9ad002d2bbb6902bda5.jpg

变量的定义和赋值

Go 是静态编译型语言,所有变量在定义时都必须明确其类型,定义格式和示例如下:

var identifier [type] = value
   var xjj string
   var xjj2 string = "hello xjj"

Go 语言支持类型推断,可以使用 := 赋值操作符对一个变量定义并赋值。

a := "xjj"
   b := false

a和b的类型编译器会自行推断,a则会默认为string类型,b为bool

这是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。使用操作符 := 可以高效地创建一个新的变量,称之为初始化声明。

常量

常量使用关键字 const 定义,用于存储不会改变的数据。存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

const Pi = 3.14159

空白标识符

在 Go 语言中,_ 被称作空白标识符,用于抛弃值,例如:

_, b := 5, 7

5 这个值将会被抛弃。

_ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

包和 import

一个文件夹下只能有一个包。

import 是以包为单位的,导入名称是包的路径,导入后使用是用包名,并非路径的最后一级字符。

import _ "..."

表示只调用包的 init 函数,并没有把整个包都导入进来

可见性

Go 语言中没有像其它语言中的 public、protected、private 等访问控制修饰符,它是通过字母大小写来控制可见性的,如果定义的变量、常量、类型、函数等的名称是大写字母开头就表示能被其它包访问或调用(相当于 public),非大写开头就只能在包内使用(相当于 private,变量或常量也可以以下划线开头)。

换行规则(坑爹)

左大括号 { 必须与方法的声明放在同一行,这是编译器的强制规定,Go 语言虽然看起来不使用分号作为语句的结束,但实际上这一过程是由编译器自动完成,所以下面这种定义将会报错:

func functionName(parameter_list) (return_value_list)
{
   …
}
syntax error: unexpected semicolon or newline before {

而右大括号 } 需要被放在紧接着函数体的下一行。如果你的函数非常简短,你也可以将它们放在同一行。

如果我们的函数参数太多,想换行来写,这时候也要注意,最后一个字符必须是逗号。

只要牢记 Go 语言使用分号作为语句的结束这一过程是由编译器自动完成的,为什么会报错也不难理解。

a := []string{"a", "b", "c"}

// Good
a := []string{
    "a",
    "b",
    "c",
}

// Bad
a := []string{
    "a",
    "b",
    "c"
}
// syntax error: unexpected newline, expecting comma or }

指针

不像 Java 和 PHP,Go 语言中有指针;但是,你不能进行指针运算。通过给予程序员基本内存布局,Go 语言允许你控制特定集合的数据结构、分配的数量以及内存访问模式。类似于引用

声明格式如下:

var intP *int

Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

var i = 5
var intP *int

intP = &i

intP 存储了 i 的内存地址;它指向了 i 的位置,它引用了变量 i。

try catch?

Go 语言追求简洁优雅,所以,Go 语言不支持传统的 try…catch…finally 这种异常,因为 Go 语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。在 Go 语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。

错误处理基本靠 if err != nil

class?

Go 语言中没有类的概念,但不代表它没有面向对象这个概念。Go 语言中可以通过一种特殊的函数定义语法来为变量定义方法。

方法是作用在接收者(receiver)上的一个函数,接收者是某种类型的变量。因此方法是一种特殊类型的函数。

接收者类型可以是(几乎)任何类型,不仅仅是结构体类型:任何类型都可以有方法,甚至可以是函数类型,可以是 int、bool、string 或数组的别名类型。但是接收者不能是一个接口类型,因为接口是一个抽象定义,但是方法却是具体实现;如果这样做会引发一个编译错误:invalid receiver type。

定义方法的一般格式如下:

func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }

因为方法是函数,所以同样的,不允许方法重载,即对于一个类型只能有一个给定名称的方法。但是如果基于接收者类型,是有重载的:具有同样名字的方法可以在 2 个或多个不同的接收者类型上存在(就相当于不同的类中有一样的名称的方法),比如在同一个包里这么做是允许的:

func (a *denseMatrix) Add(b Matrix) Matrix
func (a *sparseMatrix) Add(b Matrix) Matrix

接口

但是 Go 语言里有非常灵活的接口概念,通过它可以实现很多面向对象的特性。接口提供了一种方式来说明对象的行为:如果谁能搞定这件事,它就可以用在这儿。

接口定义了一组方法(方法集),但是这些方法不包含(实现)代码:它们没有被实现(它们是抽象的)。接口里也不能包含变量。

通过如下格式定义接口:

type Namer interface {
    Method1(param_list) return_type
    Method2(param_list) return_type
     ...
}

上面的 Namer 是一个接口类型。

(按照约定,只包含一个方法的)接口的名字由方法名加 [e]r 后缀组成,例如 Printer、Reader、Writer、Logger、Converter 等等。还有一些不常用的方式(当后缀 er 不合适时),比如 Recoverable,此时接口名以 able 结尾,或者以 I 开头(像 PHP 或 Java 中那样)

go fmt

Go 开发团队不想要 Go 语言像许多其它语言那样总是在为代码风格而引发无休止的争论,浪费大量宝贵的开发时间,因此他们制作了一个工具:go fmt(gofmt)。这个工具可以将你的源代码格式化成符合官方统一标准的风格,属于语法风格层面上的小型重构。遵循统一的代码风格是 Go 开发中无可撼动的铁律,因此你必须在编译或提交版本管理系统之前使用 gofmt 来格式化你的代码。不得不说,这个理念是真的不错。

初学Go语言,还有很多理解不到的地方,欢迎各位大佬指教

使用LNMP一键安装包搭建服务器环境,以及使用Typecho搭建个人博客

248176286.png
本文参考自http://lnmp.org更多关于LNMP安装的注意事项,请参考此网站上的一系列教程,本文不过多介绍