初始化

This commit is contained in:
lisong 2021-12-08 21:27:29 +08:00
commit 79334d5f9e
3629 changed files with 642528 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.idea
.env
*.DS_Store

7
.htaccess Normal file
View File

@ -0,0 +1,7 @@
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?s=/$1 [QSA,PT,L]
</IfModule>

42
.travis.yml Normal file
View File

@ -0,0 +1,42 @@
sudo: false
language: php
branches:
only:
- stable
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
install:
- composer install --no-dev --no-interaction --ignore-platform-reqs
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
script:
- php think unit
deploy:
provider: releases
api_key:
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
file:
- ThinkPHP_Core.zip
- ThinkPHP_Full.zip
skip_cleanup: true
on:
tags: true

7
333.htaccess Normal file
View File

@ -0,0 +1,7 @@
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1]
</IfModule>

26
404.html Normal file
View File

@ -0,0 +1,26 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>404</title>
<style>
body{
background-color:#444;
font-size:14px;
}
h3{
font-size:60px;
color:#eee;
text-align:center;
padding-top:30px;
font-weight:normal;
}
</style>
</head>
<body>
<h3>404,您请求的文件不存在!</h3>
</body>
</html>

32
LICENSE.txt Normal file
View File

@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1. 需要给代码的用户一份Apache Licence ;
2. 如果你修改了代码,需要在被修改的文件中说明;
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可,但不可以表现为对Apache Licence构成更改。
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

45
README.md Normal file
View File

@ -0,0 +1,45 @@
## 功能一览
### 登录模块
- token验证
- 图形验证码
- 极验滑动验证
### 轮播模块
- 轮播管理
### 用户模块
- 用户管理
- 用户等级管理
### 新闻模块
- 文章管理
- 文章分类管理
- 标签管理
### 商城模块
- 品牌管理
- 商品管理
- 商品分类管理
- 订单管理
- 快递管理
- 收货地址管理
### 杂项演示
- 邮件发送
- 短信发送
- 二维码生成
### 微信模块
- 服务端验证
- 接收 & 回复用户消息
- 获取用户信息
- 发送模版消息
- 统一下单
- 更多...
### 人事管理
- 员工管理
- 部门管理
- 职位管理
### 系统管理
- 用户管理
- 角色管理
- 菜单管理
- 操作日志
- 个人资料
- 代码生成
3333333444

View File

@ -0,0 +1,141 @@
<?php
const URL_CURRENT = 'url://current';
const URL_RELOAD = 'url://reload';
const URL_BACK = 'url://back';
use think\exception\HttpResponseException;
use think\Response;
use think\response\Redirect;
use app\common\model\MallImage;
use think\db;
if (!function_exists('success')) {
function success($msg = '操作成功', $url = URL_BACK, $data = '', $wait = 0, array $header = [])
{
result(1, $msg, $data, $url, $wait, $header);
}
}
if (!function_exists('error')) {
function error($msg = '操作失败', $url = URL_CURRENT, $data = '', $wait = 0, array $header = [])
{
result(0, $msg, $data, $url, $wait, $header);
}
}
if (!function_exists('result')) {
function result($code = 0, $msg = 'unknown', $data = '', $url = null, $wait = 3, array $header = [])
{
if (request()->isPost()) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : url($url);
$result = [
'code' => $code,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
$response = Response::create($result, 'json')->header($header);
throw new HttpResponseException($response);
}
if ($url === null) {
$url = request()->server('HTTP_REFERER') ?? 'admin/index/index';
}
$response = new Redirect($url);
$response->code(302)->params($data)->with([$code ? 'success_message' : 'error_message' => $msg, 'url' => $url]);
throw new HttpResponseException($response);
}
}
if(!function_exists('goods_imgs_upload')){
/**
* 简单对称加密算法之解密
* @param String $union_id 指定id
* @param String $type 类型
* @param String $ori_img 原图
* @param String $thumb_img 缩略图
* @param String $ori_fm_img 原图封面
* @param String $thumb_img_f 缩略图封面
* @param String $goods_imgs 编辑时数据库中图片
* @date 20190906
* @return li
*/
//上传商品图片
function goods_imgs_upload($union_id,$type,$ori_img, $thumb_img,$ori_fm_img,$thumb_img_f,$goods_imgs=array())
{
$_goodsimgsModel= new MallImage();
//$tps = C('TMPL_PARSE_STRING');
$inequality_img=array();
if($ori_img){
$ori_img_ys=array();
if($goods_imgs){
foreach ($goods_imgs as $key=> $v){
$ori_img_ys[$v['id']]=$v['ori_image'];
$goods_imgs[$v['id']]=$v;
}
$inequality_img = array_diff($ori_img_ys,$ori_img);//前端踢掉的图片
}
foreach ($ori_img as $key=> $v){
if(in_array($v,$ori_img_ys,TRUE)){
if($v==$ori_fm_img && $thumb_img_f=$thumb_img[$key]){
$data3['is_cover']=1;
}else{
$data3['is_cover']=0;
}
$_goodsimgsModel->where(array('ori_image'=>$v))->update($data3);
continue;
}
$ori_img_url=trim($v);
if(!$ori_img_url){
$array = array(
'code' =>400,
'msg' =>'上传文件处理失败',
);
return $array;
}
$thumb_img_url=trim($thumb_img[$key]);
if(!$thumb_img_url){
$array = array(
'code' =>400,
'msg' =>'上传文件处理失败',
);
return $array;
}
$data1['ori_image']=$yu_url=$ori_img_url;
$data1['thumb_image']=$slt_url=$thumb_img_url;
if($v==$ori_fm_img && $thumb_img_f=$thumb_img[$key]){
$data1['is_cover']=1;
}else{
$data1['is_cover']=0;
}
$data1['type']=$type;
$data1['union_id']=$union_id;
$_goodsimgsModel::create($data1);
}
if($inequality_img){
foreach ($inequality_img as $key1=> $v1){
$mag=Db::table('yo_mall_image')->where('id',$key1)->delete();
if($mag){
$ori_image_del=Env::get('root_path').'public'.$goods_imgs[$key1]['ori_image'];
if(file_exists($ori_image_del))
{
unlink($ori_image_del);
}
$thumb_image_del=Env::get('root_path').'public'.$goods_imgs[$key1]['thumb_image'];
if(file_exists($thumb_image_del))
{
unlink($thumb_image_del);
}
}
}
}
}
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* 会员账户流水记录表控制器
*/
namespace app\admin\controller;
use think\Request;
use app\common\model\AccountLog;
use app\common\validate\AccountLogValidate;
class AccountLogController extends Controller
{
//积分记录
public function integrallist(Request $request, AccountLog $model)
{
$SOURCE_TYPE=$model->SOURCE_TYPE;
$param = $request->param();
$where = [];
if(isset($param['source_type']) && $param['source_type']){
$source_type = $param['source_type'];
$where[] = ['source_type','in',$source_type];
}
if(isset($param['keyword']) && $param['keyword']){
$where[] = [$param['keyword_type'],'like','%'.$param['keyword'].'%'];
}
if (isset($param['start_time']) && $param['start_time'] && isset($param['end_time']) && $param['end_time']) {
$where[] = ['al.create_time', 'between', [strtotime($param['start_time']), strtotime($param['end_time'])]];
}
$model = $model
->alias('al')
->field('al.*,u.mobile,u.nickname,u.sn as user_sn,u.avatar')
->join('user u', 'u.id = al.user_id')
->where($where)
->scope('where', $param);
$data = $model->paginate($this->admin['per_page'], false, ['query'=>$request->get()]);
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
'source_type_list'=>$SOURCE_TYPE,
]);
return $this->fetch();
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* 后台操作日志控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use app\admin\model\AdminLog;
use app\admin\model\AdminUser;
use think\Request;
class AdminLogController extends Controller
{
public function index(Request $request, AdminLog $model)
{
$param = $request->param();
$data = $model->where(function ($query) use ($param) {
if (isset($param['create_time_range']) && !empty($param['create_time_range'])) {
$range = explode(' - ', $param['create_time_range']);
$query->whereTime('create_time', 'between', $range);
}
})
->scope('where', $param)
->paginate($this->admin['per_page'], false, ['query' => $request->get()]);
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
'admin_user_list' => AdminUser::all(),
]);
return $this->fetch();
}
//日志详情
public function view($id, AdminLog $model)
{
$data = $model::get($id);
$this->assign([
'data' => $data
]);
return $this->fetch();
}
}

View File

@ -0,0 +1,171 @@
<?php
/**
* 后台菜单控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use think\Request;
use app\admin\model\AdminMenu;
use app\admin\validate\AdminMenuValidate;
class AdminMenuController extends Controller
{
public function index(AdminMenu $model)
{
//查询所有菜单并以树的形式显示
$result = $model->order('sort_id asc, id asc')->column('*', 'id');
foreach ($result as $n => $r) {
$result[$n]['level'] = $this->getLevel($r['id'], $result);
$result[$n]['parent_id_node'] = $r['parent_id'] ? ' class="child-of-node-' . $r['parent_id'] . '"' : '';
$result[$n]['str_manage'] = '<a href="' . url('edit', ['id' => $r['id']]) . '" class="btn btn-primary btn-xs" title="修改" data-toggle="tooltip"><i class="fa fa-pencil"></i></a> ';
$result[$n]['str_manage'] .= '<a class="btn btn-danger btn-xs AjaxButton" data-id="' . $r['id'] . '" data-url="del.html" data-confirm-title="删除确认" data-confirm-content=\'您确定要删除ID为 <span class="text-red"> ' . $r['id'] . ' </span> 的数据吗\' data-toggle="tooltip" title="删除"><i class="fa fa-trash"></i></a>';
$result[$n]['is_show'] = (int)$r['is_show'] === 1 ? '显示' : '隐藏';
$result[$n]['log_method'] = $r['log_method'];
}
$str = "<tr id='node-\$id' data-level='\$level' \$parent_id_node><td><input type='checkbox' onclick='checkThis(this)'
name='data-checkbox' data-id='\$id\' class='checkbox data-list-check' value='\$id' placeholder='选择/取消'>
</td><td>\$id</td><td>\$spacer\$name</td><td>\$url</td>
<td>\$parent_id</td><td><i class='fa \$icon'></i><span>(\$icon)</span></td>
<td>\$sort_id</td><td>\$is_show</td><td>\$log_method</td><td class='td-do'>\$str_manage</td></tr>";
$this->initTree($result);
$data = $this->getTree(0, $str);
$this->assign('data', $data);
return $this->fetch('index');
}
public function add(Request $request, AdminMenu $model, AdminMenuValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('add')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $model::create($param);
//如果
if (isset($param['is_more']) && $param['is_more'] == 1) {
$name = $param['more_name'];
$url = explode('/', $param['url']);
$str = '/';
$data = [
[
'parent_id' => $result->id,
'name' => '添加' . $name,
'url' => $url[0] . $str . $url[1] . $str . 'add',
'icon' => 'fa-plus',
'is_show' => 0,
'log_method' => 'POST',
],
[
'parent_id' => $result->id,
'name' => '修改' . $name,
'url' => $url[0] . $str . $url[1] . $str . 'edit',
'icon' => 'fa-pencil',
'is_show' => 0,
'log_method' => 'POST',
],
[
'parent_id' => $result->id,
'name' => '删除' . $name,
'url' => $url[0] . $str . $url[1] . $str . 'del',
'icon' => 'fa-trash',
'is_show' => 0,
'log_method' => 'POST',
]
];
$model->saveAll($data);
}
unset($url);
$url = URL_BACK;
if (isset($param['_create']) && $param['_create'] == 1) {
$url = URL_RELOAD;
}
return $result ? success('添加成功', $url) : error();
}
$parent_id = $request->param('parent_id') ?? 0;
$parents = $this->menu($parent_id);
$this->assign([
'parents' => $parents,
'log_method' => $model->logMethod
]);
return $this->fetch();
}
public function edit($id, Request $request, AdminMenu $model, AdminMenuValidate $validate)
{
$data = $model::get($id);
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('edit')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $data->save($param);
return $result ? success() : error();
}
$parent_id = $data->parent_id;
$parents = $this->menu($parent_id);
$this->assign([
'data' => $data,
'parents' => $parents,
'log_method' => $model->logMethod,
]);
return $this->fetch('add');
}
public function del($id, Request $request, AdminMenu $model)
{
//判断是否有子菜单
$have_son = $model->whereIn('parent_id', $id)->find();
if ($have_son) {
return error('有子菜单不可删除!');
}
if (count($model->noDeletionId) > 0) {
if (is_array($id)) {
if (array_intersect($model->noDeletionId, $id)) {
return error('ID为' . implode(',', $model->noDeletionId) . '的数据无法删除');
}
} else if (in_array($id, $model->noDeletionId)) {
return error('ID为' . $id . '的数据无法删除');
}
}
if ($model->softDelete) {
$result = $model->whereIn('id', $id)->useSoftDelete('delete_time', time())->delete();
} else {
$result = $model->whereIn('id', $id)->delete();
}
return $result ? success('操作成功', URL_RELOAD) : error();
}
//菜单选择 select树形选择
protected function menu($selected = 1, $current_id = 0)
{
$result = AdminMenu::where('id', '<>', $current_id)->order('sort_id', 'asc')->order('id', 'asc')->column('id,parent_id,name,sort_id', 'id');
foreach ($result as $r) {
$r['selected'] = (int)$r['id'] === (int)$selected ? 'selected' : '';
}
$str = "<option value='\$id' \$selected >\$spacer \$name</option>";
$this->initTree($result);
return $this->getTree(0, $str, $selected);
}
}

View File

@ -0,0 +1,190 @@
<?php
/**
* 后台角色控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use app\admin\model\AdminMenu;
use app\admin\model\AdminRole;
use app\admin\validate\AdminRoleValidate;
use think\Request;
class AdminRoleController extends Controller
{
public function index(Request $request, AdminRole $model)
{
$param = $request->param();
$data = $model->scope('where', $param)
->paginate($this->admin['per_page'], false, ['query' => $request->get()]);
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
]);
return $this->fetch();
}
//添加
public function add(Request $request, AdminRole $model, AdminRoleValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('add')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $model::create($param);
$url = URL_BACK;
if (isset($param['_create']) && $param['_create'] == 1) {
$url = URL_RELOAD;
}
return $result ? success('添加成功', $url) : error();
}
return $this->fetch();
}
//修改
public function edit($id, Request $request, AdminRole $model, AdminRoleValidate $validate)
{
$data = $model::get($id);
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('edit')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $data->save($param);
return $result ? success() : error();
}
$this->assign([
'data' => $data
]);
return $this->fetch('add');
}
//删除
public function del($id, AdminRole $model)
{
if (count($model->noDeletionId) > 0) {
if (is_array($id)) {
if (array_intersect($model->noDeletionId, $id)) {
return error('ID为' . implode(',', $model->noDeletionId) . '的数据无法删除');
}
} else if (in_array($id, $model->noDeletionId)) {
return error('ID为' . $id . '的数据无法删除');
}
}
if ($model->softDelete) {
$result = $model->whereIn('id', $id)->useSoftDelete('delete_time', time())->delete();
} else {
$result = $model->whereIn('id', $id)->delete();
}
return $result ? success('操作成功', URL_RELOAD) : error();
}
//角色授权
public function access($id, Request $request, AdminRole $model)
{
$data = $model::get($id);
if ($request->isPost()) {
$param = $request->param();
if (!isset($param['url'])) {
return error('请至少选择一项权限');
}
if (!in_array(1, $param['url'])) {
return error('首页权限必选');
}
if (false !== $data->save($param)) {
return success();
}
return error();
}
$menu = AdminMenu::order('sort_id', 'asc')->order('id', 'asc')->column('*', 'id');
$html = $this->authorizeHtml($menu, $data->url);
$this->assign([
'data' => $data,
'html' => $html,
]);
return $this->fetch();
}
//启用
public function enable($id, AdminRole $model)
{
$result = $model->whereIn('id', $id)->update(['status' => 1]);
return $result ? success('操作成功', URL_RELOAD) : error();
}
//禁用
public function disable($id, AdminRole $model)
{
$result = $model->whereIn('id', $id)->update(['status' => 0]);
return $result ? success('操作成功', URL_RELOAD) : error();
}
//生成授权html
protected function authorizeHtml($menu, $auth_menus = [])
{
foreach ($menu as $n => $t) {
$menu[$n]['checked'] = in_array($t['id'], $auth_menus) ? ' checked' : '';
$menu[$n]['level'] = $this->getLevel($t['id'], $menu);
$menu[$n]['width'] = 100 - $menu[$n]['level'];
}
$this->initTree($menu);
$this->text = [
'other' => "<label class='checkbox' >
<input \$checked name='url[]' value='\$id' level='\$level'
onclick='javascript:checkNode(this);' type='checkbox'>
\$name
</label>",
'0' => [
'0' => "<dl class='checkmod'>
<dt class='hd'>
<label class='checkbox'>
<input \$checked name='url[]' value='\$id' level='\$level'
onclick='javascript:checkNode(this);'
type='checkbox'>
\$name
</label>
</dt>
<dd class='bd'>",
'1' => '</dd></dl>',
],
'1' => [
'0' => "
<div class='menu_parent'>
<label class='checkbox'>
<input \$checked name='url[]' value='\$id' level='\$level'
onclick='javascript:checkNode(this);' type='checkbox'>
\$name
</label>
</div>
<div class='rule_check' style='width: \$width%;'>",
'1' => "</div><span class='child_row'></span>",
]
];
return $this->getAuthTreeAccess(0);
}
}

View File

@ -0,0 +1,170 @@
<?php
/**
* 后台用户控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use app\common\model\Attachment;
use think\Request;
use app\admin\model\AdminRole;
use app\admin\model\AdminUser;
use app\admin\validate\AdminUserValidate;
class AdminUserController extends Controller
{
//列表
public function index(Request $request, AdminUser $model)
{
$param = $request->param();
$data = $model->scope('where', $param)
->paginate($this->admin['per_page'], false, ['query' => $request->get()]);
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
]);
return $this->fetch();
}
//添加
public function add(Request $request, AdminUser $model, AdminUserValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('add')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $model::create($param);
$url = URL_BACK;
if (isset($param['_create']) && $param['_create'] == 1) {
$url = URL_RELOAD;
}
return $result ? success('添加成功', $url) : error();
}
$role = AdminRole::all(function ($query) {
$query->column('id,name', 'id');
});
$this->assign([
'role' => $role
]);
return $this->fetch();
}
//修改
public function edit($id, Request $request, AdminUser $model, AdminUserValidate $validate)
{
$data = $model::get($id);
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('edit')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $data->save($param);
return $result ? success() : error();
}
$role = AdminRole::all(function ($query) {
$query->column('id,name', 'id');
});
$this->assign([
'data' => $data,
'role' => $role
]);
return $this->fetch('add');
}
//删除
public function del($id, AdminUser $model)
{
if (count($model->noDeletionId) > 0) {
if (is_array($id)) {
if (array_intersect($model->noDeletionId, $id)) {
return error('ID为' . implode(',', $model->noDeletionId) . '的数据无法删除');
}
} else if (in_array($id, $model->noDeletionId)) {
return error('ID为' . $id . '的数据无法删除');
}
}
if ($model->softDelete) {
$result = $model->whereIn('id', $id)->useSoftDelete('delete_time', time())->delete();
} else {
$result = $model->whereIn('id', $id)->delete();
}
return $result ? success('操作成功', URL_RELOAD) : error();
}
//启用
public function enable($id, AdminUser $model)
{
$result = $model->whereIn('id', $id)->update(['status' => 1]);
return $result ? success('操作成功', URL_RELOAD) : error();
}
//禁用
public function disable($id, AdminUser $model)
{
$result = $model->whereIn('id', $id)->update(['status' => 0]);
return $result ? success('操作成功', URL_RELOAD) : error();
}
//个人资料
public function profile(Request $request, AdminUser $model, AdminUserValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
if ($param['update_type'] === 'password') {
$validate_result = $validate->scene('password')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
if (!password_verify($param['password'], $this->user->password)) {
return error('当前密码不正确');
}
$param['password'] = $param['new_password'];
} else if ($param['update_type'] === 'avatar') {
if (!$request->file('avatar')) {
return error('请上传新头像');
}
$attachment = new Attachment();
$file = $attachment->upload('avatar');
if ($file) {
$param['avatar'] = $file->url;
} else {
return error($attachment->getError());
}
}
if (false !== $this->user->save($param)) {
return success('修改成功', URL_RELOAD);
}
return error();
}
return $this->fetch();
}
}

View File

@ -0,0 +1,151 @@
<?php
/**
* 后台登录退出控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use Exception;
use think\captcha\Captcha;
use think\Request;
use app\admin\model\AdminUser;
use app\admin\validate\AdminUserValidate;
use tools\GeeTest;
class AuthController extends Controller
{
protected $authExcept = [
'admin/auth/login',
'admin/auth/logout',
'admin/auth/captcha',
'admin/auth/initgeetest',
];
//登录
public function login(Request $request, AdminUser $model, AdminUserValidate $validate)
{
if ($request->isPost()) {
$login_config = config('admin.login');
$param = $request->param();
//如果需要验证码
if ($login_config['captcha'] > 0) {
if ($login_config['captcha'] == 1) {
if (!captcha_check($param['captcha'])) {
return error('验证码错误');
}
} else if ($login_config['captcha'] == 2) {
$config = config('geetest.');
$geeTest = new GeeTest($config['id'], $config['key']);
$data = array(
'user_id' => session('gt_uid'),
'client_type' => 'web',
'ip_address' => $request->ip(),
);
if (session('gt_server') == 1) {
$gee_test_result = $geeTest->successValidate($param['geetest_challenge'], $param['geetest_validate'], $param['geetest_seccode'], $data);
if (!$gee_test_result) {
return error('验证失败');
}
} else {
if (!$geeTest->failValidate($param['geetest_challenge'], $param['geetest_validate'])) {
return error('验证失败');
}
}
}
}
$validate_result = $validate->scene('login')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
//如果需要验证登录token
if ($login_config['token']) {
$token_validate = \think\Validate::make();
$token_validate_result = $token_validate->rule('__token__', 'token')
->check($param);
if (!$token_validate_result) {
return error($token_validate->getError());
}
}
try {
$user = $model::login($param);
} catch (Exception $e) {
return error($e->getMessage());
}
$remember = isset($param['remember']) ? true : false;
self::authLogin($user, $remember);
$redirect = session('redirect') ?? url('admin/index/index');
return success('登录成功', $redirect);
}
$this->admin['title'] = '登录';
$this->assign([
//登录设置,参考/config/admin/admin.php文件配置
'login_config' => config('admin.login'),
]);
return $this->fetch();
}
//退出
public function logout()
{
self::authLogout();
return redirect(url('admin/auth/login'));
}
//极验初始化
public function initGeeTest(Request $request)
{
$config = config('geetest.');
$geeTest = new GeeTest($config['id'], $config['key']);
$ip = $request->ip();
$ug = $request->header('user-agent');
$data = array(
'gt_uid' => md5($ip . $ug),
'client_type' => 'web',
'ip_address' => $ip,
);
$status = $geeTest->preProcess($data);
session('gt_server', $status);
session('gt_uid', $data['gt_uid']);
return success($status, URL_CURRENT, $geeTest->getResponse());
}
//ThinkPHP 图形验证码
public function captcha()
{
$config = [
// 验证码字体大小
'fontSize' => 30,
// 验证码位数
'length' => 4,
// 关闭验证码杂点
'useNoise' => false,
];
$captcha = new Captcha($config);
return $captcha->entry();
}
}

View File

@ -0,0 +1,147 @@
<?php
/**
* 后台基础控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use app\admin\model\AdminMenu;
use app\admin\model\AdminUser;
use app\admin\traits\{AdminAuth, AdminTree, PhpOffice};
class Controller extends \think\Controller
{
use AdminAuth, AdminTree, PhpOffice;
/**
* 当前url
* @var string
*/
protected $url;
/**
* 当前用户ID
* @var int
*/
protected $uid = 0;
/**
* 当前用户
* @var AdminUser
*/
protected $user;
/**
* 后台变量
* @var array
*/
protected $admin;
/**
* 无需验证权限的url
* @var array
*/
protected $authExcept = [
'admin/auth/login',
'admin/auth/logout',
'admin/editor/server',
];
//初始化基础控制器
protected function initialize()
{
$request = $this->request;
//获取当前访问url
$this->url = parse_name($request->module()) . '/' .
parse_name($request->controller()) . '/' .
parse_name($request->action());
//验证权限
if (!in_array($this->url, $this->authExcept)) {
if (!$this->isLogin()) {
error('未登录', 'auth/login');
} else if ($this->user->id !== 1 && !$this->authCheck($this->user)) {
error('无权限', $this->request->isGet() ? null : URL_CURRENT);
}
}
if ((int)$request->param('check_auth') === 1) {
success();
}
//记录日志
$menu = AdminMenu::get(['url' => $this->url]);
if ($menu) {
$this->admin['title'] = $menu->name;
if ($menu->log_method === $request->method()) {
$this->createAdminLog($this->user, $menu);
}
}
$this->admin['per_page'] = cookie('admin_per_page') ?? 10;
$this->admin['per_page'] = $this->admin['per_page'] < 100 ? $this->admin['per_page'] : 100;
}
//重写fetch
protected function fetch($template = '', $vars = [], $config = [])
{
$this->admin['pjax'] = $this->request->isPjax();
$this->admin['user'] = $this->user;
$this->setAdminInfo();
if (!$this->admin['pjax'] && 'admin/auth/login' !== $this->url) {
$this->admin['menu'] = $this->getLeftMenu($this->user);
}
$this->assign('debug', config('app.app_debug') ? 'true' : 'false');
$this->assign('cookie_prefix', config('cookie.prefix') ?? '');
$this->assign('admin', $this->admin);
return parent::fetch($template, $vars, $config);
}
//空方法
public function _empty()
{
$this->admin['title'] = '404';
return $this->fetch('template/404');
}
//设置前台显示的后台信息
protected function setAdminInfo()
{
if (!$this->admin['pjax']) {
$admin_info = [
'name' => config('admin.name'),
'author' => config('admin.author'),
'version' => config('admin.version'),
'short_name' => config('admin.short_name'),
];
cache('admin_info', json_encode($admin_info), 8640000);
} else {
$admin_info = cache('admin_info');
if (!$admin_info) {
$admin_info = [
'name' => config('admin.name'),
'author' => config('admin.author'),
'version' => config('admin.version'),
'short_name' => config('admin.short_name'),
];
} else {
$admin_info = json_decode($admin_info, true);
}
}
$this->admin = array_merge($this->admin, $admin_info);
}
}

View File

@ -0,0 +1,17 @@
<?php
/**
* 访问空控制器,用于访问不存在的控制器跳转
* @author yupoxiong <i@yufuping.com>
*/
namespace app\admin\controller;
class ErrorController extends Controller
{
public function index()
{
$this->admin['title'] = '404';
return $this->fetch('template/404');
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* 文件控制器(暂未完成)
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use think\facade\Env;
use think\Request;
class FileController extends Controller
{
protected $authExcept = [
'admin/file/icon',
];
//文件列表
public function index(Request $request)
{
}
//文件上传
public function upload()
{
$file = request()->file('file');
}
//上传图片修改
public function icon(Request $request)
{
$param = $request->param();
$file = request()->file('image');
if($file){
$info = $file->validate(['size'=>10*1024*1024,'ext'=>'jpg,png,gif'])->move(Env::get('root_path').'public/uploads/attachment');
if($info){
$data['avatar_logo_thum']='';
$data['avatar_logo']='';
if($param['type']==1){
$width=$param['width'] ?? '200';
$heigh=$param['heigh'] ?? '200';
$avatar_thum=thumbnail_img($info,$width,$heigh,'attachment');
$data['avatar_logo_thum']=$avatar_thum;
}
$data['avatar_logo']='/uploads/attachment/'.$info->getSaveName();
return success('上传成功','',$data);
}else{
// 上传失败获取错误信息
return client_error($file->getError());
}
}else{
return client_error('请上传图片');
}
}
}

View File

@ -0,0 +1,24 @@
<?php
/**
* 后台首页控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use app\admin\model\AdminLog;
use app\admin\model\AdminMenu;
use app\admin\model\AdminRole;
use app\admin\model\AdminUser;
use tools\SystemInfo;
use think\Request;
class FinanceController extends Controller
{
public function lists(Request $request)
{
return $this->fetch();
}
}

View File

@ -0,0 +1,293 @@
<?php
/**
* 代码自动生成控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use app\admin\model\AdminMenu;
use Error;
use Exception;
use generate\field\Ip;
use generate\field\Map;
use generate\field\Province;
use generate\field\Url;
use generate\field\File;
use generate\field\Icon;
use generate\field\Year;
use generate\field\Text;
use generate\field\Date;
use generate\field\Color;
use generate\field\Email;
use generate\field\Field;
use generate\field\Radio;
use generate\field\Image;
use generate\field\Select;
use generate\field\Mobile;
use generate\field\IdCard;
use generate\field\Number;
use generate\field\Editor;
use generate\field\Datetime;
use generate\field\Checkbox;
use generate\field\Password;
use generate\field\Textarea;
use generate\field\YearMonth;
use generate\field\YearRange;
use generate\field\MultiFile;
use generate\field\DateRange;
use generate\field\MultiImage;
use generate\field\SwitchField;
use generate\field\MultiSelect;
use generate\field\DatetimeRange;
use generate\field\YearMonthRange;
use think\Db;
use think\db\Connection;
use think\Request;
use generate\Generate;
class GenerateController extends Controller
{
//首页
public function index()
{
return $this->fetch();
}
//自动生成页面
public function add()
{
$this->assign([
'table' => (new Generate())->getTable(),
'menus' => $this->menu(10000),
]);
return $this->fetch();
}
//获取表数据
public function getTable()
{
return success('success', URL_CURRENT, (new Generate())->getTable());
}
public function getMenu()
{
return success('success', URL_CURRENT, (new Generate())->getMenu());
}
//自动生成代码接口
public function create(Request $request)
{
$param = $request->param();
$data = [
'table' => $param['table_name'],
'cn_name' => $param['cn_name'],
'menu' => [
//创建菜单-1为不创建,0为顶级菜单
'create' => $param['create_menu'],
'menu' => $param['create_menu_list']
],
'controller' => [
'module' => 'admin',
'create' => $param['create_controller'] ?? 0,
'name' => $param['controller_name'],
'action' => $param['controller_action_list'],
],
'model' => [
'module' => 'common',
'create' => $param['create_model'] ?? 0,
'name' => $param['model_name'],
'timestamp' => $param['auto_timestamp'] ?? 0,
'soft_delete' => $param['soft_delete'] ?? 0,
],
'validate' => [
'module' => 'common',
'create' => $param['create_validate'] ?? 0,
'name' => $param['validate_name'],
],
'view' => [
'enable' => $param['list_enable'] ?? 0,
'delete' => $param['list_delete'] ?? 0,
'create' => $param['list_create'] ?? 0,
'export' => $param['list_export'] ?? 0,
],
];
/**
* 字段数据组装
*/
$field_data = [];
foreach ($param['field_name'] as $key => $value) {
$field_data[] = [
//字段名
'field_name' => $param['field_name'][$key][0],
//字段类型
'field_type' => $param['field_type'][$key][0],
//表单名称/中文名称
'form_name' => $param['form_name'][$key][0] ?? '',
//是否为列表字段
'is_list' => $param['is_list'][$key][0] ?? 0,
//是否为列表搜索字段
'is_search' => $param['is_search'][$key][0] ?? 0,
//是否为表单字段
'is_form' => $param['is_form'][$key][0] ?? 0,
//表单类型
'form_type' => $param['form_type'][$key][0] ?? 0,
//验证规则
'form_validate' => $param['form_validate'][$key] ?? 0,
//默认值
'field_default' => $param['field_default'][$key][0] ?? 0,
//获取器/修改器
'getter_setter' => $param['getter_setter'][$key][0] ?? 0,
//是否参与列表排序
'list_sort' => $param['list_sort'][$key][0] ?? 0,
//验证场景
'field_scene' => $param['field_scene'][$key] ?? 0,
//关联
'is_relation' => $param['is_relation'][$key][0] ?? 0,
//关联类型
'relation_type' => $param['relation_type'][$key][0] ?? 1,
//关联表
'relation_table' => $param['relation_table'][$key][0] ?? '',
//关联显示字段
'relation_show' => $param['relation_show'][$key][0] ?? 'name',
];
}
$data['data'] = $field_data;
//已经组装好data,先生成表,再生成模型,验证器,控制器,视图
$generate = new Generate($data);
$msg = '生成成功';
$result = false;
try {
$generate->run();
$result = true;
} catch (Exception $e) {
$msg = $e->getMessage();
}
return $result ? success($msg, URL_CURRENT) : error($msg);
}
//自动生成form表单字段
public function form()
{
return $this->fetch();
}
//生成表单字段html接口
public function formField(Request $request)
{
$param = $request->param();
if (empty($param['form_name']) || empty($param['field_name']) || empty($param['form_type'])) {
return error('信息不完整');
}
$result = false;
try {
if ($param['form_type'] === 'switch') {
$param['form_type'] = 'switch_field';
}
$param['field_default'] = '';
$class_name = parse_name($param['form_type'], 1);
$class = '\\generate\\field\\' . $class_name;
$data = $class::create($param);
$result = true;
$msg = '生成表单html成功';
} catch (Exception $exception) {
$msg = $exception->getMessage();
} catch (Error $error) {
$msg = $error->getMessage();
}
return $result ? success($msg, URL_CURRENT, $data) : error($msg);
}
//根据字段返回相关表单类型和验证
public function getField(Request $request)
{
$param = $request->param();
$name = $param['name'];
$data = (new Generate())->getAll($name);
return success('success', URL_CURRENT, $data);
}
//获取验证select内容
/**
* @param Request $request
* @return \think\response\Json|void
*/
public function getValidateSelect(Request $request)
{
$param = $request->param();
$result = false;
try {
if ($param['form_type'] === 'switch') {
$param['form_type'] = 'switch_field';
}
$class_name = parse_name($param['form_type'], 1);
$class = '\\generate\\field\\' . $class_name;
$data = $class::rule();
$result = true;
$msg = '获取字段验证规则成功';
} catch (Exception $exception) {
$msg = $exception->getMessage();
} catch (Error $error) {
$msg = $error->getMessage();
}
return $result ? success($msg, URL_CURRENT, $data) : error($msg);
}
//菜单选择
protected function menu($selected = 1, $current_id = 0)
{
$result = AdminMenu::where('id', '<>', $current_id)->order('sort_id', 'asc')->order('id', 'asc')->column('id,parent_id,name,sort_id', 'id');
foreach ($result as $r) {
$r['selected'] = (int)$r['id'] === (int)$selected ? 'selected' : '';
}
$str = "<option value='\$id' \$selected >\$spacer \$name</option>";
$this->initTree($result);
return $this->getTree(0, $str, $selected);
}
}

