项目初始化
commit
dbccb35764
|
@ -0,0 +1,8 @@
|
|||
/runtime
|
||||
/.idea
|
||||
/.vscode
|
||||
*.log
|
||||
.env
|
||||
/tests/tmp
|
||||
/tests/.phpunit.result.cache
|
||||
ssl/
|
|
@ -0,0 +1,16 @@
|
|||
<html>
|
||||
<style>
|
||||
.btlink {
|
||||
color: #20a53a;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<meta charset="UTF-8">
|
||||
<html>
|
||||
<head><title>404 Not Found</title></head>
|
||||
<body>
|
||||
<center><h1>404 Not Found</h1></center>
|
||||
<hr>
|
||||
<div style="text-align: center;font-size: 15px" >Power by <a class="btlink" href="https://www.bt.cn/?from=404" target="_blank">堡塔 (免费,高效和安全的托管控制面板)</a></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 walkor<walkor@workerman.net> and contributors (see https://github.com/walkor/webman/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,57 @@
|
|||
<div style="padding:18px;max-width: 1024px;margin:0 auto;background-color:#fff;color:#333">
|
||||
<h1>webman</h1>
|
||||
|
||||
基于<a href="https://www.workerman.net" target="__blank">workerman</a>开发的超高性能PHP框架
|
||||
|
||||
|
||||
<h1>学习</h1>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/webman" target="__blank">主页 / Home page</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://webman.workerman.net" target="__blank">文档 / Document</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/doc/webman/install.html" target="__blank">安装 / Install</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/questions" target="__blank">问答 / Questions</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/apps" target="__blank">市场 / Apps</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/sponsor" target="__blank">赞助 / Sponsors</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/doc/webman/thanks.html" target="__blank">致谢 / Thanks</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div style="float:left;padding-bottom:30px;">
|
||||
|
||||
<h1>赞助商</h1>
|
||||
|
||||
<h4>特别赞助</h4>
|
||||
<a href="https://www.crmeb.com/?form=workerman" target="__blank">
|
||||
<img src="https://www.workerman.net/img/sponsors/6429/20230719111500.svg" width="200">
|
||||
</a>
|
||||
|
||||
<h4>铂金赞助</h4>
|
||||
<a href="https://www.fadetask.com/?from=workerman" target="__blank"><img src="https://www.workerman.net/img/sponsors/1/20230719084316.png" width="200"></a>
|
||||
<a href="https://www.yilianyun.net/?from=workerman" target="__blank" style="margin-left:20px;"><img src="https://www.workerman.net/img/sponsors/6218/20230720114049.png" width="200"></a>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div style="clear: both">
|
||||
<h1>LICENSE</h1>
|
||||
The webman is open-sourced software licensed under the MIT.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\model\Book;
|
||||
use app\model\Category;
|
||||
use app\model\Reading;
|
||||
use app\model\ReadingBook;
|
||||
use app\model\BookLog;
|
||||
|
||||
class BookController
|
||||
{
|
||||
//书籍列表
|
||||
public function index(Request $request)
|
||||
{
|
||||
$name = $request->get('name', '');
|
||||
$categoryID = $request->get('category_id', 0);
|
||||
$categoryList = Category::getList();
|
||||
return view('book/index', ['name' => $name, 'categoryID' => $categoryID, 'categoryList' => $categoryList]);
|
||||
}
|
||||
|
||||
public function add(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$name = $request->post('name');
|
||||
$categoryID = $request->post('category_id');
|
||||
$author = $request->post('author');
|
||||
$remark = $request->post('remark');
|
||||
|
||||
$old = Book::getByName($name);
|
||||
if(!$old->isEmpty()){
|
||||
return json(['code' => 1, 'msg' => '已存在此书']);
|
||||
}
|
||||
|
||||
$bookModel = new Book;
|
||||
$bookModel->save(['name' => $name, 'category_id' => $categoryID, 'author' => $author, 'remark' => $remark]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
$categoryList = Category::getList();
|
||||
return view('book/add', ['categoryList' => $categoryList]);
|
||||
}
|
||||
|
||||
public function edit(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$name = $request->post('name');
|
||||
$categoryID = $request->post('category_id');
|
||||
$author = $request->post('author');
|
||||
$remark = $request->post('remark');
|
||||
$id = $request->post('id');
|
||||
|
||||
Book::updateByID($id, ['name' => $name, 'category_id' => $categoryID, 'author' => $author, 'remark' => $remark]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
$id = $request->get('id');
|
||||
$book = Book::getByID($id);
|
||||
$categoryList = Category::getList();
|
||||
|
||||
return view('book/edit', ['book' => $book, 'categoryList' => $categoryList]);
|
||||
}
|
||||
|
||||
//读书清单
|
||||
public function reading(Request $request)
|
||||
{
|
||||
$name = $request->get('name', '');
|
||||
return view('book/reading', ['name' => $name]);
|
||||
}
|
||||
|
||||
public function addReading(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$name = $request->post('name');
|
||||
|
||||
$readingModel = new Reading;
|
||||
$readingModel->save(['name' => $name]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
return view('book/addReading');
|
||||
}
|
||||
|
||||
public function editReading(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$name = $request->post('name');
|
||||
$id = $request->post('id');
|
||||
|
||||
Reading::updateByID($id, ['name' => $name]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
$id = $request->get('id');
|
||||
$reading = Reading::getByID($id);
|
||||
|
||||
return view('book/editReading', ['reading' => $reading]);
|
||||
}
|
||||
|
||||
public function readingBook(Request $request)
|
||||
{
|
||||
$id = $request->get('id', 0);
|
||||
$reading = Reading::getByID($id);
|
||||
return view('book/readingBook', ['reading' => $reading]);
|
||||
}
|
||||
|
||||
public function addReadingBook(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$readingID = $request->post('reading_id');
|
||||
$bookID = $request->post('book_id');
|
||||
$status = $request->post('status');
|
||||
$start = $request->post('start');
|
||||
$end = $request->post('end');
|
||||
$remark = $request->post('remark');
|
||||
|
||||
ReadingBook::create([
|
||||
'reading_id' => $readingID,
|
||||
'book_id' => $bookID,
|
||||
'status' => $status,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'remark' => $remark
|
||||
]);
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
$readingID = $request->get('reading_id', 0);
|
||||
$reading = Reading::getByID($readingID);
|
||||
$categoryList = Category::getList();
|
||||
$bookList = Book::getPageList(0, '', 50);
|
||||
|
||||
return view('book/addReadingBook', ['readingID' => $readingID, 'reading' => $reading, 'categoryList' => $categoryList, 'bookList' => $bookList]);
|
||||
}
|
||||
|
||||
public function editReadingBook(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$id = $request->post('id');
|
||||
$bookID = $request->post('book_id');
|
||||
$status = $request->post('status');
|
||||
$start = $request->post('start', '');
|
||||
$end = $request->post('end', '');
|
||||
$remark = $request->post('remark');
|
||||
|
||||
ReadingBook::updateByID($id, [
|
||||
'book_id' => $bookID,
|
||||
'status' => $status,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'remark' => $remark
|
||||
]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
$readingBookID = $request->get('id', 0);
|
||||
$readingBook = ReadingBook::getByID($readingBookID);
|
||||
$reading = Reading::getByID($readingBook->reading_id);
|
||||
$categoryList = Category::getList();
|
||||
$bookList = Book::getPageList(0, '', 50);
|
||||
$book = Book::getByID($readingBook->book_id);
|
||||
|
||||
return view('book/editReadingBook', ['reading' => $reading, 'categoryList' => $categoryList, 'bookList' => $bookList, 'readingBook' => $readingBook, 'book' => $book]);
|
||||
}
|
||||
|
||||
public function apiGetList(Request $request)
|
||||
{
|
||||
$name = $request->get('name', '');
|
||||
$categoryID = $request->get('category_id', 0);
|
||||
$pageSize = $request->get('size', 20);
|
||||
$bookList = Book::getPageList($categoryID, $name, $pageSize);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok', 'bookList' => $bookList]);
|
||||
}
|
||||
|
||||
public function apiGetReadingList(Request $request)
|
||||
{
|
||||
$name = $request->get('name', '');
|
||||
|
||||
$readingList = Reading::getPageList($name);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok', 'readingList' => $readingList]);
|
||||
}
|
||||
|
||||
public function apiGetReadingBookList(Request $request)
|
||||
{
|
||||
$readingID = $request->get('id', 0);
|
||||
|
||||
$bookList = ReadingBook::getList($readingID);
|
||||
return json(['code' => 0, 'msg' => 'ok', 'bookList' => $bookList]);
|
||||
}
|
||||
|
||||
//排序
|
||||
public function apiSortReadingBook(Request $request)
|
||||
{
|
||||
$id = $request->post('id');
|
||||
$num = $request->post('num');
|
||||
$sort = 'down';
|
||||
|
||||
if($num < 0) $sort = 'up';
|
||||
$num = abs($num);
|
||||
|
||||
$item = ReadingBook::getByID($id);
|
||||
|
||||
$whereMap = [];
|
||||
$whereMap[] = ['reading_id', '=', $item['reading_id']];
|
||||
|
||||
if ($sort == 'up'){
|
||||
$whereMap[] = ['sort', '<', $item['sort']];
|
||||
$order = "sort desc";
|
||||
}else{
|
||||
$whereMap[] = ['sort', '>', $item['sort']];
|
||||
$order = "sort asc";
|
||||
}
|
||||
|
||||
$forSortItems = ReadingBook::getListByWhereAndOrder($whereMap, $order, $num);
|
||||
|
||||
if (!empty($forSortItems)){
|
||||
$updateData = [];
|
||||
$forSortCount = count($forSortItems);
|
||||
for ($i = 0; $i < $forSortCount; $i++){
|
||||
if ($i == 0){
|
||||
$updateData[] = [
|
||||
'id' => $forSortItems[$i]['id'],
|
||||
'sort' => $item['sort']
|
||||
];
|
||||
}else{
|
||||
$updateData[] = [
|
||||
'id' => $forSortItems[$i]['id'],
|
||||
'sort' => $forSortItems[$i - 1]['sort']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$updateData[] = [
|
||||
'id' => $item['id'],
|
||||
'sort' => $forSortItems[$i - 1]['sort']
|
||||
];
|
||||
if (!empty($updateData)){
|
||||
$model = new ReadingBook();
|
||||
$model->saveAll($updateData);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
}
|
||||
return json(['code' => 1, 'msg' => '无须调整排序!']);
|
||||
}
|
||||
|
||||
public function apiDelReadingBook(Request $request)
|
||||
{
|
||||
$id = $request->get('id');
|
||||
$readingBook = ReadingBook::getByID($id);
|
||||
if(empty($readingBook)) return json(['code' => 1, 'msg' => '清单中无此书!']);
|
||||
|
||||
ReadingBook::destroy($id);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
public function apiStartReadingBook(Request $request)
|
||||
{
|
||||
$id = $request->post('id');
|
||||
$readingBook = ReadingBook::getByID($id);
|
||||
|
||||
if(empty($readingBook)) return json(['code' => 1, 'msg' => '清单中无此书!']);
|
||||
|
||||
if(!empty($readingBook->start)) return json(['code' => 2, 'msg' => '已经开始,无需重新设置']);
|
||||
|
||||
ReadingBook::updateByID($id, [
|
||||
'status' => 'reading',
|
||||
'start' => date('Y-m-d')
|
||||
]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
public function apiEndReadingBook(Request $request)
|
||||
{
|
||||
$id = $request->post('id');
|
||||
$readingBook = ReadingBook::getByID($id);
|
||||
if(empty($readingBook)) return json(['code' => 1, 'msg' => '清单中无此书!']);
|
||||
|
||||
if($readingBook->status == 'finished') return json(['code' => 2, 'msg' => '已经结束,无需重新设置']);
|
||||
|
||||
$end = date('Y-m-d');
|
||||
ReadingBook::updateByID($id, ['end' => $end, 'status' => 'finished']);
|
||||
|
||||
BookLog::create([
|
||||
'book_id' => $readingBook->book_id,
|
||||
'start' => $readingBook->start,
|
||||
'end' => $end
|
||||
]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\model\Category;
|
||||
|
||||
class CategoryController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('category/index');
|
||||
}
|
||||
|
||||
public function add(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$name = $request->post('name');
|
||||
|
||||
$categoryModel = new Category;
|
||||
$categoryModel->save(['name' => $name]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
return view('category/add');
|
||||
}
|
||||
|
||||
public function apiGetList()
|
||||
{
|
||||
$list = Category::getList();
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok', 'list' => $list]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\model\zdoo\Customer;
|
||||
|
||||
class CustomerController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$statusList = $request->get('statusList', '');
|
||||
$name = $request->get('name', '');
|
||||
|
||||
$statusListArray = explode(',', $statusList);
|
||||
$statusListSelected = [];
|
||||
foreach(Customer::$statusList as $k => $v){
|
||||
$tmpItem = [
|
||||
'name' => $v,
|
||||
'value' => $k
|
||||
];
|
||||
if(in_array($k, $statusListArray)){
|
||||
$tmpItem['selected'] = true;
|
||||
}
|
||||
$statusListSelected[] = $tmpItem;
|
||||
}
|
||||
|
||||
return view('customer/index', ['statusList' => $statusList, 'name' => $name, 'statusListSelected' => json_encode($statusListSelected)]);
|
||||
}
|
||||
|
||||
public function apiGetList(Request $request)
|
||||
{
|
||||
$statusList = $request->get('statusList', '');
|
||||
$name = $request->get('name', '');
|
||||
|
||||
$list = Customer::getPageList($statusList, $name);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok', 'list' => $list]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,328 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\model\Goods;
|
||||
use app\model\GoodsReceipt;
|
||||
use app\model\SaleLog;
|
||||
use think\facade\Db;
|
||||
|
||||
class GoodsController
|
||||
{
|
||||
//商品列表
|
||||
public function index(Request $request)
|
||||
{
|
||||
$name = $request->get('name', '');
|
||||
$order = $request->get('order', 'stock_desc');
|
||||
return view('goods/index', ['name' => $name, 'order' => $order]);
|
||||
}
|
||||
|
||||
//添加商品
|
||||
public function add(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$name = $request->post('name');
|
||||
$price = $request->post('price');
|
||||
$remark = $request->post('remark');
|
||||
$stock = $request->post('stock');
|
||||
$stock_small = $request->post('stock_small');
|
||||
$sales = $request->post('sales');
|
||||
$sales_small = $request->post('sales_small');
|
||||
$split_to_small = $request->post('split_to_small');
|
||||
|
||||
$old = Goods::getByName($name);
|
||||
if(!$old->isEmpty()){
|
||||
return json(['code' => 1, 'msg' => '已存在此商品']);
|
||||
}
|
||||
|
||||
$goodsModel = new Goods;
|
||||
$goodsModel->save([
|
||||
'name' => $name,
|
||||
'price' => $price,
|
||||
'stock' => $stock,
|
||||
'stock_small' => $stock_small,
|
||||
'sales' => $sales,
|
||||
'sales_small' => $sales_small,
|
||||
'split_to_small' => $split_to_small,
|
||||
'remark' => $remark
|
||||
]);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
return view('goods/add', []);
|
||||
}
|
||||
|
||||
//编辑商品
|
||||
public function edit(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$name = $request->post('name');
|
||||
$price = $request->post('price');
|
||||
$remark = $request->post('remark');
|
||||
$stock = $request->post('stock');
|
||||
$stock_small = $request->post('stock_small');
|
||||
$sales = $request->post('sales');
|
||||
$sales_small = $request->post('sales_small');
|
||||
$split_to_small = $request->post('split_to_small');
|
||||
$id = $request->post('id');
|
||||
// return json([
|
||||
// 'id' => $id,
|
||||
// 'name' => $name,
|
||||
// 'price' => $price,
|
||||
// 'stock' => $stock,
|
||||
// 'stock_small' => $stock_small,
|
||||
// 'sales' => $sales,
|
||||
// 'sales_small' => $sales_small,
|
||||
// 'split_to_small' => $split_to_small,
|
||||
// 'remark' => $remark
|
||||
// ]);
|
||||
try{
|
||||
Goods::updateByID($id,
|
||||
[
|
||||
'name' => $name,
|
||||
'price' => $price,
|
||||
'stock' => $stock,
|
||||
'stock_small' => $stock_small,
|
||||
'sales' => $sales,
|
||||
'sales_small' => $sales_small,
|
||||
'split_to_small' => $split_to_small,
|
||||
'remark' => $remark
|
||||
]);
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}catch(\Exception $e){
|
||||
return json(['code' => 1, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
$id = $request->get('id');
|
||||
$goods = Goods::getByID($id);
|
||||
|
||||
return view('goods/edit', ['goods' => $goods]);
|
||||
}
|
||||
|
||||
//商品入库日志
|
||||
public function receipt(Request $request)
|
||||
{
|
||||
return view('goods/receipt', []);
|
||||
}
|
||||
|
||||
public function addReceipt(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
Db::startTrans();
|
||||
try {
|
||||
$goodsID = $request->post('goods_id');
|
||||
$boughtAt = $request->post('bought_at');
|
||||
$num = $request->post('num');
|
||||
$totalPrice = $request->post('total_price');
|
||||
$remark = $request->post('remark');
|
||||
|
||||
if($goodsID <= 0){
|
||||
return json(['code' => 1, 'msg' => '请选择商品']);
|
||||
}
|
||||
|
||||
if($totalPrice <= 0){
|
||||
return json(['code' => 2, 'msg' => '进货总价必须大于0']);
|
||||
}
|
||||
|
||||
if($boughtAt == ''){
|
||||
return json(['code' => 3, 'msg' => '请选择进货日期']);
|
||||
}
|
||||
$goods = Goods::getByID($goodsID);
|
||||
if($goods->isEmpty()){
|
||||
return json(['code' => 4, 'msg' => '商品不存在']);
|
||||
}
|
||||
|
||||
$splitToSmall = $goods['split_to_small'] ?: 1;
|
||||
$costPrice = bcdiv($totalPrice, $num, 2); //计算大包单价
|
||||
$smallCostPrice = bcdiv($costPrice, $splitToSmall, 2); //计算小包单价
|
||||
|
||||
GoodsReceipt::create([
|
||||
'goods_id' => $goodsID,
|
||||
'num' => $num,
|
||||
'total_price' => $totalPrice,
|
||||
'cost_price' => $costPrice,
|
||||
'small_cost_price' => $smallCostPrice,
|
||||
'bought_at' => $boughtAt,
|
||||
'split_to_small' => $splitToSmall,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'remark' => $remark
|
||||
]);
|
||||
|
||||
Goods::updateByID($goodsID, ['stock' => $goods['stock'] + $num]);
|
||||
|
||||
Db::commit();
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
return json(['code' => 5, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
$goodsList = Goods::getPageList('', 100);
|
||||
|
||||
return view('goods/addReceipt', ['goodsList' => $goodsList]);
|
||||
}
|
||||
|
||||
//商品销售日志
|
||||
public function sale(Request $request)
|
||||
{
|
||||
$goodsID = $request->get('id');
|
||||
$goods = Goods::getByID($goodsID);
|
||||
|
||||
$goodsList = Goods::getPageList('', 100);
|
||||
|
||||
return view('goods/sale', ['goods' => $goods, 'goodsID' => $goodsID, 'goodsList' => $goodsList]);
|
||||
}
|
||||
|
||||
public function addSale(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
Db::startTrans();
|
||||
try {
|
||||
$goodsID = $request->post('goods_id');
|
||||
$sold_at = $request->post('sold_at');
|
||||
$num = $request->post('num', 0);
|
||||
$num_small = $request->post('num_small', 0);
|
||||
$totalPrice = $request->post('total_price');
|
||||
$remark = $request->post('remark');
|
||||
|
||||
if($goodsID <= 0){
|
||||
return json(['code' => 1, 'msg' => '请选择商品']);
|
||||
}
|
||||
|
||||
if($totalPrice <= 0){
|
||||
return json(['code' => 2, 'msg' => '销售总价必须大于0']);
|
||||
}
|
||||
|
||||
if($sold_at == ''){
|
||||
return json(['code' => 3, 'msg' => '请选择销售时间']);
|
||||
}
|
||||
|
||||
if (empty($num) && empty($num_small)) {
|
||||
return json(['code' => 4, 'msg' => '大包销量和小包销量不能同时为空']);
|
||||
}
|
||||
if(empty($num)){
|
||||
$num = 0;
|
||||
}
|
||||
if(empty($num_small)){
|
||||
$num_small = 0;
|
||||
}
|
||||
|
||||
$goods = Goods::getByID($goodsID);
|
||||
|
||||
if($goods->isEmpty()){
|
||||
return json(['code' => 5, 'msg' => '商品不存在']);
|
||||
}
|
||||
|
||||
// 小包库存不足时,没有自动拆分大包的操作
|
||||
if ($goods->stock < $num || $goods->stock_small < $num_small) {
|
||||
return json(['code' => 6, 'msg' => '商品库存不足']);
|
||||
}
|
||||
|
||||
SaleLog::create([
|
||||
'goods_id' => $goodsID,
|
||||
'num' => $num,
|
||||
'num_small' => $num_small,
|
||||
'total_price' => $totalPrice,
|
||||
'sold_at' => $sold_at,
|
||||
'remark' => $remark
|
||||
]);
|
||||
|
||||
Goods::updateByID($goodsID, [
|
||||
'sales' => $goods->sales + $num,
|
||||
'sales_small' => $goods->sales_small + $num_small,
|
||||
'stock' => $goods->stock - $num,
|
||||
'stock_small' => $goods->stock_small - $num_small
|
||||
]);
|
||||
|
||||
Db::commit();
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
return json(['code' => 7, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
$goodsList = Goods::getPageList('', 100);
|
||||
|
||||
return view('goods/addSale', ['goodsList' => $goodsList]);
|
||||
}
|
||||
|
||||
//获取商品列表
|
||||
public function apiGetList(Request $request)
|
||||
{
|
||||
$name = $request->get('name', '');
|
||||
$order = $request->get('order', 'stock_desc');
|
||||
$pageSize = $request->get('size', 20);
|
||||
$goodsList = Goods::getPageList($name, $pageSize, str_replace('_', ' ', $order));
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok', 'goodsList' => $goodsList]);
|
||||
}
|
||||
|
||||
//获取进货列表
|
||||
public function apiGetReceiptList(Request $request)
|
||||
{
|
||||
$pageSize = $request->get('size', 20);
|
||||
$receiptList = GoodsReceipt::getPageList($pageSize);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok', 'receiptList' => $receiptList]);
|
||||
}
|
||||
|
||||
public function apiGetSaleList(Request $request)
|
||||
{
|
||||
$pageSize = $request->get('size', 20);
|
||||
$saleList = SaleLog::getPageList($pageSize);
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok', 'saleList' => $saleList]);
|
||||
}
|
||||
|
||||
public function apiDelReceipt(Request $request)
|
||||
{
|
||||
$method = $request->method();
|
||||
if($method == 'POST')
|
||||
{
|
||||
$id = $request->post('id');
|
||||
$goodsReceipt = GoodsReceipt::getByID($id);
|
||||
|
||||
if($goodsReceipt->isEmpty()){
|
||||
return json(['code' => 1, 'msg' => '进货记录不存在']);
|
||||
}
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$goodsID = $goodsReceipt['goods_id'];
|
||||
$num = $goodsReceipt['num'];
|
||||
|
||||
$goods = Goods::getByID($goodsID);
|
||||
if($goods->isEmpty()){
|
||||
return json(['code' => 2, 'msg' => '商品不存在']);
|
||||
}
|
||||
|
||||
GoodsReceipt::destroy($id);
|
||||
Goods::updateByID($goodsID, ['stock' => $goods['stock'] - $num]);
|
||||
|
||||
Db::commit();
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
return json(['code' => 3, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
return json(['code' => 4, 'msg' => '请求方式错误']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
|
||||
class IndexController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
static $readme;
|
||||
return 'AAA';
|
||||
if (!$readme) {
|
||||
$readme = file_get_contents(base_path('README.md'));
|
||||
}
|
||||
return $readme;
|
||||
}
|
||||
|
||||
public function view(Request $request)
|
||||
{
|
||||
return view('index/view', ['name' => 'webman']);
|
||||
}
|
||||
|
||||
public function json(Request $request)
|
||||
{
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
//use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
class JglController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$publicPath = public_path();
|
||||
|
||||
ini_set('memory_limit', '1G');
|
||||
$file = $publicPath . '/data/data.xls';
|
||||
$savePath = $publicPath . '/data/data2.xls';
|
||||
|
||||
$spreadsheet = IOFActory::load($file);
|
||||
// 获取第一个工作表
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
// 获取最大行数和列数
|
||||
$maxRow = $worksheet->getHighestRow();
|
||||
//$maxColumn = $worksheet->getHighestColumn();
|
||||
|
||||
//$saveSpreadsheet = new Spreadsheet();
|
||||
//$saveActiveWorksheet = $saveSpreadsheet->getActiveSheet();
|
||||
|
||||
// 遍历每一行和每一列
|
||||
//$stuList = [];
|
||||
for ($row = 4; $row <= $maxRow; $row++)
|
||||
{
|
||||
$project = $worksheet->getCell('F' . $row)->getValue();
|
||||
|
||||
if(substr($project, 0, 1) == '='){
|
||||
$project = $worksheet->getCell('E' . $row)->getValue();
|
||||
}
|
||||
$subProject = $this->getProject($project);
|
||||
|
||||
$worksheet->setCellValue('G' . $row, $subProject);
|
||||
}
|
||||
|
||||
|
||||
//$activeWorksheet = $spreadsheet->getActiveSheet();
|
||||
//$activeWorksheet->setCellValue('A1', 'Hello World !');
|
||||
|
||||
$writer = new Xlsx($spreadsheet);
|
||||
$writer->save($savePath);
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
private function getProject($project)
|
||||
{
|
||||
$projects = ['田径','篮球','足球','排球','武术','体操'];
|
||||
|
||||
$k = mt_rand(0, 5);
|
||||
$tmpProject = $projects[$k];
|
||||
|
||||
while($tmpProject == $project){
|
||||
|
||||
$k = mt_rand(0, 5);
|
||||
$tmpProject = $projects[$k];
|
||||
echo "$tmpProject ==== $project\r\n";
|
||||
}
|
||||
echo "--------------------------------\r\n";
|
||||
return $tmpProject;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
|
||||
class SalaryController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$month = "2024年11月";
|
||||
$social = 469.14; //个人社保部分
|
||||
$staffs = [
|
||||
[
|
||||
"name" => "徐从伟", //姓名
|
||||
"wages" => 6000, //工资 //试用期90%,正式工资5500
|
||||
"late_num" => 0, //迟到次数
|
||||
"card_num" => 0, //缺卡次数
|
||||
"leave" => 1, //请假天数
|
||||
"commission" => 0, //提成
|
||||
"haveSocial" => 1, //是否有社保1:有;0:无,
|
||||
],
|
||||
[
|
||||
"name" => "李禹江", //姓名
|
||||
"wages" => 3000, //工资,无社保
|
||||
"late_num" => 0, //迟到次数
|
||||
"card_num" => 0, //缺卡次数
|
||||
"leave" => 6.5, //请假天数
|
||||
"commission" => 0, //提成
|
||||
"haveSocial" => 0, //是否有社保1:有;0:无
|
||||
"collection" => 900, //收款金额
|
||||
],
|
||||
[
|
||||
"name" => "尹财波", //姓名
|
||||
"wages" => 7500, //工资,无社保
|
||||
"late_num" => 0, //迟到次数
|
||||
"card_num" => 0, //缺卡次数
|
||||
"leave" => 0, //请假天数
|
||||
"commission" => 0, //提成
|
||||
"haveSocial" => 0, //是否有社保1:有;0:无
|
||||
],
|
||||
[
|
||||
"name" => "郑继领", //姓名
|
||||
"wages" => 3000, //工资,无社保
|
||||
"late_num" => 0, //迟到次数
|
||||
"card_num" => 0, //缺卡次数
|
||||
"leave" => 0, //请假天数
|
||||
"commission" => 0, //提成
|
||||
"haveSocial" => 0, //是否有社保1:有;0:无
|
||||
"collection" => 31268, //收款金额
|
||||
],
|
||||
];
|
||||
$total = 0; //所有金额
|
||||
|
||||
$socialNumber = 0; //社保人数
|
||||
$str = $month . "工资明细:<br /><br /><br />";
|
||||
foreach ($staffs as $s) {
|
||||
$haveCommission = true; //是否计算提成
|
||||
$perTotal = $s["wages"]; //个人合计
|
||||
|
||||
$str .= $s["name"] . ",{$month} 工资明细:<br />";
|
||||
$str .= "基本工资:" . $s["wages"] . "<br /><br />";
|
||||
$num = $s["late_num"] + $s["card_num"] - 3;
|
||||
$dayWage = $s["wages"] / 22;
|
||||
$hourlyWage = $dayWage / 8;
|
||||
if ($num > 0) {
|
||||
$deduction = round($hourlyWage * $num, 2);
|
||||
} else {
|
||||
$deduction = 0;
|
||||
}
|
||||
|
||||
//$wagesStr = '应发工资(' . $s['wages'];
|
||||
$wagesStr = "应发工资(" . $perTotal;
|
||||
$str .= "迟到次数:" .
|
||||
$s["late_num"] .
|
||||
"<br />缺卡次数:" .
|
||||
$s["card_num"] .
|
||||
"<br />";
|
||||
$str .= "请假天数:" . $s["leave"] . "<br />";
|
||||
if ($s["leave"] > 0) {
|
||||
$deduction += round($dayWage * $s["leave"], 2);
|
||||
}
|
||||
if ($deduction > 0) {
|
||||
$str .= "扣款:" . $deduction . "元<br />";
|
||||
$wagesStr .= " - " . $deduction;
|
||||
$perTotal = $perTotal - $deduction;
|
||||
}
|
||||
|
||||
if ($s["haveSocial"]) {
|
||||
$str .= "<br />";
|
||||
$str .= "社保扣款:" . $social . "元<br />";
|
||||
$str .= "<br />";
|
||||
$wagesStr .= " - " . $social;
|
||||
$perTotal = $perTotal - $social;
|
||||
$socialNumber++;
|
||||
}
|
||||
//销售收款计算提成
|
||||
if (isset($s["collection"]) && $s["collection"] > 0) {
|
||||
$commission = 0;
|
||||
if ($s["collection"] > 80000) {
|
||||
$commission = $s["collection"] * 0.15;
|
||||
} elseif ($s["collection"] > 60000) {
|
||||
$commission = $s["collection"] * 0.14;
|
||||
} elseif ($s["collection"] > 40000) {
|
||||
$commission = $s["collection"] * 0.12;
|
||||
} elseif ($s["collection"] > 20000) {
|
||||
$commission = $s["collection"] * 0.1;
|
||||
} else {
|
||||
$commission = $s["collection"] * 0.08;
|
||||
}
|
||||
if ($commission > 0) {
|
||||
$s["commission"] = $commission;
|
||||
}
|
||||
}
|
||||
|
||||
if ($s["commission"] > 0) {
|
||||
$str .= "收款:" . $s["collection"] . "<br />";
|
||||
$str .= "提成:" . $s["commission"] . "<br />";
|
||||
if ($haveCommission) {
|
||||
$wagesStr .= " + " . $s["commission"];
|
||||
$perTotal = $perTotal + $s["commission"];
|
||||
} else {
|
||||
$str .= "提成不计算!按保底90%计算工资<br />";
|
||||
}
|
||||
$str .= "<br />";
|
||||
}
|
||||
$perTotal = round($perTotal, 2);
|
||||
|
||||
$wagesStr .= ") = " . $perTotal . "元";
|
||||
$str .= $wagesStr . "<br />";
|
||||
$str .= "<br /><br /><br /><br />";
|
||||
|
||||
$total += $perTotal;
|
||||
}
|
||||
|
||||
$socialTotal = ($socialNumber + 2) * 1505.63;
|
||||
|
||||
$str .= "社保总金额:" . $socialTotal . " 元<br /><br />";
|
||||
|
||||
$str .= "工资总金额:" . $total . " 元 <br /><br />";
|
||||
$str .= "总金额:" . $total + $socialTotal . " 元";
|
||||
return $str;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\model\SaleLog;
|
||||
|
||||
class SalesController
|
||||
{
|
||||
//日销量额统计
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('sales/index');
|
||||
}
|
||||
|
||||
//商品销量统计
|
||||
public function goods(Request $request)
|
||||
{
|
||||
return view('sales/goods');
|
||||
}
|
||||
|
||||
//获取日销额统计
|
||||
public function apiGetSales(Request $request)
|
||||
{
|
||||
$start = $request->get('start', '');
|
||||
$end = $request->get('end', '');
|
||||
if(empty($start)){
|
||||
$start = date('Y-m-d', strtotime('-30 days'));
|
||||
}
|
||||
|
||||
if(empty($end)){
|
||||
$end = date('Y-m-d');
|
||||
}
|
||||
|
||||
$data = SaleLog::getSales($start, $end);
|
||||
|
||||
$soldAt = $data->column('sold_at');
|
||||
$totalSales = $data->column('total_sales');
|
||||
return json(['code' => 0, 'data' => ['sold_at' => $soldAt, 'total_sales' => $totalSales]]);
|
||||
}
|
||||
|
||||
public function apiGetSalesGoods(Request $request)
|
||||
{
|
||||
$start = $request->get('start', '');
|
||||
$end = $request->get('end', '');
|
||||
$order = $request->get('order', 'total_sales');
|
||||
if(empty($start)){
|
||||
$start = date('Y-m-d', strtotime('-30 days'));
|
||||
}
|
||||
|
||||
if(empty($end)){
|
||||
$end = date('Y-m-d');
|
||||
}
|
||||
|
||||
$data = SaleLog::getSalesGoods($start, $end, $order);
|
||||
|
||||
$goodsName = $data->column('goods_name');
|
||||
$totalSales = $data->column('total_sales');
|
||||
$totalNum = $data->column('total_num');
|
||||
$totalNumSmall = $data->column('total_num_small');
|
||||
return json(['code' => 0, 'data' => [
|
||||
'goods_name' => $goodsName,
|
||||
'total_sales' => $totalSales,
|
||||
'total_num' => $totalNum,
|
||||
'total_num_small' => $totalNumSmall
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\model\pms\Task;
|
||||
|
||||
class TaskController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('task/index');
|
||||
}
|
||||
|
||||
public function apiGetList(Request $request)
|
||||
{
|
||||
$taskList = Task::getList();
|
||||
foreach($taskList as $task){
|
||||
$task->statusName = Task::$statusList[$task->status];
|
||||
}
|
||||
|
||||
return json(['code' => 0, 'msg' => 'ok', 'taskList' => $taskList]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Here is your custom functions.
|
||||
*/
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
/**
|
||||
* Class StaticFile
|
||||
* @package app\middleware
|
||||
*/
|
||||
class StaticFile implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $next): Response
|
||||
{
|
||||
// Access to files beginning with. Is prohibited
|
||||
if (strpos($request->path(), '/.') !== false) {
|
||||
return response('<h1>403 forbidden</h1>', 403);
|
||||
}
|
||||
/** @var Response $response */
|
||||
$response = $next($request);
|
||||
// Add cross domain HTTP header
|
||||
/*$response->withHeaders([
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Credentials' => 'true',
|
||||
]);*/
|
||||
return $response;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class Base extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
//protected $table = 'test';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
public static function getByID($id)
|
||||
{
|
||||
if($id <= 0) return null;
|
||||
|
||||
return self::where('id', $id)->findOrEmpty();
|
||||
}
|
||||
|
||||
//根据ID更新数据
|
||||
public static function updateByID($id, $data)
|
||||
{
|
||||
return self::where('id', $id)->update($data);
|
||||
}
|
||||
|
||||
//根据where条件和排序获取记录
|
||||
public static function getListByWhereAndOrder($where, $order, $limit = 1)
|
||||
{
|
||||
return self::where($where)
|
||||
->order($order)
|
||||
->limit($limit)
|
||||
->select();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class Book extends Base
|
||||
{
|
||||
protected $createTime = 'create_time';
|
||||
protected $updateTime = false;
|
||||
|
||||
public static function getPageList($categoryID = 0, $name = '', $size = 20)
|
||||
{
|
||||
return self::alias('b')
|
||||
->leftJoin('category c', 'b.category_id = c.id')
|
||||
->field('b.*,c.name as category_name')
|
||||
->when(!empty($categoryID) && $categoryID > 0, function($query) use($categoryID){
|
||||
$query->where('b.category_id', $categoryID);
|
||||
})
|
||||
->when(!empty($name), function($query) use($name){
|
||||
$query->where('b.name', 'like', "%$name%");
|
||||
})
|
||||
->order('b.id desc')
|
||||
->paginate([
|
||||
'list_rows'=> $size,
|
||||
'var_page' => 'page',
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getByName($name)
|
||||
{
|
||||
$name = trim($name);
|
||||
return self::where('name', $name)->findOrEmpty();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class BookLog extends Base
|
||||
{
|
||||
protected $createTime = 'create_time';
|
||||
protected $updateTime = false;
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class Category extends Base
|
||||
{
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
public static function getList()
|
||||
{
|
||||
return self::select();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class Goods extends Base
|
||||
{
|
||||
protected $createTime = false;
|
||||
protected $updateTime = false;
|
||||
|
||||
public static function getPageList($name = '', $size = 20, $order = 'id desc')
|
||||
{
|
||||
return self::when(!empty($name), function($query) use($name){
|
||||
$query->where('name', 'like', "%$name%");
|
||||
})
|
||||
->order($order)
|
||||
->paginate([
|
||||
'list_rows'=> $size,
|
||||
'var_page' => 'page',
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getByName($name)
|
||||
{
|
||||
$name = trim($name);
|
||||
return self::where('name', $name)->findOrEmpty();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class GoodsReceipt extends Base
|
||||
{
|
||||
protected $createTime = false;
|
||||
protected $updateTime = false;
|
||||
protected $name = 'goods_receipt_log';
|
||||
|
||||
public static function getPageList($size = 20)
|
||||
{
|
||||
return self::alias('rl')
|
||||
->join('goods g', 'g.id = rl.goods_id')
|
||||
->order('rl.id desc')
|
||||
->field('rl.*, g.name as goods_name')
|
||||
->paginate([
|
||||
'list_rows'=> $size,
|
||||
'var_page' => 'page',
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class Reading extends Base
|
||||
{
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
public static function getPageList($name = '')
|
||||
{
|
||||
return self::when(!empty($name), function($query) use($name){
|
||||
$query->where('name', 'like', "%$name%");
|
||||
})
|
||||
->order('id desc')
|
||||
->paginate([
|
||||
'list_rows'=> 20,
|
||||
'var_page' => 'page',
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class ReadingBook extends Base
|
||||
{
|
||||
protected $table = 'reading_book';
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
//阶段
|
||||
protected static $status = [
|
||||
'to-read' => '待阅读',
|
||||
'reading' => '阅读中',
|
||||
'finished' => '已阅读'
|
||||
];
|
||||
|
||||
public static function getList($readingID)
|
||||
{
|
||||
$list = self::alias('rb')
|
||||
->leftJoin('book b', 'rb.book_id = b.id')
|
||||
->leftJoin('category c', 'b.category_id = c.id')
|
||||
->field('rb.*,b.name as book_name,b.author,c.name as category_name')
|
||||
->where('rb.reading_id', $readingID)
|
||||
->order('rb.sort', 'asc')
|
||||
->select();
|
||||
return $list->each(function($item){
|
||||
$item->statusStr = self::$status[$item['status']];
|
||||
});
|
||||
}
|
||||
|
||||
public static function onAfterInsert($model)
|
||||
{
|
||||
$model->sort = $model->id;
|
||||
$model->save();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class SaleLog extends Base
|
||||
{
|
||||
protected $createTime = false;
|
||||
protected $updateTime = false;
|
||||
|
||||
public static function getPageList($size = 20)
|
||||
{
|
||||
return self::alias('sl')
|
||||
->join('goods g', 'g.id = sl.goods_id')
|
||||
->order('sl.id desc')
|
||||
->field('sl.*, g.name as goods_name')
|
||||
->paginate([
|
||||
'list_rows'=> $size,
|
||||
'var_page' => 'page',
|
||||
]);
|
||||
}
|
||||
|
||||
//获取销售金额统计
|
||||
public static function getSales($start, $end)
|
||||
{
|
||||
if(empty($start) || empty($end)){
|
||||
return [];
|
||||
}
|
||||
|
||||
return self::alias('sl')
|
||||
->join('goods g', 'g.id = sl.goods_id')
|
||||
->where('sl.sold_at', '>=', $start)
|
||||
->where('sl.sold_at', '<=', $end)
|
||||
->field('sl.sold_at, sum(sl.total_price) as total_sales')
|
||||
->group('sl.sold_at')
|
||||
->select();
|
||||
}
|
||||
|
||||
public static function getSalesGoods($start, $end, $order = 'total_sales')
|
||||
{
|
||||
if(empty($start) || empty($end)){
|
||||
return [];
|
||||
}
|
||||
|
||||
return self::alias('sl')
|
||||
->join('goods g', 'g.id = sl.goods_id')
|
||||
->where('sl.sold_at', '>=', $start)
|
||||
->where('sl.sold_at', '<=', $end)
|
||||
->field('g.name as goods_name, sum(sl.total_price) as total_sales, sum(sl.num) as total_num, sum(sl.num_small) as total_num_small')
|
||||
->order("{$order} asc")
|
||||
->group('sl.goods_id')
|
||||
->select();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace app\model\pms;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class Base extends Model
|
||||
{
|
||||
// 设置当前模型的数据库连接
|
||||
protected $connection = 'pms';
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
//protected $table = 'test';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
public static function getByID($id)
|
||||
{
|
||||
if($id <= 0) return null;
|
||||
|
||||
return self::where('id', $id)->findOrEmpty();
|
||||
}
|
||||
|
||||
//根据ID更新数据
|
||||
public static function updateByID($id, $data)
|
||||
{
|
||||
return self::where('id', $id)->update($data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace app\model\pms;
|
||||
|
||||
class Task extends Base
|
||||
{
|
||||
//protected $table = 'crm_customer';
|
||||
|
||||
public static $statusList = [
|
||||
'wait' => '未开始',
|
||||
'doing' => '进行中',
|
||||
'done' => '已完成',
|
||||
'pause' => '已暂停',
|
||||
'cancel' => '已取消',
|
||||
'closed' => '已关闭',
|
||||
];
|
||||
|
||||
public static function getList($size = 20)
|
||||
{
|
||||
return self::alias('t')
|
||||
->leftJoin('user u', 't.assignedTo = u.account')
|
||||
->leftjoin('user u2', 't.finishedBy = u2.account')
|
||||
->leftJoin('project p', 't.project = p.id')
|
||||
->leftJoin('project p2', 't.execution = p2.id')
|
||||
->where('t.deleted', 0)
|
||||
->where('t.status', 'not in', ['closed', 'cancel'])
|
||||
->order('t.id desc')
|
||||
->field('t.*, u.realname as assignedToName, u2.realname as finishedByName, p.name as projectName, p2.name as executionName')
|
||||
->paginate([
|
||||
'list_rows'=> $size,
|
||||
'var_page' => 'page',
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace app\model\zdoo;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class Base extends Model
|
||||
{
|
||||
// 设置当前模型的数据库连接
|
||||
protected $connection = 'zdoo';
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
//protected $table = 'test';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
public static function getByID($id)
|
||||
{
|
||||
if($id <= 0) return null;
|
||||
|
||||
return self::where('id', $id)->findOrEmpty();
|
||||
}
|
||||
|
||||
//根据ID更新数据
|
||||
public static function updateByID($id, $data)
|
||||
{
|
||||
return self::where('id', $id)->update($data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace app\model\zdoo;
|
||||
|
||||
//沟通记录
|
||||
class Communication extends Base
|
||||
{
|
||||
protected $table = 'sys_action';
|
||||
|
||||
public static function getListByCustomerList($customerIDList)
|
||||
{
|
||||
return self::where('objectType', 'customer')
|
||||
->whereIn('objectID', $customerIDList)
|
||||
->where('comment', '<>','')
|
||||
->order('date desc')
|
||||
->select();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace app\model\zdoo;
|
||||
|
||||
class Customer extends Base
|
||||
{
|
||||
protected $table = 'crm_customer';
|
||||
|
||||
//阶段
|
||||
protected static $stages = [
|
||||
'detail' => '客户录入',
|
||||
'communicate' => '需求沟通',
|
||||
'guide' => '价值引导',
|
||||
'try' => '打包试用',
|
||||
'sign' => '签约',
|
||||
'return' => '回款',
|
||||
'deliver' => '实施交付',
|
||||
'serve' => '跟踪服务',
|
||||
'renew' => '续签增购'
|
||||
];
|
||||
|
||||
//状态
|
||||
public static $statusList = [
|
||||
'potential' => '潜在',
|
||||
'intension' => '意向',
|
||||
'negotiation' => '合同洽谈',
|
||||
'payment-time' => '确认付款时间',
|
||||
'signed' => '已签约',
|
||||
'paid' => '已付款',
|
||||
'failed' => '失败'
|
||||
];
|
||||
|
||||
public static function getPageList($statusList = '', $name = '')
|
||||
{
|
||||
$list = self::alias('c')
|
||||
->leftJoin('sys_user u', 'c.assignedTo = u.account')
|
||||
->where('c.deleted', 0)
|
||||
->when($statusList != '', function($query) use($statusList){
|
||||
$query->whereIn('c.status', $statusList);
|
||||
})
|
||||
->when(!empty($name), function($query) use($name){
|
||||
$query->where('c.name', 'like', "%$name%");
|
||||
})
|
||||
->field('c.*,u.realname as assignedToName')
|
||||
->order('c.contactedDate desc, c.createdDate desc')
|
||||
->paginate([
|
||||
'list_rows'=> 50,
|
||||
'var_page' => 'page',
|
||||
]);
|
||||
$customerIDList = [];
|
||||
foreach($list as $item){
|
||||
$item['stageStr'] = self::$stages[$item['stage']];
|
||||
$item['statusStr'] = self::$statusList[$item['status']];
|
||||
$item['contactedDateStr'] = substr($item['contactedDate'], 0, 10);
|
||||
$item['createdDateStr'] = substr($item['createdDate'], 0, 10);
|
||||
|
||||
$customerIDList[] = $item['id'];
|
||||
}
|
||||
$communicationList = Communication::getListByCustomerList($customerIDList);
|
||||
$customerCommunicationList = [];
|
||||
foreach($communicationList as $c){
|
||||
$customerCommunicationList[$c['objectID']][] = $c;
|
||||
}
|
||||
|
||||
foreach($list as $item){
|
||||
$tmpCommunicationStr = '';
|
||||
if(!empty($customerCommunicationList[$item['id']])){
|
||||
$tmpCommunicationList = $customerCommunicationList[$item['id']];
|
||||
foreach($tmpCommunicationList as $t){
|
||||
if(!empty($t['comment'])){
|
||||
$tmpCommunicationStr .= '<span style="color:red;">' . substr($t['date'], 0, 10) . ':</span>' . $t['comment'] . "<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
$item['communicationStr'] = $tmpCommunicationStr;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/book/add">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">书名</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" maxlength="60" />
|
||||
<div class="layui-form-mid layui-word-aux">注:建议60个字符长度以内</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">分类</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="category_id">
|
||||
{foreach $categoryList as $cate}
|
||||
<option value="{$cate.id}">{$cate.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">作者</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="author" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="remark" maxlength="200" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,13 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/book/addReading">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">书单名</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" maxlength="60" />
|
||||
<div class="layui-form-mid layui-word-aux">注:建议60个字符长度以内</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,119 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/book/addReadingBook">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">书籍分类</label>
|
||||
<div class="layui-input-block">
|
||||
<select lay-filter="category" id="category">
|
||||
<option value="">全部</option>
|
||||
{foreach $categoryList as $cate}
|
||||
<option value="{$cate.id}">{$cate.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">书籍</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="book"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="status">
|
||||
<option value="to-read">待阅读</option>
|
||||
<option value="reading">阅读中</option>
|
||||
<option value="finished">已阅读</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开始</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="start" class="layui-input" id="start" placeholder="yyyy-MM-dd">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">结束</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="end" class="layui-input" id="end" placeholder="yyyy-MM-dd">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="remark" placeholder="文本框" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
<input type="hidden" name="reading_id" value="{$readingID}" />
|
||||
</form>
|
||||
|
||||
<script src="/js/xm-select.js"></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function(){
|
||||
var form = layui.form;
|
||||
var laydate = layui.laydate;
|
||||
var dropdown = layui.dropdown;
|
||||
|
||||
laydate.render({
|
||||
elem: '#start'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#end'
|
||||
});
|
||||
|
||||
var book = xmSelect.render({
|
||||
el: '#book',
|
||||
filterable : true, //开启搜索
|
||||
remoteSearch: true,
|
||||
radio : true, //开启单选模式
|
||||
clickClose : true, //是否点击选项后自动关闭下拉框
|
||||
name: 'book_id', //表单提交时的name
|
||||
paging: true,
|
||||
data : [],
|
||||
remoteMethod: function(val, cb, show){
|
||||
var categoryID = $('#category').val();
|
||||
$.get('/book/apiGetList', {'category_id': categoryID, 'name':val, 'size': 50}, function(data){
|
||||
var bookList = [];
|
||||
data.bookList.data.forEach(element => {
|
||||
var name = element.name + '【' + element.category_name + '】';
|
||||
if(element.author != ''){
|
||||
name += '【' + element.author + '】';
|
||||
}
|
||||
bookList.push({
|
||||
name: name,
|
||||
value: element.id
|
||||
})
|
||||
});
|
||||
cb(bookList);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
form.on('select(category)',function(data){
|
||||
var categoryID = data.value;
|
||||
$.get('/book/apiGetList', {'category_id': categoryID, 'size': 50}, function(data){
|
||||
var bookList = [];
|
||||
data.bookList.data.forEach(element => {
|
||||
var name = element.name + '【' + element.category_name + '】';
|
||||
if(element.author != ''){
|
||||
name += '【' + element.author + '】';
|
||||
}
|
||||
bookList.push({
|
||||
name: name,
|
||||
value: element.id
|
||||
})
|
||||
});
|
||||
book.update({data: bookList});
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
</script>
|
|
@ -0,0 +1,39 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/book/edit">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">书名</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" value="{$book.name??''}" maxlength="60" />
|
||||
<div class="layui-form-mid layui-word-aux">注:建议60个字符长度以内</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">分类</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="category_id">
|
||||
{foreach $categoryList as $cate}
|
||||
<option {if $cate.id == $book.category_id} selected {/if} value="{$cate.id}">{$cate.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">作者</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="author" value="{$book.author??''}" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="remark" value="{$book.remark??''}" maxlength="200" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
<input type="hidden" name="id" value="{$book.id}" />
|
||||
</form>
|
|
@ -0,0 +1,14 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/book/editReading">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">书名</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" value="{$reading.name??''}" maxlength="60" />
|
||||
<div class="layui-form-mid layui-word-aux">注:建议60个字符长度以内</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
<input type="hidden" name="id" value="{$reading.id}" />
|
||||
</form>
|
|
@ -0,0 +1,135 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/book/editReadingBook">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">书籍分类</label>
|
||||
<div class="layui-input-block">
|
||||
<select lay-filter="category" id="category">
|
||||
<option value="">全部</option>
|
||||
{foreach $categoryList as $cate}
|
||||
<option value="{$cate.id}">{$cate.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">书籍</label>
|
||||
<div class="layui-input-block">
|
||||
<div style="color:red;">{$book.name}</div>
|
||||
<div id="book"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="status">
|
||||
<option {if $readingBook.status == 'to-read'}selected{/if} value="to-read">待阅读</option>
|
||||
<option {if $readingBook.status == 'reading'}selected{/if} value="reading">阅读中</option>
|
||||
<option {if $readingBook.status == 'finished'}selected{/if} value="finished">已阅读</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开始</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" id="start" name="start" value="{$readingBook.start}" placeholder="yyyy-MM-dd">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">结束</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" id="end" name="end" value="{$readingBook.end}" placeholder="yyyy-MM-dd">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="remark" placeholder="文本框" class="layui-input" value="{$readingBook.remark}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
<input type="hidden" name="id" value="{$readingBook.id}" />
|
||||
</form>
|
||||
|
||||
<script src="/js/xm-select.js"></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function(){
|
||||
var form = layui.form;
|
||||
var laydate = layui.laydate;
|
||||
var dropdown = layui.dropdown;
|
||||
var initValue = ["{$readingBook.book_id}"];
|
||||
var bookID = {$readingBook.book_id};
|
||||
|
||||
console.log(bookID);
|
||||
|
||||
laydate.render({
|
||||
elem: '#start'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#end'
|
||||
});
|
||||
|
||||
var book = xmSelect.render({
|
||||
el: '#book',
|
||||
filterable : true, //开启搜索
|
||||
remoteSearch: true,
|
||||
radio : true, //开启单选模式
|
||||
clickClose : true, //是否点击选项后自动关闭下拉框
|
||||
name: 'book_id', //表单提交时的name
|
||||
paging: true,
|
||||
data : [],
|
||||
initValue: initValue,
|
||||
remoteMethod: function(val, cb, show){
|
||||
var categoryID = $('#category').val();
|
||||
$.get('/book/apiGetList', {'category_id': categoryID, 'name':val, 'size': 500}, function(data){
|
||||
var bookList = [];
|
||||
data.bookList.data.forEach(element => {
|
||||
var name = element.name + '【' + element.category_name + '】';
|
||||
if(element.author != ''){
|
||||
name += '【' + element.author + '】';
|
||||
}
|
||||
|
||||
if(element.id == bookID){
|
||||
bookList.push({
|
||||
name: name,
|
||||
value: element.id,
|
||||
selected: true
|
||||
});
|
||||
}else{
|
||||
bookList.push({
|
||||
name: name,
|
||||
value: element.id
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
cb(bookList);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
form.on('select(category)',function(data){
|
||||
var categoryID = data.value;
|
||||
$.get('/book/apiGetList', {'category_id': categoryID, 'size': 50}, function(data){
|
||||
var bookList = [];
|
||||
data.bookList.data.forEach(element => {
|
||||
var name = element.name + '【' + element.category_name + '】';
|
||||
if(element.author != ''){
|
||||
name += '【' + element.author + '】';
|
||||
}
|
||||
bookList.push({
|
||||
name: name,
|
||||
value: element.id
|
||||
})
|
||||
});
|
||||
book.update({data: bookList});
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
</script>
|
|
@ -0,0 +1,363 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-row">
|
||||
<div class="layui-btn-container layui-col-md2">
|
||||
<button class="layui-btn layui-btn-sm" lay-event="add">添加</button>
|
||||
</div>
|
||||
<form class="layui-form layui-col-space16" action="/book">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<select name="category_id">
|
||||
<option {if $categoryID == 0}selected{/if} value="0">全部</option>
|
||||
{foreach $categoryList as $cate}
|
||||
<option {if $cate['id'] == $categoryID}selected{/if} value="{$cate.id}">{$cate.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<input type="text" name="name" placeholder="书名" value="{$name??''}" lay-affix="clear" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-btn-container layui-col-md3 layui-col-xs12">
|
||||
<button class="layui-btn" lay-submit lay-filter="demo-table-search">搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">Clear</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
<script type="text/html" id="toolDemo">
|
||||
<div class="layui-clear-space">
|
||||
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="more">
|
||||
更多
|
||||
<i class="layui-icon layui-icon-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use(['table', 'dropdown'], function(){
|
||||
var table = layui.table;
|
||||
var dropdown = layui.dropdown;
|
||||
var name = "{$name}";
|
||||
var categoryID = "{$categoryID}";
|
||||
|
||||
// 创建渲染实例
|
||||
table.render({
|
||||
elem: '#test',
|
||||
url: '/book/apiGetList?name=' + name + '&category_id=' + categoryID, // 此处为静态模拟数据,实际使用时需换成真实接口
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar: ['filter', 'exports', 'print', { // 右上角工具图标
|
||||
title: '提示',
|
||||
layEvent: 'LAYTABLE_TIPS',
|
||||
icon: 'layui-icon-tips',
|
||||
onClick: function(obj) { // 2.9.12+
|
||||
layer.alert('自定义工具栏图标按钮');
|
||||
}
|
||||
}],
|
||||
height: 'full-135', // 最大高度减去其他容器已占有的高度差
|
||||
css: [ // 重设当前表格样式
|
||||
'.layui-table-tool-temp{padding-right: 145px;}'
|
||||
].join(''),
|
||||
cellMinWidth: 80,
|
||||
//totalRow: true, // 开启合计行
|
||||
//page: true,
|
||||
page: { // 支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档
|
||||
layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
|
||||
//curr: 5, //设定初始在第 5 页
|
||||
limit: 20,
|
||||
//groups: 1, //只显示 1 个连续页码
|
||||
//first: false, //不显示首页
|
||||
//last: false //不显示尾页
|
||||
},
|
||||
// 将原始数据解析成 table 组件所规定的数据格式
|
||||
parseData: function(res){
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.bookList.total, //解析数据长度
|
||||
"data": res.bookList.data //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{type: 'checkbox', fixed: 'left'},
|
||||
{field: 'id', fixed: 'left', width:80, title: 'ID'},
|
||||
{field: 'name', width:300, title: '书名'},
|
||||
{field: 'category_name', width:100, title: '分类'},
|
||||
{field: 'author', width:300, title: '作者'},
|
||||
{field: 'remark', width:300, title: '备注'},
|
||||
{field: 'create_time', title:'加入时间', width: 200},
|
||||
{fixed: 'right', title:'操作', minWidth: 125, templet: '#toolDemo'}
|
||||
]],
|
||||
done: function(){
|
||||
var id = this.id;
|
||||
// 下拉按钮测试
|
||||
dropdown.render({
|
||||
elem: '#dropdownButton', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'add',
|
||||
title: '添加'
|
||||
},{
|
||||
id: 'update',
|
||||
title: '编辑'
|
||||
},{
|
||||
id: 'delete',
|
||||
title: '删除'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/book/add');
|
||||
// layer.open({
|
||||
// title: '添加',
|
||||
// type: 2,
|
||||
// area: ['80%','80%'],
|
||||
// content: '/book/add'
|
||||
// });
|
||||
break;
|
||||
case 'update':
|
||||
console.log(data);
|
||||
console.log(obj);
|
||||
|
||||
if(data.length !== 1) return layer.msg('请选择一行');
|
||||
layer.open({
|
||||
title: '编辑',
|
||||
type: 1,
|
||||
area: ['80%','80%'],
|
||||
content: '<div style="padding: 16px;">自定义表单元素</div>'
|
||||
});
|
||||
break;
|
||||
case 'delete':
|
||||
if(data.length === 0){
|
||||
return layer.msg('请选择一行');
|
||||
}
|
||||
layer.msg('delete event');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 重载测试
|
||||
dropdown.render({
|
||||
elem: '#reloadTest', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'reload',
|
||||
title: '重载'
|
||||
},{
|
||||
id: 'reload-deep',
|
||||
title: '重载 - 参数叠加'
|
||||
},{
|
||||
id: 'reloadData',
|
||||
title: '仅重载数据'
|
||||
},{
|
||||
id: 'reloadData-deep',
|
||||
title: '仅重载数据 - 参数叠加'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
switch(obj.id){
|
||||
case 'reload':
|
||||
// 重载 - 默认(参数重置)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'reload-deep':
|
||||
// 重载 - 深度(参数叠加)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
},
|
||||
//defaultToolbar: ['print'], // 重载头部工具栏右侧图标
|
||||
//cols: ins1.config.cols
|
||||
}, true);
|
||||
break;
|
||||
case 'reloadData':
|
||||
// 数据重载 - 参数重置
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
scrollPos: 'fixed', // 保持滚动条位置不变 - v2.7.3 新增
|
||||
height: 2000, // 测试无效参数(即与数据无关的参数设置无效,此处以 height 设置无效为例)
|
||||
//url: '404',
|
||||
//page: {curr: 1, limit: 30} // 重新指向分页
|
||||
});
|
||||
break;
|
||||
case 'reloadData-deep':
|
||||
// 数据重载 - 参数叠加
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
}
|
||||
}, true);
|
||||
break;
|
||||
}
|
||||
layer.msg('可观察 Network 请求参数的变化');
|
||||
}
|
||||
});
|
||||
|
||||
// 行模式
|
||||
dropdown.render({
|
||||
elem: '#rowMode',
|
||||
data: [{
|
||||
id: 'default-row',
|
||||
title: '单行模式(默认)'
|
||||
},{
|
||||
id: 'multi-row',
|
||||
title: '多行模式'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'default-row':
|
||||
table.reload('test', {
|
||||
lineStyle: null // 恢复单行
|
||||
});
|
||||
layer.msg('已设为单行');
|
||||
break;
|
||||
case 'multi-row':
|
||||
table.reload('test', {
|
||||
// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注:v2.7.0 新增
|
||||
lineStyle: 'height: 95px;'
|
||||
});
|
||||
layer.msg('即通过设置 lineStyle 参数可开启多行');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(res, msg){
|
||||
console.log(res, msg)
|
||||
}
|
||||
});
|
||||
|
||||
// 工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
var id = obj.config.id;
|
||||
var checkStatus = table.checkStatus(id);
|
||||
var othis = lay(this);
|
||||
switch(obj.event){
|
||||
case 'getCheckData':
|
||||
var data = checkStatus.data;
|
||||
layer.alert(layui.util.escape(JSON.stringify(data)));
|
||||
break;
|
||||
case 'getData':
|
||||
var getData = table.getData(id);
|
||||
console.log(getData);
|
||||
layer.alert(layui.util.escape(JSON.stringify(getData)));
|
||||
break;
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/book/add');
|
||||
break;
|
||||
};
|
||||
});
|
||||
// 表头自定义元素工具事件 --- 2.8.8+
|
||||
table.on('colTool(test)', function(obj){
|
||||
var event = obj.event;
|
||||
console.log(obj);
|
||||
if(event === 'email-tips'){
|
||||
layer.alert(layui.util.escape(JSON.stringify(obj.col)), {
|
||||
title: '当前列属性配置项'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 触发单元格工具事件
|
||||
table.on('tool(test)', function(obj){ // 双击 toolDouble
|
||||
var data = obj.data; // 获得当前行数据
|
||||
// console.log(obj)
|
||||
if(obj.event === 'edit'){
|
||||
layerAlert('get', '添加', '/book/edit?id=' + data.id);
|
||||
} else if(obj.event === 'more'){
|
||||
// 更多 - 下拉菜单
|
||||
dropdown.render({
|
||||
elem: this, // 触发事件的 DOM 对象
|
||||
show: true, // 外部事件触发即显示
|
||||
data: [{
|
||||
title: '查看',
|
||||
id: 'detail'
|
||||
},{
|
||||
title: '删除',
|
||||
id: 'del'
|
||||
}],
|
||||
click: function(menudata){
|
||||
if(menudata.id === 'detail'){
|
||||
layer.msg('查看操作,当前行 ID:'+ data.id);
|
||||
} else if(menudata.id === 'del'){
|
||||
layer.confirm('真的删除行 [id: '+ data.id +'] 么', function(index){
|
||||
obj.del(); // 删除对应行(tr)的DOM结构
|
||||
layer.close(index);
|
||||
// 向服务端发送删除指令
|
||||
});
|
||||
}
|
||||
},
|
||||
align: 'right', // 右对齐弹出
|
||||
style: 'box-shadow: 1px 1px 10px rgb(0 0 0 / 12%);' // 设置额外样式
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// 触发表格复选框选择
|
||||
table.on('checkbox(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 触发表格单选框选择
|
||||
table.on('radio(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 行单击事件
|
||||
table.on('row(test)', function(obj){
|
||||
//console.log(obj);
|
||||
//layer.closeAll('tips');
|
||||
});
|
||||
// 行双击事件
|
||||
table.on('rowDouble(test)', function(obj){
|
||||
console.log(obj);
|
||||
});
|
||||
|
||||
// 单元格编辑事件
|
||||
table.on('edit(test)', function(obj){
|
||||
var field = obj.field; // 得到字段
|
||||
var value = obj.value; // 得到修改后的值
|
||||
var data = obj.data; // 得到所在行所有键值
|
||||
// 值的校验
|
||||
if(field === 'email'){
|
||||
if(!/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(obj.value)){
|
||||
layer.tips('输入的邮箱格式不正确,请重新编辑', this, {tips: 1});
|
||||
return obj.reedit(); // 重新编辑 -- v2.8.0 新增
|
||||
}
|
||||
}
|
||||
// 编辑后续操作,如提交更新请求,以完成真实的数据更新
|
||||
// …
|
||||
layer.msg('编辑成功', {icon: 1});
|
||||
|
||||
// 其他更新操作
|
||||
var update = {};
|
||||
update[field] = value;
|
||||
obj.update(update);
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,315 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-row">
|
||||
<div class="layui-btn-container layui-col-md2">
|
||||
<button class="layui-btn layui-btn-sm" lay-event="add">添加</button>
|
||||
</div>
|
||||
<form class="layui-form layui-col-space16" action="/book/reading">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<input type="text" name="name" placeholder="书单名" value="{$name??''}" lay-affix="clear" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-btn-container layui-col-md3 layui-col-xs12">
|
||||
<button class="layui-btn" lay-submit lay-filter="demo-table-search">搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">Clear</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
<script type="text/html" id="toolDemo">
|
||||
<div class="layui-clear-space">
|
||||
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="readingBook">详情</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="more">
|
||||
更多
|
||||
<i class="layui-icon layui-icon-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use(['table', 'dropdown'], function(){
|
||||
var table = layui.table;
|
||||
var dropdown = layui.dropdown;
|
||||
var name = "{$name}";
|
||||
|
||||
// 创建渲染实例
|
||||
table.render({
|
||||
elem: '#test',
|
||||
url: '/book/apiGetReadingList?name=' + name, // 此处为静态模拟数据,实际使用时需换成真实接口
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar: ['filter', 'exports', 'print', { // 右上角工具图标
|
||||
title: '提示',
|
||||
layEvent: 'LAYTABLE_TIPS',
|
||||
icon: 'layui-icon-tips',
|
||||
onClick: function(obj) { // 2.9.12+
|
||||
layer.alert('自定义工具栏图标按钮');
|
||||
}
|
||||
}],
|
||||
height: 'full-135', // 最大高度减去其他容器已占有的高度差
|
||||
css: [ // 重设当前表格样式
|
||||
'.layui-table-tool-temp{padding-right: 145px;}'
|
||||
].join(''),
|
||||
cellMinWidth: 80,
|
||||
//totalRow: true, // 开启合计行
|
||||
//page: true,
|
||||
page: { // 支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档
|
||||
layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
|
||||
//curr: 5, //设定初始在第 5 页
|
||||
limit: 20,
|
||||
//groups: 1, //只显示 1 个连续页码
|
||||
//first: false, //不显示首页
|
||||
//last: false //不显示尾页
|
||||
},
|
||||
// 将原始数据解析成 table 组件所规定的数据格式
|
||||
parseData: function(res){
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.readingList.total, //解析数据长度
|
||||
"data": res.readingList.data //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{field: 'id', fixed: 'left', width:80, title: 'ID'},
|
||||
{field: 'name', width:300, title: '书单名'},
|
||||
{fixed: 'right', title:'操作', minWidth: 125, templet: '#toolDemo'}
|
||||
]],
|
||||
done: function(){
|
||||
var id = this.id;
|
||||
// 下拉按钮测试
|
||||
dropdown.render({
|
||||
elem: '#dropdownButton', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'add',
|
||||
title: '添加'
|
||||
},{
|
||||
id: 'update',
|
||||
title: '编辑'
|
||||
},{
|
||||
id: 'delete',
|
||||
title: '删除'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/book/add');
|
||||
// layer.open({
|
||||
// title: '添加',
|
||||
// type: 2,
|
||||
// area: ['80%','80%'],
|
||||
// content: '/book/add'
|
||||
// });
|
||||
break;
|
||||
case 'update':
|
||||
console.log(data);
|
||||
console.log(obj);
|
||||
|
||||
if(data.length !== 1) return layer.msg('请选择一行');
|
||||
layer.open({
|
||||
title: '编辑',
|
||||
type: 1,
|
||||
area: ['80%','80%'],
|
||||
content: '<div style="padding: 16px;">自定义表单元素</div>'
|
||||
});
|
||||
break;
|
||||
case 'delete':
|
||||
if(data.length === 0){
|
||||
return layer.msg('请选择一行');
|
||||
}
|
||||
layer.msg('delete event');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 重载测试
|
||||
dropdown.render({
|
||||
elem: '#reloadTest', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'reload',
|
||||
title: '重载'
|
||||
},{
|
||||
id: 'reload-deep',
|
||||
title: '重载 - 参数叠加'
|
||||
},{
|
||||
id: 'reloadData',
|
||||
title: '仅重载数据'
|
||||
},{
|
||||
id: 'reloadData-deep',
|
||||
title: '仅重载数据 - 参数叠加'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
switch(obj.id){
|
||||
case 'reload':
|
||||
// 重载 - 默认(参数重置)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'reload-deep':
|
||||
// 重载 - 深度(参数叠加)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
},
|
||||
//defaultToolbar: ['print'], // 重载头部工具栏右侧图标
|
||||
//cols: ins1.config.cols
|
||||
}, true);
|
||||
break;
|
||||
case 'reloadData':
|
||||
// 数据重载 - 参数重置
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
scrollPos: 'fixed', // 保持滚动条位置不变 - v2.7.3 新增
|
||||
height: 2000, // 测试无效参数(即与数据无关的参数设置无效,此处以 height 设置无效为例)
|
||||
//url: '404',
|
||||
//page: {curr: 1, limit: 30} // 重新指向分页
|
||||
});
|
||||
break;
|
||||
case 'reloadData-deep':
|
||||
// 数据重载 - 参数叠加
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
}
|
||||
}, true);
|
||||
break;
|
||||
}
|
||||
layer.msg('可观察 Network 请求参数的变化');
|
||||
}
|
||||
});
|
||||
|
||||
// 行模式
|
||||
dropdown.render({
|
||||
elem: '#rowMode',
|
||||
data: [{
|
||||
id: 'default-row',
|
||||
title: '单行模式(默认)'
|
||||
},{
|
||||
id: 'multi-row',
|
||||
title: '多行模式'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'default-row':
|
||||
table.reload('test', {
|
||||
lineStyle: null // 恢复单行
|
||||
});
|
||||
layer.msg('已设为单行');
|
||||
break;
|
||||
case 'multi-row':
|
||||
table.reload('test', {
|
||||
// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注:v2.7.0 新增
|
||||
lineStyle: 'height: 95px;'
|
||||
});
|
||||
layer.msg('即通过设置 lineStyle 参数可开启多行');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(res, msg){
|
||||
console.log(res, msg)
|
||||
}
|
||||
});
|
||||
|
||||
// 工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
var id = obj.config.id;
|
||||
var checkStatus = table.checkStatus(id);
|
||||
var othis = lay(this);
|
||||
switch(obj.event){
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/book/addReading');
|
||||
break;
|
||||
};
|
||||
});
|
||||
// 表头自定义元素工具事件 --- 2.8.8+
|
||||
table.on('colTool(test)', function(obj){
|
||||
var event = obj.event;
|
||||
console.log(obj);
|
||||
if(event === 'email-tips'){
|
||||
layer.alert(layui.util.escape(JSON.stringify(obj.col)), {
|
||||
title: '当前列属性配置项'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 触发单元格工具事件
|
||||
table.on('tool(test)', function(obj){ // 双击 toolDouble
|
||||
var data = obj.data; // 获得当前行数据
|
||||
// console.log(obj)
|
||||
if(obj.event === 'edit'){
|
||||
layerAlert('get', '添加', '/book/editReading?id=' + data.id);
|
||||
} else if(obj.event === 'readingBook'){ //读书清单详情
|
||||
location.href = '/book/readingBook?id=' + data.id;
|
||||
}
|
||||
});
|
||||
|
||||
// 触发表格复选框选择
|
||||
table.on('checkbox(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 触发表格单选框选择
|
||||
table.on('radio(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 行单击事件
|
||||
table.on('row(test)', function(obj){
|
||||
//console.log(obj);
|
||||
//layer.closeAll('tips');
|
||||
});
|
||||
// 行双击事件
|
||||
table.on('rowDouble(test)', function(obj){
|
||||
console.log(obj);
|
||||
});
|
||||
|
||||
// 单元格编辑事件
|
||||
table.on('edit(test)', function(obj){
|
||||
var field = obj.field; // 得到字段
|
||||
var value = obj.value; // 得到修改后的值
|
||||
var data = obj.data; // 得到所在行所有键值
|
||||
// 值的校验
|
||||
if(field === 'email'){
|
||||
if(!/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(obj.value)){
|
||||
layer.tips('输入的邮箱格式不正确,请重新编辑', this, {tips: 1});
|
||||
return obj.reedit(); // 重新编辑 -- v2.8.0 新增
|
||||
}
|
||||
}
|
||||
// 编辑后续操作,如提交更新请求,以完成真实的数据更新
|
||||
// …
|
||||
layer.msg('编辑成功', {icon: 1});
|
||||
|
||||
// 其他更新操作
|
||||
var update = {};
|
||||
update[field] = value;
|
||||
obj.update(update);
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,126 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-row">
|
||||
<div class="layui-btn-container layui-col-md2">
|
||||
<span>{$reading.name}</span>
|
||||
<button class="layui-btn layui-btn-sm" lay-event="add">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/html" id="toolDemo">
|
||||
<div class="layui-clear-space">
|
||||
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="del">删除</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="start">开始</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="end">结束</a>
|
||||
</div>
|
||||
</script>
|
||||
<!--script src="/layui/soulTable/soulTable.slim.js"></script-->
|
||||
<script>
|
||||
layui.config({
|
||||
base: '/layui/', // 第三方模块所在目录
|
||||
version: 'v1.9.0' // 插件版本号
|
||||
}).extend({
|
||||
soulTable: 'soulTable/soulTable.slim'
|
||||
});
|
||||
|
||||
layui.use(['table', 'dropdown', 'soulTable'], function(){
|
||||
var table = layui.table;
|
||||
var dropdown = layui.dropdown;
|
||||
var soulTable = layui.soulTable;
|
||||
var readingID = "{$reading.id}";
|
||||
|
||||
// 创建渲染实例
|
||||
table.render({
|
||||
elem: '#test',
|
||||
url: '/book/apiGetReadingBookList?id=' + readingID, // 此处为静态模拟数据,实际使用时需换成真实接口
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar: ['filter'],
|
||||
height: 'full-135', // 最大高度减去其他容器已占有的高度差
|
||||
even: true,
|
||||
css: [ // 重设当前表格样式
|
||||
'.layui-table-tool-temp{padding-right: 145px;}'
|
||||
].join(''),
|
||||
cellMinWidth: 80,
|
||||
//totalRow: true, // 开启合计行
|
||||
//page: true,
|
||||
page: { // 支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档
|
||||
layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
|
||||
//curr: 5, //设定初始在第 5 页
|
||||
limit: 50,
|
||||
//groups: 1, //只显示 1 个连续页码
|
||||
//first: false, //不显示首页
|
||||
//last: false //不显示尾页
|
||||
},
|
||||
// 将原始数据解析成 table 组件所规定的数据格式
|
||||
parseData: function(res){
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.bookList.length, //解析数据长度
|
||||
"data": res.bookList //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{field: 'id', fixed: 'left', width:80, title: 'ID'},
|
||||
{field: 'book_name', width:300, title: '书名'},
|
||||
{field: 'author', width:180, title: '作者'},
|
||||
{field: 'category_name', width:100, title: '分类'},
|
||||
{field: 'statusStr', width:100, title: '状态'},
|
||||
{field: 'start', width:120, title: '开始'},
|
||||
{field: 'end', width:120, title: '结束'},
|
||||
{field: 'remark', title: '备注'},
|
||||
{fixed: 'right', title:'操作', minWidth: 60, templet: '#toolDemo'}
|
||||
]],
|
||||
rowDrag:{done:function(obj){
|
||||
//拖动排序
|
||||
var num = obj.newIndex - obj.oldIndex;
|
||||
$.post('/book/apiSortReadingBook', {id: obj.row.id, num: num}, function(data){
|
||||
alert(data.msg);
|
||||
});
|
||||
}},
|
||||
done: function() {
|
||||
// 在 done 中开启
|
||||
soulTable.render(this)
|
||||
}
|
||||
});
|
||||
|
||||
// 工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
var id = obj.config.id;
|
||||
var checkStatus = table.checkStatus(id);
|
||||
var othis = lay(this);
|
||||
|
||||
switch(obj.event){
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/book/addReadingBook?reading_id=' + readingID);
|
||||
break;
|
||||
};
|
||||
});
|
||||
|
||||
// 触发单元格工具事件
|
||||
table.on('tool(test)', function(obj){ // 双击 toolDouble
|
||||
var data = obj.data; // 获得当前行数据
|
||||
// console.log(obj)
|
||||
if(obj.event === 'edit'){
|
||||
layerAlert('get', '编辑', '/book/editReadingBook?id=' + data.id);
|
||||
} else if(obj.event === 'del'){ //删除
|
||||
$.get('/book/apiDelReadingBook', {id:data.id},function(data){
|
||||
layui.layer.msg(data.msg);
|
||||
});
|
||||
} else if(obj.event === 'start'){ //开始
|
||||
$.post('/book/apiStartReadingBook', {id: data.id}, function(data){
|
||||
layui.layer.msg(data.msg);
|
||||
});
|
||||
} else if(obj.event === 'end'){ //结束
|
||||
$.post('/book/apiEndReadingBook', {id: data.id}, function(data){
|
||||
layui.layer.msg(data.msg);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,13 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/category/add">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类名</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" maxlength="60" />
|
||||
<div class="layui-form-mid layui-word-aux">注:建议60个字符长度以内</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,305 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm" lay-event="getCheckData">获取选中行数据</button>
|
||||
<button class="layui-btn layui-btn-sm" lay-event="getData">获取当前页数据</button>
|
||||
<button class="layui-btn layui-btn-sm" id="dropdownButton">
|
||||
下拉按钮
|
||||
<i class="layui-icon layui-icon-down layui-font-12"></i>
|
||||
</button>
|
||||
<button class="layui-btn layui-btn-sm layui-bg-blue" id="reloadTest">
|
||||
重载测试
|
||||
<i class="layui-icon layui-icon-down layui-font-12"></i>
|
||||
</button>
|
||||
<button class="layui-btn layui-btn-sm layui-btn-primary" id="rowMode">
|
||||
<span>{{= d.lineStyle ? '多行' : '单行' }}模式</span>
|
||||
<i class="layui-icon layui-icon-down layui-font-12"></i>
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/html" id="toolDemo">
|
||||
<div class="layui-clear-space">
|
||||
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="del">删除</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use(['table', 'dropdown'], function(){
|
||||
var table = layui.table;
|
||||
var dropdown = layui.dropdown;
|
||||
|
||||
// 创建渲染实例
|
||||
table.render({
|
||||
elem: '#test',
|
||||
url: '/category/apiGetList', // 此处为静态模拟数据,实际使用时需换成真实接口
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar: ['filter', 'exports', 'print', { // 右上角工具图标
|
||||
title: '提示',
|
||||
layEvent: 'LAYTABLE_TIPS',
|
||||
icon: 'layui-icon-tips',
|
||||
onClick: function(obj) { // 2.9.12+
|
||||
layer.alert('自定义工具栏图标按钮');
|
||||
}
|
||||
}],
|
||||
height: 'full-135', // 最大高度减去其他容器已占有的高度差
|
||||
css: [ // 重设当前表格样式
|
||||
'.layui-table-tool-temp{padding-right: 145px;}'
|
||||
].join(''),
|
||||
cellMinWidth: 80,
|
||||
totalRow: true, // 开启合计行
|
||||
page: true,
|
||||
// 将原始数据解析成 table 组件所规定的数据格式
|
||||
parseData: function(res){
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.list.length, //解析数据长度
|
||||
"data": res.list //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{type: 'checkbox', fixed: 'left'},
|
||||
{field: 'id', fixed: 'left', width:80, title: 'ID', sort: true, totalRow: '合计:'},
|
||||
{field: 'name', width:300, title: '名称'},
|
||||
{fixed: 'right', title:'操作', minWidth: 125, templet: '#toolDemo'}
|
||||
]],
|
||||
done: function(){
|
||||
var id = this.id;
|
||||
// 下拉按钮测试
|
||||
dropdown.render({
|
||||
elem: '#dropdownButton', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'add',
|
||||
title: '添加'
|
||||
},{
|
||||
id: 'update',
|
||||
title: '编辑'
|
||||
},{
|
||||
id: 'delete',
|
||||
title: '删除'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/category/add');
|
||||
break;
|
||||
case 'update':
|
||||
console.log(data);
|
||||
console.log(obj);
|
||||
|
||||
if(data.length !== 1) return layer.msg('请选择一行');
|
||||
layer.open({
|
||||
title: '编辑',
|
||||
type: 1,
|
||||
area: ['80%','80%'],
|
||||
content: '<div style="padding: 16px;">自定义表单元素</div>'
|
||||
});
|
||||
break;
|
||||
case 'delete':
|
||||
if(data.length === 0){
|
||||
return layer.msg('请选择一行');
|
||||
}
|
||||
layer.msg('delete event');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 重载测试
|
||||
dropdown.render({
|
||||
elem: '#reloadTest', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'reload',
|
||||
title: '重载'
|
||||
},{
|
||||
id: 'reload-deep',
|
||||
title: '重载 - 参数叠加'
|
||||
},{
|
||||
id: 'reloadData',
|
||||
title: '仅重载数据'
|
||||
},{
|
||||
id: 'reloadData-deep',
|
||||
title: '仅重载数据 - 参数叠加'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
switch(obj.id){
|
||||
case 'reload':
|
||||
// 重载 - 默认(参数重置)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'reload-deep':
|
||||
// 重载 - 深度(参数叠加)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
},
|
||||
//defaultToolbar: ['print'], // 重载头部工具栏右侧图标
|
||||
//cols: ins1.config.cols
|
||||
}, true);
|
||||
break;
|
||||
case 'reloadData':
|
||||
// 数据重载 - 参数重置
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
scrollPos: 'fixed', // 保持滚动条位置不变 - v2.7.3 新增
|
||||
height: 2000, // 测试无效参数(即与数据无关的参数设置无效,此处以 height 设置无效为例)
|
||||
//url: '404',
|
||||
//page: {curr: 1, limit: 30} // 重新指向分页
|
||||
});
|
||||
break;
|
||||
case 'reloadData-deep':
|
||||
// 数据重载 - 参数叠加
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
}
|
||||
}, true);
|
||||
break;
|
||||
}
|
||||
layer.msg('可观察 Network 请求参数的变化');
|
||||
}
|
||||
});
|
||||
|
||||
// 行模式
|
||||
dropdown.render({
|
||||
elem: '#rowMode',
|
||||
data: [{
|
||||
id: 'default-row',
|
||||
title: '单行模式(默认)'
|
||||
},{
|
||||
id: 'multi-row',
|
||||
title: '多行模式'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'default-row':
|
||||
table.reload('test', {
|
||||
lineStyle: null // 恢复单行
|
||||
});
|
||||
layer.msg('已设为单行');
|
||||
break;
|
||||
case 'multi-row':
|
||||
table.reload('test', {
|
||||
// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注:v2.7.0 新增
|
||||
lineStyle: 'height: 95px;'
|
||||
});
|
||||
layer.msg('即通过设置 lineStyle 参数可开启多行');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(res, msg){
|
||||
console.log(res, msg)
|
||||
}
|
||||
});
|
||||
|
||||
// 工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
var id = obj.config.id;
|
||||
var checkStatus = table.checkStatus(id);
|
||||
var othis = lay(this);
|
||||
switch(obj.event){
|
||||
case 'getCheckData':
|
||||
var data = checkStatus.data;
|
||||
layer.alert(layui.util.escape(JSON.stringify(data)));
|
||||
break;
|
||||
case 'getData':
|
||||
var getData = table.getData(id);
|
||||
console.log(getData);
|
||||
layer.alert(layui.util.escape(JSON.stringify(getData)));
|
||||
break;
|
||||
};
|
||||
});
|
||||
// 表头自定义元素工具事件 --- 2.8.8+
|
||||
table.on('colTool(test)', function(obj){
|
||||
var event = obj.event;
|
||||
console.log(obj);
|
||||
if(event === 'email-tips'){
|
||||
layer.alert(layui.util.escape(JSON.stringify(obj.col)), {
|
||||
title: '当前列属性配置项'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 触发单元格工具事件
|
||||
table.on('tool(test)', function(obj){ // 双击 toolDouble
|
||||
var data = obj.data; // 获得当前行数据
|
||||
if(obj.event === 'edit'){
|
||||
layerAlert('get', '添加', '/book/edit?id=' + data.id);
|
||||
}else if(obj.event === 'del'){
|
||||
layer.confirm('真的删除行 [id: '+ data.id +'] 么', function(index){
|
||||
obj.del(); // 删除对应行(tr)的DOM结构
|
||||
layer.close(index);
|
||||
// 向服务端发送删除指令
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 触发表格复选框选择
|
||||
table.on('checkbox(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 触发表格单选框选择
|
||||
table.on('radio(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 行单击事件
|
||||
table.on('row(test)', function(obj){
|
||||
//console.log(obj);
|
||||
//layer.closeAll('tips');
|
||||
});
|
||||
// 行双击事件
|
||||
table.on('rowDouble(test)', function(obj){
|
||||
console.log(obj);
|
||||
});
|
||||
|
||||
// 单元格编辑事件
|
||||
table.on('edit(test)', function(obj){
|
||||
var field = obj.field; // 得到字段
|
||||
var value = obj.value; // 得到修改后的值
|
||||
var data = obj.data; // 得到所在行所有键值
|
||||
// 值的校验
|
||||
if(field === 'email'){
|
||||
if(!/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(obj.value)){
|
||||
layer.tips('输入的邮箱格式不正确,请重新编辑', this, {tips: 1});
|
||||
return obj.reedit(); // 重新编辑 -- v2.8.0 新增
|
||||
}
|
||||
}
|
||||
// 编辑后续操作,如提交更新请求,以完成真实的数据更新
|
||||
// …
|
||||
layer.msg('编辑成功', {icon: 1});
|
||||
|
||||
// 其他更新操作
|
||||
var update = {};
|
||||
update[field] = value;
|
||||
obj.update(update);
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,94 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<form class="layui-form layui-row layui-col-space16" action="/customer">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div id="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<input type="text" name="name" placeholder="客户名称" lay-affix="clear" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-btn-container layui-col-md3 layui-col-xs12">
|
||||
<button class="layui-btn" lay-submit lay-filter="demo-table-search">搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">Clear</button>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
<script src="/js/xm-select.js"></script>
|
||||
<script>
|
||||
layui.use(['table', 'dropdown'], function(){
|
||||
var table = layui.table;
|
||||
var dropdown = layui.dropdown;
|
||||
var statusList = "{$statusList}";
|
||||
var name = "{$name}";
|
||||
|
||||
// 创建渲染实例
|
||||
table.render({
|
||||
elem: '#test',
|
||||
url: '/customer/apiGetList?statusList=' + statusList + '&name=' + name, // 此处为静态模拟数据,实际使用时需换成真实接口
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar: ['filter'],
|
||||
height: 'full-135', // 最大高度减去其他容器已占有的高度差
|
||||
css: [ // 重设当前表格样式
|
||||
'.layui-table-tool-temp{padding-right: 145px;}',
|
||||
'.layui-table-cell{height: auto; line-height: normal;white-space: normal;word-break: break-all;overflow: visible;}'
|
||||
].join(''),
|
||||
cellMinWidth: 80,
|
||||
//totalRow: true, // 开启合计行
|
||||
//page: true,
|
||||
page: { // 支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档
|
||||
layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
|
||||
//curr: 5, //设定初始在第 5 页
|
||||
limit: 50,
|
||||
//groups: 1, //只显示 1 个连续页码
|
||||
//first: false, //不显示首页
|
||||
//last: false //不显示尾页
|
||||
},
|
||||
// 将原始数据解析成 table 组件所规定的数据格式
|
||||
parseData: function(res){
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.list.total, //解析数据长度
|
||||
"data": res.list.data //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{field: 'id', fixed: 'left', width:60, title: 'ID'},
|
||||
{field: 'name', width:200, title: '客户名称'},
|
||||
{field: 'assignedToName', width:80, title: '指派给'},
|
||||
{field: 'stageStr', width:100, title: '阶段'},
|
||||
{field: 'statusStr', width:120, title: '状态'},
|
||||
{field: 'communicationStr', title: '沟通记录', templet: function(d) {
|
||||
return d.communicationStr.replace(/<br \/>/g, '<br>');
|
||||
}},
|
||||
{field: 'contactedDateStr', title:'最后联系', width: 110},
|
||||
{field: 'nextDate', title:'下次联系', width: 110},
|
||||
{field: 'createdDateStr', title:'添加时间', width: 110}
|
||||
]],
|
||||
done: function(){
|
||||
var id = this.id;
|
||||
// 下拉按钮测试
|
||||
},
|
||||
error: function(res, msg){
|
||||
console.log(res, msg)
|
||||
}
|
||||
});
|
||||
|
||||
var customerStatus = xmSelect.render({
|
||||
// 这里绑定css选择器
|
||||
el: '#status',
|
||||
name: 'statusList',
|
||||
// 渲染的数据
|
||||
data: {php}echo $statusListSelected;{/php},
|
||||
})
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,63 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/goods/add">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商品</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" maxlength="60" />
|
||||
<div class="layui-form-mid layui-word-aux">注:建议60个字符长度以内</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">平台价格</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="price" maxlength="60" />
|
||||
<div class="layui-form-mid layui-word-aux">注:一般记录大包的价格</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包库存</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="stock" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小包库存</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="stock_small" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包销量</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="sales" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小包销量</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="sales_small" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包拆小包规格</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="split_to_small" maxlength="60" />
|
||||
<div class="layui-form-mid layui-word-aux">每中包可拆分成多少个小包,如一箱泡面24袋则填写24,方便计算每一小包的进货价,默认1即不可拆分</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="remark" maxlength="200" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,73 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/goods/addReceipt">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商品</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="goods"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">进货日期</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="bought_at" class="layui-input" id="bought_at" placeholder="yyyy-MM-dd">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包数量</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="num" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">进货总价</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="total_price" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="remark" maxlength="200" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
</form>
|
||||
<script src="/js/xm-select.js"></script>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
var laydate = layui.laydate;
|
||||
|
||||
laydate.render({
|
||||
elem: '#bought_at'
|
||||
});
|
||||
|
||||
var book = xmSelect.render({
|
||||
el: '#goods',
|
||||
filterable : true, //开启搜索
|
||||
remoteSearch: true,
|
||||
radio : true, //开启单选模式
|
||||
clickClose : true, //是否点击选项后自动关闭下拉框
|
||||
name: 'goods_id', //表单提交时的name
|
||||
paging: true,
|
||||
data : [],
|
||||
remoteMethod: function(val, cb, show){
|
||||
$.get('/goods/apiGetList', {'name':val, 'size': 50}, function(data){
|
||||
var goodsList = [];
|
||||
data.goodsList.data.forEach(element => {
|
||||
goodsList.push({
|
||||
name: element.name,
|
||||
value: element.id
|
||||
})
|
||||
});
|
||||
cb(goodsList);
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,81 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/goods/addSale">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商品</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="goods"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">销售总价</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="total_price" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">销售时间</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="sold_at" class="layui-input" id="sold_at" placeholder="yyyy-MM-dd HH:mm:ss">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包销量</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="num" maxlength="60" value="0" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小包销量</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="num_small" maxlength="60" value="0" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="remark" maxlength="200" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script src="/js/xm-select.js"></script>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
var laydate = layui.laydate;
|
||||
|
||||
laydate.render({
|
||||
elem: '#sold_at'
|
||||
});
|
||||
|
||||
var book = xmSelect.render({
|
||||
el: '#goods',
|
||||
filterable : true, //开启搜索
|
||||
remoteSearch: true,
|
||||
radio : true, //开启单选模式
|
||||
clickClose : true, //是否点击选项后自动关闭下拉框
|
||||
name: 'goods_id', //表单提交时的name
|
||||
paging: true,
|
||||
data : [],
|
||||
remoteMethod: function(val, cb, show){
|
||||
$.get('/goods/apiGetList', {'name':val, 'size': 50}, function(data){
|
||||
var goodsList = [];
|
||||
data.goodsList.data.forEach(element => {
|
||||
goodsList.push({
|
||||
name: element.name,
|
||||
value: element.id
|
||||
})
|
||||
});
|
||||
cb(goodsList);
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,64 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/goods/edit">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商品</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="name" maxlength="60" value="{$goods.name??''}" />
|
||||
<div class="layui-form-mid layui-word-aux">注:建议60个字符长度以内</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">平台价格</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="price" maxlength="60" value="{$goods.price??0}" />
|
||||
<div class="layui-form-mid layui-word-aux">注:一般记录大包的价格</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包库存</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="stock" maxlength="60" value="{$goods.stock ?? 0}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小包库存</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="stock_small" maxlength="60" value="{$goods.stock_small ?? 0}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包销量</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="sales" maxlength="60" value="{$goods.sales ?? 0}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小包销量</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="sales_small" maxlength="60" value="{$goods.sales_small ?? 0}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包拆小包规格</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="split_to_small" maxlength="60" value="{$goods.split_to_small ?? 1}" />
|
||||
<div class="layui-form-mid layui-word-aux">每大包可拆分成多少个小包,如一箱泡面24袋则填写24,方便计算每一小包的进货价,默认1即不可拆分</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="remark" maxlength="200" vlaue="{$goods.remark ?? ''}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
<input type="hidden" name="id" value="{$goods.id}" />
|
||||
</form>
|
|
@ -0,0 +1,54 @@
|
|||
<form class="layui-form eject-layuiBox" data-action="/goods/editReceipt">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商品</label>
|
||||
<div class="layui-input-block">
|
||||
<select lay-filter="goods" id="goods" name="goods_id">
|
||||
{foreach $goodsList as $goods}
|
||||
<option value="{$goods.id}">{$goods.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">进货日期</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="bought_at" class="layui-input" id="bought_at" placeholder="yyyy-MM-dd">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">大包数量</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="num" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">进货总价</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="number" name="total_price" maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="remark" maxlength="200" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="submitAll">保存</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
var laydate = layui.laydate;
|
||||
|
||||
laydate.render({
|
||||
elem: '#bought_at'
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,357 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-row">
|
||||
<div class="layui-btn-container layui-col-md2">
|
||||
<button class="layui-btn layui-btn-sm" lay-event="add">添加</button>
|
||||
</div>
|
||||
<form class="layui-form layui-col-space16" action="/goods">
|
||||
<div class="layui-col-md2">
|
||||
<div class="layui-input-wrap">
|
||||
<input type="text" name="name" placeholder="商品名" value="{$name??''}" lay-affix="clear" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md2">
|
||||
<div class="layui-input-wrap">
|
||||
<select name="order">
|
||||
<option {if $order == 'id_desc'}selected{/if} value="id_desc">ID降序</option>
|
||||
<option {if $order == 'stock_desc'}selected{/if} value="stock_desc">大包库存降序</option>
|
||||
<option {if $order == 'stock_asc'}selected{/if} value="stock_asc">大包库存升序</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-btn-container layui-col-md2">
|
||||
<button class="layui-btn" lay-submit lay-filter="demo-table-search">搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">Clear</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
<script type="text/html" id="toolDemo">
|
||||
<div class="layui-clear-space">
|
||||
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="more">
|
||||
更多
|
||||
<i class="layui-icon layui-icon-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use(['table', 'dropdown'], function(){
|
||||
var table = layui.table;
|
||||
var dropdown = layui.dropdown;
|
||||
var name = "{$name}";
|
||||
var order = "{$order}";
|
||||
|
||||
// 创建渲染实例
|
||||
table.render({
|
||||
elem: '#test',
|
||||
url: '/goods/apiGetList?name=' + name + '&order=' + order, // 此处为静态模拟数据,实际使用时需换成真实接口
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar: ['filter', 'exports', 'print', { // 右上角工具图标
|
||||
title: '提示',
|
||||
layEvent: 'LAYTABLE_TIPS',
|
||||
icon: 'layui-icon-tips',
|
||||
onClick: function(obj) { // 2.9.12+
|
||||
layer.alert('自定义工具栏图标按钮');
|
||||
}
|
||||
}],
|
||||
height: 'full-135', // 最大高度减去其他容器已占有的高度差
|
||||
css: [ // 重设当前表格样式
|
||||
'.layui-table-tool-temp{padding-right: 145px;}'
|
||||
].join(''),
|
||||
cellMinWidth: 80,
|
||||
//totalRow: true, // 开启合计行
|
||||
//page: true,
|
||||
page: { // 支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档
|
||||
layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
|
||||
//curr: 5, //设定初始在第 5 页
|
||||
limit: 20,
|
||||
//groups: 1, //只显示 1 个连续页码
|
||||
//first: false, //不显示首页
|
||||
//last: false //不显示尾页
|
||||
},
|
||||
// 将原始数据解析成 table 组件所规定的数据格式
|
||||
parseData: function(res){
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.goodsList.total, //解析数据长度
|
||||
"data": res.goodsList.data //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{type: 'checkbox', fixed: 'left'},
|
||||
{field: 'id', fixed: 'left', width:80, title: 'ID'},
|
||||
{field: 'name', width:300, title: '商品'},
|
||||
{field: 'price', width:90, title: '价格'},
|
||||
{field: 'stock', width:90, title: '大包库存'},
|
||||
{field: 'stock_small', width:90, title: '小包库存'},
|
||||
{field: 'sales', width:90, title: '大包销量'},
|
||||
{field: 'sales_small', width:90, title: '小包销量'},
|
||||
{fixed: 'right', title:'操作', minWidth: 125, templet: '#toolDemo'}
|
||||
]],
|
||||
done: function(){
|
||||
var id = this.id;
|
||||
// 下拉按钮测试
|
||||
dropdown.render({
|
||||
elem: '#dropdownButton', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'add',
|
||||
title: '添加'
|
||||
},{
|
||||
id: 'update',
|
||||
title: '编辑'
|
||||
},{
|
||||
id: 'delete',
|
||||
title: '删除'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/goods/add');
|
||||
break;
|
||||
case 'update':
|
||||
console.log(data);
|
||||
console.log(obj);
|
||||
|
||||
if(data.length !== 1) return layer.msg('请选择一行');
|
||||
layer.open({
|
||||
title: '编辑',
|
||||
type: 1,
|
||||
area: ['80%','80%'],
|
||||
content: '<div style="padding: 16px;">自定义表单元素</div>'
|
||||
});
|
||||
break;
|
||||
case 'delete':
|
||||
if(data.length === 0){
|
||||
return layer.msg('请选择一行');
|
||||
}
|
||||
layer.msg('delete event');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 重载测试
|
||||
dropdown.render({
|
||||
elem: '#reloadTest', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'reload',
|
||||
title: '重载'
|
||||
},{
|
||||
id: 'reload-deep',
|
||||
title: '重载 - 参数叠加'
|
||||
},{
|
||||
id: 'reloadData',
|
||||
title: '仅重载数据'
|
||||
},{
|
||||
id: 'reloadData-deep',
|
||||
title: '仅重载数据 - 参数叠加'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
switch(obj.id){
|
||||
case 'reload':
|
||||
// 重载 - 默认(参数重置)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'reload-deep':
|
||||
// 重载 - 深度(参数叠加)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
},
|
||||
//defaultToolbar: ['print'], // 重载头部工具栏右侧图标
|
||||
//cols: ins1.config.cols
|
||||
}, true);
|
||||
break;
|
||||
case 'reloadData':
|
||||
// 数据重载 - 参数重置
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
scrollPos: 'fixed', // 保持滚动条位置不变 - v2.7.3 新增
|
||||
height: 2000, // 测试无效参数(即与数据无关的参数设置无效,此处以 height 设置无效为例)
|
||||
//url: '404',
|
||||
//page: {curr: 1, limit: 30} // 重新指向分页
|
||||
});
|
||||
break;
|
||||
case 'reloadData-deep':
|
||||
// 数据重载 - 参数叠加
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
}
|
||||
}, true);
|
||||
break;
|
||||
}
|
||||
layer.msg('可观察 Network 请求参数的变化');
|
||||
}
|
||||
});
|
||||
|
||||
// 行模式
|
||||
dropdown.render({
|
||||
elem: '#rowMode',
|
||||
data: [{
|
||||
id: 'default-row',
|
||||
title: '单行模式(默认)'
|
||||
},{
|
||||
id: 'multi-row',
|
||||
title: '多行模式'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'default-row':
|
||||
table.reload('test', {
|
||||
lineStyle: null // 恢复单行
|
||||
});
|
||||
layer.msg('已设为单行');
|
||||
break;
|
||||
case 'multi-row':
|
||||
table.reload('test', {
|
||||
// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注:v2.7.0 新增
|
||||
lineStyle: 'height: 95px;'
|
||||
});
|
||||
layer.msg('即通过设置 lineStyle 参数可开启多行');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(res, msg){
|
||||
console.log(res, msg)
|
||||
}
|
||||
});
|
||||
|
||||
// 工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
var id = obj.config.id;
|
||||
var checkStatus = table.checkStatus(id);
|
||||
var othis = lay(this);
|
||||
switch(obj.event){
|
||||
case 'getCheckData':
|
||||
var data = checkStatus.data;
|
||||
layer.alert(layui.util.escape(JSON.stringify(data)));
|
||||
break;
|
||||
case 'getData':
|
||||
var getData = table.getData(id);
|
||||
console.log(getData);
|
||||
layer.alert(layui.util.escape(JSON.stringify(getData)));
|
||||
break;
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/goods/add');
|
||||
break;
|
||||
};
|
||||
});
|
||||
// 表头自定义元素工具事件 --- 2.8.8+
|
||||
table.on('colTool(test)', function(obj){
|
||||
var event = obj.event;
|
||||
console.log(obj);
|
||||
if(event === 'email-tips'){
|
||||
layer.alert(layui.util.escape(JSON.stringify(obj.col)), {
|
||||
title: '当前列属性配置项'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 触发单元格工具事件
|
||||
table.on('tool(test)', function(obj){ // 双击 toolDouble
|
||||
var data = obj.data; // 获得当前行数据
|
||||
// console.log(obj)
|
||||
if(obj.event === 'edit'){
|
||||
layerAlert('get', '编辑', '/goods/edit?id=' + data.id);
|
||||
} else if(obj.event === 'more'){
|
||||
// 更多 - 下拉菜单
|
||||
dropdown.render({
|
||||
elem: this, // 触发事件的 DOM 对象
|
||||
show: true, // 外部事件触发即显示
|
||||
data: [{
|
||||
title: '查看',
|
||||
id: 'detail'
|
||||
},{
|
||||
title: '删除',
|
||||
id: 'del'
|
||||
}],
|
||||
click: function(menudata){
|
||||
if(menudata.id === 'detail'){
|
||||
layer.msg('查看操作,当前行 ID:'+ data.id);
|
||||
} else if(menudata.id === 'del'){
|
||||
layer.confirm('真的删除行 [id: '+ data.id +'] 么', function(index){
|
||||
obj.del(); // 删除对应行(tr)的DOM结构
|
||||
layer.close(index);
|
||||
// 向服务端发送删除指令
|
||||
});
|
||||
}
|
||||
},
|
||||
align: 'right', // 右对齐弹出
|
||||
style: 'box-shadow: 1px 1px 10px rgb(0 0 0 / 12%);' // 设置额外样式
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// 触发表格复选框选择
|
||||
table.on('checkbox(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 触发表格单选框选择
|
||||
table.on('radio(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 行单击事件
|
||||
table.on('row(test)', function(obj){
|
||||
//console.log(obj);
|
||||
//layer.closeAll('tips');
|
||||
});
|
||||
// 行双击事件
|
||||
table.on('rowDouble(test)', function(obj){
|
||||
console.log(obj);
|
||||
});
|
||||
|
||||
// 单元格编辑事件
|
||||
table.on('edit(test)', function(obj){
|
||||
var field = obj.field; // 得到字段
|
||||
var value = obj.value; // 得到修改后的值
|
||||
var data = obj.data; // 得到所在行所有键值
|
||||
// 值的校验
|
||||
if(field === 'email'){
|
||||
if(!/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(obj.value)){
|
||||
layer.tips('输入的邮箱格式不正确,请重新编辑', this, {tips: 1});
|
||||
return obj.reedit(); // 重新编辑 -- v2.8.0 新增
|
||||
}
|
||||
}
|
||||
// 编辑后续操作,如提交更新请求,以完成真实的数据更新
|
||||
// …
|
||||
layer.msg('编辑成功', {icon: 1});
|
||||
|
||||
// 其他更新操作
|
||||
var update = {};
|
||||
update[field] = value;
|
||||
obj.update(update);
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,258 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div class="layui-row layui-col-space12">
|
||||
<div class="layui-col-xs12 layui-col-md12">
|
||||
<div class="layuimini-container location-index-page">
|
||||
<div class="layuimini-main">
|
||||
<fieldset class="table-search-fieldset">
|
||||
<legend>搜索信息</legend>
|
||||
<div style="margin: 10px 10px 10px 10px">
|
||||
<form class="layui-form layui-form-pane" action="">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">关键词</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" name="keyword" placeholder="支持模糊查询">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-inline">
|
||||
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary" ><i class="layui-icon"></i> 重 置</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-word-aux">
|
||||
1. 添加日志,直接新增对应商品库存<br>
|
||||
2. 删除日志,不会扣除已添加库存<br>
|
||||
3. 修改日志,只能修改总价和进货日期<br>
|
||||
4. 大包可拆分小包数量=当时商品的可拆分数量,如仅记录当时1大包可以拆分成10小包,后期改包装后1大包可以拆分20包不影响<br>
|
||||
5. 小包进货单价=大包单价➗大包可拆分小包数量<br>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="image-table">
|
||||
<table id="table-container" class="layui-table" data-url="/goods/apiGetReceiptList" lay-filter="table-container-filter"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 隐藏列 -->
|
||||
<!-- 编辑单元格提交url -->
|
||||
<input type="hidden" id="row-modify" data-url="/manager.goodsReceiptLog/modify">
|
||||
|
||||
<!-- 操作列 -->
|
||||
<script type="text/html" id="row-operate">
|
||||
<a class="layui-btn layui-btn-primary layui-btn-xs" data-href="/goods/editReceipt?id={{d.id}}" data-title="编辑" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-danger layui-btn-xs" data-href="/goods/delReceipt.html" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
<!-- toolbar -->
|
||||
<script type="text/html" id="toolbar-tpl">
|
||||
<a class="layui-btn layui-btn-primary layui-btn-sm" data-table-refresh lay-event="refresh"><i class="fa fa-refresh"></i></a>
|
||||
<a class="layui-btn layui-btn-normal layui-btn-sm" data-href="/manager.goodsReceiptLog/add.html" data-title="添加" lay-event="add">添加</a>
|
||||
<a class="layui-btn layui-btn-danger layui-btn-sm" data-href="/manager.goodsReceiptLog/del.html" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use(['laytpl', 'table', 'jquery', 'form', 'laydate'], function () {
|
||||
let $ = layui.jquery,
|
||||
table = layui.table,
|
||||
laydate = layui.laydate,
|
||||
form = layui.form;
|
||||
|
||||
/**** index begin ***/
|
||||
if ($('.location-index-page').length > 0) {
|
||||
|
||||
// 渲染表格
|
||||
let listUrl = $('#table-container').data('url');
|
||||
let insTb = table.render({
|
||||
elem: '#table-container',
|
||||
title: '列表',
|
||||
defaultToolbar: ['filter', 'exports', {
|
||||
title: '搜索' //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可
|
||||
, layEvent: 'search'
|
||||
, icon: 'layui-icon-search'
|
||||
}],
|
||||
toolbar: '#toolbar-tpl',
|
||||
//method: 'POST',
|
||||
url: listUrl,
|
||||
page: true,
|
||||
limit: 20,
|
||||
limits: [20,50,100,200,500,1000],
|
||||
request: {
|
||||
pageName: 'page',
|
||||
limitName: 'size',
|
||||
},
|
||||
parseData: function (res) {
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.receiptList.total, //解析数据长度
|
||||
"data": res.receiptList.data //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{type: 'checkbox'},
|
||||
{field: 'id', title: '#'},
|
||||
{field: 'goods_name', title: '商品名称'},
|
||||
{field: 'total_price', title: '总价'},
|
||||
{field: 'num', title: '大包数量'},
|
||||
{field: 'cost_price', title: '大包进货单价'},
|
||||
{field: 'small_cost_price', title: '小包进货单价'},
|
||||
{field: 'split_to_small', title: '大包可拆分小包数量'},
|
||||
{field: 'bought_at', title: '进货日期'}
|
||||
,{templet: '#row-operate', minWidth: 180, align: 'center', title: '操作'}
|
||||
]],
|
||||
done: function () {
|
||||
//Tools.setInsTb(insTb);
|
||||
}
|
||||
});
|
||||
|
||||
//监听工具条 注意区别toolbar和tool toolbar是表头上的工具条 tool是行中的工具条
|
||||
table.on('toolbar(table-container-filter)', function (obj) {
|
||||
let layEvent = obj.event;
|
||||
//let insTb = Tools.getInsTb();
|
||||
let url = $($(this).context).data('href')
|
||||
let title = $($(this).context).data('title')
|
||||
let width = $($(this).context).data('width') ? $($(this).context).data('width') : '100%';
|
||||
let height = $($(this).context).data('height') ? $($(this).context).data('height') : '100%';
|
||||
|
||||
let checkStatus = table.checkStatus('table-container');
|
||||
let selected = checkStatus.data;
|
||||
let ids = [];
|
||||
|
||||
switch (layEvent) {
|
||||
// toolbar 删除
|
||||
case 'del':
|
||||
if (checkStatus.data.length <= 0) {
|
||||
layer.msg('请先选择数据');
|
||||
return false;
|
||||
}
|
||||
// let selected = checkStatus.data;
|
||||
// let ids = [];
|
||||
|
||||
$.each(selected, function (index, val) {
|
||||
ids.push(val.id);
|
||||
})
|
||||
//delRow(url, ids, insTb);
|
||||
return false;
|
||||
// toolbar 刷新
|
||||
case 'refresh':
|
||||
//refreshTab(insTb);
|
||||
return false;
|
||||
// toolbar 搜索
|
||||
case 'search':
|
||||
let search = $('.table-search-fieldset');
|
||||
if (search.hasClass('div-show')) {
|
||||
search.css('display', 'none').removeClass('div-show');
|
||||
} else {
|
||||
search.css('display', 'block').addClass('div-show');
|
||||
}
|
||||
return false;
|
||||
// 其他 默认为打开弹出层
|
||||
default:
|
||||
if (layEvent !== 'LAYTABLE_COLS' && layEvent !== 'LAYTABLE_EXPORT') {
|
||||
layerAlert('get', '添加', '/goods/addReceipt');
|
||||
//openLayer(url, title, width, height);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//监听行工具条
|
||||
table.on('tool(table-container-filter)', function (obj) {
|
||||
let data = obj.data;
|
||||
let layEvent = obj.event;
|
||||
let url = $($(this).context).data('href');
|
||||
console.log($(this).data('href'));
|
||||
console.log(data.id);
|
||||
let title = $($(this).context).data('title');
|
||||
let width = $($(this).context).data('width') ? $($(this).context).data('width') : '100%';
|
||||
let height = $($(this).context).data('height') ? $($(this).context).data('height') : '100%';
|
||||
//let insTb = Tools.getInsTb();
|
||||
|
||||
switch (layEvent) {
|
||||
// 行 删除
|
||||
case 'del':
|
||||
let url = '/goods/apiDelReceipt';
|
||||
$.post(url, {id: data.id}, function (res) {
|
||||
if (res.code === 0) {
|
||||
insTb.reload();
|
||||
}
|
||||
layer.msg(res.msg);
|
||||
});
|
||||
return false;
|
||||
//其他 默认为打开弹出层
|
||||
default:
|
||||
layerAlert('get', title, url);
|
||||
//openLayer(url, title, width, height);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// 监听
|
||||
|
||||
|
||||
let modifyUrl = $('#row-modify').data('url');
|
||||
|
||||
table.on('edit(table-container)', function (obj) {
|
||||
let id = obj.data.id;
|
||||
$.ajax(modifyUrl, {
|
||||
data: {"id": id, "field": obj.field, "value": obj.value}
|
||||
,dataType : 'json'
|
||||
,type: 'POST'
|
||||
})
|
||||
.done(function (res) {
|
||||
if (res.code === 0) {
|
||||
insTb.reload();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// switch变更
|
||||
function changeSwitch(filter) {
|
||||
form.on('switch(' + filter + ')', function (obj) {
|
||||
let val = obj.elem.checked ? 1 : 0;
|
||||
$.post(modifyUrl, {id: this.value, field: this.name, value: val}, function (res) {
|
||||
layer.msg(res.msg)
|
||||
if (res.code !== 0) {
|
||||
//操作不成功则刷新页面
|
||||
insTb.reload();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// 监听搜索操作
|
||||
form.on('submit(data-search-btn)', function (data) {
|
||||
//执行搜索重载
|
||||
table.reload('table-container', {
|
||||
page: {curr: 1}
|
||||
, where: data.field
|
||||
}, 'data');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
/*** index end ***/
|
||||
|
||||
if ($('.location-operate-page').length > 0) {
|
||||
let parentCategory = $('#parent-category');
|
||||
let categoryList = parentCategory.data('list') ? parentCategory.data('list') : [];
|
||||
|
||||
laydate.render({
|
||||
elem: '#published-at',
|
||||
type: 'datetime',
|
||||
});
|
||||
|
||||
laydate.render({
|
||||
elem: '#bought_at'
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,357 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-row">
|
||||
<div class="layui-btn-container layui-col-md2">
|
||||
<button class="layui-btn layui-btn-sm" lay-event="add">添加</button>
|
||||
</div>
|
||||
<form class="layui-form layui-col-space16" action="/goods/sale">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<select name="goods_id">
|
||||
<option {if $goodsID == 0}selected{/if} value="0">全部</option>
|
||||
{foreach $goodsList as $goods}
|
||||
<option {if $goods['id'] == $goodsID}selected{/if} value="{$goods.id}">{$goods.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-btn-container layui-col-md3 layui-col-xs12">
|
||||
<button class="layui-btn" lay-submit lay-filter="demo-table-search">搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">Clear</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
<script type="text/html" id="toolDemo">
|
||||
<div class="layui-clear-space">
|
||||
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-xs" lay-event="more">
|
||||
更多
|
||||
<i class="layui-icon layui-icon-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use(['table', 'dropdown'], function(){
|
||||
var table = layui.table;
|
||||
var dropdown = layui.dropdown;
|
||||
|
||||
// 创建渲染实例
|
||||
table.render({
|
||||
elem: '#test',
|
||||
url: '/goods/apiGetSaleList', // 此处为静态模拟数据,实际使用时需换成真实接口
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar: ['filter', 'exports', 'print', { // 右上角工具图标
|
||||
title: '提示',
|
||||
layEvent: 'LAYTABLE_TIPS',
|
||||
icon: 'layui-icon-tips',
|
||||
onClick: function(obj) { // 2.9.12+
|
||||
layer.alert('自定义工具栏图标按钮');
|
||||
}
|
||||
}],
|
||||
height: 'full-135', // 最大高度减去其他容器已占有的高度差
|
||||
css: [ // 重设当前表格样式
|
||||
'.layui-table-tool-temp{padding-right: 145px;}'
|
||||
].join(''),
|
||||
cellMinWidth: 80,
|
||||
//totalRow: true, // 开启合计行
|
||||
//page: true,
|
||||
page: { // 支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档
|
||||
layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
|
||||
//curr: 5, //设定初始在第 5 页
|
||||
limit: 20,
|
||||
//groups: 1, //只显示 1 个连续页码
|
||||
//first: false, //不显示首页
|
||||
//last: false //不显示尾页
|
||||
},
|
||||
// 将原始数据解析成 table 组件所规定的数据格式
|
||||
parseData: function(res){
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.saleList.total, //解析数据长度
|
||||
"data": res.saleList.data //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{type: 'checkbox', fixed: 'left'},
|
||||
{field: 'id', fixed: 'left', width:80, title: 'ID'},
|
||||
{field: 'goods_name', width:300, title: '商品'},
|
||||
{field: 'total_price', width:100, title: '销售总价'},
|
||||
{field: 'num', width:100, title: '大包销量'},
|
||||
{field: 'num_small', width:100, title: '小包销量'},
|
||||
{field: 'sold_at', title:'销售时间', width: 150},
|
||||
{field: 'remark', title:'备注', width: 200},
|
||||
{fixed: 'right', title:'操作', minWidth: 125, templet: '#toolDemo'}
|
||||
]],
|
||||
done: function(){
|
||||
var id = this.id;
|
||||
// 下拉按钮测试
|
||||
dropdown.render({
|
||||
elem: '#dropdownButton', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'add',
|
||||
title: '添加'
|
||||
},{
|
||||
id: 'update',
|
||||
title: '编辑'
|
||||
},{
|
||||
id: 'delete',
|
||||
title: '删除'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/goods/addSale');
|
||||
// layer.open({
|
||||
// title: '添加',
|
||||
// type: 2,
|
||||
// area: ['80%','80%'],
|
||||
// content: '/book/add'
|
||||
// });
|
||||
break;
|
||||
case 'update':
|
||||
console.log(data);
|
||||
console.log(obj);
|
||||
|
||||
if(data.length !== 1) return layer.msg('请选择一行');
|
||||
layer.open({
|
||||
title: '编辑',
|
||||
type: 1,
|
||||
area: ['80%','80%'],
|
||||
content: '<div style="padding: 16px;">自定义表单元素</div>'
|
||||
});
|
||||
break;
|
||||
case 'delete':
|
||||
if(data.length === 0){
|
||||
return layer.msg('请选择一行');
|
||||
}
|
||||
layer.msg('delete event');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 重载测试
|
||||
dropdown.render({
|
||||
elem: '#reloadTest', // 可绑定在任意元素中,此处以上述按钮为例
|
||||
data: [{
|
||||
id: 'reload',
|
||||
title: '重载'
|
||||
},{
|
||||
id: 'reload-deep',
|
||||
title: '重载 - 参数叠加'
|
||||
},{
|
||||
id: 'reloadData',
|
||||
title: '仅重载数据'
|
||||
},{
|
||||
id: 'reloadData-deep',
|
||||
title: '仅重载数据 - 参数叠加'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
switch(obj.id){
|
||||
case 'reload':
|
||||
// 重载 - 默认(参数重置)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'reload-deep':
|
||||
// 重载 - 深度(参数叠加)
|
||||
table.reload('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
},
|
||||
//defaultToolbar: ['print'], // 重载头部工具栏右侧图标
|
||||
//cols: ins1.config.cols
|
||||
}, true);
|
||||
break;
|
||||
case 'reloadData':
|
||||
// 数据重载 - 参数重置
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: '123456',
|
||||
//test: '新的 test2',
|
||||
//token: '新的 token2'
|
||||
},
|
||||
scrollPos: 'fixed', // 保持滚动条位置不变 - v2.7.3 新增
|
||||
height: 2000, // 测试无效参数(即与数据无关的参数设置无效,此处以 height 设置无效为例)
|
||||
//url: '404',
|
||||
//page: {curr: 1, limit: 30} // 重新指向分页
|
||||
});
|
||||
break;
|
||||
case 'reloadData-deep':
|
||||
// 数据重载 - 参数叠加
|
||||
table.reloadData('test', {
|
||||
where: {
|
||||
abc: 123,
|
||||
test: '新的 test1'
|
||||
}
|
||||
}, true);
|
||||
break;
|
||||
}
|
||||
layer.msg('可观察 Network 请求参数的变化');
|
||||
}
|
||||
});
|
||||
|
||||
// 行模式
|
||||
dropdown.render({
|
||||
elem: '#rowMode',
|
||||
data: [{
|
||||
id: 'default-row',
|
||||
title: '单行模式(默认)'
|
||||
},{
|
||||
id: 'multi-row',
|
||||
title: '多行模式'
|
||||
}],
|
||||
// 菜单被点击的事件
|
||||
click: function(obj){
|
||||
var checkStatus = table.checkStatus(id)
|
||||
var data = checkStatus.data; // 获取选中的数据
|
||||
switch(obj.id){
|
||||
case 'default-row':
|
||||
table.reload('test', {
|
||||
lineStyle: null // 恢复单行
|
||||
});
|
||||
layer.msg('已设为单行');
|
||||
break;
|
||||
case 'multi-row':
|
||||
table.reload('test', {
|
||||
// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注:v2.7.0 新增
|
||||
lineStyle: 'height: 95px;'
|
||||
});
|
||||
layer.msg('即通过设置 lineStyle 参数可开启多行');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(res, msg){
|
||||
console.log(res, msg)
|
||||
}
|
||||
});
|
||||
|
||||
// 工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
var id = obj.config.id;
|
||||
var checkStatus = table.checkStatus(id);
|
||||
var othis = lay(this);
|
||||
switch(obj.event){
|
||||
case 'getCheckData':
|
||||
var data = checkStatus.data;
|
||||
layer.alert(layui.util.escape(JSON.stringify(data)));
|
||||
break;
|
||||
case 'getData':
|
||||
var getData = table.getData(id);
|
||||
console.log(getData);
|
||||
layer.alert(layui.util.escape(JSON.stringify(getData)));
|
||||
break;
|
||||
case 'add':
|
||||
layerAlert('get', '添加', '/goods/addSale');
|
||||
break;
|
||||
};
|
||||
});
|
||||
// 表头自定义元素工具事件 --- 2.8.8+
|
||||
table.on('colTool(test)', function(obj){
|
||||
var event = obj.event;
|
||||
console.log(obj);
|
||||
if(event === 'email-tips'){
|
||||
layer.alert(layui.util.escape(JSON.stringify(obj.col)), {
|
||||
title: '当前列属性配置项'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 触发单元格工具事件
|
||||
table.on('tool(test)', function(obj){ // 双击 toolDouble
|
||||
var data = obj.data; // 获得当前行数据
|
||||
// console.log(obj)
|
||||
if(obj.event === 'edit'){
|
||||
layerAlert('get', '添加', '/book/edit?id=' + data.id);
|
||||
} else if(obj.event === 'more'){
|
||||
// 更多 - 下拉菜单
|
||||
dropdown.render({
|
||||
elem: this, // 触发事件的 DOM 对象
|
||||
show: true, // 外部事件触发即显示
|
||||
data: [{
|
||||
title: '查看',
|
||||
id: 'detail'
|
||||
},{
|
||||
title: '删除',
|
||||
id: 'del'
|
||||
}],
|
||||
click: function(menudata){
|
||||
if(menudata.id === 'detail'){
|
||||
layer.msg('查看操作,当前行 ID:'+ data.id);
|
||||
} else if(menudata.id === 'del'){
|
||||
layer.confirm('真的删除行 [id: '+ data.id +'] 么', function(index){
|
||||
obj.del(); // 删除对应行(tr)的DOM结构
|
||||
layer.close(index);
|
||||
// 向服务端发送删除指令
|
||||
});
|
||||
}
|
||||
},
|
||||
align: 'right', // 右对齐弹出
|
||||
style: 'box-shadow: 1px 1px 10px rgb(0 0 0 / 12%);' // 设置额外样式
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// 触发表格复选框选择
|
||||
table.on('checkbox(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 触发表格单选框选择
|
||||
table.on('radio(test)', function(obj){
|
||||
console.log(obj)
|
||||
});
|
||||
|
||||
// 行单击事件
|
||||
table.on('row(test)', function(obj){
|
||||
//console.log(obj);
|
||||
//layer.closeAll('tips');
|
||||
});
|
||||
// 行双击事件
|
||||
table.on('rowDouble(test)', function(obj){
|
||||
console.log(obj);
|
||||
});
|
||||
|
||||
// 单元格编辑事件
|
||||
table.on('edit(test)', function(obj){
|
||||
var field = obj.field; // 得到字段
|
||||
var value = obj.value; // 得到修改后的值
|
||||
var data = obj.data; // 得到所在行所有键值
|
||||
// 值的校验
|
||||
if(field === 'email'){
|
||||
if(!/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(obj.value)){
|
||||
layer.tips('输入的邮箱格式不正确,请重新编辑', this, {tips: 1});
|
||||
return obj.reedit(); // 重新编辑 -- v2.8.0 新增
|
||||
}
|
||||
}
|
||||
// 编辑后续操作,如提交更新请求,以完成真实的数据更新
|
||||
// …
|
||||
layer.msg('编辑成功', {icon: 1});
|
||||
|
||||
// 其他更新操作
|
||||
var update = {};
|
||||
update[field] = value;
|
||||
obj.update(update);
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="/favicon.ico"/>
|
||||
<title>webman</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
hello <?=htmlspecialchars($name)?>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,95 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>layout 管理界面大布局示例 - Layui</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/layui/css/layui.css" rel="stylesheet">
|
||||
|
||||
<script src="/js/jquery-3.7.1.min.js"></script>
|
||||
<script src="/layui/layui.js"></script>
|
||||
<script src="/js/work.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
<div class="layui-header">
|
||||
<div class="layui-logo layui-hide-xs layui-bg-black">layout demo</div>
|
||||
<!-- 头部区域(可配合layui 已有的水平导航) -->
|
||||
</div>
|
||||
<div class="layui-side layui-bg-black">
|
||||
<div class="layui-side-scroll">
|
||||
<!-- 左侧导航区域(可配合layui已有的垂直导航) -->
|
||||
<ul class="layui-nav layui-nav-tree" lay-filter="test">
|
||||
<li class="layui-nav-item layui-nav-itemed">
|
||||
<a class="" href="javascript:;">个人生活</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/book/">书籍</a></dd>
|
||||
<dd><a href="/category/">分类</a></dd>
|
||||
<dd><a href="/book/reading">书单</a></dd>
|
||||
<dd><a href="javascript:;">the links</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item">
|
||||
<a href="javascript:;">工作相关</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/customer/">客户跟进</a></dd>
|
||||
<dd><a href="/salary/">工资计算</a></dd>
|
||||
<dd><a href="/task/">项目任务</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item">
|
||||
<a href="javascript:;">有机壹家</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/goods/">商品</a></dd>
|
||||
<dd><a href="/goods/receipt/">进货日志</a></dd>
|
||||
<dd><a href="/goods/sale/">销售日志</a></dd>
|
||||
<dd><a href="/sales/index/">销量统计</a></dd>
|
||||
<dd><a href="/sales/goods/">商品销售统计</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-body">
|
||||
<!-- 内容主体区域 -->
|
||||
{__CONTENT__}
|
||||
</div>
|
||||
<div class="layui-footer">
|
||||
<!-- 底部固定区域 -->
|
||||
底部固定区域
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
//JS
|
||||
layui.use(['element', 'layer', 'util'], function(){
|
||||
var element = layui.element;
|
||||
var layer = layui.layer;
|
||||
var util = layui.util;
|
||||
var $ = layui.$;
|
||||
|
||||
//头部事件
|
||||
util.event('lay-header-event', {
|
||||
menuLeft: function(othis){ // 左侧菜单事件
|
||||
layer.msg('展开左侧菜单的操作', {icon: 0});
|
||||
},
|
||||
menuRight: function(){ // 右侧菜单事件
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '更多',
|
||||
content: '<div style="padding: 15px;">处理右侧面板的操作</div>',
|
||||
area: ['260px', '100%'],
|
||||
offset: 'rt', // 右上角
|
||||
anim: 'slideLeft', // 从右侧抽屉滑出
|
||||
shadeClose: true,
|
||||
scrollbar: false
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,124 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md3" >
|
||||
<label class="layui-form-label">开始时间</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="start" class="layui-input" id="start" placeholder="yyyy-MM-dd HH:mm:ss">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<label class="layui-form-label">结束时间</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="end" class="layui-input" id="end" placeholder="yyyy-MM-dd HH:mm:ss">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-block">
|
||||
<select lay-filter="order" id="order" name="order">
|
||||
<option value="total_sales">total_sales</option>
|
||||
<option value="total_num">total_num</option>
|
||||
<option value="total_num_small">total_num_small</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" id="search">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="sales" style="width: 100%;height:1500px;"></div>
|
||||
</div>
|
||||
<script src="/js/echarts.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var laydate = layui.laydate;
|
||||
|
||||
laydate.render({
|
||||
elem: '#start'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#end'
|
||||
});
|
||||
|
||||
$('#search').click(function() {
|
||||
var start = $('#start').val();
|
||||
var end = $('#end').val();
|
||||
var order = $('#order').val();
|
||||
getData(start, end, order);
|
||||
});
|
||||
|
||||
getData();
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
var myChart = echarts.init(document.getElementById('sales'));
|
||||
|
||||
function getData(start = '', end = '', order = 'total_sales'){
|
||||
$.get('/sales/apiGetSalesGoods', {start: start, end: end, order: order}).done(function(data) {
|
||||
// 指定图表的配置项和数据
|
||||
var option = {
|
||||
title: {
|
||||
text: '产品销售统计'
|
||||
},
|
||||
tooltip: {},
|
||||
legend: {
|
||||
data: ['产品销售额', '大包销量', '小包销量']
|
||||
},
|
||||
xAxis: {
|
||||
// data: data.data.goods_name.map(function(item) {
|
||||
// return item;
|
||||
// })
|
||||
},
|
||||
yAxis: {
|
||||
//type: 'value'
|
||||
data: data.data.goods_name.map(function(item) {
|
||||
return item;
|
||||
})
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '产品销售额',
|
||||
type: 'bar',
|
||||
data: data.data.total_sales.map(function(item) {
|
||||
return item;
|
||||
}),
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'top'
|
||||
}
|
||||
}
|
||||
},{
|
||||
name: '大包销量',
|
||||
type: 'bar',
|
||||
data: data.data.total_num.map(function(item) {
|
||||
return item;
|
||||
}),
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'top'
|
||||
}
|
||||
}
|
||||
},{
|
||||
name: '小包销量',
|
||||
type: 'bar',
|
||||
data: data.data.total_num_small.map(function(item) {
|
||||
return item;
|
||||
}),
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'top'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,128 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md3" >
|
||||
<label class="layui-form-label">开始时间</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="start" class="layui-input" id="start" placeholder="yyyy-MM-dd HH:mm:ss">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<label class="layui-form-label">结束时间</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="end" class="layui-input" id="end" placeholder="yyyy-MM-dd HH:mm:ss">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn layui-btn-sm" id="search">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="sales" style="width: 100%;height:400px;"></div>
|
||||
</div>
|
||||
<script src="/js/echarts.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var laydate = layui.laydate;
|
||||
|
||||
laydate.render({
|
||||
elem: '#start'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#end'
|
||||
});
|
||||
|
||||
$('#search').click(function() {
|
||||
var start = $('#start').val();
|
||||
var end = $('#end').val();
|
||||
getData(start, end);
|
||||
});
|
||||
|
||||
getData();
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
var myChart = echarts.init(document.getElementById('sales'));
|
||||
|
||||
function getData(start = '', end = ''){
|
||||
$.get('/sales/apiGetSales', {start: start, end: end}).done(function(data) {
|
||||
// 指定图表的配置项和数据
|
||||
var option = {
|
||||
title: {
|
||||
text: '销售统计'
|
||||
},
|
||||
tooltip: {},
|
||||
legend: {
|
||||
data: ['日销额']
|
||||
},
|
||||
xAxis: {
|
||||
data: data.data.sold_at.map(function(item) {
|
||||
return item;
|
||||
})
|
||||
},
|
||||
yAxis: {
|
||||
//type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '日销额',
|
||||
type: 'line',
|
||||
data: data.data.total_sales.map(function(item) {
|
||||
return item;
|
||||
}),
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'top'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
$.get('/statistics/apiGetSales').done(function(data) {
|
||||
// 指定图表的配置项和数据
|
||||
var option = {
|
||||
title: {
|
||||
text: '销售统计'
|
||||
},
|
||||
tooltip: {},
|
||||
legend: {
|
||||
data: ['日销额']
|
||||
},
|
||||
xAxis: {
|
||||
data: data.data.sold_at.map(function(item) {
|
||||
return item;
|
||||
})
|
||||
},
|
||||
yAxis: {
|
||||
//type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '日销额',
|
||||
type: 'line',
|
||||
data: data.data.total_sales.map(function(item) {
|
||||
return item;
|
||||
}),
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'top'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
});
|
||||
*/
|
||||
</script>
|
|
@ -0,0 +1,100 @@
|
|||
{layout name="layout" /}
|
||||
|
||||
<div style="padding: 16px;">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-row">
|
||||
<form class="layui-form layui-col-space16" action="/task">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<input type="text" name="name" placeholder="任务名" value="{$name??''}" lay-affix="clear" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-btn-container layui-col-md3 layui-col-xs12">
|
||||
<button class="layui-btn" lay-submit lay-filter="demo-table-search">搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">Clear</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
<script type="text/html" id="toolDemo">
|
||||
<div class="layui-clear-space">
|
||||
<a class="layui-btn layui-btn-xs" lay-event="detail">详情</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use(['table', 'dropdown'], function(){
|
||||
var table = layui.table;
|
||||
var dropdown = layui.dropdown;
|
||||
var name = "{$name ?? ''}";
|
||||
// 创建渲染实例
|
||||
table.render({
|
||||
elem: '#test',
|
||||
url: '/task/apiGetList?name=' + name, // 此处为静态模拟数据,实际使用时需换成真实接口
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar: ['filter', 'exports', 'print', { // 右上角工具图标
|
||||
title: '提示',
|
||||
layEvent: 'LAYTABLE_TIPS',
|
||||
icon: 'layui-icon-tips',
|
||||
onClick: function(obj) { // 2.9.12+
|
||||
layer.alert('自定义工具栏图标按钮');
|
||||
}
|
||||
}],
|
||||
height: 'full-135', // 最大高度减去其他容器已占有的高度差
|
||||
css: [ // 重设当前表格样式
|
||||
'.layui-table-tool-temp{padding-right: 145px;}'
|
||||
].join(''),
|
||||
cellMinWidth: 80,
|
||||
//totalRow: true, // 开启合计行
|
||||
//page: true,
|
||||
page: { // 支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档
|
||||
layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
|
||||
//curr: 5, //设定初始在第 5 页
|
||||
limit: 20,
|
||||
//groups: 1, //只显示 1 个连续页码
|
||||
//first: false, //不显示首页
|
||||
//last: false //不显示尾页
|
||||
},
|
||||
// 将原始数据解析成 table 组件所规定的数据格式
|
||||
parseData: function(res){
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.msg, //解析提示文本
|
||||
"count": res.taskList.total, //解析数据长度
|
||||
"data": res.taskList.data //解析数据列表
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{type: 'checkbox', fixed: 'left'},
|
||||
{field: 'id', fixed: 'left', width:80, title: 'ID'},
|
||||
{field: 'name', width:300, title: '任务'},
|
||||
{field: 'projectName', width:150, title: '项目'},
|
||||
{field: 'executionName', width:150, title: '执行'},
|
||||
{field: 'statusName', width:80, title: '状态'},
|
||||
{field: 'assignedToName', width:80, title: '指派给'},
|
||||
{field: 'finishedByName', width:80, title: '完成者'},
|
||||
{field: 'finishedDate', title:'完成时间', width: 180},
|
||||
{fixed: 'right', title:'操作', minWidth: 125, templet: '#toolDemo'}
|
||||
]],
|
||||
done: function(){
|
||||
},
|
||||
error: function(res, msg){
|
||||
console.log(res, msg)
|
||||
}
|
||||
});
|
||||
|
||||
// 触发单元格工具事件
|
||||
table.on('tool(test)', function(obj){ // 双击 toolDouble
|
||||
var data = obj.data; // 获得当前行数据
|
||||
// console.log(obj)
|
||||
if(obj.event === 'detail'){
|
||||
//http://pms.scdxtc.cn/index.php?m=task&f=edit&taskID=57
|
||||
window.open('http://pms.scdxtc.cn/index.php?m=task&f=edit&taskID=57', '_blank');
|
||||
//window.open('http://pms.scdxtc.cn/index.php?m=task&f=edit&taskID=' + data.id, '_blank');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"name": "workerman/webman",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"high performance",
|
||||
"http service"
|
||||
],
|
||||
"homepage": "https://www.workerman.net",
|
||||
"license": "MIT",
|
||||
"description": "High performance HTTP Service Framework.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "walkor",
|
||||
"email": "walkor@workerman.net",
|
||||
"homepage": "https://www.workerman.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "walkor@workerman.net",
|
||||
"issues": "https://github.com/walkor/webman/issues",
|
||||
"forum": "https://wenda.workerman.net/",
|
||||
"wiki": "https://workerman.net/doc/webman",
|
||||
"source": "https://github.com/walkor/webman"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"workerman/webman-framework": "^1.5.0",
|
||||
"monolog/monolog": "^2.0",
|
||||
"topthink/think-template": "^3.0",
|
||||
"webman/think-orm": "^1.1",
|
||||
"phpoffice/phpspreadsheet": "^3.6"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "./",
|
||||
"app\\": "./app",
|
||||
"App\\": "./app",
|
||||
"app\\View\\Components\\": "./app/view/components"
|
||||
},
|
||||
"files": [
|
||||
"./support/helpers.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"post-package-install": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"post-package-update": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"pre-package-uninstall": [
|
||||
"support\\Plugin::uninstall"
|
||||
]
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Request;
|
||||
|
||||
return [
|
||||
'debug' => true,
|
||||
'error_reporting' => E_ALL,
|
||||
'default_timezone' => 'Asia/Shanghai',
|
||||
'request_class' => Request::class,
|
||||
'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
|
||||
'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
|
||||
'controller_suffix' => 'Controller',
|
||||
'controller_reuse' => false,
|
||||
];
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'files' => [
|
||||
base_path() . '/app/functions.php',
|
||||
base_path() . '/support/Request.php',
|
||||
base_path() . '/support/Response.php',
|
||||
]
|
||||
];
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
support\bootstrap\Session::class,
|
||||
support\bootstrap\LaravelDb::class,
|
||||
Webman\ThinkOrm\ThinkOrm::class,
|
||||
];
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return new Webman\Container;
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'' => support\exception\Handler::class,
|
||||
];
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'handlers' => [
|
||||
[
|
||||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/webman.log',
|
||||
7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
global $argv;
|
||||
|
||||
return [
|
||||
// File update detection and automatic reload
|
||||
'monitor' => [
|
||||
'handler' => process\Monitor::class,
|
||||
'reloadable' => false,
|
||||
'constructor' => [
|
||||
// Monitor these directories
|
||||
'monitorDir' => array_merge([
|
||||
app_path(),
|
||||
config_path(),
|
||||
base_path() . '/process',
|
||||
base_path() . '/support',
|
||||
base_path() . '/resource',
|
||||
base_path() . '/.env',
|
||||
], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')),
|
||||
// Files with these suffixes will be monitored
|
||||
'monitorExtensions' => [
|
||||
'php', 'html', 'htm', 'env'
|
||||
],
|
||||
'options' => [
|
||||
'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/',
|
||||
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'host' => '127.0.0.1',
|
||||
'password' => null,
|
||||
'port' => 6379,
|
||||
'database' => 0,
|
||||
],
|
||||
];
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Route;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'listen' => 'http://0.0.0.0:8787',
|
||||
'transport' => 'tcp',
|
||||
'context' => [],
|
||||
'name' => 'webman',
|
||||
'count' => cpu_count() * 4,
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
'reusePort' => false,
|
||||
'event_loop' => '',
|
||||
'stop_timeout' => 2,
|
||||
'pid_file' => runtime_path() . '/webman.pid',
|
||||
'status_file' => runtime_path() . '/webman.status',
|
||||
'stdout_file' => runtime_path() . '/logs/stdout.log',
|
||||
'log_file' => runtime_path() . '/logs/workerman.log',
|
||||
'max_package_size' => 10 * 1024 * 1024
|
||||
];
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Session\FileSessionHandler;
|
||||
use Webman\Session\RedisSessionHandler;
|
||||
use Webman\Session\RedisClusterSessionHandler;
|
||||
|
||||
return [
|
||||
|
||||
'type' => 'file', // or redis or redis_cluster
|
||||
|
||||
'handler' => FileSessionHandler::class,
|
||||
|
||||
'config' => [
|
||||
'file' => [
|
||||
'save_path' => runtime_path() . '/sessions',
|
||||
],
|
||||
'redis' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'auth' => '',
|
||||
'timeout' => 2,
|
||||
'database' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
],
|
||||
'redis_cluster' => [
|
||||
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
|
||||
'timeout' => 2,
|
||||
'auth' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
]
|
||||
],
|
||||
|
||||
'session_name' => 'PHPSID',
|
||||
|
||||
'auto_update_timestamp' => false,
|
||||
|
||||
'lifetime' => 7*24*60*60,
|
||||
|
||||
'cookie_lifetime' => 365*24*60*60,
|
||||
|
||||
'cookie_path' => '/',
|
||||
|
||||
'domain' => '',
|
||||
|
||||
'http_only' => true,
|
||||
|
||||
'secure' => false,
|
||||
|
||||
'same_site' => '',
|
||||
|
||||
'gc_probability' => [1, 1000],
|
||||
|
||||
];
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static file settings
|
||||
*/
|
||||
return [
|
||||
'enable' => true,
|
||||
'middleware' => [ // Static file Middleware
|
||||
//app\middleware\StaticFile::class,
|
||||
],
|
||||
];
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'default' => 'mysql',
|
||||
'connections' => [
|
||||
'mysql' => [
|
||||
// 数据库类型
|
||||
'type' => 'mysql',
|
||||
// 服务器地址
|
||||
'hostname' => '127.0.0.1',
|
||||
// 数据库名
|
||||
'database' => 'work',
|
||||
// 数据库用户名
|
||||
'username' => 'work',
|
||||
// 数据库密码
|
||||
'password' => 'WRzcKzDwZEyK5F85',
|
||||
// 数据库连接端口
|
||||
'hostport' => '3306',
|
||||
// 数据库连接参数
|
||||
'params' => [
|
||||
// 连接超时3秒
|
||||
\PDO::ATTR_TIMEOUT => 3,
|
||||
],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => 'utf8',
|
||||
// 数据库表前缀
|
||||
'prefix' => '',
|
||||
// 断线重连
|
||||
'break_reconnect' => true,
|
||||
// 自定义分页类
|
||||
'bootstrap' => ''
|
||||
],
|
||||
'zdoo' => [
|
||||
// 数据库类型
|
||||
'type' => 'mysql',
|
||||
// 服务器地址
|
||||
'hostname' => '183.221.101.89',
|
||||
// 数据库名
|
||||
'database' => 'zdoo',
|
||||
// 数据库用户名
|
||||
'username' => 'zdoo',
|
||||
// 数据库密码
|
||||
'password' => 'nJHitct3eHLtnyPe',
|
||||
// 数据库连接端口
|
||||
'hostport' => '3306',
|
||||
// 数据库连接参数
|
||||
'params' => [
|
||||
// 连接超时3秒
|
||||
\PDO::ATTR_TIMEOUT => 3,
|
||||
],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => 'utf8',
|
||||
// 数据库表前缀
|
||||
'prefix' => '',
|
||||
// 断线重连
|
||||
'break_reconnect' => true,
|
||||
// 自定义分页类
|
||||
'bootstrap' => ''
|
||||
],
|
||||
'pms' => [
|
||||
// 数据库类型
|
||||
'type' => 'mysql',
|
||||
// 服务器地址
|
||||
'hostname' => '183.221.101.89',
|
||||
// 数据库名
|
||||
'database' => 'pms20',
|
||||
// 数据库用户名
|
||||
'username' => 'pms20',
|
||||
// 数据库密码
|
||||
'password' => 'cTpkyr4KyT6XScAY',
|
||||
// 数据库连接端口
|
||||
'hostport' => '3306',
|
||||
// 数据库连接参数
|
||||
'params' => [
|
||||
// 连接超时3秒
|
||||
\PDO::ATTR_TIMEOUT => 3,
|
||||
],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => 'utf8',
|
||||
// 数据库表前缀
|
||||
'prefix' => 'zt_',
|
||||
// 断线重连
|
||||
'break_reconnect' => true,
|
||||
// 自定义分页类
|
||||
'bootstrap' => ''
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Multilingual configuration
|
||||
*/
|
||||
return [
|
||||
// Default language
|
||||
'locale' => 'zh_CN',
|
||||
// Fallback language
|
||||
'fallback_locale' => ['zh_CN', 'en'],
|
||||
// Folder where language files are stored
|
||||
'path' => base_path() . '/resource/translations',
|
||||
];
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\view\ThinkPHP;
|
||||
|
||||
return [
|
||||
'handler' => ThinkPHP::class,
|
||||
'options' => [
|
||||
//'layout_on' => true,
|
||||
'layout_name' => 'layout',
|
||||
]
|
||||
];
|
|
@ -0,0 +1,39 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>恭喜,站点创建成功!</title>
|
||||
<style>
|
||||
.container {
|
||||
width: 60%;
|
||||
margin: 10% auto 0;
|
||||
background-color: #f0f0f0;
|
||||
padding: 2% 5%;
|
||||
border-radius: 10px
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
ul li {
|
||||
line-height: 2.3
|
||||
}
|
||||
|
||||
a {
|
||||
color: #20a53a
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>恭喜, 站点创建成功!</h1>
|
||||
<h3>这是默认index.html,本页面由系统自动生成</h3>
|
||||
<ul>
|
||||
<li>本页面在FTP根目录下的index.html</li>
|
||||
<li>您可以修改、删除或覆盖本页面</li>
|
||||
<li>FTP相关信息,请到“面板系统后台 > FTP” 查看</li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,258 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace process;
|
||||
|
||||
use FilesystemIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use SplFileInfo;
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
/**
|
||||
* Class FileMonitor
|
||||
* @package process
|
||||
*/
|
||||
class Monitor
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $paths = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $loadedFiles = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public static $lockFile = __DIR__ . '/../runtime/monitor.lock';
|
||||
|
||||
/**
|
||||
* Pause monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function pause()
|
||||
{
|
||||
file_put_contents(static::$lockFile, time());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function resume(): void
|
||||
{
|
||||
clearstatcache();
|
||||
if (is_file(static::$lockFile)) {
|
||||
unlink(static::$lockFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether monitor is paused
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPaused(): bool
|
||||
{
|
||||
clearstatcache();
|
||||
return file_exists(static::$lockFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* FileMonitor constructor.
|
||||
* @param $monitorDir
|
||||
* @param $monitorExtensions
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($monitorDir, $monitorExtensions, array $options = [])
|
||||
{
|
||||
static::resume();
|
||||
$this->paths = (array)$monitorDir;
|
||||
$this->extensions = $monitorExtensions;
|
||||
foreach (get_included_files() as $index => $file) {
|
||||
$this->loadedFiles[$file] = $index;
|
||||
if (strpos($file, 'webman-framework/src/support/App.php')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!Worker::getAllWorkers()) {
|
||||
return;
|
||||
}
|
||||
$disableFunctions = explode(',', ini_get('disable_functions'));
|
||||
if (in_array('exec', $disableFunctions, true)) {
|
||||
echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n";
|
||||
} else {
|
||||
if ($options['enable_file_monitor'] ?? true) {
|
||||
Timer::add(1, function () {
|
||||
$this->checkAllFilesChange();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null);
|
||||
if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) {
|
||||
Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $monitorDir
|
||||
* @return bool
|
||||
*/
|
||||
public function checkFilesChange($monitorDir): bool
|
||||
{
|
||||
static $lastMtime, $tooManyFilesCheck;
|
||||
if (!$lastMtime) {
|
||||
$lastMtime = time();
|
||||
}
|
||||
clearstatcache();
|
||||
if (!is_dir($monitorDir)) {
|
||||
if (!is_file($monitorDir)) {
|
||||
return false;
|
||||
}
|
||||
$iterator = [new SplFileInfo($monitorDir)];
|
||||
} else {
|
||||
// recursive traversal directory
|
||||
$dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new RecursiveIteratorIterator($dirIterator);
|
||||
}
|
||||
$count = 0;
|
||||
foreach ($iterator as $file) {
|
||||
$count ++;
|
||||
/** var SplFileInfo $file */
|
||||
if (is_dir($file->getRealPath())) {
|
||||
continue;
|
||||
}
|
||||
// check mtime
|
||||
if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) {
|
||||
$lastMtime = $file->getMTime();
|
||||
if (DIRECTORY_SEPARATOR === '/' && isset($this->loadedFiles[$file->getRealPath()])) {
|
||||
echo "$file updated but cannot be reloaded because only auto-loaded files support reload.\n";
|
||||
continue;
|
||||
}
|
||||
$var = 0;
|
||||
exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var);
|
||||
if ($var) {
|
||||
continue;
|
||||
}
|
||||
echo $file . " updated and reload\n";
|
||||
// send SIGUSR1 signal to master process for reload
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
posix_kill(posix_getppid(), SIGUSR1);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$tooManyFilesCheck && $count > 1000) {
|
||||
echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n";
|
||||
$tooManyFilesCheck = 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAllFilesChange(): bool
|
||||
{
|
||||
if (static::isPaused()) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->paths as $path) {
|
||||
if ($this->checkFilesChange($path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $memoryLimit
|
||||
* @return void
|
||||
*/
|
||||
public function checkMemory($memoryLimit)
|
||||
{
|
||||
if (static::isPaused() || $memoryLimit <= 0) {
|
||||
return;
|
||||
}
|
||||
$ppid = posix_getppid();
|
||||
$childrenFile = "/proc/$ppid/task/$ppid/children";
|
||||
if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) {
|
||||
return;
|
||||
}
|
||||
foreach (explode(' ', $children) as $pid) {
|
||||
$pid = (int)$pid;
|
||||
$statusFile = "/proc/$pid/status";
|
||||
if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) {
|
||||
continue;
|
||||
}
|
||||
$mem = 0;
|
||||
if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) {
|
||||
$mem = $match[1];
|
||||
}
|
||||
$mem = (int)($mem / 1024);
|
||||
if ($mem >= $memoryLimit) {
|
||||
posix_kill($pid, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory limit
|
||||
* @return float
|
||||
*/
|
||||
protected function getMemoryLimit($memoryLimit)
|
||||
{
|
||||
if ($memoryLimit === 0) {
|
||||
return 0;
|
||||
}
|
||||
$usePhpIni = false;
|
||||
if (!$memoryLimit) {
|
||||
$memoryLimit = ini_get('memory_limit');
|
||||
$usePhpIni = true;
|
||||
}
|
||||
|
||||
if ($memoryLimit == -1) {
|
||||
return 0;
|
||||
}
|
||||
$unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]);
|
||||
if ($unit === 'g') {
|
||||
$memoryLimit = 1024 * (int)$memoryLimit;
|
||||
} else if ($unit === 'm') {
|
||||
$memoryLimit = (int)$memoryLimit;
|
||||
} else if ($unit === 'k') {
|
||||
$memoryLimit = ((int)$memoryLimit / 1024);
|
||||
} else {
|
||||
$memoryLimit = ((int)$memoryLimit / (1024 * 1024));
|
||||
}
|
||||
if ($memoryLimit < 30) {
|
||||
$memoryLimit = 30;
|
||||
}
|
||||
if ($usePhpIni) {
|
||||
$memoryLimit = (int)(0.8 * $memoryLimit);
|
||||
}
|
||||
return $memoryLimit;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
7JeNCSvvuIluBzxPtEGpPt5qMMfieZ1X
|
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>404 Not Found - webman</title>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<h1>404 Not Found</h1>
|
||||
</center>
|
||||
<hr>
|
||||
<center>webman</center>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -0,0 +1,39 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>恭喜,站点创建成功!</title>
|
||||
<style>
|
||||
.container {
|
||||
width: 60%;
|
||||
margin: 10% auto 0;
|
||||
background-color: #f0f0f0;
|
||||
padding: 2% 5%;
|
||||
border-radius: 10px
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
ul li {
|
||||
line-height: 2.3
|
||||
}
|
||||
|
||||
a {
|
||||
color: #20a53a
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>恭喜, 站点创建成功!</h1>
|
||||
<h3>这是默认index.html,本页面由系统自动生成</h3>
|
||||
<ul>
|
||||
<li>本页面在FTP根目录下的index.html</li>
|
||||
<li>您可以修改、删除或覆盖本页面</li>
|
||||
<li>FTP相关信息,请到“面板系统后台 > FTP” 查看</li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,119 @@
|
|||
layui.use(['layer', 'form', 'laypage'], function(){
|
||||
var form = layui.form;
|
||||
// alert弹窗方法
|
||||
window.layerAlert = function (type, text, href, width, state,id)
|
||||
{
|
||||
if(width == undefined || width == '') width = 700;
|
||||
|
||||
if(id) href = href + id;
|
||||
|
||||
var load = layer.load(2);
|
||||
$.ajax({
|
||||
type : type,
|
||||
url : href,
|
||||
data : {},
|
||||
headers: {
|
||||
//'X-CSRF-TOKEN': _token
|
||||
},
|
||||
success: function(data){
|
||||
if (data.code !== undefined && !isNaN(data.code) && data.code != 0)
|
||||
{
|
||||
layer.close(load);
|
||||
layer.msg(data.msg, {time: 2000})
|
||||
}
|
||||
else
|
||||
{
|
||||
layer.open({
|
||||
type : 1,
|
||||
title : text,
|
||||
shadeClose: true,
|
||||
area : ''+width+'px', //宽高
|
||||
maxmin : true,
|
||||
move : false,
|
||||
content : data,
|
||||
success : function(layero, index) {
|
||||
layer.close(load);
|
||||
|
||||
//renderMultiSelect();
|
||||
form.render(); //重新渲染form
|
||||
//tinymceEditor(); //文本编辑器
|
||||
//判断弹框内容高度
|
||||
|
||||
if($(window).height() - 180 < $('.layui-layer-content .layui-card-body:first').height())
|
||||
{
|
||||
layer.style(index, {
|
||||
height: $(window).height() - 80,
|
||||
top : 40
|
||||
})
|
||||
$('.layui-layer-content').height($(window).height()-123)
|
||||
$('.layui-layer-content').css('max-height','85vh');
|
||||
$('.eject-layuiBox').height($(window).height()-123)
|
||||
$('.eject-layuiBox').css('max-height','85vh');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('.layui-layer-content').css('max-height','79vh;padding-bottom: 10px;');
|
||||
$('.eject-layuiBox').css('max-height','79vh');
|
||||
}
|
||||
},
|
||||
end:function(){
|
||||
if(state == 'edit') $('.layui-edit-btn').remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//编辑或者添加按钮
|
||||
$(document).on('click','a.layui-btn',function()
|
||||
{
|
||||
var text = $(this).attr('title');
|
||||
var href = $(this).data('href');
|
||||
var width = $(this).data('width');
|
||||
var state = $(this).data('state');
|
||||
var id = $(this).data('id');
|
||||
|
||||
if(href && text) layerAlert('get', text, href, width, state,id);
|
||||
});
|
||||
|
||||
form.on('submit(submitAll)', function(data){
|
||||
var url = $(data.elem).parents('form').data('action');
|
||||
|
||||
formSubmit(url,data.field);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
//表单ajax提交
|
||||
function formSubmit(url, fromdata)
|
||||
{
|
||||
$.ajax(url, {
|
||||
data : fromdata,
|
||||
dataType: 'json', //服务器返回json格式数据
|
||||
type : 'post', //HTTP请求类型
|
||||
timeout : 10000, //超时时间设置为10秒;
|
||||
async : false,
|
||||
headers : {
|
||||
//'X-CSRF-TOKEN': _token
|
||||
},
|
||||
success:function(data){
|
||||
if(data.code == 0)
|
||||
{
|
||||
layer.msg('提交成功!')
|
||||
setTimeout(function(){
|
||||
parent.layer.closeAll();
|
||||
parent.location.reload()
|
||||
}, 500)
|
||||
}
|
||||
else
|
||||
{
|
||||
layer.msg(data.msg)
|
||||
}
|
||||
},
|
||||
error:function(xhr,type,errorThrown){
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 323 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,788 @@
|
|||
/** 自定义字体 **/
|
||||
/** 这里使用在线字体,如果需要离线包,请看 font/README.md **/
|
||||
@font-face {
|
||||
font-family: 'soul-icon'; /* project id 677836 */
|
||||
src: url('//at.alicdn.com/t/font_677836_jwq362m0tt.eot');
|
||||
src: url('//at.alicdn.com/t/font_677836_jwq362m0tt.eot?#iefix') format('embedded-opentype'),
|
||||
url('//at.alicdn.com/t/font_677836_jwq362m0tt.woff2') format('woff2'),
|
||||
url('//at.alicdn.com/t/font_677836_jwq362m0tt.woff') format('woff'),
|
||||
url('//at.alicdn.com/t/font_677836_jwq362m0tt.ttf') format('truetype'),
|
||||
url('//at.alicdn.com/t/font_677836_jwq362m0tt.svg#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.soul-icon {
|
||||
font-family:"soul-icon" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.soul-icon-filter:before { content: "\e60b"; }
|
||||
.soul-icon-filter-asc:before { content: "\e768"; }
|
||||
.soul-icon-filter-desc:before { content: "\e767"; }
|
||||
.soul-icon-asc:before { content: "\e6af"; }
|
||||
.soul-icon-desc:before { content: "\e6ae"; }
|
||||
.soul-icon-all-check:before { content: "\e670"; }
|
||||
.soul-icon-invert-check:before { content: "\e614"; }
|
||||
.soul-icon-fold:before { content: "\e760"; }
|
||||
.soul-icon-unfold:before { content: "\e611"; }
|
||||
.soul-icon-delete:before { content: "\e600"; }
|
||||
.soul-icon-download:before { content: "\e601"; }
|
||||
.soul-icon-drop-list:before { content: "\e6a3"; }
|
||||
.soul-icon-query:before { content: "\e66d"; }
|
||||
/* 全选*/
|
||||
.soul-icon-quanxuan:before { content: "\e623"; }
|
||||
.soul-icon-qingkong:before { content: "\e63e"; }
|
||||
.soul-icon-autoColumnWidth
|
||||
:before { content: "\e614"; }
|
||||
|
||||
/*最大化*/
|
||||
.soul-icon-min:before { content: "\e656"; }
|
||||
.soul-icon-max:before { content: "\e61b"; }
|
||||
|
||||
|
||||
/* 配色方案*/
|
||||
.layui-red {
|
||||
color: #FF5722
|
||||
}
|
||||
.layui-orange {
|
||||
color: #FFB800
|
||||
}
|
||||
.layui-green {
|
||||
color: #009688
|
||||
}
|
||||
.layui-cyan {
|
||||
color: #2F4056
|
||||
}
|
||||
.layui-blue {
|
||||
color: #1E9FFF
|
||||
}
|
||||
.layui-black {
|
||||
color: #393D49
|
||||
}
|
||||
.layui-gray {
|
||||
color: #eee
|
||||
}
|
||||
.layui-firebrick {
|
||||
color: firebrick;
|
||||
}
|
||||
.layui-deeppink {
|
||||
color: deeppink;
|
||||
}
|
||||
.layui-blueviolet {
|
||||
color: blueviolet;
|
||||
}
|
||||
|
||||
.soul-condition [class*="layui-col-"] {
|
||||
margin-top: 10px;
|
||||
}
|
||||
/* 表格排序样式*/
|
||||
.soul-edge {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-width: 6px;
|
||||
border-style: dashed;
|
||||
border-color: transparent;
|
||||
overflow: hidden
|
||||
}
|
||||
.soul-table-sort {
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
margin-left: 5px;
|
||||
cursor: pointer !important;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.soul-table-sort .soul-edge {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
border-width: 5px
|
||||
}
|
||||
|
||||
.soul-table-sort .soul-table-sort-asc {
|
||||
top: 10px;
|
||||
border-top: none;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #b2b2b2
|
||||
}
|
||||
|
||||
.soul-table-sort .soul-table-sort-asc:hover {
|
||||
border-bottom-color: #666
|
||||
}
|
||||
|
||||
.soul-table-sort .soul-table-sort-desc {
|
||||
bottom: -2px;
|
||||
border-bottom: none;
|
||||
border-top-style: solid;
|
||||
border-top-color: #b2b2b2
|
||||
}
|
||||
|
||||
.soul-table-sort .soul-table-sort-desc:hover {
|
||||
border-top-color: #666
|
||||
}
|
||||
|
||||
.soul-table-sort[soul-sort=asc] .soul-table-sort-asc {
|
||||
border-bottom-color: #000
|
||||
}
|
||||
|
||||
.soul-table-sort[soul-sort=desc] .soul-table-sort-desc {
|
||||
border-top-color: #000
|
||||
}
|
||||
|
||||
.multiOption {
|
||||
display: inline-block;
|
||||
padding: 0 5px;
|
||||
cursor: pointer;
|
||||
color: #999;
|
||||
}
|
||||
/*表格筛选*/
|
||||
.soul-table-filter {
|
||||
line-height: 20px;
|
||||
color: #b2b2b2;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.soul-table-filter .soul-icon-filter-asc,.soul-table-filter .soul-icon-filter-desc {
|
||||
display: none;
|
||||
}
|
||||
.soul-table-filter[lay-sort="asc"] .soul-icon-filter-asc{
|
||||
display: block;
|
||||
color: #000000;
|
||||
}
|
||||
.soul-table-filter[lay-sort="asc"] .soul-icon-filter,.soul-table-filter[lay-sort="asc"] .soul-icon-filter-desc{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.soul-table-filter[lay-sort="desc"] .soul-icon-filter-desc{
|
||||
display: block;
|
||||
color: #000000;
|
||||
}
|
||||
.soul-table-filter[lay-sort="desc"] .soul-icon-filter,.soul-table-filter[lay-sort="desc"] .soul-icon-filter-asc{
|
||||
display: none;
|
||||
}
|
||||
.soul-table-filter[soul-filter="true"] i {
|
||||
color: #009688!important;
|
||||
}
|
||||
|
||||
|
||||
[id^=main-list], [id^=soul-columns], [id^=soul-dropList], [id^=soul-condition], [id^=soul-bf-prefix], [id^=soul-bf-column], [id^=soul-bf-type], [id^=soul-bf-cond2] {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
z-index: 2147483647;
|
||||
background-color: white;
|
||||
max-height: 200px;
|
||||
min-width: 160px;
|
||||
max-width: 300px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 2px 4px -2px rgba(0,0,0,.2);
|
||||
}
|
||||
[id^=main-list] {
|
||||
max-height: initial;
|
||||
}
|
||||
[id^=soul-condition] {
|
||||
overflow-y: visible;
|
||||
max-height: initial;
|
||||
min-width: 285px;
|
||||
padding: 5px;
|
||||
}
|
||||
[id^=soul-condition] .layui-laydate-header {
|
||||
padding: 4px 70px 5px
|
||||
}
|
||||
[id^=soul-condition] hr{
|
||||
margin: 5px 0;
|
||||
}
|
||||
[id^=soul-condition].soul-bf{
|
||||
min-width: 150px;
|
||||
}
|
||||
[id^=soul-filter-list] ul li {
|
||||
padding: 3px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
[id^=soul-filter-list] ul li:hover {
|
||||
background-color: deepskyblue;
|
||||
}
|
||||
[id^=soul-filter-list] i.layui-icon {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
}
|
||||
[id^=soul-dropList] ul {
|
||||
border: 0;
|
||||
max-height: 116px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
[id^=soul-dropList] ul li, [id^=soul-filter-list] [id^=soul-columns]>li{
|
||||
padding: 2px 10px;
|
||||
}
|
||||
[id^=soul-dropList] .check {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
.filter-search {
|
||||
padding: 5px 10px 0 10px;
|
||||
}
|
||||
[id^=soul-condition] .layui-inline {
|
||||
width: 100px;
|
||||
}
|
||||
[id^=soul-condition] table.condition-table tr>td {
|
||||
padding: 0 3px;
|
||||
}
|
||||
[id^=soul-condition] table.condition-table tr>td:first-child {
|
||||
min-width: 60px;
|
||||
}
|
||||
[id^=soul-condition] .layui-form-switch {
|
||||
background-color: #1E9FFF;
|
||||
border: 1px solid #1E9FFF;
|
||||
width: 35px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
[id^=soul-condition] .layui-form-switch.layui-form-onswitch {
|
||||
background-color: #5FB878;
|
||||
border: 1px solid #5FB878;
|
||||
}
|
||||
[id^=soul-condition] .layui-form-switch em {
|
||||
color: #fff!important;
|
||||
}
|
||||
[id^=soul-condition] .layui-form-switch i {
|
||||
background-color: #fff;
|
||||
}
|
||||
[data-type^=date][class$=Condition] {
|
||||
width: 273px;
|
||||
}
|
||||
/*表格筛选*/
|
||||
[id^=soul-condition]>div{
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.soul-condition-title {
|
||||
text-align: center;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/*底部筛选*/
|
||||
.soul-bottom-contion {
|
||||
height: 31px;
|
||||
/*line-height: 29px;*/
|
||||
border-top: solid 1px #e6e6e6;
|
||||
}
|
||||
.soul-bottom-contion .condition-items {
|
||||
display: inline-block;
|
||||
width: calc(100vw - 100px);
|
||||
height: 30px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.soul-bottom-contion .condition-item>div {
|
||||
display: inline-block;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.soul-bottom-contion .condition-items .condition-item>div[class^='item-']:hover{
|
||||
text-decoration: underline;
|
||||
}
|
||||
.soul-bottom-contion .condition-items .condition-item{
|
||||
padding: 0 10px;
|
||||
margin: 0 2px;
|
||||
font-weight: bold;
|
||||
border: solid 1px darkslateblue;
|
||||
border-radius: 10px;
|
||||
display: inline-block;
|
||||
height: 28px;
|
||||
position: relative;
|
||||
}
|
||||
.soul-bottom-contion .editCondtion {
|
||||
height: 30px;
|
||||
float: right;
|
||||
}
|
||||
.soul-bottom-contion .item-value {
|
||||
min-width: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
.soul-bottom-contion .editCondtion a {
|
||||
border: hidden;
|
||||
border-left: solid 1px #e6e6e6;
|
||||
height: 28px;
|
||||
line-height: 29px;
|
||||
}
|
||||
.soul-bottom-contion .condition-items .condition-item .condition-item-close {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
margin-top: -8px;
|
||||
}
|
||||
.soul-bottom-contion .condition-items>.condition-item>.condition-item-close {
|
||||
margin-top: -2px;
|
||||
}
|
||||
.soul-bottom-contion .condition-items .condition-item .condition-item-close:hover{
|
||||
color: red
|
||||
}
|
||||
.soul-bottom-contion .condition-items .condition-item .condition-item-close:before {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.soul-edit-out {
|
||||
padding: 10px;
|
||||
}
|
||||
[id^=soul-bf] li {
|
||||
padding: 0px 10px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
color: #000;
|
||||
cursor: pointer;
|
||||
}
|
||||
[id^=soul-bf] li.soul-bf-selected {
|
||||
background-color: deepskyblue;
|
||||
}
|
||||
[id^=soul-bf] li:hover {
|
||||
background-color: deepskyblue;
|
||||
}
|
||||
.soul-edit-out .tempValue {
|
||||
height: 25px;
|
||||
}
|
||||
.soul-bf-condition-value {
|
||||
display: inline;
|
||||
width: 100px;
|
||||
}
|
||||
/*子表格*/
|
||||
.layui-table tbody tr.noHover:hover {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
/*编辑筛选*/
|
||||
.soul-edit-out .layui-form-radio {
|
||||
margin: 0;
|
||||
}
|
||||
.soul-edit-out ul li > div {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
height: 25px;
|
||||
vertical-align: top;
|
||||
cursor: pointer;
|
||||
}
|
||||
.soul-edit-out ul.group {
|
||||
padding-left: 50px;
|
||||
}
|
||||
.soul-edit-out ul.group.line {
|
||||
border-left: 1px dashed grey;
|
||||
}
|
||||
.soul-edit-out ul li {
|
||||
line-height: 25px;
|
||||
}
|
||||
.soul-edit-out table {
|
||||
display: inline-block;
|
||||
}
|
||||
.soul-edit-out table td[data-type='top'] {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-left: dashed 1px grey;
|
||||
border-bottom: dashed 1px grey;
|
||||
}
|
||||
.soul-edit-out table td[data-type='bottom'] {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-left: dashed 1px grey;
|
||||
}
|
||||
.soul-edit-out li.last>div>table td[data-type='bottom'] {
|
||||
border-left: none;
|
||||
}
|
||||
.soul-edit-out .layui-form-switch {
|
||||
background-color: #1E9FFF;
|
||||
border: 1px solid #1E9FFF;
|
||||
width: 35px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
.soul-edit-out .layui-form-switch em {
|
||||
color: #fff!important;
|
||||
}
|
||||
.soul-edit-out .layui-form-switch i {
|
||||
background-color: #fff;
|
||||
}
|
||||
.soul-edit-out .layui-form-switch.layui-form-onswitch {
|
||||
background-color: #5FB878;
|
||||
border: 1px solid #5FB878;
|
||||
}
|
||||
.soul-edit-out .delete-item {
|
||||
display: none;
|
||||
}
|
||||
.soul-edit-out li:hover>.delete-item {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* 拖拽相关 */
|
||||
#column-remove {
|
||||
position: absolute;
|
||||
z-index: 2147483647;
|
||||
}
|
||||
.layui-table-box.no-left-border td.isDrag, .layui-table-box.no-left-border th.isDrag {
|
||||
border-left: inherit!important;
|
||||
}
|
||||
.soul-drag-bar {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
z-index: 200;
|
||||
left: 50%;
|
||||
font-weight: 900;
|
||||
color: white;
|
||||
box-shadow: 0 1px 20px rgba(0,0,0,.15);
|
||||
text-align: center;
|
||||
transform: translateX(100vw);
|
||||
/*transition: transform .3s;*/
|
||||
}
|
||||
.soul-drag-bar.active {
|
||||
transform: translateX(-98px);
|
||||
}
|
||||
.soul-drag-bar > div {
|
||||
display: inline-block;
|
||||
padding: 10px;
|
||||
cursor: crosshair;
|
||||
width: 62px;
|
||||
background-color: rgba(0, 150, 136, 0.5);
|
||||
}
|
||||
.soul-drag-bar > div.active, .soul-drag-bar[data-type='left']>div[data-type='left'], .soul-drag-bar[data-type='right']>div[data-type='right'], .soul-drag-bar[data-type='none']>div[data-type='none'] {
|
||||
background-color: rgb(0, 150, 136);
|
||||
}
|
||||
|
||||
/* 动画 */
|
||||
.animated {
|
||||
-webkit-animation-duration: 1s;
|
||||
-moz-animation-duration: 1s;
|
||||
-o-animation-duration: 1s;
|
||||
animation-duration: 1s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
-moz-animation-fill-mode: both;
|
||||
-o-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
@-moz-keyframes fadeInLeft {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateX(-20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeInLeft {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-o-transform: translateX(-20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-o-transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInLeft {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animated.fadeInLeft {
|
||||
-webkit-animation-name: fadeInLeft;
|
||||
-moz-animation-name: fadeInLeft;
|
||||
-o-animation-name: fadeInLeft;
|
||||
animation-name: fadeInLeft;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeOutLeft {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateX(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeOutLeft {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateX(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeOutLeft {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-o-transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-o-transform: translateX(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOutLeft {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
.animated.fadeOutLeft {
|
||||
-webkit-animation-name: fadeOutLeft;
|
||||
-moz-animation-name: fadeOutLeft;
|
||||
-o-animation-name: fadeOutLeft;
|
||||
animation-name: fadeOutLeft;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeInRight {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateX(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeInRight {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateX(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeInRight {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-o-transform: translateX(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-o-transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInRight {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animated.fadeInRight {
|
||||
-webkit-animation-name: fadeInRight;
|
||||
-moz-animation-name: fadeInRight;
|
||||
-o-animation-name: fadeInRight;
|
||||
animation-name: fadeInRight;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-o-transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-o-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animated.fadeInUp {
|
||||
-webkit-animation-name: fadeInUp;
|
||||
-moz-animation-name: fadeInUp;
|
||||
-o-animation-name: fadeInUp;
|
||||
animation-name: fadeInUp;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeOutDown {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeOutDown {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateY(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeOutDown {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-o-transform: translateY(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-o-transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOutDown {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
.animated.fadeOutDown {
|
||||
-webkit-animation-name: fadeOutDown;
|
||||
-moz-animation-name: fadeOutDown;
|
||||
-o-animation-name: fadeOutDown;
|
||||
animation-name: fadeOutDown;
|
||||
}
|
||||
|
||||
#soul-table-contextmenu-wrapper {
|
||||
width: 0;
|
||||
}
|
||||
.soul-table-contextmenu {
|
||||
position: absolute;
|
||||
z-index: 2147483647;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 1px solid #ebeef5;
|
||||
box-shadow: 2px 2px 4px -2px rgba(0,0,0,.2);
|
||||
background: white;
|
||||
}
|
||||
.soul-table-contextmenu li {
|
||||
line-height: 26px;
|
||||
padding: 0 30px;
|
||||
cursor: pointer;
|
||||
word-break: keep-all;
|
||||
}
|
||||
.soul-table-contextmenu li:hover {
|
||||
background: #c5c5c5;
|
||||
}
|
||||
.soul-table-contextmenu li i.prefixIcon{
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
.soul-table-contextmenu li i.endIcon{
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
/*拖拽相关*/
|
||||
.layui-table-sort-invalid {
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
margin-left: 5px;
|
||||
cursor: pointer!important;
|
||||
}
|
||||
.layui-table-sort-invalid .layui-table-sort-asc {
|
||||
top: 3px;
|
||||
border-top: none;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #b2b2b2;
|
||||
}
|
||||
.layui-table-sort-invalid .layui-edge {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
border-width: 5px;
|
||||
}
|
||||
.layui-table-sort-invalid .layui-table-sort-desc {
|
||||
bottom: 5px;
|
||||
border-bottom: none;
|
||||
border-top-style: solid;
|
||||
border-top-color: #b2b2b2;
|
||||
}
|
||||
.layui-table-sort-invalid .layui-edge {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
border-width: 5px;
|
||||
}
|
||||
.noselect {
|
||||
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
|
||||
-webkit-user-select: none; /* Chrome/Safari/Opera */
|
||||
|
||||
-khtml-user-select: none; /* Konqueror */
|
||||
|
||||
-moz-user-select: none; /* Firefox */
|
||||
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
|
||||
user-select: none; /* Non-prefixed version, currently */
|
||||
|
||||
}
|
||||
/* 固定列滚动 */
|
||||
.soul-fixed-scroll::-webkit-scrollbar{
|
||||
display: none
|
||||
}
|
||||
.soul-fixed-scroll{
|
||||
overflow-y: auto!important;
|
||||
-ms-overflow-style:none;
|
||||
overflow:-moz-scrollbars-none;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
support\App::run();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue