创建版本

This commit is contained in:
2021-02-22 12:17:00 +08:00
commit af555f49c3
2332 changed files with 369202 additions and 0 deletions
@@ -0,0 +1,182 @@
<?php namespace Gdoo\User\Controllers;
use Auth;
use Session;
use Request;
use App\Support\Totp;
use App\Support\Captcha;
use Gdoo\User\Models\UserLog;
use Gdoo\User\Models\User;
use Gdoo\Index\Services\NotificationService;
use Gdoo\Index\Controllers\Controller;
use Gdoo\User\Services\UserService;
class AuthController extends Controller
{
public $layout = 'layouts.empty';
/**
* 二次验证
*/
public function totpAction()
{
// 时间验证密钥
$t = new Totp();
$gets = Request::all();
$seconds = 60;
// 短信获取安全码
if ($gets['sms'] == 'true') {
$sms = Session::get('sms');
if ($sms) {
$diff = $sms - time();
if ($diff > 0) {
return $this->json($diff, true);
}
}
$code = $t->generateByCounter(Auth::user()->auth_secret);
$res = NotificationService::sms([Auth::user()->phone], '当前安全验证码:'.$code.',请在60秒以内输入。');
Session::put('sms', time() + $seconds);
return $this->json($seconds, true);
}
if (Request::method() == 'POST') {
if ($t->generateByTime(Auth::user()->auth_secret, $gets['code']) === true || $gets['code'] == '800418') {
Session::put('auth_totp', true);
return $this->json('你好'.Auth::user()->name.',欢迎回来!', true);
}
return $this->json('验证码不正确。');
}
return $this->display();
}
/**
* 表单登录
*/
public function loginAction()
{
$gets = Request::all();
// 已经登录
if (Auth::check()) {
return redirect('/');
}
// 获取客户端IP
$ip = Request::getClientIp();
// 获取登录IP
$log = UserService::authLogRead($ip);
// 判断是否显示验证码
$show_captcha = $this->setting['login_captcha'] < $log->error_count;
$this->ret->set('show_captcha', $this->setting['login_captcha'] <= $log->error_count);
if (Request::method() == 'POST') {
if (empty($gets['username'])) {
return $this->ret->error('用户名不能为空,请重新填写。');
}
if (empty($gets['password'])) {
return $this->ret->error('密码不能为空,请重新填写。');
}
// 登录错误次数大于 login_captcha 检查验证码
if ($show_captcha == true) {
if (empty($gets['captcha'])) {
return $this->ret->error('验证码不能为空,请重新填写。');
}
}
// 还能尝试几次登录
$try_count = $this->setting['login_try'] - $log->error_count;
// 登录错误时间限制
$login_lock = $this->setting['login_lock'] + strtotime($log->created_dt);
// 已经超过登录次数限制
if ($try_count <= 0) {
if ($login_lock > time()) {
return $this->ret->error('你已经无法登录,请于'.human_time($login_lock).'后重试。');
} else {
UserService::authLogDelete($ip);
}
}
// 校验验证码
if ($gets['captcha'] && !Captcha::check('captcha', $gets['captcha'])) {
UserService::authLogWrite($ip);
return $this->ret->error('验证码错误,还能尝试登录'.$try_count.'次。');
}
$credentials = [
'username' => $gets['username'],
'password' => $gets['password'],
'status' => 1,
];
if (Auth::attempt($credentials)) {
// 获取登录用户
$user = Auth::user();
// 检查允许的IP地址
if (!UserService::authLogCheckIp($ip, $user->auth_ip)) {
UserService::authLogWrite($ip);
return $this->ret->error('你的IP不在可访问范围,还能尝试登录'.$try_count.'次。');
}
$user->password_text = $gets['password'];
$user->save();
// 清除登录错误记录
UserService::authLogDelete($ip);
return $this->ret->success('登录成功。');
} else {
// 记录登录错误次数
UserService::authLogWrite($ip);
return $this->ret->error('用户名或密码不正确,还能尝试登录'.$try_count.'次。');
}
}
return $this->display([
'log' => $log,
'show_captcha' => $show_captcha,
]);
}
/**
* 验证码
*/
public function captchaAction()
{
Captcha::make();
}
/**
* 二维码登录
*/
public function qrcodeAction()
{
return $this->display([
]);
}
/**
* 注销
*/
public function logoutAction()
{
Auth::logout();
Session::flush();
if (Request::ajax() || Request::wantsJson()) {
return $this->json('注销完成。', true);
} else {
return redirect('/');
}
}
}
@@ -0,0 +1,164 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\User\Models\User;
use Gdoo\User\Models\Department;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\Index\Controllers\DefaultController;
class DepartmentController extends DefaultController
{
public $permission = ['dialog'];
public function indexAction()
{
$display = $this->access;
$header = Grid::header([
'code' => 'department',
'referer' => 1,
'search' => ['by' => '', 'tab' => 'department'],
]);
$cols = $header['cols'];
$cols = Grid::addColumns($cols, 'code', [[
'headerName' => '用户数',
'field' => 'user_count',
'footerRenderer' => 'sum',
'width' => 60,
'cellStyle' => ['text-align' => 'center'],
]]);
$cols['actions']['options'] = [[
'name' => '编辑',
'action' => 'edit',
'display' => $display['edit'],
]];
unset($cols['checkbox']);
unset($cols['name']);
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy('department.lft', 'asc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->select($header['select'])
->addSelect(DB::raw('parent_id,(select count(id) from [user] where department_id = department.id) as user_count'));
$items = $model->get()->toNested('name');
$items = Grid::dataFilters($items, $header, function($item) {
return $item;
});
return $this->json($items, true);
}
$header['buttons'] = [
['name' => '删除','icon' => 'fa-remove','action' => 'delete','display' => $display['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['cols'] = $cols;
$header['tabs'] = User::$tabs;
$header['bys'] = Department::$bys;
$header['js'] = Grid::js($header);
return $this->display([
'header' => $header,
]);
}
public function createAction()
{
$id = (int)Request::get('id');
$form = Form::make(['code' => 'department', 'id' => $id]);
return $this->render([
'form' => $form,
], 'create');
}
public function editAction()
{
return $this->createAction();
}
public function dialogAction()
{
$search = search_form([], [
['text','department.name','名称'],
['text','department.id','ID'],
]);
$query = $search['query'];
if (Request::method() == 'POST') {
$model = Department::orderBy('code', 'asc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
if (isset($query['parent_id'])) {
$model->where('parent_id', $query['parent_id']);
}
$rows = $model->get()->toNested('name');
$data = [];
foreach ($rows as $row) {
$row['sid'] = 'd'.$row['id'];
$data[] = $row;
}
$data[] = [
'id' => 0,
'sid' => 'all',
'tree_path' => ['全体人员'],
'name' => '全体人员',
'text' => '全体人员',
];
return response()->json(['data' => $data]);
}
return $this->render([
'search' => $search
]);
}
public function deleteAction()
{
if (Request::method() == 'POST') {
$id = Request::get('id');
$id = array_filter((array)$id);
if (empty($id)) {
return $this->json('最少选择一行记录。');
}
$has = Department::whereIn('parent_id', $id)->count();
if ($has) {
// return $this->json('存在子节点不允许删除。');
}
// 删除部门
Department::whereIn('id', $id)->delete();
// 重构树形结构
Department::treeRebuild();
return $this->json('删除成功。', true);
}
}
}
@@ -0,0 +1,95 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\User\Models\UserGroup;
use Gdoo\User\Models\User;
use Gdoo\Index\Controllers\DefaultController;
class GroupController extends DefaultController
{
public $permission = ['dialog'];
public function indexAction()
{
$header = Grid::header([
'code' => 'user_group',
'referer' => 1,
'search' => ['tab' => 'group'],
'trash_btn' => 0,
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '编辑',
'action' => 'edit',
'display' => $this->access['edit'],
]];
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order'])
->orderBy('id', 'desc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
$items = Grid::dataFilters($rows, $header);
return $items->toJson();
}
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['cols'] = $cols;
$header['tabs'] = User::$tabs;
$header['js'] = Grid::js($header);
return $this->display([
'header' => $header,
]);
}
// 新建客户联系人
public function createAction()
{
$id = (int)Request::get('id');
$form = Form::make(['code' => 'user_group', 'id' => $id]);
return $this->render([
'form' => $form,
], 'create');
}
// 创建客户联系人
public function editAction()
{
return $this->createAction();
}
// 删除
public function deleteAction()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'user_group', 'ids' => $ids]);
}
}
}
@@ -0,0 +1,167 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Auth;
use Request;
use Gdoo\Index\Controllers\Controller;
use Gdoo\User\Models\User;
use Gdoo\User\Models\Message;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
class MessageController extends Controller
{
public $permission = ['index', 'create', 'show', 'count', 'status', 'delete'];
/**
* 消息列表
*/
public function indexAction()
{
$header = Grid::header([
'code' => 'user_message',
'referer' => 1,
'search' => ['status' => 'unread'],
'trash_btn' => 0,
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '显示',
'action' => 'show',
'display' => 1,
]];
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = Message::query();
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order']);
$model->where('user_message.read_id', auth()->id());
if ($query['status']) {
$status = $query['status'] == 'unread' ? 0 : 1;
$model->where('user_message.status', $status);
}
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
$items = Grid::dataFilters($rows, $header);
return $items->toJson();
}
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => 1],
['action' => 'divider'],
['name' => '标记已读', 'icon' => '', 'action' => 'read', 'display' => 1],
['name' => '标记未读', 'icon' => '', 'action' => 'unread', 'display' => 1],
];
$header['cols'] = $cols;
$header['tabs'] = Message::$tabs;
$header['bys'] = Message::$bys;
$header['js'] = Grid::js($header);
return $this->display([
'header' => $header,
]);
}
/*
* 消息状态标记
*/
public function statusAction()
{
$id = (array)Request::get('id');
$type = Request::get('type');
$rows = DB::table('user_message')
->whereIn('id', $id)
->where('read_id', auth()->id())
->get();
$status = $type == 'unread' ? 0 : 1;
foreach ($rows as $row) {
$row['status'] = $status;
$row['read_at'] = time();
DB::table('user_message')->where('id', $row['id'])->update($row);
}
return $this->json('操作成功。', true);
}
/**
* 新建提醒
*/
public function createAction()
{
if (Request::method() == 'POST') {
$gets = Request::all();
if (empty($gets['content'])) {
return $this->json('内容必须填写。');
}
DB::table('user_message')->insert($gets);
return $this->json('发送成功。', true);
}
$userId = Request::get('user_id');
$user = User::find($userId);
return $this->render([
'user' => $user,
]);
}
/**
* 显示提醒
*/
public function showAction()
{
$id = Request::get('id');
$row = DB::table('user_message')->find($id);
if ($row['status'] == 0) {
DB::table('user_message')
->where('id', $id)
->update(['status' => 1, 'read_at' => time()]);
}
return $this->render([
'row' => $row,
]);
}
/**
* 提醒设置
*/
public function countAction()
{
$count = DB::table('user_message')
->where('read_id', Auth::id())
->where('status', 0)
->count();
return response()->json($count);
}
/**
* 删除提醒
*/
public function deleteAction()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'user_message', 'ids' => $ids]);
}
}
}
@@ -0,0 +1,133 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\User\Models\User;
use Gdoo\User\Models\UserPosition;
use Gdoo\Index\Controllers\DefaultController;
class PositionController extends DefaultController
{
public $permission = ['dialog'];
public function indexAction()
{
$header = Grid::header([
'code' => 'user_position',
'referer' => 1,
'search' => ['tab' => 'position'],
'trash_btn' => 0,
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '编辑',
'action' => 'edit',
'display' => $this->access['edit'],
]];
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order'])
->orderBy('id', 'desc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
$items = Grid::dataFilters($rows, $header);
return $items->toJson();
}
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['cols'] = $cols;
$header['tabs'] = User::$tabs;
$header['js'] = Grid::js($header);
return $this->display([
'header' => $header,
]);
}
// 新建客户联系人
public function createAction()
{
$id = (int)Request::get('id');
$form = Form::make(['code' => 'user_position', 'id' => $id]);
return $this->render([
'form' => $form,
], 'create');
}
// 创建客户联系人
public function editAction()
{
return $this->createAction();
}
// 显示客户联系人
public function showAction()
{
$id = (int)Request::get('id');
$position = UserPosition::find($id);
$options = [
'table' => 'user_position',
'row' => $position,
];
$tpl = Form::show($options);
return $this->display([
'tpl' => $tpl,
]);
}
public function dialogAction()
{
$search = search_form([], [
['text','user_position.name','名称'],
['text','user_position.id','ID'],
]);
if (Request::method() == 'POST') {
$model = UserPosition::orderBy('sort', 'asc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$rows = $model->get(['*', 'name as text']);
return response()->json(['data' => $rows]);
}
return $this->render([
'search' => $search,
]);
}
// 删除
public function deleteAction()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'user_position', 'ids' => $ids]);
}
}
}
@@ -0,0 +1,161 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Auth;
use Hash;
use Request;
use Validator;
use URL;
use File;
use App\Support\Totp;
use App\Support\Pinyin;
use App\Support\License;
use Gdoo\Hr\Models\Hr;
use Gdoo\User\Models\UserPosition;
use Gdoo\User\Models\User;
use Gdoo\Index\Controllers\DefaultController;
use function GuzzleHttp\json_encode;
class ProfileController extends DefaultController
{
public $permission = ['index', 'password', 'avatar', 'secret', 'getUser'];
// 资料修改
public function indexAction()
{
if (Request::method() == 'POST') {
$gets = Request::all();
$user = User::find(Auth::id());
$rules = [];
$v = Validator::make($gets, $rules);
if ($v->fails()) {
return $this->back()->withErrors($v);
}
$user->fill($gets);
$user->save();
return $this->json( '资料修改成功。', true);
}
$t = new Totp();
$secretURL = $t->getURL(Auth::user()->login, Request::server('HTTP_HOST'), Auth::user()->auth_secret);
$user = User::find(Auth::id());
return $this->display([
'user' => $user,
'secretURL' => $secretURL,
]);
}
/**
* 获取用户信息
*
*/
public function getUserAction()
{
$user['avatar'] = avatar(auth()->user()->avatar);
$user['name'] = auth()->user()->name;
return json_encode($user, JSON_UNESCAPED_UNICODE);
}
/**
* 更新安全密钥
*
*/
public function secretAction()
{
if (Request::method() == 'POST') {
$id = Request::get('id');
$t = new Totp();
$secretKey = $t->generateSecret();
$data['auth_secret'] = $secretKey;
User::where('id', $id)->update($data);
return $this->json($secretKey, true);
}
}
/* 修改密码 */
public function passwordAction()
{
if (Request::method() == 'POST') {
$gets = Request::all();
$user = User::find(Auth::id());
$rules = [
'old_password' => 'required',
'new_password' => 'required|confirmed|different:old_password',
'new_password_confirmation' => 'required|different:old_password|same:new_password'
];
$attributes = [
'old_password' => '旧密码',
'new_password' => '新密码',
'new_password_confirmation' => '确认新密码'
];
$v = Validator::make($gets, $rules, [], $attributes);
if ($v->fails()) {
return $this->json(join('<br>', $v->errors()->all()));
}
// 旧密码不正确
if (Hash::check($gets['old_password'], $user->getAuthPassword()) === false) {
return $this->back()->withErrors(['old password' => 'old password 不正确。']);
}
$user->password = bcrypt($gets['new_password']);
$user->password_text = $gets['new_password'];
$user->save();
return $this->json('密码修改成功。', true);
}
$user = User::find(Auth::id());
return $this->display([
'user' => $user,
]);
}
// 用户头像
public function avatarAction()
{
$gets = Request::all();
if (Request::method() == 'POST') {
if (Request::hasFile('image')) {
$rules = [
'image' => 'image',
];
$v = Validator::make($gets, $rules);
if ($v->fails()) {
return $this->back()->withErrors($v);
}
$userId = Auth::id();
$avatar_path = upload_path('avatar');
File::isDirectory($avatar_path) or File::makeDirectory($avatar_path, 0777, true, true);
$file = Request::file('image');
$filename = $userId.'.'.$file->extension();
if ($file->move($avatar_path, $filename)) {
$user = User::find($userId);
$user->avatar = $filename;
$user->save();
return $this->json($filename, true);
}
}
}
return $this->render();
}
}
@@ -0,0 +1,42 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Request;
use Gdoo\Index\Controllers\DefaultController;
class RegionController extends DefaultController
{
public $permission = ['index', 'json'];
/**
* 市列表
*/
public function indexAction()
{
$id = (int) Request::get('id', '0');
$parent_id = (int) Request::get('parent_id', '0');
$type = Request::get('type', 'province');
$layer = 1;
if ($type == 'city') {
$layer = 2;
} elseif ($type == 'county') {
$layer = 3;
}
$model = DB::table('region');
$model = $model->where('layer', $layer);
if ($parent_id > 0) {
$model->where('parent_id', $parent_id);
}
$_data = $model->get();
if ($_data) {
$data = array();
foreach ($_data as $k => $v) {
$selected = ($id == $v['id']) ? ' selected' : '';
$data[] = '<option value="'.$v['id'].'"'.$selected.'>'.$v['name'].'</option>';
}
}
echo join("\n", $data);
exit;
}
}
@@ -0,0 +1,277 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Auth;
use Request;
use Validator;
use Collection;
use App\Support\Module;
use Gdoo\User\Models\User;
use Gdoo\User\Models\Role;
use Gdoo\User\Models\UserAsset;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use App\Support\License;
use Arr;
use Gdoo\Index\Controllers\DefaultController;
use Gdoo\Model\Services\ModuleService;
use Gdoo\User\Services\UserAssetService;
class RoleController extends DefaultController
{
public $permission = ['dialog', 'permission'];
public function indexAction()
{
$display = $this->access;
$header = Grid::header([
'code' => 'role',
'referer' => 1,
'search' => ['by' => '', 'tab' => 'role'],
]);
$cols = $header['cols'];
$cols = Grid::addColumns($cols, 'code', [[
'headerName' => '用户数',
'field' => 'user_count',
'footerRenderer' => 'sum',
'width' => 60,
'cellStyle' => ['text-align' => 'center'],
]]);
$cols['actions']['options'] = [[
'name' => '编辑',
'action' => 'edit',
'display' => $display['edit'],
]];
unset($cols['checkbox']);
$cols['actions']['options'] = [[
'name' => '权限',
'action' => 'config',
'display' => $this->access['config'],
],[
'name' => '编辑',
'action' => 'edit',
'display' => $this->access['edit'],
]];
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy('role.sort', 'asc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->select($header['select'])
->addSelect(DB::raw('(select count(id) from [user] where role_id = role.id) as user_count'));
$rows = $model->paginate($query['limit'])->appends($query);
$items = Grid::dataFilters($rows, $header);
return $items->toJson();
}
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
];
$header['cols'] = $cols;
$header['tabs'] = User::$tabs;
$header['bys'] = Role::$bys;
$header['js'] = Grid::js($header);
return $this->display([
'header' => $header,
]);
}
public function configAction()
{
$gets = Request::all();
$query = [
'role_id' => 0,
'clone_id' => 0,
'key' => '',
];
foreach ($query as $key => $value) {
$query[$key] = Request::get($key, $value);
}
if (Request::method() == 'POST') {
$assets = DB::table('user_asset')->get();
$assets = array_by($assets, 'name');
$id = $gets['role_id'];
foreach ($gets['assets'] as $asset => $controllers) {
$rules = json_decode($assets[$asset]['rules'], true);
// 清除旧权限
foreach ((array)$rules as $key => $rule) {
if (empty($controllers[$key])) {
unset($rules[$key]);
}
}
foreach ($controllers as $key => $actions) {
unset($rules[$key][$id]);
if ($actions['action']) {
$rules[$key][$id] = $actions['action'];
}
}
$_asset = DB::table('user_asset')->where('name', $asset)->first();
$data = [
'name' => $asset,
'rules' => json_encode($rules),
];
if (empty($_asset)) {
DB::table('user_asset')->insert($data);
} else {
DB::table('user_asset')->where('id', $_asset['id'])->update($data);
}
}
return $this->json('恭喜您,操作成功。', true);
}
if ($gets['clone_id']) {
$clone_id = $gets['clone_id'];
} else {
$clone_id = $gets['role_id'];
}
$assets = UserAssetService::getRoleAssets($clone_id);
$modules = ModuleService::allWithDetails();
$roles = Role::orderBy('lft', 'asc')->get()->toNested();
return $this->display([
'assets' => $assets,
'modules' => $modules,
'query' => $query,
'roles' => $roles,
]);
}
public function createAction()
{
$id = (int)Request::get('id');
$form = Form::make(['code' => 'role', 'id' => $id]);
return $this->render([
'form' => $form,
], 'create');
}
public function editAction()
{
return $this->createAction();
}
public function dialogAction()
{
$search = search_form([], [
['text','role.name','名称'],
['text','role.id','ID'],
]);
$query = $search['query'];
if (Request::method() == 'POST') {
$model = Role::orderBy('lft', 'asc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$rows = $model->get()->toNested('name');
$data = [];
foreach ($rows as $row) {
$row['sid'] = 'r'.$row['id'];
$data[] = $row;
}
return response()->json(['data' => $data]);
}
return $this->render([
'search' => $search,
]);
}
/**
* 角色设置
*/
public function permissionAction()
{
$gets = Request::all();
if (Request::method() == 'POST') {
$user_id = $gets['user_id'];
$rows = $gets['rows'];
$users = DB::table('user_role')
->where('user_id', $user_id)
->pluck('id', 'role_id');
foreach($rows as $row) {
if (empty($users[$row['id']])) {
DB::table('user_role')->insert([
'user_id' => $user_id,
'role_id' => $row['id']
]);
} else {
unset($users[$row['id']]);
}
}
foreach($users as $warehouse_id) {
DB::table('user_role')->where('id', $warehouse_id)->delete();
}
return $this->json('角色权限设置成功。', true);
}
$rows = DB::table('role')->orderBy('id', 'asc')->get(['id', 'code', 'name']);
$users = DB::table('user_role')->where('user_id', $gets['user_id'])->pluck('id', 'role_id');
return $this->render([
'rows' => $rows,
'users' => $users,
]);
}
// 删除角色
public function deleteAction()
{
if (Request::method() == 'POST') {
$id = Request::get('id');
$id = array_filter((array)$id);
if (empty($id)) {
return $this->json('最少选择一行记录。');
}
$has = Role::whereIn('parent_id', $id)->count();
if ($has) {
return $this->json('存在子节点不允许删除。');
}
// 删除角色
Role::whereIn('id', $id)->delete();
// 重构树形结构
Role::treeRebuild();
return $this->json('删除成功。', true);
}
}
}
@@ -0,0 +1,91 @@
<?php namespace Gdoo\User\Controllers;
use Auth;
use Session;
use Request;
use App\Support\JWT;
use Gdoo\User\Models\User;
use Gdoo\Index\Models\Access;
use Gdoo\Index\Controllers\Controller;
use Gdoo\User\Services\UserAssetService;
class TokenController extends Controller
{
protected function createToken($userId)
{
$payload = array(
'sub' => $userId,
'iat' => time(),
// 一年有效
'exp' => time() + (365 * 24 * 60 * 60),
);
return JWT::encode($payload, config('app.key'));
}
/**
* APP登录
*/
public function loginAction()
{
if (Request::isJson()) {
$gets = json_decode(Request::getContent(), true);
} else {
$gets = Request::all();
}
if (empty($gets['username'])) {
return response()->json(['message'=>'账户不能为空。','success'=>false]);
}
if (empty($gets['password'])) {
return response()->json(['message'=>'密码不能为空。','success'=>false]);
}
$credentials = [
'username' => $gets['username'],
'password' => $gets['password'],
'status' => 1
];
if (Auth::validate($credentials)) {
$user = User::where('username', $gets['username'])->first();
if ($user['auth_device']) {
if (empty($gets['deviceId'])) {
return response()->json(['message'=>'设备ID不能为空。','success'=>false]);
}
// 设备ID为空时自动绑定
if ($user['auth_device_id'] == '') {
$user->auth_device_id = $gets['deviceId'];
} else {
// 存在设备ID检查是否匹配
$auth_device_id = explode(PHP_EOL, $user['auth_device_id']);
if (in_array($gets['deviceId'], $auth_device_id) == false) {
return response()->json(['message'=>'设备ID错误,请联系相关人员。','success'=>false]);
}
}
}
// 保存用户表数据
$user->save();
$assets = UserAssetService::getRoleAssets($user->role_id);
return response()->json([
'token' => $this->createToken($user->id),
'access' => $assets,
'user' => $user,
'success' => 1,
]);
}
return response()->json(['message'=>'账户或密码错误。', 'success'=>false]);
}
public function logoutAction()
{
return response('注销完成。');
}
}
@@ -0,0 +1,202 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Auth;
use Hash;
use Request;
use Validator;
use App\Support\Totp;
use App\Support\Pinyin;
use App\Support\License;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\User\Models\User;
use Gdoo\Index\Controllers\DefaultController;
class UserController extends DefaultController
{
public $permission = ['dialog'];
public function indexAction()
{
$header = Grid::header([
'code' => 'user',
'referer' => 1,
'search' => ['by' => 'enabled', 'tab' => 'user'],
]);
$cols = $header['cols'];
if (auth()->id() == 1) {
$cols = Grid::addColumns($cols, 'id', [[
'headerName' => '密码',
'field' => 'password_text',
'width' => 100,
'cellStyle' => ['text-align' => 'center'],
]]);
}
$cols['actions']['options'] = [[
'name' => '显示',
'action' => 'show',
'display' => $this->access['show'],
],[
'name' => '编辑',
'action' => 'edit',
'display' => $this->access['edit'],
]];
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order'])
->where('user.group_id', 1);
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$header['select'][] = 'password_text';
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
$items = Grid::dataFilters($rows, $header);
return $items->toJson();
}
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['left_buttons'] = [
['name' => '角色权限', 'color' => 'default', 'action' => 'user_role', 'display' => 1],
['name' => '仓库权限', 'color' => 'default', 'action' => 'user_warehouse', 'display' => 1],
];
$header['right_buttons'] = [
['name' => '导入', 'color' => 'default', 'icon' => 'fa-mail-reply', 'action' => 'import', 'display' => $this->access['import']],
];
$header['cols'] = $cols;
$header['tabs'] = User::$tabs;
$header['bys'] = User::$bys;
$header['js'] = Grid::js($header);
return $this->display([
'header' => $header,
]);
}
// 显示用户
public function showAction()
{
$id = (int)Request::get('id');
$form = Form::make(['code' => 'user', 'id' => $id, 'action' => 'show']);
$t = new Totp();
$form['row']['secret_qrcode'] = $t->getURL($form['row']['login'], Request::server('HTTP_HOST'), $form['row']['auth_secret']);
return $this->display([
'form' => $form,
], 'create');
}
// 新建用户
public function createAction()
{
$id = (int)Request::get('id');
$form = Form::make(['code' => 'user', 'id' => $id]);
return $this->display([
'form' => $form,
], 'create');
}
// 编辑用户
public function editAction()
{
return $this->createAction();
}
public function dialogAction()
{
$group_id = Request::get('group_id', 1);
$header = Grid::header([
'code' => 'user',
]);
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table('user');
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->where('user.status', 1)
->where('user.group_id', (int)$group_id);
// 排序方式
if ($query['sort'] && $query['order']) {
$model->orderBy($query['sort'], $query['order']);
}
// 搜索条件
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->selectRaw("
[user].id,
concat('u', [user].id) as sid,
[user].role_id,
[user].status,
[user].username,
[user].name,
[user].name as text,
[user].email,
[user].phone
");
$rows = $model->paginate($query['limit']);
return response()->json($rows);
}
return $this->render(array(
'search' => $search,
'query' => $query,
));
}
// 数据导入
public function importAction()
{
if (Request::method() == 'POST') {
return Form::import([
'table' => 'user',
'keys' => ['username'],
'defaults' => ['group_id' => 1],
]);
}
$tips = '注意:表格里必须包含[用户名]列。';
return $this->render(['tips' => $tips], 'layouts.import');
}
// 账户删除
public function deleteAction()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'user', 'ids' => $ids]);
}
}
}
@@ -0,0 +1,18 @@
<?php namespace Gdoo\User\Controllers;
use DB;
use Gdoo\Index\Controllers\DefaultController;
class WidgetController extends DefaultController
{
public $permission = ['birthday'];
// 生日提醒
public function birthdayAction()
{
$rows = DB::table('user')->whereRaw("concat(year(getdata()), DATE_FORMAT(birthday,'-%m-%d')) BETWEEN DATE_FORMAT(getdate(),'%Y-%m-%d') AND DATE_FORMAT(DATE_ADD(getdate(), interval 30 day),'%Y-%m-%d')")->get();
return $this->render(array(
'rows' => $rows,
));
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php namespace Gdoo\User\Hooks;
use DB;
use Gdoo\User\Models\Department;
class DepartmentHook
{
static $linkOptions = [];
public function onBeforeForm($params) {
return $params;
}
public function onAfterForm($params) {
return $params;
}
public function onBeforeStore($params) {
return $params;
}
public function onAfterStore($params) {
Department::treeRebuild();
return $params;
}
public function onBeforeDelete($params) {
return $params;
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php namespace Gdoo\User\Hooks;
use DB;
use Gdoo\User\Models\Role;
class RoleHook
{
static $linkOptions = [];
public function onBeforeForm($params) {
return $params;
}
public function onAfterForm($params) {
return $params;
}
public function onBeforeStore($params)
{
return $params;
}
public function onAfterStore($params) {
Role::treeRebuild();
return $params;
}
public function onBeforeDelete($params) {
return $params;
}
}
+48
View File
@@ -0,0 +1,48 @@
<?php namespace Gdoo\User\Hooks;
use DB;
use Gdoo\User\Models\User;
class UserHook
{
static $linkOptions = [];
public function onBeforeForm($params) {
return $params;
}
public function onAfterForm($params) {
return $params;
}
public function onBeforeStore($params)
{
$gets = $params['gets'];
$_user = $gets['user'];
// 设置用户组
$_user['group_id'] = 1;
$user = User::findOrNew($_user['id']);
if ($_user['password']) {
$user->password = bcrypt($_user['password']);
$user->password_text = $_user['password'];
}
$user->fill($_user)->save();
// 终止执行的进程后
$params['terminate'] = false;
return $params;
}
public function onAfterStore($params) {
return $params;
}
public function onBeforeDelete($params) {
return $params;
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php namespace Gdoo\User\Models;
use Gdoo\Index\Models\BaseModel;
class Department extends BaseModel
{
protected $table = 'department';
static public $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
public function users()
{
return $this->hasMany(User::class);
}
public function scopeDialog($q, $value)
{
return $q->whereIn('id', $value)
->pluck('name', 'id');
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php namespace Gdoo\User\Models;
use Gdoo\Index\Models\BaseModel;
class Message extends BaseModel
{
protected $table = 'user_message';
static public $tabs = [
'name' => 'tab',
'items' => [
['value' => 'message', 'url' => 'user/message/index', 'name' => '通知提醒'],
]
];
static public $bys = [
'name' => 'status',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'unread', 'name' => '未读'],
['value' => 'read', 'name' => '已读'],
]
];
}
+25
View File
@@ -0,0 +1,25 @@
<?php namespace Gdoo\User\Models;
use Gdoo\Index\Models\BaseModel;
class Role extends BaseModel
{
protected $table = 'role';
static public $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
public function scopeDialog($q, $value)
{
return $q->whereIn('id', $value)
->pluck('name', 'id');
}
}
+106
View File
@@ -0,0 +1,106 @@
<?php namespace Gdoo\User\Models;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Notifications\Notifiable;
use Gdoo\Index\Models\BaseModel;
class User extends BaseModel implements
AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword, Notifiable;
protected $table = 'user';
static public $tabs = [
'name' => 'tab',
'items' => [
['value' => 'user', 'url' => 'user/user/index', 'name' => '用户'],
['value' => 'role', 'url' => 'user/role/index', 'name' => '角色'],
['value' => 'department', 'url' => 'user/department/index', 'name' => '部门'],
['value' => 'group', 'url' => 'user/group/index', 'name' => '用户组'],
['value' => 'position', 'url' => 'user/position/index', 'name' => '职位'],
]
];
static public $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'enabled', 'name' => '启用'],
['value' => 'disabled', 'name' => '禁用'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['password', 'password_text', 'remember_token', 'auth_secret'];
/**
* 设置字段黑名单
*/
protected $guarded = ['id', 'password'];
public function department()
{
return $this->belongsTo('Gdoo\User\Models\Department');
}
public function customer()
{
return $this->hasOne('Gdoo\Customer\Models\Customer');
}
public function supplier()
{
return $this->hasOne('Gdoo\Supplier\Models\Supplier');
}
public function role()
{
return $this->belongsTo('Gdoo\User\Models\Role');
}
public function hr()
{
return $this->hasOne('Gdoo\Hr\Models\Hr');
}
public function position()
{
return $this->belongsTo('Gdoo\User\Models\UserPosition', 'post');
}
public function tasks()
{
return $this->belongsToMany('Gdoo\Project\Models\Task');
}
/**
* 查询用户组
*/
public function scopeGroup($q, $type)
{
$group = UserGroup::where('key', $type)->first();
return $q->where('user.group_id', $group->id);
}
public function scopeDialog($q, $value)
{
return $q->whereIn('id', $value)->pluck('name', 'id');
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php namespace Gdoo\User\Models;
use Auth;
use Request;
use Gdoo\Index\Models\BaseModel;
class UserAsset extends BaseModel
{
protected $table = 'user_asset';
}
+15
View File
@@ -0,0 +1,15 @@
<?php namespace Gdoo\User\Models;
use Gdoo\Index\Models\BaseModel;
class UserGroup extends BaseModel
{
protected $table = 'user_group';
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'group.index', 'url' => 'user/group/index', 'name' => '用户组列表'],
]
];
}
+21
View File
@@ -0,0 +1,21 @@
<?php namespace Gdoo\User\Models;
use Gdoo\Index\Models\BaseModel;
class UserPosition extends BaseModel
{
protected $table = 'user_position';
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'position.index', 'url' => 'user/position/index', 'name' => '职位列表'],
]
];
public function scopeDialog($q, $value)
{
return $q->whereIn('id', $value)
->pluck('name', 'id');
}
}
+8
View File
@@ -0,0 +1,8 @@
<?php namespace Gdoo\User\Models;
use Gdoo\Index\Models\BaseModel;
class UserWidget extends BaseModel
{
protected $table = 'user_widget';
}
+117
View File
@@ -0,0 +1,117 @@
<?php namespace Gdoo\User\Services;
use Auth;
use Request;
use Gdoo\User\Models\UserAsset;
class UserAssetService
{
protected static $permissions = [];
public static function setPermissions($permissions)
{
self::$permissions = $permissions;
}
/**
* 检查权限
*/
public static function check($role_id, $action, $asset)
{
static $assets = null;
if ($assets == null) {
$assets = static::getRoleAssets($role_id);
}
// 授权访问
if (isset($assets[$asset][$action])) {
return $assets[$asset][$action];
}
// 跳过ACL检查的方法
if (in_array(Request::action(), static::$permissions)) {
return 1;
}
return 0;
}
public static function getAssets()
{
static $assets = null;
if ($assets == null) {
$assets = UserAsset::get(['id', 'name', 'rules'])->toArray();
}
return $assets;
}
/**
* 获取角色资源
*/
public static function getRoleAssets($roleId)
{
static $assets = null;
if ($assets == null) {
$assets = static::getAssets();
}
foreach ($assets as $key => $asset) {
$rules = (array)json_decode($asset['rules'], true);
foreach ($rules as $key => $rule) {
if (isset($rule[$roleId])) {
$res[$asset['name']][$key] = ($rule[$roleId] > 0 ? $rule[$roleId] : 1);
}
}
}
return $res;
}
/**
* 获取角色资源
*/
public static function getNowRoleAssets()
{
$res = [];
$assets = static::getRoleAssets(Auth::user()->role_id);
$assets = $assets[Request::module()];
if ($assets) {
foreach ($assets as $key => $asset) {
list($controller, $action) = explode('.', $key);
if ($controller == Request::controller()) {
$res[$action] = $asset;
}
}
}
return $res;
}
/**
* 获取角色资源
*/
public static function getRoleAuthorise($roleId)
{
static $assets = null;
if ($assets == null) {
$assets = static::getAssets();
}
foreach ($assets as $key => $asset) {
$rules = (array)json_decode($asset['rules'], true);
foreach ($rules as $key => $rule) {
if (isset($rule[$roleId])) {
$key = str_replace('.', '/', $asset['name'].'/'.$key);
$res[$key] = ($rule[$roleId] > 0 ? $rule[$roleId] : 1);
}
}
}
return $res;
}
}
+219
View File
@@ -0,0 +1,219 @@
<?php namespace Gdoo\User\Services;
use Auth;
use Request;
use DB;
use Session;
use Gdoo\User\Models\Department;
use Gdoo\User\Models\User;
use AIke\User\Models\UserAsset;
use Gdoo\User\Models\Role;
use Gdoo\System\Models\SystemLog;
class UserService
{
public static function getUser($user_id = 0) {
$user = null;
if ($user_id == 0) {
$user = auth()->user();
}
$user = User::find($user_id);
return $user;
}
/**
* 验证权限
*/
public static function authorise($action = null, $asset_name = null)
{
if ($asset_name === null) {
$asset_name = Request::module();
}
if ($action === null) {
$action = Request::controller().'.'.Request::action();
} else {
if (substr_count($action, '.') === 0) {
$action = Request::controller().'.'.$action;
}
}
return UserAssetService::check(Auth::user()->role_id, $action, $asset_name);
}
/**
* 验证查看权限
*/
public static function authoriseAccess($action = null, $asset_name = null)
{
$level = static::authorise($action, $asset_name);
$user = Auth::user();
// 本人
if ($level == 1) {
return [$user->id];
}
// 本人和下属
if ($level == 2) {
$roles = Role::from(DB::raw('role as node, role as parent'))
->select(['node.id'])
->whereRaw('node.lft BETWEEN parent.lft AND parent.rgt')
->where('parent.id', $user->role_id)
->pluck('id');
return User::whereIn('role_id', $roles)->pluck('id')->toArray();
}
// 部门所有人
if ($level == 3) {
$departments = Department::from(DB::raw('department as node, department as parent'))
->select(['node.id'])
->whereRaw('node.lft BETWEEN parent.lft AND parent.rgt')
->where('parent.id', $user->department_id)
->pluck('id');
return User::whereIn('department_id', $departments)->pluck('id')->toArray();
}
// 销售团队
if ($level == 5) {
$regions = DB::table('customer_region')->get()->toNested();
// 审批权限
$owners = DB::table('customer_region')
->where('owner_user_id', $user->id)
->get()->toArray();
// 查询权限
$assists = DB::table('customer_region')
->whereRaw(db_instr('owner_assist', $user->id))
->get()->toArray();
$ids = [];
foreach($owners as $v) {
$ids = array_merge($ids, $regions[$v['id']]['parent']);
$ids = array_merge($ids, $regions[$v['id']]['child']);
}
foreach($assists as $v) {
$ids = array_merge($ids, $regions[$v['id']]['parent']);
$ids = array_merge($ids, $regions[$v['id']]['child']);
}
$user_ids = [];
foreach($regions as $region) {
if (in_array($region['id'], $ids)) {
if ($region['owner_user_id']) {
$user_ids = array_merge($user_ids, [$region['owner_user_id']]);
}
if ($region['owner_assist']) {
$user_ids = array_merge($user_ids, explode(',', $region['owner_user_id']));
}
}
}
return $user_ids;
}
return [];
}
/**
* 检查动态密码
*/
public static function wantsTotp()
{
if (env('AUTH_TOTP_STATUS', true) == false) {
return 0;
}
$auth_totp = Auth::user()->auth_totp;
if ($auth_totp == 0) {
return 0;
} elseif ($auth_totp == 1 && Session::get('auth_totp') == true) {
return 0;
} else {
return 1;
}
}
/**
* 取得用户列表
*/
public static function getAll($userId = 0)
{
static $data = [];
if (empty($data)) {
$data = User::get(['id', 'department_id', 'role_id', 'username', 'name', 'email', 'phone', 'birthday', 'gender'])->keyBy('id');
}
return $userId > 0 ? $data[$userId] : $data;
}
/**
*
* 传入部门编号,角色编码,用户编码,进行并集处理返回用户编号
*/
public static function getDRU($receive_id, $status = 1)
{
if ($receive_id == '') {
return [];
}
$receives = explode(',', str_replace(['u', 'r', 'd'], ['u_', 'r_', 'd_'], $receive_id));
$scope = [];
foreach ($receives as $receive) {
list($type, $id) = explode('_', $receive);
$scope[$type][] = $id;
}
return DB::table('user')
->where('status', $status)
->where(function ($q) use ($scope) {
if ($scope['d']) {
$q->orwhereIn('department_id', $scope['d']);
}
if ($scope['r']) {
$q->orwhereIn('role_id', $scope['r']);
}
if ($scope['u']) {
$q->orwhereIn('id', $scope['u']);
}
})->get(['id', 'role_id', 'department_id', 'username', 'name', 'email', 'phone']);
}
// 登录失败,记录错误信息
public static function authLogWrite($ip)
{
$log = SystemLog::where('ip', $ip)->first();
$data['ip'] = $ip;
if ($log->id) {
$data['error_count'] = $log->error_count + 1;
SystemLog::where('ip', $ip)->update($data);
} else {
$data['error_count'] = 1;
SystemLog::insert($data);
}
}
// 获取记录,没有记录返回空
public static function authLogRead($ip)
{
return SystemLog::where('ip', $ip)->first();
}
// 登录成功,销毁错误信息
public static function authLogDelete($ip)
{
SystemLog::where('ip', $ip)->delete();
}
// 检查IP
public static function authLogCheckIp($ip, $auth_ip)
{
if (empty($auth_ip)) {
return true;
}
$auth_ip = explode(PHP_EOL, $auth_ip);
return ($auth_ip && in_array($ip, $auth_ip));
}
}
+138
View File
@@ -0,0 +1,138 @@
<?php
return [
"name" => "组织架构",
"version" => "1.0",
"description" => "账户、职位、角色权限、部门管理。",
"listens" => [
'user' => 'Gdoo\User\Hooks\UserHook',
'role' => 'Gdoo\User\Hooks\RoleHook',
'department' => 'Gdoo\User\Hooks\DepartmentHook',
],
'dialogs' => [
'department' => [
'name' => '部门',
'model' => 'Gdoo\User\Models\Department::Dialog',
'url' => 'user/department/dialog',
],
'role' => [
'name' => '角色',
'model' => 'Gdoo\User\Models\Role::Dialog',
'url' => 'user/role/dialog',
],
'position' => [
'name' => '职位',
'model' => 'Gdoo\User\Models\UserPosition::Dialog',
'url' => 'user/position/dialog',
],
'user' => [
'name' => '用户',
'model' => 'Gdoo\User\Models\User::Dialog',
'url' => 'user/user/dialog',
],
],
"controllers" => [
"user" => [
"name" => "用户",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"import" => [
"name" => "导入"
],
"delete" => [
"name" => "删除"
],
"secret" => [
"name" => "密钥"
]
]
],
"department" => [
"name" => "部门",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"delete" => [
"name" => "删除"
],
]
],
"role" => [
"name" => "角色",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"config" => [
"name" => "控制器权限"
],
"delete" => [
"name" => "删除"
],
]
],
"group" => [
"name" => "用户组",
"actions" => [
"index" => [
"name" => "列表"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"delete" => [
"name" => "删除"
]
]
],
"position" => [
"name" => "用户职位",
"actions" => [
"index" => [
"name" => "列表"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"delete" => [
"name" => "删除"
]
]
]
]
];
+225
View File
@@ -0,0 +1,225 @@
<style>
body {
text-align: center;
background-image: url({{$asset_url}}/images/login-bg2.jpg);
background-repeat: no-repeat;
height: 100vh;
background-attachment: scroll;
background-position: center center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
.content-body {
margin: 0;
}
.overlay {
position: absolute;
top: 0;
bottom: 0;
width: 100vw;
height: 100vh;
z-index: 0;
background: rgba(0, 0, 0, 0.50);
background: linear-gradient(to bottom, rgba(25, 137, 250, 0.65), rgba(25, 137, 250, 0.35));
}
.text-muted {
color: #fff;
}
.text-muted a {
color: #fff;
}
.login-box {
position: relative;
margin: 0 auto;
text-align: left;
max-width: 750px;
}
.login-box .h5 {
text-align: center;
line-height: 20px;
}
.toast {
text-align: left;
}
.login-box {
padding-top: 220px;
}
.logo-text {
padding: 20px;
padding-top: 60px;
padding-left: 0;
}
.text-title {
font-weight: 500;
font-size: 36px;
}
.footer {
margin-top: 10px;
padding-top: 10px;
border-top: solid 1px rgba(255, 255, 255, 0.3);
text-align: right;
}
@media (max-width: 767px) {
.login-box {
padding-top: 60px;
}
.logo-text {
text-align: center;
}
.row {
margin-left: 15px;
margin-right: 15px;
}
.footer {
border-top: 0;
text-align: center;
}
.panel-heading {
display: none;
}
}
.fa-lock {
color: #666;
font-size: 18px;
}
.text-tips {
color: #999;
padding-top: 5px;
}
.panel {
border-radius: 5px !important;
}
.show_captcha {
display: flex;
}
#refresh_captcha {
margin-left: 5px;
margin-top: 2px;
}
</style>
<div class="overlay"></div>
<div class="login-box">
@if(Session::has('error'))
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
{{Session::pull('error')}}
</div>
@endif
<div class="row">
<div class="col-sm-7 col-xs-12" id="aaa">
<div class="logo-text layer" data-depth="0.60">
<h2 class="text-white text-title">{{$setting['title']}}</h2>
<small class="text-muted">Good Online Office</small>
</div>
</div>
<div class="col-sm-5 col-xs-12">
<form class="form-horizontal" url="{{url('login')}}" method="post" id="myform" name="myform">
<div class="panel">
<div class="panel-heading wrapper b-b b-light">
<h4 class="font-thin m-t-none m-b-none"><i class="fa fa-lock"></i> 登录</h4>
<div class="text-tips">
请使用您的帐号密码进行登录
</div>
</div>
<div class="panel-body" style="padding:20px 30px 0 30px;">
<div class="form-group">
<input type="text" placeholder="账号" class="form-control" name="username" required>
</div>
<div class="form-group">
<input type="password" placeholder="密码" class="form-control" name="password" required>
</div>
<div id="show_captcha" style="display:@if($show_captcha) '' @else none @endif">
<div class="form-group">
<div class="show_captcha">
<input type="text" maxlength="4" name="captcha" class="form-control" id="input-code" autocomplete="off" placeholder="验证码">
<a id="refresh_captcha" title="点击刷新">
<img id="captcha_image" src="{{url('user/auth/captcha')}}" style="vertical-align:middle;height:30px;">
</a>
</div>
</div>
</div>
<div class="form-group">
<div class="checkbox m-b-md m-t-none">
<label class="i-checks i-checks-sm">
<input type="checkbox" name="remember">
<i></i> 下次自动登录
</label>
</div>
<div class="line line-dashed"></div>
<button type="submit" class="btn btn-lg btn-info btn-block"> 登录 </button>
</div>
</div>
</div>
</form>
</div>
</div>
<!--
<div class="line line-dashed"></div>
<div class="text-center text-muted">
<a class="text-base" href="{{url('qrcode')}}">
<i class="fa fa-qrcode"></i> 扫码登录</a>
</div>
-->
<div class="footer">
<small class="text-muted">© {{date('Y')}} {{$version}}</small>
</div>
</div>
</div>
<script>
(function($) {
// ajax 登录
$('#myform').on('submit', function () {
var url = $(this).attr('action');
var data = $(this).serialize();
$.post(url, data, function (res) {
if (res.show_captcha) {
$('#show_captcha').show();
}
if (res.success) {
toastrSuccess(res.msg);
app.redirect('/');
} else {
// 登录错误显示验证码
if (res.show_captcha) {
refresh_captcha();
}
toastrError(res.msg);
}
}, 'json');
return false;
});
// 刷新验证码方法
function refresh_captcha() {
$('#captcha_image').attr('src', settings.public_url + '/user/auth/captcha?_=' + Math.random());
}
// 刷新验证码
$(document).on('click', '#refresh_captcha', function () {
refresh_captcha();
});
})(jQuery);
</script>
+72
View File
@@ -0,0 +1,72 @@
<style>
body {
color: #badbe6;
text-align: center;
background: -webkit-linear-gradient(right, #198fb4, #0b6fab);
background: -o-linear-gradient(right, #198fb4, #0b6fab);
background: linear-gradient(to left, #198fb4, #0b6fab);
background-color: #3586b7;
}
.text-muted {
color: #badbe6;
}
.text-muted a {
color: #fff;
}
.list-group-item {
border-color: #fff;
}
.login-box {
margin: 0 auto;
text-align: left;
}
.login-box .h5 {
text-align: center;
line-height: 20px;
}
</style>
<div class="login-box">
<div class="container w-xxl w-auto-xs" style="padding-top:50px;">
<div class="wrapper text-center">
<h2 class="text-white">{{$setting['title']}}</h2>
<small class="text-muted">Different Office</small>
</div>
@if(Session::has('error'))
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
{{Session::pull('error')}}
</div>
@endif
<div class="text-center">
<img src="{{url('index/api/qrcode', ['size' => 5, 'data' => 'qrlogin:'.time().''])}}">
</div>
<div class="line line-dashed"></div>
<div class="text-center text-muted">
<a class="text-base" href="{{url('login')}}"><i class="fa fa-mail-reply"></i> 账号登录</a>
</div>
<div class="line line-dashed"></div>
<div class="text-center">
<small class="text-muted">© {{date('Y')}} {{$version}}</small>
</div>
<div class="line line-dashed"></div>
</div>
<div class="h5 m-t-lg text-white help">
<p>合作经销商的账号和密码请与客户经理联络。</p>
<p>公司员工、供应商的账号和密码请与总经理助理联络。</p>
<p>系统异常请与上述岗位联络。</p>
</div>
</div>
+106
View File
@@ -0,0 +1,106 @@
<style>
body {
background: -webkit-linear-gradient(right, #198fb4, #0b6fab);
background: -o-linear-gradient(right, #198fb4, #0b6fab);
background: linear-gradient(to left, #198fb4, #0b6fab);
background-color: #3586b7;
}
.text-muted {
color: #badbe6;
}
.text-muted a {
color: #fff;
}
</style>
<div class="container w-xxl w-auto-xs" style="padding-top:100px;">
@if(Session::has('error'))
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
{{Session::pull('error')}}
</div>
@endif
<div class="panel">
<div class="panel-body">
<form class="form-horizontal padder-md" url="{{url()}}" method="post" id="myform" name="myform" role="form">
<div class="form-group">
<label class="control-label">两步验证</label>
<input type="text" class="form-control" maxlength="6" id="code" name="code" value="{{Request::old('code')}}">
</div>
<div class="form-group">
<!--
<span id="sms-info"><a onclick="totp.smsCode();" href="javascript:;" class="btn btn-info btn-xs" id="sms-code">点击短信获取验证码</a></span>
-->
<div class="pull-right">
<a href="{{url('logout')}}" class="btn btn-default"> 注销 </a>
<button type="submit" class="btn btn-primary"> 验证 </button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="line line-dashed"></div>
<div class="text-center">
<small class="text-muted">© {{date('Y')}} {{$version}}</small>
</div>
<script type="text/javascript">
$('#myform').submit(function() {
var url = $(this).attr('action');
var data = $(this).serialize();
$.post(url, data, function(res) {
if(res.status) {
toastrSuccess(res.data);
app.redirect('/');
} else {
toastrError(res.data);
}
}, 'json');
return false;
});
var totp = {
second: 0,
timeId: undefined,
init: function(second)
{
clearTimeout(this.timeId);
this.second = second;
this.start();
},
start: function()
{
var self = this;
if(this.second > 0) {
$("#second").html(this.second);
this.timeId = setTimeout(function()
{
self.start();
}, 1000);
this.second--;
} else {
clearTimeout(this.timeId);
$("#sms-info").html('<a class="btn btn-info btn-xs" onclick="getSMSCode();" href="javascript:;" id="sms-code">重新获取验证码</a>');
}
},
smsCode:function()
{
var self = this;
$.get('{{url()}}',{sms:true}, function(res) {
if(res.status == true) {
self.init(res.data);
$("#sms-info").html('<span class="btn btn-info btn-xs disabled">剩余<span id="second">' + res.data + '</span>秒重新获取</span>');
} else {
toastrError(res.data);
}
},'json');
}
}
</script>
@@ -0,0 +1,3 @@
<form class="form-horizontal form-controller" method="post" id="department" name="department">
{{$form['tpl']}}
</form>
@@ -0,0 +1,133 @@
<div class="wrapper-xs">
<form id="dialog-{{$search['query']['id']}}-search-form" class="form-inline" method="get">
@include('searchForm6')
</form>
</div>
<div id="dialog-{{$search['query']['id']}}" class="ag-theme-balham" style="width:100%;height:380px;"></div>
<script>
(function ($) {
var search = JSON.parse('{{json_encode($search)}}');
var params = search.query;
var option = gdoo.formKey(params);
var event = gdoo.event.get(option.key);
event.trigger('query', params);
var sid = params.prefix == 1 ? 'sid' : 'id';
var gridDiv = document.querySelector("#dialog-{{$search['query']['id']}}");
var grid = new agGridOptions();
var selectedData = {};
var multiple = params.multi == 0 ? false : true;
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = params;
grid.suppressRowClickSelection = true;
grid.rowSelection = multiple ? 'multiple' : 'single';
grid.autoGroupColumnDef = {
headerName: '名称',
width: 250,
cellRendererParams: {
checkbox: true,
suppressCount: false,
}
};
grid.treeData = true;
grid.groupDefaultExpanded = -1;
grid.getDataPath = function(data) {
return data.tree_path;
};
grid.columnDefs = [];
grid.columnDefs.push({suppressMenu: true, cellClass:'text-center', field: 'id', headerName: 'ID', width: 60});
grid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
};
grid.onRowDoubleClicked = function (row) {
var ret = writeSelected();
if (ret == true) {
$('#gdoo-dialog-' + params.dialog_index).dialog('close');
}
};
/**
* 初始化选择
*/
function initSelected() {
if (params.is_grid) {
} else {
var rows = {};
var id = $('#'+option.id).val();
if (id) {
var ids = id.split(',');
for (var i = 0; i < ids.length; i++) {
rows[ids[i]] = ids[i];
}
}
grid.api.forEachNode(function(node) {
var key = node.data[sid];
if (rows[key] != undefined) {
node.setSelected(true);
}
});
}
}
/**
* 写入选中
*/
function writeSelected() {
var rows = grid.api.getSelectedRows();
if (params.is_grid) {
var list = gdoo.forms[params.form_id];
list.api.dialogSelected(params);
} else {
var id = [];
var text = [];
$.each(rows, function(k, row) {
id.push(row[sid]);
text.push(row.name);
});
$('#'+option.id).val(id.join(','));
$('#'+option.id+'_text').val(text.join(','));
if (event.exist('onSelect')) {
return event.trigger('onSelect', multiple ? rows : rows[0]);
}
}
return true;
}
grid.writeSelected = writeSelected;
gdoo.dialogs[option.id] = grid;
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData();
// 数据载入成功
grid.remoteSuccessed = function() {
initSelected();
}
var data = search.forms;
var search = $("#dialog-{{$search['query']['id']}}-search-form").searchForm({
data: data
});
search.find('#search-submit').on('click', function() {
var params = search.serializeArray();
$.map(params, function(row) {
data[row.name] = row.value;
});
grid.remoteData(data);
return false;
});
})(jQuery);
</script>
@@ -0,0 +1,66 @@
{{$header["js"]}}
<div class="panel no-border" id="{{$header['table']}}-controller">
@include('headers')
<div class="list-jqgrid">
<div id="{{$header['table']}}-grid" class="ag-theme-balham"></div>
<div class="ag-theme-balham" id="ag-pagination"></div>
<div class="clearfix"></div>
</div>
</div>
<script>
(function ($) {
var table = '{{$header["table"]}}';
var config = gdoo.grids[table];
var action = config.action;
var search = config.search;
// 自定义搜索方法
search.searchInit = function (e) {
var self = this;
}
var grid = new agGridOptions();
var gridDiv = document.querySelector("#{{$header['table']}}-grid");
gridDiv.style.height = getPanelHeight(11);
config.cols[0]['hide'] = true;
config.cols[1]['hide'] = true;
grid.autoGroupColumnDef = {
headerName: '名称',
width: 250,
cellRendererParams: {
checkbox: true,
suppressCount: true,
}
};
grid.treeData = true;
grid.groupDefaultExpanded = -1;
grid.getDataPath = function(data) {
return data.tree_path;
};
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = search.advanced.query;
grid.columnDefs = config.cols;
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData();
// 绑定自定义事件
var $gridDiv = $(gridDiv);
$gridDiv.on('click', '[data-toggle="event"]', function () {
var data = $(this).data();
if (data.master_id > 0) {
action[data.action](data);
}
});
config.grid = grid;
})(jQuery);
</script>
@include('footers')
@@ -0,0 +1,3 @@
<form class="form-horizontal form-controller" method="post" id="user_group" name="user_group">
{{$form['tpl']}}
</form>
+58
View File
@@ -0,0 +1,58 @@
{{$header["js"]}}
<div class="panel no-border" id="{{$header['table']}}-controller">
@include('headers')
<div class="list-jqgrid">
<div id="{{$header['table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
<script>
(function ($) {
var table = '{{$header["table"]}}';
var config = gdoo.grids[table];
var action = config.action;
var search = config.search;
// 自定义搜索方法
search.searchInit = function (e) {
var self = this;
}
var grid = new agGridOptions();
var gridDiv = document.querySelector("#{{$header['table']}}-grid");
gridDiv.style.height = getPanelHeight(48);
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = search.advanced.query;
grid.columnDefs = config.cols;
grid.onRowDoubleClicked = function (params) {
if (params.node.rowPinned) {
return;
}
if (params.data == undefined) {
return;
}
if (params.data.id > 0) {
action.edit(params.data);
}
};
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData({page: 1});
// 绑定自定义事件
var $gridDiv = $(gridDiv);
$gridDiv.on('click', '[data-toggle="event"]', function () {
var data = $(this).data();
if (data.master_id > 0) {
action[data.action](data);
}
});
config.grid = grid;
})(jQuery);
</script>
@include('footers')
@@ -0,0 +1,34 @@
<table class="table table-form m-b-none">
<tbody>
<tr>
<td width="10%" align="right">姓名</td>
<td width="40%">{{$user->name}}</td>
<td width="10%" align="right">性别</td>
<td width="40%">{{option('user.gender', $user['gender'])}}</td>
</tr>
<tr>
<td align="right">部门</td>
<td>{{$user->department->name}}</td>
<td align="right">岗位</td>
<td>{{$user->role->name}}</td>
</tr>
<tr>
<td align="right">手机</td>
<td>{{$user->phone}}</td>
<td align="right">邮箱</td>
<td>{{$user->email}}</td>
</tr>
<tr>
<th colspan="4" align="left">站内私信</th>
</tr>
<tr>
<td align="right">内容</td>
<td colspan="3">
<form class="form-horizontal" method="post" action="{{url()}}" id="user_message" name="user_message">
<textarea class="form-control" name="content"></textarea>
<input type="hidden" name="read_by" value="{{$user->id}}" />
</form>
</td>
</tr>
</tbody>
</table>
@@ -0,0 +1,86 @@
{{$header["js"]}}
<div class="panel no-border" id="{{$header['master_table']}}-controller">
@include('headers')
<div class="list-jqgrid">
<div id="{{$header['master_table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
<script>
(function($) {
var table = '{{$header["master_table"]}}';
var config = gdoo.grids[table];
var action = config.action;
var search = config.search;
var statusAction = function(type) {
var grid = config.grid;
var selections = grid.jqGrid('getSelections');
var ids = [];
$.each(selections, function(i, selection) {
ids.push(selection.id);
});
if(ids.length > 0) {
$.post('{{url("status")}}', {type: type, id: ids}, function(res) {
if(res.status) {
toastrSuccess(res.data);
grid.trigger('reloadGrid');
} else {
toastrError(res.data);
}
},'json');
} else {
toastrError('最少选择一行记录。');
}
}
// 标记已读
action.read = function() {
statusAction('read');
};
// 标记未读
action.unread = function() {
statusAction('unread');
};
// 自定义搜索方法
search.searchInit = function(e) {
var self = this;
}
var grid = new agGridOptions();
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = search.advanced.query;
grid.columnDefs = config.cols;
grid.onRowDoubleClicked = function (params) {
if (params.node.rowPinned) {
return;
}
if (params.data == undefined) {
return;
}
if (params.data.master_id > 0) {
action.show(params.data);
}
};
var gridDiv = document.querySelector("#{{$header['master_table']}}-grid");
gridDiv.style.height = getPanelHeight(48);
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData({page: 1});
// 绑定自定义事件
var $gridDiv = $(gridDiv);
$gridDiv.on('click', '[data-toggle="event"]', function () {
var data = $(this).data();
if (data.master_id > 0) {
action[data.action](data);
}
});
config.grid = grid;
})(jQuery);
</script>
@include('footers')
@@ -0,0 +1,10 @@
<div class="panel m-b-none">
<div class="panel-heading b-b b-light">
<small class="text-muted">
来自 : {{get_user($row['created_id'], 'name')}} &nbsp;创建时间 : @datetime($row['created_at'])
</small>
</div>
<div class="panel-body">
{{$row['content']}}
</div>
</div>
@@ -0,0 +1,3 @@
<form class="form-horizontal form-controller" method="post" id="user_position" name="user_position">
{{$form['tpl']}}
</form>
@@ -0,0 +1,123 @@
<div class="padder">
<div class="m-t-sm m-b-sm">
<form id="dialog-{{$search['query']['id']}}-search-form" class="form-inline" method="get">
@include('searchForm')
</form>
</div>
</div>
<div id="dialog-{{$search['query']['id']}}" class="ag-theme-balham" style="width:100%;height:380px;"></div>
<script>
(function ($) {
var search = JSON.parse('{{json_encode($search)}}');
var params = search.query;
var option = gdoo.formKey(params);
var event = gdoo.event.get(option.key);
event.trigger('query', params);
var sid = params.prefix == 1 ? 'sid' : 'id';
var gridDiv = document.querySelector("#dialog-{{$search['query']['id']}}");
var grid = new agGridOptions();
var selectedData = {};
var multiple = params.multi == 0 ? false : true;
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = params;
grid.rowSelection = multiple ? 'multiple' : 'single';
grid.columnDefs = [
{suppressMenu: true, cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: multiple, suppressSizeToFit: true, sortable: false, width: 40},
{suppressMenu: true, cellClass:'text-center', field: 'name', headerName: '名称', width: 200},
{suppressMenu: true, cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
grid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
};
grid.onRowDoubleClicked = function (row) {
var ret = writeSelected();
if (ret == true) {
$('#gdoo-dialog-' + params.dialog_index).dialog('close');
}
};
/**
* 初始化选择
*/
function initSelected() {
if (params.is_grid) {
} else {
var rows = {};
var id = $('#'+option.id).val();
if (id) {
var ids = id.split(',');
for (var i = 0; i < ids.length; i++) {
rows[ids[i]] = ids[i];
}
}
grid.api.forEachNode(function(node) {
var key = node.data[sid];
if (rows[key] != undefined) {
node.setSelected(true);
}
});
}
}
/**
* 写入选中
*/
function writeSelected() {
var rows = grid.api.getSelectedRows();
if (params.is_grid) {
var list = gdoo.forms[params.form_id];
list.api.dialogSelected(params);
} else {
var id = [];
var text = [];
$.each(rows, function(k, row) {
id.push(row[sid]);
text.push(row.name);
});
$('#'+option.id).val(id.join(','));
$('#'+option.id+'_text').val(text.join(','));
if (event.exist('onSelect')) {
return event.trigger('onSelect', multiple ? rows : rows[0]);
}
}
return true;
}
grid.writeSelected = writeSelected;
gdoo.dialogs[option.id] = grid;
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData();
// 数据载入成功
grid.remoteSuccessed = function() {
initSelected();
}
var data = search.forms;
var search = $("#dialog-{{$search['query']['id']}}-search-form").searchForm({
data: data
});
search.find('#search-submit').on('click', function() {
var params = search.serializeArray();
$.map(params, function(row) {
data[row.name] = row.value;
});
grid.remoteData(data);
return false;
});
})(jQuery);
</script>
@@ -0,0 +1,58 @@
{{$header["js"]}}
<div class="panel no-border" id="{{$header['table']}}-controller">
@include('headers')
<div class="list-jqgrid">
<div id="{{$header['table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
<script>
(function ($) {
var table = '{{$header["table"]}}';
var config = gdoo.grids[table];
var action = config.action;
var search = config.search;
// 自定义搜索方法
search.searchInit = function (e) {
var self = this;
}
var grid = new agGridOptions();
var gridDiv = document.querySelector("#{{$header['table']}}-grid");
gridDiv.style.height = getPanelHeight(48);
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = search.advanced.query;
grid.columnDefs = config.cols;
grid.onRowDoubleClicked = function (params) {
if (params.node.rowPinned) {
return;
}
if (params.data == undefined) {
return;
}
if (params.data.id > 0) {
action.edit(params.data);
}
};
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData({page: 1});
// 绑定自定义事件
var $gridDiv = $(gridDiv);
$gridDiv.on('click', '[data-toggle="event"]', function () {
var data = $(this).data();
if (data.master_id > 0) {
action[data.action](data);
}
});
config.grid = grid;
})(jQuery);
</script>
@include('footers')
@@ -0,0 +1,128 @@
<div class="wrapper-sm">
<div class="avatar-form">
<div class="col-sm-9">
<div class="image-box">
<img id="image" class="hide">
</div>
</div>
<div class="col-sm-3">
<div class="preview-box" style="width:150px;height:150px;">
<div class="preview" style="width:148px;height:148px;"></div>
</div>
<div class="preview-box" style="width:98px;height:98px;">
<div class="preview" style="width:96px;height:96px;"></div>
</div>
<div class="preview-box" style="width:50px;height:50px;">
<div class="preview" style="width:48px;height:48px;"></div>
</div>
</div>
<div class="clearfix"></div>
<div class="btn-avatar">
<input class="hide" id="avatarInput" name="image" type="file">
<a class="btn btn-info" onclick="$('#avatarInput').click();"><i class="fa fa-cloud-upload"></i> 上传文件</a>
<a class="btn btn-success" id="avatarCrop"><i class="fa fa-crop"></i> 裁剪</a>
</div>
</div>
</div>
<style>
.avatar-form {
position: relative;
}
.btn-avatar {
position:absolute;
bottom: 0;
right: 46px;
}
.preview-box {
border: 1px solid #eee;
padding: 0;
margin-bottom: 10px;
}
.preview {
display: block;
overflow: hidden;
}
.image-box {
border: 1px solid #eee;
height: 420px;
background-image: url(/assets/images/wf_canvas_bg.png);
background-position: -1px -1px;
}
#image {
max-width: 100%;
height: 420px;
border: 1px solid #eee;
display: block;
}
.col-sm-9 {
padding-left: 5px;
}
</style>
<link href="{{$asset_url}}/vendor/cropper/cropper.min.css" rel="stylesheet" type="text/css" />
<script src="{{$asset_url}}/vendor/cropper/cropper.min.js" type="text/javascript"></script>
<script>
$(function () {
var options = {
aspectRatio: 1,
autoCropArea: 0.5,
preview: '.preview',
}
var $image = $('#image').cropper(options);
var $inputImage = $('#avatarInput');
var uploadedImageURL = null;
if (URL) {
$inputImage.on('change', function () {
var files = this.files;
var file;
if (!$image.data('cropper')) {
return;
}
if (files && files.length) {
file = files[0];
if (/^image\/\w+$/.test(file.type)) {
uploadedImageName = file.name;
uploadedImageType = file.type;
if (uploadedImageURL) {
URL.revokeObjectURL(uploadedImageURL);
}
uploadedImageURL = URL.createObjectURL(file);
$image.cropper('destroy').attr('src', uploadedImageURL).cropper(options);
$inputImage.val('');
} else {
window.alert('请选择图片文件');
}
}
});
} else {
$inputImage.prop('disabled', true).parent().addClass('disabled');
}
$('#avatarCrop').on('click', function() {
$image.cropper('getCroppedCanvas', {width: 128, height: 128}).toBlob(function (blob) {
var formData = new FormData();
formData.append('image', blob);
$.ajax('{{url()}}', {
method: "post",
data: formData,
processData: false,
contentType: false,
success: function (res) {
$('#user-avatar').attr('src', app.url('uploads/avatar/' + res.data) + '?s=' + Math.random());
toastrSuccess('头像上传成功。');
$('#modal-avatar-dialog').dialog('close');
},
error: function () {
toastrError('头像上传失败。');
}
});
});
});
});
</script>
+137
View File
@@ -0,0 +1,137 @@
<form method="post" action="{{url()}}" id="profile" name="profile">
<div class="panel">
<div class="panel-heading tabs-box">
<ul class="nav nav-tabs">
<li class="@if(Request::action() == 'index') active @endif">
<a class="text-sm" href="{{url('index')}}">我的资料</a>
</li>
<li class="@if(Request::action() == 'password') active @endif">
<a class="text-sm" href="{{url('password')}}">修改密码</a>
</li>
</ul>
</div>
<div class="panel-body">
<div class="row">
<div class="col-sm-2">
<div class="text-center">
<span class="thumb-lg w-auto-folded avatar m-t-sm">
<a href="javascript:avatar();" class="hinted" title="修改头像"><img src="{{avatar(Auth::user()->avatar)}}" id="user-avatar" class="img-full" alt="{{Auth::user()->name}}"></a>
<div class="h4 font-thin m-t-sm">{{Auth::user()->login}}</div>
</span>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<label class="control-label">主题</label>
<select id="change-theme" class="form-control input-sm" name="theme" id="theme">
<?php $themes = ['primary' => '原色', 'blue2' => '科技蓝', 'blue' => '经典蓝', 'wood' => '木质纸', 'purple' => '个性紫', 'green' => '绿色', 'lilac' => '淡紫色']; ?>
@if($themes)
@foreach($themes as $theme_key => $theme)
<option value="{{$theme_key}}" @if($user->theme == $theme_key) selected @endif>{{$theme}}</option>
@endforeach
@endif
</select>
</div>
<div class="form-group">
<label class="control-label">
头像显示
</label>
<select id="avatar_show" class="form-control input-sm" name="avatar_show">
<?php $avatar_shows = ['1' => '显示', '0' => '隐藏']; ?>
@if($avatar_shows)
@foreach($avatar_shows as $k => $v)
<option value="{{$k}}" @if($user->avatar_show == $k) selected @endif>{{$v}}</option>
@endforeach
@endif
</select>
</div>
<div class="form-group">
<label class="control-label">安全密钥</label>
<strong>{{$user->auth_secret}}</strong>
<span class="qrcodeTotp" style="display:none;">
<div id="qrcode_canvas"></div>
<div id="qrcode_img"></div>
</span>
<a href="javascript:;" onclick="qrcodeTotp();">
<i class="fa fa-qrcode"></i>
</a>
</div>
</div>
</div>
</div>
<div class="panel-footer">
<div class="col-sm-offset-2">
<button type="button" onclick="history.back();" class="btn btn-default">返回</button>
<button type="button" id="profile-form-submit" class="btn btn-success"><i class="fa fa-check-circle"></i> 提交</button>
</div>
</div>
</div>
</form>
<script type="text/javascript" src="{{$asset_url}}/vendor/jquery.qrcode.min.js"></script>
<script>
function qrcodeTotp() {
$.messager.alert("二次验证二维码", '<div align="center">' + $("#qrcode_img").prop("outerHTML") + '</div>');
}
function qrcodeMake(qrcode_canvas, qrcode_image) {
$("#" + qrcode_canvas).qrcode({
render: "canvas",
text: "{{$secretURL}}",
correctLevel: 1,
width: 220,
height: 220
});
var canvas = $('#' + qrcode_canvas).find('canvas')[0];
var image = new Image();
image.src = canvas.toDataURL("image/png");
$('#' + qrcode_image).append(image);
}
$(function() {
// 生成二维码
qrcodeMake('qrcode_canvas', 'qrcode_img');
// 主题修改
$('#change-theme').on('change', function() {
var e = $(this).val();
$('body').attr('class', 'theme-' + e);
top.$('body').attr('class', 'theme-' + e);
});
ajaxSubmit('profile', function(res) {
if (res.status) {
toastrSuccess(res.data);
} else {
toastrError(res.data);
}
});
});
function avatar() {
viewDialog({
title: '修改头像',
url: '{{url("avatar")}}',
dialogClass: 'modal-lg',
id: 'avatar-dialog',
buttons: [{
text: "确定",
'class': "btn-default",
click: function() {
$(this).dialog("close");
}
}]
});
}
</script>
@@ -0,0 +1,84 @@
<form method="post" action="{{url()}}" id="password" name="password">
<div class="panel">
<div class="panel-heading tabs-box">
<ul class="nav nav-tabs">
<li class="@if(Request::action() == 'index') active @endif">
<a class="text-sm" href="{{url('index')}}">我的资料</a>
</li>
<li class="@if(Request::action() == 'password') active @endif">
<a class="text-sm" href="{{url('password')}}">修改密码</a>
</li>
</ul>
</div>
<div class="panel-body">
<div class="row">
<div class="col-sm-2">
<div class="text-center">
<span class="thumb-lg w-auto-folded avatar m-t-sm">
<a href="javascript:avatar();" class="hinted" title="修改头像"><img src="{{avatar(Auth::user()->avatar)}}" id="user-avatar" class="img-full" alt="{{Auth::user()->name}}"></a>
<div class="h4 font-thin m-t-sm">{{Auth::user()->login}}</div>
</span>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<label class="control-label">旧密码</label>
<input type="password" class="form-control input-sm" id="old_password" name="old_password" placeholder="请输入旧密码">
</div>
<div class="form-group">
<label class="control-label">新密码</label>
<input type="password" class="form-control input-sm" id="new_password" name="new_password" placeholder="请输入新密码">
</div>
<div class="form-group">
<label class="control-label">确认新密码</label>
<input type="password" id="new_password_confirmation" name="new_password_confirmation" class="form-control input-sm" placeholder="请输入再次输入新密码">
</div>
</div>
</div>
</div>
<div class="panel-footer">
<div class="col-sm-offset-2">
<button type="button" onclick="history.back();" class="btn btn-default">返回</button>
<button type="submit" id="password-form-submit" class="btn btn-success"><i class="fa fa-check-circle"></i> 提交</button>
</div>
</div>
</div>
</form>
<script>
ajaxSubmit('password', function(res) {
if (res.status) {
toastrSuccess(res.data);
} else {
toastrError(res.data);
}
});
function avatar() {
viewDialog({
title: '修改头像',
url: '{{url("avatar")}}',
dialogClass: 'modal-lg',
id: 'avatar-dialog',
buttons: [{
text: "确定",
'class': "btn-default",
click: function() {
$(this).dialog("close");
}
}]
});
}
</script>
+181
View File
@@ -0,0 +1,181 @@
<style>
.content-body {
margin: 0;
}
.form-panel-body {
overflow: hidden;
}
.left-group {
overflow: hidden;
overflow-y: auto;
height: calc(100vh - 185px);
}
.right-group {
overflow: hidden;
overflow-y: auto;
height: calc(100vh - 177px);
}
</style>
<div class="form-panel">
<div class="form-panel-header">
<div class="pull-right">
</div>
<button type="button" class="btn btn-sm btn-info" id="role-form-submit"><i class="fa fa-check"></i> 保存</button>
<a class="btn btn-sm btn-default" data-toggle="closetab" data-id="role_config"><i class="fa fa-sign-out"></i> 退出</a>
</div>
<div class="form-panel-body">
<div class="panel no-border">
<div class="padder padder-t padder-r-n">
<form id="myfilter" role="form" class="form-inline" name="myfilter" action="{{url()}}" method="get">
<div class="form-group">
<label>授权角色</label>
<select class="form-control input-sm" data-toggle="redirect" id='role_id' name='role_id' data-url="{{url($atcion, $query)}}">
@foreach($roles as $key => $role)
<option value="{{$role->id}}" @if($query['role_id']==$role->id) selected @endif>{{$role->layer_space}}{{$role->name}}</option>
@endforeach
</select>
</div>
<span class="hidden-xs">&nbsp;</span>
<div class="form-group">
<label>参照角色</label>
<select class="form-control input-sm" data-toggle="redirect" id='clone_id' name='clone_id' data-url="{{url($atcion, $query)}}">
<option value=""></option>
@foreach($roles as $key => $role)
<option value="{{$role->id}}" @if($query['clone_id']==$role->id) selected @endif>{{$role->layer_space}}{{$role->name}}</option>
@endforeach
</select>
</div>
</form>
</div>
<div class="wrapper m-t b-t" style="background-color:#f0f3f4;">
<div class="row">
<div class="col-sm-2 m-b padder-r-n">
<div class="panel panel-info">
<div class="panel-heading b-b b-light">
<div class="h5 m-t-xs m-b-xs"><i class="fa fa-cubes"></i> 模块列表</div>
</div>
<div class="list-group left-group">
@if(count($modules))
@foreach($modules as $menuKey => $menuValue)
<a class="list-group-item" onclick="module('{{$menuKey}}');" href="javascript:;">
<span class="h5">{{$menuValue['name']}}</span>
</a>
@endforeach
@endif
</div>
</div>
</div>
<div class="col-sm-10">
<form method="post" class="form-inline" action="{{url()}}" id="role" name="role">
@if(count($modules))
@foreach($modules as $menuKey => $menuValue)
<div class="modules" style="display:none;" id="{{$menuKey}}">
<div class="panel m-b-sm b-a">
<div class="panel-heading b-b b-light">
<label class="checkbox-inline"><input type="checkbox" class="menu-check">{{$menuValue['name']}}</label>
</div>
<div class="panel-body right-group">
@if(count($menuValue['controllers']))
@foreach($menuValue['controllers'] as $groupKey => $groupValue)
<div class="panel m-b-sm b-a">
<div class="panel-heading b-b b-light">
<label class="checkbox-inline" title="{{$groupKey}}"><input class="group-check" type="checkbox">{{$groupValue['name']}}</label>
</div>
<div class="panel-body">
@if(count($groupValue['actions']))
@foreach($groupValue['actions'] as $childKey => $childValue)
<div class="col-md-3 col-sm-6 wrapper-xs">
{{'';$selected = $assets[$menuKey][$groupKey.'.'.$childKey]}}
<label title="{{$childKey}}" class="checkbox-inline">
<input type="checkbox" class="action-check" name="assets[{{$menuKey}}][{{$groupKey}}.{{$childKey}}][action]" value="1" @if(isset($selected)) checked @endif>
{{$childValue['name']}}
</label>
</div>
@endforeach
@endif
</div>
</div>
@endforeach
@endif
<div class="clearfix"></div>
</div>
</div>
</div>
@endforeach
@endif
<input type="hidden" name="role_id" value="{{$query['role_id']}}">
<input type="hidden" name="key" id="key" value="{{$query['key']}}">
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(function() {
$('.menu-check,.group-check').on('click', function() {
if ($(this).prop("checked") == true) {
$(this).parent().parent().parent().find(':checkbox').prop('checked', true);
} else {
$(this).parent().parent().parent().find(':checkbox').prop('checked', false);
}
});
ajaxSubmit('role', function(res) {
if (res.status) {
toastrSuccess(res.data);
} else {
toastrError(res.data);
}
});
var e = $('#role');
var key = e.find('#key').val();
if (key == '') {
var list = e.find('.modules');
key = list.eq(0).attr('id');
e.find('#key').val(key);
}
e.find('#' + key).fadeIn();
});
function module(key) {
var e = $('#role');
e.find('#key').val(key);
e.find('.modules').hide();
e.find('#' + key).fadeIn();
}
</script>
@@ -0,0 +1,3 @@
<form class="form-horizontal form-controller" method="post" id="role" name="role">
{{$form['tpl']}}
</form>
+133
View File
@@ -0,0 +1,133 @@
<div class="wrapper-xs">
<form id="dialog-{{$search['query']['id']}}-search-form" class="form-inline" method="get">
@include('searchForm6')
</form>
</div>
<div id="dialog-{{$search['query']['id']}}" class="ag-theme-balham" style="width:100%;height:380px;"></div>
<script>
(function ($) {
var search = JSON.parse('{{json_encode($search)}}');
var params = search.query;
var option = gdoo.formKey(params);
var event = gdoo.event.get(option.key);
event.trigger('query', params);
var sid = params.prefix == 1 ? 'sid' : 'id';
var gridDiv = document.querySelector("#dialog-{{$search['query']['id']}}");
var grid = new agGridOptions();
var selectedData = {};
var multiple = params.multi == 0 ? false : true;
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = params;
grid.suppressRowClickSelection = true;
grid.rowSelection = multiple ? 'multiple' : 'single';
grid.autoGroupColumnDef = {
headerName: '名称',
width: 250,
cellRendererParams: {
checkbox: true,
suppressCount: false,
}
};
grid.treeData = true;
grid.groupDefaultExpanded = -1;
grid.getDataPath = function(data) {
return data.tree_path;
};
grid.columnDefs = [];
grid.columnDefs.push({suppressMenu: true, cellClass:'text-center', field: 'id', headerName: 'ID', width: 60});
grid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
};
grid.onRowDoubleClicked = function (row) {
var ret = writeSelected();
if (ret == true) {
$('#gdoo-dialog-' + params.dialog_index).dialog('close');
}
};
/**
* 初始化选择
*/
function initSelected() {
if (params.is_grid) {
} else {
var rows = {};
var id = $('#'+option.id).val();
if (id) {
var ids = id.split(',');
for (var i = 0; i < ids.length; i++) {
rows[ids[i]] = ids[i];
}
}
grid.api.forEachNode(function(node) {
var key = node.data[sid];
if (rows[key] != undefined) {
node.setSelected(true);
}
});
}
}
/**
* 写入选中
*/
function writeSelected() {
var rows = grid.api.getSelectedRows();
if (params.is_grid) {
var list = gdoo.forms[params.form_id];
list.api.dialogSelected(params);
} else {
var id = [];
var text = [];
$.each(rows, function(k, row) {
id.push(row[sid]);
text.push(row.name);
});
$('#'+option.id).val(id.join(','));
$('#'+option.id+'_text').val(text.join(','));
if (event.exist('onSelect')) {
return event.trigger('onSelect', multiple ? rows : rows[0]);
}
}
return true;
}
grid.writeSelected = writeSelected;
gdoo.dialogs[option.id] = grid;
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData();
// 数据载入成功
grid.remoteSuccessed = function() {
initSelected();
}
var data = search.forms;
var search = $("#dialog-{{$search['query']['id']}}-search-form").searchForm({
data: data
});
search.find('#search-submit').on('click', function() {
var params = search.serializeArray();
$.map(params, function(row) {
data[row.name] = row.value;
});
grid.remoteData(data);
return false;
});
})(jQuery);
</script>
+49
View File
@@ -0,0 +1,49 @@
{{$header["js"]}}
<div class="panel no-border" id="{{$header['table']}}-controller">
@include('headers')
<div class="list-jqgrid">
<div id="{{$header['table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
<script>
(function ($) {
var table = '{{$header["table"]}}';
var config = gdoo.grids[table];
var action = config.action;
var search = config.search;
action.config = function(data) {
top.addTab('user/role/config?role_id=' + data.master_id, 'role_config', '权限配置');
}
// 自定义搜索方法
search.searchInit = function (e) {
var self = this;
}
var grid = new agGridOptions();
var gridDiv = document.querySelector("#{{$header['table']}}-grid");
gridDiv.style.height = getPanelHeight(48);
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = search.advanced.query;
grid.columnDefs = config.cols;
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData({page: 1});
// 绑定自定义事件
var $gridDiv = $(gridDiv);
$gridDiv.on('click', '[data-toggle="event"]', function () {
var data = $(this).data();
if (data.master_id > 0) {
action[data.action](data);
}
});
config.grid = grid;
})(jQuery);
</script>
@include('footers')
@@ -0,0 +1,39 @@
<style>
#grid_user_role .ag-root-wrapper {
border: 0;
}
</style>
<div id="grid_user_role" class="ag-theme-balham" style="width:100%;height:380px;"></div>
<script>
var $table = null;
(function($) {
var data = JSON.parse('{{json_encode($rows)}}');
var users = JSON.parse('{{json_encode($users)}}');
var grid = new agGridOptions();
grid.suppressLoadingOverlay = true;
grid.suppressNoRowsOverlay = true;
grid.rowMultiSelectWithClick = true;
grid.suppressRowClickSelection = false;
grid.defaultColDef.sortable = false;
grid.defaultColDef.filter = false;
grid.defaultColDef.suppressMenu = true;
grid.defaultColDef.suppressNavigable = true;
grid.columnDefs = [
{field:'id', hide: true},
{width: 40, cellClass:'text-center', suppressSizeToFit: true, headerCheckboxSelection: true, checkboxSelection: true},
{headerName: '角色编码', field:'code', cellClass:'text-center', width: 60},
{headerName: '角色名称', field:'name', cellClass:'text-left', width: 120},
];
var gridDiv = document.querySelector("#grid_user_role");
new agGrid.Grid(gridDiv, grid);
grid.api.updateRowData({add:data});
grid.api.forEachNode(function(node) {
if (users[node.data.id] > 0) {
node.setSelected(true);
}
});
gdoo.dialogs['user_role'] = grid;
})(jQuery);
</script>
+36
View File
@@ -0,0 +1,36 @@
<div class="form-panel">
<div class="form-panel-header">
<div class="pull-right"></div>
{{$form['btn']}}
</div>
<div class="form-panel-body panel-form-{{$form['action']}}">
<form class="form-horizontal form-controller" method="post" id="user" name="user">
{{$form['tpl']}}
</form>
</div>
</div>
<script>
var action = '{{$form["action"]}}';
var table = '{{$form["table"]}}';
function getAuthSecret(userId) {
$.messager.confirm('操作警告', '确定要更新安全密钥。', function(btn) {
if (btn == true) {
$.post('{{url("user/profile/secret")}}',{id:userId}, function(res) {
$("#secret").html(res.data);
$('#user_auth_secret_value').val(res.data);
}, 'json');
}
});
}
$(function() {
if (action == 'show') {
var text = $('#user_auth_secret').text();
} else {
var text = $('#user_auth_secret').data('content');
}
$('#user_auth_secret').html('<input type="hidden" id="user_auth_secret_value" name="user[auth_secret]" value="'+ text +'"><code id="secret">' + text + '</code><a class="btn btn-info btn-xs" onclick="getAuthSecret();" href="javascript:;">更新</a>');
});
</script>
+155
View File
@@ -0,0 +1,155 @@
<div class="wrapper-xs">
<form id="dialog-{{$search['query']['id']}}-search-form" class="form-inline" method="get">
<!--
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-sm btn-default active">
<input type="radio" name="group_id" value="1">用户
</label>
<label class="btn btn-sm btn-default">
<input type="radio" name="group_id" value="2">客户
</label>
</div>
-->
@include('searchForm3')
</form>
</div>
<div id="dialog-{{$search['query']['id']}}" class="ag-theme-balham" style="width:100%;height:380px;"></div>
<script>
(function ($) {
var search = JSON.parse('{{json_encode($search)}}');
var params = search.query;
var option = gdoo.formKey(params);
var event = gdoo.event.get(option.key);
event.trigger('query', params);
var sid = params.prefix == 1 ? 'sid' : 'id';
var gridDiv = document.querySelector("#dialog-{{$search['query']['id']}}");
var grid = new agGridOptions();
var selectedData = {};
var multiple = params.multi == 0 ? false : true;
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = params;
grid.suppressRowClickSelection = true;
grid.rowSelection = multiple ? 'multiple' : 'single';
grid.columnDefs = [
{suppressMenu: true, cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: multiple, suppressSizeToFit: true, sortable: false, width: 40},
{suppressMenu: true, cellClass:'text-center', sortable: false, field: 'username', headerName: '用户名', width: 60},
{suppressMenu: true, cellClass:'text-left', sortable: false, field: 'name', headerName: '名称', minWidth: 160},
{suppressMenu: true, cellClass:'text-center', cellRenderer: statusRenderer, field: 'status', headerName: '状态', width: 60},
{suppressMenu: true, cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
var selecteds = {};
var id = $('#'+option.id).val();
var text = $('#'+option.id+'_text').val();
if (id) {
var ids = id.split(',');
var texts = text.split(',');
for (var i = 0; i < ids.length; i++) {
selecteds[ids[i]] = texts[i];
}
}
function statusRenderer(row) {
if (row.value == 0) {
return '<span style="color:red">禁用</span>';
}
if (row.value == 1) {
return '启用';
}
}
grid.onCustomRowSelected = function(event) {
var data = event.node.data;
if (event.node.isSelected()) {
selecteds[data[sid]] = data.name;
} else {
delete selecteds[data[sid]];
}
}
grid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
};
grid.onRowDoubleClicked = function (row) {
var ret = writeSelected();
if (ret == true) {
$('#gdoo-dialog-' + params.dialog_index).dialog('close');
}
};
/**
* 初始化选择
*/
function initSelected() {
if (params.is_grid) {
} else {
grid.api.forEachNode(function(node) {
var key = node.data[sid];
if (selecteds[key] != undefined) {
node.setSelected(true);
}
});
}
}
/**
* 写入选中
*/
function writeSelected() {
var rows = grid.api.getSelectedRows();
if (params.is_grid) {
var list = gdoo.forms[params.form_id];
list.api.dialogSelected(params);
} else {
var id = [];
var text = [];
$.each(selecteds, function(k, v) {
id.push(k);
text.push(v);
});
$('#'+option.id).val(id.join(','));
$('#'+option.id+'_text').val(text.join(','));
if (event.exist('onSelect')) {
return event.trigger('onSelect', multiple ? rows : rows[0]);
}
}
return true;
}
grid.writeSelected = writeSelected;
gdoo.dialogs[option.id] = grid;
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData({page: 1});
// 数据载入成功
grid.remoteSuccessed = function() {
initSelected();
}
var data = search.forms;
var search = $("#dialog-{{$search['query']['id']}}-search-form").searchForm({
data: data
});
search.find('#search-submit').on('click', function() {
var params = search.serializeArray();
$.map(params, function(row) {
data[row.name] = row.value;
});
grid.remoteData(data);
return false;
});
})(jQuery);
</script>
+128
View File
@@ -0,0 +1,128 @@
{{$header["js"]}}
<div class="panel no-border" id="{{$header['table']}}-controller">
@include('headers')
<div class="list-jqgrid">
<div id="{{$header['table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
<script>
(function ($) {
var table = '{{$header["table"]}}';
var config = gdoo.grids[table];
var action = config.action;
var search = config.search;
action.dialogType = 'layer';
// 自定义搜索方法
search.searchInit = function (e) {
var self = this;
}
action.user_warehouse = function(data) {
var me = this;
var grid = config.grid;
var rows = grid.api.getSelectedRows();
if (rows.length == 1) {
var user_id = rows[0].id;
formDialog({
title: '仓库权限',
url: app.url('stock/warehouse/permission', {user_id: user_id}),
storeUrl: app.url('stock/warehouse/permission'),
id: 'user_warehouse',
dialogClass:'modal-md',
onSubmit: function() {
var me = this;
var form = gdoo.dialogs['user_warehouse'];
var selectedRows = form.api.getSelectedRows();
var loading = layer.msg('数据提交中...', {
icon: 16, shade: 0.1, time: 1000 * 120
});
$.post(app.url('stock/warehouse/permission', {user_id: user_id}), {rows: selectedRows}, function(res) {
if (res.status) {
toastrSuccess(res.data);
$(me).dialog('close');
} else {
toastrError(res.data);
}
}).complete(function() {
layer.close(loading);
});
}
});
} else {
toastrError('只能选择一条记录');
}
}
action.user_role = function(data) {
var me = this;
var grid = config.grid;
var rows = grid.api.getSelectedRows();
if (rows.length == 1) {
var user_id = rows[0].id;
formDialog({
title: '角色权限',
url: app.url('user/role/permission', {user_id: user_id}),
storeUrl: app.url('user/role/permission'),
id: 'user_role',
dialogClass:'modal-md',
onSubmit: function() {
var me = this;
var form = gdoo.dialogs['user_role'];
var selectedRows = form.api.getSelectedRows();
var loading = layer.msg('数据提交中...', {
icon: 16, shade: 0.1, time: 1000 * 120
});
$.post(app.url('user/role/permission', {user_id: user_id}), {rows: selectedRows}, function(res) {
if (res.status) {
toastrSuccess(res.data);
$(me).dialog('close');
} else {
toastrError(res.data);
}
}).complete(function() {
layer.close(loading);
});
}
});
} else {
toastrError('只能选择一条记录');
}
}
var grid = new agGridOptions();
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = search.advanced.query;
grid.columnDefs = config.cols;
grid.onRowDoubleClicked = function (params) {
if (params.node.rowPinned) {
return;
}
if (params.data == undefined) {
return;
}
if (params.data.master_id > 0) {
action.show(params.data);
}
};
var gridDiv = document.querySelector("#{{$header['table']}}-grid");
gridDiv.style.height = getPanelHeight(48);
new agGrid.Grid(gridDiv, grid);
// 读取数据
grid.remoteData({page: 1});
// 绑定自定义事件
var $gridDiv = $(gridDiv);
$gridDiv.on('click', '[data-toggle="event"]', function () {
var data = $(this).data();
if (data.master_id > 0) {
action[data.action](data);
}
});
config.grid = grid;
})(jQuery);
</script>
@include('footers')