View File

@ -0,0 +1,101 @@
<?php
/**
* 商品分类控制器
*/
namespace app\admin\controller;
use think\Request;
use app\common\model\GoodsCategory;
use app\common\validate\GoodsCategoryValidate;
class GoodsCategoryController extends Controller
{
//列表
public function index(GoodsCategory $model)
{
$data = $this->getTreeList($model);
$this->assign([
'data' => $data,
]);
return $this->fetch();
}
//添加
public function add(Request $request, GoodsCategory $model, GoodsCategoryValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('add')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $model::create($param);
$url = URL_BACK;
if (isset($param['_create']) && $param['_create'] == 1) {
$url = URL_RELOAD;
}
return $result ? success('添加成功', $url) : error();
}
$this->assign([
'cat_list' => $this->getSelectList($model),
]);
return $this->fetch();
}
//修改
public function edit($id, Request $request, GoodsCategory $model, GoodsCategoryValidate $validate)
{
$data = $model::get($id);
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('edit')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $data->save($param);
return $result ? success() : error();
}
$this->assign([
'data' => $data,
'cat_list' => $this->getSelectList($model, $data->parent_id),
]);
return $this->fetch('add');
}
//删除
public function del($id, GoodsCategory $model)
{
if (count($model->noDeletionId) > 0) {
if (is_array($id)) {
if (array_intersect($model->noDeletionId, $id)) {
return error('ID为' . implode(',', $model->noDeletionId) . '的数据无法删除');
}
} else if (in_array($id, $model->noDeletionId)) {
return error('ID为' . $id . '的数据无法删除');
}
}
if ($model->softDelete) {
$result = $model->whereIn('id', $id)->useSoftDelete('delete_time', time())->delete();
} else {
$result = $model->whereIn('id', $id)->delete();
}
return $result ? success('操作成功', URL_RELOAD) : error();
}
}

View File

@ -0,0 +1,150 @@
<?php
/**
* 商品控制器
*/
namespace app\admin\controller;
use think\Request;
use app\common\model\Goods;
use app\common\model\MallImage;
use app\common\model\GoodsCategory;
use app\common\model\Brand;
use app\common\model\GoodsAttrCategory;
use app\common\validate\GoodsValidate;
class GoodsController extends Controller
{
//列表
public function index(Request $request, Goods $model)
{
$param = $request->param();
$model = $model->with('goods_category')->scope('where', $param);
$data = $model->paginate($this->admin['per_page'], false, ['query' => $request->get()]);
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
]);
return $this->fetch();
}
//添加
public function add(Request $request, Goods $model,MallImage $mimode, GoodsValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('add')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$param['detail'] = $request->param(false)['detail'];
// 启动事务
$model->startTrans();
try{
$model::create($param);
$goods_id=$model->getLastInsID();
goods_imgs_upload($goods_id,1,$param['ori_img'],$param['thumb_img'],$param['ori_fm_img'],$param['thumb_img_f']);
// 提交事务
$model->commit();
}catch(\Exception $e){
// 回滚事务
$model->rollback();
return error($e->getMessage());
}
$url = URL_BACK;
if(isset($param['_create']) && $param['_create']==1){
$url = URL_RELOAD;
}
return success('添加成功',$url);
}
$this->assign([
'goods_category_list' => $this->getSelectList(new GoodsCategory),
'imgurl_list'=>array(),
]);
return $this->fetch();
}
//修改
public function edit($id, Request $request, Goods $model ,MallImage $mimode, GoodsValidate $validate)
{
$data = $model::get($id);
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('edit')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$param['detail'] = $request->param(false)['detail'];
// 启动事务
$model->startTrans();
try{
$data->save($param);
$MallImage=$mimode->where(array('type'=>1,'union_id'=>$id))->select();
goods_imgs_upload($id,1,$param['ori_img'],$param['thumb_img'],$param['ori_fm_img'],$param['thumb_img_f'],$MallImage);
// 提交事务
$model->commit();
}catch(\Exception $e){
// 回滚事务
$model->rollback();
return error($e->getMessage());
}
return success();
}
$ori_img='';
$thumb_img='';
$imgurl_list=$mimode->field('thumb_image,ori_image,is_cover')->where(array('type'=>1,'union_id'=>$id))->select();
foreach ($imgurl_list as $key => $v) {
$is_cover=$v['is_cover']>0 ? $v['is_cover']:'0';
if ($is_cover == 1) {
$ori_img = $v['ori_image'];
$thumb_img = $v['thumb_image'];
}
}
$this->assign([
'data' => $data,
'goods_category_list' => $this->getSelectList(new GoodsCategory, $data->goods_category_id),
'ori_img'=>$ori_img,
'thumb_img'=>$thumb_img,
'imgurl_list'=>$imgurl_list,
]);
return $this->fetch('add');
}
//删除
public function del($id, Goods $model)
{
if (count($model->noDeletionId) > 0) {
if (is_array($id)) {
if (array_intersect($model->noDeletionId, $id)) {
return error('ID为' . implode(',', $model->noDeletionId) . '的数据无法删除');
}
} else if (in_array($id, $model->noDeletionId)) {
return error('ID为' . $id . '的数据无法删除');
}
}
if ($model->softDelete) {
$result = $model->whereIn('id', $id)->useSoftDelete('delete_time', time())->delete();
} else {
$result = $model->whereIn('id', $id)->delete();
}
return $result ? success('操作成功', URL_RELOAD) : error();
}
}

View File

@ -0,0 +1,105 @@
<?php
/**
* 后台首页控制器
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\controller;
use app\admin\model\AdminLog;
use app\admin\model\AdminMenu;
use app\admin\model\AdminRole;
use app\admin\model\AdminUser;
use tools\SystemInfo;
use think\Request;
use think\Db;
class IndexController extends Controller
{
public function index(Request $request)
{
//更新时间
$time = date('Y-m-d H:i:s', time());
//今日成交订单
$order_num_today = Db::name('order')
->where(['order_type' =>1])
->whereTime('create_time', 'today')
->count();
//昨日
$order_num_yesterday = Db::name('order')
->where(['order_type' =>1])
->whereTime('create_time', 'yesterday')
->count();
//变化
$order_num_change = $order_num_today - $order_num_yesterday;
if ($order_num_change >= 0) {
$order_num_change = '+' . $order_num_change;
}
//总
$order_num_all = Db::name('order')
->where(['order_type' =>1])
->count();
//今日销售金额(元)
$order_amount_today = Db::name('order')
->where(['order_type' =>1])
->whereTime('create_time', 'today')
->sum('order_price');
//昨日
$order_amount_yesterday = Db::name('order')
->where(['order_type' =>1])
->whereTime('create_time', 'yesterday')
->sum('order_price');
//总
$order_amount_all = Db::name('order')
->where(['order_type' =>1])
->sum('order_price');
//变化
$order_amount_change = $order_amount_today - $order_amount_yesterday;
if ($order_amount_change >= 0) {
$order_amount_change = '+' . $order_amount_change;
}
// 今天新增会员数量
$add_user_today = Db::name('user')
->whereTime('create_time', 'today')
->count();
//昨天
$add_user_yesterday = Db::name('user')
->whereTime('create_time', 'yesterday')
->count();
//总
$user_all = Db::name('user')
->count();
//变化
$add_change = $add_user_today - $add_user_yesterday;
if ($add_change >= 0) {
$add_change = '+' . $add_change;
}
$date=[
'time' => $time,
'order_num_today' => $order_num_today,
'order_num_yesterday' => $order_num_yesterday,
'order_num_change' => $order_num_change,
'order_amount_today' => $order_amount_today,
'order_amount_yesterday' => $order_amount_yesterday,
'order_amount_change' => $order_amount_change,
'add_user_today' => $add_user_today,
'add_user_yesterday' => $add_user_yesterday,
'add_user_change' => $add_change,
'order_num_all' => $order_num_all,
'order_amount_all' => $order_amount_all,
'user_all' => $user_all,
];
$this->assign([
'res'=>$date,
]);
return $this->fetch();
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* 订单控制器
*/
namespace app\admin\controller;
use think\Request;
use app\common\model\Order;
use app\common\validate\OrderValidate;
class OrderController extends Controller
{
//列表
public function index(Request $request, Order $model)
{
$param = $request->param();
$where = [];
//订单搜素
if (!empty($param['search_key']) && !empty($param['keyword'])) {
$keyword = $param['keyword'];
switch ($param['search_key']) {
case 'order_sn':
$where[] = ['o.order_sn', 'like', '%' . $keyword . '%'];
break;
case 'user_sn':
$where[] = ['u.sn', 'like', '%' . $keyword . '%'];
break;
case 'nickname':
$where[] = ['u.nickname', 'like', '%' . $keyword . '%'];
break;
case 'user_mobile':
$where[] = ['u.mobile', 'like', '%' . $keyword . '%'];
break;
}
}
//商品名称
if (isset($param['goods_name']) && $param['goods_name'] != '') {
$where[] = ['o.goods_name', 'like', '%' . $param['goods_name'] . '%'];
}
//订单类型
if (isset($param['order_type']) && $param['order_type'] != '') {
$where[] = ['o.order_type', '=', $param['order_type']];
}
//下单时间
if (isset($param['start_time']) && $param['start_time'] != '') {
$where[] = ['o.create_time', '>=', strtotime($param['start_time'])];
}
if (isset($param['end_time']) && $param['end_time'] != '') {
$where[] = ['o.create_time', '<=', strtotime($param['end_time'])];
}
$model = $model
->alias('o')
->field('o.*,u.mobile,u.nickname,u.sn,u.avatar')
->join('user u', 'u.id = o.user_id')
->where($where)
->order('o.id desc')
->group('o.id')
->scope('where', $param);
$data = $model->paginate($this->admin['per_page'], false, ['query'=>$request->get()]);
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
]);
return $this->fetch();
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* 公共控制器
*/
namespace app\admin\controller;
use app\common\model\Article;
use app\common\model\Goods;
use think\Request;
class PubController extends Controller
{
protected $authExcept = [
'admin/pub/getslidetargetdata'
];
public function getSlideTargetData(Request $request)
{
$param = $request->param();
switch ($param['type_id']) {
case 1:
$data = Goods::all();
break;
case 2:
$data = Article::all();
break;
default:
$data = Goods::all();
break;
}
return success('success', URL_CURRENT, $data);
}
}

View File

@ -0,0 +1,151 @@
<?php
/**
* 配置表控制器
*/
namespace app\admin\controller;
use think\Request;
use app\common\model\ShopConfig;
use app\common\model\Goods;
use app\common\validate\ShopConfigValidate;
class ShopConfigController extends Controller
{
//每日收益
public function shouyi(Request $request, ShopConfig $model, ShopConfigValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
ShopConfig::set('shouyi', 'time', $param['time']);
ShopConfig::set('shouyi', 'num', $param['num']);
$url = URL_RELOAD;
return success('添加成功',$url);
}
$config = [
'time' => ShopConfig::get('shouyi', 'time'),
'num' => ShopConfig::get('shouyi', 'num'),
];
$this->assign([
'config' => $config,
]);
return $this->fetch();
}
//分销管理
public function fenxiao(Request $request, ShopConfig $model, ShopConfigValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
ShopConfig::set('fenxiao', 'first_ratio', $param['first_ratio']);
ShopConfig::set('fenxiao', 'second_ratio', $param['second_ratio']);
ShopConfig::set('fenxiao', 'number', $param['number']);
$url = URL_RELOAD;
return success('添加成功',$url);
}
$config = [
'first_ratio' => ShopConfig::get('fenxiao', 'first_ratio'),
'second_ratio' => ShopConfig::get('fenxiao', 'second_ratio'),
'number' => ShopConfig::get('fenxiao', 'number'),
];
$this->assign([
'config' => $config,
]);
return $this->fetch();
}
//政策协议
public function policy(Request $request, ShopConfig $model, ShopConfigValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
ShopConfig::set('policy', 'integral_rule', $param['integral_rule']);
$url = URL_RELOAD;
return success('添加成功',$url);
}
$config = [
'integral_rule' => ShopConfig::get('policy', 'integral_rule'),
];
$this->assign([
'config' => $config,
]);
return $this->fetch();
}
//会员提现
public function withdraw(Request $request, ShopConfig $model, ShopConfigValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
ShopConfig::set('withdraw', 'min_withdraw', $param['min_withdraw']);
ShopConfig::set('withdraw', 'max_withdraw', $param['max_withdraw']);
ShopConfig::set('withdraw', 'poundage', $param['poundage']);
ShopConfig::set('withdraw', 'poundage_type', $param['poundage_type']);
$url = URL_RELOAD;
return success('添加成功',$url);
}
$config = [
'min_withdraw' => ShopConfig::get('withdraw', 'min_withdraw'),
'max_withdraw' => ShopConfig::get('withdraw', 'max_withdraw'),
'poundage' => ShopConfig::get('withdraw', 'poundage'),
'poundage_type' => ShopConfig::get('withdraw', 'poundage_type'),
];
$this->assign([
'config' => $config,
]);
return $this->fetch();
}
//试用设备设置
public function goods(Request $request, Goods $gmodel, ShopConfigValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
ShopConfig::set('goods', 'goods_id', $param['goods_id']);
ShopConfig::set('goods', 'day', $param['day']);
ShopConfig::set('goods', 'is_withdraw', $param['is_withdraw']);
ShopConfig::set('goods', 'is_first', $param['is_first']);
ShopConfig::set('goods', 'is_open', $param['is_open']);
$url = URL_RELOAD;
return success('添加成功',$url);
}
$config = [
'goods_id' => ShopConfig::get('goods', 'goods_id'),
'day' => ShopConfig::get('goods', 'day'),
'is_withdraw' => ShopConfig::get('goods', 'is_withdraw'),
'is_first' => ShopConfig::get('goods', 'is_first'),
'is_open' => ShopConfig::get('goods', 'is_open'),
'goods_list'=>Goods::all(),
];
$this->assign([
'config' => $config,
]);
return $this->fetch();
}
//网站设置
public function website(Request $request, ShopConfig $model, ShopConfigValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
ShopConfig::set('website', 'APPID', $param['APPID']);
ShopConfig::set('website', 'APPSECRET', $param['APPSECRET']);
ShopConfig::set('website', 'img_url', $param['img_url']);
ShopConfig::set('website', 'tel', $param['tel']);
$url = URL_RELOAD;
return success('添加成功',$url);
}
$config = [
'APPID' => ShopConfig::get('website', 'APPID'),
'APPSECRET' => ShopConfig::get('website', 'APPSECRET'),
'img_url' => ShopConfig::get('website', 'img_url'),
'tel' => ShopConfig::get('website', 'tel'),
];
$this->assign([
'config' => $config,
]);
return $this->fetch();
}
}

View File

@ -0,0 +1,110 @@
<?php
/**
* 轮播控制器
*/
namespace app\admin\controller;
use think\Request;
use app\common\model\Slide;
use app\common\validate\SlideValidate;
class SlideController extends Controller
{
//列表
public function index(Request $request, Slide $model)
{
$param = $request->param();
$model = $model->scope('where', $param);
$data = $model->paginate($this->admin['per_page'], false, ['query' => $request->get()]);
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
]);
return $this->fetch();
}
//添加
public function add(Request $request, Slide $model, SlideValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('add')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $model::create($param);
$url = URL_BACK;
if (isset($param['_create']) && $param['_create'] == 1) {
$url = URL_RELOAD;
}
return $result ? success('添加成功', $url) : error();
}
$this->assign([
'jump_type' => $model->jumpType,
'banner_list' => $model->BannerList,
]);
return $this->fetch();
}
//修改
public function edit($id, Request $request, Slide $model, SlideValidate $validate)
{
$data = $model::get($id);
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('edit')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
$result = $data->save($param);
return $result ? success() : error();
}
$this->assign([
'data' => $data,
'jump_type' => $model->jumpType,
'banner_list' => $model->BannerList,
]);
return $this->fetch('add');
}
//删除
public function del($id, Slide $model)
{
if (count($model->noDeletionId) > 0) {
if (is_array($id)) {
if (array_intersect($model->noDeletionId, $id)) {
return error('ID为' . implode(',', $model->noDeletionId) . '的数据无法删除');
}
} else if (in_array($id, $model->noDeletionId)) {
return error('ID为' . $id . '的数据无法删除');
}
}
if ($model->softDelete) {
$result = $model->whereIn('id', $id)->useSoftDelete('delete_time', time())->delete();
} else {
$result = $model->whereIn('id', $id)->delete();
}
return $result ? success('操作成功', URL_RELOAD) : error();
}
}

View File

@ -0,0 +1,20 @@
<?php
/**
* 统计示例控制器
*/
namespace app\admin\controller;
class StatisticsController extends Controller
{
//统计概览
public function index()
{
return $this->fetch();
}
}

View File

@ -0,0 +1,214 @@
<?php
/**
* 用户控制器
*/
namespace app\admin\controller;
use think\Request;
use app\common\model\User;
use app\common\model\Order;
use app\common\model\Goods;
use app\common\validate\UserValidate;
use app\common\validate\OrderValidate;
class UserController extends Controller
{
//列表
public function index(Request $request, User $model)
{
$param = $request->param();
$where = [];
//查询
if(isset($param['keyword']) && $param['keyword']){
$where[] = [$param['keyword_type'],'like','%'.$param['keyword'].'%'];
}
//等级查询
if(isset($param['level']) && $param['level'] != ''){
$where[] = ['user_level_id','=',$param['level']];
}
//提现积分
if(isset($param['integral_start']) && $param['integral_start']){
$where[] = ['integral','>=',$param['integral_start']];
}
if(isset($param['integral_end']) && $param['integral_end']){
$where[] = ['integral','<=',$param['integral_end']];
}
//注册时间
if(isset($param['start_time']) && $param['start_time']!=''){
$where[] = ['create_time','>=',strtotime($param['start_time'])];
}
if(isset($param['end_time']) && $param['end_time']!=''){
$where[] = ['create_time','<=',strtotime($param['end_time'])];
}
$model = $model->where($where)->scope('where', $param);
$data = $model->paginate($this->admin['per_page'], false, ['query' => $request->get()]);
foreach ($data as $key => $value) {
// 上级推荐人
$value['first_leader_info'] = User::getUserInfo($value['first_leader']);
//推荐下级人数
$value['fans'] = User::where([
['first_leader|second_leader', '=', $value['id']]
])->count();
//设备数量
$value['sb_num'] = Order::where([
['user_id', '=', $value['id']]
])->count();
}
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
]);
return $this->fetch();
}
//添加
public function add(Request $request, User $model, UserValidate $validate)
{
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('add')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
//处理头像上传
$attachment_avatar = new \app\common\model\Attachment;
$file_avatar = $attachment_avatar->upload('avatar');
if ($file_avatar) {
$param['avatar'] = $file_avatar->url;
} else {
return error($attachment_avatar->getError());
}
$result = $model::create($param);
$url = URL_BACK;
if (isset($param['_create']) && $param['_create'] == 1) {
$url = URL_RELOAD;
}
return $result ? success('添加成功', $url) : error();
}
return $this->fetch();
}
//修改
public function edit($id, Request $request, User $model, UserValidate $validate)
{
$data = $model::get($id);
if ($request->isPost()) {
$param = $request->param();
$validate_result = $validate->scene('edit')->check($param);
if (!$validate_result) {
return error($validate->getError());
}
//处理头像上传
if (!empty($_FILES['avatar']['name'])) {
$attachment_avatar = new \app\common\model\Attachment;
$file_avatar = $attachment_avatar->upload('avatar');
if ($file_avatar) {
$param['avatar'] = $file_avatar->url;
}
}
$result = $data->save($param);
return $result ? success() : error();
}
$this->assign([
'data' => $data,
]);
return $this->fetch('add');
}
//删除
public function del($id, User $model)
{
if (count($model->noDeletionId) > 0) {
if (is_array($id)) {
if (array_intersect($model->noDeletionId, $id)) {
return error('ID为' . implode(',', $model->noDeletionId) . '的数据无法删除');
}
} else if (in_array($id, $model->noDeletionId)) {
return error('ID为' . $id . '的数据无法删除');
}
}
if ($model->softDelete) {
$result = $model->whereIn('id', $id)->useSoftDelete('delete_time', time())->delete();
} else {
$result = $model->whereIn('id', $id)->delete();
}
return $result ? success('操作成功', URL_RELOAD) : error();
}
//启用
public function enable($id, User $model)
{
$result = $model->whereIn('id', $id)->update(['status' => 1]);
return $result ? success('操作成功', URL_RELOAD) : error();
}
//禁用
public function disable($id, User $model)
{
$result = $model->whereIn('id', $id)->update(['status' => 0]);
return $result ? success('操作成功', URL_RELOAD) : error();
}
//分配设备
public function equipmentadd(Request $request,Order $omodel)
{
if ($request->isPost()) {
$param = $request->param();
$goods_ids=$param['goods_id'];
if(count($goods_ids)==0){
return error('请选择设备信息');
}
$field_data = array();
foreach ($goods_ids as $key => $value) {
if($param['goods_id'][$key][0] && $param['number'][$key][0] && $param['end_time'][$key][0]){
$goods_info=Goods::where(array('id'=>$param['goods_id'][$key][0]))->find()->toArray();
$field_data[] = [
'order_no'=>get_order_sn(),
'goods_id' => $param['goods_id'][$key][0],
'number' => $param['number'][$key][0],
'end_time' => strtotime($param['end_time'][$key][0]),
'user_id' => $param['id'],
'goods_name' => $goods_info['name'],
'attr' => $goods_info['attr'],
'order_price' => $goods_info['price']*$param['number'][$key][0],
'create_time'=>time(),
];
}
}
if(count($field_data)==0){
return error('请检查设备信息是否填写完整');
}
$result = $omodel->insertAll($field_data);
$url = URL_BACK;
if (isset($param['_create']) && $param['_create'] == 1) {
$url = URL_RELOAD;
}
return $result ? success('添加成功', $url) : error();
}
$this->assign([
'goods_list' => Goods::all(),
]);
return $this->fetch();
}
}

View File

@ -0,0 +1,149 @@
<?php
/**
* 提现申请记录表控制器
*/
namespace app\admin\controller;
use think\Request;
use app\common\model\WithdrawApply;
use app\common\model\AccountLog;
use app\common\model\User;
use app\common\validate\WithdrawApplyValidate;
class WithdrawController extends Controller
{
//列表
public function lists(Request $request, WithdrawApply $model)
{
$WITHDRAW_TYPE=$model->WITHDRAW_TYPE;
$STATUS_TYPE=$model->STATUS_TYPE;
$param = $request->param();
$where = [];
// 会员信息
if (!empty($param['search_key']) && !empty($param['keyword'])) {
$keyword = $param['keyword'];
if ($param['search_key'] == 'user_sn') {
$where[] = ['u.sn', '=', $keyword];
} elseif ($param['search_key'] == 'nickname'){
$where[] = ['u.nickname', 'like', '%' . $keyword . '%'];
}
}
//提现单号
if (isset($param['withdraw_sn']) && $param['withdraw_sn'] != '') {
$where[] = ['w.sn', '=', $param['withdraw_sn']];
}
//提现方式
if (isset($param['type']) && $param['type'] != '') {
$where[] = ['type', '=', $param['type']];
}
//提现状态
if (isset($param['status']) && $param['status'] != '') {
$where[] = ['w.status', '=', $param['status']];
}
// 提现时间
if (isset($param['start_time']) && $param['start_time'] && isset($param['end_time']) && $param['end_time']) {
$where[] = ['w.create_time', 'between', [strtotime($param['start_time']), strtotime($param['end_time'])]];
}
$model = $model
->alias('w')
->field('w.*,u.mobile,u.nickname,u.sn as user_sn,u.avatar')
->join('user u', 'u.id = w.user_id')
->where($where)
->scope('where', $param);
$data = $model->paginate($this->admin['per_page'], false, ['query'=>$request->get()]);
//关键词,排序等赋值
$this->assign($request->get());
$this->assign([
'data' => $data,
'page' => $data->render(),
'total' => $data->total(),
'type_list' =>$WITHDRAW_TYPE,
'status_list'=>$STATUS_TYPE,
]);
return $this->fetch();
}
public function review($id,Request $request, WithdrawApply $model)
{
$this->assign([
'id' => $id,
]);
return $this->fetch();
}
//审核通过
public function confirm(Request $request, WithdrawApply $model)
{
$param = $request->param();
$id = $param['id'];
$withdraw =$model
->where('id', $id)
->find();
// 判断提现单是否为待提现状态 1
if($withdraw['status'] != 1) {
return error('不是待提现申请单');
}
// 启动事务
$model->startTrans();
try{
// 直接标识为审核成功状态
$model
->where('id', $id)
->update(['status' =>2, 'update_time' => time(),'description'=>$param['description']]);
// 提交事务
$model->commit();
}catch(\Exception $e){
// 回滚事务
$model->rollback();
return error($e->getMessage());
}
return success('审核通过');
}
//审核拒绝
public function refuse(Request $request, WithdrawApply $model)
{
$model->startTrans();
$param = $request->param();
try{
$withdraw_apply = WithdrawApply::where('id', $param['id'])->find();
$withdraw_apply->status =3; // 提现失败
$withdraw_apply->description = $param['description'];
$withdraw_apply->update_time = time();
$withdraw_apply->save();
//拒绝提现,回退佣金
$user = User::get($withdraw_apply['user_id']);
$user->integral = ['inc', $withdraw_apply['money']];
$user->save();
//增加账户变动记录
AccountLog::AccountRecord(
$withdraw_apply['user_id'],
$withdraw_apply['money'],
1,
130,
'',
$withdraw_apply['id'],
$withdraw_apply['sn']
);
$model->commit();
} catch (Exception $e){
$model->rollback();
return error($e->getMessage());
}
return success('提现失败已回退用户账户');
}
}

View File

