first commit

This commit is contained in:
2025-06-25 10:53:11 +08:00
commit 9f374011ae
1240 changed files with 181139 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
/**
======================
*模块数据获取公共文件
======================
*/
use think\facade\Db;
+400
View File
@@ -0,0 +1,400 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\account\controller;
use app\base\BaseController;
use app\model\Account as AccountList;
use app\model\AccountCategory as AccountCategoryList;
use app\model\AccountChannel as AccountChannelList;
use app\account\validate\AccountCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Index extends BaseController
{
public function index()
{
if (request()->isAjax()) {
$param = get_params();
$rows = empty($param['limit']) ? get_md_contentconfig('app.page_size') : $param['limit'];
$list = AccountList::withoutField('')
->where('delete_time', null)
->order('id desc')
->paginate($rows, false)
->filter(function ($item) {
return $item->delete_time === null;
});
// 获取相应的类别和频道
$list = $list->map(function ($item) {
$item['category'] = AccountCategoryList::where('id', $item['category'])->value('category');
$item['channel'] = AccountChannelList::where('id', $item['channel'])->value('channel');
return $item;
});
return table_assign(0, '', $list->toArray());
} else {
return view();
}
}
//添加
public function add()
{
$param = get_params();
if (request()->isPost()) {
if (!empty($param['id']) && $param['id'] > 0) {
$account = (new AccountList())->detail($param['id']);
try {
validate(AccountCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['update_time'] = time();
$res = AccountList::where('id', $param['id'])->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param, $account);
}
return to_assign();
} else {
try {
validate(AccountCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
// 检查条目是否已经存在
$exist = AccountList::where('id', $param['id'])->find();
if ($exist) {
return to_assign(1, '该信息已存在');
}
// 插入条目的其余代码
$param['create_time'] = time();
$param['admin_id'] = $this->uid;
$sid = AccountList::strict(false)->field(true)->insertGetId($param);
if ($sid) {
add_log('add', $sid, $param);
$log_data = array(
'module' => 'account',
'id' => $sid,
'new_content' => '录入账号',
'field' => 'new',
'action' => 'add',
'admin_id' => $this->uid,
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
}
return to_assign(2, '添加成功!');
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
if ($id > 0) {
$detail = (new AccountList())->detail($id);
if (empty($detail)) {
return to_assign(1, '1.信息不存在');
}
View::assign('detail', $detail);
}
View::assign('id', $id);
return view();
}
}
//添加账号类型
public function add_category()
{
$param = get_params();
if (request()->isPost()) {
if (!empty($param['id']) && $param['id'] > 0) {
$account = (new AccountCategoryList())->detail($param['id']);
try {
validate(AccountCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['update_time'] = time();
$res = AccountCategoryList::where('id', $param['id'])->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param, $account);
}
return to_assign();
} else {
try {
validate(AccountCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$exist = AccountCategoryList::where('id', $param['id'])
->where('id', '<>', $param['id'])->find();
if ($exist) {
return to_assign(1, '该信息已存在');
}
$param['create_time'] = time();
$param['admin_id'] = $this->uid;
AccountCategoryList::strict(false)->field(true)->insertGetId($param);
return to_assign(2, '添加成功!');
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
if ($id > 0) {
$detail = (new AccountCategoryList())->detail($id);
if (empty($detail)) {
return to_assign(1, '1.信息不存在');
}
View::assign('detail', $detail);
}
View::assign('id', $id);
return view();
}
}
// 获取账号类型
public function getaccountcategory()
{
$pageNumber = $_GET['page'] ?? 1; // 获取当前页码,默认为第1页
$pageSize = 10; // 每页显示的数据条数
$totalRecords = AccountCategoryList::where('delete_time', null)->count(); // 获取总记录数
$totalPages = ceil($totalRecords / $pageSize); // 计算总页数
$offset = ($pageNumber - 1) * $pageSize; // 计算偏移量
$category = AccountCategoryList::where('delete_time', null)->limit($offset, $pageSize)->order('id', 'desc')->column('category', 'id');
$formattedCategorys = [];
foreach ($category as $id => $category) {
$formattedCategorys[] = ["id" => $id, "category" => $category];
}
return json(["code" => 0, "count" => $totalRecords, "data" => $formattedCategorys, "pages" => $totalPages]);
}
//获取账号类型-添加界面
public function getaddcategory()
{
$categories = AccountCategoryList::where('delete_time', null)->column('category', 'id');
$formattedCategories = array_map(function ($id, $category) {
return array("id" => $id, "category" => $category);
}, array_keys($categories), $categories);
return json_encode($formattedCategories);
}
//删除账号类型
public function del_account_category()
{
$id = $_POST['id'];
$res = Db::name('Account_category')->where('id', $id)->update(['delete_time' => time()]);
if ($res) {
return to_assign(1, '删除成功!');
} else {
return to_assign(2, '删除失败!');
}
}
//添加账号渠道
public function add_channel()
{
$param = get_params();
if (request()->isPost()) {
if (!empty($param['id']) && $param['id'] > 0) {
$account = (new AccountChannelList())->detail($param['id']);
try {
validate(AccountCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
return to_assign(1, $e->getError());
}
$param['update_time'] = time();
$res = AccountChannelList::where('id', $param['id'])->strict(false)->update($param);
if ($res) {
add_log('edit', $param['id'], $param, $account);
}
return to_assign();
} else {
try {
validate(AccountCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
return to_assign(1, $e->getError());
}
$param['create_time'] = time();
$param['admin_id'] = $this->uid;
AccountChannelList::strict(false)->field(true)->insertGetId($param);
return to_assign(2, '添加成功!');
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
if ($id > 0) {
$detail = (new AccountChannelList())->detail($id);
if (empty($detail)) {
return to_assign(1, '1.信息不存在');
}
View::assign('detail', $detail);
}
View::assign('id', $id);
return view();
}
}
//删除账号渠道
public function del_account_channel()
{
$id = $_POST['id'];
$res = Db::name('Account_channel')->where('id', $id)->update(['delete_time' => time()]);
if ($res) {
return to_assign(1, '删除成功!');
} else {
return to_assign(2, '删除失败!');
}
}
// 获取账号渠道
public function getaccountchannel()
{
$pageNumber = $_GET['page'] ?? 1; // 获取当前页码,默认为第1页
$pageSize = 10; // 每页显示的数据条数
$totalRecords = AccountChannelList::where('delete_time', null)->count(); // 获取总记录数
$totalPages = ceil($totalRecords / $pageSize); // 计算总页数
$offset = ($pageNumber - 1) * $pageSize; // 计算偏移量
$channels = AccountChannelList::where('delete_time', null)->limit($offset, $pageSize)->order('id', 'desc')->column('channel', 'id');
$formattedChannels = [];
foreach ($channels as $id => $channel) {
$formattedChannels[] = ["id" => $id, "channel" => $channel];
}
return json(["code" => 0, "count" => $totalRecords, "data" => $formattedChannels, "pages" => $totalPages]);
}
// 获取账号渠道all
public function getaccountchannelall()
{
$channels = AccountChannelList::where('delete_time', null)->order('id', 'desc')->column('channel', 'id');
$formattedChannels = [];
foreach ($channels as $id => $channel) {
$formattedChannels[] = ["id" => $id, "channel" => $channel];
}
return json(["code" => 0, "data" => $formattedChannels]);
}
//获取账号渠道-添加界面
public function getaddchannel()
{
$channels = AccountChannelList::where('delete_time', null)->column('channel', 'id');
$formattedChannels = array_map(function ($id, $channel) {
return array("id" => $id, "channel" => $channel);
}, array_keys($channels), $channels);
return json_encode($formattedChannels);
}
//编辑
public function edit()
{
$param = get_params();
$id = isset($param['id']) ? $param['id'] : 0;
$account = AccountList::where('id', $id)
->field('id, category, channel, creater, email, regphone, account, pwd, remark, create_time')
->find();
if ($account) {
View::assign('detail', $account);
} else {
View::assign('message', '没有详细数据');
}
if (request()->isPost()) {
$data = [
'category' => $param['category'],
'channel' => $param['channel'],
'email' => $param['email'],
'regphone' => $param['regphone'],
'account' => $param['account'],
'pwd' => $param['pwd'],
'remark' => $param['remark'],
'update_time' => time(),
];
$res = AccountList::where('id', $id)->update($data);
if ($res) {
return to_assign(2, '更新成功!');
} else {
return to_assign(1, '更新失败');
}
}
return view();
}
//删除
public function delete()
{
$request = request();
if ($request->isDelete() || $request->isAjax()) {
$id = get_params("id");
$detail = Db::name('Account')->where('id', $id)->find();
if (!isset($detail['id'])) {
return to_assign(1, "账号不存在");
}
if (Db::name('Account')->where('id', $id)->update(['delete_time' => time()]) !== false) {
$log_data = array(
'module' => 'account',
'field' => 'delete',
'action' => 'delete',
'admin_id' => $this->uid,
'old_content' => '',
'new_content' => '',
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "删除成功");
} else {
return to_assign(0, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
//批量删除
public function batch_delete()
{
$request = request();
if ($request->isDelete() || $request->isAjax()) {
$ids = get_params("ids");
foreach ($ids as $id) {
$detail = Db::name('Plan')->where('id', $id)->find();
if (Db::name('Plan')->where('id', $id)->update(['delete_time' => date('Y-m-d H:i:s')]) !== false) {
$log_data = array(
'module' => 'plan',
'field' => 'delete',
'action' => 'delete',
'admin_id' => $this->uid,
'old_content' => '',
'new_content' => $detail['name'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
}
}
return to_assign(0, "批量删除成功");
} else {
return to_assign(1, "错误的请求");
}
}
}
+5
View File
@@ -0,0 +1,5 @@
<?php
// 这是系统自动生成的event定义文件
return [
];
+15
View File
@@ -0,0 +1,15 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
// 这是系统自动生成的middleware定义文件
return [
//开启session中间件
'think\middleware\SessionInit',
\app\home\middleware\Install::class,
//允许跨域的请求
\think\middleware\AllowCrossDomain::class,
];
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace app\account\validate;
use think\facade\Db;
use think\Validate;
class AccountCheck extends Validate
{
// 自定义验证规则
protected function checkOne($value, $rule, $data = [])
{
$count = Db::name('Account')->where(['id' => $data['id'], 'delete_time' => 0])->count();
return $count == 0 ? true : false;
}
protected $rule = [
'maincontact' => 'require|checkOne',
'id' => 'require',
'regphone' => 'require|length:11',
'email' => 'require|regex:/^.+@.+\..+$/',
];
protected $message = [
'category.require' => '账号类型不能为空',
'channel.require' => '账号渠道不能为空',
'creater.require' => '创建人不能为空',
'regphone.require' => '创建手机号不能为空',
'regphone.length' => '创建手机号必须为11位',
'account.require' => '账号不能为空',
'pwd.require' => '密码不能为空',
'account.checkOne' => '同样的账号已经存在',
'id.require' => '缺少更新条件',
'email.require' => '邮箱不能为空',
'email.email' => '邮箱格式不正确',
];
protected $scene = [
'add' => ['account'],
'edit' => ['id'],
];
}
+176
View File
@@ -0,0 +1,176 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">录入账号</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray-2">账号类型<font>*</font></td>
<td>
<select
name="category"
lay-verify="required"
lay-reqText="请选择账号类型"
class="layui-select"
lay-search=""
lay-filter="category"
></select>
</td>
<td class="layui-td-gray-2">账号渠道<font>*</font></td>
<td colspan="3">
<select
name="channel"
lay-verify="required"
lay-reqText="请选择账号渠道"
class="layui-select"
lay-search=""
lay-filter="channel"
></select>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">电子邮箱<font>*</font></td>
<td>
<input
type="text"
name="email"
lay-verify="required"
lay-reqText="请输入电子邮箱"
placeholder="请输入电子邮箱"
class="layui-input"
value=""
/>
</td>
<td class="layui-td-gray-2">创建手机号<font>*</font></td>
<td colspan="3">
<input
type="text"
name="regphone"
lay-verify="required"
lay-reqText="请输入创建手机号"
placeholder="请输入创建手机号"
class="layui-input"
value=""
/>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">账号<font>*</font></td>
<td>
<input
type="text"
name="account"
lay-verify="required"
lay-reqText="请输入账号"
placeholder="请输入账号"
class="layui-input"
value=""
/>
</td>
<td class="layui-td-gray-2">密码<font>*</font></td>
<td>
<input
type="text"
name="pwd"
lay-verify="required"
lay-reqText="请输入密码"
placeholder="请输入密码"
class="layui-input"
value=""
/>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">备注<font>*</font></td>
<td colspan="3">
<textarea
type="text"
name="remark"
lay-verify="required"
lay-reqText="请输入备注"
placeholder="请输入备注"
class="layui-input"
value=""
style="height: 200px"
/>
</td>
</tr>
</table>
<div class="pt-1">
<input type="hidden" name="id" value="0" />
<button
class="layui-btn layui-btn-normal"
lay-submit=""
lay-filter="webform"
>
立即提交
</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
layui.use(["form", "layer"], function () {
var form = layui.form,
layer = layui.layer;
// 获取帐户类别
fetch("/account/index/getaddcategory")
.then((response) => response.json())
.then((data) => {
var select = document.querySelector('select[name="category"]');
select.innerHTML = '<option value="">请选择账号类型</option>';
data.forEach((category) => {
var option = document.createElement("option");
option.value = category.id;
option.innerText = category.category;
select.appendChild(option);
});
form.render("select");
})
.catch((error) => {
console.error("Error:", error);
});
// 获取帐户渠道
fetch("/account/index/getaddchannel")
.then((response) => response.json())
.then((data) => {
var select = document.querySelector('select[name="channel"]');
select.innerHTML = '<option value="">请选择账号渠道</option>';
data.forEach((channel) => {
var option = document.createElement("option");
option.value = channel.id;
option.innerText = channel.channel;
select.appendChild(option);
});
form.render("select");
})
.catch((error) => {
console.error("Error:", error);
});
// 监听提交事件
form.on("submit(webform)", function (data) {
// 发送请求并处理响应
fetch("/account/index/add", {
method: "POST",
body: JSON.stringify(data.field),
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((result) => {
layer.msg(result.msg);
if (result.code === 2) {
setTimeout(function () {
document.querySelector("form").reset(); // Reset the form
location.reload(); // 刷新页面
}, 1000);
}
});
return false;
});
});
</script>
+125
View File
@@ -0,0 +1,125 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">增加账号类型</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray-2">账号类型<font>*</font></td>
<td>
<input
type="text"
name="category"
lay-verify="required"
lay-reqText="请输入账号类型"
placeholder="请输入账号类型"
class="layui-input"
value=""
/>
</td>
</tr>
</table>
<div class="pt-1">
<input type="hidden" name="id" value="0" />
<button
class="layui-btn layui-btn-normal"
lay-submit=""
lay-filter="webform"
>
立即提交
</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<div class="tablelist" style="padding: 20px">
<h3 class="h3-title">账号类型列表</h3>
<table class="layui-table" lay-filter="tablelist" id="categoryList"></table>
</div>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="detail"
>查看</a
>
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete">删除</a>
</script>
<script>
layui.use(['table', 'form', 'layer'], function () {
var table = layui.table;
var form = layui.form;
var layer = layui.layer;
// 获取账号渠道列表
function getAccountCategoryList(pageNumber, pageSize) {
var url = "/account/index/getaccountcategory";
table.render({
elem: "#categoryList",
url: url,
page: {
curr: pageNumber ? pageNumber : 1,
limit: pageSize ? pageSize : 10,
},
limit: pageSize ? pageSize : 10,
cols: [
[
{ field: "id", title: "ID" },
{ field: "category", title: "账号类型" },
{
title: "操作",
align: "center",
width: 180,
minWidth: 125,
toolbar: "#barDemo",
},
],
],
});
}
function openInit() {
form.render();
// 监听提交
form.on("submit(webform)", function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 2) {
layui.tool.close(1000);
}
};
layui.tool.post("/account/index/add_category", data.field, callback);
return false;
});
// 初始化账号渠道列表
getAccountCategoryList();
}
openInit();
// 监听工具条
table.on('tool(tablelist)', function (obj) {
var data = obj.data;
console.log(obj.event);
if (obj.event === 'detail') {
layer.msg('ID' + data.id + ' 的查看操作');
} else if (obj.event === 'delete') {
layer.confirm('确定要删除该账号渠道吗?', function (index) {
let callback = function (e) {
console.log('e.code:', e.code);
if (e.code == 1) {
obj.del();
layer.msg('删除成功');
} else {
layer.msg('删除失败');
}
};
layui.tool.post('/account/index/del_account_category', { id: data.id }, callback);
layer.close(index);
});
} else if (obj.event === 'edit') {
layer.alert('编辑行:<br>' + JSON.stringify(data));
}
});
});
</script>
+123
View File
@@ -0,0 +1,123 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">增加账号渠道</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray-2">账号渠道<font>*</font></td>
<td>
<input
type="text"
name="channel"
lay-verify="required"
lay-reqText="请输入账号渠道"
placeholder="请输入账号渠道"
class="layui-input"
value=""
/>
</td>
</tr>
</table>
<div class="pt-1">
<input type="hidden" name="id" value="0" />
<button
class="layui-btn layui-btn-normal"
lay-submit=""
lay-filter="webform"
>
立即提交
</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<div class="tablelist" style="padding: 20px">
<h3 class="h3-title">账号渠道列表</h3>
<table class="layui-table" lay-filter="tablelist" id="channelList"></table>
</div>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="detail">查看</a>
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete">删除</a>
</script>
<script>
layui.use(['table', 'form', 'layer'], function () {
var table = layui.table;
var form = layui.form;
var layer = layui.layer;
// 获取账号渠道列表
function getAccountChannelList(pageNumber, pageSize) {
var url = "/account/index/getaccountchannel";
table.render({
elem: "#channelList",
url: url,
page: {
curr: pageNumber ? pageNumber : 1,
limit: pageSize ? pageSize : 10,
},
limit: pageSize ? pageSize : 10,
cols: [
[
{ field: "id", title: "ID" },
{ field: "channel", title: "账号渠道" },
{
title: "操作",
align: "center",
width: 180,
minWidth: 125,
toolbar: "#barDemo",
},
],
],
});
}
function openInit() {
form.render();
// 监听提交
form.on("submit(webform)", function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 2) {
layui.tool.close(1000);
}
};
layui.tool.post("/account/index/add_channel", data.field, callback);
return false;
});
// 初始化账号渠道列表
getAccountChannelList();
}
openInit();
// 监听工具条
table.on('tool(tablelist)', function (obj) {
var data = obj.data;
console.log(obj.event);
if (obj.event === 'detail') {
layer.msg('ID' + data.id + ' 的查看操作');
} else if (obj.event === 'delete') {
layer.confirm('确定要删除该账号渠道吗?', function (index) {
let callback = function (e) {
console.log('e.code:', e.code);
if (e.code == 1) {
obj.del();
layer.msg('删除成功');
} else {
layer.msg('删除失败');
}
};
layui.tool.post('/account/index/del_account_channel', { id: data.id }, callback);
layer.close(index);
});
} else if (obj.event === 'edit') {
layer.alert('编辑行:<br>' + JSON.stringify(data));
}
});
});
</script>
+154
View File
@@ -0,0 +1,154 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">账号信息</h3>
<input type="hidden" value="{$detail.id}" id="id">
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray-2">账号渠道<font>*</font>
</td>
<td>
<select id="channel" name="channel" lay-verify="required" lay-reqText="" class="layui-select" lay-search=""
lay-filter="channel"></select>
</td>
<td class="layui-td-gray-2">账号类型<font>*</font>
</td>
<td colspan="3">
<select id="category" name="cate" lay-verify="required" lay-reqText="" class="layui-select" lay-search=""
lay-filter="category"></select>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">电子邮箱<font>*</font>
</td>
<td>
<input id="email" type="text" name="email" lay-verify="required" lay-reqText="" placeholder=""
class="layui-input" value="{$detail.email}" />
</td>
<td class="layui-td-gray-2">创建手机号
</td>
<td colspan="3">
<input id="regphone" type="text" name="regphone" lay-verify="" lay-reqText="" placeholder="" class="layui-input"
value="{$detail.regphone}" />
</td>
</tr>
<tr>
<td class="layui-td-gray-2">账号<font>*</font>
</td>
<td>
<input id="account" type="text" name="account" lay-verify="required" lay-reqText="" placeholder=""
class="layui-input" value="{$detail.account}" />
</td>
<td class="layui-td-gray-2">密码<font>*</font>
</td>
<td colspan="3">
<input id="pwd" type="text" name="pwd" lay-verify="required" lay-reqText="" placeholder="" class="layui-input"
value="{$detail.pwd}" />
</td>
</tr>
<tr>
<td class="layui-td-gray-2">备注
</td>
<td colspan="4">
<textarea id="remark" name="remark" lay-verify="" lay-reqText="" placeholder="" class="layui-textarea">{$detail.remark}</textarea>
</td>
</tr>
</table>
<div class="pt-1">
<!-- <input type="hidden" name="id" value="0" /> -->
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">
立即提交
</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
layui.use(["form", "layer"], function () {
var laydate = layui.laydate;
var form = layui.form,
$ = layui.jquery,
layer = layui.layer;
// 获取账号渠道
fetch("/account/index/getaccountchannelall")
.then((response) => response.json())
.then((data) => {
var select = document.querySelector('select[name="channel"]');
select.innerHTML = '<option value="">请选择项目类型</option>';
data.data.forEach((channel) => {
var option = document.createElement("option");
option.value = channel.id;
option.innerText = channel.channel;
select.appendChild(option);
});
// 设置账号渠道的值
select.value = '{$detail.channel}';
form.render("select");
})
.catch((error) => {
console.error("Error:", error);
});
// 获取账号类型
fetch("/account/index/getaccountcategory")
.then((response) => response.json())
.then((data) => {
var select = document.querySelector('select[name="cate"]');
select.innerHTML = '<option value="">请选择项目类型</option>';
data.data.forEach((category) => {
var option = document.createElement("option");
option.value = category.id;
option.innerText = category.category;
select.appendChild(option);
});
// 设置账号类型的值
select.value = '{$detail.category}';
form.render("select");
})
.catch((error) => {
console.error("Error:", error);
});
// 监听提交事件
form.on("submit(webform)", function (data) {
// 获取当前时间并格式化
var updateTime = new Date().toISOString();
var idValue = document.getElementById('id').value;
console.log('输出:' + idValue);
console.log('账号:' + document.getElementById('account').value);
// 发送请求并处理响应
fetch("/account/index/edit?id=" + idValue, {
method: "POST",
body: JSON.stringify({
id: idValue,
category: document.getElementById('category').value,
channel: document.getElementById('channel').value,
email: document.getElementById('email').value,
regphone: document.getElementById('regphone').value,
account: document.querySelector('input[name="account"]').value,
pwd: document.getElementById('pwd').value,
remark: document.getElementById('remark').value,
update_time: updateTime,
}),
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((result) => {
layer.msg(result.msg);
if (result.code === 2) {
setTimeout(function () {
document.querySelector("form").reset();
location.reload(); // 刷新页面
}, 1000);
}
});
return false;
});
});
</script>
+255
View File
@@ -0,0 +1,255 @@
{extend name="../../base/view/common/base" /}
<!-- 主体 -->
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/application/nav/index"><cite>应用</cite></a>
<a><cite>账号管理</cite></a>
</span>
{/block} {block name="body"}
<div class="table-content p-3">
<div class="layui-form-bar border-t border-x">
<button class="layui-btn layui-btn-sm add-new">+ 录入账号</button>
<button class="layui-btn layui-btn-sm" id="refresh-btn">刷新</button>
<button class="layui-btn layui-btn-sm add-category">增加类型</button>
<button class="layui-btn layui-btn-sm add-channel">增加渠道</button>
</div>
<table class="layui-hide" id="account" lay-filter="account"></table>
</div>
{/block}
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ["tool", "gouguEdit", "gouguComment"];
function gouguInit() {
var table = layui.table;
var tool = layui.tool;
// 刷新按钮
$("#refresh-btn").on("click", function () {
location.reload();
});
//录入账号按钮
$(".add-new").on("click", function () {
tool.open("/account/index/add");
});
//增加类型按钮
$(".add-category").on("click", function () {
tool.open("/account/index/add_category");
});
//增加渠道按钮
$(".add-channel").on("click", function () {
tool.open("/account/index/add_channel");
});
table.on('tool(account)', function (obj) {
var data = obj.data; // 获取当前行的数据
// console.log(data);
if (obj.event === 'edit') {
var id = data.id; // 获取当前行数据的id
var url = '/account/index/edit?id=' + id;
tool.open(url);
} else if (obj.event === 'delete') {
layui.layer.confirm(
"确定删除该账号吗?",
{ icon: 3, title: "提示" },
function (index) {
$.post(
"/account/index/delete",
{ id: data.id },
function (res) {
if (res.code === 0) {
// layui.layer.msg("删除成功");
layui.layer.msg(res.msg);
obj.del(); // 删除表格中的对应行数据
} else {
// layui.layer.msg("删除失败");
layui.layer.msg(res.msg);
}
}
);
layui.layer.close(index);
}
);
}
});
function loadTableData() {
layui.pageTable.reload();
}
layui.pageTable = table.render({
elem: "#account",
title: "账号列表",
cellMinWidth: 80,
url: "/account/index/index", // 数据接口
page: true, // 开启分页
limit: 20,
height: "full-130",
cols: [
[
{ field: "checkbox", type: "checkbox" }, // 添加复选框列
// {
// field: "id",
// title: "ID",
// width: 80,
// align: "center",
// rowspan: 2,
// templet: function (d) {
// var html = "A - " + d.id;
// return html;
// },
// },
{
field: "channel",
title: "账号渠道",
align: "center",
width: 200,
rowspan: 2,
templet: function (d) {
var html =
'<span class="a1-' + d.channel + '">' + d.channel + "</span>";
return html;
},
},
{
field: "category",
title: "账号类型",
width: 120,
align: "center",
rowspan: 2,
templet: function (d) {
var html =
'<span class="a1-' + d.category + '">' + d.category + "</span>";
return html;
},
},
{
field: "email",
title: "电子邮箱",
width: 200,
align: "center",
rowspan: 2,
templet: function (d) {
var html =
'<span class="a1-' + d.email + '">' + d.email + "</span>";
return html;
},
},
{
field: "regphone",
title: "创建手机号",
width: 120,
align: "center",
rowspan: 2,
templet: function (d) {
var html =
'<span class="a1-' + d.regphone + '">' + d.regphone + "</span>";
return html;
},
},
{
field: "account",
title: "账号",
align: "center",
width: 180,
rowspan: 2,
templet: function (d) {
var html =
'<span class="a1-' + d.account + '">' + d.account + "</span>";
return html;
},
},
{
field: "pwd",
title: "密码",
align: "center",
width: 180,
rowspan: 2,
templet: function (d) {
var html = '<span class="a1-' + d.pwd + '">' + d.pwd + "</span>";
return html;
},
},
{
field: "remark",
title: "备注",
align: "center",
rowspan: 2,
templet: function (d) {
var html =
'<span class="a1-' + d.remark + '">' + d.remark + "</span>";
return html;
},
},
{
field: "create_time",
title: "创建时间",
align: "center",
width: 180,
rowspan: 2,
},
{
title: "操作",
align: "center",
width: 180,
minWidth: 125,
toolbar: "#barDemo",
},
],
],
done: function () {
// 获取右边列表的高度
var rightListHeight = $(
".table-content .layui-table-view .layui-table-body"
).height();
// 将右边列表的高度应用到图片编号这一列的每条数据上
$(".layui-table-view .layui-table-body .layui-table-cell").each(
function () {
var $cell = $(this);
if ($cell.text().startsWith("P")) {
// 判断是否是图片编号列
var $leftCell = $cell
.parents("tr")
.find(".layui-table-cell")
.first(); // 找到左侧图片编号列对应的单元格
$leftCell.css("height", rightListHeight + "px");
}
}
);
// 重新渲染表格,以解决表格高度问题
layui.table.resize("account");
// 绑定点击事件
$(".open-a").on("click", function () {
var imgUrl = $(this).attr("src");
// 创建图层并显示大图
layer.open({
type: 1,
title: false,
closeBtn: 1,
skin: "layui-layer-nobg", // 没有背景色
shadeClose: true,
content: '<img src="' + imgUrl + '" style="max-width: 100%;">',
});
});
},
});
}
</script>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs " lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="delete">删除</a>
</script>
{/block}
+148
View File
@@ -0,0 +1,148 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">账号信息</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray-2">项目名称<font>*</font>
</td>
<td>
<input type="text" name="name" lay-verify="required" lay-reqText="请输入项目名称" placeholder="请输入项目名称"
class="layui-input" value="" />
</td>
<td class="layui-td-gray-2">项目类型<font>*</font>
</td>
<td colspan="3">
<select name="cate" lay-verify="required" lay-reqText="请选择项目类型" class="layui-select" lay-search=""
lay-filter="cate"></select>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">重要程度<font>*</font>
</td>
<td>
<select name="important" lay-verify="required" lay-reqText="请选择项目类型" class="layui-select" lay-search=""
lay-filter="important">
<option value="1"></option>
<option value="2">★★</option>
<option value="3">★★★</option>
<option value="4">★★★★</option>
<option value="5">★★★★★</option>
</select>
</td>
<td class="layui-td-gray-2">项目金额
</td>
<td colspan="3">
<input type="text" name="price" lay-verify="" lay-reqText="请输入项目金额" placeholder="请输入项目金额,例如:20000.10"
class="layui-input" value="" />
</td>
</tr>
<tr>
<td class="layui-td-gray-2">计划年份<font>*</font>
</td>
<td>
<input type="text" name="year" lay-verify="required" lay-reqText="请输入" placeholder="例如:2024" class="layui-input"
value="" />
</td>
<td class="layui-td-gray-2">负责人<font>*</font>
</td>
<td colspan="3">
<input type="text" name="responsible" lay-verify="required" lay-reqText="请输入" placeholder="请输入"
class="layui-input" value="" />
</td>
</tr>
<tr>
<td class="layui-td-gray-2">开始时间
</td>
<td>
<input type="text" name="start_time" lay-verify="" lay-reqText="请选择开始时间" placeholder="请选择开始时间"
class="layui-input" value="" id="start_time" />
</td>
<td class="layui-td-gray-2">结束时间
</td>
<td colspan="3">
<input type="text" name="end_time" lay-verify="" lay-reqText="请选择结束时间" placeholder="请选择结束时间"
class="layui-input" value="" id="end_time" />
</td>
</tr>
<tr>
<td class="layui-td-gray-2">计划进度
</td>
<td colspan="4">
<textarea name="schedule" lay-verify="" lay-reqText="请输入" placeholder="请输入项目进度" class="layui-textarea"
value=""></textarea>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">备注
</td>
<td colspan="4">
<textarea name="schedule" lay-verify="" lay-reqText="请输入" placeholder="请输入备注" class="layui-textarea"
value=""></textarea>
</td>
</tr>
</table>
<div class="pt-1">
<input type="hidden" name="id" value="0" />
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">
立即提交
</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
layui.use(["form", "layer"], function () {
var laydate = layui.laydate;
var form = layui.form,
layer = layui.layer;
laydate.render({
elem: '#start_time',
});
laydate.render({
elem: '#end_time',
});
// 获取项目类别
fetch("/plan/index/getprojectcate")
.then((response) => response.json())
.then((data) => {
var select = document.querySelector('select[name="cate"]');
select.innerHTML = '<option value="">请选择项目类型</option>';
data.data.forEach((cate) => {
var option = document.createElement("option");
option.value = cate.id;
option.innerText = cate.cate;
select.appendChild(option);
});
form.render("select");
})
.catch((error) => {
console.error("Error:", error);
});
// 监听提交事件
form.on("submit(webform)", function (data) {
// 发送请求并处理响应
fetch("/plan/index/add", {
method: "POST",
body: JSON.stringify(data.field),
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((result) => {
layer.msg(result.msg);
if (result.code === 2) {
setTimeout(function () {
document.querySelector("form").reset(); // Reset the form
location.reload(); // 刷新页面
}, 1000);
}
});
return false;
});
});
</script>
+82
View File
@@ -0,0 +1,82 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
/**
======================
*模块数据获取公共文件
======================
*/
use think\facade\Db;
//读取后台菜单列表
function admin_menu()
{
$menu = Db::name('AdminRule')->where(['menu' => 1, 'status' => 1])->order('sort asc,id asc')->select()->toArray();
return $menu;
}
//读取权限节点列表
function admin_rule()
{
$rule = Db::name('AdminRule')->where(['status' => 1])->order('sort asc,id asc')->select()->toArray();
return $rule;
}
//读取权限分组列表
function admin_group()
{
$group = Db::name('AdminGroup')->order('id desc')->select()->toArray();
return $group;
}
//读取指定权限分组菜单详情
function admin_group_info($id)
{
$rule = Db::name('AdminGroup')->where(['id' => $id])->value('rules');
$rules = explode(',', $rule);
return $rules;
}
//读取公告分类列表
function admin_note_cate()
{
$cate = Db::name('NoteCate')->order('id desc')->select()->toArray();
return $cate;
}
//读取公告分类子分类ids
function admin_note_cate_son($id = 0, $is_self = 1)
{
$cate = admin_note_cate();
$cate_list = get_data_node($cate, $id);
$cate_array = array_column($cate_list, 'id');
if ($is_self == 1) {
//包括自己在内
$cate_array[] = $id;
}
return $cate_array;
}
//读取知识分类分类
function admin_knowledge_cate()
{
$cate = Db::name('KnowledgeCate')->order('id desc')->select()->toArray();
return $cate;
}
//读取知识分类子分类ids
function admin_knowledge_cate_son($id = 0, $is_self = 1)
{
$cate = admin_knowledge_cate();
$cate_list = get_data_node($cate, $id);
$cate_array = array_column($cate_list, 'id');
if ($is_self == 1) {
//包括自己在内
$cate_array[] = $id;
}
return $cate_array;
}
+69
View File
@@ -0,0 +1,69 @@
<?php
/**
* @copyright Copyright (c) 2021 勾股工作室
* @license https://opensource.org/licenses/Apache-2.0
* @link https://blog.gougucms.com
*/
declare (strict_types = 1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\ConfCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Api
// extends BaseController
{
//清空缓存
public function cache_clear()
{
\think\facade\Cache::clear();
return to_assign(0, '系统缓存已清空');
}
//发送测试邮件
public function email_to($email)
{
$name = empty(get_config('webconfig.admin_title')) ? '系统' : get_config('webconfig.admin_title');
if (send_email($email, "一封来自{$name}的测试邮件。")) {
return to_assign(0, '发送成功,请注意查收');
}
return to_assign(1, '发送失败');
}
// 测试邮件发送
public function email_test()
{
$sender = get_params('email');
//检查是否邮箱格式
if (!is_email($sender)) {
return to_assign(1, '测试邮箱码格式有误');
}
$email_config = \think\facade\Db::name('config')
->where('name', 'email')
->find();
$config = unserialize($email_config['content']);
$content = $config['template'];
print_r($content);
//所有项目必须填写
if (empty($config['smtp']) || empty($config['smtp_port']) || empty($config['smtp_user']) || empty($config['smtp_pwd'])) {
return to_assign(1, '请完善邮件配置信息!');
}
$send = send_email($sender, '测试邮件', $content);
if ($send) {
return to_assign(0, '邮件发送成功!');
} else {
return to_assign(1, '邮件发送失败!');
}
}
}
+119
View File
@@ -0,0 +1,119 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\ConfCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Conf extends BaseController
{
public function index()
{
if (request()->isAjax()) {
$param = get_params();
$where = array();
$where[] = ['status', '>=', 0];
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
$content = Db::name('Config')
->where($where)
->paginate($rows, false, ['query' => $param]);
return table_assign(0, '', $content);
} else {
return view();
}
}
//添加/编辑配置项
public function add()
{
$param = get_params();
if (request()->isPost()) {
try {
validate(ConfCheck::class)->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
if (!empty($param['id']) && $param['id'] > 0) {
$param['update_time'] = time();
$res = Db::name('config')->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param);
}
return to_assign();
} else {
$param['create_time'] = time();
$insertId = Db::name('Config')->strict(false)->field(true)->insertGetId($param);
if ($insertId) {
add_log('add', $insertId, $param);
}
return to_assign();
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
if ($id > 0) {
$config = Db::name('Config')->where(['id' => $id])->find();
View::assign('config', $config);
}
View::assign('id', $id);
return view();
}
}
//删除配置项
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$data['status'] = '-1';
$data['id'] = $id;
$data['update_time'] = time();
if (Db::name('Config')->update($data) !== false) {
add_log('delete', $id, $data);
return to_assign(0, "删除成功");
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
//编辑配置信息
public function edit()
{
$param = get_params();
if (request()->isPost()) {
$data['content'] = serialize($param);
$data['update_time'] = time();
$data['id'] = $param['id'];
$res = Db::name('Config')->strict(false)->field(true)->update($data);
$conf = Db::name('Config')->where('id', $param['id'])->find();
clear_cache('system_config' . $conf['name']);
if ($res) {
add_log('edit', $param['id'], $param);
}
return to_assign();
} else {
$id = isset($param['id']) ? $param['id'] : 0;
$conf = Db::name('Config')->where('id', $id)->find();
$config = [];
if ($conf['content']) {
$config = unserialize($conf['content']);
}
View::assign('id', $id);
View::assign('config', $config);
return view($conf['name']);
}
}
}
+223
View File
@@ -0,0 +1,223 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use backup\Backup;
use think\facade\Session;
use think\facade\Db;
use think\facade\View;
class Database extends BaseController
{
//数据表列表
public function database()
{
if (request()->isAjax()) {
// 数据信息
$db = new Backup();
$list = $db->dataList();
// 计算总大小
$total = 0;
foreach ($list as $k => $v) {
$total += $v['data_length'];
$list[$k]['data_size'] = $v['data_length'];
$list[$k]['data_length'] = format_bytes($v['data_length']);
}
// 提示信息
$dataTips = '数据库中共有<strong> ' . count($list) . '</strong> 张表,共计 <strong>' . format_bytes($total) . '</strong>大小。';
$data['data'] = $list;
return table_assign(0, $dataTips, $data);
}
return view();
}
//备份数据
public function backup()
{
$db = new Backup();
if (request()->isPost()) {
$tables = get_params('tables');
$fileinfo = $db->getFile();
//检查是否有正在执行的任务
$lock = "{$fileinfo['filepath']}backup.lock";
if (is_file($lock)) {
return to_assign(2, '检测到有一个备份任务未完成');
} else {
//创建锁文件
file_put_contents($lock, time());
}
// 检查备份目录是否可写
if (!is_writeable($fileinfo['filepath'])) {
return to_assign(1, '备份目录不存在或不可写,请检查后重试!');
}
//缓存锁文件
Session::set('lock', $lock);
//缓存备份文件信息
Session::set('backup_file', $fileinfo['file']);
//缓存要备份的表
Session::set('backup_tables', $tables);
//创建备份文件
if (false !== $db->Backup_Init()) {
return to_assign(0, '初始化成功,开始备份...', ['tab' => ['id' => 0, 'start' => 0, 'table' => $tables[0]]]);
} else {
return to_assign(1, '初始化失败,备份文件创建失败!');
}
} else if (request()->isGet()) {
$tables = Session::get('backup_tables');
$file = Session::get('backup_file');
$id = get_params('id');
$start = get_params('start');
$start = $db->setFile($file)->backup($tables[$id], $start);
if (false === $start) {
return to_assign(1, '备份出错');
} else if (0 === $start) {
if (isset($tables[++$id])) {
return to_assign(0, '备份完成', ['tab' => ['id' => $id, 'start' => 0, 'table' => $tables[$id - 1]]]);
} else { //备份完成,清空缓存
unlink(Session::get('lock'));
Session::delete('backup_tables');
Session::delete('backup_file');
add_log('bak');
return to_assign(0, '备份完成', ['tab' => ['start' => 'ok', 'table' => $tables[$id - 1]]]);
}
}
} else {
return to_assign(1, '参数错误!');
}
}
//优化表
public function optimize($tables = null)
{
$db = new Backup();
//return to_assign(0, $db->optimize($tables));
if ($db->optimize($tables)) {
add_log('optimize');
return to_assign(0, '数据表优化完成');
} else {
return to_assign(1, '数据表优化出错请重试');
}
}
//修复表
public function repair($tables = null)
{
$db = new Backup();
//return to_assign(0, $db->repair($tables));
if ($db->repair($tables)) {
add_log('repair');
return to_assign(0, '数据表修复完成');
} else {
return to_assign(1, '数据表修复出错请重试');
}
}
//备份文件列表
public function backuplist()
{
$db = new Backup();
$list = $db->fileList();
$fileinfo = $db->getFile();
$lock = "{$fileinfo['filepath']}backup.lock";
$lock_time = 0;
if (is_file($lock)) {
$lock_time = file_get_contents($lock);
}
$listNew = [];
$indx = 0;
foreach ($list as $k => $v) {
$listNew[$indx]['time'] = $k;
$listNew[$indx]['timespan'] = $v['time'];
$listNew[$indx]['data'] = $v;
$indx++;
}
$list = $listNew;
array_multisort(array_column($list, 'time'), SORT_DESC, $list);
return view('', ['list' => $list, 'lock_time' => $lock_time]);
}
//数据还原
public function import($time = 0, $part = null, $start = null)
{
$db = new Backup();
$time = (int) $time;
if (is_numeric($time) && is_null($part) && is_null($start)) {
$list = $db->getFile('timeverif', $time);
if (is_array($list)) {
Session::set('backup_list', $list);
return to_assign(0, '初始化完成,开始还原...', array('part' => 1, 'start' => 0, 'time' => $time));
} else {
return to_assign(1, '备份文件可能已经损坏,请检查');
}
} else if (is_numeric($part) && is_numeric($start)) {
$list = Session::get('backup_list');
$part = (int) $part;
$start = (int) $start;
$start = $db->setFile($list)->import($start, $time, $part);
if (false === $start) {
return to_assign(1, '还原数据出错,请重试');
} elseif (0 === $start) {
if (isset($list[++$part])) {
$data = array('part' => $part, 'start' => 0, 'time' => $time);
return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面", $data);
} else {
Session::delete('backup_list');
return to_assign(0, '还原数据成功');
}
} else {
$data = array('part' => $part, 'start' => $start[0], 'time' => $time);
if ($start[1]) {
$rate = floor(100 * ($start[0] / $start[1]));
return to_assign(0, "正在还原...卷{$part} ({$rate}%),请勿关闭当前页面", $data);
} else {
$data['gz'] = 1;
return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面", $data);
}
return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面");
}
} else {
return to_assign(1, "参数错误");
}
}
/**
* 删除备份文件
*/
public function del($time = 0, $lock = 0)
{
$db = new Backup();
if ($lock == 1) {
$fileinfo = $db->getFile();
$lock = "{$fileinfo['filepath']}backup.lock";
if (is_file($lock)) {
$time = file_get_contents($lock);
unlink($lock);
}
}
if ($db->delFile((int) $time)) {
add_log('delete');
return to_assign(0, '删除成功');
} else {
return to_assign(0, '删除失败,请检查权限');
}
}
/**
* 下载备份文件
*/
public function downfile($time = 0, $part = 0)
{
$db = new Backup();
add_log('down');
$db->downloadFile((int) $time, $part - 1);
}
}
+107
View File
@@ -0,0 +1,107 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\DepartmentCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Department extends BaseController
{
public function index()
{
if (request()->isAjax()) {
$list = Db::name('Department')
->field('d.*,a.name as leader')
->alias('d')
->join('Admin a', 'a.id = d.leader_id', 'LEFT')
->order('d.id asc')
->select();
return to_assign(0, '', $list);
} else {
return view();
}
}
//添加部门
public function add()
{
$param = get_params();
if (request()->isPost()) {
if ($param['id'] > 0) {
try {
validate(DepartmentCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['update_time'] = time();
$department_array = get_department_son($param['id']);
if (in_array($param['pid'], $department_array)) {
return to_assign(1, '上级部门不能是该部门本身或其下属部门');
} else {
Db::name('Department')->strict(false)->field(true)->update($param);
add_log('edit', $param['id'], $param);
return to_assign();
}
} else {
try {
validate(DepartmentCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$did = Db::name('Department')->strict(false)->field(true)->insertGetId($param);
add_log('add', $did, $param);
return to_assign();
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
$pid = isset($param['pid']) ? $param['pid'] : 0;
$department = set_recursion(get_department());
if ($id > 0) {
$detail = Db::name('Department')->where(['id' => $id])->find();
$users = Db::name('Admin')->where(['did' => $id, 'status' => 1])->select();
View::assign('users', $users);
View::assign('detail', $detail);
}
View::assign('department', $department);
View::assign('pid', $pid);
View::assign('id', $id);
return view();
}
}
//删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$count = Db::name('Department')->where([['pid', '=', $id], ['status', '>=', 0]])->count();
if ($count > 0) {
return to_assign(1, "该部门下还有子部门,无法删除");
}
$users = Db::name('Admin')->where([['did', '=', $id], ['status', '>=', 0]])->count();
if ($users > 0) {
return to_assign(1, "该部门下还有员工,无法删除");
}
if (Db::name('Department')->delete($id) !== false) {
add_log('delete', $id);
return to_assign(0, "删除成功");
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+117
View File
@@ -0,0 +1,117 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\KnowledgeCateCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Kcate extends BaseController
{
//知识类别
public function index()
{
if (request()->isAjax()) {
$cate = Db::name('KnowledgeCate')->order('create_time asc')->select();
return to_assign(0, '', $cate);
} else {
return view();
}
}
public function tags()
{
if (request()->isAjax()) {
$cate = Db::name('KnowledgeTags')->order('id asc')->select();
return to_assign(0, '', $cate);
} else {
return view();
}
}
//知识分类添加&编辑
public function add()
{
$param = get_params();
if (request()->isPost()) {
if (!empty($param['id']) && $param['id'] > 0) {
try {
validate(KnowledgeCateCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$cate_array = admin_knowledge_cate_son($param['id']);
if (in_array($param['pid'], $cate_array)) {
return to_assign(1, '父级分类不能是该分类本身或其子分类');
} else {
$param['update_time'] = time();
$res = Db::name('KnowledgeCate')->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param);
return to_assign();
}
}
} else {
try {
validate(KnowledgeCateCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['create_time'] = time();
$insertId = Db::name('KnowledgeCate')->strict(false)->field(true)->insertGetId($param);
if ($insertId) {
add_log('add', $insertId, $param);
}
return to_assign();
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
$pid = isset($param['pid']) ? $param['pid'] : 0;
$cate = Db::name('KnowledgeCate')->order('id desc')->select()->toArray();
$cates = set_recursion($cate);
if ($id > 0) {
$detail = Db::name('KnowledgeCate')->where(['id' => $id])->find();
View::assign('detail', $detail);
}
View::assign('id', $id);
View::assign('pid', $pid);
View::assign('cates', $cates);
return view();
}
}
//删除知识分类
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$cate_count = Db::name('KnowledgeCate')->where(["pid" => $id])->count();
if ($cate_count > 0) {
return to_assign(1, "该分类下还有子分类,无法删除");
}
$content_count = Db::name('Knowledge')->where(["cate_id" => $id])->count();
if ($content_count > 0) {
return to_assign(1, "该分类下还有文档,无法删除");
}
if (Db::name('KnowledgeCate')->delete($id) !== false) {
add_log('delete', $id);
return to_assign(0, "删除成功");
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use think\facade\Db;
use think\facade\View;
class Log extends BaseController
{
//管理员操作日志
public function index()
{
if (request()->isAjax()) {
$param = get_params();
$where = array();
if (!empty($param['keywords'])) {
$where[] = ['name|rule_menu|param_id', 'like', '%' . $param['keywords'] . '%'];
}
if (!empty($param['action'])) {
$where['action'] = $param['action'];
}
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
$content = DB::name('AdminLog')
->field("id,uid,name,action,title,content,rule_menu,ip,param_id,param,FROM_UNIXTIME(create_time,'%Y-%m-%d %H:%i:%s') create_time")
->order('create_time desc')
->where($where)
->paginate($rows, false, ['query' => $param]);
$content->toArray();
foreach ($content as $k => $v) {
$data = $v;
$param_array = json_decode($v['param'], true);
if (is_array($param_array)) {
$param_value = '';
foreach ($param_array as $key => $value) {
if (is_array($value)) {
$value = implode(',', $value);
}
$param_value .= $key . ':' . $value . '&nbsp;&nbsp;|&nbsp;&nbsp;';
}
$data['param'] = $param_value;
} else {
$data['param'] = $param_array;
}
$content->offsetSet($k, $data);
}
return table_assign(0, '', $content);
} else {
$type_action = get_config('log.type_action');
View::assign('type_action', $type_action);
return view();
}
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
/**
* @copyright Copyright (c) 2023 李志强
* @author 李志强
* @link https://www.yunzer.cn
*/
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\ConfCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
class Mail extends BaseController
{
}
?>
+107
View File
@@ -0,0 +1,107 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\NoteCateCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Ncate extends BaseController
{
//公告类别
public function index()
{
if (request()->isAjax()) {
$cate = Db::name('NoteCate')->order('create_time asc')->select();
return to_assign(0, '', $cate);
} else {
return view();
}
}
//公告类别添加
public function add()
{
$param = get_params();
if (request()->isPost()) {
if (!empty($param['id']) && $param['id'] > 0) {
try {
validate(NoteCateCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$note_array = admin_note_cate_son($param['id']);
if (in_array($param['pid'], $note_array)) {
return to_assign(1, '父级分类不能是该分类本身或其子分类');
} else {
$param['update_time'] = time();
$res = Db::name('NoteCate')->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param);
}
return to_assign();
}
} else {
try {
validate(NoteCateCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['create_time'] = time();
$insertId = Db::name('NoteCate')->strict(false)->field(true)->insertGetId($param);
if ($insertId) {
add_log('add', $insertId, $param);
}
return to_assign();
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
$pid = isset($param['pid']) ? $param['pid'] : 0;
$cate = $cate = Db::name('NoteCate')->order('id desc')->select()->toArray();
$cates = set_recursion($cate);
if ($id > 0) {
$detail = Db::name('NoteCate')->where(['id' => $id])->find();
View::assign('detail', $detail);
}
View::assign('id', $id);
View::assign('pid', $pid);
View::assign('cates', $cates);
return view();
}
}
//公告类别删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$cate_count = Db::name('NoteCate')->where(["pid" => $id])->count();
if ($cate_count > 0) {
return to_assign(1, "该分类下还有子分类,无法删除");
}
$content_count = Db::name('Note')->where(["cate_id" => $id])->count();
if ($content_count > 0) {
return to_assign(1, "该分类下还有公告,无法删除");
}
if (Db::name('NoteCate')->delete($id) !== false) {
add_log('delete', $id);
return to_assign(0, "删除成功");
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+136
View File
@@ -0,0 +1,136 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\admin\validate\NoteCheck;
use app\base\BaseController;
use app\model\Note as NoteList;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Note extends BaseController
{
public function index()
{
if (request()->isAjax()) {
$param = get_params();
$where = array();
if (!empty($param['keywords'])) {
$where[] = ['a.title|a.content', 'like', '%' . $param['keywords'] . '%'];
}
$where[] = ['a.delete_time', '=', 0];
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
$note = NoteList::where($where)
->field('a.*,c.title as cate_title')
->alias('a')
->join('NoteCate c', 'a.cate_id = c.id', 'LEFT')
->order('a.create_time desc')
->paginate($rows, false, ['query' => $param])
->each(function ($item, $key) {
$item->start_time = empty($item->start_time) ? '-' : date('Y-m-d', $item->start_time);
$item->end_time = empty($item->end_time) ? '-' : date('Y-m-d', $item->end_time);
});
return table_assign(0, '', $note);
} else {
return view();
}
}
//添加
public function add()
{
$param = get_params();
if (request()->isPost()) {
//markdown数据处理
if (isset($param['table-align'])) {
unset($param['table-align']);
}
if (isset($param['docContent-html-code'])) {
$param['content'] = $param['docContent-html-code'];
$param['md_content'] = $param['docContent-markdown-doc'];
unset($param['docContent-html-code']);
unset($param['docContent-markdown-doc']);
}
if (isset($param['ueditorcontent'])) {
$param['content'] = $param['ueditorcontent'];
$param['md_content'] = '';
}
$param['start_time'] = isset($param['start_time']) ? strtotime(urldecode($param['start_time'])) : 0;
$param['end_time'] = isset($param['end_time']) ? strtotime(urldecode($param['end_time'])) : 0;
if (!empty($param['id']) && $param['id'] > 0) {
try {
validate(NoteCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['update_time'] = time();
$res = NoteList::where('id', $param['id'])->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param);
}
return to_assign();
} else {
try {
validate(NoteCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['create_time'] = time();
$sid = NoteList::strict(false)->field(true)->insertGetId($param);
if ($sid) {
add_log('add', $sid, $param);
$users = Db::name('Admin')->where(['status' => 1])->column('id');
sendMessage($users, 1, ['title' => $param['title'], 'from_uid' => $this->uid, 'action_id' => $sid]);
}
return to_assign();
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
if ($id > 0) {
$note = Db::name('Note')->where(['id' => $id])->find();
View::assign('note', $note);
}
View::assign('id', $id);
return view();
}
}
//查看
public function view()
{
$id = empty(get_params('id')) ? 0 : get_params('id');
$note = Db::name('Note')->where(['id' => $id])->find();
View::assign('note', $note);
return view();
}
//删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$data['delete_time'] = time();
$data['id'] = $id;
if (Db::name('Note')->update($data) !== false) {
add_log('delete', $id);
return to_assign(0, "删除成功");
} else {
return to_assign(0, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+180
View File
@@ -0,0 +1,180 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\PositionCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Position extends BaseController
{
public function index()
{
if (request()->isAjax()) {
$list = Db::name('Position')->where('status', '>=', 0)->order('create_time asc')->select()->toArray();
foreach ($list as &$val) {
$groupId = Db::name('PositionGroup')->where(['pid' => $val['id']])->column('group_id');
$groupName = Db::name('AdminGroup')->where('id', 'in', $groupId)->column('title');
$val['groupName'] = implode(',', $groupName);
}
$res['data'] = $list;
return table_assign(0, '', $res);
} else {
return view();
}
}
//添加&编辑
public function add()
{
$param = get_params();
if (request()->isPost()) {
if (!empty($param['id']) && $param['id'] > 0) {
try {
validate(PositionCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
// 启动事务
Db::startTrans();
try {
Db::name('Position')->where(['id' => $param['id']])->strict(false)->field(true)->update($param);
Db::name('PositionGroup')->where(['pid' => $param['id']])->delete();
foreach ($param['group_id'] as $k => $v) {
$data[$k] = [
'pid' => $param['id'],
'group_id' => $v,
'create_time' => time(),
];
}
Db::name('PositionGroup')->strict(false)->field(true)->insertAll($data);
add_log('edit', $param['id'], $param);
//清除菜单\权限缓存
clear_cache('adminMenu');
clear_cache('adminRules');
// 提交事务
Db::commit();
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
return to_assign(1, '提交失败:' . $e->getMessage());
}
} else {
try {
validate(PositionCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
// 启动事务
Db::startTrans();
try {
$uid = Db::name('Position')->strict(false)->field(true)->insertGetId($param);
foreach ($param['group_id'] as $k => $v) {
$data[$k] = [
'pid' => $uid,
'group_id' => $v,
'create_time' => time(),
];
}
Db::name('PositionGroup')->strict(false)->field(true)->insertAll($data);
add_log('add', $uid, $param);
// 提交事务
Db::commit();
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
return to_assign(1, '提交失败:' . $e->getMessage());
}
}
return to_assign();
} else {
$id = isset($param['id']) ? $param['id'] : 0;
$group = Db::name('AdminGroup')->order('create_time asc')->select()->toArray();
if ($id > 0) {
$detail = Db::name('Position')->where(['id' => $id])->find();
$detail['group_id'] = Db::name('PositionGroup')->where(['pid' => $id])->column('group_id');
foreach ($group as &$val) {
if (in_array($val['id'], $detail['group_id'])) {
$val['checked'] = 1;
} else {
$val['checked'] = 0;
}
}
View::assign('detail', $detail);
}
View::assign('group', $group);
View::assign('id', $id);
return view();
}
}
//查看
public function view()
{
$id = get_params('id');
$group = Db::name('AdminGroup')->order('create_time asc')->select()->toArray();
$detail = Db::name('Position')->where(['id' => $id])->find();
$detail['group_id'] = Db::name('PositionGroup')->where(['pid' => $id])->column('group_id');
foreach ($group as &$val) {
if (in_array($val['id'], $detail['group_id'])) {
$val['checked'] = 1;
} else {
$val['checked'] = 0;
}
}
$rule = Db::name('AdminRule')->order('sort asc,id asc')->select()->toArray();
$user_groups = Db::name('PositionGroup')
->alias('a')
->join("AdminGroup g", "a.group_id=g.id", 'LEFT')
->where("a.pid='{$id}' and g.status='1'")
->select()
->toArray();
$groups = $user_groups ?: [];
$rules = [];
foreach ($groups as $g) {
$rules = array_merge($rules, explode(',', trim($g['rules'], ',')));
}
$rules = array_unique($rules);
$role_rule = create_tree_list(0, $rule, $rules);
View::assign('role_rule', $role_rule);
View::assign('detail', $detail);
View::assign('group', $group);
add_log('view', $id);
return view();
}
//删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
if ($id == 1) {
return to_assign(0, "超级岗位,不能删除");
}
$data['status'] = '-1';
$data['id'] = $id;
$data['update_time'] = time();
if (Db::name('Position')->update($data) !== false) {
add_log('delete', $id);
return to_assign(0, "删除成功");
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+107
View File
@@ -0,0 +1,107 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\model\AdminGroup;
use app\admin\validate\GroupCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Role extends BaseController
{
public function index()
{
if (request()->isAjax()) {
$param = get_params();
$where = array();
if (!empty($param['keywords'])) {
$where[] = ['id|title|desc', 'like', '%' . $param['keywords'] . '%'];
}
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
$group = AdminGroup::where($where)
->order('create_time asc')
->paginate($rows, false, ['query' => $param]);
return table_assign(0, '', $group);
} else {
return view();
}
}
//添加&编辑
public function add()
{
$param = get_params();
if (request()->isPost()) {
$ruleData = isset($param['rule']) ? $param['rule'] : 0;
$param['rules'] = implode(',', $ruleData);
if (!empty($param['id']) && $param['id'] > 0) {
try {
validate(GroupCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
//为了系统安全id为1的系统所有者管理组不允许修改
if ($param['id'] == 1) {
return to_assign(1, '为了系统安全,该管理组不允许修改');
}
Db::name('AdminGroup')->where(['id' => $param['id']])->strict(false)->field(true)->update($param);
add_log('edit', $param['id'], $param);
} else {
try {
validate(GroupCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$gid = Db::name('AdminGroup')->strict(false)->field(true)->insertGetId($param);
add_log('add', $gid, $param);
}
//清除菜单\权限缓存
clear_cache('adminMenu');
return to_assign();
} else {
$id = isset($param['id']) ? $param['id'] : 0;
$rule = admin_rule();
if ($id > 0) {
$rules = admin_group_info($id);
$role_rule = create_tree_list(0, $rule, $rules);
$role = Db::name('AdminGroup')->where(['id' => $id])->find();
View::assign('role', $role);
} else {
$role_rule = create_tree_list(0, $rule, []);
}
View::assign('role_rule', $role_rule);
View::assign('id', $id);
return view();
}
}
//删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
if ($id == 1) {
return to_assign(1, "该组是系统所有者,无法删除");
}
if (Db::name('AdminGroup')->delete($id) !== false) {
add_log('delete', $id, []);
return to_assign(0, "删除成功");
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+106
View File
@@ -0,0 +1,106 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\RuleCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Rule extends BaseController
{
public function index()
{
if (request()->isAjax()) {
$rule = Db::name('adminRule')->order('sort asc,id asc')->select();
return to_assign(0, '', $rule);
} else {
return view();
}
}
//添加
public function add()
{
$param = get_params();
if (request()->isPost()) {
$param['src'] = preg_replace('# #', '', $param['src']);
if ($param['id'] > 0) {
try {
validate(RuleCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
Db::name('AdminRule')->strict(false)->field(true)->update($param);
add_log('edit', $param['id'], $param);
} else {
try {
validate(RuleCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['create_time'] = time();
$rid = Db::name('AdminRule')->strict(false)->field(true)->insertGetId($param);
//自动为系统所有者管理组分配新增的节点
// $groups = Db::name('AdminGroup')->select();
// if (!empty($group)) {
// $newGroup['id'] = 1;
// $newGroup['rules'] = $group['rules'] . ',' . $rid;
// Db::name('AdminGroup')->strict(false)->field(true)->update($newGroup);
// add_log('add', $rid, $param);
// }
//自动为系统所有人分配新增的节点
$groups = Db::name('AdminGroup')->select();
foreach ($groups as $group) {
$newGroup['id'] = $group['id'];
$newGroup['rules'] = $group['rules'] . ',' . $rid;
Db::name('AdminGroup')->strict(false)->field(true)->update($newGroup);
}
add_log('add', $rid, $param);
}
// 删除后台节点缓存
clear_cache('adminRules');
return to_assign();
} else {
$id = isset($param['id']) ? $param['id'] : 0;
$pid = isset($param['pid']) ? $param['pid'] : 0;
if ($id > 0) {
$detail = Db::name('AdminRule')->where('id', $id)->find();
View::assign('detail', $detail);
}
View::assign('id', $id);
View::assign('pid', $pid);
return view();
}
}
//删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$count = Db::name('AdminRule')->where(["pid" => $id])->count();
if ($count > 0) {
return to_assign(1, "该节点下还有子菜单,无法删除");
}
if (Db::name('AdminRule')->delete($id) !== false) {
clear_cache('adminRules');
add_log('delete', $id, []);
return to_assign(0, "删除成功");
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+40
View File
@@ -0,0 +1,40 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use think\facade\Db;
use think\facade\View;
class Setting extends BaseController
{
public function index()
{
$install = false;
if (file_exists(CMS_ROOT . 'app/install')) {
$install = true;
}
View::assign('install', $install);
$conf = Db::name('Config')->where('id', 1)->find();
$config = [];
if ($conf['content']) {
$config = unserialize($conf['content']);
}
View::assign('config', $config);
View::assign('TP_VERSION', \think\facade\App::version());
return View();
}
public function errorShow()
{
echo '错误';
}
}
+88
View File
@@ -0,0 +1,88 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\TaskCateCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Tcate extends BaseController
{
//任务类别
public function index()
{
if (request()->isAjax()) {
$cate = Db::name('TaskCate')->order('sort desc')->select();
return to_assign(0, '', $cate);
} else {
return view();
}
}
//任务类别添加
public function add()
{
if (request()->isPost()) {
$param = get_params();
if (!empty($param['id']) && $param['id'] > 0) {
try {
validate(TaskCateCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$data['update_time'] = time();
$res = Db::name('TaskCate')->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param);
}
return to_assign();
} else {
try {
validate(TaskCateCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['create_time'] = time();
$insertId = Db::name('TaskCate')->strict(false)->field(true)->insertGetId($param);
if ($insertId) {
add_log('add', $insertId, $param);
}
return to_assign();
}
}
}
//任务类别设置
public function check()
{
if (request()->isPost()) {
$param = get_params();
$res = Db::name('TaskCate')->strict(false)->field('id,status')->update($param);
if ($res) {
if ($param['status'] == 0) {
add_log('disable', $param['id'], $param);
} else if ($param['status'] == 1) {
add_log('recover', $param['id'], $param);
}
return to_assign();
} else {
return to_assign(0, '操作失败');
}
} else {
return to_assign(0, '错误的请求');
}
}
}
+346
View File
@@ -0,0 +1,346 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\model\Admin as AdminList;
use app\admin\validate\AdminCheck;
use avatars\MDAvatars;
use Overtrue\Pinyin\Pinyin;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class User extends BaseController
{
public function index()
{
if (request()->isAjax()) {
$param = get_params();
$where = array();
if (!empty($param['keywords'])) {
$where[] = ['id|username|name|nickname|mobile|desc', 'like', '%' . $param['keywords'] . '%'];
}
$where[] = ['status', '<', 2];
if (isset($param['status']) && $param['status'] != '') {
$where[] = ['status', '=', $param['status']];
}
if (!empty($param['type'])) {
$where[] = ['type', '=', $param['type']];
}
if (!empty($param['did'])) {
$department_array = get_department_son($param['did']);
$where[] = ['did', 'in', $department_array];
}
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
$admin = AdminList::where($where)
->order('id desc')
->paginate($rows, false, ['query' => $param])
->each(function ($item, $key) {
$item->department = Db::name('Department')->where(['id' => $item->did])->value('title');
$item->position = Db::name('Position')->where(['id' => $item->position_id])->value('title');
$item->entry_time = empty($item->entry_time) ? '-' : date('Y-m-d', $item->entry_time);
$item->last_login_time = empty($item->last_login_time) ? '-' : date('Y-m-d H:i', $item->last_login_time);
$item->last_login_ip = empty($item->last_login_ip) ? '-' : $item->last_login_ip;
});
return table_assign(0, '', $admin);
} else {
return view();
}
}
//添加
public function add()
{
$param = get_params();
if (request()->isPost()) {
$param['entry_time'] = strtotime($param['entry_time']);
$param['nickname'] = $param['name'];
$pinyin = new Pinyin();
$username = $pinyin->name($param['name'], PINYIN_UMLAUT_V);
$param['username'] = implode('', $username);
if (!empty($param['id']) && $param['id'] > 0) {
$count = Db::name('Admin')->where([['username', 'like', $param['username'] . '%'], ['id', '<>', $param['id']]])->count();
if ($count > 0) {
$param['username'] = implode('', $username) . $count;
}
try {
validate(AdminCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
// 启动事务
Db::startTrans();
try {
Db::name('Admin')->where(['id' => $param['id']])->strict(false)->field(true)->update($param);
if (!isset($param['thumb']) || $param['thumb'] == '') {
$char = mb_substr($param['name'], 0, 1, 'utf-8');
Db::name('Admin')->where('id', $param['id'])->update(['thumb' => $this->to_avatars($char)]);
}
add_log('edit', $param['id'], $param);
//清除菜单\权限缓存
clear_cache('adminMenu');
// 提交事务
Db::commit();
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
return to_assign(1, '提交失败:' . $e->getMessage());
}
} else {
$count = Db::name('Admin')->where([['username', 'like', $param['username'] . '%']])->count();
if ($count > 0) {
$param['username'] = implode('', $username) . $count;
}
try {
validate(AdminCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['salt'] = set_salt(20);
$param['pwd'] = set_password($param['reg_pwd'], $param['salt']);
// 启动事务
Db::startTrans();
try {
$uid = Db::name('Admin')->strict(false)->field(true)->insertGetId($param);
if (!isset($param['thumb']) || $param['thumb'] == '') {
$char = mb_substr($param['name'], 0, 1, 'utf-8');
Db::name('Admin')->where('id', $uid)->update(['thumb' => $this->to_avatars($char)]);
}
add_log('add', $uid, $param);
// 提交事务
Db::commit();
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
return to_assign(1, '提交失败:' . $e->getMessage());
}
}
return to_assign();
} else {
$id = isset($param['id']) ? $param['id'] : 0;
$department = set_recursion(get_department());
$position = Db::name('Position')->where('status', '>=', 0)->order('create_time asc')->select();
if ($id > 0) {
$detail = get_admin($id);
View::assign('detail', $detail);
} else {
//初始化密码
$reg_pwd = set_salt(6);
View::assign('reg_pwd', $reg_pwd);
}
View::assign('department', $department);
View::assign('position', $position);
View::assign('id', $id);
return view();
}
}
//生成头像
public function to_avatars($char)
{
$defaultData = array(
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'S',
'Y',
'Z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'零',
'壹',
'贰',
'叁',
'肆',
'伍',
'陆',
'柒',
'捌',
'玖',
'拾',
'一',
'二',
'三',
'四',
'五',
'六',
'七',
'八',
'九',
'十'
);
if (isset($char)) {
$Char = $char;
} else {
$Char = $defaultData[mt_rand(0, count($defaultData) - 1)];
}
$OutputSize = min(512, empty($_GET['size']) ? 36 : intval($_GET['size']));
$Avatar = new MDAvatars($Char, 256, 1);
$avatar_name = '/avatars/avatar_256_' . set_salt(10) . time() . '.png';
$path = get_config('filesystem.disks.public.url') . $avatar_name;
$res = $Avatar->Save('.' . $path, 256);
$Avatar->Free();
return $path;
}
//查看
public function view()
{
$id = get_params('id');
$detail = get_admin($id);
//查询所有菜单和权限节点
$menu = Db::name('AdminRule')->where(['menu' => 1])->order('sort asc,id asc')->select()->toArray();
$rule = Db::name('AdminRule')->order('sort asc,id asc')->select()->toArray();
//查询用户拥有的查单和节点
$user_groups = Db::name('PositionGroup')
->alias('a')
->join("AdminGroup g", "a.group_id=g.id", 'LEFT')
->where([['a.pid', '=', $detail["position_id"]], ['g.status', '=', 1]])
->select()
->toArray();
$groups = $user_groups ?: [];
$rules = [];
foreach ($groups as $g) {
$rules = array_merge($rules, explode(',', trim($g['rules'], ',')));
}
$rules = array_unique($rules);
//数据嵌套
$role_rule = create_tree_list(0, $rule, $rules);
View::assign('role_rule', $role_rule);
View::assign('detail', $detail);
add_log('view', get_params('id'));
return view();
}
//禁用,恢复
public function set()
{
if (request()->isPost()) {
$type = get_params("type");
$ids = get_params("ids");
$idArray = explode(',', $ids);
$list = [];
foreach ($idArray as $key => $val) {
if ($val == 1) {
continue;
}
$list[] = [
'status' => $type,
'id' => $val,
'update_time' => time(),
];
}
foreach ($list as $key => $v) {
if (Db::name('Admin')->update($v) !== false) {
if ($type == 0) {
add_log('disable', $v['id']);
} else if ($type == 1) {
add_log('recover', $v['id']);
}
}
}
return to_assign(0, '操作成功');
} else {
return to_assign(1, "错误的请求");
}
}
//重置密码
public function reset()
{
if (request()->isPost()) {
$id = get_params("id");
if ($id == 1) {
return to_assign(1, '该账号是超级管理员,不允许重置');
}
$new_pwd = set_salt(6);
$salt = set_salt(20);
$data = [
'reg_pwd' => $new_pwd,
'salt' => $salt,
'pwd' => set_password($new_pwd, $salt),
'id' => $id,
'update_time' => time(),
];
if (Db::name('Admin')->update($data) !== false) {
add_log('reset', $id);
return to_assign(0, '操作成功');
} else {
return to_assign(1, '操作失败');
}
} else {
return to_assign(1, "错误的请求");
}
}
//获取员工数据
public function getuserinfo() {
try {
// 查询数据
$list = Db::name('Admin')
->field('id, nickname') // 选择所需字段
->where('status', 1) // 增加条件,status 值为 1
->order('id desc') // 按 id 倒序排序
->select(); // 获取数据
// 返回成功响应
return json([
'code' => 1, // 成功状态码
'msg' => '获取成功', // 提示信息
'data' => $list // 数据展示
]);
} catch (\Exception $e) {
// 捕获异常并返回错误信息
return json([
'code' => 0, // 失败状态码
'msg' => '获取失败: ' . $e->getMessage(), // 错误信息
'data' => [] // 空数据
]);
}
}
}
+88
View File
@@ -0,0 +1,88 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\admin\controller;
use app\base\BaseController;
use app\admin\validate\WorkCateCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
class Wcate extends BaseController
{
//工作类别
public function index()
{
if (request()->isAjax()) {
$cate = Db::name('WorkCate')->order('id asc')->select();
return to_assign(0, '', $cate);
} else {
return view();
}
}
//工作类别添加
public function add()
{
if (request()->isPost()) {
$param = get_params();
if (!empty($param['id']) && $param['id'] > 0) {
try {
validate(WorkCateCheck::class)->scene('edit')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$data['update_time'] = time();
$res = Db::name('WorkCate')->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param);
}
return to_assign();
} else {
try {
validate(WorkCateCheck::class)->scene('add')->check($param);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return to_assign(1, $e->getError());
}
$param['create_time'] = time();
$insertId = Db::name('WorkCate')->strict(false)->field(true)->insertGetId($param);
if ($insertId) {
add_log('add', $insertId, $param);
}
return to_assign();
}
}
}
//工作类别设置
public function check()
{
if (request()->isPost()) {
$param = get_params();
$res = Db::name('WorkCate')->strict(false)->field('id,status')->update($param);
if ($res) {
if ($param['status'] == 0) {
add_log('disable', $param['id'], $param);
} else if ($param['status'] == 1) {
add_log('recover', $param['id'], $param);
}
return to_assign();
} else {
return to_assign(0, '操作失败');
}
} else {
return to_assign(0, '错误的请求');
}
}
}
+5
View File
@@ -0,0 +1,5 @@
<?php
// 这是系统自动生成的event定义文件
return [
];
+13
View File
@@ -0,0 +1,13 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
// 这是系统自动生成的middleware定义文件
return [
//开启session中间件
//'think\middleware\SessionInit',
\app\home\middleware\Install::class,
];
+22
View File
@@ -0,0 +1,22 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\home\middleware;
class Install
{
public function handle($request, \Closure $next)
{
if (!is_installed()) {
return $request->isAjax() ? to_assign(1, '请先完成系统安装引导') : redirect((string) url('/install/index'));
}
return $next($request);
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class AdminCheck extends Validate
{
protected $regex = ['checkUser' => '/^[A-Za-z]{1}[A-Za-z0-9_-]{4,19}$/'];
protected $rule = [
'name' => 'require|chs',
'username' => 'require|regex:checkUser|unique:admin',
'mobile' => 'require|mobile|unique:admin',
'reg_pwd' => 'require|min:6',
'did' => 'require',
'position_id' => 'require',
'type' => 'require',
'entry_time' => 'require',
'id' => 'require',
'pwd' => 'require|min:6|confirm',
'status' => 'require|checkStatus:-1,1',
'old_pwd' => 'require|different:pwd',
];
protected $message = [
'name.require' => '员工姓名不能为空',
'name.chs' => '员工姓名只能是汉字',
'username.require' => '登录账号不能为空',
'username.regex' => '登录账号必须是以字母开头,只能包含字母数字下划线和减号,5到20位',
'username.unique' => '同样的登录账号已经存在,建议增加数字,如:xxx123',
'mobile.require' => '手机不能为空',
'mobile.mobile' => '手机格式错误',
'mobile.unique' => '同样的手机号码已经存在,请检查一下是否被离职或者禁用员工占用',
'reg_pwd.require' => '密码不能为空',
'reg_pwd.min' => '密码至少要6个字符',
'did.require' => '请选择所在部门',
'position_id.require' => '请选择职位',
'type.require' => '请选择员工类型',
'entry_time.require' => '请选择入职时间',
'id.require' => '缺少更新条件',
'pwd.require' => '密码不能为空',
'pwd.min' => '密码至少要6个字符',
'pwd.confirm' => '两次密码不一致',
'old_pwd.require' => '请提供旧密码',
'old_pwd.different' => '新密码不能和旧密码一样',
];
protected $scene = [
'add' => ['name', 'username', 'mobile', 'reg_pwd', 'did', 'position_id', 'type', 'entry_time'],
'edit' => ['name', 'username', 'mobile', 'did', 'position_id', 'entry_time', 'id'],
'editPwd' => ['old_pwd', 'pwd'],
];
}
+27
View File
@@ -0,0 +1,27 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class ConfCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:config',
'name' => 'require|lower|min:3|unique:config',
];
protected $message = [
'title.require' => '配置名称不能为空',
'title.unique' => '同样的配置名称已经存在',
'name.require' => '配置标识不能为空',
'name.lower' => '配置标识只能是小写字母',
'name.min' => '配置标识至少需要2个小写字母',
'name.unique' => '同样的配置标识已经存在',
];
}
+29
View File
@@ -0,0 +1,29 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class DepartmentCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:department',
'id' => 'require',
];
protected $message = [
'title.require' => '部门名称不能为空',
'title.unique' => '同样的部门名称已经存在',
'id.require' => '缺少更新条件',
];
protected $scene = [
'add' => ['title'],
'edit' => ['id', 'title'],
];
}
+41
View File
@@ -0,0 +1,41 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class GroupCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:admin_group',
'id' => 'require',
'status' => 'require|checkStatus:-1,1',
];
protected $message = [
'title.require' => '名称不能为空',
'title.unique' => '同样的记录已经存在',
'id.require' => '缺少更新条件',
'status.require' => '状态为必选',
'status.checkStatus' => '系统所有者组不能被禁用',
];
protected $scene = [
'add' => ['title', 'status'],
'edit' => ['id', 'title', 'status'],
];
// 自定义验证规则
protected function checkStatus($value, $rule, $data)
{
if ($value == -1 and $data['id'] == 1) {
return $rule == false;
}
return $rule == true;
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class KnowledgeCateCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:knowledge_cate',
'id' => 'require',
];
protected $message = [
'title.require' => '名称不能为空',
'title.unique' => '同样的名称已经存在',
'id.require' => '缺少更新条件',
];
protected $scene = [
'add' => ['title'],
'edit' => ['id', 'title'],
];
}
+29
View File
@@ -0,0 +1,29 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class NoteCateCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:note_cate',
'id' => 'require',
];
protected $message = [
'title.require' => '名称不能为空',
'title.unique' => '同样的名称已经存在',
'id.require' => '缺少更新条件',
];
protected $scene = [
'add' => ['title'],
'edit' => ['id', 'title'],
];
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace app\admin\validate;
use think\Validate;
class NoteCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:note',
'id' => 'require',
'status' => 'require'
];
protected $message = [
'title.require' => '标题不能为空',
'title.unique' => '同样的记录已经存在!',
'id.require' => '缺少更新条件',
'status.require' => '状态为必选',
];
protected $scene = [
'add' => ['title'],
'edit' => ['id', 'title']
];
}
+34
View File
@@ -0,0 +1,34 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class PositionCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:position',
'work_price' => 'require|number',
'group_id' => 'require',
'id' => 'require'
];
protected $message = [
'title.require' => '岗位名称不能为空',
'title.unique' => '同样的岗位名称已经存在',
'work_price.require' => '岗位工时单价不能为空',
'work_price.number' => '岗位工时单价只能是整数',
'group_id.require' => '至少要选择一个角色权限',
'id.require' => '缺少更新条件',
];
protected $scene = [
'add' => ['title', 'work_price', 'group_id'],
'edit' => ['title', 'work_price', 'group_id', 'id'],
];
}
+34
View File
@@ -0,0 +1,34 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class RuleCheck extends Validate
{
protected $rule = [
'title' => 'require',
'name' => 'require',
'menu' => 'require',
'src' => 'unique:admin_rule',
'id' => 'require',
];
protected $message = [
'title.require' => '菜单节点名称不能为空',
'src.unique' => '同样的菜单节点URL已经存在',
'menu.require' => '是否是左侧菜单需要选择',
'name.require' => '节点日志操作名称不能为空',
'id.require' => '缺少更新条件'
];
protected $scene = [
'add' => ['title', 'src', 'name', 'menu'],
'edit' => ['id', 'title', 'src', 'name', 'menu']
];
}
+29
View File
@@ -0,0 +1,29 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class TaskCateCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:task_cate',
'id' => 'require',
];
protected $message = [
'title.require' => '名称不能为空',
'title.unique' => '同样的名称已经存在',
'id.require' => '缺少更新条件',
];
protected $scene = [
'add' => ['title'],
'edit' => ['id', 'title'],
];
}
+29
View File
@@ -0,0 +1,29 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
namespace app\admin\validate;
use think\Validate;
class WorkCateCheck extends Validate
{
protected $rule = [
'title' => 'require|unique:work_cate',
'id' => 'require',
];
protected $message = [
'title.require' => '名称不能为空',
'title.unique' => '同样的名称已经存在',
'id.require' => '缺少更新条件',
];
protected $scene = [
'add' => ['title'],
'edit' => ['id', 'title'],
];
}
+64
View File
@@ -0,0 +1,64 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">配置项</h3>
<table class="layui-table">
<tr>
<td class="layui-td-gray">配置名称<font>*</font>
</td>
<td>
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入配置名称" lay-reqText="请输入配置名称" class="layui-input" {notempty name="$config.title"} value="{$config.title}" {/notempty}>
</td>
<td class="layui-td-gray">状态<font>*</font></td>
<td>{if condition="$id eq 0"}
<input type="radio" name="status" value="1" title="正常" checked>
<input type="radio" name="status" value="0" title="禁用">
{else/}
<input type="radio" name="status" value="1" title="正常" {eq name="$config.status" value="1"
}checked{/eq}>
<input type="radio" name="status" value="0" title="禁用" {eq name="$config.status" value="0"
}checked{/eq}>
{/if}
</td>
</tr>
<tr>
<td class="layui-td-gray">
配置标识<font>*</font>
</td>
<td colspan="3">
<input type="text" name="name" lay-verify="required" placeholder="请输入配置标识" lay-reqText="请输入配置标识" autocomplete="off" class="layui-input" {notempty name="$config.name"} value="{$config.name}" {/notempty}>
</td>
</tr>
<tr>
<td class="layui-td-gray" style="vertical-align: top;">
注意
</td>
<td colspan="3">
<span style ="color: red; font-size: 12px;">(注意:新增配置项以后,需要对应新增模板文件,模板文件名称需与标识名称一致,建议复制现有的配置模板文件,然后根据需求修改对应的表单即可)</span>
</td>
</tr>
</table>
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}" />
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/admin/conf/add",data.field,callback);
return false;
});
}
</script>
+121
View File
@@ -0,0 +1,121 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">邮箱配置</h3>
<table class="layui-table">
<tr>
<td class="layui-td-gray-2">SMTP地址<font>*</font>
</td>
<td>
<input type="text" name="smtp" lay-verify="required" autocomplete="off" placeholder="请输入SMTP服务器地址" lay-reqText="请输入SMTP服务器地址" class="layui-input" {notempty name="$config.smtp"} value="{$config.smtp}" {/notempty} style="width:240px;display: inline-block;">
<span style="color:#999; font-size:12px;">如:QQ邮箱的SMTP服务器地址是smtp.qq.com163邮箱的SMTP服务器地址是smtp.163.com</span>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">协议端口号<font>*</font>
</td>
<td>
<input type="text" name="smtp_port" lay-verify="required" autocomplete="off" placeholder="请输入端口" lay-reqText="请输入端口" class="layui-input" {notempty name="$config.smtp_port"} value="{$config.smtp_port}" {/notempty} style="width:240px;display: inline-block;">
<span style="color:#999; font-size:12px;">如:QQ邮箱的ssl协议方式端口号是465/587,163邮箱的ssl协议方式端口号是465/994</span>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">邮箱账户<font>*</font>
</td>
<td>
<input type="text" name="smtp_user" autocomplete="off" lay-verify="required" placeholder="请输入邮箱用户名" lay-reqText="请输入邮箱用户名" class="layui-input" {notempty name="$config.smtp_user"} value="{$config.smtp_user}" {/notempty} style="width:240px;display: inline-block;">
<span style="color:#999; font-size:12px;">如:gougucms@qq.com</span>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">邮箱密码<font>*</font>
</td>
<td>
<input type="password" name="smtp_pwd" lay-verify="required" autocomplete="off" placeholder="请输入邮箱密码"
class="layui-input" {notempty name="$config.smtp_pwd"} value="{$config.smtp_pwd}" {/notempty} style="width:240px;display: inline-block;">
<span style="color:#999; font-size:12px;">
不一定是登录密码,如QQ邮箱的是第三方授权登录码,要自己去开启,在邮箱的设置->账户->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务</span>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">发送人<font>*</font>
</td>
<td>
<input type="text" name="from" autocomplete="off" lay-verify="required" placeholder="请输入要显示的发送者" lay-reqText="请输入要显示的发送者"
class="layui-input" {notempty name="$config.from"} value="{$config.from}" {/notempty} style="width:240px; display: inline-block;">
<span style="color:#999; font-size:12px;">用于展示给发送方,如:勾股CMS系统管理员</span>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">显示的邮箱<font>*</font>
</td>
<td>
<input type="text" name="email" lay-verify="required" autocomplete="off" placeholder="请输入要显示的发送者邮箱" lay-reqText="请输入要显示的发送者邮箱"
class="layui-input" {notempty name="$config.email"} value="{$config.email}" {/notempty} style="width:240px;display: inline-block;">
<span style="color:#999;font-size:12px;">可以不同于上面的账户,用于展示给发送方的邮箱,如:admin@gougucms.com</span>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">邮件内容</td>
<td>
<textarea class="layui-textarea" name="template">{notempty name="$config.template"}{$config.template}{/notempty}</textarea>
</td>
</tr>
</table>
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button lay-event="email" class="layui-btn">发送测试</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/admin/conf/edit",data.field,callback);
return false;
});
$('.page-content').on('click', '[lay-event="email"]', function () {
layer.prompt({
formType: 0,
value: '',
title: '输入接收测试邮件的邮箱',
id: 'email_to'
}, function (value, index, elem) {
var isEmail = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
if (value.length < 6 || !(isEmail.test(value))) {
layer.tips('请正确输入邮箱', elem);
return false;
}
$.ajax({
url: "/admin/api/email_test",
data: { email: value },
type: "post",
beforeSend: function () {
// 禁用按钮防止重复提交
$("#email_to input").val('');
},
success: function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layer.close(index);
}
}
})
});
return false;
})
}
</script>
+106
View File
@@ -0,0 +1,106 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>系统配置</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add-conf">+ 添加配置项</button>
</div>
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
</div>
<script type="text/html" id="status">
<i class="layui-icon {{# if(d.status == 1){ }}layui-icon-ok{{# } else { }}layui-icon-close{{# } }}"></i>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
var table = layui.table,
tool = layui.tool,
form = layui.form;
layui.pageTable = table.render({
elem: '#test',
title: '配置列表',
url: "/admin/conf/index",
page: true, //开启分页
limit: 20,
cols: [
[{
field: 'id',
width: 80,
title: 'ID编号',
align: 'center'
},{
field: 'title',
width: 200,
title: '配置名称'
}, {
field: 'name',
title: '配置标识(新增的模板文件名称需与标识名称一致)'
},{
field: 'status',
width: 80,
title: '状态',
templet: '#status',
align: 'center'
}, {
width: 160,
title: '操作',
align: 'center',
templet: function (d) {
var html = '<div class="layui-btn-group"><button class="layui-btn layui-btn-xs" lay-event="add">修改</button><button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit" >编辑配置</button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</button></div>';
return html;
}
}]
]
});
//表头工具栏事件
$('.add-conf').on('click', function(){
tool.open('/admin/conf/add');
});
//监听行工具事件
table.on('tool(test)', function(obj){
var data = obj.data;
if(obj.event === 'add'){
tool.open('/admin/conf/add?id='+data.id);
}
if(obj.event === 'edit'){
tool.open('/admin/conf/edit?id='+data.id);
}
if (obj.event === 'del') {
layer.confirm('确定要删除吗?', {
icon: 3,
title: '提示'
}, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete('/admin/conf/delete',{ id: obj.data.id },callback);
layer.close(index);
});
}
return;
});
}
</script>
{/block}
<!-- /脚本 -->
+41
View File
@@ -0,0 +1,41 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">其他配置</h3>
<table class="layui-table">
<tr>
<td class="layui-td-gray">开发者</td>
<td>
<input type="text" name="author" autocomplete="off" placeholder="请输入开发者" lay-reqText="请输入开发者" class="layui-input"{notempty name="$config.author"} value="{$config.author}" {/notempty}>
</td>
<td class="layui-td-gray-2">开发版本号
</td>
<td>
<input type="text" name="version" autocomplete="off" placeholder="请输入版本号" lay-reqText="请输入版本号" class="layui-input" {notempty name="$config.version"} value="{$config.version}" {/notempty}>
</td>
</tr>
</table>
<div style="padding: 10px 0">
<input type="hidden" value="{$id}" name="id">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/admin/conf/edit",data.field,callback);
return false;
});
}
</script>
+121
View File
@@ -0,0 +1,121 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">Token配置</h3>
<table class="layui-table">
<tr>
<td class="layui-td-gray-2">Token签发组织</td>
<td>
<input type="text" name="iss" autocomplete="off" placeholder="请输入签发组织" lay-reqText="请输入签发组织" class="layui-input"{notempty name="$config.iss"} value="{$config.iss}" {/notempty}>
</td>
<td class="layui-td-gray-2">Token签发作者
</td>
<td>
<input type="text" name="aud" autocomplete="off" placeholder="请输入签发作者" lay-reqText="请输入签发作者" class="layui-input" {notempty name="$config.aud"} value="{$config.aud}" {/notempty}>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">Token Secrect</td>
<td>
<input type="text" name="secrect" autocomplete="off" placeholder="请输入secrect" lay-reqText="请输入secrect" class="layui-input"{notempty name="$config.secrect"} value="{$config.secrect}" {/notempty}>
</td>
<td class="layui-td-gray-2">Token过期时间
</td>
<td>
<input type="text" name="exptime" autocomplete="off" placeholder="请输入过期时间" lay-reqText="请输入过期时间" class="layui-input" {notempty name="$config.exptime"} value="{$config.exptime}" {/notempty}>
</td>
</tr>
</table>
<div style="padding:20px 0;">
<span class="layui-btn layui-btn-sm" onclick="testLogin();">Api测试登录</span>
<span class="layui-btn layui-btn-sm" onclick="testToken();">Token测试</span>
</div>
<div style="padding:20px; background-color:#f2f2f2;word-wrap:break-word">
测试结果:
<div id="res"></div>
</div>
<div style="padding: 20px 0">
<input type="hidden" value="{$id}" name="id">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/admin/conf/edit",data.field,callback);
return false;
});
}
var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZ291Z3VjbXMuY29tIiwiYXVkIjoiZ291Z3VjbXMiLCJpYXQiOjE2MjczMTY1MTgsImV4cCI6MTYyNzMyMDExOCwidWlkIjoxfQ.3soLDbwrEqn4EZtpD4h05FmvmMtJEh1LtE1vZ_ANcnI';
function testToken(){
$.ajax({
headers: {
Token: token
},
url: "/admin/api/index/demo",
type: "get",
success: function (res) {
$('#res').html(JSON.stringify(res));
if(res.code == 111){
layer.msg(res.msg);
}
}
});
}
function testLogin(){
var content='<form class="layui-form" style="width:400px"><div style="padding:10px 15px">\
<p style="padding:10px 0">用户名:</p>\
<p><input name="username" type="text" class="layui-input" value="hdm58"/></p>\
<p style="padding:10px 0">密 码:</p>\
<p><input name="password" type="password" class="layui-input" value="123456"/></p>\
</div>\
</form>';
layer.open({
type:1,
title:'API测试用户登录',
area:['432px','300px'],
content:content,
btnAlign: 'c',
btn: ['登录'],
yes: function(idx){
var username = $('[name="username"]').val();
var password = $('[name="password"]').val();
if(username==''){
layer.msg('请填写用户名');
return;
}
if(password==''){
layer.msg('请填写密码');
return;
}
$.ajax({
url: "/admin/api/index/login",
type:'post',
data:{username:username,password:password},
success:function(res){
$('#res').html(JSON.stringify(res));
layer.msg(res.msg);
if(res.code==1){
token = res.data.token;
layer.close(idx);
}
}
})
}
})
}
</script>
+122
View File
@@ -0,0 +1,122 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">系统配置</h3>
<table class="layui-table">
<tr>
<td class="layui-td-gray-2">系统名称<font>*</font>
</td>
<td>
<input type="text" name="admin_title" lay-verify="required" autocomplete="off" placeholder="请输入系统名称" lay-reqText="请输入系统名称" class="layui-input" {notempty name="$config.admin_title"} value="{$config.admin_title}" {/notempty}>
</td>
<td rowspan="3" class="layui-td-gray-2">公司LOGO</td>
<td rowspan="3" style="width: 240px;">
<div class="layui-upload" style="width: 240px;">
<div class="layui-upload-list" id="demo1" style="width: 100%; height:100px; overflow: hidden;">
<img src='{notempty name="$config.logo"}{$config.logo}{/notempty}' style="max-width: 100%; width: 100%;" />
<input type="hidden" name="logo" {notempty name="$config.logo"} value="{$config.logo}" {/notempty}>
</div>
<button type="button" class="layui-btn layui-btn-normal" style="width: 100%;"
id="test1">上传LOGO</button>
</div>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">网络域名<font>*</font>
</td>
<td>
<input type="text" name="domain" lay-verify="required" autocomplete="off" placeholder="请输入网络域名" lay-reqText="请输入网络域名" class="layui-input" {notempty name="$config.domain"} value="{$config.domain}" {/notempty}>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">平台名称<font>*</font>
</td>
<td>
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入网站平台名称" lay-reqText="请输入平台名称" class="layui-input" {notempty name="$config.title"} value="{$config.title}" {/notempty}>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">ICP备案号</td>
<td>
<input type="text" name="icp" autocomplete="off" placeholder="请输入ICP备案号" class="layui-input" {notempty name="$config.icp"} value="{$config.icp}" {/notempty}>
</td>
<td class="layui-td-gray-2">公安备案号</td>
<td>
<input type="text" name="beian" autocomplete="off" placeholder="请输入公安备案号" class="layui-input" {notempty name="$config.beian"} value="{$config.beian}" {/notempty}>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">版权信息</td>
<td>
<input type="text" name="copyright" autocomplete="off" placeholder="请输入版权信息" lay-reqText="请输入版权信息" class="layui-input"{notempty name="$config.copyright"} value="{$config.copyright}" {/notempty}>
</td>
<td class="layui-td-gray-2">代码版本号<font>*</font>
</td>
<td>
<input type="text" lay-verify="required" name="version" autocomplete="off" placeholder="请输入版本号" lay-reqText="请输入版本号" class="layui-input" {notempty name="$config.version"} value="{$config.version}" {/notempty}>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">SEO关键词<font>*</font>
</td>
<td colspan="3">
<input type="text" name="keywords" lay-verify="required" autocomplete="off" placeholder="多个关键词用“,”隔开" lay-reqText="请输入SEO关键字" class="layui-input" {notempty name="$config.keywords"} value="{$config.keywords}" {/notempty}>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">平台描述<font>*</font>
</td>
<td colspan="3">
<textarea name="desc" lay-verify="required" placeholder="请输入平台描述" lay-reqText="请输入平台描述" class="layui-textarea">{notempty name="$config.desc"}{$config.desc} {/notempty}</textarea>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">统计代码</td>
<td colspan="5">
<textarea name="code" placeholder="请输入完整的统计代码" class="layui-textarea">{notempty name="$config.code"} value={$config.code}{/notempty}</textarea>
</td>
</tr>
</table>
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool,
upload = layui.upload;
form.render();
//logo上传
var uploadInst = upload.render({
elem: '#test1',
url: "/api/index/upload",
done: function (res) {
//如果上传失败
if (res.code == 1) {
return layer.msg('上传失败');
}
//上传成功
layer.msg('上传成功');
$('#demo1 input').attr('value', res.data.filepath);
$('#demo1 img').attr('src', res.data.filepath);
}
});
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/admin/conf/edit",data.field,callback);
return false;
});
}
</script>
+166
View File
@@ -0,0 +1,166 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>数据还原</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-tab layui-tab-brief layui-tab-big">
<ul class="layui-tab-title">
<li><a href="/admin/database/database">数据备份</a></li>
<li class="layui-this"><a href="/admin/database/backuplist">数据还原</a></li>
</ul>
</div>
<table cellspacing="0" cellpadding="0" border="0" class="layui-table">
<tr style="background-color: #f5f5f5; text-align: center;">
<th style=" text-align: center; font-weight: 800;"><span>文件名称</span></th>
<th style=" text-align: center; font-weight: 800;"><span>文件格式</span></th>
<th style=" text-align: center; font-weight: 800;"><span>分隔符</span></th>
<th style=" text-align: center; font-weight: 800;"><span>文件总大小</span></th>
<th style=" text-align: center; font-weight: 800;"><span>分卷总数</span></th>
<th style=" text-align: center; font-weight: 800; width:200px"><span>操作</span></th>
</tr>
{empty name="list"}
<tr>
<td colspan="6" align="center">暂无备份数据</td>
</tr>
{/empty}
{volist name="list" id="vo" key="k"}
<tr style="background-color: #fafafa;">
<td><strong>备份时间:{$vo.time}</strong>{if $vo.timespan == $lock_time}<span style="color:red; margin-left:20px;">该备份不是完整备份,请删除重新备份</span>{/if}</td>
<td align="center"><span>.sql</span></td>
<td align="center"><span>{$vo.data.compress}</span></td>
<td align="center"><span>{:format_bytes($vo.data.size)}</span></td>
<td align="center"><span>{$vo.data.part}</span></td>
<td align="center">
<div class="layui-btn-group" data-time='{$vo.timespan}'>
{if $vo.timespan == $lock_time}
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="reset">清除不完整的备份</a>
{else/}
<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="import">数据还原</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">备份删除</a>
{/if}
</div>
</td>
</tr>
{for start="0" end="$vo.data.part" step="1"}
<tr>
<td colspan="5">
{:date("Ymd",$vo.timespan)}{$vo.data.compress}{:date("His",$vo.timespan)}{$vo.data.compress}{$i+1}.sql
</td>
<td align="center">
<a class="layui-btn layui-btn-xs" href='/admin/database/downfile?time={$vo.data.time}&part={$i+1}'>下载备份(分卷{$i+1})</a>
</td>
</tr>
{/for}
{/volist}
</table>
</div>
</div>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
function importData(data){
if(data.code==0){
console.log(data.msg);
layer.closeAll();
layer.msg(data.msg,{time: 200000});
if($.isPlainObject(data.data)){
$.ajax({
url: "/admin/database/import",
type:'get',
data:{"part" : data.data.part, "start" : data.data.start,time:data.data.time},
success: function (res) {
importData(res);
}
})
}else {
layer.msg(data.msg);
window.onbeforeunload = function(){ return null; }
}
} else {
layer.msg(data.msg);
}
}
//监听行工具事件
$('[lay-event="import"]').on('click',function(){
var time=$(this).parent().data('time');
layer.confirm('确认要还原该备份吗?', {
icon: 3,
title: '提示'
}, function (index) {
layer.msg("数据还原中...",{time: 200000});
$.ajax({
url: "/admin/database/import?time="+time,
type:'get',
success: function (res) {
importData(res);
}
})
window.onbeforeunload = function(){ return "正在还原数据库,请不要关闭!" }
layer.close(index);
});
return false;
})
$('[lay-event="del"]').on('click',function(){
var time=$(this).parent().data('time');
layer.confirm('确认要删除该备份吗?', {
icon: 3,
title: '提示'
}, function (index) {
$.ajax({
url: "/admin/database/del",
data: {'time':time},
success: function (res) {
layer.msg(res.msg);
if (res.code == 0) {
setTimeout(function(){
location.reload();
},2000)
}
}
})
layer.close(index);
});
return false;
})
$('[lay-event="reset"]').on('click',function(){
var time=$(this).parent().data('time');
layer.confirm('确认要清除该备份吗?', {
icon: 3,
title: '提示'
}, function (index) {
$.ajax({
url: "/admin/database/del",
data: {'time':time,'lock':1},
success: function (res) {
layer.msg(res.msg);
if (res.code == 0) {
setTimeout(function(){
location.reload();
},2000)
}
}
})
layer.close(index);
});
return false;
})
}
</script>
{/block}
<!-- /脚本 -->
+220
View File
@@ -0,0 +1,220 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>数据备份</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-tab layui-tab-brief layui-tab-big">
<ul class="layui-tab-title">
<li class="layui-this"><a href="/admin/database/database">数据备份</a></li>
<li><a href="/admin/database/backuplist">数据还原</a></li>
</ul>
</div>
<table class="layui-hide" id="backup" lay-filter="test"></table>
</div>
</div>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-group">
<span class="layui-btn layui-btn-sm layui-btn-normal" lay-event="backup">数据备份</span><span class="layui-btn layui-btn-sm" lay-event="optimize"></span><span class="layui-btn layui-btn-danger layui-btn-sm" lay-event="repair"></span>
</div>
<span id="dataTips" style="font-size:12px; margin-left:10px"></span>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
var table = layui.table,
form = layui.form;
var tableIns = table.render({
elem: '#backup',
title: '数据备份',
toolbar: '#toolbarDemo',
url: "/admin/database/database", //数据接口
page: false,
defaultToolbar: false,
cols: [
[ //表头
{ type: 'checkbox' },
{
field: 'name',
title: '数据表',
width: 220
},
{
field: 'status',
title: '状态',
width: 120,
templet: function (d) {
return '<span id="table_' + d.name + '">-</span>';
}
},
{
field: 'engine',
title: '存储引擎',
align: 'center',
width: 90
}, {
field: 'row_format',
title: '行格式',
align: 'center',
width: 90
}, {
field: 'rows',
title: '行数',
align: 'center',
width: 100,
}, {
field: 'data_size',
title: '字节数',
align: 'center',
width: 120
}, {
field: 'data_length',
title: '数据大小',
align: 'center',
width: 120
}, {
field: 'comment',
title: '数据表注释'
}, {
field: 'create_time',
title: '创建时间',
width: 160,
align: 'center'
}
]
],
done: function (res, curr, count) {
$('#dataTips').html(res.msg);
}
});
//递归备份表
function backup(tab, status, table) {
layer.closeAll();
layer.msg("备份中...,请勿关闭本页面", { time: 200000 });
$.get("/admin/database/backup", tab, function (data) {
// console.log(data)
if (data.code == 0) {
showmsg(data.data.tab.table, data.msg);
if (data.data.tab.start == 'ok') {
layer.msg('备份完成');
window.onbeforeunload = function () { return null }
return;
}
backup(data.data.tab, tab.id != data.data.tab.id);
} else {
layer.msg('立即备份');
}
}, "json");
}
//修改备份状态
function showmsg(table, msg) {
console.log(table);
$("#table_" + table).addClass('span-color-2').html(msg);
}
//监听行工具事件
table.on('toolbar(test)', function (obj) {
var checkData = table.checkStatus(obj.config.id).data;
var len = checkData.length;
var tables = [];
if (len == 0) {
layer.msg('请先选择表');
return false;
}
for (var i = 0; i < len; i++) {
tables.push(checkData[i].name);
}
if (obj.event === 'backup') {
layer.confirm('确认要备份选中的' + len + '个数据表吗?', {
icon: 3,
title: '提示'
}, function (index) {
$.ajax({
url: "/admin/database/backup",
type: 'post',
data: { 'tables': tables },
success: function (res) {
if (res.code == 0) {
layer.msg("开始备份,请不要关闭本页面!");
window.onbeforeunload = function () { return "正在备份数据库,请不要关闭!" }
backup(res.data.tab);
}
if (res.code == 2) {
layer.confirm('检测到有一个备份任务未完成,请先清除未完成的备份', {
icon: 3,
title: '提示'
}, function (index) {
$.ajax({
url: "/admin/database/del",
data: { 'lock': 1 },
success: function (res) {
layer.msg(res.msg);
}
})
})
}
else {
layer.msg(res.msg);
}
}
})
layer.close(index);
});
} else if (obj.event === 'optimize') {
layer.confirm('确认要优化选中的' + len + '个数据表吗?', {
icon: 3,
title: '提示'
}, function (index) {
$.ajax({
url: "/admin/database/optimize",
data: { 'tables': tables },
success: function (res) {
layer.msg(res.msg);
if (res.code == 0) {
setTimeout(function () {
location.reload();
}, 2000)
}
}
})
layer.close(index);
});
} else if (obj.event === 'repair') {
layer.confirm('确认要修复选中的' + len + '个数据表吗?', {
icon: 3,
title: '提示'
}, function (index) {
$.ajax({
url: "/admin/database/repair",
data: { 'tables': tables },
success: function (res) {
layer.msg(res.msg);
if (res.code == 0) {
setTimeout(function () {
location.reload();
}, 2000)
}
}
})
layer.close(index);
});
}
});
}
</script>
{/block}
<!-- /脚本 -->
+86
View File
@@ -0,0 +1,86 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">部门架构</h3>
{eq name="$id" value="0"}
<table class="layui-table">
<tr>
<td class="layui-td-gray-2">部门名称<font>*</font></td>
<td>
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入部门名称" lay-reqText="请输入部门名称" class="layui-input">
</td>
<td class="layui-td-gray-2">上级部门<font>*</font></td>
<td>
<select name="pid" lay-verify="required" lay-reqText="请选择上级部门">
<option value="0">作为顶级部门</option>
{volist name="department" id="v"}
<option value="{$v.id}" {eq name="$pid" value="$v.id"} selected{/eq}>{$v.title}</option>
{/volist}
</select>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">部门联系电话</td>
<td colspan="3">
<input type="text" name="phone" placeholder="请输入部门联系电话,可空" autocomplete="off" class="layui-input">
</td>
</tr>
</table>
{else/}
<table class="layui-table">
<tr>
<td class="layui-td-gray-2">部门名称<font>*</font></td>
<td>
<input type="text" name="title" value="{$detail.title}" lay-verify="required" autocomplete="off" placeholder="请输入部门名称" lay-reqText="请输入部门名称" class="layui-input">
</td>
<td class="layui-td-gray-2">上级部门<font>*</font></td>
<td>
<select name="pid" lay-verify="required" lay-reqText="请选择上级部门">
<option value="0">作为顶级部门</option>
{volist name="department" id="v"}
<option value="{$v.id}" {eq name="$detail.pid" value="$v.id"} selected{/eq}>{$v.title}</option>
{/volist}
</select>
</td>
</tr>
<tr>
<td class="layui-td-gray-2">部门负责人</td>
<td>
<select name="leader_id">
<option value="0">请选择部门负责人</option>
{volist name="users" id="v"}
<option value="{$v.id}" {eq name="detail.leader_id" value="$v.id"} selected{/eq}>{$v.name}</option>
{/volist}
</select>
</td>
<td class="layui-td-gray-2">部门联系电话</td>
<td>
<input type="text" name="phone" value="{$detail.phone}" placeholder="请输入部门联系电话,可空" autocomplete="off" class="layui-input">
</td>
</tr>
</table>
{/eq}
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function(data){
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
location.reload();
}
}
tool.post("/admin/department/add",data.field,callback);
return false;
});
}
</script>
+93
View File
@@ -0,0 +1,93 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>部门架构</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add-menu">+ 添加部门</button>
</div>
<div>
<table class="layui-hide" id="treeTable" lay-filter="treeTable"></table>
</div>
</div>
</div>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool','treeGrid'];
function gouguInit() {
var treeGrid = layui.treeGrid,
layer = layui.layer,
tool = layui.tool,
ptable = treeGrid.render({
id: 'treeTable'
, elem: '#treeTable'
, idField: 'id'
, url: "/admin/department/index"
, method :"get"
, cellMinWidth: 80
, treeId: 'id'//树形id字段名称
, treeUpId: 'pid'//树形父id字段名称
, treeShowName: 'title'//以树形式显示的字段
, height: 'full-0'
,isOpenDefault:true
,heightRemove:[".dHead",24]//不计算的高度,表格设定的是固定高度,此项不生效
, cols: [[
{ field: 'id', width: 100, title: 'ID号', align: 'center' }
, { field: 'pid', title: '上级部门ID',width: 120, align: 'center'}
, { field: 'title', title: '部门名称'}
, { field: 'leader', title: '部门负责人',width: 120, align: 'center'}
, { field: 'phone', title: '部门电话',width: 160,}
, { width:180, title: '操作', align: 'center', templet: function (d) {
var html = '<span class="layui-btn-group"><button class="layui-btn layui-btn-xs" lay-event="add">添加下级部门</button><button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</button></span>';
return html;
}
}
]]
, page: false
});
//表头工具栏事件
$('.main-page-content').on('click','.add-menu', function(){
tool.open('/admin/department/add');
return;
});
//操作按钮
treeGrid.on('tool(treeTable)', function (obj) {
if (obj.event === 'add') {
tool.open('/admin/department/add?pid='+obj.data.id);
return;
}
if (obj.event === 'edit') {
tool.open('/admin/department/add?id='+obj.data.id);
return;
}
if (obj.event === 'del') {
layer.confirm('确定要删除吗?', { icon: 3, title: '提示' }, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/admin/department/delete",{ id: obj.data.id },callback);
layer.close(index);
});
}
});
}
</script>
{/block}
<!-- /脚本 -->
+81
View File
@@ -0,0 +1,81 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">知识分类</h3>
{eq name="$id" value="0"}
<table class="layui-table">
<tr>
<td class="layui-td-gray">父级分类<font>*</font></td>
<td>
<select name="pid" lay-verify="required" lay-reqText="请选择父级分类">
<option value="0">作为顶级分类</option>
{volist name="$cates" id="v"}
<option value="{$v.id}" {eq name="$pid" value="$v.id"}selected=""{/eq}>{$v.title}</option>
{/volist}
</select>
</td>
<td class="layui-td-gray">分类名称<font>*</font></td>
<td>
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入分类名称" lay-reqText="请输入分类名称" class="layui-input">
</td>
<td class="layui-td-gray">排序</td>
<td>
<input type="text" name="sort" placeholder="请输入排序,数字" value="0" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray">描述</td>
<td colspan="5"><textarea name="desc" placeholder="请输入描述,可空" class="layui-textarea"></textarea></td>
</tr>
</table>
{else/}
<table class="layui-table">
<tr>
<td class="layui-td-gray">父级分类<font>*</font></td>
<td>
<select name="pid" lay-verify="required" lay-reqText="请选择父级分类">
<option value="0">作为顶级分类</option>
{volist name="$cates" id="v"}
<option value="{$v.id}" {eq name="$detail.pid" value="$v.id"}selected=""{/eq}>{$v.title}</option>
{/volist}
</select>
</td>
<td class="layui-td-gray">分类名称<font>*</font></td>
<td>
<input type="text" name="title" value="{$detail.title}" lay-verify="required" autocomplete="off" placeholder="请输入分类名称" lay-reqText="请输入分类名称" class="layui-input">
</td>
<td class="layui-td-gray">排序</td>
<td>
<input type="text" name="sort" value="{$detail.sort}" placeholder="请输入排序,数字" value="0" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray">描述</td>
<td colspan="5"><textarea name="desc" placeholder="请输入描述,可空" class="layui-textarea">{$detail.desc}</textarea></td>
</tr>
</table>
{/eq}
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function(data){
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
location.reload();
}
}
tool.post("/admin/kcate/add",data.field,callback);
return false;
});
}
</script>
+95
View File
@@ -0,0 +1,95 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>知识类型</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add-menu">+ 添加分类</button>
</div>
<div>
<table class="layui-hide" id="treeTable" lay-filter="treeTable"></table>
</div>
</div>
</div>
<script type="text/html" id="switchStatus">
<input type="checkbox" name="status" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="status" {{ d.status == 1 ? 'checked' : '' }}>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool','treeGrid'];
function gouguInit() {
var treeGrid = layui.treeGrid,
layer = layui.layer,
tool = layui.tool,
ptable = treeGrid.render({
id:'treeTable'
,elem: '#treeTable'
,idField:'id'
,url: "/admin/kcate/index"
,method :"get"
,cellMinWidth: 100
,treeId:'id'//树形id字段名称
,treeUpId:'pid'//树形父id字段名称
,treeShowName:'title'//以树形式显示的字段
,heightRemove:[".dHead",24]//不计算的高度,表格设定的是固定高度,此项不生效
,cols: [[
{field:'id',width:80, title: 'ID号', align:'center'}
,{field: 'sort', title: '排序',align:'center', width:80}
,{field:'title', edit:'text',width:240, title: '分类名称'}
,{field:'pid', title: '父级ID', width:80, align:'center'}
,{field:'desc', title: '描述', }
,{width:160,title: '操作', align:'center',templet: function(d){
var html = '<span class="layui-btn-group"><button class="layui-btn layui-btn-xs" lay-event="add">添加子分类</button><button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</button></span>';
return html;
}
}
]]
,page:false
//,skin:'line'
});
//表头工具栏事件
$('.add-menu').on('click', function(){
tool.open('/admin/kcate/add','900px');
return;
});
//操作按钮
treeGrid.on('tool(treeTable)', function (obj) {
if (obj.event === 'add') {
tool.open('/admin/kcate/add?pid='+obj.data.id);
return;
}
if (obj.event === 'edit') {
tool.open('/admin/kcate/add?id='+obj.data.id);
return;
}
if (obj.event === 'del') {
layer.confirm('确定要删除吗?', { icon: 3, title: '提示' }, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/admin/kcate/delete",{ id: obj.data.id },callback);
layer.close(index);
});
}
});
}
</script>
{/block}
<!-- /脚本 -->
+95
View File
@@ -0,0 +1,95 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>知识类型</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add-menu">+ 添加分类</button>
</div>
<div>
<table class="layui-hide" id="treeTable" lay-filter="treeTable"></table>
</div>
</div>
</div>
<script type="text/html" id="switchStatus">
<input type="checkbox" name="status" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="status" {{ d.status == 1 ? 'checked' : '' }}>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool','treeGrid'];
function gouguInit() {
var treeGrid = layui.treeGrid,
layer = layui.layer,
tool = layui.tool,
ptable = treeGrid.render({
id:'treeTable'
,elem: '#treeTable'
,idField:'id'
,url: "/admin/kcate/index"
,method :"get"
,cellMinWidth: 100
,treeId:'id'//树形id字段名称
,treeUpId:'pid'//树形父id字段名称
,treeShowName:'title'//以树形式显示的字段
,heightRemove:[".dHead",24]//不计算的高度,表格设定的是固定高度,此项不生效
,cols: [[
{field:'id',width:80, title: 'ID号', align:'center'}
,{field: 'sort', title: '排序',align:'center', width:80}
,{field:'title', edit:'text',width:240, title: '分类名称'}
,{field:'pid', title: '父级ID', width:80, align:'center'}
,{field:'desc', title: '描述', }
,{width:160,title: '操作', align:'center',templet: function(d){
var html = '<span class="layui-btn-group"><button class="layui-btn layui-btn-xs" lay-event="add">添加子分类</button><button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</button></span>';
return html;
}
}
]]
,page:false
//,skin:'line'
});
//表头工具栏事件
$('.add-menu').on('click', function(){
tool.open('/admin/kcate/add','900px');
return;
});
//操作按钮
treeGrid.on('tool(treeTable)', function (obj) {
if (obj.event === 'add') {
tool.open('/admin/kcate/add?pid='+obj.data.id);
return;
}
if (obj.event === 'edit') {
tool.open('/admin/kcate/add?id='+obj.data.id);
return;
}
if (obj.event === 'del') {
layer.confirm('确定要删除吗?', { icon: 3, title: '提示' }, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/admin/kcate/delete",{ id: obj.data.id },callback);
layer.close(index);
});
}
});
}
</script>
{/block}
<!-- /脚本 -->
+108
View File
@@ -0,0 +1,108 @@
{extend name="../../base/view/common/base"/}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>操作日志</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<form class="layui-form layui-form-bar">
<div class="layui-input-inline" style="width:300px;">
<input type="text" name="keywords" placeholder="昵称/操作节点名称/操作数据ID" class="layui-input" autocomplete="off" />
</div>
<div class="layui-input-inline">
<select name="action">
<option value="">请选择类型</option>
{volist name="$type_action" id="vo"}
<option value="{$vo}">{$vo}</option>
{/volist}
</select>
</div>
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">提交搜索</button>
</form>
<div style="width:100%;">
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
</div>
</div>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
var table = layui.table,
form = layui.form;
layui.pageTable = table.render({
elem: '#test',
title: '操作日志列表',
url: "/admin/log/index", //数据接口
page: true, //开启分页
limit: 20,
height: 'full-112',
cols: [
[ //表头
{
field: 'id',
title: 'ID号',
align: 'center',
width: 90
}, {
field: 'action',
title: '操作',
align: 'center',
width: 80
}, {
field: 'content',
title: '操作描述'
}, {
field: 'param_id',
title: '操作数据ID',
align: 'center',
width: 100
},{
field: 'name',
title: '操作用户',
align: 'center',
width: 100
}, {
field: 'ip',
title: 'IP地址',
align: 'center',
width: 150
}, {
field: 'create_time',
title: '操作时间',
fixed: 'right',
align: 'center',
width: 160
}
]
]
});
//监听搜索提交
form.on('submit(webform)', function (data) {
layui.pageTable.reload({
where: {
keywords: data.field.keywords,
action: data.field.action
},
page: {
curr: 1
}
});
return false;
});
}
</script>
{/block}
<!-- /脚本 -->
+72
View File
@@ -0,0 +1,72 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">公告分类</h3>
{eq name="$id" value="0"}
<table class="layui-table">
<tr>
<td class="layui-td-gray">父级分类<font>*</font></td>
<td>
<select name="pid" lay-verify="required" lay-reqText="请选择父级分类">
<option value="0">作为顶级分类</option>
{volist name="$cates" id="v"}
<option value="{$v.id}" {eq name="$pid" value="$v.id"}selected=""{/eq}>{$v.title}</option>
{/volist}
</select>
</td>
<td class="layui-td-gray">分类名称<font>*</font></td>
<td>
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入分类名称" lay-reqText="请输入分类名称" class="layui-input">
</td>
<td class="layui-td-gray">排序</td>
<td>
<input type="text" name="sort" placeholder="请输入排序,数字" value="0" autocomplete="off" class="layui-input">
</td>
</tr>
</table>
{else/}
<table class="layui-table">
<tr>
<td class="layui-td-gray">父级分类<font>*</font></td>
<td>
<select name="pid" lay-verify="required" lay-reqText="请选择父级分类">
<option value="0">作为顶级分类</option>
{volist name="$cates" id="v"}
<option value="{$v.id}" {eq name="$detail.pid" value="$v.id"}selected=""{/eq}>{$v.title}</option>
{/volist}
</select>
</td>
<td class="layui-td-gray">分类名称<font>*</font></td>
<td>
<input type="text" name="title" value="{$detail.title}" lay-verify="required" autocomplete="off" placeholder="请输入分类名称" lay-reqText="请输入分类名称" class="layui-input">
</td>
<td class="layui-td-gray">排序</td>
<td>
<input type="text" name="sort" value="{$detail.sort}" placeholder="请输入排序,数字" autocomplete="off" class="layui-input">
</td>
</tr>
</table>
{/eq}
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
location.reload();
}
}
tool.post("/admin/ncate/add",data.field,callback);
return false;
});
}
</script>
+96
View File
@@ -0,0 +1,96 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>公告类型</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add-menu">+ 添加分类</button>
</div>
<div>
<table class="layui-hide" id="treeTable" lay-filter="treeTable"></table>
</div>
</div>
</div>
<script type="text/html" id="switchStatus">
<input type="checkbox" name="status" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="status" {{ d.status == 1 ? 'checked' : '' }}>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool','treeGrid'];
function gouguInit() {
var treeGrid = layui.treeGrid,
layer = layui.layer,
tool = layui.tool,
ptable = treeGrid.render({
id:'treeTable'
,elem: '#treeTable'
,idField:'id'
,url: "/admin/ncate/index"
,method :"get"
,cellMinWidth: 100
,treeId:'id'//树形id字段名称
,treeUpId:'pid'//树形父id字段名称
,treeShowName:'title'//以树形式显示的字段
,isOpenDefault:true
,heightRemove:[".dHead",24]//不计算的高度,表格设定的是固定高度,此项不生效
,cols: [[
{field:'id',width:80, title: 'ID号', align:'center'}
,{field: 'sort', title: '排序', align:'center', style:'cursor: pointer;', width:80}
,{field:'title', title: '分类名称'}
,{field:'pid', title: '父级ID', width:80, align:'center'}
,{width:160,title: '操作', align:'center',templet: function(d){
var html = '<span class="layui-btn-group"><button class="layui-btn layui-btn-xs" lay-event="add">添加子分类</button><button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</button></span>';
return html;
}
}
]]
,page:false
//,skin:'line'
});
//表头工具栏事件
$('.add-menu').on('click', function(){
tool.open('/admin/ncate/add');
return;
});
//操作按钮
treeGrid.on('tool(treeTable)', function (obj) {
if (obj.event === 'add') {
tool.open('/admin/ncate/add?pid='+obj.data.id);
return;
}
if (obj.event === 'edit') {
tool.open('/admin/ncate/add?id='+obj.data.id);
return;
}
if (obj.event === 'del') {
layer.confirm('确定要删除吗?', { icon: 3, title: '提示' }, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/admin/ncate/delete",{ id: obj.data.id },callback);
layer.close(index);
});
}
});
}
</script>
{/block}
<!-- /脚本 -->
+113
View File
@@ -0,0 +1,113 @@
<form class="layui-form page-content p-4">
{eq name="$id" value="0"}
<h3 class="h3-title">新增公告</h3>
{else/}
<h3 class="h3-title">编辑公告</h3>
{/eq}
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">公告标题<font>*</font></td>
<td>
<input type="text" name="title" lay-verify="required" lay-reqText="请输入公告标题" placeholder="请输入公告标题" class="layui-input"
{notempty name="$note.title" }value="{$note.title}" {/notempty}>
</td>
<td class="layui-td-gray">公告分类<span style="color: red">*</span></td>
<td>
<select name="cate_id" lay-verify="required" lay-reqText="请选择分类">
<option value="">请选择分类</option>
{notempty name="$note.cate_id"}
{volist name=":set_recursion(admin_note_cate())" id="v"}
<option value="{$v.id}" {eq name="$note.cate_id" value="$v.id" }selected{/eq}>{$v.title}</option>
{/volist}
{else/}
{volist name=":set_recursion(admin_note_cate())" id="v"}
<option value="{$v.id}">{$v.title}</option>
{/volist}
{/notempty}
</select>
</td>
</tr>
<tr>
<td class="layui-td-gray">展示期间<span style="color: red">*</span></td>
<td id="date">
<div class="layui-input-inline">
<input type="text" id="start_time" name="start_time" readonly lay-verify="required" lay-reqText="请选择公告展示开始时间" placeholder="请选择时间" class="layui-input" {notempty name="$note.start_time" }value="{$note.start_time | date='Y-m-d'}" {/notempty}>
</div>
-
<div class="layui-input-inline">
<input type="text" id="end_time" name="end_time" readonly lay-verify="required" lay-reqText="请选择公告展示结束时间" placeholder="请选择时间" class="layui-input" {notempty name="$note.end_time" }value="{$note.end_time | date='Y-m-d'}" {/notempty}>
</div>
</td>
<td class="layui-td-gray">排序</td>
<td>
<input type="text" name="sort" placeholder="请输入排序,数字" class="layui-input" {notempty
name="$note.sort" }value="{$note.sort}" {/notempty}>
</td>
</tr>
<tr>
<td class="layui-td-gray" style="vertical-align:top; text-align:left;" colspan="4">公告内容<span style="color: red">*</span></td>
</tr>
<tr>
<td colspan="4">
<div style="margin-top:-2px; margin-right:2px">
<textarea id="mdContent" style="display:none;">{notempty name="$note.md_content" }{$note.md_content|raw}{/notempty}</textarea>
<div id="docContent"></div>
</div>
</td>
<tr>
<td class="layui-td-gray">关联链接</td>
<td colspan="3">
<input type="text" name="src" placeholder="请输入链接" class="layui-input" {notempty
name="$note.src" }value="{$note.src}" {/notempty}>
</td>
</tr>
</table>
<div class="pt-3">
<input type="hidden" name="id" value="{$id}" />
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool,
editor = layui.editormd,
laydate = layui.laydate;
form.render();
var edit = editor.render('docContent', {
markdown: $('#mdContent').val(),
imageUploadURL: "/api/index/md_upload",
lineNumbers: false,
toolbarIcons: function () {
return [
"undo", "redo","bold", "del", "italic", "quote","h1", "h2", "h3", "h4", "h5",
"list-ul", "list-ol", "hr","link", "reference-link", "image", "code", "code-block", "table","watch", "fullscreen"
];
},
height:window.innerHeight - 350
});
//日期范围
laydate.render({
elem: '#date',
range: ['#start_time', '#end_time']
});
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/admin/note/add",data.field,callback);
return false;
});
}
</script>
+121
View File
@@ -0,0 +1,121 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>企业公告</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add">+ 添加公告</button>
</div>
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
</div>
<script type="text/html" id="barDemo">
<div class="layui-btn-group"><span class="layui-btn layui-btn-normal layui-btn-xs" lay-event="view">查看</span><span class="layui-btn layui-btn-xs" lay-event="edit"></span><span class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"></span></div>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool','editormd'];
function gouguInit() {
var table = layui.table,
tool = layui.tool,
form = layui.form;
layui.pageTable = table.render({
elem: '#test',
title: '公告列表',
url: "/admin/note/index", //数据接口
page: true, //开启分页
limit: 20,
height: 'full-104',
cols: [
[
{
field: 'id',
title: '编号ID',
align: 'center',
width: 80,
templet: function (d) {
var html = 'N' + d.id;
return html;
}
}, {
field: 'sort',
title: '排序',
align: 'center',
width: 80
}, {
field: 'cate_title',
title: '公告分类',
align: 'center',
width: 100
}, {
field: 'title',
title: '公告标题'
}, {
field: 'cate_title',
title: '公告展示期间',
align: 'center',
width: 200,
templet: function (d) {
var html = d.start_time + ' ~ ' + d.end_time;
return html;
}
}, {
field: 'right',
title: '操作',
toolbar: '#barDemo',
width: 136,
align: 'center'
}
]
]
});
//表头工具栏事件
$('.add').on('click', function () {
tool.open('/admin/note/add');
});
//监听行工具事件
table.on('tool(test)', function (obj) {
var data = obj.data;
if (obj.event === 'view') {
tool.open('/admin/note/view?id=' + data.id);
return;
}
if (obj.event === 'edit') {
tool.open('/admin/note/add?id=' + data.id);
return;
}
if (obj.event === 'del') {
layer.confirm('确定删除该公告吗?', {
icon: 3,
title: '提示'
}, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/admin/note/delete", { id: obj.data.id }, callback);
layer.close(index);
});
}
});
}
</script>
{/block}
<!-- /脚本 -->
+33
View File
@@ -0,0 +1,33 @@
<div class="page-content p-4">
<h3 class="h3-title">公告详情</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">公告标题</td>
<td colspan="3">{$note.title}</td>
<td class="layui-td-gray">公告分类</td>
<td>
{volist name=":set_recursion(get_note_cate())" id="v"}
{eq name="$note.cate_id" value="$v.id" }{$v.title}{/eq}
{/volist}
</td>
</tr>
<tr>
<td class="layui-td-gray">展示期间</td>
<td>{$note.start_time | date='Y-m-d'} - {$note.end_time | date='Y-m-d'}</td>
<td class="layui-td-gray">关联链接</td>
<td>{$note.src}</td>
<td class="layui-td-gray">排序</td>
<td>{$note.sort}</td>
</tr>
<tr>
<td class="layui-td-gray" style="vertical-align:top;">公告内容</td>
<td colspan="5"><div class="md-content-content">{$note.content|raw}</div></td>
</tr>
</table>
</div>
<script>
function openInit(layui) {
}
</script>
+98
View File
@@ -0,0 +1,98 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">岗位职称</h3>
{if condition="$id eq 0"}
<table class="layui-table">
<tr>
<td class="layui-td-gray">岗位名称<font>*</font></td>
<td>
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入岗位名称" lay-reqText="请输入岗位名称" class="layui-input">
</td>
<td class="layui-td-gray-3">岗位工时单价(元)<font>*</font></td>
<td>
<input type="text" name="work_price" lay-verify="required|number" placeholder="请输入岗位工时单价" lay-reqText="请输入岗位工时单价" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray">状态<font>*</font></td>
<td colspan="3">
<input type="radio" name="status" value="1" title="正常" checked>
<input type="radio" name="status" value="0" title="禁用">
</td>
</tr>
<tr>
<td class="layui-td-gray">权限角色<font>*</font></td>
<td colspan="3">
{volist name="$group" id="v"}
<input type="checkbox" name="group_id[]" title="{$v.title}" value="{$v.id}" lay-skin="primary">
{/volist}
</td>
</tr>
<tr>
<td class="layui-td-gray">岗位备注</td>
<td colspan="3">
<textarea name="remark" placeholder="请输入岗位备注" class="layui-textarea"></textarea>
</td>
</tr>
</table>
{else/}
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">岗位名称<font>*</font></td>
<td>
<input type="text" name="title" value="{$detail.title}" lay-verify="required" autocomplete="off" placeholder="请输入岗位名称" lay-reqText="请输入岗位名称" class="layui-input">
</td>
<td class="layui-td-gray-3">岗位工时单价(元)<font>*</font></td>
<td>
<input type="text" name="work_price" value="{$detail.work_price}" lay-verify="required|number" placeholder="请输入岗位工时单价" lay-reqText="请输入岗位工时单价" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray">状态<font>*</font></td>
<td colspan="3">
<input type="radio" name="status" value="1" title="正常" {eq name="$detail.status" value="1"}checked{/eq}>
<input type="radio" name="status" value="0" title="禁止" {eq name="$detail.status" value="0"}checked{/eq}>
</td>
</tr>
<tr>
<td class="layui-td-gray">权限角色<font>*</font></td>
<td colspan="3">
{volist name="$group" id="v"}
<input type="checkbox" name="group_id[]" title="{$v.title}" value="{$v.id}" {eq name="$v.checked" value="1" }checked{/eq} lay-skin="primary">
{/volist}
</td>
</tr>
<tr>
<td class="layui-td-gray">岗位备注</td>
<td colspan="3">
<textarea name="remark" placeholder="请输入岗位备注" class="layui-textarea">{$detail.remark}</textarea>
</td>
</tr>
</table>
{/if}
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/admin/position/add",data.field,callback);
return false;
});
}
</script>
+122
View File
@@ -0,0 +1,122 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>岗位职称</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add">+ 添加岗位</button>
</div>
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
</div>
<script type="text/html" id="status">
<i class="layui-icon {{# if(d.status == 1){ }}layui-icon-ok{{# } else { }}layui-icon-close{{# } }}"></i>
</script>
<script type="text/html" id="barDemo">
<div class="layui-btn-group"><button class="layui-btn layui-btn-xs layui-btn-normal" lay-event="view">详情</button><button class="layui-btn layui-btn-xs" lay-event="edit"></button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"></button></div>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
var layer = layui.layer,
tool = layui.tool,
table = layui.table;
layui.pageTable = table.render({
elem: '#test',
title: '岗位列表',
url: "/admin/position/index", //数据接口
page: false, //开启分页
cols: [
[
{
field: 'id',
title: 'ID号',
align: 'center',
width: 80
}, {
field: 'title',
title: '岗位名称',
align: 'center',
width: 120
}, {
field: 'groupName',
title: '权限角色',
width: 200
}, {
field: 'remark',
title: '备注'
}, {
field: 'work_price',
title: '岗位工时单价(元)',
align: 'center',
width: 132
}, {
field: 'status',
title: '状态',
toolbar: '#status',
align: 'center',
width: 60
}, {
field: 'right',
title: '操作',
toolbar: '#barDemo',
width: 132,
align: 'center'
}
]
]
});
//表头工具栏事件
$('.add').on('click', function () {
tool.open('/admin/position/add');
});
//监听行工具事件
table.on('tool(test)', function (obj) {
var data = obj.data;
if (obj.event === 'view') {
tool.open('/admin/position/view?id=' + data.id);
return;
}
if (obj.event === 'edit') {
tool.open('/admin/position/add?id=' + data.id);
return;
}
if (obj.event === 'del') {
if (data.id == 1) {
layer.msg('超级岗位不能删除');
return;
}
layer.confirm('您确定要删除该岗位', {
icon: 3,
title: '提示'
}, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/admin/position/delete", { id: obj.data.id }, callback);
layer.close(index);
});
}
});
}
</script>
{/block}
<!-- /脚本 -->
+80
View File
@@ -0,0 +1,80 @@
<style>
.left-note{font-weight:800; vertical-align:top; padding-top:28px!important; text-align:center}
.left-note .layui-form-checkbox span{background-color: #bbbbbb!important;}
.left-note .layui-form-checkbox:hover span{background-color: #808080;}
.layui-form-checked.layui-checkbox-disabled i{background-color:#ababab!important;color: #ffffff!important;border-color:#ababab!important;}
.layui-form-checked.layui-checkbox-disabled[lay-skin=primary] i{background-color:#ababab!important;}
.right-note .layui-checkbox-disabled span {color: #808080!important;}
</style>
<form class="layui-form page-content p-4">
<h3 class="h3-title">岗位信息</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">岗位名称</td>
<td>
{$detail.title}
</td>
<td class="layui-td-gray-2">岗位工时单价</td>
<td>
{$detail.work_price}
</td>
<td class="layui-td-gray">状态</td>
<td>
{eq name="$detail.status" value="1" }正常{/eq}
{eq name="$detail.status" value="0" }禁止登录{/eq}
</td>
</tr>
<tr>
<td class="layui-td-gray">用户角色</td>
<td colspan="5">
{volist name="$group" id="v"}
{eq name="$v.checked" value="1" }{$v.title},{/eq}
{/volist}
</td>
</tr>
<tr>
<td class="layui-td-gray">岗位备注</td>
<td colspan="5">
{$detail.remark}
</td>
</tr>
</table>
<h3 class="h3-title" style="padding-top:15px;">岗位权限</h3>
<table class="layui-table layui-table-form">
{volist name="role_rule" id="vo"}
<tr>
<td style="font-weight:800; text-align:center;">
<input type="checkbox" disabled value="{$vo.id}" title="{$vo.title}" {eq name="$vo.checked" value="true" }checked{/eq}>
</td>
{notempty name="vo.children"}
<td>
<div style="padding:0 0 0 10px;">
{volist name="vo.children" key="k" id="voo"}
<div class="checkbox16" style="padding:10px 0;">
<input type="checkbox" disabled lay-filter="rule" name="rule[]" value="{$voo.id}" lay-skin="primary" title="{$voo.title}" {eq name="$voo.checked" value="true" }checked{/eq}>
</div>
{notempty name="voo.children"}
<div style="padding:0 0 3px; {if condition='$k != count($vo.children)'}margin-bottom:3px; padding-bottom:16px; border-bottom:1px solid #eee;{/if}">
{volist name="voo.children" id="vooo"}
<div class="layui-input-inline" style="margin-right:10px;">
<input type="checkbox" disabled data-rule="{$voo.id}" name="rule[]" value="{$vooo.id}" lay-skin="primary" title="{$vooo.title}" {eq name="$vooo.checked" value="true" }checked{/eq}>
</div>
{/volist}
</div>
{/notempty}
{/volist}
</div>
</td>
{/notempty}
</tr>
{/volist}
</table>
</form>
<script>
function openInit() {
var form = layui.form;
form.render();
}
</script>
+143
View File
@@ -0,0 +1,143 @@
<style>
.left-note{font-weight:800; vertical-align:top; padding-top:28px!important; text-align:center}
.left-note .layui-form-checkbox span{background-color: #969696;}
.left-note .layui-form-checkbox:hover span{background-color: #808080;}
.left-note .layui-form-checked span, .left-note .layui-form-checked:hover span { background-color: #5fb878;}
.checkbox14 .layui-form-checkbox span{font-size:15px;font-weight:800;}
.right-note .layui-checkbox-disabled span {color: #666666!important;}
</style>
<form class="layui-form page-content p-4">
<h3 class="h3-title">权限角色</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">角色名称<font>*</font>
</td>
<td>
<input class="layui-input" type="text" name="title" lay-verify="required" lay-reqText="请输入角色名称" {notempty name="$role.title"
}value="{$role.title}" {/notempty} placeholder="请输入角色名称" autocomplete="off" />
</td>
<td class="layui-td-gray">状态<font>*</font>
</td>
<td>
{if condition="$id eq 0"}
<input type="radio" name="status" value="1" title="正常" checked>
<input type="radio" name="status" value="-1" title="禁用">
{else/}
<input type="radio" name="status" value="1" title="正常" {eq name="$role.status" value="1" }checked{/eq}>
<input type="radio" name="status" value="-1" title="禁用" {eq name="$role.status" value="-1" }checked{/eq}>
{/if}
</td>
</tr>
<tr>
<td class="layui-td-gray-2">权限配置说明<font>*</font></td>
<td colspan="3"><strong class="red">注意:如果右侧子级权限有节点被勾选了,左侧的顶级权限就必须勾选,否则无法查看右侧的子级菜单。</strong></td>
</tr>
<tr>
<td colspan="4">
<table style="width:100%" id="rule">
<tr>
<td style="text-align:center; background-color:#f8f8f8; width:160px;">选择可操作的顶级权限 <font style="color:red"></font></td>
<td style="text-align:left; background-color:#f8f8f8;">选择可操作的子级权限 <font style="color:red"></font></td>
</tr>
{volist name="role_rule" id="vo"}
<tr>
<td class="left-note">
<input type="checkbox" name="rule[]" value="{$vo.id}" title="{$vo.title}" class="aaa" {eq name="$vo.checked" value="true" }checked{/eq}>
</td>
{notempty name="vo.children"}
<td class="right-note">
<div style="padding:0 0 0 10px;">
{volist name="vo.children" key="k" id="voo"}
<div class="checkbox15" style="padding:10px 0;">
<input type="checkbox" lay-filter="rule" name="rule[]" value="{$voo.id}" lay-skin="primary" title="{$voo.title}" {eq name="$voo.checked" value="true" }checked{/eq}>
</div>
{notempty name="voo.children"}
<div style="padding:0 0 3px; {if condition='$k != count($vo.children)'}margin-bottom:3px; padding-bottom:16px; border-bottom:1px solid #eee;{/if}">
{volist name="voo.children" id="vooo"}
<div class="layui-input-inline" style="margin-right:10px;">
<input type="checkbox" data-rule="{$voo.id}" name="rule[]" value="{$vooo.id}" lay-skin="primary" title="{$vooo.title}" {eq name="$vooo.checked" value="true" }checked{/eq}>
</div>
{notempty name="vooo.children"}
<div style="padding:0 0 3px; {if condition='$k != count($vo.children)'}margin-bottom:3px; padding-bottom:16px; border-bottom:1px solid #eee;{/if}">
{volist name="vooo.children" id="voooo"}
<div class="layui-input-inline" style="margin-right:10px;">
<input type="checkbox" data-rule="{$vooo.id}" name="rule[]" value="{$voooo.id}" lay-skin="primary" title="{$voooo.title}" {eq name="$voooo.checked" value="true" }checked{/eq}>
</div>
{/volist}
</div>
{/notempty}
{/volist}
</div>
{/notempty}
{/volist}
</div>
</td>
{/notempty}
</tr>
{/volist}
</table>
</td>
</tr>
<tr>
<td class="layui-td-gray" style="vertical-align: top;">备注内容
</td>
<td colspan="3">
<textarea name="desc" placeholder="请输入备注" class="layui-textarea">{notempty name="$role.desc" }{$role.desc}{/notempty}</textarea>
</td>
</tr>
</table>
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}" />
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
setTimeout(function(){
tool.close();
},500);
}
}
tool.post("/admin/role/add",data.field,callback);
return false;
});
//监听多选框点击事件 通过 lay-filter="menu"来监听
form.on('checkbox(menu)', function (data) {
  let val = data.value;
if(data.elem.checked){
//判断当前多选框是选中还是取消选中
$("input[data-menu='"+val+"']").prop("checked", true);//true:选中 false:不选中
}
else{
$("input[data-menu='"+val+"']").prop("checked", false);
}
form.render();//实时渲染选中和不选中的样式
});
//监听多选框点击事件 通过 lay-filter="rule"来监听
form.on('checkbox(rule)', function (data) {
  let val = data.value;
if(data.elem.checked){
//判断当前多选框是选中还是取消选中
$("input[data-rule='"+val+"']").prop("checked", true);//true:选中 false:不选中
}
else{
$("input[data-rule='"+val+"']").prop("checked", false);
}
form.render();//实时渲染选中和不选中的样式
});
}
</script>
+104
View File
@@ -0,0 +1,104 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>权限角色</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<form class="layui-form layui-form-bar">
<div class="layui-input-inline" style="width:300px;">
<input type="text" name="keywords" placeholder="名称/备注" class="layui-input" autocomplete="off" />
</div>
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">提交搜索</button>
</form>
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
</div>
<script type="text/html" id="status">
<i class="layui-icon {{# if(d.status == 1){ }}layui-icon-ok{{# } else { }}layui-icon-close{{# } }}"></i>
</script>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="add">+ 添加权限组</button>
</div>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
var table = layui.table,
tool = layui.tool;
form = layui.form;
layui.pageTable = table.render({
elem: '#test',
toolbar: '#toolbarDemo',
url: "/admin/role/index", //数据接口
page: true, //开启分页
limit: 20,
defaultToolbar: false,
cols: [[ //表头
{ field: 'id', title: 'ID号', align: 'center', width: 80 }
, { field: 'title', title: '权限组名称', width: 200 }
, { field: 'desc', title: '备注' }
, { field: 'status', title: '状态', toolbar: '#status', align: 'center', width: 80 }
, {
width: 100, title: '操作', align: 'center', templet: function (d) {
var html = '<div class="layui-btn-group"><button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</button></div>';
return html;
}
}
]]
});
//表头工具栏事件
table.on('toolbar(test)', function (obj) {
if (obj.event === "add") {
tool.open("/admin/role/add");
return;
}
});
//监听行工具事件
table.on('tool(test)', function (obj) {
var data = obj.data;
if (obj.event === "edit") {
tool.open("/admin/role/add?id=" + obj.data.id);
return;
}
if (obj.event === 'del') {
layer.confirm("确定要删除该权限角色吗?", { icon: 3, title: '提示' }, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/admin/role/delete", { id: obj.data.id }, callback);
layer.close(index);
});
}
});
//监听搜索提交
form.on('submit(webform)', function (data) {
layui.pageTable.reload({
where: { keywords: data.field.keywords },
page: { curr: 1 }
});
return false;
});
}
</script>
{/block}
<!-- /脚本 -->
+121
View File
@@ -0,0 +1,121 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">功能菜单/节点</h3>
{if condition="$id eq 0"}
<table class="layui-table">
<tr>
<td class="layui-td-gray-3">父级菜单/节点<font>*</font></td>
<td>
<select name="pid" lay-verify="required" lay-reqText="请选择父级菜单/节点">
<option value="0">作为顶级菜单/节点</option>
{volist name=":set_recursion(admin_rule())" id="v"}
<option value="{$v.id}" {eq name="pid" value="$v.id" }selected="" {/eq}>{$v.title} </option>
{/volist}
</select>
</td>
<td class="layui-td-gray-3">菜单排序</td>
<td>
<input type="text" name="sort" value="0" placeholder="请输入数字,越小越靠前" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray-3">菜单/节点名称<font>*</font></td>
<td>
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入菜单/节点名称" lay-reqText="请输入菜单/节点名称" class="layui-input">
</td>
<td class="layui-td-gray-3">菜单/节点URL</td>
<td>
<input type="text" name="src" placeholder="请输入菜单/节点URL,可空" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray-3">操作日志名称<font>*</font></td>
<td>
<input type="text" name="name" lay-verify="required" placeholder="请输入操作日志名称" lay-reqText="请输入操作日志名称" autocomplete="off" class="layui-input">
</td>
<td class="layui-td-gray-3">是否左侧菜单<font>*</font></td>
<td>
<input type="radio" name="menu" value="1" title="是">
<input type="radio" name="menu" value="2" title="不是">
</td>
</tr>
<tr>
<td class="layui-td-gray-3">左侧图标</td>
<td colspan="3">
<input type="text" name="icon" style="width:150px; display:inline" placeholder="请输入图标,可空" autocomplete="off" class="layui-input">
如:icon-jichuguanli<a href="{__METE__}/icon/index.html" target="_blank" style="margin-left:10px; color:#007AFF">[查看图标]</a>
</td>
</tr>
</table>
{else/}
<table class="layui-table">
<tr>
<td class="layui-td-gray-3">父级菜单/节点<font>*</font></td>
<td>
<select name="pid" lay-verify="required" lay-reqText="请选择父级菜单/节点">
<option value="0">作为顶级节点</option>
{volist name=":set_recursion(admin_rule())" id="v"}
<option value="{$v.id}" {eq name="$detail.pid" value="$v.id" }selected="" {/eq}>{$v.title} </option>
{/volist}
</select>
</td>
<td class="layui-td-gray-3">菜单排序</td>
<td>
<input type="text" name="sort" value="{$detail.sort}" placeholder="请输入数字,越小越靠前" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray-3">菜单/节点名称<font>*</font></td>
<td>
<input type="text" name="title" value="{$detail.title}" lay-verify="required" autocomplete="off" placeholder="请输入菜单/节点名称" lay-reqText="请输入菜单/节点名称" class="layui-input">
</td>
<td class="layui-td-gray-3">菜单/节点URL</td>
<td>
<input type="text" name="src" value="{$detail.src}" placeholder="请输入菜单/节点URL,可空" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray-3">操作日志名称<font>*</font></td>
<td>
<input type="text" name="name" value="{$detail.name}" lay-verify="required" placeholder="请输入操作日志名称" lay-reqText="请输入操作日志名称" autocomplete="off" class="layui-input">
</td>
<td class="layui-td-gray-3">是否左侧菜单<font>*</font></td>
<td>
<input type="radio" name="menu" value="1" title="是" {eq name="$detail.menu" value="1"} checked{/eq}>
<input type="radio" name="menu" value="2" title="不是" {eq name="$detail.menu" value="2"} checked{/eq}>
</td>
</tr>
<tr>
<td class="layui-td-gray-3">左侧图标</td>
<td colspan="3">
<input style="width:150px; display:inline" type="text" name="icon" value="{$detail.icon}" placeholder="请输入图标,可空" autocomplete="off" class="layui-input">
如:icon-jichuguanli<a href="{__METE__}/icon/index.html" target="_blank" style="margin-left:10px; color:#007AFF">[查看图标]</a>
</td>
</tr>
</table>
{/if}
<div style="padding: 10px 0">
<input type="hidden" name="id" value="{$id}">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<!-- /主体 -->
<script>
function openInit() {
let form = layui.form,
layer = layui.layer,
tool = layui.tool;
form.render();
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
location.reload();
}
}
tool.post("/admin/rule/add",data.field,callback);
return false;
});
}
</script>
+105
View File
@@ -0,0 +1,105 @@
{extend name="../../base/view/common/base"/}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>菜单节点</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add-menu">+ 添加菜单/节点</button>
</div>
<div>
<table class="layui-hide" id="treeTable" lay-filter="treeTable"></table>
</div>
</div>
</div>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
var ptable = null, treeGrid = null,rightpage=null, layer = null, tableId = "treeTable";
const moduleInit = ['tool','treeGrid'];
function gouguInit() {
treeGrid = layui.treeGrid;
tool = layui.tool;
layer = layui.layer;
ptable = treeGrid.render({
id: tableId
, elem: '#' + tableId
, idField: 'id'
, url: "/admin/rule/index"
, method :"get"
, cellMinWidth: 180
, treeId: 'id'//树形id字段名称
, treeUpId: 'pid'//树形父id字段名称
, treeShowName: 'title'//以树形式显示的字段
,heightRemove:[".dHead",24]//不计算的高度,表格设定的是固定高度,此项不生效
,height:'100%'
, cols: [[
{ field: 'id', width: 80, title: 'ID号', align: 'center'}
, { field: 'sort', width: 60, title: '排序',align: 'center'}
,{field:'icon',title: '菜单图标',width: 80, align: 'center' ,templet: function(d){
var html='<strong class="iconfont '+d.icon+'"></strong>';
return html;
}}
, { field: 'title', width: 150, title: '菜单/节点名称'}
, { field: 'pid', title: '父ID', width: 80, align: 'center' }
, { field: 'src', title: 'URL链接'}
, { field: 'menu', width: 90, title: '是否菜单',align: 'center', templet: function (d) {
var html = '<span style="color:#fbbc05">否</span>';
if(d.menu=='1'){
html = '<span style="color:#12bb37">是</span>';
}
return html;
}
}
, {field: 'name', width: 90, title: '日志名称',align: 'center'}
, {width: 200, title: '操作', align: 'center'
, templet: function (d) {
var html = '<span class="layui-btn-group"><button class="layui-btn layui-btn-xs" lay-event="add">添加子菜单/节点</button><button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</button></span>';
return html;
}
}
]]
, page: false
});
//表头工具栏事件
$('.add-menu').on('click',function(){
tool.open('/admin/rule/add');
return;
});
//操作按钮
treeGrid.on('tool(' + tableId + ')', function (obj) {
if (obj.event === 'add') {
tool.open('/admin/rule/add?pid='+obj.data.id);
}
if (obj.event === 'edit') {
tool.open('/admin/rule/add?id='+obj.data.id);
}
if (obj.event === 'del') {
layer.confirm('确定要删除吗?', { icon: 3, title: '提示' }, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/admin/rule/delete",{ id: obj.data.id },callback);
layer.close(index);
});
}
return;
});
}
</script>
{/block}
<!-- /脚本 -->
+131
View File
@@ -0,0 +1,131 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a><cite>系统设置</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
<div class="sub-menu" style="width: 200px;">
{include file="../../base/view/common/submenu" /}
<div class="menu-bar">
<div class="menu-bar-content">
<div class="line"></div>
</div>
</div>
</div>
<div class="main-bg-content">
<div class="layui-card">
<div class="table-title">系统信息</div>
<div class="layui-card-body">
<table class="layui-table">
<tr>
<td class="layui-td-gray">系统名称</td>
<td>
{notempty name="$config.admin_title"}{$config.admin_title}{/notempty}
</td>
<td rowspan="3" class="layui-td-gray-2">LOGO</td>
<td rowspan="3" style="width: 240px;">
<div class="layui-upload" style="width: 240px;">
<img src='{notempty name="$config.logo"}{$config.logo}{/notempty}' style="max-width: 100%; width: 100%;" />
</div>
</td>
</tr>
<tr>
<td class="layui-td-gray">网站域名</td>
<td>
{notempty name="$config.domain"}{$config.domain}{/notempty}
</td>
</tr>
<tr>
<td class="layui-td-gray">网站名称</td>
<td>
{notempty name="$config.title"}{$config.title}{/notempty}
</td>
</tr>
<tr>
<td class="layui-td-gray">ICP备案号</td>
<td>
{notempty name="$config.icp"}{$config.icp}{/notempty}
</td>
<td class="layui-td-gray">公安备案号</td>
<td>
{notempty name="$config.beian"}{$config.beian}{/notempty}
</td>
</tr>
<tr>
<td class="layui-td-gray">版权信息</td>
<td>
{notempty name="$config.copyright"}{$config.copyright}{/notempty}
</td>
<td class="layui-td-gray">代码版本号
</td>
<td>
{notempty name="$config.version"}{$config.version}{/notempty}
</td>
</tr>
<tr>
<td class="layui-td-gray">简介</td>
<td colspan="3">
{notempty name="$config.desc"}{$config.desc} {/notempty}
</td>
</tr>
</table>
</div>
</div>
<div class="layui-card">
<div class="table-title">服务器信息</div>
<div class="layui-card-body">
<table class="layui-table" lay-skin="" lay-size="sm">
{if condition="($install == true)"}
<tr>
<td colspan="4" style="color: #E94335; background-color:#f5f5f5">提醒:发现app目录下的install文件夹没删除,为了系统的安全,请手动去删除。</td>
</tr>
{/if}
<tr>
<td class="layui-td-gray-2">服务器系统</td>
<td>{:get_system_info('os')}</td>
<td class="layui-td-gray-2">PHP版本</td>
<td>{:get_system_info('php')}</td>
</tr>
<tr>
<td class="layui-td-gray-2">上传限制</td>
<td>{:get_system_info('upload_max_filesize')}</td>
<td class="layui-td-gray-2">执行限制</td>
<td>{:get_system_info('max_execution_time')}</td>
</tr>
<tr>
<td class="layui-td-gray-2">ThinkPHP</td>
<td colspan="3">{$TP_VERSION}<a class="layui-badge layui-bg-blue" style="margin-left:10px"
href="https://www.kancloud.cn/manual/thinkphp6_0" target="_blank">TP6文档</a></td>
</tr>
<tr>
<td class="layui-td-gray-2">Layui</td>
<td colspan="3">{:LAYUI_VERSION}<a class="layui-badge layui-bg-blue" style="margin-left:10px"
href="https://www.layui.site/doc/" target="_blank">Layui文档</a></td>
</tr>
<tr>
<td class="layui-td-gray-2">江苏美天科技</td>
<td colspan="3">{:CMS_VERSION}<a class="layui-badge layui-bg-blue" style="margin-left:10px"
href="https://blog.gougucms.com/home/book/detail/bid/7.html" target="_blank">江苏美天科技文档</a></td>
</tr>
<tr>
<td class="layui-td-gray-2">BUG反馈</td>
<td colspan="3"><a href="mailto:hdm58@qq.com" target="_blank">hdm58@qq.com</a></td>
</tr>
<tr>
<td class="layui-td-gray-2">QQ交流群</td>
<td colspan="3">搜Q群:24641076,或点击 <a href="https://jq.qq.com/?_wv=1027&k=pxshRv6I" target="_blank" rel="nofollow"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="gougucms交流群" title="gougucms交流群" style="vertical-align:middle"></a></td>
</tr>
<tr>
<td class="layui-td-gray-2">同系开源软件</td>
<td colspan="3"><a class="layui-badge layui-bg-blue" style="margin-right:16px" href="https://gitee.com/gougucms/gougucms" target="_blank">勾股CMS</a><a class="layui-badge layui-bg-blue" style="margin-right:16px" href="https://gitee.com/gougucms/blog" target="_blank">勾股BLOG</a><a class="layui-badge layui-bg-blue" style="margin-right:16px" href="https://gitee.com/gougucms/office" target="_blank">勾股OA</a></td>
</tr>
</table>
</div>
</div>
</div>
</div>
{/block}
+133
View File
@@ -0,0 +1,133 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>任务类型</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add-new">+ 添加类别</button>
</div>
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
</div>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
var table=layui.table,
tool=layui.tool,
layer=layui.layer;
layui.pageTable = table.render({
elem: '#test'
,title:'任务类型列表'
,url: "/admin/tcate/index"
,method :"get"
,page: false //开启分页
,limit: 20
,cellMinWidth: 200
,cols: [[
{field:'id',width:80, title: 'ID号', align:'center'}
,{field:'title',title: '类别名称'}
,{field:'sort',title: '排序'}
,{field:'status', title: '状态',width:80,align:'center',templet: function(d){
var html1='<span>正常</span>';
var html2='<span style="color:#FF5722">禁用</span>';
if(d.status==1){
return html1;
}
else{
return html2;
}
}}
,{width:100,title: '操作', align:'center',templet: function(d){
var html='';
var btn='<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</a>';
var btn1='<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="disable">禁用</a>';
var btn2='<a class="layui-btn layui-btn-xs" lay-event="open">启用</a>';
if(d.status==1){
html = '<div class="layui-btn-group">'+btn+btn1+'</div>';
}
else{
html = '<div class="layui-btn-group">'+btn+btn2+'</div>';
}
return html;
}}
]]
});
table.on('tool(test)',function (obj) {
if(obj.event === 'edit'){
addExpense(obj.data.id,obj.data.title);
}
if(obj.event === 'disable'){
layer.confirm('确定要禁用该类别吗?', {icon: 3, title:'提示'}, function(index){
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
}
}
tool.post("/admin/tcate/check",{ id: obj.data.id, status: 0 },callback);
layer.close(index);
});
}
if(obj.event === 'open'){
layer.confirm('确定要启用该类别吗?', {icon: 3, title:'提示'}, function(index){
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
}
}
tool.post("/admin/tcate/check",{ id: obj.data.id, status: 1 },callback);
layer.close(index);
});
}
});
$('.main-page-content').on('click','.add-new',function(){
addExpense(0,'');
});
function addExpense(id,val){
var title = '新增类别';
if(id>0){
title = '编辑类别';
}
layer.prompt({
title: title,
value: val,
yes: function(index, layero) {
// 获取文本框输入的值
var value = layero.find(".layui-layer-input").val();
if (value) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
}
layer.close(index);
}
tool.post("/admin/tcate/add",{id: id, title: value,},callback);
} else {
layer.msg('请填写类别标题');
}
}
})
}
}
</script>
{/block}
<!-- /脚本 -->
+259
View File
@@ -0,0 +1,259 @@
<form class="layui-form page-content p-4">
{if condition="$id eq 0"}
<h3 class="h3-title">添加员工信息</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">员工姓名<font>*</font>
</td>
<td>
<input type="text" name="name" lay-verify="required" placeholder="请输入员工姓名" lay-reqText="请输入员工姓名"
autocomplete="off" class="layui-input">
</td>
<td class="layui-td-gray">手机号码<font>*</font>
</td>
<td>
<input type="text" name="mobile" lay-verify="required" placeholder="可使用手机号码登录" lay-reqText="请输入手机"
autocomplete="off" class="layui-input">
</td>
<td class="layui-td-gray">初始密码</td>
<td>
{$reg_pwd}
<input type="hidden" name="reg_pwd" value="{$reg_pwd}" lay-verify="required">
</td>
</tr>
<tr>
<td class="layui-td-gray">所在部门<font>*</font>
</td>
<td>
<select name="did" lay-verify="required" lay-reqText="请选择所属部门">
<option value="">请选择所属部门</option>
{volist name="department" id="v"}
<option value="{$v.id}">{$v.title}</option>
{/volist}
</select>
</td>
<td class="layui-td-gray">岗位职称<font>*</font>
</td>
<td>
<select name="position_id" lay-verify="required" lay-reqText="请选择岗位职称">
<option value="">请选择岗位职称</option>
{volist name="position" id="v"}
<option value="{$v.id}">{$v.title}</option>
{/volist}
</select>
</td>
<td rowspan="3" class="layui-td-gray-2">头像<br /><span style="font-size: 12px;">(如若不上传<br />系统将自动生成)</span>
</td>
<td rowspan="3" valign="top" style="width: 100px;">
<div class="layui-upload" style="width: 100px;">
<div class="layui-upload-list" id="demo1" style="width: 100%; height:100px; overflow: hidden;">
<img src="/static/home/images/nonepic600x600.jpg" height="100"
style="max-width: 100%; width: 100%;" />
<input type="hidden" name="thumb" value="">
</div>
<button type="button" class="layui-btn layui-btn-normal" style="width: 100%;"
id="test1">上传头像</button>
</div>
</td>
</tr>
<tr>
<td class="layui-td-gray">入职日期<font>*</font>
</td>
<td>
<input type="text" id="entry_time" name="entry_time" readonly lay-verify="required"
placeholder="请选择入职日期" lay-reqText="请选择入职日期" autocomplete="off" class="layui-input">
</td>
<td class="layui-td-gray">员工性别<font>*</font>
</td>
<td>
<input type="radio" name="sex" value="1" title="男">
<input type="radio" name="sex" value="2" title="女">
</td>
</tr>
<tr>
<td class="layui-td-gray">员工类型<font>*</font>
</td>
<td>
<input type="radio" name="type" value="3" title="实习">
<input type="radio" name="type" value="2" title="试用">
<input type="radio" name="type" value="1" title="正式">
</td>
<td class="layui-td-gray">电子邮箱<font>*</font>
</td>
<td>
<input type="text" name="email" value="" lay-verify="required" placeholder="请输入电子邮箱" lay-reqText="请输入电子邮箱" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray">账号状态</td>
<td colspan="5">
<input type="radio" name="status" value="0" title="禁止登录">
<input type="radio" name="status" value="1" title="正常" checked>
<input type="radio" name="status" value="2" title="离职">
</td>
</tr>
<tr>
<td class="layui-td-gray">员工简介</td>
<td colspan="7">
<textarea name="desc" placeholder="请输入员工简介" class="layui-textarea"></textarea>
</td>
</tr>
</table>
{else/}
<h3 class="h3-title">编辑员工信息</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">登录账号</td>
<td>
{$detail.username}
</td>
<td class="layui-td-gray">初始密码</td>
<td>
{empty name="$detail.reg_pwd"}
密码已重置
{else/}
{$detail.reg_pwd}
{/empty}
</td>
<td class="layui-td-gray">账号状态</td>
<td>
{eq name="$detail.status" value="0"}<span style="color:#FF5722">禁止登录</span>{/eq}
{eq name="$detail.status" value="1"}<span style="color:#009688">正常</span>{/eq}
{eq name="$detail.status" value="2"}<span style="color:#FFB800">已离职</span>{/eq}
</td>
</tr>
<tr>
<td class="layui-td-gray">员工姓名<font>*</font>
</td>
<td>
<input type="text" name="name" value="{$detail.name}" lay-verify="required" placeholder="请输入员工姓名"
lay-reqText="请输入员工姓名" autocomplete="off" class="layui-input">
</td>
<td class="layui-td-gray">手机号码<font>*</font>
</td>
<td>
<input type="text" name="mobile" value="{$detail.mobile}" lay-verify="required" placeholder="可使用手机号码登录"
lay-reqText="请输入手机" autocomplete="off" class="layui-input">
</td>
<td rowspan="3" class="layui-td-gray">头像<br /><span style="font-size: 12px;">(如若不上传<br />系统自动生成)</span></td>
<td rowspan="3" valign="top" style="width: 100px;">
<div class="layui-upload" style="width: 100px;">
<div class="layui-upload-list" id="demo1" style="width: 100%; height:100px; overflow: hidden;">
<img src="{$detail.thumb}" height="100" style="max-width: 100%; width: 100%;" />
<input type="hidden" name="thumb" value="{$detail.thumb}">
</div>
<button type="button" class="layui-btn layui-btn-normal" style="width: 100%;"
id="test1">上传头像</button>
</div>
</td>
</tr>
<tr>
<td class="layui-td-gray">所在部门<font>*</font>
</td>
<td>
<select name="did" lay-verify="required" lay-reqText="请选择所属部门">
<option value="">请选择所属部门</option>
{volist name="department" id="v"}
<option value="{$v.id}" {eq name="$v.id" value="$detail.did" }selected{/eq}>{$v.title}</option>
{/volist}
</select>
</td>
<td class="layui-td-gray">岗位职称<font>*</font>
</td>
<td>
<select name="position_id" lay-verify="required" lay-reqText="请选择岗位职称">
<option value="">请选择岗位职称</option>
{volist name="position" id="v"}
<option value="{$v.id}" {eq name="$v.id" value="$detail.position_id" }selected{/eq}>{$v.title}
</option>
{/volist}
</select>
</td>
</tr>
<tr>
<td class="layui-td-gray">入职日期<font>*</font>
</td>
<td>
<input type="text" id="entry_time" value="{$detail.entry_time|time_format=###,'Y-m-d'}"
name="entry_time" readonly lay-verify="required" placeholder="请选择入职日期" lay-reqText="请选择入职日期"
autocomplete="off" class="layui-input">
</td>
<td class="layui-td-gray">员工性别<font>*</font>
</td>
<td>
<input type="radio" name="sex" value="1" title="男" {eq name="$detail.sex" value="1" }checked{/eq}>
<input type="radio" name="sex" value="2" title="女" {eq name="$detail.sex" value="2" }checked{/eq}>
</td>
</tr>
<tr>
<td class="layui-td-gray">员工类型<font>*</font>
</td>
<td>
<input type="radio" name="type" value="3" title="实习" {eq name="$detail.type" value="3" }checked{/eq}>
<input type="radio" name="type" value="2" title="试用" {eq name="$detail.type" value="2" }checked{/eq}>
<input type="radio" name="type" value="1" title="正式" {eq name="$detail.type" value="1" }checked{/eq}>
</td>
<td class="layui-td-gray">电子邮箱<font>*</font>
</td>
<td colspan="3">
<input type="text" name="email" value="{$detail.email}" lay-verify="required" placeholder="请输入电子邮箱" lay-reqText="请输入电子邮箱" autocomplete="off" class="layui-input">
</td>
</tr>
<tr>
<td class="layui-td-gray">员工简介</td>
<td colspan="7">
<textarea name="desc" placeholder="请输入员工简介" class="layui-textarea">{$detail.desc}</textarea>
</td>
</tr>
</table>
{/if}
<div style="padding: 10px 0">
<input type="hidden" value="{$id}" name="id">
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form,
layer = layui.layer,
tool = layui.tool,
laydate = layui.laydate,
upload = layui.upload;
form.render();
//日期选择
laydate.render({
elem: '#entry_time',
max: 7,
showBottom: false
});
//头像上传
var uploadInst = upload.render({
elem: "#test1",
url: "/api/index/upload",
done: function (e) {
//如果上传失败
if (e.code == 1) {
return layer.msg('上传失败');
}
//上传成功
$('#demo1 input').attr('value', e.data.filepath);
$('#demo1 img').attr('src', e.data.filepath);
}
});
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/admin/user/add", data.field, callback);
return false;
});
}
</script>
+338
View File
@@ -0,0 +1,338 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>企业员工</cite></a>
</span>
{/block}
{block name="style"}
<style>
.layui-tree-entry{font-size:14px;}
.layui-tree-set{padding:2px 0}
.layui-tree-iconClick .layui-icon{color:#1E9FFF}
.layui-tree-icon {height: 13px;line-height: 13px; width: 13px; text-align: center; border: 1px solid #1E9FFF; color:#1E9FFF}
.layui-tree-line .layui-tree-set .layui-tree-set:after{top:18px;}
.tree-left{width:200px; position:absolute; height:100%; top:0; left:0; border-right:1px solid #eeeeee; padding:0 10px;}
.tree-left h3{font-size:16px; height:30px; margin-top:20px; padding-left:10px; font-weight:800}
</style>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="tree-left">
<h3>企业组织架构</h3>
<div id="depament"></div>
</div>
<div class="body-table" style="margin-left:220px;">
<form class="layui-form layui-form-bar">
<div class="layui-input-inline" style="width:136px">
<select name="status">
<option value="">选择员工状态</option>
<option value="1">正常状态</option>
<option value="0">禁止登录</option>
</select>
</div>
<div class="layui-input-inline" style="width:136px">
<select name="type">
<option value="">选择员工类型</option>
<option value="1">正式员工</option>
<option value="2">试用员工</option>
<option value="3">实习员工</option>
</select>
</div>
<div class="layui-input-inline" style="width:240px">
<input type="text" name="keywords" placeholder="输入关键字,如:ID/姓名/手机号码" class="layui-input" autocomplete="off" />
</div>
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">提交搜索</button>
</form>
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
</div>
</div>
<script type="text/html" id="thumb">
<img src="{{d.thumb}}" width="30" height="30" />
</script>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-normal layui-btn-sm" lay-event="add"><i class="layui-icon">&#xe61f;</i></button>
<button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="disable"><i class="layui-icon">&#x1006;</i></button>
<button class="layui-btn layui-btn-sm" lay-event="recovery"><i class="layui-icon">&#xe605;</i></button>
</div>
</script>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
var tree = layui.tree,
table = layui.table,
tool = layui.tool,
form = layui.form;
var treeRender = function(res){
//仅节点左侧图标控制收缩
tree.render({
elem: '#depament',
data: res.trees,
onlyIconControl: true, //是否仅允许节点左侧图标控制展开收缩
click: function(obj){
//layer.msg(JSON.stringify(obj.data));
layui.pageTable.reload({
where: {did: obj.data.id}
,page:{curr:1}
});
$('[name="keywords"]').val('');
$('[name="status"]').val('');
$('[name="type"]').val('');
layui.form.render('select');
}
});
}
tool.get("/api/index/get_department_tree",{},treeRender);
layui.pageTable = table.render({
elem: '#test',
title: '员工列表',
toolbar: '#toolbarDemo',
url: "/admin/user/index", //数据接口
page: true, //开启分页
limit: 20,
defaultToolbar: false,
height: 'full-112',
cols: [
[
{type:'checkbox',fixed:'left'},
{
field: 'id',
title: '员工号',
align: 'center',
width: 80
}, {
field: 'status',
title: '状态',
align: 'center',
width: 80,
templet: function (d) {
var html = '<span class="layui-badge layui-bg-green">正常</span>';
if(d.status == 2){
html = '<span class="layui-badge layui-bg-orange">已离职</span>'
}
else if(d.status == 0){
html = '<span class="layui-badge">被禁用</span>'
}
return html;
}
},{
field: 'type',
title: '员工类型',
align: 'center',
width: 80,
templet: function (d) {
var html = '<span style="color:#393D49">正式员工</span>';
if(d.type == 2){
html = '<span style="color:#01AAED">试用员工</span>'
}
else if(d.type == 3){
html = '<span style="color:#5FB878">实 习 生</span>'
}
return html;
}
}, {
field: 'username',
title: '登录账号',
width: 120
}, {
field: 'thumb',
title: '头像',
toolbar: '#thumb',
align: 'center',
width: 60
}, {
field: 'name',
title: '用户姓名',
align: 'center',
width: 80
},{
field: 'mobile',
title: '手机号码',
align: 'center',
width: 120
},{
field: 'sex',
title: '性别',
align: 'center',
width: 50,
templet: function (d) {
var html = '未知';
if(d.sex == 1){
html = '男'
}
else if(d.sex == 2){
html = '女'
}
return html;
}
},{
field: 'department',
title: '所在部门',
align: 'center',
width: 110
}, {
field: 'position',
title: '岗位职称',
align: 'center',
width: 110
}, {
field: 'entry_time',
title: '入职日期',
align: 'center',
width: 100
}, {
field: 'login_num',
title: '累计登录',
align: 'center',
width: 80
}, {
field: 'last_login_time',
title: '最后登录时间',
align: 'center',
minWidth: 136
},{
field: 'right',
fixed:'right',
title: '操作',
width: 160,
align: 'center',
templet: function (d) {
var html = '';
var btn1 = '<span class="layui-btn layui-btn-xs layui-btn-normal" lay-event="view">详情</span>';
var btn2 = '<span class="layui-btn layui-btn-xs" lay-event="edit">编辑</span>';
var btn3 = '<span class="layui-btn layui-btn-xs layui-btn-warm" lay-event="copy">复制密码</span>';
var btn4 = '<span class="layui-btn layui-btn-xs layui-btn-danger" lay-event="psw">重置密码</span>';
if(d.reg_pwd == ''){
html = '<div class="layui-btn-group">'+btn1+btn2+btn4+'</div>';
}
else{
html = '<div class="layui-btn-group">'+btn1+btn2+btn3+'</div>';
}
return html;
}
}
]
]
});
//表头工具栏事件
table.on('toolbar(test)', function(obj){
var checkStatus = table.checkStatus(obj.config.id); //获取选中行状态
var data = checkStatus.data;
if (obj.event === 'add') {
tool.open("/admin/user/add");
return;
}
if(data.length==0){
layer.msg('请选择要操作的员工');
return false;
}
var uidArray=[],msg='是否执行该操作?',type=0;
for(var i=0;i<data.length;i++){
uidArray.push(data[i].id);
}
switch(obj.event){
case 'disable':
msg = '您确定要把选中的员工设为禁止登录?';
type = 0;
break;
case 'recovery':
msg = '您确定要把选中的员工恢复正常?';
type = 1;
break;
};
layer.confirm(msg, {
icon: 3,
title: '提示'
}, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
}
}
tool.post("/admin/user/set",{ ids: uidArray.join(','), type: type },callback);
layer.close(index);
});
});
//监听行工具事件
table.on('tool(test)', function (obj) {
var data = obj.data;
if (obj.event === 'view') {
tool.open('/admin/user/view?id='+data.id);
return;
}
if(obj.event === 'edit'){
tool.open('/admin/user/add?id='+data.id);
}
else if (obj.event === 'copy') {
copyToClip(data.reg_pwd);
return;
}
else if (obj.event === 'psw') {
layer.confirm('确定要重设该用户的密码?', {
icon: 3,
title: '提示'
}, function (index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
}
}
tool.post("/admin/user/reset",{id: data.id},callback);
layer.close(index);
});
return;
}
});
//监听搜索提交
form.on('submit(webform)', function (data) {
layui.pageTable.reload({
where: {
keywords: data.field.keywords,
status: data.field.status,
type: data.field.type
},
page: {
curr: 1
}
});
return false;
});
}
//拷贝密码
function copyToClip(content) {
var save = function(e){
e.clipboardData.setData('text/plain', content);
e.preventDefault();
}
document.addEventListener('copy', save);
document.execCommand('copy');
document.removeEventListener('copy',save);
if (content != '') {
layer.msg('复制成功');
}
}
</script>
{/block}
<!-- /脚本 -->
+161
View File
@@ -0,0 +1,161 @@
<form class="layui-form page-content p-4">
<h3 class="h3-title">员工信息</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">登录账号</td>
<td>
{$detail.username}
</td>
<td class="layui-td-gray">员工状态</td>
<td>
{eq name="$detail.status" value="0"}<span style="color:#FF5722">禁止登录</span>{/eq}
{eq name="$detail.status" value="1"}<span style="color:#009688">正常</span>{/eq}
{eq name="$detail.status" value="2"}<span style="color:#FFB800">已离职</span>{/eq}
{empty name="$detail.reg_pwd"}
,密码已重置
<span class="layui-btn layui-btn-normal layui-btn-xs" data-note="rest" data-val="{$detail.id}">重设新密码</span>
{else/}
,默认密码:{$detail.reg_pwd}
<span class="layui-btn layui-btn-normal layui-btn-xs" data-note="copy" data-val="{$detail.reg_pwd}">复制初始密码</span>
{/empty}
</td>
<td rowspan="3" class="layui-td-gray">头像</td>
<td rowspan="3" valign="top" style="width: 100px;">
<div class="layui-upload">
<img src="{$detail.thumb}" style="width:100px; height:100px; max-width:100%" />
</div>
</td>
</tr>
<tr>
<td class="layui-td-gray">员工姓名</td>
<td>
{$detail.name}
</td>
<td class="layui-td-gray">性别</td>
<td>
{eq name="$detail.sex" value="0"}未知{/eq}
{eq name="$detail.sex" value="1"}男{/eq}
{eq name="$detail.sex" value="2"}女{/eq}
</td>
</tr>
<tr>
<td class="layui-td-gray">手机号码</td>
<td>
{$detail.mobile}
</td>
<td class="layui-td-gray">电子邮箱</td>
<td>
{$detail.email}
</td>
</tr>
<tr>
<td class="layui-td-gray">所在部门</td>
<td>{$detail.department}</td>
<td class="layui-td-gray">岗位职称</td>
<td>{$detail.position}</td>
<td class="layui-td-gray">入职日期</td>
<td>
{$detail.entry_time | date='Y-m-d'}
</td>
</tr>
<tr>
<td class="layui-td-gray">员工类型</td>
<td>
{eq name="$detail.type" value="3"}<span style="color:#5FB878">实 习 生</span>{/eq}
{eq name="$detail.type" value="2"}<span style="color:#01AAED">试用员工</span>{/eq}
{eq name="$detail.type" value="1"}<span style="color:#393D49">正式员工</span>{/eq}
</td>
<td class="layui-td-gray-2">最后登录时间</td>
<td>
{$detail.last_login_time}
</td>
<td class="layui-td-gray-2">累计登录次数</td>
<td>
{$detail.login_num}
</td>
</tr>
<tr>
<td class="layui-td-gray">员工简介</td>
<td colspan="7">
{$detail.desc}
</td>
</tr>
</table>
<h3 class="h3-title" style="padding-top:15px;">用户权限</h3>
<table class="layui-table layui-table-form">
{volist name="role_rule" id="vo"}
<tr>
<td style="font-weight:800; text-align:center;">
<input type="checkbox" disabled value="{$vo.id}" title="{$vo.title}" {eq name="$vo.checked" value="true" }checked{/eq}>
</td>
{notempty name="vo.children"}
<td>
<div style="padding:0 0 0 10px;">
{volist name="vo.children" key="k" id="voo"}
<div class="checkbox16" style="padding:10px 0;">
<input type="checkbox" disabled lay-filter="rule" name="rule[]" value="{$voo.id}" lay-skin="primary" title="{$voo.title}" {eq name="$voo.checked" value="true" }checked{/eq}>
</div>
{notempty name="voo.children"}
<div style="padding:0 0 3px; {if condition='$k != count($vo.children)'}margin-bottom:3px; padding-bottom:16px; border-bottom:1px solid #eee;{/if}">
{volist name="voo.children" id="vooo"}
<div class="layui-input-inline" style="margin-right:10px;">
<input type="checkbox" disabled data-rule="{$voo.id}" name="rule[]" value="{$vooo.id}" lay-skin="primary" title="{$vooo.title}" {eq name="$vooo.checked" value="true" }checked{/eq}>
</div>
{/volist}
</div>
{/notempty}
{/volist}
</div>
</td>
{/notempty}
</tr>
{/volist}
</table>
</form>
<script>
function openInit() {
var form = layui.form,layer = layui.layer,tool=layui.tool;
form.render();
//重设密码
$('[data-note="rest"]').on('click',function(){
let id = $(this).data('id');
layer.confirm('确定要重设该用户的密码?', {
icon: 3,
title: '提示'
}, function (index) {
let callback = function(e){
layer.msg(e.msg);
if(e.code==0){
setTimeout(function(){
location.reload();
},2000);
}
}
tool.post('/admin/admin/reset_psw',{id: id},callback);
layer.close(index);
});
})
//拷贝密码
$('[data-note="copy"]').on('click',function(){
let val = $(this).data('val');
if (navigator.clipboard) {
navigator.clipboard.writeText(content);
} else {
var copy_textarea = document.createElement('textarea');
copy_textarea.style.position = 'fixed';
copy_textarea.style.clip = 'rect(0 0 0 0)';
copy_textarea.style.top = '10px';
copy_textarea.value = content;
document.body.appendChild(copy_textarea);
copy_textarea.select();
document.execCommand('copy', true);
document.body.removeChild(copy_textarea);
}
if (content != '') {
layer.msg('复制成功');
}
})
}
</script>
+132
View File
@@ -0,0 +1,132 @@
{extend name="../../base/view/common/base" /}
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
<a href="/home/user/setting">信息设置</a>
<a><cite>工作类型</cite></a>
</span>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="main-content">
{include file="../../base/view/common/submenu" /}
<div class="main-page-content">
<div class="layui-form-bar">
<button class="layui-btn layui-btn-sm add-new">+ 添加类别</button>
</div>
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
</div>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool'];
function gouguInit() {
var table=layui.table,
tool=layui.tool,
layer=layui.layer;
layui.pageTable = table.render({
elem: '#test'
,title:'工作类别列表'
,url: "/admin/wcate/index"
,method :"get"
,page: false //开启分页
,limit: 20
,cellMinWidth: 200
,cols: [[
{field:'id',width:80, title: 'ID号', align:'center'}
,{field:'title',title: '类别名称'}
,{field:'status', title: '状态',width:80,align:'center',templet: function(d){
var html1='<span>正常</span>';
var html2='<span style="color:#FF5722">禁用</span>';
if(d.status==1){
return html1;
}
else{
return html2;
}
}}
,{width:100,title: '操作', align:'center',templet: function(d){
var html='';
var btn='<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</a>';
var btn1='<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="disable">禁用</a>';
var btn2='<a class="layui-btn layui-btn-xs" lay-event="open">启用</a>';
if(d.status==1){
html = '<div class="layui-btn-group">'+btn+btn1+'</div>';
}
else{
html = '<div class="layui-btn-group">'+btn+btn2+'</div>';
}
return html;
}}
]]
});
table.on('tool(test)',function (obj) {
if(obj.event === 'edit'){
addExpense(obj.data.id,obj.data.title);
}
if(obj.event === 'disable'){
layer.confirm('确定要禁用该类别吗?', {icon: 3, title:'提示'}, function(index){
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
}
}
tool.post("/admin/wcate/check",{ id: obj.data.id, status: 0 },callback);
layer.close(index);
});
}
if(obj.event === 'open'){
layer.confirm('确定要启用该类别吗?', {icon: 3, title:'提示'}, function(index){
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
}
}
tool.post("/admin/wcate/check",{ id: obj.data.id, status: 1 },callback);
layer.close(index);
});
}
});
$('.main-page-content').on('click','.add-new',function(){
addExpense(0,'');
});
function addExpense(id,val){
var title = '新增类别';
if(id>0){
title = '编辑类别';
}
layer.prompt({
title: title,
value: val,
yes: function(index, layero) {
// 获取文本框输入的值
var value = layero.find(".layui-layer-input").val();
if (value) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
layui.pageTable.reload();
}
layer.close(index);
}
tool.post("/admin/wcate/add",{id: id, title: value,},callback);
} else {
layer.msg('请填写类别标题');
}
}
})
}
}
</script>
{/block}
<!-- /脚本 -->
+12
View File
@@ -0,0 +1,12 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
/**
======================
*模块数据获取公共文件
======================
*/
use think\facade\Db;
+23
View File
@@ -0,0 +1,23 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\analysis\controller;
use app\base\BaseController;
use think\facade\Db;
use think\facade\View;
class index extends BaseController
{
public function index()
{
return View();
}
}
+5
View File
@@ -0,0 +1,5 @@
<?php
// 这是系统自动生成的event定义文件
return [
];
+13
View File
@@ -0,0 +1,13 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
// 这是系统自动生成的middleware定义文件
return [
//开启session中间件
//'think\middleware\SessionInit',
\app\home\middleware\Install::class,
];
+430
View File
@@ -0,0 +1,430 @@
{extend name="../../base/view/common/base" /}
{block name="style"}
<style type="text/css">
/* 这段样式只是用于演示 */
.layui-card-header span {
position: absolute;
right: 10px;
top: 10px;
}
.layui-sales {
margin-bottom: 0;
overflow: hidden;
color: rgba(0,0,0,.85);
font-size: 30px;
}
.layui-sales-info {
padding-top: 16px;
color: rgba(0,0,0,.65);
white-space: nowrap;
text-overflow: ellipsis;
}
fieldset.layui-field-title {
margin-bottom: 10px;
}
</style>
{/block}
<!-- 主体 -->
{block name="body"}
<div class="layui-row layui-col-space15">
<div class="layui-col-xs6 layui-col-md3">
<div class="layui-card">
<div class="layui-card-header">报销售额</div>
<div class="layui-card-body">
<div class="layui-sales">¥ 126,560</div>
<div class="layui-sales-info" style="height: 125px;">
周同比 <span>12%</span>
<i class="layui-edge layui-edge-top" style="border-bottom-color: green"></i>
日同比 <span>3%</span>
<i class="layui-edge layui-edge-bottom" style="border-top-color: red"></i>
<fieldset class="layui-elem-field layui-field-title"></fieldset>
<div>日销报销 ¥12,423</div>
</div>
</div>
</div>
</div>
<div class="layui-col-xs6 layui-col-md3">
<div class="layui-card">
<div class="layui-card-header">发票总数 <span class="layui-badge layui-badge-blue pull-right"></span></div>
<div class="layui-card-body">
<div class="layui-sales">6,560</div>
<div class="layui-sales-info" >
<div id="zfbs" style="height: 80px;"></div>
<fieldset class="layui-elem-field layui-field-title"></fieldset>
<div>总发票数 1,234</div>
</div>
</div>
</div>
</div>
<div class="layui-col-xs6 layui-col-md3">
<div class="layui-card">
<div class="layui-card-header">访问量 <span class="layui-badge layui-badge-green pull-right"></span></div>
<div class="layui-card-body">
<div class="layui-sales">6,560</div>
<div class="layui-sales-info" >
<div id="fwl" style="height: 80px;"></div>
<fieldset class="layui-elem-field layui-field-title" ></fieldset>
<div>日访问量 1,234</div>
</div>
</div>
</div>
</div>
<div class="layui-col-xs6 layui-col-md3">
<div class="layui-card">
<div class="layui-card-header">业绩效果 <span class="layui-badge layui-badge-red pull-right"></span></div>
<div class="layui-card-body">
<div class="layui-sales">83%</div>
<div class="layui-sales-info" >
<div style="height: 80px;">
<div class="layui-progress layui-progress-big">
<div class="layui-progress-bar layui-bg-blue" lay-percent="83%" style="width: 83%;"></div>
</div>
</div>
<fieldset class="layui-elem-field layui-field-title" style="position: relative;"></fieldset>
<div>回款金额 ¥ 12,234</div>
</div>
</div>
</div>
</div>
<div class="layui-col-xs6 layui-col-md9">
<div class="layui-card">
<div class="layui-card-header">地域分布</div>
<div class="layui-card-body">
<div id="map" style="height: 578px;"></div>
</div>
</div>
</div>
<div class="layui-col-xs6 layui-col-md3">
<div class="layui-card" >
<div class="layui-card-header">在线人数</div>
<div class="layui-card-body">
<div id="zxrs" style="height: 250px" ></div>
</div>
</div>
</div>
<div class="layui-col-xs6 layui-col-md3">
<div class="layui-card" >
<div class="layui-card-header">浏览器分布</div>
<div class="layui-card-body">
<div id="llq" style="height: 250px" ></div>
</div>
</div>
</div>
</div>
{/block}
<!-- /主体 -->
<!-- 脚本 -->
{block name="script"}
<script src="https://cdn.staticfile.org/echarts/5.3.0/echarts.min.js"></script>
<script src="{__METE__}/third_party/echart/china.js"></script>
<script>
const moduleInit = ['tool'];
function gouguInit() {
var layer = layui.layer, table = layui.table;
}
// 访问量
var fwlCharts = echarts.init(document.getElementById('fwl'));
var fwlOptions = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
grid: {
left: '-1%',
right: '0',
bottom: '0',
top: '5px',
containLabel: false
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
show: false
}
],
yAxis: [
{
type: 'value',
show: false
}
],
series: [
{
name: '总量',
type: 'line',
stack: '总量',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#1890ff'
}, {
offset: 1,
color: '#1890ff'
}])
},
emphasis: {
focus: 'series'
},
data: [120, 132, 156, 200, 90, 100, 165]
},
]
};
fwlCharts.setOption(fwlOptions);
// 渲染表信息
var zfbsCharts = echarts.init(document.getElementById('zfbs'));
var zfbsOptions = {
color: ['#1890ff','#666'],
tooltip: {},
grid: {
left: '0',
right: '20',
bottom: '30',
containLabel: true
},
xAxis: {
data: ['1月', '2月', '3月', '4月', '6月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
show:false,
},
yAxis: {
show:false
},
series: [{
type: 'bar',
data: [726, 1013, 690, 892, 982, 570, 536, 546, 988, 1002, 500, 506],
barMaxWidth: 45
}]
}
zfbsCharts.setOption(zfbsOptions);
// 地图数据信息
function randomValue() {
return Math.round(Math.random()*1000);
}
var mapCharts = echarts.init(document.getElementById('map'));
var dataList=[
{name:"南海诸岛",value:0},
{name: '北京', value: randomValue()},
{name: '天津', value: randomValue()},
{name: '上海', value: randomValue()},
{name: '重庆', value: randomValue()},
{name: '河北', value: randomValue()},
{name: '河南', value: randomValue()},
{name: '云南', value: randomValue()},
{name: '辽宁', value: randomValue()},
{name: '黑龙江', value: randomValue()},
{name: '湖南', value: randomValue()},
{name: '安徽', value: randomValue()},
{name: '山东', value: randomValue()},
{name: '新疆', value: randomValue()},
{name: '江苏', value: randomValue()},
{name: '浙江', value: randomValue()},
{name: '江西', value: randomValue()},
{name: '湖北', value: randomValue()},
{name: '广西', value: randomValue()},
{name: '甘肃', value: randomValue()},
{name: '山西', value: randomValue()},
{name: '内蒙古', value: randomValue()},
{name: '陕西', value: randomValue()},
{name: '吉林', value: randomValue()},
{name: '福建', value: randomValue()},
{name: '贵州', value: randomValue()},
{name: '广东', value: randomValue()},
{name: '青海', value: randomValue()},
{name: '西藏', value: randomValue()},
{name: '四川', value: randomValue()},
{name: '宁夏', value: randomValue()},
{name: '海南', value: randomValue()},
{name: '台湾', value: randomValue()},
{name: '香港', value: randomValue()},
{name: '澳门', value: randomValue()}
]
// 世界地图
var mapOption = {
tooltip: {
formatter:function(params,ticket, callback){
return params.seriesName+'<br />'+params.name+''+params.value
}
},
visualMap: {
min: 0,
max: 1500,
left: 'left',
top: 'bottom',
text: ['高','低'],//取值范围的文字
inRange: {
color: ['#e0ffff', '#006edd']//取值范围的颜色
},
show: true//图注
},
geo: {
map: 'china',
roam: false, //不开启缩放和平移
zoom:1.23, //视角缩放比例
label: {
normal: {
show: true,
fontSize:'10',
color: 'rgba(0,0,0,0.7)'
}
},
itemStyle: {
normal:{
borderColor: 'rgba(0, 0, 0, 0.2)'
},
emphasis:{
areaColor: '#F3B329',//鼠标选择区域颜色
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowBlur: 20,
borderWidth: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
},
series : [
{
name: '信息量',
type: 'map',
geoIndex: 0,
data:dataList
}
]
};
mapCharts.setOption(mapOption);
var myCharts = echarts.init(document.getElementById('zxrs'));
var mData = [50, 100, 150, 80, 120, 150, 200, 250, 220, 250, 300, 350, 400, 380, 440, 450, 500, 550, 500];
var option = {
tooltip: {
trigger: "axis"
},
xAxis: [{
type: "category",
boundaryGap: !1,
data: ["06:00", "06:30", "07:00", "07:30", "08:00", "08:30", "09:00", "09:30", "10:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30", "16:00"]
}],
yAxis: [{
type: "value"
}],
series: [{
name: "总量",
type: "line",
smooth: !0,
itemStyle: {
normal: {
areaStyle: {
type: "default"
}
}
},
data: mData
}]
};
myCharts.setOption(option);
// 动态改变图表1数据
setInterval(function () {
for (var i = 0; i < mData.length; i++) {
mData[i] += (Math.random() * 50 - 25);
if (mData[i] < 0) {
mData[i] = 0;
}
}
myCharts.setOption({
series: [{
data: mData
}]
});
}, 1000);
// 渲染浏览器分布
var llqCharts = echarts.init(document.getElementById('llq'));
var llqOptions = {
tooltip: {
trigger: 'item'
},
legend: {
bottom: '1%',
left: 'center',
icon: 'circle', // 设置小圆点
itemWidth: 10, // 设置宽度
itemHeight: 10, // 设置高度
},
series: [
{
name: '浏览器分布',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '14px',
}
},
labelLine: {
show: false
},
data: [
{value: 1048, name: 'Chrome'},
{value: 735, name: 'Safair'},
{value: 580, name: 'Firefox'},
{value: 484, name: 'Edge'},
{value: 300, name: 'IE'},
{value: 200, name: 'Other'},
]
}
]
};
llqCharts.setOption(llqOptions);
// 窗口大小改变事件
window.onresize = function () {
myCharts.resize();
mapCharts.resize();
fwlCharts.resize();
zfbsCharts.resize();
llqCharts.resize();
};
</script>
{/block}
<!-- /脚本 -->
+173
View File
@@ -0,0 +1,173 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api;
use think\App;
use think\exception\HttpResponseException;
use think\facade\Request;
use think\facade\Session;
use think\facade\View;
use think\Response;
/**
* 控制器基础类
*/
abstract class BaseController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
/**
* 分页数量
* @var string
*/
protected $pageSize = '';
/**
* 无需登录验证的接口
* @var array
*/
protected $noNeedLogin = ['bifill'];
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
$this->module = strtolower(app('http')->getName());
$this->controller = strtolower($this->request->controller());
$this->action = strtolower($this->request->action());
$this->uid = 0;
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{
// 调用 Auth 中间件
$this->app->middleware->add(\app\api\middleware\Auth::class);
// 检测权限
$this->checkLogin();
// 每页显示数据量
$this->pageSize = Request::param('page_size', \think\facade\Config::get('app.page_size'));
// 显示当前登录账户权限
// $this->showLoginUserInfo();
}
/**
* 显示当前登录账户信息
*/
protected function showLoginUserInfo()
{
$session_admin = get_config('app.session_admin');
if (Session::has($session_admin)) {
$loginUser = Session::get($session_admin);
// 输出当前登录账户信息
// echo '当前登录账户信息:' . $loginUser['username'];
}
}
/**
* 验证用户登录
*/
protected function checkLogin()
{
// 检查当前方法是否在无需登录列表中
if (in_array($this->action, $this->noNeedLogin)) {
return; // 跳过登录验证
}
$session_admin = get_config('app.session_admin');
if (!Session::has($session_admin)) {
$this->apiError('请先登录');
} else {
$this->uid = Session::get($session_admin)['id'];
View::assign('login_user', $this->uid);
}
}
/**
* Api处理成功结果返回方法
* @param $message
* @param null $redirect
* @param null $extra
* @return mixed
* @throws ReturnException
*/
protected function apiSuccess($msg = 'success', $data = [])
{
return $this->apiReturn($data, 0, $msg);
}
/**
* Api处理结果失败返回方法
* @param $error_code
* @param $message
* @param null $redirect
* @param null $extra
* @return mixed
* @throws ReturnException
*/
protected function apiError($msg = 'fail', $data = [], $code = 1)
{
return $this->apiReturn($data, $code, $msg);
}
/**
* 返回封装后的API数据到客户端
* @param mixed $data 要返回的数据
* @param integer $code 返回的code
* @param mixed $msg 提示信息
* @param string $type 返回数据格式
* @param array $header 发送的Header信息
* @return Response
*/
protected function apiReturn($data, int $code = 0, $msg = '', string $type = '', array $header = []): Response
{
$result = [
'code' => $code,
'msg' => $msg,
'time' => time(),
'data' => $data,
];
$type = $type ?: 'json';
$response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response);
}
}
+6
View File
@@ -0,0 +1,6 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
+183
View File
@@ -0,0 +1,183 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use think\facade\Db;
class Appendix extends BaseController
{
//添加修改
public function add()
{
$param = get_params();
$param['create_time'] = time();
$param['admin_id'] = $this->uid;
$fid = Db::name('FileInterfix')->strict(false)->field(true)->insertGetId($param);
if ($fid) {
$log_data = array(
'module' => $param['module'],
'field' => 'file',
'action' => 'upload',
$param['module'] . '_id' => $param['topic_id'],
'admin_id' => $this->uid,
'old_content' => '',
'new_content' => $param['file_name'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, '', $fid);
}
}
//删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$detail = Db::name('FileInterfix')->where('id', $id)->find();
if (Db::name('FileInterfix')->where('id', $id)->delete() !== false) {
$file_name = Db::name('File')->where('id', $detail['file_id'])->value('name');
$log_data = array(
'module' => $detail['module'],
'field' => 'file',
'action' => 'delete',
$detail['module'] . '_id' => $detail['topic_id'],
'admin_id' => $this->uid,
'new_content' => $file_name,
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "删除成功");
} else {
return to_assign(0, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
//链接添加修改
public function add_link()
{
$param = get_params();
$validate = \think\facade\Validate::rule([
'url' => 'url',
]);
if (!$validate->check($param)) {
return to_assign(1, $validate->getError());
}
if (!empty($param['id']) && $param['id'] > 0) {
$param['update_time'] = time();
$res = Db::name('LinkInterfix')->where('id', $param['id'])->strict(false)->field(true)->update($param);
if ($res) {
$log_data = array(
'module' => $param['module'],
'field' => 'link',
'action' => 'edit',
$param['module'] . '_id' => $param['topic_id'],
'admin_id' => $this->uid,
'old_content' => $param['url'],
'new_content' => $param['desc'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, '编辑成功');
}
} else {
$param['create_time'] = time();
$param['admin_id'] = $this->uid;
$lid = Db::name('LinkInterfix')->strict(false)->field(true)->insertGetId($param);
if ($lid) {
$log_data = array(
'module' => $param['module'],
'field' => 'link',
'action' => 'add',
$param['module'] . '_id' => $param['topic_id'],
'admin_id' => $this->uid,
'new_content' => $param['desc'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, '添加成功', $lid);
}
}
}
//删除
public function delete_link()
{
if (request()->isDelete()) {
$id = get_params("id");
$detail = Db::name('LinkInterfix')->where('id', $id)->find();
if (Db::name('LinkInterfix')->where('id', $id)->update(['delete_time' => time()]) !== false) {
$log_data = array(
'module' => $detail['module'],
'field' => 'link',
'action' => 'delete',
$detail['module'] . '_id' => $detail['topic_id'],
'admin_id' => $this->uid,
'new_content' => $detail['desc'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "删除成功");
} else {
return to_assign(0, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
//添加联系人
public function add_contact()
{
$param = get_params();
if (!empty($param['id']) && $param['id'] > 0) {
$param['update_time'] = time();
$res = BusinessContact::where(['admin_id' => $this->uid, 'id' => $param['id']])->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param);
return to_assign();
}
} else {
$param['create_time'] = time();
$param['admin_id'] = $this->uid;
$cid = BusinessContact::strict(false)->field(true)->insertGetId($param);
if ($cid) {
add_log('add', $cid, $param);
//sendMessage($users,1,['title'=>$param['title'],'action_id'=>$sid]);
return to_assign();
}
}
}
//删除联系人
public function delete_contact()
{
if (request()->isDelete()) {
$id = get_params("id");
$detail = Businesscontact::where(['admin_id' => $this->uid, 'id' => $id])->find();
if (Businesscontact::where(['admin_id' => $this->uid, 'id' => $id])->update(['delete_time' => time()]) !== false) {
add_log('delete', $id, $detail);
return to_assign(0, "删除成功");
} else {
return to_assign(0, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+94
View File
@@ -0,0 +1,94 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use think\facade\Db;
class Business extends BaseController
{
//添加联系人
public function add_contact()
{
$param = get_params();
if (request()->isPost()) {
$has = Db::name('Businesscontact')->where(['contact' => $param['contact'], 'phone' => $param['phone'], 'business_id' => $param['business_id']])->find();
if (!empty($has)) {
to_assign(1, '该联系人已经存在');
}
$param['admin_id'] = $this->uid;
$param['create_time'] = time();
$res = Db::name('Businesscontact')->strict(false)->field(true)->insert($param);
if ($res) {
$log_data = array(
'module' => 'businesscontact',
'field' => 'contact',
'action' => 'add',
'admin_id' => $this->uid,
'new_content' => $param['contact'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "添加联系人成功!");
}
}
}
//编辑联系人
public function edit_contact()
{
$param = get_params();
print_r($param);
if (request()->isPost()) {
$param['admin_id'] = $this->uid;
$param['update_time'] = time();
$res = Db::name('Businesscontact')->where('id', $param['id'])->strict(false)->field(true)->update($param);
// $res = Db::name('Businesscontact')->where('id',$param['id'])->strict(false)->field(true)->update($param);
if ($res) {
$log_data = array(
'module' => 'businesscontact',
'field' => 'contact',
'action' => 'edit',
'admin_id' => $this->uid,
'new_content' => $param['contact'],
'update_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "修改联系人成功!");
}
}
}
//删除联系人
public function delete_contact()
{
if (request()->isDelete()) {
$id = get_params("id");
$time = time();
$module = 'Business';
$detail = Db::name('Businesscontact')->where('id', $id)->find();
if (Db::name('Businesscontact')->where('id', $id)->update(['delete_time' => $time]) !== false) {
$log_data = array(
'field' => 'contact',
'action' => 'delete',
'admin_id' => $this->uid,
'new_content' => $detail['contact'],
'create_time' => $time,
'module' => $module,
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "删除成功");
} else {
return to_assign(0, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+118
View File
@@ -0,0 +1,118 @@
<?php
/**
* @copyright Copyright (c)
* @company 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use think\facade\Db;
class BusinessInfo extends BaseController
{
//商机填写接口
public function bifill()
{
// 允许来自kd.meteteme.top的跨域请求
header('Access-Control-Allow-Origin: https://kd.meteteme.top');
header('Access-Control-Allow-Origin: http://test1.mete.com/');
header('Access-Control-Allow-Headers: Content-Type');
// 获取表单数据
$name = isset($_POST['name']) ? $_POST['name'] : '';
$email = isset($_POST['email']) ? $_POST['email'] : '';
$phone = isset($_POST['phone']) ? $_POST['phone'] : '';
$ip = isset($_POST['IP']) ? $_POST['IP'] : '';
$message = isset($_POST['message']) ? $_POST['message'] : '';
$product = isset($_POST['product']) ? $_POST['product'] : '';
$company = isset($_POST['company']) ? $_POST['company'] : '';
$create_time = time();
// 判断表单数据是否完整
if ($name && $message && $product) {
// 向数据库插入数据
$result = Db::name('Information')->insert([
'name' => $name,
'email' => $email,
'phone' => $phone,
'ip' => $ip,
'message' => $message,
'product' => $product,
'company' => $company,
'create_time' => $create_time,
]);
// 判断插入结果
if ($result) {
$webhook = 'https://oapi.dingtalk.com/robot/send?access_token=c39726abd36659f92442847430eda90bebb360c438270f7c05bea388f1c8168c';
$title = '**有新的商机生成!**';
$line = '------------------------------';
$companynames = '公司名称:' . $company;
$names = '联 系 人 ' . $name;
$contents = '请及时进入项管系统查看!';
$times = '创建日期:' . date('Y-m-d H:i:s', $create_time);
$data = array(
'msgtype' => 'actionCard',
'actionCard' => array(
'title' => $title,
'text' => $title . "\n\n" . $companynames . "\n\n" . $names . "\n\n" . $times,
'btnOrientation' => '0',
'btns' => [
[
'title' => '查看商机',
'actionURL' => 'dingtalk://dingtalkclient/page/link?url=' . urlencode('https://project.meteteme.com/business_info/index/index') . '&pc_slide=false'
]
]
)
);
$options = array(
'http' => array(
'header' => "Content-type: application/json",
'method' => 'POST',
'content' => json_encode($data),
)
);
$context = stream_context_create($options);
$result = file_get_contents($webhook, false, $context);
// return json(['code' => 0, 'msg' => '留言提交成功!']);
return json([
'code' => 0,
'msg' => '留言提交成功!',
'data' => [
'name' => $name,
'email' => $email,
'phone' => $phone,
'ip' => $ip,
'message' => $message,
'product' => $product,
'company' => $company,
'create_time' => date('Y-m-d H:i:s', $create_time)
]
]);
} else {
return json(['code' => 1, 'msg' => '留言提交失败!']);
}
} else {
return json(['code' => 2, 'msg' => '请填写完整的表单数据!']);
}
}
//获取产品信息
public function product_info()
{
// 查询Product表中的所有产品信息
$products = Db::name('Product')->field('id, name')->select();
// 返回产品信息数组给前端,包括id和name
return json(['code' => 0, 'msg' => '获取产品信息成功', 'data' => $products]);
}
}
+79
View File
@@ -0,0 +1,79 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use app\model\Comment as CommentList;
use app\model\Admin as AdminList;
use think\facade\Db;
use think\facade\Session;
class Comment extends BaseController
{
//获取评论列表
public function get_list()
{
$param = get_params();
$contents = CommentList::where(['topic_id' => $param['tid'], 'module' => $param['m']])->select();
// 获取所有admin_id
$adminIds = array_unique(array_column($contents->toArray(), 'admin_id'));
// 查询Admin表获取名称
$admins = AdminList::whereIn('id', $adminIds)->column('name', 'id');
$thumb = AdminList::whereIn('id', $adminIds)->column('thumb', 'id');
// 加工数据,添加管理员名称
foreach ($contents as $content) {
$content['name'] = $admins[$content['admin_id']] ?? '未知';
$content['thumb'] = $thumb[$content['admin_id']] ?? '未知';
}
return to_assign(0, '', $contents);
}
//添加修改评论内容
public function add()
{
$param = get_params();
if (!empty($param['id']) && $param['id'] > 0) {
$param['update_time'] = time();
$res = CommentList::where(['admin_id' => $this->uid, 'id' => $param['id']])->strict(false)->field(true)->update($param);
if ($res) {
add_log('edit', $param['id'], $param);
return to_assign();
}
} else {
$param['create_time'] = time();
$param['admin_id'] = $this->uid;
$cid = CommentList::strict(false)->field(true)->insertGetId($param);
if ($cid) {
add_log('add', $cid, $param);
//sendMessage($users,1,['title'=>$param['title'],'action_id'=>$sid]);
return to_assign();
}
}
}
//删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$res = CommentList::where('id', $id)->strict(false)->field(true)->update(['delete_time' => time()]);
if ($res) {
add_log('delete', $id);
return to_assign(0, "删除成功");
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use think\facade\Db;
use think\facade\View;
use app\api\controller\Schedule;
class Dingdingrobot extends BaseController
{
public function sendto()
{
// 获取前端传递的消息
$message = $this->request->param('message');
// 警保项目群机器人地址
$webhook1 = 'https://oapi.dingtalk.com/robot/send?access_token=46ad1d7d5aa6e365a50a1a08608f1d89f16031a658bf729c32f38d369bcfc520';
// 功能测试群机器人地址
$webhook2 = 'https://oapi.dingtalk.com/robot/send?access_token=4448cd3d356856f7f91739b832f3ef466c2c1d8df6ce43a80e02661b6cfc3ea3';
// 选择要使用的webhook地址
$webhook = $webhook2;
// 定义消息内容
$content = [
'msgtype' => 'text',
'text' => [
'content' => $message
]
];
// 将消息内容转换为json格式
$jsonContent = json_encode($content);
$options = [
'http' => [
'header' => 'Content-Type: application/json',
'method' => 'POST',
'content' => $jsonContent
]
];
$context = stream_context_create($options);
$result = file_get_contents($webhook, false, $context);
if ($result === false) {
// 发送失败
return '消息发送失败!';
} else {
// 发送成功
return '消息发送成功!';
}
}
}
+143
View File
@@ -0,0 +1,143 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use app\model\Document as DocumentList;
use think\facade\Db;
use think\facade\View;
class Document extends BaseController
{
//获取文档列表
public function get_list()
{
$param = get_params();
$model = new DocumentList();
$list = $model->get_list($param);
return to_assign(0, '', $list);
}
//添加修改
public function add()
{
$param = get_params();
if (request()->isPost()) {
//markdown数据处理
if (isset($param['table-align'])) {
unset($param['table-align']);
}
if (isset($param['docContent-html-code'])) {
$param['content'] = $param['docContent-html-code'];
$param['md_content'] = $param['docContent-markdown-doc'];
unset($param['docContent-html-code']);
unset($param['docContent-markdown-doc']);
}
if (isset($param['ueditorcontent'])) {
$param['content'] = $param['ueditorcontent'];
$param['md_content'] = '';
}
if (!empty($param['id']) && $param['id'] > 0) {
$param['update_time'] = time();
printf($param->uid);
$detail = (new DocumentList())->detail($param['id']);
$res = DocumentList::where('id', $param['id'])->strict(false)->field(true)->update($param);
if ($res) {
$log_data = array(
'module' => 'document',
'field' => 'document',
'action' => 'edit',
'document_id' => $param['id'],
'admin_id' => $this->uid,
'old_content' => $detail['content'],
'new_content' => $param['content'],
'remark' => $param['title'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
}
return to_assign();
} else {
$param['create_time'] = time();
$param['admin_id'] = $this->uid;
$sid = DocumentList::strict(false)->field(true)->insertGetId($param);
if ($sid) {
$log_data = array(
'module' => 'document',
'field' => 'document',
'action' => 'add',
'document_id' => $sid,
'admin_id' => $this->uid,
'remark' => $param['title'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
}
return to_assign();
}
} else {
$id = isset($param['id']) ? $param['id'] : 0;
if ($id > 0) {
$detail = (new DocumentList())->detail($id);
if (empty($detail)) {
return to_assign(1, '文档不存在');
}
View::assign('project_id', $detail['topic_id']);
View::assign('detail', $detail);
}
if (isset($param['project_id'])) {
View::assign('project_id', $param['project_id']);
}
View::assign('id', $id);
return view();
}
}
//查看
public function view()
{
$param = get_params();
$id = isset($param['id']) ? $param['id'] : 0;
$detail = (new DocumentList())->detail($id);
if (empty($detail)) {
return to_assign(1, '文档不存在');
} else {
View::assign('detail', $detail);
View::assign('id', $id);
return view();
}
}
//删除
public function delete()
{
if (request()->isDelete()) {
$id = get_params("id");
$detail = (new DocumentList())->detail($id);
if (DocumentList::where('id', $id)->update(['delete_time' => time()]) !== false) {
$log_data = array(
'module' => $detail['module'],
'field' => 'document',
'action' => 'delete',
'document_id' => $param['id'],
'admin_id' => $this->uid,
'remark' => $detail['title'],
'new_content' => '',
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "删除成功");
} else {
return to_assign(0, "删除失败");
}
} else {
return to_assign(1, "错误的请求");
}
}
}
+591
View File
@@ -0,0 +1,591 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use think\facade\Db;
use think\Response;
use app\model\PicbedImages as PicbedList;
class Index extends BaseController
{
//上传文件
public function upload()
{
$param = get_params();
if (request()->file('file')) {
$file = request()->file('file');
} else {
return to_assign(1, '没有选择上传文件');
}
// dump($file);die;
// 获取上传文件的hash散列值
$sha1 = $file->hash('sha1');
$md5 = $file->hash('md5');
$rule = [
'image' => 'jpg,png,jpeg,gif,ai,psd',
'doc' => 'txt,doc,docx,ppt,pptx,xls,xlsx,pdf,xmind,drawio',
'file' => 'zip,gz,7z,rar,tar',
'video' => 'mpg,mp4,mpeg,avi,wmv,mov,flv,m4v',
];
$fileExt = $rule['image'] . ',' . $rule['doc'] . ',' . $rule['file'] . ',' . $rule['video'];
//1M=1024*1024=1048576字节
$fileSize = 100 * 1024 * 1024;
if (isset($param['type']) && $param['type']) {
$fileExt = $rule[$param['type']];
}
if (isset($param['size']) && $param['size']) {
$fileSize = $param['size'];
}
$validate = \think\facade\Validate::rule([
'image' => 'require|fileSize:' . $fileSize . '|fileExt:' . $fileExt,
]);
$file_check['image'] = $file;
if (!$validate->check($file_check)) {
return to_assign(1, $validate->getError());
}
// 日期前綴
$dataPath = date('Ym');
$use = 'thumb';
$filename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file, function () use ($md5) {
return $md5;
});
if ($filename) {
//写入到附件表
$data = [];
$path = get_config('filesystem.disks.public.url');
$data['filepath'] = $path . '/' . $filename;
$data['name'] = $file->getOriginalName();
$data['mimetype'] = $file->getOriginalMime();
$data['fileext'] = $file->extension();
$data['filesize'] = $file->getSize();
$data['filename'] = $filename;
$data['sha1'] = $sha1;
$data['md5'] = $md5;
$data['module'] = \think\facade\App::initialize()->http->getName();
$data['action'] = app('request')->action();
$data['uploadip'] = app('request')->ip();
$data['create_time'] = time();
$data['user_id'] = $this->uid;
if ($data['module'] = 'admin') {
//通过后台上传的文件直接审核通过
$data['status'] = 1;
$data['admin_id'] = $data['user_id'];
$data['audit_time'] = time();
}
$data['use'] = request()->has('use') ? request()->param('use') : $use; //附件用处
$res['id'] = Db::name('file')->insertGetId($data);
$res['filepath'] = $data['filepath'];
$res['name'] = $data['name'];
$res['filename'] = $data['filename'];
$res['filesize'] = $data['filesize'];
add_log('upload', $data['user_id'], $data);
return to_assign(0, '上传成功', $res);
} else {
return to_assign(1, '上传失败,请重试');
}
}
// 图床上传
public function upload_picbed()
{
if (request()->file('file')) {
// 获取文件信息
$file = request()->file('file');
$file_name = $file->getOriginalName();
$file_size = $file->getSize();
$file_type = $file->getMime();
$file_extension = pathinfo($file->getOriginalName(), PATHINFO_EXTENSION);
// 检查文件类型
$allowed_types = Db::name('FileType')->column('suffix');
if (!in_array($file_extension, $allowed_types)) {
return json(['code' => 1, 'msg' => '该文件类型不允许上传!请联系管理员!']);
}
// 检查文件大小
$max_file_size = 10 * 1024 * 1024; // 10MB
if ($file_size > $max_file_size) {
return json(['code' => 2, 'msg' => '文件过大,已经超过10M,请联系管理员!']);
}
// 创建文件夹
$upload_dir = 'upload/' . date('Y-m-d') . '/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
// 生成新文件名
$new_name = $this->generateRandomName(5) . '.' . $file_extension;
// 保存文件
$file->move($upload_dir, $new_name);
// 添加数据到数据库
$data = [
'name' => $file_name,
'new_name' => $new_name,
'path' => $upload_dir . $new_name,
'admin_id' => $this->uid,
'size' => $file_size,
'type' => $file_extension,
'create_time' => time()
];
Db::name('PicbedImages')->insert($data);
// 获取文件上传域名
$fileDomain = $_SERVER['HTTP_HOST'];
// 构建文件访问地址
$url = $fileDomain . '/upload/' . date('Y-m-d') . '/' . $new_name;
// 返回 JSON 数据
return json([
'code' => 200,
'msg' => '文件上传成功!',
'fileDomain' => $fileDomain,
'filename' => $file_name,
'filepath' => $upload_dir . $new_name,
'url' => $url,
'admin_id' => $this->uid
]);
} else {
return json(['code' => 400, 'msg' => '未选择上传文件!']);
}
}
// 生成随机文件名
private function generateRandomName($length)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$random_name = '';
for ($i = 0; $i < $length; $i++) {
$random_name .= $characters[rand(0, strlen($characters) - 1)];
}
return $random_name;
}
// 外部站点上传图片到本站接口
public function upload_pic_out()
{
if (request()->file('file')) {
// 获取文件信息
$file = request()->file('file');
$file_name = $file->getOriginalName();
$file_size = $file->getSize();
$file_type = $file->getMime();
$file_extension = pathinfo($file->getOriginalName(), PATHINFO_EXTENSION);
// 检查文件类型
$allowed_types = Db::name('FileType')->column('suffix');
if (!in_array($file_extension, $allowed_types)) {
return json(['code' => 1, 'msg' => '该文件类型不允许上传!请联系管理员!'], 400);
}
// 获取文件上传域名
$fileDomain = '//' . $_SERVER['HTTP_HOST'];
// 检查文件大小
$max_file_size = 10 * 1024 * 1024; // 10MB
if ($file_size > $max_file_size) {
return json(['code' => 2, 'msg' => '文件过大,已经超过10M,请联系管理员!'], 400);
}
// 创建文件夹
$upload_dir = './upload/' . date('Y-m-d') . '/';
$upload_dir_1 = '/upload/' . date('Y-m-d') . '/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
// 生成新文件名
$file_extension = pathinfo($file->getOriginalName(), PATHINFO_EXTENSION);
$new_name = $this->generateRandomName(5) . '.' . $file_extension;
// 保存文件
$file_destination = $upload_dir . $new_name;
$file_destination1 = $upload_dir_1 . $new_name;
$result = $file->move($upload_dir, $new_name);
if (!$result) {
return json(['code' => 3, 'msg' => '文件保存失败'], 400);
}
$file_name = urlencode($file_name);
// 添加数据到数据库
$data = [
'name' => $file_name,
'new_name' => $new_name,
'path' => $file_destination,
'admin_id' => request()->param('pr_name'),
'size' => $file_size,
'type' => $file_type,
'create_time' => time()
];
// 检查 admin_id 是否为空
if (empty($data['admin_id'])) {
return json(['code' => 4, 'msg' => '上传失败,缺少 pr_name 参数!'], 400);
}
Db::name('PicbedImages')->insert($data);
// 构建文件访问地址
$url = $_SERVER['HTTP_HOST'] . '/upload/' . date('Y-m-d') . '/' . $new_name;
// 构建响应数据
$response_data = [
'code' => 5,
'msg' => '文件上传成功!',
'filename' => $file_name,
'fileDomain' => $fileDomain,
'filepath' => $file_destination1,
'url' => $url
];
// 返回 JSON 格式的响应数据
return json($response_data, 200);
} else {
return json(['code' => 6, 'msg' => '未选择上传文件!'], 400);
}
}
//编辑器图片上传
public function tinymce_upload()
{
$param = get_params();
if (request()->file('file')) {
$file = request()->file('file');
} else {
return json(['error' => 1, 'message' => '没有选择上传文件']);
}
// 获取上传文件的hash散列值
$sha1 = $file->hash('sha1');
$md5 = $file->hash('md5');
$rule = [
'image' => 'jpg,png,jpeg,gif',
'doc' => 'doc,docx,ppt,pptx,xls,xlsx,pdf,txt',
'file' => 'zip,gz,7z,rar,tar',
];
$fileExt = $rule['image'] . ',' . $rule['doc'] . ',' . $rule['file'];
$fileSize = 2 * 1024 * 1024; // 默认文件大小限制
if (isset($param['type']) && $param['type']) {
$fileExt = $rule[$param['type']];
}
if (isset($param['size']) && $param['size']) {
$fileSize = $param['size'];
}
$validate = \think\facade\Validate::rule([
'image' => 'require|fileSize:' . $fileSize . '|fileExt:' . $fileExt,
]);
$file_check['image'] = $file;
if (!$validate->check($file_check)) {
return json(['error' => 1, 'message' => $validate->getError()]);
}
$dataPath = date('Ym');
$filename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file, function () use ($md5) {
return $md5;
});
if ($filename) {
$path = get_config('filesystem.disks.public.url');
$filepath = $path . '/' . $filename;
return json(['location' => $filepath]); // Tinymce 需要的关键字段是 'location'
} else {
return json(['error' => 1, 'message' => '上传失败']);
}
}
public function md_upload()
{
$param = get_params();
if (request()->file('editormd-image-file')) {
$file = request()->file('editormd-image-file');
} else {
return to_assign(1, '没有选择上传文件');
}
// dump($file);die;
// 获取上传文件的hash散列值
$sha1 = $file->hash('sha1');
$md5 = $file->hash('md5');
$rule = [
'image' => 'jpg,png,jpeg,gif',
'doc' => 'doc,docx,ppt,pptx,xls,xlsx,pdf',
'file' => 'zip,gz,7z,rar,tar',
];
$fileExt = $rule['image'] . ',' . $rule['doc'] . ',' . $rule['file'];
//1M=1024*1024=1048576字节
$fileSize = 2 * 1024 * 1024;
if (isset($param['type']) && $param['type']) {
$fileExt = $rule[$param['type']];
}
if (isset($param['size']) && $param['size']) {
$fileSize = $param['size'];
}
$validate = \think\facade\Validate::rule([
'image' => 'require|fileSize:' . $fileSize . '|fileExt:' . $fileExt,
]);
$file_check['image'] = $file;
if (!$validate->check($file_check)) {
return to_assign(1, $validate->getError());
}
// 日期前綴
$dataPath = date('Ym');
$use = 'thumb';
$filename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file, function () use ($md5) {
return $md5;
});
if ($filename) {
//写入到附件表
$data = [];
$path = get_config('filesystem.disks.public.url');
$data['filepath'] = $path . '/' . $filename;
$data['name'] = $file->getOriginalName();
$data['mimetype'] = $file->getOriginalMime();
$data['fileext'] = $file->extension();
$data['filesize'] = $file->getSize();
$data['filename'] = $filename;
$data['sha1'] = $sha1;
$data['md5'] = $md5;
return json(['success' => 1, 'message' => '上传成功', 'url' => $data['filepath']]);
} else {
return json(['success' => 0, 'message' => '上传失败', 'url' => '']);
}
}
//清空缓存
public function cache_clear()
{
\think\facade\Cache::clear();
return to_assign(0, '系统缓存已清空');
}
//获取部门树形节点列表
public function get_department_tree()
{
$department = get_department();
$list = get_tree($department, 0, 2);
$data['trees'] = $list;
return json($data);
}
//获取部门树形节点列表2
public function get_department_select()
{
$keyword = get_params('keyword');
$selected = [];
if (!empty($keyword)) {
$selected = explode(",", $keyword);
}
$department = get_department();
$list = get_select_tree($department, 0, 0, $selected);
return to_assign(0, '', $list);
}
//获取子部门所有员工
public function get_employee($did = 0)
{
$did = get_params('did');
/*
if ($did == 1) {
$department = $did;
} else {
$department = get_department_son($did);
}
*/
$department = get_department_son($did);
$employee = Db::name('admin')
->field('a.id,a.did,a.position_id,a.mobile,a.name,a.nickname,a.sex,a.status,a.thumb,a.username,d.title as department')
->alias('a')
->join('Department d', 'a.did = d.id')
->where(['a.status' => 1])
->where('a.did', "in", $department)
->select();
return to_assign(0, '', $employee);
}
//获取部门所有员工
public function get_employee_select()
{
$employee = Db::name('admin')->field('id as value,name')->where(['status' => 1])->select();
return to_assign(0, '', $employee);
}
//获取角色列表
public function get_position()
{
$position = Db::name('Position')->field('id,title as name')->where([['status', '=', 1], ['id', '>', 1]])->select();
return to_assign(0, '', $position);
}
//获取工作类型列表
public function get_work()
{
$cate = Db::name('WorkCate')->field('id,title')->where([['status', '=', 1]])->select();
return to_assign(0, '', $cate);
}
//获取任务类型列表
public function get_task_cate()
{
$cate = Db::name('TaskCate')->field('id,title')->where([['status', '=', 1]])->select();
return to_assign(0, '', $cate);
}
//获取产品列表
public function get_product()
{
$product = Db::name('Product')->field('id,name as title')->where([['delete_time', '=', 0]])->select();
return to_assign(0, '', $product);
}
//获取客户列表
public function get_business()
{
$business = Db::name('Business')->field('id,name as title')->where([['delete_time', '=', 0]])->select();
return to_assign(0, '', $business);
}
//获取项目列表
public function get_project($pid = 0)
{
$where = [];
$where[] = ['delete_time', '=', 0];
if ($pid > 0) {
$where[] = ['product_id', '=', $pid];
}
$project = Db::name('Project')->field('id,name as title')->where($where)->select();
//$belong_project = Db::name('Project')->field('id,name_short as title')->where($where)->select();
return to_assign(0, '', $project);
}
//获取所属项目短名
public function get_belong_project()
{
$where = [];
$where[] = ['delete_time', '=', 0];
if ($pid > 0) {
$where[] = ['product_id', '=', $pid];
}
$belong_project = Db::name('Project')->field('id,name_short as title')->where($where)->select();
return to_assign(0, '', $belong_project);
}
//文档列表
public function get_doc_list($kid = 0, $tree = 0)
{
if ($tree == 2) {
$list = Db::name('knowledgeDoc')->where(['knowledge_id' => $kid, 'delete_time' => 0])
->field('id,pid as pId,title as name,type,link,knowledge_id,sort,read')
->order('sort asc,id asc')
->select();
return to_assign(0, '', $list);
} else {
$list = Db::name('knowledgeDoc')->where(['knowledge_id' => $kid, 'delete_time' => 0])
->field('id,pid,title,type,knowledge_id,sort,read')
->order('sort asc,id asc')
->select();
if ($tree == 1) {
foreach ($list as $k => &$v) {
$v['title'] = sub_str($v['title'], 9);
}
$tree = get_tree($list, 0, 4);
$data['trees'] = $tree;
return json($data);
} else {
return to_assign(0, '', $list);
}
}
}
//删除消息附件
public function del_message_interfix()
{
$id = get_params("id");
$detail = Db::name('MessageFileInterfix')->where('id', $id)->find();
if ($detail['admin_id'] == $this->uid) {
if (Db::name('MessageFileInterfix')->where('id', $id)->delete() !== false) {
$data = Db::name('MessageFileInterfix')->where('mid', $detail['mid'])->column('file_id');
return to_assign(0, "删除成功", $data);
} else {
return to_assign(1, "删除失败");
}
} else {
return to_assign(1, "您没权限删除该消息附件");
}
}
// 测试邮件发送
public function email_test()
{
$sender = get_params('email');
//检查是否邮箱格式
if (!is_email($sender)) {
return to_assign(1, '测试邮箱码格式有误');
}
$email_config = \think\facade\Db::name('config')->where('name', 'email')->find();
$config = unserialize($email_config['content']);
$content = $config['template'];
//所有项目必须填写
if (empty($config['smtp']) || empty($config['smtp_port']) || empty($config['smtp_user']) || empty($config['smtp_pwd'])) {
return to_assign(1, '请完善邮件配置信息!');
}
$send = send_email($sender, '测试邮件', $content);
if ($send) {
return to_assign(0, '邮件发送成功!');
} else {
return to_assign(1, '邮件发送失败!');
}
}
public function get_captcha()
{
return captcha();
}
// 新增接口
public function pullart()
{
// 允许来自任何来源的跨域请求
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Content-Type');
$images = Db::name('PicbedImages')->order('id', 'desc')->select()->toArray();
// 获取当前请求的域名
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$baseUrl = $protocol . '://' . $host;
// 筛选出只需要的字段并拼接完整路径
$images = array_map(function ($image) use ($baseUrl) {
return [
'name' => htmlspecialchars($image['name'], ENT_QUOTES),
'path' => $baseUrl . '/' . $image['path'],
];
}, $images);
return json(['code' => 0, 'msg' => '', 'data' => $images]);
}
public function getallstaff(){
$employees = Db::name('admin')
->field('id, name, status') // 根据需要选择字段
->where('status', 1) // 只获取在职员工
->select();
return to_assign(0, '', $employees);
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use app\model\Log as LogList;
use think\facade\Db;
use think\facade\Session;
class Log extends BaseController
{
//获取日志列表
public function get_list()
{
$param = get_params();
$list = new LogList();
$content = $list->get_list($param);
return to_assign(0, '', $content);
}
//获取日志列表
public function log_list()
{
$param = get_params();
$list = new LogList();
$content = $list->log_list($param);
return to_assign(0, '', $content);
}
}
+460
View File
@@ -0,0 +1,460 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use think\facade\Db;
use think\facade\View;
class Project extends BaseController
{
public function view()
{
$param = get_params();
View::assign('id', $param['id']);
View::assign('user_info', get_login_admin());
return view('view_' . $param['page']);
}
public function get_chart_data()
{
$param = get_params();
$tasks = Db::name('Task')->field('id,plan_hours,end_time,flow_status,over_time')->order('end_time asc')->where([['project_id', '=', $param['project_id']], ['delete_time', '=', 0], ['is_bug', '=', 0]])->select()->toArray();
$task_count = count($tasks);
$task_count_ok = Db::name('Task')->where([['project_id', '=', $param['project_id']], ['delete_time', '=', 0], ['is_bug', '=', 0], ['flow_status', '>', 2]])->count();
$task_delay = 0;
if ($task_count > 0) {
foreach ($tasks as $k => $v) {
if (($v['flow_status'] < 3) && ($v['end_time'] < time() - 86400)) {
$task_delay++;
}
if (($v['flow_status'] == 3) && ($v['end_time'] < $v['over_time'] - 86400)) {
$task_delay++;
}
}
}
$task_pie = [
'count' => $task_count,
'count_ok' => $task_count_ok,
'delay' => $task_delay,
'ok_lv' => $task_count == 0 ? 100 : round($task_count_ok * 100 / $task_count, 2),
'delay_lv' => $task_count == 0 ? 100 : round($task_delay * 100 / $task_count, 2),
];
$bugs = Db::name('Task')->field('id,flow_status')->order('end_time asc')->where(['delete_time' => 0, 'is_bug' => 1, 'project_id' => $param['project_id']])->select()->toArray();
$status_a = $status_b = $status_c = $status_d = $status_e = 0;
foreach ($bugs as $k => $v) {
if ($v['flow_status'] == 1) {
$status_a++;
} else if ($v['flow_status'] == 2) {
$status_b++;
} else if ($v['flow_status'] == 3) {
$status_c++;
} else if ($v['flow_status'] == 4) {
$status_d++;
} else if ($v['flow_status'] == 5) {
$status_e++;
}
}
$bug_status = [
'status_a' => $status_a,
'status_b' => $status_b,
'status_c' => $status_c,
'status_d' => $status_d,
'status_e' => $status_e,
];
$date_tasks = [];
if ($tasks) {
$date_tasks = plan_count($tasks);
}
$tasks_ok = Db::name('Task')->field('id,over_time as end_time')->order('over_time asc')->where([['over_time', '>', 0], ['delete_time', '=', 0], ['project_id', '=', $param['project_id']]])->select()->toArray();
$date_tasks_ok = [];
if ($tasks_ok) {
$date_tasks_ok = plan_count($tasks_ok);
}
$tids = Db::name('Task')->where(['delete_time' => 0, 'project_id' => $param['project_id']])->column('id');
$schedules = Db::name('Schedule')->where([['tid', 'in', $tids], ['delete_time', '=', 0]])->select()->toArray();
$date_schedules = [];
if ($schedules) {
$date_schedules = hour_count($schedules);
}
$res['task_pie'] = $task_pie;
$res['bug_status'] = $bug_status;
$res['date_tasks'] = $date_tasks;
$res['date_tasks_ok'] = $date_tasks_ok;
$res['date_schedules'] = $date_schedules;
to_assign(0, '', $res);
}
public function user()
{
$param = get_params();
$project = Db::name('Project')->where(['id' => $param['tid']])->find();
$users = Db::name('ProjectUser')
->field('pu.*,a.name,a.mobile,p.title as position,d.title as department')
->alias('pu')
->join('Admin a', 'pu.uid = a.id', 'LEFT')
->join('Department d', 'a.did = d.id', 'LEFT')
->join('Position p', 'a.position_id = p.id', 'LEFT')
->order('pu.id asc')
->where(['pu.project_id' => $param['tid']])
->select()->toArray();
if (!empty($users)) {
foreach ($users as $k => &$v) {
$v['role'] = 0; //普通项目成员
if ($v['uid'] == $project['admin_id']) {
$v['role'] = 1; //项目创建人
}
if ($v['uid'] == $project['director_uid']) {
$v['role'] = 2; //项目负责人
}
$v['create_time'] = date('Y-m-d', (int) $v['create_time']);
if ($v['delete_time'] > 0) {
$v['delete_time'] = date('Y-m-d', (int) $v['delete_time']);
}
$tids = Db::name('Task')->where([['project_id', '=', $param['tid']], ['delete_time', '=', 0]])->column('id');
$schedule_map = [];
$schedule_map[] = ['tid', 'in', $tids];
$schedule_map[] = ['delete_time', '=', 0];
$schedule_map[] = ['admin_id', '=', $v['uid']];
$v['schedules'] = Db::name('Schedule')->where($schedule_map)->count();
$v['labor_times'] = Db::name('Schedule')->where($schedule_map)->sum('labor_time');
$task_map = [];
$task_map[] = ['project_id', '=', $param['tid']];
$task_map[] = ['delete_time', '=', 0];
$task_map1 = [
['admin_id', '=', $v['uid']],
];
$task_map2 = [
['director_uid', '=', $v['uid']],
];
$task_map3 = [
['', 'exp', Db::raw("FIND_IN_SET('{$v['uid']}',assist_admin_ids)")],
];
//任务
$task_map_a = $task_map;
$task_map_a[] = ['is_bug', '=', 0];
//任务总数
$v['tasks_a_total'] = Db::name('Task')
->where(function ($query) use ($task_map1, $task_map2, $task_map3) {
$query->where($task_map1)->whereor($task_map2)->whereor($task_map3);
})
->where($task_map_a)->count();
//已完成任务
$task_map_a[] = ['flow_status', '>', 2]; //已完成
$v['tasks_a_finish'] = Db::name('Task')->where(function ($query) use ($task_map1, $task_map2, $task_map3) {
$query->where($task_map1)->whereor($task_map2)->whereor($task_map3);
})
->where($task_map_a)->count();
//未完成任务
$v['tasks_a_unfinish'] = $v['tasks_a_total'] - $v['tasks_a_finish'];
$v['tasks_a_pensent'] = "100";
if ($v['tasks_a_total'] > 0) {
$v['tasks_a_pensent'] = round($v['tasks_a_finish'] / $v['tasks_a_total'] * 100, 2) . "";
}
//缺陷
$task_map_b = $task_map;
$task_map_b[] = ['is_bug', '=', 1];
//缺陷总数
$v['tasks_b_total'] = Db::name('Task')
->where(function ($query) use ($task_map1, $task_map2, $task_map3) {
$query->where($task_map1)->whereor($task_map2)->whereor($task_map3);
})
->where($task_map_b)->count();
//已完成缺陷
$task_map_b[] = ['flow_status', '>', 2]; //已完成
$v['tasks_b_finish'] = Db::name('Task')->where(function ($query) use ($task_map1, $task_map2, $task_map3) {
$query->where($task_map1)->whereor($task_map2)->whereor($task_map3);
})
->where($task_map_b)->count();
//未完成缺陷
$v['tasks_b_unfinish'] = $v['tasks_b_total'] - $v['tasks_b_finish'];
$v['tasks_b_pensent'] = "100";
if ($v['tasks_b_total'] > 0) {
$v['tasks_b_pensent'] = round($v['tasks_b_finish'] / $v['tasks_b_total'] * 100, 2) . "";
}
}
}
to_assign(0, '', $users);
}
//新增项目成员
public function add_user()
{
$param = get_params();
if (request()->isPost()) {
$has = Db::name('ProjectUser')->where(['uid' => $param['uid'], 'project_id' => $param['project_id']])->find();
if (!empty($has)) {
to_assign(1, '该员工已经是项目成员');
}
$project = Db::name('Project')->where(['id' => $param['project_id']])->find();
if ($this->uid == $project['admin_id'] || $this->uid == $project['director_uid']) {
$param['admin_id'] = $this->uid;
$param['create_time'] = time();
$res = Db::name('ProjectUser')->strict(false)->field(true)->insert($param);
if ($res) {
$log_data = array(
'module' => 'project',
'field' => 'user',
'action' => 'add',
'project_id' => $param['project_id'],
'admin_id' => $this->uid,
'new_content' => $param['uid'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
to_assign();
}
} else {
to_assign(1, '只有项目创建者和负责人才有权限新增项目成员');
}
}
}
//移除项目成员
public function remove_user()
{
$param = get_params();
if (request()->isDelete()) {
$detail = Db::name('ProjectUser')->where(['id' => $param['id']])->find();
$project = Db::name('Project')->where(['id' => $detail['project_id']])->find();
if ($this->uid == $project['admin_id'] || $this->uid == $project['director_uid']) {
if ($detail['uid'] == $project['admin_id']) {
to_assign(1, '该项目成员是项目的创建者,不能移除');
}
if ($detail['uid'] == $project['director_uid']) {
to_assign(1, '该项目成员是项目的负责人,需要去除负责人权限才能移除');
}
$param['delete_time'] = time();
if (Db::name('ProjectUser')->update($param) !== false) {
$log_data = array(
'module' => 'project',
'field' => 'user',
'action' => 'remove',
'project_id' => $detail['project_id'],
'admin_id' => $this->uid,
'new_content' => $detail['uid'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "移除成功");
} else {
return to_assign(1, "移除失败");
}
} else {
to_assign(1, '只有项目创建者和负责人才有权限移除项目成员');
}
} else {
return to_assign(1, "错误的请求");
}
}
//恢复项目成员
public function recover_user()
{
$param = get_params();
if (request()->isPost()) {
$detail = Db::name('ProjectUser')->where(['id' => $param['id']])->find();
$project = Db::name('Project')->where(['id' => $detail['project_id']])->find();
if ($this->uid == $project['admin_id'] || $this->uid == $project['director_uid']) {
$param['delete_time'] = 0;
if (Db::name('ProjectUser')->update($param) !== false) {
$log_data = array(
'module' => 'project',
'field' => 'user',
'action' => 'recover',
'project_id' => $detail['project_id'],
'admin_id' => $this->uid,
'new_content' => $detail['uid'],
'create_time' => time(),
);
Db::name('Log')->strict(false)->field(true)->insert($log_data);
return to_assign(0, "恢复成功");
} else {
return to_assign(1, "恢复失败");
}
} else {
to_assign(1, '只有项目创建者和负责人才有权限恢复项目成员');
}
} else {
return to_assign(1, "错误的请求");
}
}
//编辑阶段
public function reset_check()
{
$param = get_params();
$id = isset($param['id']) ? $param['id'] : 0;
$detail = Db::name('Project')->where(['id' => $param['id']])->find();
if (request()->isPost()) {
$flowNameData = isset($param['flowName']) ? $param['flowName'] : '';
$flowUidsData = isset($param['chargeIds']) ? $param['chargeIds'] : '';
$flowIdsData = isset($param['membeIds']) ? $param['membeIds'] : '';
// $flowDateData = isset($param['cycleDate']) ? $param['cycleDate'] : '';
$flow = [];
$time_1 = $detail['start_time'];
$time_2 = $detail['end_time'];
foreach ($flowNameData as $key => $value) {
if (!$value) {
continue;
}
// $flowDate = explode('到', $flowDateData[$key]);
// $start_time = strtotime(urldecode(trim($flowDate[0])));
// $end_time = strtotime(urldecode(trim($flowDate[1])));
// if ($start_time < $time_1) {
// if ($key == 0) {
// return to_assign(1, '第' . ($key + 1) . '阶段的开始时间不能小于计划开始时间');
// } else {
// return to_assign(1, '第' . ($key + 1) . '阶段的开始时间不能小于第' . ($key) . '阶段的结束时间');
// }
// break;
// }
// if ($end_time > $time_2) {
// return to_assign(1, '第' . ($key + 1) . '阶段的结束时间不能大于计划结束时间');
// break;
// } else {
// $time_1 = $end_time;
// }
$item = [];
$item['action_id'] = $id;
$item['flow_name'] = $value;
$item['type'] = 1;
$item['flow_uid'] = $flowUidsData[$key];
$item['flow_ids'] = $flowIdsData[$key];
$item['sort'] = $key;
// $item['start_time'] = $start_time;
// $item['end_time'] = $end_time;
$item['create_time'] = time();
$flow[] = $item;
}
//删除原来的阶段步骤
Db::name('Step')->where(['action_id' => $id, 'type' => 1, 'delete_time' => 0])->update(['delete_time' => time()]);
Db::name('StepRecord')->where(['action_id' => $id, 'type' => 1, 'delete_time' => 0])->update(['delete_time' => time()]);
$res = Db::name('Step')->strict(false)->field(true)->insertAll($flow);
if ($res) {
$checkData = array(
'action_id' => $id,
'step_id' => 0,
'check_uid' => $this->uid,
'type' => 1,
'check_time' => time(),
'status' => 0,
'create_time' => time()
);
$aid = Db::name('StepRecord')->strict(false)->field(true)->insertGetId($checkData);
$resa = Db::name('Project')->where('id', $id)->strict(false)->field(true)->update(['step_sort' => 0, 'update_time' => time()]);
add_log('reset', $param['id'], $param, [], '项目阶段');
}
return to_assign();
}
}
//审核
public function step_check()
{
$param = get_params();
$detail = Db::name('Project')->where(['id' => $param['id']])->find();
//当前审核节点详情
$step = Db::name('Step')->where(['action_id' => $detail['id'], 'type' => 1, 'sort' => $detail['step_sort'], 'delete_time' => 0])->find();
// if ($this->uid != $step['flow_uid']) {
// return to_assign(1, '您没权限操作');
// }
//审核通过
if ($param['check'] == 1) {
$next_step = Db::name('Step')->where(['action_id' => $detail['id'], 'type' => 1, 'sort' => ($detail['step_sort'] + 1), 'delete_time' => 0])->find();
if ($next_step) {
$param['step_sort'] = $next_step['sort'];
$param['status'] = 2;
} else {
//不存在下一步审核,审核结束
$param['status'] = 3;
$param['step_sort'] = $detail['step_sort'] + 1;
}
//审核通过数据操作
$res = Db::name('Project')->strict(false)->field('step_sort,status')->update($param);
if ($res !== false) {
$checkData = array(
'action_id' => $detail['id'],
'step_id' => $step['id'],
'check_uid' => $this->uid,
'type' => 1,
'check_time' => time(),
'status' => $param['check'],
'create_time' => time()
);
$aid = Db::name('StepRecord')->strict(false)->field(true)->insertGetId($checkData);
add_log('check', $param['id'], $param, [], '项目阶段');
return to_assign();
} else {
return to_assign(1, '操作失败');
}
}
//拒绝审核
else if ($param['check'] == 2) {
//获取上一步的审核信息
$prev_step = Db::name('Step')->where(['action_id' => $detail['id'], 'type' => 1, 'sort' => ($detail['step_sort'] - 1), 'delete_time' => 0])->find();
if ($prev_step) {
//存在上一步审核
$param['step_sort'] = $prev_step['sort'];
} else {
//不存在上一步审核,审核初始化步骤
$param['step_sort'] = 0;
$param['status'] = 1;
}
}
$res = Db::name('Project')->strict(false)->field('step_sort,status')->update($param);
if ($res !== false) {
$checkData = array(
'action_id' => $detail['id'],
'step_id' => $step['id'],
'check_uid' => $this->uid,
'type' => 1,
'check_time' => time(),
'status' => $param['check'],
'content' => $param['content'],
'create_time' => time()
);
$aid = Db::name('StepRecord')->strict(false)->field(true)->insertGetId($checkData);
add_log('refue', $param['id'], $param, [], '项目阶段');
return to_assign();
} else {
return to_assign(1, '操作失败');
}
}
//获取钉钉机器人webhook
public function getddurl()
{
$param = get_params();
if (request()->isGet()) {
$ddurl = Db::name('Project')->where('id', $param['id'])->value('ddurl');
if ($ddurl) {
return json(['id' => $param["id"], 'ddurl' => $ddurl]);
} else {
return json('操作失败');
}
} elseif (request()->isPost()) {
$updateResult = Db::name('Project')->where('id', $param['id'])->update(['ddurl' => $param['ddurl']]);
if ($updateResult) {
return json(['id' => $param["id"], 'ddurl' => $param['ddurl']]);
} else {
return json('更新失败');
}
}
}
}
+119
View File
@@ -0,0 +1,119 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\api\controller;
use app\api\BaseController;
use app\model\Schedule as ScheduleList;
use think\facade\Db;
use think\facade\View;
class Schedule extends BaseController
{
//获取工作记录列表
public function index()
{
if (request()->isAjax()) {
$param = get_params();
$task_ids = Db::name('Task')->where(['delete_time' => 0, 'project_id' => $param['tid']])->column('id');
$where = array();
if (!empty($param['keywords'])) {
$where[] = ['a.title', 'like', '%' . $param['keywords'] . '%'];
}
if (!empty($param['uid'])) {
$where[] = ['a.admin_id', '=', $param['uid']];
}
if (!empty($task_ids)) {
$where[] = ['a.tid', 'in', $task_ids];
}
$where[] = ['a.delete_time', '=', 0];
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
$list = ScheduleList::where($where)
->field('a.*,u.name,d.title as department,t.title as task,p.name as project,w.title as work_cate')
->alias('a')
->join('Admin u', 'a.admin_id = u.id', 'LEFT')
->join('Department d', 'u.did = d.id', 'LEFT')
->join('Task t', 'a.tid = t.id', 'LEFT')
->join('WorkCate w', 'w.id = t.cate', 'LEFT')
->join('Project p', 't.project_id = p.id', 'LEFT')
->order('a.end_time desc')
->paginate($rows, false, ['query' => $param])
->each(function ($item, $key) {
$item->start_time_a = empty($item->start_time) ? '' : date('Y-m-d', $item->start_time);
$item->start_time_b = empty($item->start_time) ? '' : date('H:i', $item->start_time);
$item->end_time_a = empty($item->end_time) ? '' : date('Y-m-d', $item->end_time);
$item->end_time_b = empty($item->end_time) ? '' : date('H:i', $item->end_time);
$item->start_time = empty($item->start_time) ? '' : date('Y-m-d H:i', $item->start_time);
$item->end_time = empty($item->end_time) ? '' : date('H:i', $item->end_time);
});
return table_assign(0, '', $list);
} else {
return view();
}
}
//获取任务工作记录列表
public function get_list()
{
$param = get_params();
$where = array();
$where['a.tid'] = $param['tid'];
$where['a.delete_time'] = 0;
$list = Db::name('Schedule')
->field('a.*,u.name')
->alias('a')
->join('Admin u', 'u.id = a.admin_id')
->order('a.create_time desc')
->where($where)
->select()->toArray();
foreach ($list as $k => $v) {
$list[$k]['start_time'] = empty($v['start_time']) ? '' : date('Y-m-d H:i', $v['start_time']);
$list[$k]['end_time'] = empty($v['end_time']) ? '' : date('H:i', $v['end_time']);
}
return to_assign(0, '', $list);
}
//查看
public function view($id)
{
$id = get_params('id');
$schedule = ScheduleList::where(['id' => $id])->find();
if (!empty($schedule)) {
$schedule['start_time_1'] = date('H:i', $schedule['start_time']);
$schedule['end_time_1'] = date('H:i', $schedule['end_time']);
$schedule['start_time'] = date('Y-m-d', $schedule['start_time']);
$schedule['end_time'] = date('Y-m-d', $schedule['end_time']);
// $schedule['create_time'] = date('Y-m-d H:i:s', $schedule['create_time']);
$schedule['user'] = Db::name('Admin')->where(['id' => $schedule['admin_id']])->value('name');
$schedule['department'] = Db::name('Department')->where(['id' => $schedule['did']])->value('title');
}
if (request()->isAjax()) {
return to_assign(0, "", $schedule);
} else {
return $schedule;
}
}
//更新工作记录读取状态
public function update_status()
{
$param = get_params();
$id = $param['id'];
$is_new = $param['is_new'];
$result = Db::name('Schedule')->where('id', $id)->update(['is_new' => $is_new]);
if ($result) {
return to_assign(0, '更新成功');
} else {
return to_assign(1, '更新失败');
}
}
}
+5
View File
@@ -0,0 +1,5 @@
<?php
// 这是系统自动生成的event定义文件
return [
];
+10
View File
@@ -0,0 +1,10 @@
<?php
// 这是系统自动生成的middleware定义文件
return [
//开启session中间件
//'think\middleware\SessionInit',
//验证勾股cms是否完成安装
\app\home\middleware\Install::class,
// 跳过登录验证 AuthMiddleware
\app\api\middleware\Auth::class,
];
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace app\api\middleware;
use Closure;
use think\Request;
use think\Response;
class Auth
{
protected $noNeedLogin = [
'BusinessInfo' => ['product_info'],
];
public function handle(Request $request, Closure $next): Response
{
// 获取当前请求的控制器和方法
$controller = $request->controller();
$action = $request->action();
// 判断当前请求是否在 noNeedLogin 列表中
if (isset($this->noNeedLogin[$controller]) && in_array($action, $this->noNeedLogin[$controller])) {
return $next($request);
}
// 执行登录验证逻辑
if (!session('?user_id')) {
// 未登录,返回错误或重定向到登录页面
return redirect('login/index');
}
return $next($request);
}
}
+82
View File
@@ -0,0 +1,82 @@
<form class="layui-form page-content p-4">
{eq name="id" value ="0"}
<h3 class="h3-title">新建文档</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">文档名称<font>*</font>
</td>
<td>
<input type="text" name="title" lay-verify="required" lay-reqText="请输入文档名称" placeholder="请输入文档名称"
class="layui-input" value="">
</td>
</tr>
</table>
<div>
<div style="padding:10px 0">文档内容<span style="color: red">*</span></div>
<div>
<textarea id="mdContent" style="display:none;"></textarea>
<div id="docContent"></div>
</div>
<input type="hidden" name="id" value="0" />
<input type="hidden" name="topic_id" value="{$project_id}" />
<input type="hidden" name="module" value="project" />
</div>
{else/}
<h3 class="h3-title">编辑文档</h3>
<table class="layui-table layui-table-form">
<tr>
<td class="layui-td-gray">文档名称<font>*</font>
</td>
<td>
<input type="text" name="title" lay-verify="required" lay-reqText="请输入文档名称" placeholder="请输入文档名称"
class="layui-input" value="{$detail.title}">
</td>
</tr>
</table>
<div>
<div style="padding:10px 0">文档内容<span style="color: red">*</span></div>
<div>
<div id="docContent"></div>
<textarea id="mdContent" style="display:none;">{$detail.md_content}</textarea>
</div>
<input type="hidden" name="id" value="{$detail.id}" />
</div>
{/eq}
<div style="padding: 10px 0 0">
<input type="hidden" name="module" value="project" />
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
<script>
function openInit() {
var form = layui.form, layer = layui.layer, tool = layui.tool,editor = layui.editormd;
form.render();
var edit = editor.render('docContent', {
markdown: $('#mdContent').val(),
imageUploadURL: "/api/index/md_upload",
lineNumbers: false,
toolbarIcons: function () {
return [
"undo", "redo","bold", "del", "italic", "quote","h1", "h2", "h3", "h4", "h5",
"list-ul", "list-ol", "hr","link", "reference-link", "image", "code", "code-block", "table","watch", "fullscreen"
];
},
height: window.innerHeight - 240,
});
//监听提交
form.on('submit(webform)', function (data) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
tool.close(1000);
}
}
tool.post("/api/document/add", data.field, callback);
return false;
});
}
</script>
+20
View File
@@ -0,0 +1,20 @@
<div class="page-content">
<div class="p-4 border-b">
<h3 class="h3-title">
<span id="title_{$detail.id}" data-val="">{$detail.title}</span></i>
</h3>
<div>
<span class="mr-2">{$detail.admin_name}</span>
<span class="font-gray">创建于{$detail.times}<span id="editTips">{gt name="$detail.update_time" value="0"},最近更新于 {:time_trans($detail.update_time)}{/gt}</span></span>
</div>
</div>
<div class="layui-row p-4">
<div class="md-content-content">{$detail.content|raw}</div>
</div>
</div>
<script>
function openInit() {
}
</script>
+74
View File
@@ -0,0 +1,74 @@
<div class="table-content">
<!-- <div class="layui-form-bar border-t border-x">
<button class="layui-btn layui-btn-sm add-new">+ 新建附件</button>
</div> -->
<div>
<form class="layui-form layui-form-pane" action="">
<div class="layui-form-item">
<label class="layui-form-label">项目id</label>
<div class="layui-input-block">
<input type="text" value="{$id}" autocomplete="off" readonly disabled placeholder="请输入项目id" lay-verify="required"
class="layui-input">
<input type="hidden" id="projectId" value="{$id}">
<input type="hidden" id="attachments" value="attachment">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">附件地址</label>
<div class="layui-input-block">
<input type="text" name="attachmentUrl" autocomplete="off" lay-verify="required"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-sm edit">修改</button>
</div>
</form>
</div>
</div>
<script>
function pageInit() { }
$(document).ready(function () {
var id = $('#projectId').val();
var attachment = $('#attachments').val();
// 获取数据并填充到输入框
$.ajax({
url: '/api/project/getattachmenturl', // 接口地址
type: 'GET', // 请求类型
data: {
id: id,
page: attachment,
},
success: function (data) {
$('input[name="attachmentUrl"]').val(data.attachmentUrl); // 填充数据
},
error: function () {
alert('获取数据失败!');
}
});
// 修改按钮点击事件
$('.edit').click(function (e) {
e.preventDefault(); // 阻止表单默认提交
var updatedUrl = $('input[name="attachmentUrl"]').val(); // 获取修改后的值
$.ajax({
url: '/api/project/getattachmenturl', // 提交修改的接口地址
type: 'POST', // 请求类型
data: {
id: id,
attachmentUrl: updatedUrl
},
success: function (response) {
alert('修改成功!');
},
error: function () {
alert('修改失败!');
}
});
});
});
</script>
+40
View File
@@ -0,0 +1,40 @@
<div class="table-content">
<div class="layui-card p-3 comment-list">
<h4>项目评论</h4>
<div class="comment-input my-2">
<input type="text" id="commentInput" readonly placeholder="发表一下你的看法" class="layui-input" value="">
</div>
<div id="comment_project_{$id}"></div>
</div>
</div>
<script>
function pageInit(){
let detail_id = {$id};
let comment = layui.gouguComment;
//评论
comment.load(detail_id,'project');
$('#commentInput').on('click',function(){
comment.editor(0,detail_id,0,0,'project','');
})
//回复
$('#comment_project_'+detail_id).on('click','[data-event="replay"]',function(){
let pid = $(this).data('id');
let padmin_id = $(this).data('uid');
comment.editor(0,detail_id,pid,padmin_id,'project','');
})
//编辑
$('#comment_project_'+detail_id).on('click','[data-event="edit"]',function(){
let id = $(this).data('id');
let mdcontent=$('#comment_'+id).data('mdcontent');
comment.editor(id,detail_id,0,0,'project',mdcontent);
})
//删除
$('#comment_project_'+detail_id).on('click','[data-event="del"]',function(){
let id = $(this).data('id');
comment.del(id,detail_id,'project');
})
}
</script>
+68
View File
@@ -0,0 +1,68 @@
<div class="table-content">
<div class="layui-form-bar border-t border-x">
<button class="layui-btn layui-btn-sm add-new">+ 新建文档</button>
</div>
<table class="layui-hide" id="test" lay-filter="test"></table>
</div>
<script type="text/html" id="barDemo">
<div class="layui-btn-group"><span class="layui-btn layui-btn-normal layui-btn-xs" lay-event="view">查看</span><span class="layui-btn layui-btn-xs" lay-event="edit">编辑</span><span class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</span></div>
</script>
<script>
function pageInit(){
var project_id = {$id};
var table = layui.table,tool = layui.tool;
layui.documentTable = table.render({
elem: '#test',
title: '文档列表',
cellMinWidth:200,
url: "/api/document/get_list", //数据接口
where:{'m':'project','tid':project_id},
page: true, //开启分页
limit: 20,
cols: [[
{field:'id', title: 'ID编号',width: 80, align:'center'}
,{field:'title',title: '标题'}
,{field:'name',title: '创建人', align:'center',width: 100}
,{field:'create_time',title: '创建时间',align:'center',width: 150}
,{field:'update_time',title: '最后更新时间', align:'center',width: 150}
,{title: '操作',align: 'center',width: 136,toolbar: '#barDemo',}
]]
});
//新增
$('.add-new').on('click',function(){
tool.open('/api/document/add?project_id='+project_id);
});
//监听行工具事件
table.on('tool(test)', function(obj) {
var data = obj.data;
if (obj.event === 'view') {
tool.open('/api/document/view?id='+data.id);
return;
}
if (obj.event === 'edit') {
tool.open('/api/document/add?id='+data.id);
return;
}
if (obj.event === 'del') {
layer.confirm('确定删除该文档吗?', {
icon: 3,
title: '提示'
}, function(index) {
let callback = function (e) {
layer.msg(e.msg);
if (e.code == 0) {
obj.del();
}
}
tool.delete("/api/document/delete",{ id: obj.data.id,'module':'project'},callback);
layer.close(index);
});
}
});
}
</script>
+78
View File
@@ -0,0 +1,78 @@
<div class="table-content">
<div id="logList" class="log-timeline layui-card p-3"></div>
</div>
<script>
function pageInit(){
var project_id = {$id};
var project_page = 1;
var tool = layui.tool;
let callback = function(res){
$('.log-more').remove();
if(res.code==0 && res.data.length>0){
let itemLog = '',log_time='';
$.each(res.data, function (index, item) {
let link="",detail = "";
if(log_time != item.create_time){
if(log_time==''){
itemLog+='<dl><dt><span class="date-second-point"></span>'+item.create_time+'</dt>'
}
else{
itemLog+='</dl><dl><dt><span class="date-second-point"></span>'+item.create_time+'</dt>'
}
log_time = item.create_time;
}
if(item.topic_title != ''){
link='<a class="'+item.module+' open-a" data-href="'+item.url+'">'+item.topic+' '+item.topic_title+'</a>';
}
if(item.field =='new' || item.field =='delete'){
detail= `
<span class="log-content font-gray">${item.action}了项目${item.module_name}${link}</strong><span class="ml-4 font-gray" title="${item.create_time}">${item.times}</span>
`;
}
else if(item.field =='content'){
detail= `
<span class="log-content font-gray">${item.action}了<strong>${item.title}</strong><i title="对比查看" class="iconfont icon-yuejuan" style="color:#1E9FFF; cursor: pointer;"></i> <span class="ml-4 font-gray" title="${item.create_time}">${item.times}</span></span>
`;
}
else if(item.field =='file'|| item.field =='link' || item.field =='user'){
detail= `
<span class="log-content font-gray">${item.action}了${item.title}<strong>${item.new_content}</strong><span class="ml-4 font-gray" title="${item.create_time}">${item.times}</span></span>
`;
}
else if(item.field =='document'){
if(item.action =='修改'){
detail= `
<span class="log-content font-gray">项目${item.module_name}${link}${item.action}了${item.title}<strong>${item.remark}</strong><i title="对比查看" class="iconfont icon-yuejuan" style="color:#1E9FFF; cursor: pointer;"></i> <span class="ml-4 font-gray" title="${item.create_time}">${item.times}</span></span>
`;
}
else{
detail= `
<span class="log-content font-gray">项目${item.module_name}${link}${item.action}了${item.title}<strong>${item.remark}</strong><span class="ml-4 font-gray" title="${item.create_time}">${item.times}</span></span>
`;
}
}
else{
detail= `
<span class="log-content font-gray">将项目${item.module_name}${link}<strong>${item.title}</strong>从 ${item.old_content} ${item.action}为<strong>${item.new_content}</strong><span class="ml-4 font-gray" title="${item.create_time}">${item.times}</span></span>
`;
}
itemLog+= `
<dd><img src="${item.thumb}" class="log-thumb" /><span class="log-name">${item.name}</span>${detail}</dd>
`;
});
itemLog+='</dl>';
if(res.data.length>19){
itemLog+='<div class="py-3 log-more"><button class="layui-btn layui-btn-normal layui-btn-sm" type="button">查看更多项目动态</button></div>';
}
$("#logList").append(itemLog);
}
}
tool.get("/api/log/log_list",{topic_id:project_id,page:project_page},callback);
$('#logList').on('click','.log-more',function(){
project_page++;
tool.get("/api/log/log_list",{topic_id:project_id,page:project_page},callback);
});
}
</script>

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