@ -0,0 +1,47 @@
<?php
/**
* 后台操作日志模型
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\model;
class AdminLog extends Model
{
protected $name = 'admin_log';
public $softDelete = false;
public $methodText = [
1=>'GET',
2=>'POST',
3=>'PUT',
4=>'DELETE',
];
protected $autoWriteTimestamp = true;
protected $updateTime= false;
protected $searchField = [
'name',
'url',
'log_ip'
];
protected $whereField = [
'admin_user_id'
];
//关联用户
public function adminUser()
{
return $this->belongsTo(AdminUser::class, 'admin_user_id', 'id');
}
//关联详情
public function adminLogData()
{
return $this->hasOne(AdminLogData::class,'admin_log_id','id');
}
}

View File

@ -0,0 +1,29 @@
<?php
/**
* 后台管理员操作日志数据模型
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\model;
use tools\Crypt;
class AdminLogData extends Model
{
protected $name = 'admin_log_data';
public $softDelete = false;
//关联log
public function adminLog()
{
return $this->belongsTo('app\admin\AdminLog','admin_log_id','id');
}
public function getDataAttr($value)
{
$data = Crypt::decrypt($value, config('app.app_key'));
return json_encode(json_decode($data, true), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* 后台菜单(权限)模型
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\model;
class AdminMenu extends Model
{
protected $name = 'admin_menu';
public $softDelete = false;
public $logMethod = [
0 => '不记录',
1 => 'GET',
2 => 'POST',
3 => 'PUT',
4 => 'DELETE'
];
public $noDeletionId = [
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
];
}

View File

@ -0,0 +1,41 @@
<?php
/**
* 后台角色模型
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\model;
class AdminRole extends Model
{
protected $name = 'admin_role';
public $softDelete = false;
protected $searchField = [
'name',
'description'
];
public $noDeletionId = [
1
];
public static function init()
{
//添加首页,系统管理,个人资料菜单/权限
self::event('before_insert', static function ($data) {
$data->url = [1,2,18];
});
}
protected function getUrlAttr($value)
{
return $value !== '' ? explode(',', $value) : [];
}
protected function setUrlAttr($value)
{
return $value !== '' ? implode(',', $value) : [];
}
}

View File

@ -0,0 +1,142 @@
<?php
/**
* 后台用户模型
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\model;
use think\model\concern\SoftDelete;
/**
* @property int id
* @property mixed sign_str
* @property mixed auth_url
* @property mixed role
* @property string password
*/
class AdminUser extends Model
{
use SoftDelete;
protected $name = 'admin_user';
protected $searchField = [
'nickname',
'username'
];
public $noDeletionId = [
1, 2
];
public static function init()
{
//添加自动加密密码
self::event('before_insert', static function ($data) {
$data->password = password_hash($data->password, 1);
});
//修改密码自动加密
self::event('before_update', function ($data) {
$old = (new static())::get($data->id);
if ($data->password !== $old->password) {
$data->password = password_hash($data->password, 1);
}
});
}
//关联操作日志
public function adminLog()
{
return $this->hasMany(AdminLog::class, 'admin_user_id', 'id');
}
//角色获取器
protected function getRoleAttr($value)
{
return explode(',', $value);
}
//角色修改器
protected function setRoleAttr($value)
{
return implode(',', $value);
}
//用户角色名称
protected function getRoleTextAttr($value, $data)
{
return AdminRole::where('id', 'in', $data['role'])->column('id,name', 'id');
}
/**
* 获取已授权url
* @param $value
* @param $data
* @return array
*/
protected function getAuthUrlAttr($value, $data)
{
$role_urls = AdminRole::where('id', 'in', $data['role'])->where('status', 1)->column('url');
$url_id_str = '';
foreach ($role_urls as $key => $val) {
$url_id_str .= $key == 0 ? $val : ',' . $val;
}
$url_id = array_unique(explode(',', $url_id_str));
$auth_url = [];
if (count($url_id) > 0) {
$auth_url = AdminMenu::where('id', 'in', $url_id)->column('url');
}
return $auth_url;
}
//加密字符串,用在登录的时候加密处理
protected function getSignStrAttr($value, $data)
{
$ua = request()->header('user-agent');
return sha1($data['id'] . $data['username'] . $ua);
}
//获取当前用户已授权的显示菜单
public function getShowMenu()
{
if ($this->id === 1) {
return AdminMenu::where('is_show', 1)->order('sort_id', 'asc')->order('id', 'asc')->column('id,parent_id,name,url,icon,sort_id', 'id');
}
$role_urls = AdminRole::where('id', 'in', $this->role)->where('status', 1)->column('url');
$url_id_str = '';
foreach ($role_urls as $key => $val) {
$url_id_str .= $key == 0 ? $val : ',' . $val;
}
$url_id = array_unique(explode(',', $url_id_str));
return AdminMenu::where('id', 'in', $url_id)->where('is_show', 1)->order('sort_id', 'asc')->order('id', 'asc')->column('id,parent_id,name,url,icon,sort_id', 'id');
}
//用户登录
public static function login($param)
{
$username = $param['username'];
$password = $param['password'];
$user = self::get(['username' => $username]);
if (!$user) {
exception('用户不存在');
}
if (!password_verify($password, $user->password)) {
exception('密码错误');
}
if ((int)$user->status !== 1) {
exception('用户被冻结');
}
return $user;
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* 后台基础模型
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\model;
use think\db\Query;
class Model extends \think\Model
{
//是否字段,使用场景:用户的是否冻结,文章是否为热门等等。
const BOOLEAN_TEXT = [0 => '否', 1 => '是'];
//是否为软删除
public $softDelete = true;
//软删除字段默认值
protected $defaultSoftDelete = 0;
//可搜索字段
protected $searchField = [];
//可作为条件的字段
protected $whereField = [];
//禁止删除的数据id
public $noDeletionId = [];
/**
* 查询处理
* @var Query $query
* @var array $param
*/
public function scopeWhere($query, $param)
{
//关键词like搜索
$keywords = $param['_keywords'] ?? '';
if (!empty($keywords) && count($this->searchField) > 0) {
$this->searchField = implode('|', $this->searchField);
$query->where($this->searchField, 'like', '%' . $keywords . '%');
}
//字段条件查询
if (count($this->whereField) > 0 && count($param) > 0) {
foreach ($param as $key => $value) {
if (!empty($value) && in_array($key, $this->whereField)) {
$query->where($key, $value);
}
}
}
//排序
$order = $param['_order'] ?? '';
$by = $param['_by'] ?? 'desc';
$query->order($order ?: 'id', $by ?: 'desc');
}
//状态获取器
public function getStatusTextAttr($value, $data)
{
return self::BOOLEAN_TEXT[$data['status']];
}
}

View File

@ -0,0 +1,133 @@
<?php
/**
* 登录、退出、记录日志相关
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\traits;
use app\admin\model\AdminLog;
use app\admin\model\AdminUser;
use tools\Crypt;
use tools\SafeCookie;
use think\facade\Session;
trait AdminAuth
{
public static $admin_user_id = 'admin_user_id';
public static $admin_user_id_sign = 'admin_user_sign';
//是否登录
protected function isLogin()
{
//这里要写个判断数据库的才行
$admin_user_id = Session::get(self::$admin_user_id);
$user = false;
$this->user = &$user;
if (empty($admin_user_id)) {
if (SafeCookie::has(self::$admin_user_id) && SafeCookie::has(self::$admin_user_id_sign)) {
$admin_user_id = SafeCookie::get(self::$admin_user_id);
$sign = SafeCookie::get(self::$admin_user_id_sign);
$user = AdminUser::get($admin_user_id);
if ($user && $user->sign_str === $sign) {
Session::set(self::$admin_user_id, $admin_user_id);
Session::set(self::$admin_user_id_sign, $sign);
return true;
}
}
return false;
}
$user = AdminUser::get($admin_user_id);
if(!$user) {
return false;
}
$this->uid = $user->id;
return Session::get(self::$admin_user_id_sign) === $user->sign_str;
}
/**
* session 与cookie登录
* @param $user AdminUser
* @param bool $remember
* @return bool
*/
public static function authLogin($user, $remember = false)
{
Session::set(self::$admin_user_id, $user->id);
Session::set(self::$admin_user_id_sign, $user->sign_str);
//记住登录
if ($remember === true) {
SafeCookie::set(self::$admin_user_id, $user->id);
SafeCookie::set(self::$admin_user_id_sign, $user->sign_str);
} else if (SafeCookie::has(self::$admin_user_id) || SafeCookie::has(self::$admin_user_id_sign)) {
SafeCookie::delete(self::$admin_user_id);
SafeCookie::delete(self::$admin_user_id_sign);
}
//记录登录日志
self::loginLog($user);
return true;
}
//退出
public static function authLogout()
{
Session::delete(self::$admin_user_id);
Session::delete(self::$admin_user_id_sign);
if (SafeCookie::has(self::$admin_user_id) || SafeCookie::has(self::$admin_user_id_sign)) {
SafeCookie::delete(self::$admin_user_id);
SafeCookie::delete(self::$admin_user_id_sign);
}
return true;
}
/**
* 权限检查
* @param $user AdminUser
* @return bool
*/
public function authCheck($user)
{
return in_array($this->url, $this->authExcept, true) || in_array($this->url, $user->auth_url, true);
}
//登录记录
public static function loginLog($user)
{
$data = AdminLog::create([
'admin_user_id' => $user->id,
'name' => '登录',
'url' => 'admin/auth/login',
'log_method' => 'POST',
'log_ip' => request()->ip()
]);
$crypt_data = Crypt::encrypt(json_encode(request()->param()), config('app.app_key'));
$log_data = [
'data' => $crypt_data
];
$data->adminLogData()->save($log_data);
}
//创建操作日志
public function createAdminLog($user, $menu)
{
$data = [
'admin_user_id' => $user->id,
'name' => $menu->name,
'log_method' => $menu->log_method,
'url' => request()->pathinfo(),
'log_ip' => request()->ip()
];
$log = AdminLog::create($data);
//加密数据,防脱库
$crypt_data = Crypt::encrypt(json_encode(request()->param()), config('app.app_key'));
$log_data = [
'data' => $crypt_data
];
$log->adminLogData()->save($log_data);
}
}

View File

@ -0,0 +1,375 @@
<?php
/**
* 后台tree(左侧菜单,菜单列表,权限操作)相关
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\traits;
use app\admin\model\AdminUser;
trait AdminTree
{
public $text, $html;
/**
* 生成树型结构所需要的2维数组
* @var array
*/
public $array;
/**
* 生成树型结构所需修饰符号,可以换成图片
* @var array
*/
public $icon = array('│', '├', '└');
public $space = '&nbsp;&nbsp;';
/**
* @access private
*/
public $ret = '';
/**
* 构造函数,初始化类
* @param array $arr
* @return bool
*/
public function initTree($arr=[])
{
$this->array = $arr;
$this->ret = '';
$this->html = '';
return is_array($arr);
}
/**
* 得到树型结构
* @param int $my_id ,表示获得这个ID下的所有子级
* @param string $str 生成树型结构的基本代码,例如:"<option value=\$id \$selected>\$spacer\$name</option>"
* @param int $sid 被选中的ID,比如在做树型下拉框的时候需要用到
* @param string $adds
* @param string $str_group
* @return string
*/
public function getTree($my_id, $str, $sid = 0, $adds = '', $str_group = '')
{
$parent_id = '';
$n_str = '';
$number = 1;
$child = $this->getChild($my_id);
if (is_array($child)) {
$total = count($child);
foreach ($child as $id => $value) {
$j = $k = '';
if ($number == $total) {
$j .= $this->icon[2];
} else {
$j .= $this->icon[1];
$k = $adds ? $this->icon[0] : '';
}
$spacer = $adds ? $adds . $j : '';
$selected = $id == $sid ? 'selected' : '';
extract($value);
0 == $parent_id && $str_group ? eval("\$n_str = \"$str_group\";") : eval("\$n_str = \"$str\";");
$this->ret .= $n_str;
$space = $this->space;
$this->getTree($id, $str, $sid, $adds . $k . $space, $str_group);
$number++;
}
}
return $this->ret;
}
/**
* 获取后台左侧菜单
* @param $my_id
* @param $current_id
* @param $parent_ids
* @return mixed
*/
public function get_authTree($my_id, $current_id, $parent_ids)
{
$n_str = '';
$child = $this->getChild($my_id);
if (is_array($child)) {
$menu = current($child);
//获取当前等级的html
$text = $this->text[$menu['level']] ?? end($this->text);
foreach ($child as $k => $v) {
@extract($v);
//如果有下级菜单
if ($this->getChild($k)) {
if (in_array($k, $parent_ids, true)) {
//如果下级菜单是当前页面
eval("\$n_str = \"$text[1]\";");
$this->html .= $n_str;
} else {
//如果下级菜单不是当前页面
eval("\$n_str = \"$text[0]\";");
$this->html .= $n_str;
}
self::get_authTree($k, $current_id, $parent_ids);
eval("\$n_str = \"$text[2]\";");
$this->html .= $n_str;
} else if ($k == $current_id) {
$a = $this->text['current'];
eval("\$n_str = \"$a\";");
$this->html .= $n_str;
} else {
$a = $this->text['other'];
eval("\$n_str = \"$a\";");
$this->html .= $n_str;
}
}
}
return $this->html;
}
/**
* 得到子级数组
* @param int $pid
* @return bool|array
*/
public function getChild($pid)
{
$result = [];
foreach ($this->array as $key => $value) {
if ($value['parent_id'] == $pid) {
$result[$key] = $value;
}
}
return $result;
}
/**
* 递归获取级别
* @param int $id ID
* @param array $array 所有菜单
* @param int $i 所在级别
* @return int
*/
public function getLevel($id, $array, $i = 0)
{
if ($array[$id]['parent_id'] == 0 || empty($array[$array[$id]['parent_id']]) || $array[$id]['parent_id'] == $id) {
return $i;
}
$i++;
return self::getLevel($array[$id]['parent_id'], $array, $i);
}
//获取权限树
public function getAuthTreeAccess($my_id)
{
$id = '';
$n_str = '';
$child = $this->getChild($my_id);
if (is_array($child)) {
$level = current($child);
$text = $this->text[$level['level']] ?? end($this->text);
foreach ($child as $k => $v) {
@extract($v);
if ($this->getChild($k)) {
eval("\$n_str = \"$text[0]\";");
$this->html .= $n_str;
self::getAuthTreeAccess($k);
eval("\$n_str = \"$text[1]\";");
$this->html .= $n_str;
} else {
$a = $this->text['other'];
eval("\$n_str = \"$a\";");
$this->html .= $n_str;
}
}
}
return $this->html;
}
/**
* 获取左侧菜单
* @param $user AdminUser
* @return mixed
*/
protected function getLeftMenu($user)
{
$menu = $user->getShowMenu();
$max_level = 0;
$current_id = 1;
$parent_ids = array(0 => 0);
foreach ($menu as $k => $v) {
if ($v['url'] == $this->url) {
$parent_ids = $this->getMenuParent($menu, $v['id']);
$current_id = $v['id'];
}
}
if ($parent_ids == false) {
$parent_ids = array(0 => 0);
}
foreach ($menu as $k => $v) {
$url = url($v['url']);
$menu[$k]['icon'] = $v['icon'];
$menu[$k]['level'] = $this->getLevel($v['id'], $menu);
$max_level = $max_level <= $menu[$k]['level'] ? $menu[$k]['level'] : $max_level;
$menu[$k]['url'] = $url;
}
$this->initTree($menu);
$text_base_one = "<li class='treeview";
$text_hover = ' active';
$text_base_two = "'><a href='javascript:void(0);'>
<i class='fa \$icon'></i>
<span>
\$name
</span>
<span class='pull-right-container'><i class='fa fa-angle-left pull-right'></i></span>
</a><ul class='treeview-menu";
$text_open = ' menu-open';
$text_base_three = "'>";
$text_base_four = '<li';
$text_hover_li = " class='active'";
$text_base_five = ">
<a href='\$url'>
<i class='fa \$icon'></i>
<span>\$name</span>
</a>
</li>";
$text_0 = $text_base_one . $text_base_two . $text_base_three;
$text_1 = $text_base_one . $text_hover . $text_base_two . $text_open . $text_base_three;
$text_2 = '</ul></li>';
$text_current = $text_base_four . $text_hover_li . $text_base_five;
$text_other = $text_base_four . $text_base_five;
for ($i = 0; $i <= $max_level; $i++) {
$this->text[$i]['0'] = $text_0;
$this->text[$i]['1'] = $text_1;
$this->text[$i]['2'] = $text_2;
}
$this->text['current'] = $text_current;
$this->text['other'] = $text_other;
return $this->get_authTree(0, $current_id, $parent_ids);
}
//获取父级菜单
protected function getMenuParent($arr, $my_id, $parent_ids = array())
{
$a = array();
if (is_array($arr)) {
foreach ($arr as $id => $a) {
if (($a['id'] === $my_id) && $a['parent_id'] !== 0) {
$parent_ids[] = $a['parent_id'];
$parent_ids = $this->getMenuParent($arr, $a['parent_id'], $parent_ids);
}
}
}
return !empty($parent_ids) ? $parent_ids : false;
}
//获取当前导航
protected function getCurrentNav($arr, $my_id, $parent_ids = array(), $current_nav = '')
{
$a = array();
if (is_array($arr)) {
foreach ($arr as $id => $a) {
if (($a['id'] === $my_id) && $a['parent_id'] !== 0) {
$parent_ids[] = $a['parent_id'];
$ru = '<li><a><i class="fa ' . $a['icon'] . '"></i> ' . $a['name'] . '</a></li>';
$current_nav = $ru . $current_nav;
$temp_result = $this->getCurrentNav($arr, $a['parent_id'], $parent_ids, $current_nav);
$parent_ids = $temp_result[0];
$current_nav = $temp_result[1];
}
}
}
return !empty([$parent_ids, $current_nav]) ? [$parent_ids, $current_nav] : false;
}
/**
* 获取树形数据列表
* @param $model
* @return string
*/
protected function getTreeList($model)
{
$data = $model->column('id,name,parent_id', 'id');
foreach ($data as $key => $value) {
//左侧选择
$data[$key]['select_html'] = '<td>
<input type="checkbox" onclick="checkThis(this)" name="data-checkbox"
data-id="' . $value['id'] . '" class="checkbox data-list-check" value="' . $value['id'] . '"
placeholder="选择/取消">
</td>';
//右侧操作
$data[$key]['todo_html'] = '<td class="td-do">
<a href="' . url('edit', ['id' => $value['id']]) . '"
class="btn btn-primary btn-xs" title="修改" data-toggle="tooltip">
<i class="fa fa-pencil"></i>
</a>
<a class="btn btn-danger btn-xs AjaxButton" data-toggle="tooltip" title="删除"
data-id="' . $value['id'] . '" data-confirm-title="删除确认"
data-confirm-content=\'您确定要删除ID为 <span class="text-red">' . $value['id'] . '</span> 的数据吗\'
data-url="' . url('del') . '" >
<i class="fa fa-trash"></i>
</a>
</td>';
}
$this->initTree($data);
$html = "<tr>
\$select_html
<td>\$id</td>
<td>\$spacer \$name</td>
\$todo_html
</tr>";
return $this->getTree(0, $html);
}
/**
* 获取树形选择列表
* @param $model
* @param int $selected
* @return string
*/
protected function getSelectList($model, $selected = 0)
{
$data = $model->column('id,parent_id,name', 'id');
$html = "<option value='\$id' \$selected >\$spacer \$name</option>";
$this->initTree($data);
return $this->getTree(0, $html, $selected);
}
}

View File

@ -0,0 +1,12 @@
<?php
/**
* 登录验证码
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\traits;
class LoginCaptcha
{
}

View File

@ -0,0 +1,81 @@
<?php
/**
* phpOffice相关操作
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\traits;
use Exception;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
trait PhpOffice
{
public function exportData($head, $body, $name = '', $version = '2007',$title='导出记录')
{
try {
// 输出 Excel 文件头
if(empty($name)){
$name =date('Y-m-d-H-i-s');
}
$spreadsheet = new Spreadsheet();
$sheetPHPExcel = $spreadsheet->setActiveSheetIndex(0);
$char_index = range('A', 'Z');
//处理超过26列
$a = 'A';
foreach ($char_index as $item){
$char_index[] = $a . $item;
}
// Excel 表格头
foreach ($head as $key => $val) {
$sheetPHPExcel->setCellValue("{$char_index[$key]}1", $val);
}
$spreadsheet->getActiveSheet()->setTitle($title);
// Excel body 部分
foreach ($body as $key => $val) {
$row = $key + 2;
$col = 0;
foreach ($val as $k => $v) {
$spreadsheet->getActiveSheet()->setCellValue("{$char_index[$col]}{$row}", $v);
$col++;
}
}
// 版本差异信息
$version_opt = [
'2007' => [
'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'ext' => '.xlsx',
'write_type' => 'Xlsx',
],
'2003' => ['mime' => 'application/vnd.ms-excel',
'ext' => '.xls',
'write_type' => 'Xls',
],
'pdf' => ['mime' => 'application/pdf',
'ext' => '.pdf',
'write_type' => 'PDF',
],
'ods' => ['mime' => 'application/vnd.oasis.opendocument.spreadsheet',
'ext' => '.ods',
'write_type' => 'OpenDocument',
],
];
header('Content-Type: ' . $version_opt[$version]['mime']);
header('Content-Disposition: attachment;filename="' . $name . $version_opt[$version]['ext'] . '"');
header('Cache-Control: max-age=0');
$objWriter = IOFactory::createWriter($spreadsheet, 'Xlsx');
return $objWriter->save('php://output');
} catch (Exception $e) {
return $e->getMessage();
}
}
}

View File

@ -0,0 +1,29 @@
<?php
/**
* 后台菜单证类
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\validate;
class AdminMenuValidate extends Validate
{
protected $rule = [
'parent_id|上级' => 'require|egt:0',
'name|名称' => 'require',
'url|url' => 'require|unique:admin_menu',
'icon|图标' => 'require',
'sort_id|排序' => 'require',
'is_show|是否显示' => 'require',
'log_method|记录类型' => 'require',
];
protected $message = [
'parent_id.egt' => '请选择上级菜单',
];
protected $scene = [
'add' => ['parent_id', 'title', 'url', 'icon', 'sort_id', 'is_show', 'log_method'],
'edit' => ['parent_id', 'title', 'url', 'icon', 'sort_id', 'is_show', 'log_method'],
];
}

View File

@ -0,0 +1,21 @@
<?php
/**
* 后台角色验证类
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\validate;
class AdminRoleValidate extends Validate
{
protected $rule = [
'name|名称' => 'require|unique:admin_role',
'description|介绍' => 'require',
'rules|权限' => 'require',
];
protected $scene = [
'add' => ['name', 'description'],
'edit' => ['name', 'description'],
];
}

View File

@ -0,0 +1,38 @@
<?php
/**
* 后台用户验类
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\validate;
class AdminUserValidate extends Validate
{
protected $rule = [
'username|帐号' => 'require|unique:admin_user',
'password|密码' => 'require',
'new_password|新密码' => 'require',
'renew_password|确认新密码' => 'require|confirm:new_password',
'nickname|昵称' => 'require',
'role|角色' => 'require',
'status|状态' => 'require',
];
protected $message = [
'role.require' => '请选择角色',
];
protected $scene = [
'add' => ['username', 'password', 'nickname', 'role'],
'edit' => ['username', 'nickname', 'role'],
'password' => ['password', 'new_password', 'renew_password'],
'nickname' => ['nickname'],
];
public function sceneLogin()
{
$this->only(['username', 'password'])
->remove('username', 'unique');
}
}

View File

@ -0,0 +1,12 @@
<?php
/**
* 后台基础验证类
* @author yupoxiong<i@yufuping.com>
*/
namespace app\admin\validate;
class Validate extends \think\Validate
{
}

View File

@ -0,0 +1,174 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<style type="text/css">
.layui-table-cell {
height: auto;
white-space: normal;
}
.layui-card-header.layuiadmin-card-header-auto {
padding-top: 15px;
padding-bottom: 15px;
height: auto;
}
.layui-form-label{ width:100px; }
</style>
<!--数据列表页面-->
<section class="content">
<!--顶部搜索筛选-->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('integrallist')}" method="GET">
<div class="layui-form layui-card-header layuiadmin-card-header-auto">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">订单搜索:</label>
<div class="layui-input-inline" style="width: 200px;">
<select name="keyword_type" id="keyword_type">
<option value="sn" {if isset($keyword_type) && $keyword_type=='sn'}selected{/if}>会员编号</option>
<option value="nickname" {if isset($keyword_type) && $keyword_type=='nickname'}selected{/if}>会员昵称</option>
<option value="mobile" {if isset($keyword_type) && $keyword_type=='mobile'}selected{/if}>会员手机号码</option>
</select>
</div>
<div class="layui-input-inline" style="width: 200px;">
<input type="text" id="keyword" name="keyword" value="{$keyword?$keyword:'';}" placeholder="请输入关键词" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">变动类型:</label>
<div class="layui-input-inline">
<select name="source_type" id="source_type">
<option value="0">全部</option>
{foreach $source_type_list as $key => $value}
<option value="{$key}" {if isset($source_type) && $source_type==$key}selected{/if}>{$value}</option>
{/foreach}
</select>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">下单时间:</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="start_time" name="start_time" value="{$start_time?$start_time:'';}" autocomplete="off">
</div>
<div class="layui-input-inline" style="margin-right: 5px;width: 10px;">
<label class="layui-form-mid">-</label>
</div>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="end_time" name="end_time" value="{$end_time?$end_time:'';}" autocomplete="off">
</div>
</div>
<div class="layui-inline">
<div class="layui-inline">
<button class="btn btn-success btn-sm" type="submit" >查询</button>
</div>
<div class="layui-inline">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<!--数据列表顶部-->
<div class="box-header">
<div>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>流水单号(20位)</th>
<th>会员昵称</th>
<th>会员编号</th>
<th>手机号码</th>
<th>来源类型</th>
<th>来源单号</th>
<th>变动总数</th>
<th>剩余总数</th>
<th>变动时间</th>
</tr>
</thead>
<tbody>
{foreach name="data" item="item"}
<tr>
<td>{$item.log_sn}</td>
<td>{$item.nickname}</td>
<td>{$item.user_sn}</td>
<td>{$item.mobile}</td>
<td>{$item.source_type_text}</td>
<td>{$item.source_sn}</td>
<td>{$item.change_amount}</td>
<td>{$item.left_amount}</td>
<td>{$item.create_time}</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
<script type="text/javascript">
layui.use(['form','table'], function(){
var form = layui.form;
form.render('select');
});
//日期时间范围
laydate.render({
elem: '#start_time'
,type: 'datetime'
,trigger: 'click'
});
//日期时间范围
laydate.render({
elem: '#end_time'
,type: 'datetime'
,trigger: 'click'
});
</script>
{/block}

View File

@ -0,0 +1,125 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('index')}" method="GET">
<div class="form-group">
<input value="{$_keywords ? $_keywords : '' ;}"
name="_keywords" id="_keywords" class="form-control input-sm" placeholder="操作/URL/IP">
</div>
<div class="form-group">
<select name="admin_user_id" id="admin_user_id" class="form-control input-sm">
<option value="">选择用户</option>
{foreach name='admin_user_list' id='item'}
<option value="{$item.id}"
{if isset($admin_user_id)&& $admin_user_id==$item.id}selected{/if}
>
{$item.nickname}[{$item.username}]
</option>
{/foreach}
</select>
</div>
<script>
$('#admin_user_id').select2();
</script>
<div class="form-group">
<input value="{$create_time_range ?? '' ;}"
name="create_time_range" id="create_time_range" class="form-control input-sm date-range" placeholder="日期">
</div>
<div class="form-group">
<button class="btn btn-sm btn-primary" type="submit"><i class="fa fa-search"></i> 查询
</button>
</div>
<div class="form-group">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>ID</th>
<th>用户</th>
<th>操作</th>
<th>URL</th>
<th>请求方式</th>
<th>IP</th>
<th>日期</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{foreach name='data' item='list'}
<tr>
<td>{$list.id}</td>
<td>{$list->adminUser->nickname}</td>
<td>{$list.name}</td>
<td>{$list.url}</td>
<td>{$list.log_method}</td>
<td>{$list.log_ip}</td>
<td>{$list.create_time}</td>
<td class="td-do">
<a data-id="{$list.id}" data-url="view" data-confirm="2" data-type="2"
class="btn btn-default btn-xs AjaxButton" title="查看详情" data-toggle="tooltip">
<i class="fa fa-eye"></i>
</a>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
<script>
laydate.render({
elem: '.date-range'
,range: true
,type:'datetime'
});
</script>
{/block}

View File

@ -0,0 +1,53 @@
{include file='public/head_css'}
{include file='public/head_js'}
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body table-responsive no-padding">
<table class="table table-bordered table-striped">
<tbody>
<tr>
<th colspan="4" class="text-bold text-center">日志摘要</th>
</tr>
<tr>
<td class="text-bold">日志ID</td>
<td>{$data.id}</td>
</tr>
<tr>
<td class="text-bold">操作用户</td>
<td>{$data->adminUser->nickname}</td>
</tr>
<tr>
<td class="text-bold">操作</td>
<td>{$data.name}</td>
</tr>
<tr>
<td class="text-bold">url</td>
<td>{$data.url}</td>
</tr>
<tr>
<td class="text-bold">类型</td>
<td>{$data.log_method}</td>
</tr>
<tr>
<td class="text-bold">ip</td>
<td>{$data.log_ip}</td>
</tr>
<tr>
<td class="text-bold">日期</td>
<td>{$data.create_time}</td>
</tr>
<tr style="border-top:2px solid #d2d6de;">
<th colspan="2" class="text-bold text-center">数据详情</th>
</tr>
<tr>
<td colspan="2" >
<pre>{$data.adminLogData.data}</pre>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,213 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<form id="dataForm" class="dataForm form-horizontal" action="" method="post"
enctype="multipart/form-data">
<div class="box-body">
<div class="fields-group">
<div class="form-group">
<label for="parent_id" class="col-sm-2 control-label">上级菜单</label>
<div class="col-sm-10 col-md-4">
<select name="parent_id" id="parent_id" class="form-control select2">
<option value="0">/</option>
{$parents|raw}
</select>
</div>
</div>
<script>
$('#parent_id').select2();
</script>
<div class="form-group">
<label for="name" class="col-sm-2 control-label">名称</label>
<div class="col-sm-10 col-md-4">
<input maxlength="50" id="name" name="name" value="{$data.name|default=''}"
class="form-control" placeholder="请输入菜单名称">
</div>
</div>
<div class="form-group">
<label for="url" class="col-sm-2 control-label">url</label>
<div class="col-sm-10 col-md-4">
<input maxlength="100" id="url" name="url" value="{$data.url|default=''}"
class="form-control" placeholder="菜单url">
</div>
</div>
<div class="form-group">
<label for="icon" class="col-sm-2 control-label">图标</label>
<div class="col-sm-10 col-md-4">
<div class="input-group iconpicker-container">
<span class="input-group-addon"><i class="fa fa-pencil"></i></span>
<input maxlength="30" id="icon" name="icon"
value="{$data.icon|default='fa-list'}" class="form-control "
placeholder="请输入图标class">
</div>
</div>
</div>
<script>
$('#icon').iconpicker({placement: 'bottomLeft'});
</script>
<div class="form-group">
<label for="sort_id" class="col-sm-2 control-label">排序</label>
<div class="col-sm-10 col-md-4">
<div class="input-group">
<input max="9999" min="1" type="number" id="sort_id" name="sort_id"
value="{$data.sort_id|default='1000'}"
class="form-control input-number field-number" placeholder="默认1000">
</div>
</div>
</div>
<script>
$('#sort_id')
.bootstrapNumber({
upClass: 'success',
downClass: 'primary',
center: true
});
</script>
<div class="form-group">
<label for="is_show" class="col-sm-2 control-label">是否显示</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="is_show" value="1"
{if !isset($data) || ($data.is_show==1)}checked{/if} type="checkbox"/>
<input class="switch" name="is_show" value="{$data.is_show|default='1'}"
placeholder="" hidden/>
</div>
</div>
<script>
$('#is_show').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
<div class="form-group">
<label for="log_method" class="col-sm-2 control-label">日志请求方式</label>
<div class="col-sm-10 col-md-4">
<select name="log_method" id="log_method" class="form-control select2">
{foreach name='log_method' item='item'}
<option value="{$item}" {if isset($data) && $data.log_method==$item}selected{/if}>
{$item}
</option>
{/foreach}
</select>
</div>
</div>
<script>
$('#log_method').select2();
</script>
{if !isset($data)}
<div class="form-group">
<label for="is_more" class="col-sm-2 control-label">是否自动生成增删改菜单</label>
<div class="col-sm-10 col-md-4">
<input id="is_more" class="input-switch" placeholder="" type="checkbox"/>
<input class="switch" name="is_more" value="0" hidden/>
</div>
</div>
<script>
$('#is_more').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
<div class="form-group">
<label for="more_name" class="col-sm-2 control-label">增删改操作名称</label>
<div class="col-sm-10 col-md-4">
<input maxlength="50" id="more_name" name="more_name"
value="{$data.more_name|default=''}" class="form-control"
placeholder="请输入操作名称">
</div>
</div>
{/if}
</div>
</div>
<!--表单底部-->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
{if !isset($data)}
<div class="btn-group pull-right">
<label class="createContinue">
<input type="checkbox" value="1" id="_create" name="_create"
title="继续添加数据">继续添加</label>
</div>
{/if}
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
$("#dataForm").validate({
rules: {
name: {
required: true,
},
url: {
required: true
},
icon: {
required: true
},
sort_id: {
required: true
}
},
messages: {
name: {
required: "名称不能为空",
},
url: {
required: "url不能为空",
},
icon: {
required: "图标不能为空",
},
sort_id: {
required: "排序不能为空",
},
},
});
</script>
{/block}

View File

@ -0,0 +1,51 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box">
<!--列表头部-->
<div class="box-header">
<div>
<a title="添加" data-toggle="tooltip" class="btn btn-primary btn-sm " href="{:url('add')}">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-danger btn-sm AjaxButton" data-toggle="tooltip" title="删除选中数据" data-confirm-title="删除确认" data-confirm-content="您确定要删除选中的数据吗?" data-id="checked" data-url="{:url('del')}">
<i class="fa fa-trash"></i> 删除
</a>
<a class="btn btn-success btn-sm ReloadButton" data-toggle="tooltip" title="刷新" data-id="checked" data-url="{:url('del')}">
<i class="fa fa-refresh"></i> 刷新
</a>
</div>
</div>
<!--数据内容-->
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>
<input id="dataCheckAll" type="checkbox" onclick="checkAll(this)" class="checkbox" placeholder="全选/取消">
</th>
<th>ID</th>
<th>菜单名称</th>
<th>url</th>
<th>父级ID</th>
<th>图标</th>
<th>排序</th>
<th>状态</th>
<th>日志记录方式</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{$data|raw}
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,137 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
{css href="__ADMIN_CSS__/access.css" /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<div class="box-header with-border">
<h3 class="box-title">【{$data->name|raw}】授权</h3>
<label class="checkbox" for="check_all">
<input class="checkbox-inline" type="checkbox" name="check_all" id="check_all">全选
</label>
</div>
<div class="box-body" id="all_check">
<form id="dataForm" class="form-horizontal dataForm" action="" method="post" enctype="multipart/form-data">
<div class="box-body">
<div class="table_full">
<table width="100%" cellspacing="0">
<tbody>
{$html|raw}
</tbody>
</table>
</div>
</div>
<!--表单底部-->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<script>
$("#check_all").click(function(){
if(this.checked){
$("#all_check").find(":checkbox").prop("checked", true);
}else{
$("#all_check").find(":checkbox").prop("checked", false);
}
});
function checkNode(obj) {
var level_bottom;
var chk = $("input[type='checkbox']");
var count = chk.length;
var num = chk.index(obj);
var level_top = level_bottom = chk.eq(num).attr('level');
for (var i = num; i >= 0; i--) {
var le = chk.eq(i).attr('level');
if (eval(le) < eval(level_top)) {
chk.eq(i).prop("checked", true);
level_top = level_top - 1;
}
}
for (var j = num + 1; j < count; j++) {
le = chk.eq(j).attr('level');
if (chk.eq(num).prop("checked")) {
if (eval(le) > eval(level_bottom)) {
chk.eq(j).prop("checked", true);
}
else if (eval(le) == eval(level_bottom)) {
break;
}
} else {
if (eval(le) > eval(level_bottom)) {
chk.eq(j).prop("checked", false);
} else if (eval(le) == eval(level_bottom)) {
break;
}
}
}
var all_length = $("input[name='menu_id[]']").length;
var checked_length = $("input[name='menu_id[]']:checked").length;
console.log(all_length);
console.log(checked_length);
if(all_length==checked_length){
$("#check_all").prop("checked",true);
}else{
$("#check_all").prop("checked",false);
}
}
</script>
</div>
</section>
<script>
$("#dataForm").validate({
rules: {
'url[]': {
required: true
}
},
messages: {
'url[]': {
required: "请选择权限",
},
},
});
</script>
{/block}

View File

@ -0,0 +1,112 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<form id="dataForm" class="form-horizontal dataForm" action="" method="post"
enctype="multipart/form-data">
<div class="box-body">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">名称</label>
<div class="col-sm-10 col-md-4">
<input maxlength="50" id="name" name="name" value="{$data.name|default=''}"
class="form-control" placeholder="请输入名称">
</div>
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">简介</label>
<div class="col-sm-10 col-md-4">
<input maxlength="50" id="description" name="description"
value="{$data.description|default=''}" class="form-control" placeholder="请输入简介">
</div>
</div>
<div class="form-group">
<label for="status" class="col-sm-2 control-label">启用状态</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="status" value="1" {if(!isset($data) ||$data.status==1)}checked{/if} type="checkbox" />
<input class="switch field-switch" placeholder="启用状态" name="status" value="{$data.status|default='1'}" hidden />
</div>
</div>
<script>
$('#status').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
</div>
<!--表单底部-->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
{if !isset($data)}
<div class="btn-group pull-right">
<label class="createContinue">
<input type="checkbox" value="1" id="_create" name="_create"
title="继续添加数据">继续添加</label>
</div>
{/if}
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
$("#dataForm").validate({
rules: {
name: {
required: true,
},
description: {
required: true
}
},
messages: {
name: {
required: "名称不能为空",
},
description: {
required: "简介不能为空",
}
},
});
</script>
{/block}

View File

@ -0,0 +1,153 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('index')}" method="GET">
<div class="form-group">
<input value="{$_keywords ? $_keywords : '' ;}"
name="_keywords" id="_keywords" class="form-control input-sm" placeholder="名称/简介">
</div>
<div class="form-group">
<button class="btn btn-sm btn-primary" type="submit"><i class="fa fa-search"></i> 查询
</button>
</div>
<div class="form-group">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<!--数据列表顶部-->
<div class="box-header">
<div>
<a title="添加" data-toggle="tooltip" class="btn btn-primary btn-sm " href="{:url('add')}">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-danger btn-sm AjaxButton" data-toggle="tooltip" title="删除选中数据"
data-confirm-title="删除确认" data-confirm-content="您确定要删除选中的数据吗?" data-id="checked"
data-url="{:url('del')}">
<i class="fa fa-trash"></i> 删除
</a>
<a class="btn btn-success btn-sm AjaxButton" data-toggle="tooltip" title="启用选中数据"
data-confirm-title="启用确认" data-confirm-content="您确定要启用选中的数据吗?" data-id="checked"
data-url="{:url('enable')}">
<i class="fa fa-circle"></i> 启用
</a>
<a class="btn btn-warning btn-sm AjaxButton" data-toggle="tooltip" title="禁用选中数据"
data-confirm-title="禁用确认" data-confirm-content="您确定要禁用选中的数据吗?" data-id="checked"
data-url="{:url('disable')}">
<i class="fa fa-circle"></i> 禁用
</a>
<a class="btn btn-success btn-sm ReloadButton" data-toggle="tooltip" title="刷新"
data-id="checked" data-url="{:url('del')}">
<i class="fa fa-refresh"></i> 刷新
</a>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>
<input id="dataCheckAll" type="checkbox" onclick="checkAll(this)" class="checkbox"
placeholder="全选/取消">
</th>
<th>ID</th>
<th>名称</th>
<th>简介</th>
<th>是否启用</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{foreach name="data" item="item"}
<tr>
<td>
<input type="checkbox" onclick="checkThis(this)" name="data-checkbox"
data-id="{$item.id}" class="checkbox data-list-check" value="{$item.id}"
placeholder="选择/取消">
</td>
<td>{$item.id}</td>
<td>{$item.name}</td>
<td>{$item.description}</td>
<td>{$item.status_text}</td>
<td class="td-do">
<a href="{:url('admin_role/access',['id'=>$item.id])}"
class="btn btn-warning btn-xs" data-toggle="tooltip" title="授权">
<i class="fa fa-key"></i>
</a>
<a href="{:url('admin_role/edit',['id'=>$item.id])}"
class="btn btn-primary btn-xs" title="修改" data-toggle="tooltip">
<i class="fa fa-pencil"></i>
</a>
<a class="btn btn-danger btn-xs AjaxButton" data-toggle="tooltip" title="删除"
data-id="{$item.id}" data-confirm-title="删除确认"
data-confirm-content='您确定要删除ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('del')}">
<i class="fa fa-trash"></i>
</a>
{if $item.status==1}
<a class="btn btn-warning btn-xs AjaxButton" data-toggle="tooltip" title="禁用"
data-id="{$item.id}" data-confirm-title="禁用确认"
data-confirm-content='您确定要禁用ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('disable')}">
<i class="fa fa-circle"></i>
</a>
{else/}
<a class="btn btn-success btn-xs AjaxButton" data-toggle="tooltip" title="启用"
data-id="{$item.id}" data-confirm-title="启用确认"
data-confirm-content='您确定要启用ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('enable')}">
<i class="fa fa-circle"></i>
</a>
{/if}
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,155 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<form id="dataForm" class="form-horizontal dataForm" action="" method="post"
enctype="multipart/form-data">
<div class="box-body">
<div class="form-group">
<label for="role" class="col-sm-2 control-label">角色</label>
<div class="col-sm-10 col-md-4">
<select name="role[]" id="role" class="form-control field-multi-select"
multiple="multiple">
{foreach name='role' item='item'}
<option value="{$item.id}" {if isset($data) && in_array($item.id,$data.role)}selected{/if}>
{$item.name}
</option>
{/foreach}
</select>
</div>
</div>
<script>
$('#role').select2();
</script>
<div class="form-group">
<label for="nickname" class="col-sm-2 control-label">昵称</label>
<div class="col-sm-10 col-md-4">
<input maxlength="50" id="nickname" name="nickname" value="{$data.nickname|default=''}"
class="form-control" placeholder="请输入昵称">
</div>
</div>
<div class="form-group">
<label for="username" class="col-sm-2 control-label">账号</label>
<div class="col-sm-10 col-md-4">
<input maxlength="50" id="username" autocomplete="off" name="username"
value="{$data.username|default=''}" class="form-control" placeholder="请输入账号">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码</label>
<div class="col-sm-10 col-md-4">
<input maxlength="255" id="password" autocomplete="off" type="password" name="password"
value="{$data.password|default=''}" class="form-control" placeholder="请输入密码">
</div>
</div>
<div class="form-group">
<label for="status" class="col-sm-2 control-label">启用状态</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="status" value="1" {if(!isset($data)
||$data.status==1)}checked{/if} type="checkbox"/>
<input class="switch field-switch" name="status" value="{$data.status|default='1'}"
hidden/>
</div>
</div>
<script>
$('#status').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
</div>
<!--表单底部-->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
{if !isset($data)}
<div class="btn-group pull-right">
<label class="createContinue">
<input type="checkbox" value="1" id="_create" name="_create"
title="继续添加数据">继续添加</label>
</div>
{/if}
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
$("#dataForm").validate({
rules: {
nickname: {
required: true,
minlength: 2
},
username: {
required: true,
minlength: 2
},
password: {
required: true,
minlength: 6
},
},
messages: {
nickname: {
required: "请输入昵称",
minlength: "名称长度不能小于2"
},
username: {
required: "请输入账号",
minlength: "用户名长度不能小于2"
},
password: {
required: "请输入密码",
minlength: "密码长度不能小于6"
},
},
});
</script>
{/block}

View File

@ -0,0 +1,148 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('index')}" method="GET">
<div class="form-group">
<input value="{$_keywords ? $_keywords : '' ;}"
name="_keywords" id="_keywords" class="form-control input-sm" placeholder="昵称/账号">
</div>
<div class="form-group">
<button class="btn btn-sm btn-primary" type="submit"><i class="fa fa-search"></i> 查询
</button>
</div>
<div class="form-group">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<!--数据列表顶部-->
<div class="box-header">
<div>
<a title="添加" data-toggle="tooltip" class="btn btn-primary btn-sm " href="{:url('add')}">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-danger btn-sm AjaxButton" data-toggle="tooltip" title="删除选中数据" data-confirm-title="删除确认" data-confirm-content="您确定要删除选中的数据吗?" data-id="checked" data-url="{:url('del')}">
<i class="fa fa-trash"></i> 删除
</a>
<a class="btn btn-success btn-sm AjaxButton" data-toggle="tooltip" title="启用选中数据"
data-confirm-title="启用确认" data-confirm-content="您确定要启用选中的数据吗?" data-id="checked"
data-url="{:url('enable')}">
<i class="fa fa-circle"></i> 启用
</a>
<a class="btn btn-warning btn-sm AjaxButton" data-toggle="tooltip" title="禁用选中数据"
data-confirm-title="禁用确认" data-confirm-content="您确定要禁用选中的数据吗?" data-id="checked"
data-url="{:url('disable')}">
<i class="fa fa-circle"></i> 禁用
</a>
<a class="btn btn-success btn-sm ReloadButton" data-toggle="tooltip" title="刷新" data-id="checked" data-url="{:url('del')}">
<i class="fa fa-refresh"></i> 刷新
</a>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>
<input id="dataCheckAll" type="checkbox" onclick="checkAll(this)" class="checkbox" placeholder="全选/取消">
</th>
<th>ID</th>
<th>昵称</th>
<th>账号</th>
<th>角色</th>
<th>是否启用</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{foreach name="data" item="item"}
<tr>
<td>
<input type="checkbox" onclick="checkThis(this)" name="data-checkbox"
data-id="{$item.id}" class="checkbox data-list-check" value="{$item.id}"
placeholder="选择/取消">
</td>
<td>{$item.id}</td>
<td>{$item.nickname}</td>
<td>{$item.username}</td>
<td>
{foreach name='item.role_text' id='role'}
<small class="label bg-blue">{$role}</small>
{/foreach}
</td>
<td>{$item.status_text}</td>
<td class="td-do">
<a href="{:url('admin_user/edit',['id'=>$item.id])}"
class="btn btn-primary btn-xs" title="修改" data-toggle="tooltip">
<i class="fa fa-pencil"></i>
</a>
<a class="btn btn-danger btn-xs AjaxButton" data-toggle="tooltip" title="删除" data-id="{$item.id}" data-confirm-title="删除确认" data-confirm-content='您确定要删除ID为 <span class="text-red">{$item.id}</span> 的数据吗' data-url="{:url('del')}">
<i class="fa fa-trash"></i>
</a>
{if $item.status==1}
<a class="btn btn-warning btn-xs AjaxButton" data-toggle="tooltip" title="禁用"
data-id="{$item.id}" data-confirm-title="禁用确认"
data-confirm-content='您确定要禁用ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('disable')}">
<i class="fa fa-circle"></i>
</a>
{else/}
<a class="btn btn-success btn-xs AjaxButton" data-toggle="tooltip" title="启用"
data-id="{$item.id}" data-confirm-title="启用确认"
data-confirm-content='您确定要启用ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('enable')}">
<i class="fa fa-circle"></i>
</a>
{/if}
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,168 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-3">
<div class="box box-primary">
<div class="box-body box-profile">
<img class="profile-user-img img-responsive img-circle" src="{$admin.user.avatar}" alt="头像">
<h3 class="profile-username text-center">{$admin.user.nickname}</h3>
<p class="text-muted text-center">{$admin.user.username}</p>
<p>
{foreach name='admin.user.role_text' id='role'}
<small class="label bg-blue">{$role}</small>
{/foreach}
</p>
</div>
</div>
</div>
<div class="col-md-9">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#profile" data-toggle="tab" aria-expanded="true">个人信息</a></li>
<li class=""><a href="#privacy" data-toggle="tab" aria-expanded="false">修改密码</a></li>
<li class=""><a href="#avatars" data-toggle="tab" aria-expanded="false">修改头像</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="profile">
<form class="dataForm form-horizontal" id="dataForm1" action="" method="post">
<input type="hidden" value="profile" name="update_type" placeholder="请勿修改">
<div class="form-group">
<label for="nickname" class="col-sm-2 control-label">昵称</label>
<div class="col-sm-10 col-md-4">
<input class="form-control" value="{$admin.user.nickname}" name="nickname"
id="nickname" maxlength="30"
placeholder="请输入昵称">
</div>
</div>
{:token()}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-danger">保存</button>
</div>
</div>
</form>
</div>
<div class="tab-pane" id="privacy">
<form class="dataForm form-horizontal" id="dataForm2" action="" method="post">
<input type="hidden" value="password" name="update_type" placeholder="请勿修改">
<div class="form-group">
<label for="password" class="col-sm-2 control-label">当前密码</label>
<div class="col-sm-10 col-md-4">
<input type="password" autocomplete='password' class="form-control" name="password" id="password"
placeholder="请输入当前密码">
</div>
</div>
<div class="form-group">
<label for="new_password" class="col-sm-2 control-label">新密码</label>
<div class="col-sm-10 col-md-4">
<input type="password" class="form-control" autocomplete='off' name="new_password" id="new_password"
placeholder="请输入新密码">
</div>
</div>
<div class="form-group">
<label for="renew_password" class="col-sm-2 control-label">确认新密码</label>
<div class="col-sm-10 col-md-4">
<input type="password" class="form-control" autocomplete='off' name="renew_password" id="renew_password"
placeholder="再次输入新密码">
</div>
</div>
{:token()}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-danger">保存</button>
</div>
</div>
</form>
</div>
<div class="tab-pane" id="avatars">
<form class="dataForm form-horizontal" id="dataForm3" action="" method="post" enctype="multipart/form-data">
<input type="hidden" value="avatar" name="update_type" placeholder="请勿淘气修改">
<div class="form-group">
<label for="avatar" class="col-sm-2 control-label">头像</label>
<div class="col-sm-10 col-md-4">
<input type="file" class="form-control" name="avatar" id="avatar"
placeholder="头像可空">
</div>
</div>
{:token()}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-danger">保存</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
$("#dataForm1").validate({
rules: {
nickname: {
required: true,
minlength: 2,
maxlength: 10
}
},
messages: {
nickname: {
required: "请输入昵称",
minlength: "昵称长度不能小于2",
maxlength: "昵称长度不能大于10"
}
}
});
$("#dataForm2").validate({
rules: {
password: {
required: true,
minlength: 6
},
new_password: {
required: true,
minlength: 6
},
renew_password: {
required: true,
minlength: 6
}
},
messages: {
password: {
required: "请输入当前密码",
minlength: "当前密码长度不能小于6"
},
new_password: {
required: "请输入新密码",
minlength: "新密码长度不能小于6"
},
renew_password: {
required: "请输入确认新密码",
minlength: "确认新密码长度不能小于6"
}
}
});
$("#dataForm3").validate({
rules: {
avatar: {
required: true
}
},
messages: {
avatar: {
required: "请选择文件"
}
}
});
</script>
{/block}

View File

@ -0,0 +1,26 @@
<div class="row" style="margin-bottom: 15px;">
<div class="col-sm-8">
<input type="text" id="captcha" class=" form-control" name="captcha" placeholder="验证码" maxlength="6">
</div>
<div class="col-sm-4" style="padding-left: 0">
<img style="width: 100%" src="{:url('auth/captcha')}" alt="图形验证码" id="captchaImg" height="34" onclick="refreshCaptcha('captchaImg')">
</div>
</div>
<script>
function refreshCaptcha(dom) {
let $dom = $('#'+dom);
$dom.attr('src','{:url("auth/captcha")}?'+img_name_random());
}
//图片后缀随机数
function img_name_random() {
var rand_one = parseInt(100 * Math.random());
var rand_two = parseInt(100 * Math.random());
return String(rand_one) + String(rand_two);
}
</script>

View File

@ -0,0 +1,53 @@
{js href="__ADMIN_PLUGINS__/gee-test/gee-test.min.js" /}
<div id="wait" class="text-center" style="height: 44px;font-size: 18px;">
正在加载验证码...
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group text-center">
<div id="embed-captcha" style="width: 300px;margin: 0 auto;;"></div>
</div>
</div>
</div>
<script>
var handlerEmbed = function (captchaObj) {
$("#loginButton").click(function (e) {
var validate = captchaObj.getValidate();
if (!validate) {
layer.msg('请先完成验证',{icon:2});
e.preventDefault();
}
});
// 将验证码加到id为captcha的元素里,同时会有三个input的值:geetest_challenge, geetest_validate, geetest_seccode
captchaObj.appendTo("#embed-captcha");
captchaObj.onReady(function () {
//$("#loginButton").attr("disabled",false);
$("#wait").hide();
});
};
$(function () {
$.ajax({
// 获取id,challenge,success(是否启用failback)
url: "{:url('auth/initGeeTest')}",
type: "POST",
dataType: "JSON",
success: function (result) {
let data = result.data;
// 使用initGeetest接口
// 参数1:配置参数
// 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件
initGeetest({
with: '300px',
gt: data.gt,
challenge: data.challenge,
new_captcha: data.new_captcha,
product: "embed", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效
offline: !data.success // 表示用户后台检测极验服务器是否宕机,一般不需要关注
}, handlerEmbed);
}
});
});
</script>

View File

@ -0,0 +1,160 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit">
<title>{$admin.title} | {$admin.name|default='OneWeekBackend'}</title>
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
{css href="__ADMIN_PLUGINS__/bootstrap/css/bootstrap.min.css" /}
{css href="__ADMIN_PLUGINS__/font-awesome/css/font-awesome.min.css" /}
{css href="__ADMIN_CSS__/AdminLTE.min.css" /}
{css href="__ADMIN_CSS__/admin.css" /}
<!-- 如果有登录背景 -->
{if $login_config.background}
<style>
.login-page{
background-color: #ececec;
background-image: url({$login_config.background});
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed;
background-position: 50% 50%;
}
</style>
{/if}
<script>
var adminDebug = {$debug};
</script>
{js href="__ADMIN_PLUGINS__/jquery/jquery.min.js" /}
{js href="__ADMIN_PLUGINS__/bootstrap/js/bootstrap.min.js" /}
{js href="__ADMIN_PLUGINS__/jquery-validation/jquery.validate.min.js" /}
{js href="__ADMIN_PLUGINS__/jquery-validation/localization/messages_zh.min.js" /}
{js href="__ADMIN_PLUGINS__/layer/layer.js" /}
{js href="__ADMIN_JS__/admin.js" /}
<!--[if lt IE 9]>
{js href="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js" /}
{js href="https://oss.maxcdn.com/respond/1.4.2/respond.min.js" /}
<![endif]-->
</head>
<body class="hold-transition login-page">
<div class="login-box">
<div class="login-logo">
<a>{$admin.name|default=''}</a>
</div>
<div class="login-box-body">
<p class="login-box-msg">登录</p>
<form class="dataForm" id="dataForm" action="" method="post">
<div class="form-group has-feedback">
<input name="username" id="username" type="text" class="form-control" placeholder="用户名">
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input name="password" id="password" type="password" class="form-control" placeholder="密码">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
{if $login_config.token}
{:token()}
{/if}
{if $login_config.captcha==1}
{include file='auth/captcha' /}
{else/}
{if $login_config.captcha==2}
{include file='auth/gee_test' /}
{/if}
{/if}
<div class="row">
<div class="col-xs-8">
<div class="checkbox">
<label>
<input id="remember" name="remember" value="1" type="checkbox"> 记住我
</label>
</div>
</div>
<div class="col-xs-4">
{:token()}
<button type="submit" id="loginButton" class="btn btn-primary btn-block btn-flat">登录</button>
</div>
</div>
</form>
</div>
</div>
<div id="browser_warning" style="display: none">
<div class=" margin text-center">
<p class="text-red ">请使用现代浏览器(谷歌浏览器、360极速或其他国产浏览器极速模式)操作本后台!</p>
<a class="btn btn-success" target="_blank" href="https://www.google.cn/chrome/" data-toggle="tooltip"
title="点击去下载谷歌浏览器">谷歌浏览器</a>
<a class="btn btn-success" target="_blank" href="https://browser.360.cn/ee/index.html" data-toggle="tooltip"
title="点击去下载360极速浏览器">360极速浏览器</a>
<a class="btn btn-success" target="_blank" href="https://browser.qq.com/" title="点击去下载QQ浏览器"
data-toggle="tooltip">QQ浏览器</a>
</div>
</div>
<script>
$(document).ready(function () {
$("#dataForm").validate({
rules: {
username: {
required: true,
minlength: 2
},
password: {
required: true,
minlength: 6
},
},
messages: {
username: {
required: "请输入用户名",
minlength: "用户名长度不能小于2"
},
password: {
required: "请输入密码",
minlength: "密码长度不能小于6"
},
}
});
$('#username').focus();
});
checkBrowser();
/*检查浏览器*/
function checkBrowser() {
if (isIE()) {
console.log('古代浏览器');
layer.open({
type: 1,
content: $('#browser_warning').html(),
icon: 5,
title: '警告',
area: ['500px', '300px'],
closeBtn: 0,
moveType: 1,
resize: false
});
} else {
console.log('现代浏览器');
}
}
function isIE() {
return !!window.ActiveXObject || "ActiveXObject" in window;
}
</script>
</body>
</html>

View File

@ -0,0 +1,177 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<style>
.layui-card .header-title {
font-size: 16px;
font-weight: bold;
}
.layui-card .header-title::before {
content: '';
display: inline-block;
width: 4px;
height: 18px;
vertical-align: -4px;
margin-right: 5px;
background: #3A91FB;
}
.layui-card .survey-list {
display: flex;
flex-wrap: wrap;
}
.layui-card .survey-list .item {
width: 20%;
min-width: 200px;
}
.layui-card .survey-list .item .title {
display: flex;
align-items: center;
}
.layui-card .survey-list .item .title img {
width: 30px;
height: 30px;
margin-right: 12px;
}
.layui-card .survey-list .item .layuiadmin-big-font {
margin-left: 42px;
color: #333;
font-size: 25px;
}
</style>
<section class="content">
<!-- 订单-->
<div class="layui-card">
<div class="layui-card-header">
<div class="header-title">订单概况</div>
</div>
<div class="layui-card-body layuiadmin-card-list survey-list">
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/month_order_amount.png" alt="">
<div>本月订单金额(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/total_order_amount.png" alt="">
<div>订单总金额(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/order_num.png" alt="">
<div>订单总数(笔)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/refund_amount.png" alt="">
<div>退款订单总额(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/refund_num.png" alt="">
<div>退款订单总数(笔)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
</div>
</div>
<!--会员-->
<div class="layui-card">
<div class="layui-card-header">
<div class="header-title">会员概况</div>
</div>
<div class="layui-card-body layuiadmin-card-list survey-list">
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/total_user_money.png" alt="">
<div>会员余额(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/total_user_integral.png" alt="">
<div>会员积分 </div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/able_earnings.png" alt="">
<div>会员可提现佣金(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/have_withdraw_earnings.png" alt="">
<div>会员已提现佣金(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
</div>
</div>
<!--分销-->
<div class="layui-card">
<div class="layui-card-header">
<div class="header-title">分销概况</div>
</div>
<div class="layui-card-body layuiadmin-card-list survey-list">
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/month_earnings.png" alt="">
<div>本月分销佣金(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/distribution_earnings.png" alt="">
<div>分销总佣金(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/wait_earnings.png" alt="">
<div>提现中佣金(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
<div class="item">
<div class="title">
<img class="icon" src="__PUBLIC__/static/common/image/finance/distribution_have_withdraw.png" alt="">
<div>已提现佣金(元)</div>
</div>
<p class="layuiadmin-big-font">1</p>
</div>
</div>
</div>
</section>
<script>
</script>
{/block}

View File

@ -0,0 +1,810 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<script>
//收起左侧菜单,留出更大空间
if (!$('body').hasClass('sidebar-collapse')) {
$('body').addClass('sidebar-collapse');
}
</script>
<section class="content">
<style scoped>
#dataBody th, #dataBody td {
min-width: 60px;
}
td label {
font-weight: normal;
}
.box-header .select2 {
min-width: 130px;
}
.form-type-th {
min-width: 150px;
}
.form-validate-th {
min-width: 200px;
}
.form-validate-label, .form-validate-select, .form-type-label, .form-type-select {
width: 100%;
}
#create_menu_list {
min-width: 400px;
}
#controller_action_list {
min-width: 400px;
}
.form-inline .form-group {
margin-right: 20px;
}
.extend-div {
display: none;
position: absolute;
z-index: 2;
}
#model_relation .form-group {
margin-bottom: 10px;
}
.more-setting .extend-div {
width: 570px;
margin-right: 0;
margin-left: -500px;
}
.more-setting .more-from {
margin-bottom: 20px;
}
.modelRelationDiv .form-group .form-control {
margin-right: 20px;
}
</style>
<form id="dataForm" class="dataForm" action="create" method="post">
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">代码自动生成</h3>
</div>
<!-- 表和菜单 -->
<div class="box-header with-border">
<div class="form-inline">
<div class="form-group">
<label for="table_name">选择表</label>
<select data-id="table_name" name="table_name" class="select2 form-control input-sm"
id="table_name" data-placeholder="请选择表">
<option value=""></option>
{foreach name='table' id='item'}
<option value="{$item}">{$item}</option>
{/foreach}
</select>
<button onclick="refreshTable()" type="button" class="btn btn-flat btn-success"
data-toggle="tooltip" title="刷新表数据">
<i class="fa fa-refresh"></i>
</button>
</div>
<div class="form-group">
<label for="cn_name">中文名</label>
<input name="cn_name" id="cn_name" class="form-control input-sm" placeholder="请填写中文名"
title="表及功能的中文名字,例如用户表,就填写[用户]" data-toggle="tooltip">
</div>
<div class="form-group checkbox">
<label><input checked type="checkbox" value="1" id="auto_class_name"
name="auto_class_name"
title="自动生成控制器|模型|验证器类名" data-toggle="tooltip">自动生成类名</label>
</div>
<div class="form-group checkbox">
<label><input checked type="checkbox" value="1" id="list_delete"
name="list_delete"
title="列表删除功能" data-toggle="tooltip">列表删除</label>
</div>
<div class="form-group checkbox">
<label><input checked type="checkbox" value="1" id="list_create"
name="list_create"
title="列表添加功能" data-toggle="tooltip">列表添加</label>
</div>
<div class="form-group checkbox">
<label><input checked type="checkbox" value="1" id="list_refresh"
name="list_refresh"
title="列表刷新功能" data-toggle="tooltip">列表刷新</label>
</div>
<div class="form-group checkbox">
<label><input type="checkbox" value="1" id="list_export"
name="list_export"
title="列表导出功能" data-toggle="tooltip">列表导出</label>
</div>
<div class="form-group checkbox">
<label><input type="checkbox" value="1" id="list_enable"
name="list_enable"
title="列表启用/禁用功能" data-toggle="tooltip">列表启用/禁用</label>
</div>
</div>
</div>
<!-- 控制器 -->
<div class="box-header with-border">
<div class="form-inline">
<div class="form-group">
<label for="create_menu">菜 单</label>
<select data-id="create_menu" name="create_menu" class="select2 form-control input-sm"
id="create_menu" data-placeholder="不选择为不生成菜单">
<option value="-1">不生成</option>
<option value="0">顶级菜单</option>
{$menus|raw}
</select>
<button onclick="refreshMenu()" type="button" class="btn btn-flat btn-success"
data-toggle="tooltip" title="刷新菜单">
<i class="fa fa-refresh"></i>
</button>
</div>
<div class="form-group">
<label for="create_menu_list">菜单选择</label>
<select name="create_menu_list[]" class="select2 form-control input-sm"
id="create_menu_list" multiple="multiple" data-placeholder="默认生成增删改菜单">
<option value="1" disabled selected>列表</option>
<option value="2" selected>添加</option>
<option value="3" selected>修改</option>
<option value="4" selected>删除</option>
<option value="5">启用/禁用</option>
</select>
</div>
</div>
</div>
<div class="box-header with-border">
<div class="form-inline">
<div class="form-group">
<label for="create_controller">控制器</label>
<select data-id="create_controller" name="create_controller"
class="select2 form-control input-sm"
id="create_controller" data-placeholder="默认生成">
<option value="1">生成</option>
<option value="0">不生成</option>
</select>
</div>
<div class="form-group">
<label for="controller_name">控制器名</label>
<input name="controller_name" id="controller_name"
class="form-control input-sm" title="默认会根据表名自动生成" placeholder="请填写控制器名"
data-toggle="tooltip">
</div>
<div class="form-group">
<label for="controller_action_list">控制器方法</label>
<select name="controller_action_list[]" class="select2 form-control input-sm"
id="controller_action_list" multiple="multiple" data-placeholder="默认生成增删改方法">
<option value="1" selected>列表</option>
<option value="2" selected>添加</option>
<option value="3" selected>修改</option>
<option value="4" selected>删除</option>
<option value="5">启用/禁用</option>
</select>
</div>
</div>
</div>
<div class="box-header with-border">
<div class="form-inline">
<div class="form-group">
<label for="create_model">模 型</label>
<select data-id="create_model" name="create_model" class="select2 form-control input-sm"
id="create_model" data-placeholder="默认生成">
<option value="1">生成</option>
<option value="0">不生成</option>
</select>
</div>
<div class="form-group">
<label for="model_name">模型名</label>
<input name="model_name" id="model_name" class="form-control input-sm"
placeholder="模型名" title="默认会根据表名自动生成" data-toggle="tooltip">
</div>
<div class="form-group checkbox">
<label><input checked type="checkbox" value="1" name="auto_timestamp"
title="自动添加create_time和update_time字段" data-toggle="tooltip">自动时间戳</label>
</div>
<div class="form-group checkbox">
<label><input checked type="checkbox" value="1" name="soft_delete"
title="自动添加delete_time字段,默认为0" data-toggle="tooltip">软删除</label>
</div>
<div>
</div>
</div>
</div>
<div class="box-header with-border">
<div class="form-inline">
<div class="form-group">
<label for="create_validate">验证器</label>
<select data-id="create_validate" name="create_validate"
class="select2 form-control input-sm"
id="create_validate" data-placeholder="默认生成">
<option value="1">生成</option>
<option value="0">不生成</option>
</select>
</div>
<div class="form-group">
<label for="validate_name">验证器名</label>
<input name="validate_name" id="validate_name" class="form-control input-sm"
placeholder="验证器名" title="默认会根据表名自动生成" data-toggle="tooltip">
</div>
</div>
</div>
<div class="box-body table-responsive">
<table id="dataList" class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr class="input-type">
<th>操作</th>
<th title="字段名为小写下划线形式">字段</th>
<th title="字段类型,例如varchar(255),int(10),decimal(12,2)">类型</th>
<th title="中文名称,例如username为用户名">名称</th>
<th title="是否在列表页显示">列表</th>
<th title="是否为列表页搜索字段">搜索</th>
<th title="是否为添加/修改页字段">表单</th>
<th class="form-type-th" title="表单类型">表单类型</th>
<th class="form-validate-th" title="表单验证">表单验证</th>
<th title="字段更多设置">更多</th>
</tr>
</thead>
<tbody id="dataBody">
</tbody>
</table>
</div>
<div class="box-footer">
<a class="btn btn-primary btn-sm btn-success" onclick="addNewField(null,2)">添加一行</a>
<button class="btn btn-primary btn-sm pull-right" type="submit">提交</button>
</div>
</div>
</div>
</div>
</form>
<table>
<tbody id="data-template" style="display: none">
<tr>
<td>
<a class="btn btn-xs btn-primary" onclick="addNewField(this,1)">插入</a>
<a class="btn btn-xs btn-success" onclick="addNewField(this,2)">追加</a>
<a class="btn btn-xs btn-danger" onclick="delThisField(this,1)">删除</a>
</td>
<td>
<label>
<input class="form-control" name="field_nameFORM_INDEX[]" value="" placeholder="字段"
>
</label>
</td>
<td>
<label>
<input class="form-control field-type" value="" name="field_typeFORM_INDEX[]"
placeholder="字段类型,例如varchar(255),int(10),decimal(12,2)">
</label>
</td>
<td>
<label>
<input class="form-control" name="form_nameFORM_INDEX[]" placeholder="名称">
</label>
</td>
<td>
<label class="bodyFormCheckbox">
<input type="checkbox" value="1" id="is_listFORM_INDEX[]" name="is_listFORM_INDEX[]">列表
</label>
</td>
<td>
<label class="bodyFormCheckbox">
<input type="checkbox" value="1" id="is_searchFORM_INDEX[]" name="is_searchFORM_INDEX[]">搜索
</label>
</td>
<td>
<label class="bodyFormCheckbox">
<input type="checkbox" value="1" id="is_formFORM_INDEX[]" name="is_formFORM_INDEX[]">表单
</label>
</td>
<td>
<label class="form-type-label">
<select class="form-control select2 form-type-select" name="form_typeFORM_INDEX[]"
onchange="selectField(this)">
<option value="text">文本[text]</option>
<option value="number">数字[number]</option>
<option value="password">密码[password]</option>
<option value="mobile">手机号[mobile]</option>
<option value="email">邮箱[email]</option>
<option value="id_card">身份证号[id_card]</option>
<option value="url">网址[url]</option>
<option value="ip">IP地址[ip]</option>
<option value="textarea">文本域[textarea]</option>
<option value="checkbox">复选[checkbox]</option>
<option value="switch">开关[switch]</option>
<option value="radio">单选[radio]</option>
<option value="select">选择列表[select]</option>
<option value="multi_select">多项选择列表[multi-select]</option>
<option value="image">图片上传[image]</option>
<option value="multi_image">多图上传[multi-image]</option>
<option value="file">文件上传[file]</option>
<option value="multi_file">多文件上传[multi-file]</option>
<option value="date">日期[date]</option>
<option value="date_range">日期范围[date-range]</option>
<option value="datetime">日期时间[datetime]</option>
<option value="datetime_range">日期时间范围[datetime-range]</option>
<option value="year">年[year]</option>
<option value="year_range">年范围[year-range]</option>
<option value="year_month">年月[year-month]</option>
<option value="year_month_range">年月范围[year-month-range]</option>
<option value="map">地图选点[map]</option>
<option value="color">颜色选择[color]</option>
<option value="icon">图标选择[icon]</option>
<option value="editor">富文本编辑器[editor]</option>
</select>
</label>
</td>
<td class="form-validate-td">
<label class="form-validate-label">
<select class="form-control form-validate-select select2" multiple="multiple"
name="form_validateFORM_INDEX[]">
<option value="required">非空</option>
<!--当前采用微信号的规则6至20位,以字母开头,字母,数字,减号,下划线 /^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$/-->
<option value="account">账号</option>
<!--验证简单中文名字2-4个汉字, /[\u4E00-\u9FA5]{2,4}/如有特殊名字请手动更改规则长度-->
<option value="cn_name">中文姓名</option>
<!--/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/-->
<option value="car_number">车牌号</option>
</select>
</label>
</td>
<td class="more-setting" data-id="INDEX_ID">
<!-- 这里放更多设置
例如:date,date_time类型的自动加时间转换功能
is_xxx同时是switch的字段自动加is_xxx_text功能
-->
<a class="btn btn-default btn-sm setting-more" data-id="INDEX_ID">更多设置</a>
<div class="extend-div" id="field_setting_div_INDEX_ID" data-id="INDEX_ID">
<div class="box box-warning box-solid">
<div class="box-header with-border">
<h3 class="box-title">字段更多设置</h3>
</div>
<div class="box-body" id="field_setting_INDEX_ID">
<div class="more-from">
<div class="form-inline">
<div class="form-group">
<label for="field_defaultINEDEX_ID">默认值</label>
<input name="field_defaultFORM_INDEX[]"
class="form-control input-sm"
id="field_defaultINEDEX_ID" placeholder="请填写默认值">
</div>
<div class="form-group">
<label for="getter_setterFORM_INDEX">获取/修改器</label>
<select name="getter_setterFORM_INDEX[]"
class="select2 form-control input-sm"
id="getter_setterFORM_INDEX" data-placeholder="获取/修改器">
<option value="">无</option>
<option value="datetime">datetime</option>
<option value="switch">switch</option>
<option value="date">date</option>
</select>
</div>
<div class="form-group checkbox">
<label><input type="checkbox" value="1" name="list_sortFORM_INDEX[]"
title="是否参与列表排序" data-toggle="tooltip">列表排序</label>
</div>
</div>
</div>
<hr/>
<div class="more-from">
<div class="form-inline">
<div class="form-group">
<label for="is_relationFORM_INDEX">关联设置</label>
<select name="is_relationFORM_INDEX[]"
class="select2 form-control input-sm"
id="is_relationFORM_INDEX" data-placeholder="是否关联字段"
onchange="selectRelation(this)"
data-relation-table="relation_tableFORM_INDEX[]"
data-relation-show="relation_showFORM_INDEX[]">
<option value="0">非关联字段</option>
<option value="1">关联外键</option>
<option value="2">关联主键</option>
</select>
</div>
<div class="form-group">
<select name="relation_typeFORM_INDEX[]"
class="select2 form-control input-sm"
id="relation_typeFORM_INDEX" title="暂时只支持一对一和一对多" data-toggle="tooltip"
data-placeholder="关联方式">
<option value="1">一对多</option>
<option value="2">一对一</option>
</select>
</div>
<div class="form-group">
<input readonly name="relation_showFORM_INDEX[]"
class="form-control input-sm"
id="relation_showINEDEX_ID"
title="belongsTo填写,例如文章发布人user_id要显示成User模型的nickname,填写nickname即可"
data-toggle="tooltip" placeholder="关联显示字段">
</div>
<div class="form-group">
<input readonly name="relation_tableFORM_INDEX[]"
class="form-control input-sm"
id="relation_tableINEDEX_ID"
title="一般此字段为id,belongsTo的无须填写,hasOne/hasMany填写此字段,关联多个模型务必使用英文逗号隔开,例如用户关联多篇文章,多个积分记录,可以写成article,integral_log"
data-toggle="tooltip" placeholder="关联表/模型,用英文逗号隔开">
</div>
</div>
</div>
<hr/>
<div class="more-from">
<div class="form-inline">
<div class="form-group">
<label for="field_sceneINEDEX_ID">验证场景</label>
<select style="min-width: 380px;width: 420px;" name="field_sceneFORM_INDEX[]"
class="select2 form-control input-sm"
id="field_sceneINEDEX_ID" multiple="multiple"
data-placeholder="默认选择三大模块">
<option value="admin_add" selected>admin_add</option>
<option value="admin_edit" selected>admin_edit</option>
<option value="api_add" selected>api_add</option>
<option value="api_edit" selected>api_edit</option>
<option value="index_add" selected>index_add</option>
<option value="index_edit" selected>index_edit</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</section>
<script>
//刷新数据库表
function refreshTable() {
$.post('{:url("admin/generate/getTable")}', function (result) {
let html = '<option value=""></option>';
$.each(result.data, function (index, item) {
html += '<option value="' + item + '">' + item + '</option>';
});
$('#table_name').html(html).select2();
});
}
//表单索引
var formIndex = 0;
$(function () {
//获取表信息和字段等,进行页面填充
$("#table_name").on('change', function () {
getField($(this).val());
});
//列表启用/禁止关联菜单和控制器
$('#list_enable').change(function () {
console.log('启用/禁止选项');
let checked = $(this).is(':checked');
let $menu_list = $('#create_menu_list');
let $action_list = $('#controller_action_list');
$menu_list.find("option[value='5']").attr("selected", checked);
$action_list.find("option[value='5']").attr("selected", checked);
$menu_list.select2();
$action_list.select2();
});
//默认添加一行空的字段
addNewField(null, 1);
});
//添加新的字段
function addNewField(obj, type) {
formIndex++;
let template = $("#data-template").html().replace(/FORM_INDEX/g, '[' + formIndex + ']').replace(/INDEX_ID/g, formIndex);
if (obj == null) {
$("#dataBody").append(template);
} else {
if (type === 1) {
$(obj).parent().parent().before(template);
} else {
$(obj).parent().parent().after(template);
}
}
//刷新 dataBody DOM后的操作
dataBodyRefreshed();
}
//删除当前字段
function delThisField(obj) {
layer.confirm('您确认删除本行吗?', {title: '删除确认', closeBtn: 1, icon: 3}, function () {
$(obj).parent().parent().remove();
layer.closeAll();
});
}
//提交验证
$("#dataForm").validate({
rules: {
table_name: {
required: true,
},
cn_name: {
required: true,
},
},
messages: {
table_name: {
required: "表名不能为空",
},
cn_name: {
required: "中文名不能为空",
},
},
});
//选择表
$('#table_name').select2();
//生成菜单列表
$('#create_menu_list').select2();
//是否生成控制器
$('#create_controller').select2();
//是否生成模型
$('#create_model').select2();
//是否生成验证器
$('#create_validate').select2();
//控制器方法表
$('#controller_action_list').select2();
//选择父级菜单
$('#create_menu').select2();
//获取表信息
function getField(name) {
$.post('getField', {name: name}, function (result) {
if (result.code === 1) {
let $dataBody = $("#dataBody");
if (adminDebug) {
console.time('表信息与相关DOM操作耗时');
}
let controller = result.data.controller;
let model = result.data.model;
let validate = result.data.validate;
let field = result.data.field;
if (adminDebug) {
console.log('字段数量:' + field.length);
}
let table = result.data.table;
//中文名
$('#cn_name').val(table.cn_name);
//如果是自动生成类名
if ($('#auto_class_name').is(':checked')) {
$("#controller_name").val(controller.name);
$("#model_name").val(model.name);
$("#validate_name").val(validate.name);
}
$dataBody.html('');
//字段名
let field_name = "#data-template input[name='field_nameFORM_INDEX[]']";
//字段类型
let field_type = "#data-template input[name='field_typeFORM_INDEX[]']";
//是否为列表字段
let field_list = "#data-template [name='is_listFORM_INDEX[]']";
//是否为搜索字段
let field_search = "#data-template [name='is_searchFORM_INDEX[]']";
//是否为表单字段
let field_form = "#data-template [name='is_formFORM_INDEX[]']";
//中文名称
let form_name = "#data-template [name='form_nameFORM_INDEX[]']";
//表单类型
let form_type = "#data-template [name='form_typeFORM_INDEX[]']";
//表单验证
let form_validate = "#data-template [name='form_validateFORM_INDEX[]']";
//字段默认值
let field_form_default = "#data-template [name='field_defaultFORM_INDEX[]']";
//获取器/修改器
let getter_setter = "#data-template [name='getter_setterFORM_INDEX[]']";
//列表排序
let list_sort = "#data-template [name='list_sortFORM_INDEX[]']";
//
let listHtml = '';
$.each(field, function (index, item) {
//字段名
$(field_name).attr('value', item.name);
//字段类型
$(field_type).attr('value', item.field_type);
//中文名称
$(form_name).attr('value', item.cn_name);
//默认值
$(field_form_default).attr('value', item.default);
//表单类型
$(form_type).val(item.form_type);
//是否为列表字段
if (item.is_list === 1) {
$(field_list).attr('checked', true);
} else {
$(field_list).attr('checked', false);
}
//是否为搜索字段
if (item.is_search === 1) {
$(field_search).attr('checked', true);
} else {
$(field_search).attr('checked', false);
}
//是否为表单字段
if (item.is_form === 1) {
$(field_form).attr('checked', true);
} else {
$(field_form).attr('checked', false);
}
//表单类型
$(form_type).find("option[value='" + item.form_type + "']").attr("selected", true);
//表单验证内容
$(form_validate).html(item.validate_html);
//表单选项
$(form_validate).find("option[value='required']").attr("selected", true);
//获取器/修改器
if (item.getter_setter !== false) {
$(getter_setter).find("option[value='" + item.getter_setter + "']").attr("selected", true);
}
//优化生成DOM慢的问题
formIndex++;
listHtml += $("#data-template").html().replace(/FORM_INDEX/g, '[' + formIndex + ']').replace(/INDEX_ID/g, formIndex);
if (getter_setter !== false) {
$(getter_setter).find("option[value='" + item.getter_setter + "']").attr("selected", false);
}
$(form_type).find("option[value='" + item.form_type + "']").attr("selected", false);
$(field_name).attr('value', '');
$(field_type).attr('value', '');
$(form_validate).empty();
});
$dataBody.append(listHtml);
dataBodyRefreshed();
if (adminDebug) {
console.timeEnd('表信息与相关DOM操作耗时');
}
}
});
}
//表单元素类型改变
function selectField(field) {
let $field = $(field);
let form_type = $field.val();
console.log(form_type);
let $validate_select = $field.parent().parent().next().find('.form-validate-select');
$.post('getValidateSelect', {form_type: form_type}, function (result) {
if (1 === result.code) {
$validate_select.html(result.data);
$validate_select.select2();
} else {
layer.msg(result.msg);
}
});
}
//刷新菜单
function refreshMenu() {
//目前还没写,争取尽快完善
}
//字段更多设置
$("#pjax-container").off('click').on('click', '.setting-more', function () {
let $dom = $('#field_setting_div_' + $(this).data('id'));
$dom.is(":hidden") ? $dom.show() : $dom.hide();
});
//选择关联类型防呆设计
function selectRelation(obj) {
let $obj = $(obj);
let relation_type = parseInt($obj.val());
let relation_show = $obj.data('relationShow');
let relation_table = $obj.data('relationTable');
if (relation_type === 1) {
$('input[name="' + relation_table + '"]').attr('readonly', 'readonly');
$('input[name="' + relation_show + '"]').removeAttr('readonly');
} else if (relation_type === 2) {
$('input[name="' + relation_show + '"]').attr('readonly', 'readonly');
$('input[name="' + relation_table + '"]').removeAttr('readonly');
} else {
$('input[name="' + relation_table + '"]').attr('readonly', 'readonly');
$('input[name="' + relation_show + '"]').attr('readonly', 'readonly');
}
}
//列表刷新后的操作
function dataBodyRefreshed() {
$('[data-toggle="tooltip"]').tooltip();
$('#dataBody .select2').select2();
}
</script>
{/block}

View File

@ -0,0 +1,218 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-6">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<form id="dataForm" class="form-horizontal dataForm" action="formField" method="post"
enctype="multipart/form-data">
<div class="box-body">
<div class="form-group">
<label for="form_name" class="col-sm-2 control-label">名称</label>
<div class="col-sm-10 col-md-4">
<input maxlength="50" id="form_name" autocomplete="off" name="form_name"
class="form-control" placeholder="请输入名称">
</div>
</div>
<div class="form-group">
<label for="field_name" class="col-sm-2 control-label">字段</label>
<div class="col-sm-10 col-md-4">
<input maxlength="50" id="field_name" autocomplete="off" name="field_name"
class="form-control" placeholder="请输入字段">
</div>
</div>
<div class="form-group">
<label for="form_type" class="col-sm-2 control-label">类型</label>
<div class="col-sm-10 col-md-4">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-list"></i></span>
<select class="form-control select2 form-type-select" id="form_type"
name="form_type">
<option value="text">文本[text]</option>
<option value="number">数字[number]</option>
<option value="password">密码[password]</option>
<option value="mobile">手机号[mobile]</option>
<option value="email">邮箱[email]</option>
<option value="id_card">身份证号[id_card]</option>
<option value="url">网址[url]</option>
<option value="ip">IP地址[ip]</option>
<option value="texterea">文本域[textarea]</option>
<option value="checkbox">复选[checkbox]</option>
<option value="switch">开关[switch]</option>
<option value="radio">单选[radio]</option>
<option value="select">选择列表[select]</option>
<option value="multi_select">多项选择列表[multi-select]</option>
<option value="image">图片上传[image]</option>
<option value="multi_image">多图上传[multi-image]</option>
<option value="file">文件上传[file]</option>
<option value="multi_file">多文件上传[multi-file]</option>
<option value="date">日期[date]</option>
<option value="date_range">日期范围[date-range]</option>
<option value="datetime">日期时间[datetime]</option>
<option value="datetime_range">日期时间范围[datetime-range]</option>
<option value="year">年[year]</option>
<option value="year_range">年范围[year-range]</option>
<option value="year_month">年月[year-month]</option>
<option value="year_month_range">年月范围[year-month-range]</option>
<option value="map">地图选点[map]</option>
<option value="color">颜色选择[color]</option>
<option value="icon">图标选择[icon]</option>
<option value="editor">富文本编辑器[editor]</option>
<option value="province_city_district">省市区[三级联动]</option>
</select>
</div>
</div>
</div>
<script>
$('#form_type').select2();
</script>
</div>
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
生成
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">生成结果</h3>
</div>
<div class="box-body">
<textarea id="code" style="width: 100%" placeholder="生成结果" rows="6"></textarea>
</div>
<div class="box-footer">
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button class="clipboard-btn btn flat btn-info" data-clipboard-target="#code">
复制到剪切板
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
// button的class的值
var clipboardDemos = new ClipboardJS('.clipboard-btn');
clipboardDemos.on('success', function (e) {
e.clearSelection();
console.info('Action:', e.action);
console.info('Text:', e.text);
console.info('Trigger:', e.trigger);
layer.msg('复制成功');
});
clipboardDemos.on('error', function (e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
console.log('复制失败');
});
</script>
<script>
$(function () {
/**
* ajax表单提交
*/
$(".dataForm").submit(function (e) {
e.preventDefault();
var loadT = layer.msg('正在提交,请稍候…', {icon: 16, time: 0, shade: [0.3, "#000"]});
var form_action = $(this).attr('action');
var form_method = $(this).attr('method');
var form_data = new FormData($(this)[0]);
console.log('%cajax submit start!', ';color:#333333');
console.log('action:' + form_action);
console.log('method:' + form_method);
console.log('data:' + form_data);
$.ajax({
url: form_action,
dataType: 'json',
type: form_method,
data: form_data,
contentType: false,
processData: false,
success: function (result) {
layer.close(loadT);
layer.msg(result.msg, {
icon: result.code ? 1 : 2
});
console.log('submit success!');
if (result.code === 1) {
addCode(result.data);
console.log('%cresult success', ';color:#00a65a');
} else {
addCode('');
console.log('%cresult fail', ';color:#f39c12');
}
},
error: function (xhr, type, errorThrown) {
//异常处理;
console.log('%csubmit fail!', ';color:#dd4b39');
console.log();
console.log("type:" + type + ",readyState:" + xhr.readyState + ",status:" + xhr.status);
console.log("url:" + form_action);
console.log("data:" + form_data);
layer.close(loadT);
layer.msg('访问错误,代码' + xhr.status, {icon: 2});
}
}
);
return false;
}
);
});
function addCode(code) {
//$('#code').html(code);
$('#code').val(code);
}
</script>
{/block}

View File

@ -0,0 +1,29 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-3 col-sm-6 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-aqua"><i class="fa fa-file-code-o"></i></span>
<div class="info-box-content">
<span class="info-box-text">代码自动生成</span>
<a href="{:url('generate/add')}" class="info-box-number">点击跳转</a>
</div>
</div>
</div>
<div class="col-md-3 col-sm-6 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-red"><i class="fa fa-code"></i></span>
<div class="info-box-content">
<span class="info-box-text">表单字段生成</span>
<a href="{:url('generate/form')}" class="info-box-number">点击跳转</a>
</div>
</div>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,392 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<script src="https://www.layuicdn.com/layui/layui.js"></script>
<link rel="stylesheet" type="text/css" href="https://www.layuicdn.com/layui/css/layui.css">
<style type="text/css">
/* 图片展示
----------------------------------------------- */
ul.albums {
display: block;
min-height: 1px;
height: auto;
overflow: hidden;
padding: 5px 0;
margin: 0 15px;
border: 1px dashed #ccc;
}
ul.albums li {
position: relative;
display: inline-block;
padding: 5px;
border: 1px solid #e5e5e5;
margin: 5px 0 0 20px;
cursor: pointer;
}
ul.albums li a.btn-close {
display: block;
position: absolute;
z-index: 2;
top: -8px;
right: -10px;
width: 20px;
height: 20px;
}
ul.albums li a.btn-fm{width: 100px;
display:none;
height: 100px;
border: 0px;
opacity: 0.5;
background-color: #000;
line-height: 100px;
text-align: center;
color: #fff;
position: absolute;}
ul.albums li:hover a.btn-fm{ display: block; }
ul.albums li a.btn-fm_z{
display:none;
color: #ccc;
border: 0px;
background-color: #000;
position: absolute;
bottom: 5px;
left: 5px;
opacity: 0.6;
width: 40px;
text-align: center;
}
</style>
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post"
enctype="multipart/form-data">
<div class="box-body" style="height: 725px;">
<div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
<ul class="layui-tab-title">
<li class="layui-this">基本设置</li>
<li>商品详情</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">商品名称</label>
<div class="col-sm-10 col-md-4">
<input id="name" name="name" value="{$data.name|default=''}" placeholder="请输入商品名称" type="text" class="form-control field-text">
</div>
</div>
<div class="form-group">
<label for="goods_category_id" class="col-sm-2 control-label">所属分类</label>
<div class="col-sm-10 col-md-4">
<select name="goods_category_id" id="goods_category_id"
class="form-control field-select" data-placeholder="请选择所属分类">
<option value=""></option>
{$goods_category_list|raw}
</select>
</div>
</div>
<script>
$('#goods_category_id').select2();
</script>
<div class="form-group">
<label for="img" class="col-sm-2 control-label">上传图片</label>
<ul class="albums" id="albums">
{foreach name="imgurl_list" item="img1"}
<li class="img">
<a class="btn-close layui-btn-primary" title="删除" href="javascript:void(0)" onclick="removeImg(this)">
<i class="layui-icon" style="font-size: 20px; line-height: 20px;"></i>
</a>
<a class="btn-fm layui-btn-primary" title="设为封面" href="javascript:void(0)" onclick="removeImg_l(this)">设置为封面</a>
<a class="btn-fm_z layui-btn-primary" {if $img1.is_cover == 1}style="display: block;"{/if} title="封面" href="javascript:void(0)">封面</a>
<img src="{$img1['thumb_image']}" width="100" height="100">
<input type="hidden" name="ori_img[]" class="ori_img" value="{$img1['ori_image']}">
<input type="hidden" name="thumb_img[]" class="thumb_img" class="inputAlbums" value="{$img1['thumb_image']}">
</li>
{/foreach}
<li id="nophoto" ><img src="/static/admin/images/nophoto_100x100.png"></li>
</ul>
<input type="hidden" name="ori_fm_img" id="ori_fm_img" value="{$ori_img|default=''}">
<input type="hidden" name="thumb_img_f" id="thumb_img_f" value="{$thumb_img|default=''}">
</div>
<script type="text/javascript">
layui.use(['upload','laydate','form'], function(){
var form = layui.form;
var upload = layui.upload;
//执行实例
upload.render({
elem: '#nophoto' //绑定元素
,url: "{:url('file/icon')}" //接口url
,data:{type:1,width:750,heigh:461}
,field:'image'
,multiple: true
,done: function(res){
var html='';
html+='<li class="img">';
html+='<a class="btn-close layui-btn-primary" title="删除" href="javascript:void(0)" onclick="removeImg(this)">';
html+='<i class="layui-icon" style="font-size: 20px; line-height: 20px;">&#xe640;</i>';
html+='</a>';
html+='<a class="btn-fm layui-btn-primary" title="设为封面" href="javascript:void(0)" onclick="removeImg_l(this)" img="">设置为封面</a>';
html+='<a class="btn-fm_z layui-btn-primary" title="封面" href="javascript:void(0)">封面</a>';
html+='<img src="'+res.data.avatar_logo_thum+'" width="100" height="100">'
html+='<input type="hidden" name="ori_img[]" class="ori_img" value="'+res.data.avatar_logo+'">';
html+='<input type="hidden" name="thumb_img[]" class="thumb_img" class="inputAlbums" value="'+res.data.avatar_logo_thum+'">';
html+='</li>';
$(".albums").prepend(html);
}
,error: function(){
layer.tips('图片错误', '#btn');
return false;
}
});
});
function removeImg(obj){
$(obj).parent().remove();
var img=$('.img').length;
if(img==5){
$('#nophoto').hide();
}else{
$('#nophoto').show();
}
var ori_img=$(obj).siblings('.ori_img').val();
var thumb_img=$('#thumb_img').val();
if(ori_img==ori_fm_img){
$('#ori_fm_img').val('');
$('#thumb_img_f').val('');
}
}
function removeImg_l(obj){
var thumb_img=$(obj).siblings('.thumb_img').val();
var ori_img=$(obj).siblings('.ori_img').val();
$('#ori_fm_img').val(ori_img);
$('#thumb_img_f').val(thumb_img);
$('.btn-fm_z').css('display','none');
$(obj).siblings('.btn-fm_z').css('display','block');
}
</script>
<div class="form-group">
<label for="price" class="col-sm-2 control-label">售价</label>
<div class="col-sm-10 col-md-4">
<input id="price" name="price" value="{$data.price|default='0.00'}"
placeholder="请输入售价" type="number" class="form-control field-number">
</div>
</div>
<div class="form-group">
<label for="attr" class="col-sm-2 control-label">规格</label>
<div class="col-sm-10 col-md-4">
<input id="attr" name="attr" value="{$data.attr|default=''}"
placeholder="请输入规格" type="text" class="form-control field-number">
</div>
</div>
<div class="form-group">
<label for="stock" class="col-sm-2 control-label">库存</label>
<div class="col-sm-10 col-md-4">
<input id="stock" name="stock" value="{$data.stock|default='100'}"
placeholder="请输入库存" type="number" class="form-control field-number">
</div>
</div>
<script>
$('#stock')
.bootstrapNumber({
upClass: 'success',
downClass: 'primary',
center: true
});
</script>
<div class="form-group">
<label for="status" class="col-sm-2 control-label">是否上架</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="status" value="1" {if(!isset($data)
||$data.status==1)}checked{/if} type="checkbox"/>
<input class="switch field-switch" placeholder="是否上架" name="status"
value="{$data.status|default='1'}" hidden/>
</div>
</div>
<script>
$('#status').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
<div class="form-group">
<label for="is_recommend" class="col-sm-2 control-label">热门推荐</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="is_recommend" value="1" {if(!isset($data)
||$data.is_recommend==1)}checked{/if} type="checkbox"/>
<input class="switch field-switch" placeholder="是否上架" name="is_recommend"
value="{$data.is_recommend|default='1'}" hidden/>
</div>
</div>
<script>
$('#is_recommend').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
<div class="form-group">
<label for="sort_number" class="col-sm-2 control-label">排序(升序)</label>
<div class="col-sm-10 col-md-4">
<input id="sort_number" name="sort_number" value="{$data.sort_number|default='1000'}"
placeholder="请输入排序(升序)" type="text" class="form-control field-text">
</div>
</div>
<script>
$('#sort_number')
.bootstrapNumber({
upClass: 'success',
downClass: 'primary',
center: true
});
</script>
</div>
<div class="layui-tab-item">
<div class="form-group">
<label for="detail" class="col-sm-2 control-label">商品详情</label>
<div class="col-sm-10">
<script id="detail" name="detail" type="text/plain">{$data.detail|raw|default=''}</script>
</div>
</div>
<script>
UE.delEditor('detail');
var ue = UE.getEditor('detail',{
serverUrl :UEServer,
});
ue.ready(function() {
ue.setHeight(500); //设置高度
});
</script>
</div>
</div>
</div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
{if !isset($data)}
<div class="btn-group pull-right">
<label class="createContinue">
<input type="checkbox" value="1" id="_create" name="_create"
title="继续添加数据">继续添加</label>
</div>
{/if}
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate({
rules: {
'goods_category_id': {
required: true,
},
'brand_id': {
required: true,
},
'name': {
required: true,
},
'origin_price': {
required: true,
},
'price': {
required: true,
},
'attr': {
required: true,
},
'detail': {
required: true,
},
'weight': {
required: true,
},
'stock': {
required: true,
},
'sort_number': {
required: true,
},
'status': {
required: true,
},
},
messages: {
'goods_category_id': {
required: "所属分类不能为空",
},
'brand_id': {
required: "品牌不能为空",
},
'name': {
required: "名称不能为空",
},
'origin_price': {
required: "原价不能为空",
},
'price': {
required: "售价不能为空",
},
'attr': {
required: "规格不能为空",
},
'detail': {
required: "详情不能为空",
},
'weight': {
required: "重量不能为空",
},
'stock': {
required: "库存不能为空",
},
'sort_number': {
required: "排序(升序不能为空",
},
'status': {
required: "是否上架不能为空",
},
}
});
</script>
{/block}

View File

@ -0,0 +1,168 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<!--数据列表页面-->
<section class="content">
<!--顶部搜索筛选-->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('index')}" method="GET">
<div class="form-group">
<input value="{$_keywords ? $_keywords : '' ;}"
name="_keywords" id="_keywords" class="form-control input-sm" placeholder="名称">
</div>
<div class="form-group">
<select name="_order" id="_order" class="form-control input-sm index-order">
<option value="">排序字段</option>
<option value="id" {if isset($_order) && $_order=='id'}selected{/if}>ID</option>
<option value="origin_price" {if isset($_order) &&
$_order=='origin_price'}selected{/if}>原价
</option>
<option value="price" {if isset($_order) && $_order=='price'}selected{/if}>售价</option>
<option value="weight" {if isset($_order) && $_order=='weight'}selected{/if}>重量</option>
<option value="stock" {if isset($_order) && $_order=='stock'}selected{/if}>库存</option>
<option value="sort_number" {if isset($_order) && $_order=='sort_number'}selected{/if}>
排序(升序
</option>
<option value="status" {if isset($_order) && $_order=='status'}selected{/if}>是否上架
</option>
</select>
</div>
<div class="form-group">
<select name="_by" id="_by" class="form-control input-sm index-order">
<option value="">排序方式</option>
<option value="desc" {if isset($_by) && $_by=='desc'}selected{/if}>倒序</option>
<option value="asc" {if isset($_by) && $_by=='asc'}selected{/if}>正序</option>
</select>
</div>
<script>
$('#_order').select2();
$('#_by').select2();
</script>
<div class="form-group">
<button class="btn btn-sm btn-primary" type="submit"><i class="fa fa-search"></i> 查询
</button>
</div>
<div class="form-group">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<!--数据列表顶部-->
<div class="box-header">
<div>
<a title="添加" data-toggle="tooltip" class="btn btn-primary btn-sm " href="{:url('add')}">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-danger btn-sm AjaxButton" data-toggle="tooltip" title="删除选中数据"
data-confirm-title="删除确认" data-confirm-content="您确定要删除选中的数据吗?" data-id="checked"
data-url="{:url('del')}">
<i class="fa fa-trash"></i> 删除
</a>
<a class="btn btn-success btn-sm ReloadButton" data-toggle="tooltip" title="刷新">
<i class="fa fa-refresh"></i> 刷新
</a>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>
<input id="dataCheckAll" type="checkbox" onclick="checkAll(this)" class="checkbox"
placeholder="全选/取消">
</th>
<th>ID</th>
<th>名称</th>
<th>所属分类</th>
<th>售价</th>
<th>规格</th>
<th>库存</th>
<th>排序(升序)</th>
<th>是否上架</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{foreach name="data" item="item"}
<tr>
<td>
<input type="checkbox" onclick="checkThis(this)" name="data-checkbox"
data-id="{$item.id}" class="checkbox data-list-check" value="{$item.id}"
placeholder="选择/取消">
</td>
<td>{$item.id}</td>
<td>{$item.name}</td>
<td>{$item.goods_category.name|default=''}</td>
<td>{$item.price}</td>
<td>{$item.attr}</td>
<td>{$item.stock}</td>
<td>{$item.sort_number}</td>
<td>{$item.status_text}</td>
<td>{$item.create_time}</td>
<td class="td-do">
<a href="{:url('edit',['id'=>$item.id])}"
class="btn btn-primary btn-xs" title="修改" data-toggle="tooltip">
<i class="fa fa-pencil"></i>
</a>
<a class="btn btn-danger btn-xs AjaxButton" data-toggle="tooltip" title="删除"
data-id="{$item.id}" data-confirm-title="删除确认"
data-confirm-content='您确定要删除ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('del')}">
<i class="fa fa-trash"></i>
</a>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,98 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post"
enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body">
<div class="form-group">
<label for="parent_id" class="col-sm-2 control-label">上级分类</label>
<div class="col-sm-10 col-md-4">
<select name="parent_id" id="parent_id" class="form-control field-select"
data-placeholder="请选择上级分类">
<option value="0">顶级分类</option>
{$cat_list|raw}
</select>
</div>
</div>
<script>
$('#parent_id').select2();
</script>
<div class="form-group">
<label for="name" class="col-sm-2 control-label">名称</label>
<div class="col-sm-10 col-md-4">
<input id="name" name="name" value="{$data.name|default=''}" placeholder="请输入名称"
type="text" class="form-control field-text">
</div>
</div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
{if !isset($data)}
<div class="btn-group pull-right">
<label class="createContinue">
<input type="checkbox" value="1" id="_create" name="_create"
title="继续添加数据">继续添加</label>
</div>
{/if}
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate({
rules: {
'parent_id': {
required: true,
},
'name': {
required: true,
},
},
messages: {
'parent_id': {
required: "上级分类不能为空",
},
'name': {
required: "名称不能为空",
},
}
});
</script>
{/block}

View File

@ -0,0 +1,85 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<!--数据列表页面-->
<section class="content">
<!--顶部搜索筛选-->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('index')}" method="GET">
<div class="form-group">
<input value="{$_keywords ? $_keywords : '' ;}"
name="_keywords" id="_keywords" class="form-control input-sm" placeholder="名称">
</div>
<div class="form-group">
<button class="btn btn-sm btn-primary" type="submit"><i class="fa fa-search"></i> 查询
</button>
</div>
<div class="form-group">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<!--数据列表顶部-->
<div class="box-header">
<div>
<a title="添加" data-toggle="tooltip" class="btn btn-primary btn-sm " href="{:url('add')}">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-danger btn-sm AjaxButton" data-toggle="tooltip" title="删除选中数据"
data-confirm-title="删除确认" data-confirm-content="您确定要删除选中的数据吗?" data-id="checked"
data-url="{:url('del')}">
<i class="fa fa-trash"></i> 删除
</a>
<a class="btn btn-success btn-sm ReloadButton" data-toggle="tooltip" title="刷新">
<i class="fa fa-refresh"></i> 刷新
</a>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>
<input id="dataCheckAll" type="checkbox" onclick="checkAll(this)" class="checkbox"
placeholder="全选/取消">
</th>
<th>ID</th>
<th>名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{$data|raw}
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,155 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<style>
.header-font{
font-size: 20px
}
.layui-card .data-all {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.layui-card .text-style {
font-size: 16px;
}
.header-time{
margin-left: 20px
}
.layadmin-shortcut .shortcut-list {
padding: 30px 0;
display: flex;
flex-wrap: wrap;
}
.layadmin-shortcut .shortcut-list li {
min-width: 100px;
margin-bottom: 20px;
width: 12.5%;
}
.layadmin-shortcut .shortcut-list .icon{
width: 62px;
height: 62px;
margin-bottom: 5px;
}
.tips {
float: right;
padding: 0 10px;
margin-top: 10px;
height: 20px;
line-height: 20px;
font-size: 12px;
color: #3A91FB;
border-radius: 30px;
border: 1px #3A91FB solid;
background: #eaf3ff;
}
</style>
<section class="content">
<div class="layui-fluid" style="margin-bottom: 100px">
<div class="layui-card" >
<div class="layui-card-header">
<span class="header-font">运营数据</span>
<span class="header-time">更新时间:{$res.time}</span>
</div>
</div>
<div class="layui-row layui-col-space15">
<div class="layui-col-sm3">
<div class="layui-card">
<div class="layui-card-header">
成交订单(笔)
<span class="tips">今日</span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p class="layuiadmin-big-font">{$res.order_num_today}</p>
<p>昨日:<span class="text-style">{$res.order_num_yesterday}</span>
<span class="text-style" {if condition="$res.order_num_change lt 0" } style="color: #009688" {elseif condition="$res.order_num_change egt 0" } style="color: #FA2828" {/if}>{$res.order_num_change}</span></p>
<div class="data-all">成交订单总量(笔)<div class="text-style">{$res.order_num_all}</div></div>
</div>
</div>
</div>
<div class="layui-col-sm3 ">
<div class="layui-card">
<div class="layui-card-header">
销售金额(元)
<span class="tips">今日</span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p class="layuiadmin-big-font">{$res.order_amount_today}</p>
<p>昨日:<span class="text-style">{$res.order_amount_yesterday}</span>
<span class="text-style" {if condition="$res.order_amount_change lt 0" } style="color: #009688" {elseif condition="$res.order_amount_change egt 0" } style="color: #FA2828" {/if}>{$res.order_amount_change}</span></p>
<div class="data-all">销售总额(元)<div class="text-style">{$res.order_amount_all}</div></div>
</div>
</div>
</div>
<div class="layui-col-sm3 ">
<div class="layui-card">
<div class="layui-card-header">
新增会员(人)
<span class="tips">今日</span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p class="layuiadmin-big-font">{$res.add_user_today}</p>
<p >昨日:<span class="text-style">{$res.add_user_yesterday}</span>
<span class="text-style" {if condition="$res.add_user_change lt 0" } style="color: #009688" {elseif condition="$res.add_user_change egt 0" } style="color: #FA2828" {/if}>{$res.add_user_change}</span></p>
<div class="data-all">会员总量(人)<div class="text-style">{$res.user_all}</div></div>
</div>
</div>
</div>
<!--快捷功能-->
<div class="layui-col-sm12">
<div class="layui-card">
<div class="layui-card-header">快捷功能</div>
<div class="layui-card-body">
<div class="layadmin-shortcut">
<ul class="shortcut-list">
<li class="shop-item" >
<a lay-href="{:url('goods/index')}" data-id="29">
<img class="icon" src="__PUBLIC__/static/common/image/workbench/goods.png" alt="">
<cite>设备管理</cite>
</a>
</li>
<li class="shop-item">
<a lay-href="{:url('user/index')}" data-id="33">
<img class="icon" src="__PUBLIC__/static/common/image/workbench/user.png" alt="">
<cite>会员管理</cite>
</a>
</li>
<li class="shop-item">
<a lay-href="{:url('order/index')}" data-id="37">
<img class="icon" src="__PUBLIC__/static/common/image/workbench/order.png" alt="">
<cite>用户订单管理</cite>
</a>
</li>
<li class="shop-item">
<a lay-href="{:url('account_log/integrallist')}" data-id="39">
<img class="icon" src="__PUBLIC__/static/common/image/workbench/coupon.png" alt="">
<cite>积分记录</cite>
</a>
</li>
<li class="shop-item">
<a lay-href="{:url('withdraw/lists')}" data-id="39">
<img class="icon" src="__PUBLIC__/static/common/image/workbench/seckill.png" alt="">
<cite>提现记录</cite>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
</script>
{/block}

View File

@ -0,0 +1,29 @@
{if !$admin.pjax}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit">
{/if}
{block name='title'}
<title>{$admin.title|default='Admin'} | {$admin.name|default='Admin'}</title>
{/block}
{if !$admin.pjax}
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
{include file='public/head_css' /}
{include file='public/head_js' /}
</head>
<body class="hold-transition skin-blue sidebar-mini">
{/if}
<!-- 内容 -->
<div id="pjax-container">
{block name='content'}{/block}
</div>
{if !$admin.pjax}
{/if}
{if !$admin.pjax}
</body>
</html>
{/if}

View File

@ -0,0 +1,213 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<style type="text/css">
.layui-table-cell {
height: auto;
white-space: normal;
}
.layui-card-header.layuiadmin-card-header-auto {
padding-top: 15px;
padding-bottom: 15px;
height: auto;
}
.layui-form-label{ width:100px; }
</style>
<!--数据列表页面-->
<section class="content">
<!--顶部搜索筛选-->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('index')}" method="GET">
<div class="layui-form layui-card-header layuiadmin-card-header-auto">
<div class="layui-form-item">
<div class="layui-row">
<div class="layui-inline">
<label class="layui-form-label">订单搜索:</label>
<div class="layui-input-block">
<select name="search_key">
<option value="order_sn" {if isset($search_key) && $search_key=='order_sn'}selected{/if}>订单编号</option>
<option value="nickname" {if isset($search_key) && $search_key=='nickname'}selected{/if}>会员昵称</option>
<option value="user_mobile" {if isset($search_key) && $search_key=='user_mobile'}selected{/if}>会员手机号码</option>
<option value="user_sn" {if isset($search_key) && $search_key=='user_sn'}selected{/if}>会员编号</option>
</select>
</div>
</div>
<div class="layui-inline">
<input type="text" name="keyword" id="keyword" value="{$keyword?$keyword:'';}" placeholder="请输入搜索内容"
autocomplete="off" class="layui-input">
</div>
<div class="layui-inline">
<label class="layui-form-label">商品名称:</label>
<div class="layui-input-block">
<input type="text" name="goods_name" id="goods_name" value="{$goods_name?$goods_name:'';}" placeholder="请输入商品名称"
autocomplete="off" class="layui-input">
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-inline">
<label class="layui-form-label">订单类型:</label>
<div class="layui-input-block">
<select name="order_type" id="order_type">
<option value="">全部</option>
<option value="1" {if isset($order_type) && $order_type=='1'}selected{/if}>正式订单</option>
<option value="2" {if isset($order_type) && $order_type=='2'}selected{/if}>体验订单</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">下单时间:</label>
<div class="layui-input-inline">
<div class="layui-input-inline">
<input type="text" name="start_time" class="layui-input" id="start_time"
placeholder="" autocomplete="off" value="{$start_time?$start_time:'';}">
</div>
</div>
<div class="layui-input-inline" style="margin-right: 5px;width: 20px;">
<label class="layui-form-mid">至</label>
</div>
<div class="layui-input-inline">
<input type="text" name="end_time" class="layui-input" id="end_time"
placeholder="" autocomplete="off" value="{$end_time?$end_time:'';}">
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<button class="btn btn-success btn-sm" type="submit" >查询</button>
</div>
<div class="layui-inline">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>
<div style="width:380px;text-align:center;">用户信息</div>
</th>
<th>
<div class="layui-table-cell" style="width:380px;text-align:center;">订单信息</div>
</th>
<th>
<div class="layui-table-cell" style="width:380px;text-align:center;">商品信息</div>
</th>
<th><div class="layui-table-cell" style="width:100px;text-align:center;">购买数量</div></th>
<th><div class="layui-table-cell" style="width:200px;text-align:center;">结束时间</div></th>
<th><div class="layui-table-cell" style="width:100px;text-align:center;">产生收益</div></th>
<th><div class="layui-table-cell" style="width:200px;text-align:center;">创建时间</div></th>
</tr>
</thead>
<tbody>
{foreach name="data" item="item"}
<tr>
<td class="layui-table-col-special">
<div class="layui-table-cell laytable-cell-1-0-2">
<img src="{$item.avatar}" style="height:80px;width: 80px;margin-right: 10px;" class="image-show">
<div class="layui-input-inline" style="text-align:left;width: 240px;">
<p>用户编号:{$item.sn}</p>
<p>用户昵称:{$item.nickname}</p>
<p>用户手机:{$item.mobile}</p>
</div>
</div>
</td>
<td class="layui-table-col-special">
<div class="layui-table-cell laytable-cell-1-0-2">
<div class="layui-input-inline" style="text-align:left;width: 240px;">
<p>订单编号:{$item.order_no}</p>
<p>订单类型:{$item.order_type_text}</p>
<p>订单金额:{$item.order_price}</p>
</div>
</div>
</td>
<td class="layui-table-col-special">
<div class="layui-table-cell laytable-cell-1-0-2">
<div class="layui-input-inline" style="text-align:left;width: 240px;">
<p>设备名称:{$item.goods_name}</p>
<p>设备规格:{$item.attr}M</p>
</div>
</div>
</td>
<td>
<div class="layui-table-cell" style="width:100px;text-align:center;">{$item.number}</div>
</td>
<td>
<div class="layui-table-cell" style="width:200px;text-align:center;">{$item.end_time}</div>
</td>
<td>
<div class="layui-table-cell" style="width:100px;text-align:center;">{$item.profit}</div>
</td>
<td>
<div class="layui-table-cell" style="width:200px;text-align:center;">{$item.create_time}</div>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
<script>
layui.use('form', function(){
var form = layui.form;
form.render('select');
});
//日期时间范围
laydate.render({
elem: '#start_time'
,type: 'datetime'
,trigger: 'click'
});
//日期时间范围
laydate.render({
elem: '#end_time'
,type: 'datetime'
,trigger: 'click'
});
</script>
{/block}

View File

@ -0,0 +1,53 @@
{if !$admin.pjax}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit">
{/if}
{block name='title'}
<title>{$admin.title|default='Admin'} | {$admin.name|default='Admin'}</title>
{/block}
{if !$admin.pjax}
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
{include file='public/head_css' /}
{include file='public/head_js' /}
</head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
{/if}
<!-- 顶部 -->
{block name='header'}
{include file='public/header' /}
{/block}
<!-- 左侧 -->
{block name='sidebar'}
{include file='public/sidebar' /}
{/block}
<!-- 内容 -->
<div class="content-wrapper" id="pjax-container">
{block name='content'}
{/block}
</div>
{block name='footer'}
{include file='public/footer' /}
{/block}
{block name='control_sidebar'}
{include file='public/control_sidebar' /}
{/block}
{if !$admin.pjax}
</div>
{/if}
{if !$admin.pjax}
</body>
</html>
{/if}

View File

@ -0,0 +1,32 @@
<!--内容头部-->
<section class="content-header">
<h1>
{$admin.title|default='admin'|raw}
</h1>
<ol class="breadcrumb">
<li><a href="{:url('index/index')}"><i class="fa fa-dashboard"></i> 主页</a></li>
<li class="active">{$admin.title|default='Admin'|raw}</li>
</ol>
</section>
{if $Think.session.error_message}
<!--如果有错误或者成功的消息-->
<script>
layer.msg('{$Think.session.error_message}',{icon:2});
$.pjax({
url: "{$Think.session.url}",
container: '#pjax-container'
});
</script>
{/if}
{if $Think.session.success_message}
<script>
layer.msg('{$Think.session.success_message}',{icon:1});
$.pjax({
url: '{$Think.session.url}',
container: '#pjax-container'
});
</script>
{/if}

View File

@ -0,0 +1,12 @@
<!--侧边栏-->
{if !$admin.pjax}
<aside class="control-sidebar control-sidebar-dark">
<ul class="nav nav-tabs nav-justified control-sidebar-tabs">
</ul>
<div class="tab-content">
<div class="tab-pane" id="control-sidebar-home-tab">
</div>
</div>
</aside>
<div class="control-sidebar-bg"></div>
{/if}

View File

@ -0,0 +1,10 @@
<!--页面底部-->
{if !$admin.pjax}
<footer class="main-footer">
<div class="pull-right hidden-xs">
<b>Version</b> {$admin.version|default='1.0'}
</div>
<strong>Copyright &copy; 2020 <a href="{$admin.link|default='#'}">{$admin.author|default='admin'}</a>.</strong> All rights
reserved.
</footer>
{/if}

View File

@ -0,0 +1,18 @@
<!--头部css-->
{css href="__ADMIN_PLUGINS__/bootstrap/css/bootstrap.min.css" /}
{js href="__ADMIN_PLUGINS__/bootstrap-switch/css/bootstrap-switch.min.css" /}
{css href="__ADMIN_PLUGINS__/font-awesome/css/font-awesome.min.css" /}
{css href="__ADMIN_PLUGINS__/iconpicker/css/iconpicker.min.css" /}
{css href="__ADMIN_PLUGINS__/select2/css/select2.min.css" /}
{css href="__ADMIN_PLUGINS__/fileinput/css/fileinput.min.css" /}
{css href="__ADMIN_PLUGINS__/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css" /}
{css href="__ADMIN_CSS__/AdminLTE.min.css" /}
{css href="__ADMIN_CSS__/admin.css" /}
{css href="__ADMIN_CSS__/_all-skins.min.css" /}
{css href="__ADMIN_CSS__/skins.css" /}
{css href="__ADMIN_PLUGINS__/nprogress/nprogress.css" /}
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

View File

@ -0,0 +1,49 @@
<!--头部js-->
{if !$admin.pjax}
{js href="__ADMIN_PLUGINS__/js-cookie/js.cookie-2.2.0.min.js" /}
{js href="__ADMIN_PLUGINS__/jquery/jquery.min.js" /}
{js href="__ADMIN_PLUGINS__/jquery-ui/jquery-ui.min.js" /}
{js href="__ADMIN_PLUGINS__/layer/layer.js" /}
{js href="__ADMIN_PLUGINS__/laydate/laydate.js" /}
{js href="__ADMIN_PLUGINS__/bootstrap/js/bootstrap.min.js" /}
{js href="__ADMIN_PLUGINS__/jquery-slimscroll/jquery.slimscroll.min.js" /}
{js href="__ADMIN_PLUGINS__/jquery-validation/jquery.validate.min.js" /}
{js href="__ADMIN_PLUGINS__/jquery-validation/localization/messages_zh.min.js" /}
{js href="__ADMIN_PLUGINS__/bootstrap-switch/js/bootstrap-switch.min.js" /}
{js href="__ADMIN_PLUGINS__/bootstrap-number/bootstrap-number.min.js" /}
{js href="__ADMIN_PLUGINS__/fastclick/fastclick.min.js" /}
{js href="__ADMIN_PLUGINS__/select2/js/select2.full.min.js" /}
{js href="__ADMIN_PLUGINS__/nprogress/nprogress.min.js" /}
{js href="__ADMIN_PLUGINS__/iconpicker/js/iconpicker.min.js" /}
{js href="__ADMIN_PLUGINS__/ueditor/ueditor.config.js" /}
{js href="__ADMIN_PLUGINS__/ueditor/ueditor.all.min.js" /}
{js href="__ADMIN_PLUGINS__/ueditor/lang/zh-cn/zh-cn.min.js" /}
{js href="__ADMIN_PLUGINS__/clipboard/clipboard.min.js" /}
{js href="__ADMIN_PLUGINS__/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js" /}
{js href="__ADMIN_PLUGINS__/viewer/viewer.min.js" /}
{js href="__ADMIN_PLUGINS__/viewer/jquery-viewer.min.js" /}
{js href="__ADMIN_JS__/tag/jquery.tag-editor.js" /}
{css href="__ADMIN_JS__/tag/jquery.tag-editor.css" /}
<script src="https://www.layuicdn.com/layui/layui.js"></script>
<link rel="stylesheet" type="text/css" href="https://www.layuicdn.com/layui/css/layui.css">
<!--勿必把地图api key更换成自己的-->
<script type="text/javascript" src='//webapi.amap.com/maps?v=1.4.15&key=cccf8ea926e153be0a013d55edd47c11&plugin=AMap.ToolBar'></script>
<!-- UI组件库 1.0 -->
<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
<script>
//是否为debug模式
var adminDebug = {$debug};
//cookie前缀
var cookiePrefix = '{$cookie_prefix}';
//UEditor server地址
var UEServer = "{:url('editor/server')}";
//列表页当前选择的ID
var dataSelectIds = [];
</script>
{js href="__ADMIN_JS__/adminlte.min.js" /}
{js href="__ADMIN_JS__/jquery.pjax.js" /}
{js href="__ADMIN_JS__/admin.js" /}
{js href="__ADMIN_JS__/demo.js" /}
{js href="__ADMIN_JS__/app.js" /}
{/if}

View File

@ -0,0 +1,54 @@
<!--网页头部-->
{if !$admin.pjax}
<header class="main-header">
<a class="logo">
<span class="logo-mini">{$admin.short_name|default='Backend'}</span>
<span class="logo-lg">{$admin.name|default='Backend'}</span>
</a>
<nav class="navbar navbar-static-top">
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="dropdown messages-menu">
<a href="#" class="dropdown-toggle ReloadButton" title="刷新页面" data-toggle="dropdown">
<i class="fa fa-refresh"></i>
</a>
</li>
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<img src="{$admin.user.avatar|default='__ADMIN_IMAGES__/avatar.png'}" class="user-image" alt="用户头像">
<span class="hidden-xs">{$admin.user.nickname|default=''}</span>
</a>
<ul class="dropdown-menu">
<li class="user-header">
<img src="{$admin.user.avatar|default='__ADMIN_IMAGES__/avatar.png'}" class="img-circle" alt="用户头像">
<p>
{$admin.user.nickname|default=''}
<small>{$admin.user.username|default=''}</small>
</p>
</li>
<li class="user-footer">
<div class="pull-left">
<a href="{:url('admin_user/profile')}" class="btn btn-default btn-flat">个人资料</a>
</div>
<div class="pull-right">
<a href="{:url('auth/logout')}" class="btn btn-default btn-flat">退出</a>
</div>
</li>
</ul>
</li>
<li>
<a href="#" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>
</li>
</ul>
</div>
</nav>
</header>
{/if}

View File

@ -0,0 +1,30 @@
<!--左侧菜单-->
{if !$admin.pjax}
<aside class="main-sidebar">
<section class="sidebar">
<div class="user-panel">
<div class="pull-left image">
<img src="{$admin.user.avatar|default='__BACKEND_IMAGES__/avatar.png'}" class="img-circle" alt="用户头像">
</div>
<div class="pull-left info">
<p>{$admin.user.nickname|default=''}</p>
<a><i class="fa fa-circle text-success"></i> 在线</a>
</div>
</div>
<form method="get" class="sidebar-form" id="sidebar-form">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="搜索菜单" id="search-input">
<span class="input-group-btn">
<button type="submit" name="search" id="search-btn" class="btn btn-flat">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
<ul class="sidebar-menu" data-widget="tree">
<li class="header">导航菜单</li>
{$admin.menu|default=''|raw}
</ul>
</section>
</aside>
{/if}

View File

@ -0,0 +1,81 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post" enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body" style="height: 500px;">
<div class="form-group">
<label for="first_ratio" class="col-sm-2 control-label">一级分销比例</label>
<div class="col-sm-10 col-md-4">
<input id="first_ratio" name="first_ratio" value="{$config.first_ratio|default=''}" placeholder="请输入一级分销比例" type="text" class="form-control field-text">
</div>
<label for="name" class="control-label">%</label>
</div>
<div class="form-group">
<label for="second_ratio" class="col-sm-2 control-label">二级分销比例</label>
<div class="col-sm-10 col-md-4">
<input id="second_ratio" name="second_ratio" value="{$config.second_ratio|default=''}" placeholder="请输入二级分销比例" type="text" class="form-control field-text">
</div>
<label for="name" class="control-label">%</label>
</div>
<div class="form-group">
<label for="number" class="col-sm-2 control-label">升级人数</label>
<div class="col-sm-10 col-md-4">
<input id="number" name="number" value="{$config.number|default=''}" placeholder="请输入升级人数" type="text" class="form-control field-text">
</div>
<label for="name" class="control-label">人</label>
</div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate({
rules: {
'type': {
required: true,
},
'name': {
required: true,
},
'value': {
required: true,
},
},
messages: {
'type': {
required: "类型不能为空",
},
'name': {
required: "名称不能为空",
},
'value': {
required: "值不能为空",
},
}
});
</script>
{/block}

View File

@ -0,0 +1,114 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post" enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body">
<div class="form-group">
<label for="goods_id" class="col-sm-2 control-label">体验设备</label>
<div class="col-sm-10 col-md-4">
<select name="goods_id" id="goods_id" class="form-control field-select"
data-placeholder="请选择体验设备">
<option value=""></option>
{foreach name='config.goods_list' id='item'}
<option value="{$item.id}" {if isset($config) &&
$config.goods_id==$item.id}selected{/if}>
{$item.name}
</option>
{/foreach}
</select>
</div>
</div>
<script>
$('#goods_id').select2();
</script>
<div class="form-group">
<label for="day" class="col-sm-2 control-label">体验天数</label>
<div class="col-sm-10 col-md-4">
<input id="day" name="day" value="{$config.day|default=''}" placeholder="请输入体验天数" type="number" class="form-control field-number">
</div>
<label for="name" class="control-label">天</label>
</div>
<div class="form-group">
<label for="is_withdraw" class="col-sm-2 control-label">是否可提现</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="is_withdraw" value="1" {if(!isset($config) ||$config.is_withdraw==1)}checked{/if} type="checkbox" />
<input class="switch field-switch" placeholder="是否可提现" name="is_withdraw" value="{$config.is_withdraw|default=''}" hidden />
</div>
</div>
<script>
$('#is_withdraw').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
<div class="form-group">
<label for="is_first" class="col-sm-2 control-label">是否新用户领取</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="is_first" value="1" {if(!isset($config) ||$config.is_first==1)}checked{/if} type="checkbox" />
<input class="switch field-switch" placeholder="是否新用户领取" name="is_first" value="{$config.is_first|default=''}" hidden />
</div>
</div>
<script>
$('#is_first').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
<div class="form-group">
<label for="is_open" class="col-sm-2 control-label">是否开启</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="is_open" value="1" {if(!isset($config) ||$config.is_open==1)}checked{/if} type="checkbox" />
<input class="switch field-switch" placeholder="是否开启" name="is_open" value="{$config.is_open|default=''}" hidden />
</div>
</div>
<script>
$('#is_open').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate();
</script>
{/block}

View File

@ -0,0 +1,69 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post" enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body" style="height: 550px;">
<div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
<ul class="layui-tab-title">
<li class="layui-this">积分规则</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<div class="form-group">
<div class="col-sm-10">
<script id="integral_rule" name="integral_rule" type="text/plain">{$config.integral_rule|raw|default=''}</script>
</div>
</div>
<script>
UE.delEditor('integral_rule');
var ue = UE.getEditor('integral_rule',{
serverUrl :UEServer,
});
ue.ready(function() {
ue.setHeight(250); //设置高度
});
</script>
</div>
</div>
<div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate({
rules: {
'integral_rule': {
required: true,
},
},
messages: {
'integral_rule': {
required: "请输入积分规则",
},
}
});
</script>
{/block}

View File

@ -0,0 +1,102 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<style>
.layui-form-label {
color: #6a6f6c;
width: 100px;
}
.layui-input-block {
margin-left: 130px;
}
.tips{
color: red;
}
.layui-laydate-content>.layui-laydate-list {
padding-bottom: 0px;
overflow: hidden;
}
.layui-laydate-content>.layui-laydate-list>li{
width: 100%;
}
.merge-box .scrollbox .merge-list {
padding-bottom: 5px;
}
</style>
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post" enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body" style="height: 500px;">
<div class="form-group">
<label for="time" class="col-sm-2 control-label">结算时间</label>
<div class="col-sm-10 col-md-4">
<input id="time" name="time" value="{$config.time|default=''}" placeholder="请输入类型" type="text" class="form-control field-text">
</div>
</div>
<div class="form-group">
<label for="num" class="col-sm-2 control-label">实时收益</label>
<div class="col-sm-10 col-md-4">
<input id="num" name="num" value="{$config.num|default=''}" placeholder="请输入名称" type="text" class="form-control field-text">
</div>
<label for="name" class="control-label">/M</label>
</div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate({
rules: {
'type': {
required: true,
},
'name': {
required: true,
},
'value': {
required: true,
},
},
messages: {
'type': {
required: "类型不能为空",
},
'name': {
required: "名称不能为空",
},
'value': {
required: "值不能为空",
},
}
});
laydate.render({
elem :'#time',
trigger : 'click',
type: 'time',
format: 'HH',
});
</script>
{/block}

View File

@ -0,0 +1,84 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post" enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body" style="height: 500px;">
<div class="form-group">
<label for="APPID" class="col-sm-2 control-label">AppID</label>
<div class="col-sm-10 col-md-4">
<input id="APPID" name="APPID" value="{$config.APPID|default=''}" placeholder="请输入AppID" type="text" class="form-control field-text">
</div>
</div>
<div class="form-group">
<label for="APPSECRET" class="col-sm-2 control-label">AppSecret</label>
<div class="col-sm-10 col-md-4">
<input id="APPSECRET" name="APPSECRET" value="{$config.APPSECRET|default=''}" placeholder="请输入AppSecret" type="text" class="form-control field-text">
</div>
</div>
<div class="form-group">
<label for="img_url" class="col-sm-2 control-label">图片访问地址</label>
<div class="col-sm-10 col-md-4">
<input id="img_url" name="img_url" value="{$config.img_url|default=''}" placeholder="请输入图片访问地址" type="text" class="form-control field-text">
</div>
</div>
<div class="form-group">
<label for="tel" class="col-sm-2 control-label">联系电话</label>
<div class="col-sm-10 col-md-4">
<input id="tel" name="tel" value="{$config.tel|default=''}" placeholder="请输入联系电话" type="text" class="form-control field-text">
</div>
</div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate({
rules: {
'type': {
required: true,
},
'name': {
required: true,
},
'value': {
required: true,
},
},
messages: {
'type': {
required: "类型不能为空",
},
'name': {
required: "名称不能为空",
},
'value': {
required: "值不能为空",
},
}
});
</script>
{/block}

View File

@ -0,0 +1,70 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post" enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body" style="height: 500px;">
<div class="form-group">
<label for="min_withdraw" class="col-sm-2 control-label">最低提现金额</label>
<div class="col-sm-10 col-md-4">
<input id="min_withdraw" name="min_withdraw" value="{$config.min_withdraw|default=''}" placeholder="请输入最低提现金额" type="text" class="form-control field-text">
<span id="min_withdraw-error" class="help-block">会员提现需满足最低提现金额,才能提交提现申请。</span>
</div>
<label for="name" class="control-label">元</label>
</div>
<div class="form-group">
<label for="max_withdraw" class="col-sm-2 control-label">最高提现金额</label>
<div class="col-sm-10 col-md-4">
<input id="max_withdraw" name="max_withdraw" value="{$config.max_withdraw|default=''}" placeholder="请输入最高提现金额" type="text" class="form-control field-text">
<span id="min_withdraw-error" class="help-block">会员提现允许的最高提现金额。</span>
</div>
<label for="name" class="control-label">元</label>
</div>
<div class="form-group">
<label for="poundage_type" class="col-sm-2 control-label">手续费类型</label>
<div class="col-sm-10 col-md-4 layui-form">
<input type="radio" name="poundage_type" class="poundage_type" value="1" title="固定" {if isset($config.poundage_type) && $config.poundage_type=='1'}checked{/if}>
<input type="radio" name="poundage_type" class="poundage_type" value="2" title="百分比" {if isset($config.poundage_type) && $config.poundage_type=='2'}checked{/if}>
</div>
</div>
<div class="form-group">
<label for="poundage" class="col-sm-2 control-label">提现手续费</label>
<div class="col-sm-10 col-md-4">
<input id="poundage" name="poundage" value="{$config.poundage|default=''}" placeholder="请输入提现手续费" type="text" class="form-control field-text">
<span id="min_withdraw-error" class="help-block">会员提现时收取的手续费。</span>
</div>
<label for="name" class="control-label"></label>
</div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate();
layui.use('form', function(){
var form = layui.form;
form.render();
});
</script>
{/block}

View File

@ -0,0 +1,258 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<style type="text/css">
/* 图片展示
----------------------------------------------- */
ul.albums {
display: block;
min-height: 1px;
height: auto;
overflow: hidden;
padding: 5px 0;
margin: 0 15px;
}
ul.albums li {
position: relative;
display: inline-block;
padding: 5px;
border: 1px solid #e5e5e5;
margin: 5px 0 0 20px;
cursor: pointer;
}
ul.albums li a.btn-close {
display: block;
position: absolute;
z-index: 2;
top: -8px;
right: -10px;
width: 20px;
height: 20px;
}
ul.albums li a.btn-fm{width: 100px;
display:none;
height: 100px;
border: 0px;
opacity: 0.5;
background-color: #000;
line-height: 100px;
text-align: center;
color: #fff;
position: absolute;}
ul.albums li:hover a.btn-fm{ display: block; }
ul.albums li a.btn-fm_z{
display:none;
color: #ccc;
border: 0px;
background-color: #000;
position: absolute;
bottom: 5px;
left: 5px;
opacity: 0.6;
width: 40px;
text-align: center;
}
</style>
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post"
enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">名称</label>
<div class="col-sm-10 col-md-4">
<input id="name" name="name" value="{$data.name|default=''}" placeholder="请输入名称"
type="text" class="form-control field-text">
</div>
</div>
<div class="form-group">
<label for="alias" class="col-sm-2 control-label">广告位置</label>
<div class="col-sm-10 col-md-4">
<select name="alias" id="alias" class="form-control field-select"
data-placeholder="请选择广告位置">
<option value=""></option>
{foreach name='banner_list' id='item'}
<option value="{$item.bm}" {if isset($data) &&
$data.alias==$item.bm}selected{/if}>{$item.name}
</option>
{/foreach}
</select>
</div>
</div>
<script>
$('#alias').select2();
</script>
<div class="form-group">
<label for="img" class="col-sm-2 control-label">图片</label>
<ul class="albums" id="albums">
<li id="nophoto" ><img src="{if isset($data.img)}{$data.img}{else}/static/admin/images/nophoto_100x100.png{/if}" style="width: 100px;height: 100px;"></li>
<input type="hidden" name="img" id="img" value="{$data.img|default=''}">
</ul>
</div>
<script type="text/javascript">
layui.use(['upload','laydate','form'], function(){
var form = layui.form;
var upload = layui.upload;
//执行实例
upload.render({
elem: '#nophoto' //绑定元素
,url: "{:url('file/icon')}" //接口url
,data:{type:0,width:200,heigh:200}
,field:'image'
,multiple: true
,done: function(res){
$(".albums img").attr('src',res.data.avatar_logo);
$("#img").val(res.data.avatar_logo);
}
,error: function(){
layer.tips('图片错误', '#btn');
return false;
}
});
});
</script>
<div class="form-group">
<label for="jump_type" class="col-sm-2 control-label">跳转类型</label>
<div class="col-sm-10 col-md-4">
<select name="jump_type" id="jump_type" class="form-control field-select"
data-placeholder="请选择跳转类型" onchange="getTargetList(this.value)">
<option value=""></option>
{foreach name='jump_type' id='item'}
<option value="{$item.id}" {if isset($data) &&
$data.jump_type==$item.id}selected{/if}>{$item.name}
</option>
{/foreach}
</select>
</div>
</div>
<script>
$('#jump_type').select2();
</script>
<div class="form-group">
<label for="jump_target" class="col-sm-2 control-label">跳转目标</label>
<div class="col-sm-10 col-md-4">
<select name="jump_target" id="jump_target" class="form-control field-select">
</select>
</div>
</div>
<script>
$('#jump_target').select2({
placeholder: '请选择跳转目标'
});
</script>
<div class="form-group">
<label for="sort_number" class="col-sm-2 control-label">排序</label>
<div class="col-sm-10 col-md-4">
<input id="sort_number" name="sort_number" value="{$data.sort_number|default='1000'}"
placeholder="请输入排序" type="text" class="form-control field-text">
</div>
</div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
{if !isset($data)}
<div class="btn-group pull-right">
<label class="createContinue">
<input type="checkbox" value="1" id="_create" name="_create"
title="继续添加数据">继续添加</label>
</div>
{/if}
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate({
rules: {
'name': {
required: true,
},
'jump_type': {
required: true,
},
'jump_target': {
required: true,
},
'sort_number': {
required: true,
},
},
messages: {
'name': {
required: "名称不能为空",
},
'jump_type': {
required: "跳转类型不能为空",
},
'jump_target': {
required: "跳转目标不能为空",
},
'sort_number': {
required: "排序不能为空",
},
}
});
function getTargetList(id) {
var html ='';
var $jump_target = $('#jump_target');
id = parseInt(id);
if (id !== 3) {
$.post('{:url("pub/getSlideTargetData")}', {type_id: id}, function (result) {
$.each(result.data,function (index, item) {
html+='<option value="'+item.id+'">'+item.name+'</option>';
});
$jump_target.html(html);
$jump_target.select2();
});
}else{
$jump_target.html(html);
$jump_target.select2({
tags:true,
placeholder:'请输入需要跳转的网址',
});
}
}
</script>
{/block}

View File

@ -0,0 +1,137 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<!--数据列表页面-->
<section class="content">
<!--顶部搜索筛选-->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('index')}" method="GET">
<div class="form-group">
<input value="{$_keywords ? $_keywords : '' ;}"
name="_keywords" id="_keywords" class="form-control input-sm" placeholder="名称">
</div>
<div class="form-group">
<button class="btn btn-sm btn-primary" type="submit"><i class="fa fa-search"></i> 查询
</button>
</div>
<div class="form-group">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<!--数据列表顶部-->
<div class="box-header">
<div>
<a title="添加" data-toggle="tooltip" class="btn btn-primary btn-sm " href="{:url('add')}">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-danger btn-sm AjaxButton" data-toggle="tooltip" title="删除选中数据"
data-confirm-title="删除确认" data-confirm-content="您确定要删除选中的数据吗?" data-id="checked"
data-url="{:url('del')}">
<i class="fa fa-trash"></i> 删除
</a>
<a class="btn btn-success btn-sm ReloadButton" data-toggle="tooltip" title="刷新">
<i class="fa fa-refresh"></i> 刷新
</a>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<th>
<input id="dataCheckAll" type="checkbox" onclick="checkAll(this)" class="checkbox"
placeholder="全选/取消">
</th>
<th>ID</th>
<th>名称</th>
<th>图片</th>
<th>跳转类型</th>
<th>跳转目标</th>
<th>排序</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{foreach name="data" item="item"}
<tr>
<td>
<input type="checkbox" onclick="checkThis(this)" name="data-checkbox"
data-id="{$item.id}" class="checkbox data-list-check" value="{$item.id}"
placeholder="选择/取消">
</td>
<td>{$item.id}</td>
<td>{$item.name}</td>
<td><img class="dataListImg" src="{$item.img}"></td>
<td>{$item.jump_type_text}</td>
<td>{$item.jump_target_text}</td>
<td>{$item.sort_number}</td>
<td>{$item.create_time}</td>
<td class="td-do">
<a href="{:url('edit',['id'=>$item.id])}"
class="btn btn-primary btn-xs" title="修改" data-toggle="tooltip">
<i class="fa fa-pencil"></i>
</a>
<a class="btn btn-danger btn-xs AjaxButton" data-toggle="tooltip" title="删除"
data-id="{$item.id}" data-confirm-title="删除确认"
data-confirm-content='您确定要删除ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('del')}">
<i class="fa fa-trash"></i>
</a>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,17 @@
<!--找不到页面-->
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="error-page">
<h2 class="headline text-yellow"> 404</h2>
<div class="error-content">
<h3><i class="fa fa-warning text-yellow"></i> 哎呀!找不到页面。</h3>
<p>
我们找不到您要查找的页面。
同时,您可以<br/> <br/> <a class="btn btn-success BackButton">返回上一页</a> 或者 <a class="btn btn-primary" href="{:url('index/index')}">去首页</a>
</p>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,17 @@
<!--500错误-->
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="error-page">
<h2 class="headline text-yellow"> 404</h2>
<div class="error-content">
<h3><i class="fa fa-warning text-yellow"></i> 哎呀!页面出问题了。</h3>
<p>
当前页面出现了一点点问题。
同时,您可以<br/> <br/> <a class="btn btn-success BackButton">返回上一页</a> 或者 <a class="btn btn-primary" href="{:url('index/index')}">去首页</a>
</p>
</div>
</div>
</section>
{/block}

View File

@ -0,0 +1,11 @@
<!--空白页面参考模版-->
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<!-- 这里写内容即可 -->
</section>
{/block}

View File

@ -0,0 +1,227 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<style type="text/css">
/* 图片展示
----------------------------------------------- */
ul.albums {
display: block;
min-height: 1px;
height: auto;
overflow: hidden;
padding: 5px 0;
margin: 0 15px;
}
ul.albums li {
position: relative;
display: inline-block;
padding: 5px;
border: 1px solid #e5e5e5;
margin: 5px 0 0 20px;
cursor: pointer;
}
ul.albums li a.btn-close {
display: block;
position: absolute;
z-index: 2;
top: -8px;
right: -10px;
width: 20px;
height: 20px;
}
ul.albums li a.btn-fm{width: 100px;
display:none;
height: 100px;
border: 0px;
opacity: 0.5;
background-color: #000;
line-height: 100px;
text-align: center;
color: #fff;
position: absolute;}
ul.albums li:hover a.btn-fm{ display: block; }
ul.albums li a.btn-fm_z{
display:none;
color: #ccc;
border: 0px;
background-color: #000;
position: absolute;
bottom: 5px;
left: 5px;
opacity: 0.6;
width: 40px;
text-align: center;
}
</style>
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post"
enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body">
<div class="form-group">
<label for="img" class="col-sm-2 control-label">头像</label>
<ul class="albums" id="albums">
<li id="nophoto" ><img src="{if isset($data.avatar)}{$data.avatar}{else}/static/admin/images/nophoto_100x100.png{/if}" style="width: 100px;height: 100px;"></li>
<input type="hidden" name="avatar" id="avatar" value="{$data.avatar|default=''}">
</ul>
</div>
<script type="text/javascript">
layui.use(['upload','laydate','form'], function(){
var form = layui.form;
var upload = layui.upload;
//执行实例
upload.render({
elem: '#nophoto' //绑定元素
,url: "{:url('file/icon')}" //接口url
,data:{type:1,width:200,heigh:200}
,field:'image'
,multiple: true
,done: function(res){
$(".albums img").attr('src',res.data.avatar_logo_thum);
$("#avatar").val(res.data.avatar_logo_thum);
}
,error: function(){
layer.tips('图片错误', '#btn');
return false;
}
});
});
</script>
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-10 col-md-4">
<input id="username" name="username" value="{$data.username|default=''}"
placeholder="请输入用户名" type="text" class="form-control field-text">
</div>
</div>
<div class="form-group layui-form">
<label for="user_level_id" class="col-sm-2 control-label">会员等级</label>
<div class="col-sm-10 col-md-10">
<input type="radio" name="user_level_id" lay-filter="filter" value="1" title="体验会员" {if(!isset($data)
||$data.user_level_id==1)}checked{/if}>
<input type="radio" name="user_level_id" lay-filter="filter" value="2" title="正式会员" {if(!isset($data)
||$data.user_level_id==2)}checked{/if}>
</div>
</div>
<script>
layui.use(['upload','laydate','form'], function(){
var form = layui.form;
form.render();
});
</script>
<div class="form-group">
<label for="mobile" class="col-sm-2 control-label">手机号</label>
<div class="col-sm-10 col-md-4">
<input id="mobile" name="mobile" value="{$data.mobile|default=''}" placeholder="请输入手机号"
type="tel" maxlength="11" class="form-control field-mobile">
</div>
</div>
<div class="form-group">
<label for="nickname" class="col-sm-2 control-label">昵称</label>
<div class="col-sm-10 col-md-4">
<input id="nickname" name="nickname" value="{$data.nickname|default=''}"
placeholder="请输入昵称" type="text" class="form-control field-text">
</div>
</div>
<div class="form-group">
<label for="status" class="col-sm-2 control-label">是否启用</label>
<div class="col-sm-10 col-md-4">
<input class="input-switch" id="status" value="1" {if(!isset($data)
||$data.status==1)}checked{/if} type="checkbox"/>
<input class="switch field-switch" placeholder="是否启用" name="status"
value="{$data.status|default='1'}" hidden/>
</div>
</div>
<script>
$('#status').bootstrapSwitch({
onText: "是",
offText: "否",
onColor: "success",
offColor: "danger",
onSwitchChange: function (event, state) {
$(event.target).closest('.bootstrap-switch').next().val(state ? '1' : '0').change();
}
});
</script>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
{if !isset($data)}
<div class="btn-group pull-right">
<label class="createContinue">
<input type="checkbox" value="1" id="_create" name="_create"
title="继续添加数据">继续添加</label>
</div>
{/if}
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
<div class="btn-group">
<button type="reset" class="btn flat btn-default dataFormReset">
重置
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate({
rules: {
'username': {
required: true,
},
'mobile': {
required: true,
},
'nickname': {
required: true,
},
'status': {
required: true,
},
},
messages: {
'username': {
required: "用户名不能为空",
},
'mobile': {
required: "手机号不能为空",
},
'nickname': {
required: "昵称不能为空",
},
'status': {
required: "是否启用不能为空",
},
}
});
</script>
{/block}

View File

@ -0,0 +1,141 @@
{extend name='public/base' /}
{block name='content'}
{include file='public/content_header' /}
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<!-- 表单头部 -->
<div class="box-header with-border">
<div class="btn-group">
<a class="btn flat btn-sm btn-default BackButton">
<i class="fa fa-arrow-left"></i>
返回
</a>
</div>
</div>
<!-- 表单 -->
<form id="dataForm" class="form-horizontal dataForm" action="" method="post"
enctype="multipart/form-data">
<!-- 表单字段区域 -->
<div class="box-body">
<div class="form-group">
<div class="col-sm-10 col-md-12">
<table id="dataList" class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr class="input-type">
<th>操作</th>
<th>设备产品</th>
<th>数量</th>
<th>到期时间</th>
</tr>
</thead>
<tbody id="dataBody"></tbody>
</table>
</div>
</div>
</div>
<!-- 表单底部 -->
<div class="box-footer">
{:token()}
<div class="col-sm-2">
</div>
<div class="col-sm-10 col-md-4">
{if !isset($data)}
<div class="btn-group pull-right">
<label class="createContinue">
<input type="checkbox" value="1" id="_create" name="_create"
title="继续添加数据">继续分配</label>
</div>
{/if}
<div class="btn-group">
<button type="submit" class="btn flat btn-info dataFormSubmit">
保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<table>
<tbody id="data-template" style="display: none">
<tr>
<td>
<a class="btn btn-xs btn-success" onclick="addNewField(this,2)">追加</a>
<a class="btn btn-xs btn-danger" onclick="delThisField(this,1)">删除</a>
</td>
<td>
<label>
<select name="goods_idFORM_INDEX[]" style="min-width: 380px;width: 420px;" class="form-control field-select select2" data-placeholder="请选择设备商品">
<option value=""></option>
{foreach name='goods_list' id='item'}
<option value="{$item.id}">
{$item.name}
</option>
{/foreach}
</select>
</label>
</td>
<td>
<label>
<input class="form-control field-type" value="" name="numberFORM_INDEX[]" placeholder="请输入数量">
</label>
</td>
<td>
<label>
<input class="form-control field-type" id="end_timeINDEX_ID" value="" name="end_timeFORM_INDEX[]" placeholder="请输入到期时间">
</label>
</td>
</tr>
</tbody>
</table>
</section>
<script>
/** 表单验证 **/
$('#dataForm').validate();
//表单索引
var formIndex =0;
addNewField(null, 1);
//添加新的字段
function addNewField(obj, type) {
formIndex++;
let template = $("#data-template").html().replace(/FORM_INDEX/g, '[' + formIndex + ']').replace(/INDEX_ID/g, formIndex);
if (obj == null) {
$("#dataBody").append(template);
} else {
if (type === 1) {
$(obj).parent().parent().before(template);
} else {
$(obj).parent().parent().after(template);
}
}
laydate.render({
elem: '#end_time'+formIndex
,type: 'datetime'
});
//刷新 dataBody DOM后的操作
dataBodyRefreshed();
}
$(function () {
dataBodyRefreshed();
});
//删除当前字段
function delThisField(obj) {
layer.confirm('您确认删除本行吗?', {title: '删除确认', closeBtn: 1, icon: 3}, function () {
$(obj).parent().parent().remove();
layer.closeAll();
});
}
//列表刷新后的操作
function dataBodyRefreshed() {
$('[data-toggle="tooltip"]').tooltip();
$('#dataBody .select2').select2();
}
</script>
{/block}

View File

@ -0,0 +1,271 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<style type="text/css">
.layui-table-cell {
height: auto;
white-space: normal;
}
.layui-card-header.layuiadmin-card-header-auto {
padding-top: 15px;
padding-bottom: 15px;
height: auto;
}
.layui-form-label{ width:100px; }
</style>
<!--数据列表页面-->
<section class="content">
<!--顶部搜索筛选-->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('index')}" method="GET">
<div class="layui-form layui-card-header layuiadmin-card-header-auto">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">会员信息:</label>
<div class="layui-input-inline" style="width: 200px;">
<select name="keyword_type" id="keyword_type">
<option value="sn" {if isset($keyword_type) && $keyword_type=='sn'}selected{/if}>会员编号</option>
<option value="nickname" {if isset($keyword_type) && $keyword_type=='nickname'}selected{/if}>会员昵称</option>
<option value="mobile" {if isset($keyword_type) && $keyword_type=='mobile'}selected{/if}>会员手机号码</option>
</select>
</div>
<div class="layui-input-inline" style="width: 200px;">
<input type="text" id="keyword" name="keyword" value="{$keyword?$keyword:'';}" placeholder="请输入关键词" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">会员等级:</label>
<div class="layui-input-inline">
<select id="level" name="level" style="height:80px;width: 80px" >
<option value="" selected>全部</option>
<option value="0" {if isset($level) && $level=='0'}selected{/if}>无等级</option>
<option value="1" {if isset($level) && $level=='1'}selected{/if}>体验会员</option>
<option value="2" {if isset($level) && $level=='2'}selected{/if}>正式会员</option>
</select>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">提现积分:</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" name="integral_start" value="{$integral_start?$integral_start:'';}" autocomplete="off">
</div>
<div class="layui-input-inline" style="margin-right: 5px;width: 10px;">
<label class="layui-form-mid">-</label>
</div>
<div class="layui-input-inline">
<input type="text" class="layui-input" name="integral_end" value="{$integral_end?$integral_end:'';}" autocomplete="off">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">注册时间:</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="start_time" name="start_time" value="{$start_time?$start_time:'';}" autocomplete="off">
</div>
<div class="layui-input-inline" style="margin-right: 5px;width: 10px;">
<label class="layui-form-mid">-</label>
</div>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="end_time" name="end_time" value="{$end_time?$end_time:'';}" autocomplete="off">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<button class="btn btn-success btn-sm" type="submit" >查询</button>
</div>
<div class="layui-inline">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<!--数据列表顶部-->
<div class="box-header">
<div>
<a class="btn btn-success btn-sm AjaxButton" data-toggle="tooltip" title="启用选中数据"
data-confirm-title="启用确认" data-confirm-content="您确定要启用选中的数据吗?" data-id="checked"
data-url="{:url('enable')}">
<i class="fa fa-circle"></i> 启用
</a>
<a class="btn btn-warning btn-sm AjaxButton" data-toggle="tooltip" title="禁用选中数据"
data-confirm-title="禁用确认" data-confirm-content="您确定要禁用选中的数据吗?" data-id="checked"
data-url="{:url('disable')}">
<i class="fa fa-circle"></i> 禁用
</a>
</div>
</div>
<div class="box-body table-responsive" style="position: relative; width:100%;">
<table class="layui-table" style="width: auto;">
<thead>
<tr>
<th>
<input id="dataCheckAll" type="checkbox" onclick="checkAll(this)" class="checkbox"
placeholder="全选/取消">
</th>
<th>
<div style="width:380px;text-align:center;">用户信息</div>
</th>
<th>
<div class="layui-table-cell" style="width:100px;text-align:center;">用户等级</div>
</th>
<th>
<div class="layui-table-cell" style="width:100px;text-align:center;">可提现积分</div>
</th>
<th>
<div class="layui-table-cell" style="width:100px;text-align:center;">设备数量</div>
</th>
<th>
<div style="width:380px;text-align:center;">上级推荐人</div>
</th>
<th><div class="layui-table-cell" style="width:120px;text-align:center;">推荐下级人数</div></th>
<th><div class="layui-table-cell" style="width:200px;text-align:center;">注册时间</div></th>
<th>
<div class="layui-table-cell" style="width:200px;text-align:center;">操作</div>
</th>
</tr>
</thead>
<tbody>
{foreach name="data" item="item"}
<tr>
<td>
<input type="checkbox" onclick="checkThis(this)" name="data-checkbox"
data-id="{$item.id}" class="checkbox data-list-check" value="{$item.id}"
placeholder="选择/取消">
</td>
<td class="layui-table-col-special">
<div class="layui-table-cell laytable-cell-1-0-2">
<img src="{$item.avatar}" style="height:80px;width: 80px;margin-right: 10px;" class="image-show">
<div class="layui-input-inline" style="text-align:left;width: 240px;">
<p>用户编号:{$item.sn}</p>
<p>用户昵称:{$item.nickname}</p>
<p>用户手机:{$item.mobile}</p>
</div>
</div>
</td>
<td>
<div class="layui-table-cell" style="width:100px;text-align:center;">{$item.user_level_id_text}</div>
</td>
<td>
<div class="layui-table-cell" style="width:100px;text-align:center;">{$item.integral}</div>
</td>
<td>
<div class="layui-table-cell" style="width:100px;text-align:center;">{$item.sb_num}</div>
</td>
<td>
<div class="layui-table-cell laytable-cell-1-0-2">
{if $item.first_leader_info != '系统'}
<img src="{$item.first_leader_info.avatar}" style="height:80px;width: 80px;margin-right: 10px;">
<div class="layui-input-inline" style="text-align:left;width: 240px;">
<p>用户编号:{$item.first_leader_info.sn}</p>
<p>用户昵称:{$item.first_leader_info.nickname}</p>
<p>用户手机:{$item.first_leader_info.mobile}</p>
</div>
{else}
<div class="layui-table-cell" style="width:380px;text-align:center;">{$item.first_leader_info}</div>
{/if}
</div>
</td>
<td>
<div class="layui-table-cell" style="width:120px;text-align:center;">{$item.fans}</div>
</td>
<td>
<div class="layui-table-cell" style="width:200px;text-align:center;">{$item.create_time}</div>
</td>
<td class="td-do">
<a href="{:url('edit',['id'=>$item.id])}"
class="btn btn-primary btn-xs" title="修改" data-toggle="tooltip">
修改
</a>
<a href="{:url('equipmentadd',['id'=>$item.id])}"
class="btn btn-primary btn-xs" title="分配设备" data-toggle="tooltip">
分配设备
</a>
{if $item.status==1}
<a class="btn btn-warning btn-xs AjaxButton" data-toggle="tooltip" title="禁用"
data-id="{$item.id}" data-confirm-title="禁用确认"
data-confirm-content='您确定要禁用ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('disable')}">
禁用
</a>
{else/}
<a class="btn btn-success btn-xs AjaxButton" data-toggle="tooltip" title="启用"
data-id="{$item.id}" data-confirm-title="启用确认"
data-confirm-content='您确定要启用ID为 <span class="text-red">{$item.id}</span> 的数据吗'
data-url="{:url('enable')}">
启用
</a>
{/if}
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
<script>
layui.use('form', function(){
var form = layui.form;
form.render('select');
});
//日期时间范围
laydate.render({
elem: '#start_time'
,type: 'datetime'
,trigger: 'click'
});
//日期时间范围
laydate.render({
elem: '#end_time'
,type: 'datetime'
,trigger: 'click'
});
</script>
{/block}

View File

@ -0,0 +1,251 @@
{extend name="public/base" /}
{block name='content'}
{include file='public/content_header' /}
<style type="text/css">
.layui-table-cell {
height: auto;
white-space: normal;
}
.layui-card-header.layuiadmin-card-header-auto {
padding-top: 15px;
padding-bottom: 15px;
height: auto;
}
.layui-form-label{ width:100px; }
</style>
<!--数据列表页面-->
<section class="content">
<!--顶部搜索筛选-->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<form class="form-inline searchForm" id="searchForm" action="{:url('lists')}" method="GET">
<div class="layui-form layui-card-header layuiadmin-card-header-auto">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">会员信息:</label>
<div class="layui-input-inline" style="width: 120px;">
<select name="search_key" id="search_key">
<option value="user_sn" {if isset($search_key) && $search_key=='user_sn'}selected{/if}>会员编号</option>
<option value="nickname" {if isset($search_key) && $search_key=='nickname'}selected{/if}>会员昵称</option>
</select>
</div>
<div class="layui-input-inline" style="width: 200px;">
<input type="text" id="keyword" name="keyword" value="{$keyword?$keyword:'';}" placeholder="会员信息" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">提现单号:</label>
<div class="layui-input-inline" style="width: 120px;">
<input type="text" id="withdraw_sn" name="withdraw_sn" value="{$withdraw_sn?$withdraw_sn:'';}" placeholder="提现单号" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">提现方式:</label>
<div class="layui-input-inline">
<select name="type" id="type">
<option value="">全部</option>
{foreach name="type_list" key="item" item="val"}
<option value="{$item}" {if isset($type) && $type==$item}selected{/if}>{$val}</option>
{/foreach}
</select>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">提现状态:</label>
<div class="layui-input-inline">
<select name="status" id="status">
<option value="">全部</option>
{foreach name="status_list" key="item" item="val"}
<option value="{$item}" {if isset($status) && $status==$item}selected{/if}>{$val}</option>
{/foreach}
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">提现时间:</label>
<div class="layui-input-inline">
<input type="text" class="layui-input time" id="start_time" name="start_time" value="{$start_time?$start_time:'';}" autocomplete="off">
</div>
<div class="layui-input-inline" style="margin-right: 5px;width: 10px;">
<label class="layui-form-mid">-</label>
</div>
<div class="layui-input-inline">
<input type="text" class="layui-input time" id="end_time" name="end_time" value="{$end_time?$end_time:'';}" autocomplete="off">
</div>
</div>
<div class="layui-inline">
<div class="layui-inline">
<button class="btn btn-success btn-sm" type="submit" >查询</button>
</div>
<div class="layui-inline">
<button onclick="clearSearchForm()" class="btn btn-sm btn-default" type="button"><i
class="fa fa-eraser"></i> 清空查询
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<!--数据列表顶部-->
<div class="box-header">
<div>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-hover table-bordered datatable" width="100%">
<thead>
<tr>
<tr>
<th>
<div class="layui-table-cell" style="width:200px;text-align:center;">提现单号</div>
</th>
<th>
<div style="width:380px;text-align:center;">用户信息</div>
</th>
<th>
<div class="layui-table-cell" style="width:380px;text-align:center;">收款账户信息</div>
</th>
<th><div class="layui-table-cell" style="width:380px;text-align:center;">提现金额信息</div></th>
<th><div class="layui-table-cell" style="width:100px;text-align:center;">提现状态</div></th>
<th><div class="layui-table-cell" style="width:100px;text-align:center;">审核备注</div></th>
<th><div class="layui-table-cell" style="width:200px;text-align:center;">创建时间</div></th>
<th><div class="layui-table-cell" style="width:200px;text-align:center;">操作</div></th>
</tr>
</tr>
</thead>
<tbody>
{foreach name="data" item="item"}
<tr>
<td>
<div class="layui-table-cell" style="width:200px;text-align:center;">{$item.sn}</div>
</td>
<td class="layui-table-col-special">
<div class="layui-table-cell laytable-cell-1-0-2">
<img src="{$item.avatar}" style="height:80px;width: 80px;margin-right: 10px;" class="image-show">
<div class="layui-input-inline" style="text-align:left;width: 240px;">
<p>用户编号:{$item.user_sn}</p>
<p>用户昵称:{$item.nickname}</p>
<p>用户手机:{$item.mobile}</p>
</div>
</div>
</td>
<td class="layui-table-col-special">
<div class="layui-table-cell laytable-cell-1-0-2">
<div class="layui-input-inline" style="text-align:left;width: 240px;">
<p>提现方式:{$item.type_text}</p>
<p>提现姓名:{$item.real_name}</p>
<p>提现手机:{$item.real_tel}</p>
<p>提现账户:{$item.account}</p>
{if $item.type eq 3}
<p>提现开户:{$item.subbank}</p>
{/if}
</div>
</div>
</td>
<td class="layui-table-col-special">
<div class="layui-table-cell laytable-cell-1-0-2">
<div class="layui-input-inline" style="text-align:left;width: 240px;">
<p>用户提现金额:{$item.money}</p>
<p>手续费:{$item.poundage}</p>
<p>用户到账金额:{$item.left_money}</p>
</div>
</div>
</td>
<td>
<div class="layui-table-cell" style="width:100px;text-align:center;">{$item.status_text}</div>
</td>
<td>
<div class="layui-table-cell" style="width:200px;text-align:center;">{$item.description}</div>
</td>
<td>
<div class="layui-table-cell" style="width:200px;text-align:center;">{$item.create_time}</div>
</td>
<td>
<div class="layui-table-cell" style="width:200px;text-align:center;">
{if $item.status eq 1}
<a href="javascript:;" onclick="status_review({$item.id})" class="btn btn-primary btn-xs" title="审核" data-toggle="tooltip">
审核
</a>
{/if}
</div>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- 数据列表底部 -->
<div class="box-footer">
{$page|raw}
<label class="control-label pull-right" style="margin-right: 10px; font-weight: 100;">
<small>共{$total}条记录</small>&nbsp;
<small>每页显示</small>
&nbsp;
<select class="input-sm" onchange="changePerPage(this)">
<option value="10" {if $admin.per_page==10}selected{/if}>10</option>
<option value="20" {if $admin.per_page==20}selected{/if}>20</option>
<option value="30" {if $admin.per_page==30}selected{/if}>30</option>
<option value="50" {if $admin.per_page==50}selected{/if}>50</option>
<option value="100" {if $admin.per_page==100}selected{/if}>100</option>
</select>
&nbsp;
<small>条记录</small>
</label>
</div>
</div>
</div>
</div>
</section>
<script type="text/javascript">
layui.use(['form','table'], function(){
var form = layui.form;
form.render('select');
});
//日期时间范围
laydate.render({
elem: '#start_time'
,type: 'datetime'
,trigger: 'click'
});
//日期时间范围
laydate.render({
elem: '#end_time'
,type: 'datetime'
,trigger: 'click'
});
function status_review(id) {
layer.open({
type: 2
, title: '提现审核'
, content: '{:url("withdraw/review")}?id=' + id
, area: ['60%', '60%']
});
}
</script>
{/block}

View File

@ -0,0 +1,118 @@
{extend name="layout1" /}
{block name='content'}
<style>
.layui-form-label{ width:120px; }
.layui-table-cell { height: auto; }
.layui-input-block {
line-height: 38px;
}
</style>
<section class="content">
<div class="layui-form" style="margin-left: 50px;margin-top: 15px;margin-bottom:30px;">
<input type="hidden" name="id" id="id" value="{$id}" />
<div class="layui-form-item" style="margin-bottom:0;">
<label class="layui-form-label">提现审核:</label>
<div class="layui-input-block">
<input type="radio" name="review_status" class="review_status" value="1" title="审核通过">
<input type="radio" name="review_status" class="review_status" value="0" title="审核拒绝" checked>
</div>
</div>
<div class="layui-form-item" style="margin-bottom:0;">
<label class="layui-form-label"></label>
<div class=" layui-form-mid layui-word-aux" style="white-space: nowrap">审核拒绝后,提现金额会全部退回佣金账户</div>
</div>
<div class="layui-form-item" style="margin-bottom:0;">
<label class="layui-form-label">审核备注:</label>
<div class="layui-input-block">
<textarea name="description" id="description" placeholder="请输入内容" class="layui-textarea" style="width:380px;height:120px;"></textarea>
</div>
</div>
<div class="layui-form-item" style="margin-bottom:0;">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn layui-btn-sm layuiadmin-btn-withdraw layui-btn-normal" onclick="confirm()">确 认</button>
<button class="layui-btn layui-btn-sm layuiadmin-btn-withdraw layui-btn-primary" onclick="cancel()">返 回</button>
</div>
</div>
</div>
<script>
layui.use(['index','table','like'], function(){
var $ = layui.$
,form = layui.form
,table = layui.table
,like = layui.like;
// 确认
form.on('submit(confirm)', function(data){
console.log(data.field)
if(data.field.review_status == '0') {
// 审核拒绝
like.ajax({
url:'{:url("withdraw/refuse")}',
data:{'id':data.field.id, 'description': data.field.description},
type:"post",
success:function(res)
{
if(res.code == 1)
{
layui.layer.msg(res.msg, {offset: '15px', icon: 1, time: 1000}, function(){
parent.location.reload();
});
}
}
});
}else if(data.field.review_status == '1') {
// 审核通过
like.ajax({
url:'{:url("withdraw/confirm")}',
data:{'id':data.field.id, 'description': data.field.description},
type:"post",
success:function(res)
{
if(res.code == 1)
{
layui.layer.msg(res.msg, {offset: '15px', icon: 1, time: 1000}, function(){
parent.location.reload();
});
}
}
});
}
return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。
});
});
function confirm() {
var review_status=$("input[name='review_status']:checked").val();
var id=$('#id').val();
var description=$('#description').val();
if(review_status=='0'){
$.post('{:url("withdraw/refuse")}', {id: id,description:description}, function (result) {
if(result.code == 1)
{
layui.layer.msg(result.msg, {offset: '15px', icon: 1, time: 1000}, function(){
parent.location.reload();
});
}
});
}else if(review_status == '1') {
$.post('{:url("withdraw/confirm")}', {id: id,description:description}, function (result) {
if(result.code == 1)
{
layui.layer.msg(result.msg, {offset: '15px', icon: 1, time: 1000}, function(){
parent.location.reload();
});
}
});
}
}
function cancel() {
var index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。
}
</script>
</section>
{/block}

182
application/api/common.php Normal file
View File

@ -0,0 +1,182 @@
<?php
use think\response\Json;
use app\common\model\Slide;
use app\common\model\ShopConfig;
use tools\Crypt;
if(!function_exists('success')){
/**
* 操作成功
* @param string $msg
* @param string $data
* @param int $code
* @return Json
*/
function success($data = '', $msg = 'success', $code = 200)
{
return result($msg, $data, $code);
}
}
if(!function_exists('error')){
/**
* 操作失败
* @param string $msg
* @param string $data
* @param int $code
* @return Json
*/
function error($msg = 'fail', $data = '', $code = 500)
{
return result($msg, $data, $code);
}
}
if(!function_exists('result')){
/**
* 返回json结果
* @param string $msg
* @param string $data
* @param int $code
* @return Json
*/
function result($msg = 'fail', $data = '', $code = 500)
{
$header = [];
//处理跨域请求问题
if (config('api.cross_domain.allow')) {
$header = ['Access-Control-Allow-Origin' => '*'];
if (request()->isOptions()) {
$header = config('api.cross_domain.header');
return json('',200,$header);
}
}
return json([
'code' => $code,
'msg' => $msg,
'data' => $data,
], $code, $header);
}
}
if(!function_exists('unauthorized')){
/**
* 未授权
* @param string $msg
* @param string $data
* @param int $code
* @return Json
*/
function unauthorized($msg = 'unauthorized', $data = '', $code = 401)
{
return result($msg, $data, $code);
}
}
if(!function_exists('client_error')){
/**
* 客户端错误
* @param string $msg
* @param string $data
* @param int $code
* @return Json
*/
function client_error($msg = 'client error', $data = '', $code = 400)
{
return result($msg, $data, $code);
}
}
if(!function_exists('server_error')){
/**
* 服务端错误
* @param string $msg
* @param string $data
* @param int $code
* @return Json
*/
function server_error($msg = 'server error', $data = '', $code = 500)
{
return result($msg, $data, $code);
}
}
if(!function_exists('error_404')){
/**
* 资源或接口不存在
* @param string $msg
* @param string $data
* @param int $code
* @return Json
*/
function error_404($msg = '404 not found', $data = '', $code = 404)
{
return result($msg, $data, $code);
}
}
if (!function_exists('get_ad')) {
/**
* 广告列表
* @param string $alias 广告别名
* @param string $num。显示数量
* @return li
*/
function get_ad($alias, $num = '999')
{
$_malladviceModel = new Slide();
$where = 'alias="'.$alias.'"';
$malladvice_list = $_malladviceModel->where($where)->limit($num)->order('sort_number desc')->select();
$ad = array();
$web_url = ShopConfig::get('website', 'img_url');
foreach ($malladvice_list as $key => $row) {
$ad[$key]['id'] = $row['id'];
if($row['jump_type']==1){
$ad[$key]['unionid'] = Crypt::encrypt($row['jump_target']);
}else{
$ad[$key]['url'] = $row['jump_target'];
}
$ad[$key]['type'] = $row['jump_type'];
$ad[$key]['img'] = $web_url . $row['img'];
}
return $ad;
}
}
if(!function_exists('curl_request')){
//参数1:访问的URL,参数2:post数据(不填则为GET),参数3:提交的$cookies,参数4:是否返回$cookies
function curl_request($url,$post='',$cookie='', $returnCookie=0)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
curl_setopt($curl, CURLOPT_REFERER, "http://XXX");
if($post) {
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
}
if($cookie) {
curl_setopt($curl, CURLOPT_COOKIE, $cookie);
}
curl_setopt($curl, CURLOPT_HEADER, $returnCookie);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($curl);
if (curl_errno($curl)) {
return curl_error($curl);
}
curl_close($curl);
if($returnCookie){
list($header, $body) = explode("\r\n\r\n", $data, 2);
preg_match_all("/Set\-Cookie:([^;]*);/", $header, $matches);
$info['cookie'] = substr($matches[1][0], 1);
$info['content'] = $body;
return $info;
}else{
return $data;
}
}
}

View File

@ -0,0 +1,109 @@
<?php
namespace app\api\controller;
use app\common\model\User;
use app\common\model\ShopConfig;
use Exception;
use think\Request;
use think\response\Json;
use tools\Crypt;
use tools\WXBizDataCrypt;
class AuthController extends Controller
{
protected $authExcept = [
'login'
];
/**d
* 登录并发放token
* @param Request $request
* @param User $model
* @param UserValidate $validate
* @return Json|void
*/
public function login(Request $request,User $fumodel)
{
$param = $request->param();
$avatar =$param['avatar']??'';
$nickname =$param['nickname']??'';
$code =$param['code']??'';
$distribution_code =$param['distribution_code']??'';
$encryptedData =$param['encryptedData']??'';
$iv =$param['iv']??'';
if(!$avatar || !$nickname || !$code){
return error('参数不足');
}
$user_info = $this->get_openid($code,$encryptedData,$iv);
if (!$user_info['openid']) {
return error('授权失败');
}
$where['mobile'] = array('EQ',$user_info['tel']);
$userinfo = $fumodel->field('id,avatar,nickname,openid')->where($where)->find();
if($userinfo && !$userinfo['openid']){
$data_login['login_ip']=$request->ip();
$data_login['login_time']=time();
$data_login['openid']=$user_info['openid'];
$fumodel->where('id', $userinfo['id'])->update($data_login);
$token = $this->getToken($userinfo['id']);
$uid=Crypt::encrypt($userinfo['id']);
return success(['token' => $token,'uid'=>$uid], '登录成功');
}else if($userinfo && $userinfo['openid']){
$data_login['login_ip']=$request->ip();
$data_login['login_time']=time();
$fumodel->where('id', $userinfo['id'])->update($data_login);
$token = $this->getToken($userinfo['id']);
$uid=Crypt::encrypt($userinfo['id']);
return success(['token' => $token,'uid'=>$uid], '登录成功');
}
//登录逻辑
// 启动事务
$fumodel->startTrans();
try {
$res['sn'] =create_user_sn();
$res['distribution_code'] =generate_invite_code();
$res['nickname']=$nickname;
$res['username'] = '用户'.$res['sn'];
$res['avatar'] = $avatar;
$res['openid'] = $user_info['openid'];
$res['mobile'] = $user_info['tel'];
$res['create_time'] = time();
$res['login_ip']=$request->ip();
$res['login_time']=time();
$fumodel::create($res);
$uid=$fumodel->getLastInsID();
//分销
if($distribution_code){
$fumodel->code($distribution_code,$uid);
}
$fumodel->commit();
} catch (Exception $e) {
$fumodel->rollback();
return client_error($e->getMessage());
}
$uid=Crypt::encrypt($uid);
$token = $this->getToken($uid);
//返回数据
return success(['token' => $token,'uid'=>$uid], '注册成功');
}
//获取用户临时code 用来去获取openid
public function get_openid($code,$encryptedData,$iv)
{
$APPID =ShopConfig::get('website', 'APPID');
$APPSECRET=ShopConfig::get('website', 'APPSECRET');
$url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . $APPID. '&secret=' . $APPSECRET. '&js_code=' . $code . '&grant_type=authorization_code';
$val = curl_request($url);
$user_info = json_decode($val,true);
$encryptedData=urldecode($encryptedData);
$iv = urldecode($iv);
$pc = new WXBizDataCrypt($APPID,$user_info['session_key']);
$errCode = $pc->decryptData($encryptedData,$iv,$data);
$data1 = json_decode($data, true);
$user_info['tel']=$data1['purePhoneNumber'];
return $user_info;
}
}

View File

@ -0,0 +1,59 @@
<?php
/**
* Api基础控制器
*/
namespace app\api\controller;
use think\Request;
use app\api\traits\ApiAuth;
use app\common\model\ShopConfig;
class Controller
{
use ApiAuth;
//无需验证登录的方法,禁止在此处修改,请在具体业务Controller中修改
protected $authExcept = [];
//当前访问的用户
protected $uid = 0;
//当前页码
protected $page;
//每页数据量
protected $limit;
/**
* @var Request
*/
protected $request;
//当前请求的参数,get/post都在其中
protected $param;
//当前请求数据的ID
protected $id;
public function __construct(Request $request)
{
$this->request = $request;
//jwt验证
$this->jtwInit();
$this->checkToken();
//初始化基本数据
$this->param = $request->param();
$this->page = $this->param['page'] ?? 1;
$this->limit = $this->param['limit'] ?? 10;
$this->id = $this->param['id'] ?? 0;
$this->img_url=ShopConfig::get('website', 'img_url');
//limit防止过大处理
$this->limit = $this->limit <= 100 ? $this->limit : 100;
}
}

View File

@ -0,0 +1,210 @@
<?php
/**
* @author yupoxiong<i@yufuping.com>
* @title 首页
*/
namespace app\api\controller;
use app\common\model\User;
use app\common\model\AccountLog;
use app\common\model\Goods;
use app\common\model\Order;
use app\common\model\MallImage;
use app\common\model\GoodsCategory;
use app\common\model\ShopConfig;
use tools\Crypt;
use think\Request;
class IndexController extends Controller
{
protected $authExcept = [
'home','recommend_goods','goods_info','goods_list','category_list'
];
public function home(Request $request,AccountLog $almodel,Goods $gmodel,Order $omodel,User $umodel)
{
//echo $token = $this->getToken(1).'|';
//echo $uid=Crypt::encrypt(1);
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
//首页轮播
$carousel = get_ad('carousel',6);
//精品推荐
$merchant = get_ad('merchant',6);
//每日收益
$profit_num=ShopConfig::get('shouyi', 'num');
//弹窗配置
$goods_config=array();
$amount_today='0.00';
$amount_yesterday='0.00';
$amount_tuiguang='0.00';
if($uid){
$where[]=array('source_type','in','100,110,120');
$where[]=array('user_id','eq',$uid);
//今日收益
$amount_today = $almodel
->where($where)
->whereTime('create_time', 'today')
->sum('change_amount');
//昨天收益
$amount_yesterday = $almodel
->where($where)
->whereTime('create_time', 'yesterday')
->sum('change_amount');
//推广收益
$amount_tuiguang = $almodel
->where(['source_type' =>100,'user_id'=>$uid])
->sum('change_amount');
$goods_config['is_open']=ShopConfig::get('goods', 'is_open');
$is_first=ShopConfig::get('goods', 'is_first');
$goods_id=ShopConfig::get('goods', 'goods_id');
if($is_first==1){
$user_count=$umodel->where(array('user_level_id'=>1))->count();
if($user_count==0){
$goods_config['is_open']=0;
}
}
$ty_count=$omodel->where(array('order_type'=>2,'goods_id'=>$goods_id))->count();
if($ty_count>0){
$goods_config['is_open']=0;
}
$goods_config['day']=ShopConfig::get('goods', 'day');
if($goods_id){
$goods_info= $gmodel
->alias('g')
->field("mi.thumb_image as img, g.name")
->join('mall_image mi', 'mi.union_id= g.id and is_cover=1 and mi.type=1', 'LEFT')
->where(array('g.id'=>$goods_id))
->find();
$goods_info['img']=$this->img_url.$goods_info['img'];
$goods_config['goods_info'] =$goods_info;
}
}
$data = [
'carousel' =>$carousel,//首页轮播
'merchant' => $merchant,//精品推荐
'profit_num'=>$profit_num,//每日收益
'amount_today'=>$amount_today,//今日收益
'amount_yesterday'=>$amount_yesterday,//昨天收益
'amount_tuiguang'=>$amount_tuiguang,//推广收益
'goods_config'=>$goods_config,//弹窗配置
];
return success($data);
}
//精品推荐
public function recommend_goods(Request $request,Goods $model)
{
$param = $request->param();
$size=$param['size']>0?$param['size']:12;
$page_l=$param['page']>1?$param['page']:1;
$page=$size * ($page_l - 1);
$goods_count = $model
->alias('g')
->where(array('is_recommend'=>1))
->join('mall_image mi', 'mi.union_id= g.id and is_cover=1 and mi.type=1', 'LEFT')
->count();
$totalPages = ceil($goods_count / $size);
$goods_list = $model
->alias('g')
->field("mi.thumb_image as img, g.name,g.attr,g.price,g.order_num,g.id as goods_id")
->join('mall_image mi', 'mi.union_id= g.id and is_cover=1 and mi.type=1', 'LEFT')
->where(array('is_recommend'=>1))
->limit($page, $size)
->order('g.sort_number ASC')
->select();
if (!$goods_list) {
return client_error('暂无数据');
}
foreach ($goods_list as $k1 => $v1) {
$goods_list[$k1]['img'] =$this->img_url.$v1['img'];
$goods_list[$k1]['goods_id'] = Crypt::encrypt($v1['goods_id']);
}
$page=array(
'count'=>$goods_count,
'num'=>$page_l,
'size'=>$size,
'page'=>$totalPages
);
return success(array('list'=>$goods_list,'page'=>$page));
}
//商品列表
public function goods_list(Request $request,Goods $model)
{
$param = $request->param();
$size=$param['size']>0?$param['size']:12;
$page_l=$param['page']>1?$param['page']:1;
$page=$size * ($page_l - 1);
$where[]=array('status','=',1);
$cid = $param['cid']?Crypt::decrypt($param['cid']):'';
if($cid){
$where[]=array('goods_category_id','=',$cid);
}
$goods_count = $model
->alias('g')
->where($where)
->join('mall_image mi', 'mi.union_id= g.id and is_cover=1 and mi.type=1', 'LEFT')
->count();
$totalPages = ceil($goods_count / $size);
$goods_list = $model
->alias('g')
->field("mi.thumb_image as img,g.name,g.attr,g.price,g.order_num,g.id as goods_id")
->join('mall_image mi', 'mi.union_id= g.id and is_cover=1 and mi.type=1', 'LEFT')
->where($where)
->limit($page, $size)
->order('g.sort_number ASC')
->select();
if (!$goods_list) {
return client_error('暂无数据');
}
foreach ($goods_list as $k1 => $v1) {
$goods_list[$k1]['img'] =$this->img_url.$v1['img'];
$goods_list[$k1]['goods_id'] = Crypt::encrypt($v1['goods_id']);
}
$page=array(
'count'=>$goods_count,
'num'=>$page_l,
'size'=>$size,
'page'=>$totalPages
);
return success(array('list'=>$goods_list,'page'=>$page));
}
//商品详情
public function goods_info(Request $request,Goods $model,MallImage $mimodel)
{
$param = $request->param();
$gid = $param['gid']?Crypt::decrypt($param['gid']):'';
if(!$gid){
return client_error('暂无数据');
}
$goods_info=$model->field('name,attr,price,order_num,id as goods_id,detail')->where(array('id'=>$gid,'status'=>1))->find();
$goods_info['goods_id'] = Crypt::encrypt($goods_info['goods_id']);
$img_list=$mimodel->field('thumb_image,ori_image')->where(array('union_id'=>$gid,'type'=>1))->select();
foreach ($img_list as $key => $value) {
$img_list[$key]['thumb_image'] =$this->img_url.$value['thumb_image'];
$img_list[$key]['ori_image'] =$this->img_url.$value['ori_image'];
}
return success(array('info'=>$goods_info,'img_list'=>$img_list));
}
//商品分类
public function category_list(Request $request,GoodsCategory $gcmodel)
{
$category_list=$gcmodel->field('name,id as cid')->select();
foreach ($category_list as $k1 => $v1) {
$category_list[$k1]['cid'] = Crypt::encrypt($v1['cid']);
}
//广告
$ad = get_ad('goods',1);
return success(array('list'=>$category_list,'ad'=>$ad));
}
}

View File

@ -0,0 +1,467 @@
<?php
namespace app\api\controller;
use app\common\model\User;
use app\common\model\Order;
use app\common\model\Goods;
use app\common\validate\WithdrawAccountValidate;
use app\common\model\ShopConfig;
use app\common\model\AccountLog;
use app\common\model\WithdrawApply;
use app\common\model\WithdrawAccount;
use think\Request;
use tools\Crypt;
class UserController extends Controller
{
//我的设备
public function equipment(Request $request,Order $model)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
$size=$param['size']>0?$param['size']:12;
$page_l=$param['page']>1?$param['page']:1;
$page=$size * ($page_l - 1);
$order_count = $model
->alias('o')
->where(array('o.user_id'=>$uid))
->join('mall_image mi', 'mi.union_id= o.goods_id and is_cover=1 and mi.type=1', 'LEFT')
->count();
$totalPages = ceil($order_count / $size);
$order_list = $model
->alias('o')
->field("mi.thumb_image as img, o.goods_name,o.attr,o.order_price,number,o.id as order_id,o.create_time,o.end_time")
->where(array('o.user_id'=>$uid))
->join('mall_image mi', 'mi.union_id= o.goods_id and is_cover=1 and mi.type=1', 'LEFT')
->limit($page, $size)
->order('o.create_time DESC')
->select();
if (!$order_list) {
return client_error('暂无数据');
}
foreach ($order_list as $k1 => $v1) {
$order_list[$k1]['img'] =$this->img_url.$v1['img'];
$order_list[$k1]['order_id'] = Crypt::encrypt($v1['order_id']);
}
$page=array(
'count'=>$order_count,
'num'=>$page_l,
'size'=>$size,
'page'=>$totalPages
);
return success(array('list'=>$order_list,'page'=>$page));
}
//收益统计
public function profit_census(Request $request,AccountLog $almodel,WithdrawApply $wamodel,User $umodel)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
$type = $param['type']??'1';
//积分规则
$integral_rule =ShopConfig::get('policy', 'integral_rule');
//个人收益
if($type==1){
$where[]=array('source_type','in','100,110,120');
$where[]=array('user_id','eq',$uid);
//今日收益
$amount_today = $almodel
->where($where)
->whereTime('create_time', 'today')
->sum('change_amount');
//已提现金额
$amount_ytx = $wamodel->where(array('user_id'=>$uid,'status'=>2))->sum('money');
//可提现金额
$amount_ktx = $umodel->where(array('id'=>$uid))->value('integral');
$data=array(
'amount_today'=>$amount_today,
'amount_ytx'=>$amount_ytx,
'amount_ktx'=>$amount_ktx,
'integral_rule'=>$integral_rule,
);
return success($data);
}
if($type==2){
$where[]=array('user_id','eq',$uid);
//今日收益
$amount_today = $almodel
->where($where)
->where(array('source_type'=>100))
->whereTime('create_time', 'today')
->sum('change_amount');
//累计收益
$amount_sum = $almodel
->where($where)
->where(array('source_type'=>100))
->sum('change_amount');
//推广人数
$user_fans =$umodel->where([['first_leader|second_leader', '=', $uid]])->count();
$data=array(
'amount_today'=>$amount_today,
'amount_sum'=>$amount_sum,
'user_fans'=>$user_fans,
'integral_rule'=>$integral_rule,
);
return success($data);
}
}
//提现记录
public function withdraw(Request $request,WithdrawApply $wamodel)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
$size=$param['size']>0?$param['size']:12;
$page_l=$param['page']>1?$param['page']:1;
$page=$size * ($page_l - 1);
$withdraw_count = $wamodel
->where(array('user_id'=>$uid))
->count();
$totalPages = ceil($withdraw_count / $size);
$withdraw_list = $wamodel
->field("money,create_time,poundage,status")
->where(array('user_id'=>$uid))
->limit($page, $size)
->order('create_time DESC')
->select();
if (!$withdraw_list) {
return client_error('暂无数据');
}
foreach ($withdraw_list as $key => $value) {
$withdraw_list[$key]['status_text'] =$wamodel->STATUS_TYPE[$value['status']];
}
$page=array(
'count'=>$withdraw_count,
'num'=>$page_l,
'size'=>$size,
'page'=>$totalPages
);
return success(array('list'=>$withdraw_list,'page'=>$page));
}
//收益记录
public function account_log(Request $request,AccountLog $almodel)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
$size=$param['size']>0?$param['size']:12;
$page_l=$param['page']>1?$param['page']:1;
$page=$size * ($page_l - 1);
$where[]=array('user_id','=',$uid);
$type = $param['type']??'';
if($type){
$where[]=array('source_type','=',$type);
}
$accountlog_count = $almodel
->alias('al')
->where($where)
->join('user u', 'u.id= al.user_id')
->count();
$totalPages = ceil($accountlog_count / $size);
$accountlog_list = $almodel
->alias('al')
->field("change_amount,al.create_time,source_type,avatar,nickname")
->where($where)
->join('user u', 'u.id= al.user_id')
->limit($page, $size)
->order('create_time DESC')
->select();
if (!$accountlog_list) {
return client_error('暂无数据');
}
foreach ($accountlog_list as $key => $value) {
$accountlog_list[$key]['avatar'] =$this->img_url.$value['avatar'];
$accountlog_list[$key]['source_type_text'] =$almodel->SOURCE_TYPE[$value['source_type']];
}
$amount_sum = $almodel
->where($where)
->sum('change_amount');
$page=array(
'count'=>$accountlog_count,
'num'=>$page_l,
'size'=>$size,
'page'=>$totalPages
);
return success(array('list'=>$accountlog_list,'page'=>$page,'amount_sum'=>$amount_sum));
}
//邀请明细
public function invitation_user(Request $request,User $umodel)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
$size=$param['size']>0?$param['size']:12;
$page_l=$param['page']>1?$param['page']:1;
$page=$size * ($page_l - 1);
$user_count = $umodel
->where([['first_leader|second_leader', '=', $uid]])
->count();
$totalPages = ceil($user_count / $size);
$user_list = $umodel
->field("create_time,avatar,nickname")
->where([['first_leader|second_leader', '=', $uid]])
->limit($page, $size)
->order('create_time DESC')
->select();
if (!$user_list) {
return client_error('暂无数据');
}
foreach ($user_list as $key => $value) {
$user_list[$key]['avatar'] =$this->img_url.$value['avatar'];
}
$page=array(
'count'=>$user_count,
'num'=>$page_l,
'size'=>$size,
'page'=>$totalPages
);
//推广规则
$extension_rule =ShopConfig::get('policy', 'extension_rule');
return success(array('list'=>$user_list,'page'=>$page,'extension_rule'=>$extension_rule));
}
//用户中心
public function userhome(Request $request,User $umodel,Order $omodel)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
$user_info=$umodel->field('avatar,nickname,user_level_id as level,integral,mobile')->where(array('id'=>$uid))->find();
if($user_info['level']==2){
$time=time();
$order_count=$omodel->where('end_time>='.$time.' and user_id='.$uid)->count();
if($order_count==0){
$user_info['level']=1;
}
}
$user_info['avatar'] =$this->img_url.$user_info['avatar'];
//联系电话
$tel =ShopConfig::get('website', 'tel');
$data=array(
'user_info'=>$user_info,
'tel'=>$tel
);
return success($data);
}
//提现账户列表
public function account_list(Request $request,WithdrawAccount $wamodel)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
$account_list=$wamodel->field('real_name,real_tel,account,subbank,type,id')->where(array('user_id'=>$uid))->select();
foreach ($account_list as $key => $value) {
$account_list[$key]['id'] = Crypt::encrypt($value['id']);
}
return success($account_list);
}
//添加提现账户
public function account_add(Request $request,WithdrawAccount $wamodel, WithdrawAccountValidate $validate)
{
$param = $request->param();
$param['user_id'] = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$param['user_id']){
return unauthorized('请先授权');
}
$validate_result = $validate->scene('add')->check($param);
if (!$validate_result) {
return client_error($validate->getError());
}
// 启动事务
$wamodel->startTrans();
try{
$wamodel::create($param);
// 提交事务
$wamodel->commit();
}catch(\Exception $e){
// 回滚事务
$wamodel->rollback();
return client_error($e->getMessage());
}
return success('','添加成功');
}
//删除提现账户
public function account_dal(Request $request,WithdrawAccount $wamodel)
{
$param = $request->param();
$param['user_id'] = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$param['user_id']){
return unauthorized('请先授权');
}
$param['id'] = $param['id']?Crypt::decrypt($param['id']):'';
if (!$param['id']) {
return client_error('账户不存在');
}
$result = $wamodel->whereIn('id', $param['id'])->delete();
return $result ? success('','删除成功') : client_error('删除失败');
}
//提现操作
public function wthdrawal(Request $request,WithdrawAccount $wamodel,WithdrawApply $waymodel,AccountLog $almodel,User $umodel)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
//提现积分
$integral = $param['integral']??'0';
//提现账户
$account_id = $param['account_id']?Crypt::decrypt($param['account_id']):'';
if(!$account_id){
return client_error('请选择提现账户');
}
$account_info=$wamodel->where(array('id'=>$account_id))->find();
if(!$account_info){
return client_error('请选择提现账户');
}
$umodel_info=$umodel->field('integral')->where(array('id'=>$uid))->find();
if($umodel_info['integral']<$integral){
return client_error('积分不足,无法提现');
}
$min_withdraw =ShopConfig::get('withdraw', 'min_withdraw');//最低提现
$max_withdraw =ShopConfig::get('withdraw', 'max_withdraw');//最高提现积分
$poundage_type =ShopConfig::get('withdraw', 'poundage_type');//手续费类型 1固定 2比例
$poundage =ShopConfig::get('withdraw', 'poundage');//手续费
if($integral<$min_withdraw){
return client_error('最少提现积分数'.$min_withdraw.',无法提现');
}
if($integral>$max_withdraw){
return client_error('最多提现积分数'.$max_withdraw.',无法提现');
}
if($poundage_type==2){
$poundage=$integral*($poundage/100);
}
// 启动事务
$waymodel->startTrans();
try{
$data = [
'sn' => createSn('withdraw_apply', 'sn'),
'user_id' => $uid,
'type' => $account_info['type'],
'account' => $account_info['account'] ?? '',
'real_name' => $account_info['real_name'] ?? '',
'real_tel' => $account_info['real_tel'] ?? '',
'money' => $integral,
'left_money' => $integral - $poundage,
'money_qr_code' => '',
'subbank' => $account_info['subbank'] ?? '',
'poundage' => $poundage,
'status' => 1, // 待提现
'create_time' => time(),
];
$withdraw_id = $waymodel->insertGetId($data);
//提交申请后,扣减用户的积分
$user = User::get($uid);
$user->integral = ['dec', $integral];
$user->save();
//增加佣金变动记录
$almodel->AccountRecord(
$uid,
$integral,
2,
140,
'',
$withdraw_id,
$data['sn']
);
// 提交事务
$waymodel->commit();
}catch(\Exception $e){
// 回滚事务
$waymodel->rollback();
return client_error($e->getMessage());
}
return success('','提交提现申请成功,等待审核打款');
}
//领取体验设备
public function experience(Request $request,Order $omodel,User $umodel)
{
$param = $request->param();
$uid = $param['uid']?Crypt::decrypt($param['uid']):'';
if(!$uid){
return unauthorized('请先授权');
}
$goods_id=ShopConfig::get('goods', 'goods_id');
if(!$goods_id){
return client_error('体验设备信息不存在');
}
$is_open=ShopConfig::get('goods', 'is_open');
if($is_open==0){
return client_error('体验设备已关闭,无法领取');
}
$ty_count=$omodel->where(array('order_type'=>2,'goods_id'=>$goods_id))->count();
if($ty_count>0){
return client_error('您已领取该体验设备,无法重复领取');
}
$is_first=ShopConfig::get('goods', 'is_first');
if($is_first==1){
$user_count=$umodel->where(array('user_level_id'=>1))->count();
if($user_count==0){
return client_error('您不是新用户,无法领取');
}
}
$day=ShopConfig::get('goods', 'day');
$field_data = array();
$goods_info=Goods::where(array('id'=>$goods_id))->find()->toArray();
$field_data[] = [
'order_no'=>get_order_sn(),
'goods_id' => $goods_id,
'number' => 1,
'end_time' => time()+$day*60*60*24,
'user_id' => $uid,
'goods_name' => $goods_info['name'],
'attr' => $goods_info['attr'],
'order_price' =>'0.00',
'create_time'=>time(),
'order_type'=>2,
];
if(count($field_data)==0){
return client_error('体验设备信息不存在');
}
// 启动事务
$omodel->startTrans();
try{
$omodel->insertAll($field_data);
// 提交事务
$omodel->commit();
}catch(\Exception $e){
// 回滚事务
$omodel->rollback();
return client_error($e->getMessage());
}
return success('','领取成功');
}
}

View File

@ -0,0 +1,182 @@
<?php
/**
* Api身份验证
*/
namespace app\api\traits;
use Exception;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser as TokenParser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key;
use think\exception\HttpResponseException;
trait ApiAuth
{
protected $config = [
//token在header中的name
'name' => 'token',
//加密使用的secret
'secret' => '552ac90778a976c72f7f673db174df30',
//颁发者
'iss' => 'iss',
//使用者
'aud' => 'aud',
//过期时间,以秒为单位,默认2小时
'ttl' => 30*60*60*24,
//刷新时间,以秒为单位,默认14天,以
'refresh_ttl' => 1209600,
//是否自动刷新,开启后可自动刷新token,附在header中返回,name为`Authorization`,字段为`Bearer `+$token
'auto_refresh' => true,
//黑名单宽限期,以秒为单位,首次token刷新之后在此时间内原token可以继续访问
'blacklist_grace_period' => 60
];
protected $token;
public function jtwInit()
{
$config = config('jwt.');
if ($config) {
$this->config = $config;
}
}
/**
* 检查token
*/
public function checkToken()
{
$config = $this->config;
if (!in_array($this->request->action(true), $this->authExcept)) {
$token = $this->request->header($config['name']);
//缺少token
if (empty($token)) {
throw new HttpResponseException(error('缺少token'));
}
$this->token = $token;
$token_verify = true;
$signer = new Sha256();
try {
$jwt = (new TokenParser())->parse((string)$token);
//验证成功后给当前uid赋值
if (true === $jwt->verify($signer, $config['secret'])) {
$this->uid = $jwt->getClaim('uid');
$exp = $jwt->isExpired();
//token已过期
if ($exp) {
$token_verify = false;
$token_verify_msg = 'token已过期';
//如果为自动刷新
if ($config['auto_refresh']) {
$token = $this->refreshToken();
$token_verify = $token;
}
}
} else {
//token错误
$token_verify = false;
$token_verify_msg = 'token错误';
}
} catch (Exception $e) {
//token验证过程出错
$token_verify = false;
$token_verify_msg = $e->getMessage();
}
//统一处理token相关错误,返回401
if (!$token_verify) {
throw new HttpResponseException(unauthorized('token验证错误,错误信息:'.$token_verify_msg));
}
}
}
/**
* 获取token
* @param $uid int 用户ID
* @param array $data 更多数据
* @return string
* @throws Exception
*/
public function getToken($uid, $data = [])
{
$config = $this->config;
//发放token
$signer = new Sha256();
$time = time();
$jti = md5($time . $uid . random_int(9999, 999999));
$jwt = (new Builder())->issuedBy($config['iss'])//颁发者(iss claim)
->permittedFor($config['aud'])//使用者(aud claim)
->identifiedBy($jti)//JWT ID (jti claim)
->issuedAt($time)//签发时间(iat claim)
->canOnlyBeUsedAfter($time)//可使用时间(nbf claim)
->expiresAt($time + $config['ttl'])//过期时间(exp claim)
->withClaim('uid', $uid); //用户ID
if (count($data) > 0) {
foreach ($data as $key => $value) {
$jwt = $jwt->withClaim($key, $value);
}
}
$token = $jwt->getToken($signer, new Key($config['secret']));
return (string)$token;
}
/**
* 刷新token
* @param $data
* @return string
*/
public function refreshToken()
{
$result = false;
$claim_protect = [
'iss', 'aud', 'jti', 'iat', 'exp', 'nbf', 'uid'
];
$time = time();
$jwt = (new TokenParser())->parse((string)$this->token);
$jti = $jwt->getClaim('jti');
$nbf_time = $jwt->getClaim('nbf');
$refresh_time = $nbf_time + $this->config['refresh_ttl'];
if ($time >= $nbf_time && $time <= $refresh_time) {
$blacklist_time = cache('token_blacklist_' . $jti);
if ($blacklist_time) {
$grace_period = $blacklist_time + $this->config['blacklist_grace_period'];
if ($time < $grace_period) {
$result = true;
}
} else {
//颁发新的token
//将过期的token存到缓存中
$claims = $jwt->getClaims();
$data = [];
foreach ($claims as $key => $value) {
$name = $value->getName();
if (!in_array($name, $claim_protect)) {
$data[$name] = $value->getValue();
}
}
$token = $this->getToken($this->uid, $data);
cache('token_blacklist_' . $jti, $time, $refresh_time - $time + 1);
header('Authorization:Bearer ' . $token);
$result = true;
}
}
return $result;
}
}

14
application/command.php Normal file
View File

@ -0,0 +1,14 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [
];

168
application/common.php Normal file
View File

@ -0,0 +1,168 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Env;
use app\common\model\Order;
use think\db;
// 应用公共文件
if (!function_exists('get_middle_str')) {
/**
* 获取指定字符串中间内容
* @param string $str 原字符串
* @param string $leftStr 左侧
* @param string $rightStr
* @return bool|string
*/
function get_middle_str($str, $leftStr, $rightStr)
{
$left = strpos($str, $leftStr);
$right = strpos($str, $rightStr, $left);
if ($left < 0 || $right < $left) {
return '';
}
return substr($str, $left + strlen($leftStr), $right - $left - strlen($leftStr));
}
}
if (!function_exists('format_size')) {
/**
* 格式化文件大小单位
* @param $size
* @param string $delimiter
* @return string
*/
function format_size($size, $delimiter = '')
{
$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
for ($i = 0; $size >= 1024 && $i < 5; $i++) {
$size /= 1024;
}
return round($size, 2) . $delimiter . $units[$i];
}
}
if (!function_exists('thumbnail_img')) {
/**
* 生成缩略图
* @param string $status 上传后图片信息
* @param string $width 宽
* @param string $heigh 高
*/
function thumbnail_img($status, $width, $heigh, $folder_name = '')
{
$img = Env::get('root_path') . 'public/uploads/attachment/' . $status->getSaveName();
$image = \think\Image::open($img);
$slt = substr($img, 0, strlen($img) - 4);
$image->thumb($width, $heigh, \think\Image::THUMB_CENTER)->save($slt . '_' . $width . '_' . $heigh . '.' . $status->getExtension());
$img_url = $status->getSaveName();
$img_slt = '/uploads/' . $folder_name . '/' . substr($img_url, 0, strlen($img_url) - 4) . '_' . $width . '_' . $heigh . '.' . $status->getExtension();
return $img_slt;
}
}
if (!function_exists('get_order_sn')) {
/**
* 获取得到新订单编号
*/
function get_order_sn()
{
mt_srand((float) microtime() * 1000000);
$order_sn = 'O' . date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
$where = 'order_no="' . $order_sn . '"';
//开始编辑区域
$_OrderModel = new Order();
$count = $_OrderModel->where($where)->count();
//结束编辑区域
if ($count == 0) {
/* 否则就使用这个订单号 */
return $order_sn;
}
return get_order_sn();
}
}
/**
* Desc: 用时间生成订单编号
* @param $table
* @param $field
* @param string $prefix
* @param int $rand_suffix_length
* @param array $pool
* @return string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
function createSn($table, $field, $prefix = '', $rand_suffix_length = 4, $pool = [])
{
$suffix = '';
for ($i = 0; $i < $rand_suffix_length; $i++) {
if (empty($pool)) {
$suffix .= rand(0, 9);
} else {
$suffix .= $pool[array_rand($pool)];
}
}
$sn = $prefix . date('YmdHis') . $suffix;
if (Db::name($table)->where($field, $sn)->find()) {
return createSn($table, $field, $prefix, $rand_suffix_length, $pool);
}
return $sn;
}
/**
* 生成会员码
* @return 会员码
*/
function create_user_sn($prefix = '', $length = 8)
{
$rand_str = '';
for ($i = 0; $i < $length; $i++) {
$rand_str .= mt_rand(0, 9);
}
$sn = $prefix . $rand_str;
if (Db::name('user')->where(['sn' => $sn])->find()) {
return create_user_sn($prefix, $length);
}
return $sn;
}
//生成用户邀请码
function generate_invite_code()
{
$letter_all = range('A', 'Z');
shuffle($letter_all);
//排除I、O字母
$letter_array = array_diff($letter_all, ['I', 'O', 'D']);
//排除1、0
$num_array = range('2', '9');
shuffle($num_array);
$pattern = array_merge($num_array, $letter_array, $num_array);
shuffle($pattern);
$pattern = array_values($pattern);
$code = '';
for ($i = 0; $i < 6; $i++) {
$code .= $pattern[mt_rand(0, count($pattern) - 1)];
}
$code = strtoupper($code);
$check = Db::name('user')->where('distribution_code', $code)->find();
if ($check) {
return generate_invite_code();
}
return $code;
}

Some files were not shown because too many files have changed in this diff Show More