发布测试版 2.5.0

This commit is contained in:
乐风 2021-11-28 12:06:10 +08:00
parent 672cc966db
commit 8408038188
807 changed files with 94347 additions and 47563 deletions

View File

@ -48,11 +48,6 @@ PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
# 即时通讯
REALTIME_KEY=
REALTIME_URL=ws://192.168.0.2:6002/realtime
REALTIME_API=http://192.168.0.2:6002/api
# 是否二次验证
AUTH_TOTP=false

View File

@ -46,11 +46,28 @@
2021-11-07 开源测试版 2.4.0 更新记录
新增
新增
1.去掉原辅料清单功能删除product_formula表。
2.重新实现物料清单,不在单独建立原辅料表,采用产品关联机制。
3.修改生产计划BOM计算逻辑配合新的物料清单计算原料使用功能。
4.首页加入客户统计部件。
4.首页加入客户联系人统计部件。
4.首页加入销售订单统计部件。
SQL更新: 导入database/gdoo-2.4.0.upgrade.sql或者按新的结构修改。
修正
1.角色权限分配提交保存部分丢失
2.销售订单参照未发货订单字段不完整
SQL更新
1.导入database/gdoo-2.4.0.upgrade.sql或者按新的结构修改。
2021-11-28 开源测试版 2.5.0 更新记录
新增
1.修改组织架构逻辑,加入职级功能。
2.去掉市场费用模块,将来更专注开发进销存,故而去掉行业性模块。
3.整理前端代码架构。
4.优化首页部件显示逻辑,加入信息块筛选。
4.清理部分SQL表结构。
修正
1.修正日历因事件提醒无法保存bug。
SQL安装
1.导入database/gdoo-2.5.0.sql
本次更新大量更新sql可能出现不兼容情况。

202
LICENSE
View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright Twosee [twosee@php.net]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,7 +1,7 @@
# Gdoo协同办公
<p align="center">
<a href="http://www.gdoo.net"><img src="https://img.shields.io/badge/version-beta2.3.x-%23ff0000" alt="Build Status" /></a>
<a href="http://www.gdoo.net"><img src="https://img.shields.io/badge/version-beta2.5.x-%23ff0000" alt="Build Status" /></a>
<a href="http://www.gdoo.net"><img src="https://img.shields.io/badge/laravel-8.0-%23ef3b2d" alt="laravel framework" /></a>
<a href="http://www.gdoo.net"><img src="https://img.shields.io/badge/MYSQL-8.0-%2300758f" alt="License" /></a>
<a href="http://www.gdoo.net"><img src="https://img.shields.io/badge/Licence-Apache2.0-blue.svg?style=flat" /></a>
@ -89,7 +89,7 @@ QQ交流群: 79446405
</p>
## 安装
1. 推荐使用宝塔面板安装nginx 1.18.x、php-8.x(需要扩展fileinfo)、mysql-8.x(mariaDB 10.4.x)如果你使用win请自行安装相关环境修改php参数max_input_vars = 100000 (避免变量部分丢失)
1. 推荐使用宝塔面板安装nginx 1.18.x、php-8.x(需要扩展fileinfo)、mysql-8.x(mariaDB 10.4.x)如果你使用win请自行安装相关环境
2. 创建网站和数据库, 数据库字符utf8mb4, 在网站目录中设置PHP命令行版本为php-80
3. 下载gdoo: https://gitee.com/hawind/gdoo 上传至宝塔网站根目录并解压
4. 打开Xshell并登录, 执行 <code>composer -v</code> 查看composer版本, 执行 <code>composer self-update</code> 升级composer至最新版本
@ -98,7 +98,7 @@ QQ交流群: 79446405
7. 执行 <code>cp .env.example .env</code> 并修改相关配置
8. 执行 <code>php artisan key:generate</code>
9. 打开宝塔数据库管理:
1. 将项目database目录中的 gdoo-2.2.sql 文件上传并导入到数据库
1. 将项目database目录中的 gdoo-2.5.0.sql 文件上传并导入到数据库
10. 打开宝塔网站管理:
1. 设置运行目录为public
2. 设置伪静态为laravel5

View File

@ -2,6 +2,7 @@
namespace App\Console;
use DB;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@ -24,7 +25,17 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
// */1 * * * * /www/web/php70/bin/php /www/htdocs/shenghua.app/artisan schedule:run --env=production 1>> /dev/null 2>&1
$rows = DB::table('cron')->where('status', 1)->get();
if ($rows) {
foreach ($rows as $row) {
if ($row['expression'] && $row['command']) {
$schedule->command($row['command'])->cron($row['expression']);
}
}
}
}
/**

View File

@ -1,360 +0,0 @@
<?php namespace Gdoo\Approach\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\Approach\Models\Approach;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\Index\Controllers\WorkflowController;
class ApproachController extends WorkflowController
{
public $permission = ['dialog', 'reference', 'useCount', 'serviceReview', 'serviceCostList', 'serviceCostDetail', 'product'];
public function index()
{
// 客户权限
$region = regionCustomer('customer_id_customer');
$header = Grid::header([
'code' => 'approach',
'referer' => 1,
'search' => ['by' => ''],
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '显示',
'action' => 'show',
'display' => $this->access['show'],
]];
$cols['master_product']['cellRenderer'] = 'htmlCellRenderer';
$cols['master_cash_amount']['cellRenderer'] = 'htmlCellRenderer';
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => 0],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['left_buttons'] = [
['name' => '批量编辑', 'color' => 'default', 'icon' => 'fa-pencil-square-o', 'action' => 'batchEdit', 'display' => $this->access['batchEdit']],
];
$header['cols'] = $cols;
$header['tabs'] = Approach::$tabs;
$header['bys'] = Approach::$bys;
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->leftJoin(DB::raw('(SELECT sum(verification_cost) as master_cash_amount, min(date) as master_cash_date, apply_id FROM approach_review where status = 1 group by apply_id) as b'), 'approach.id', '=', 'b.apply_id');
$header['select'][] = 'b.master_cash_amount';
$header['select'][] = 'b.master_cash_date';
$model->orderBy($header['sort'], $header['order']);
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
if ($region['authorise']) {
foreach ($region['whereIn'] as $key => $where) {
$model->whereIn($key, $where);
}
}
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
return Grid::dataFilters($rows, $header, function($item) {
$item['master_cash_amount'] = '<a href="javascript:;" data-toggle="event" data-action="fee_detail" data-master_id="'.$item['master_id'].'" class="option">'.$item['master_cash_amount'].'</a>';
$item['master_product'] = '<a href="javascript:;" data-toggle="event" data-action="product" data-master_id="'.$item['master_id'].'" class="option">明细</a>';
return $item;
});
}
return $this->display([
'header' => $header,
]);
}
public function create($action = 'edit')
{
$id = (int) Request::get('id');
// 客户权限
$header['region'] = ['field' => 'customer_id'];
$header['authorise'] = ['action' => 'index', 'field' => 'created_id'];
$header['action'] = $action;
$header['code'] = 'approach';
$header['id'] = $id;
$form = Form::make($header);
$tpl = $action == 'print' ? 'print' : 'create';
return $this->display([
'form' => $form,
], $tpl);
}
public function edit()
{
return $this->create();
}
public function audit()
{
return $this->create('audit');
}
public function show()
{
return $this->create('show');
}
public function print()
{
$this->layout = 'layouts.print_html';
return $this->create('print');
}
// 关闭操作
public function close()
{
$gets = Request::all();
if (Request::method() == 'POST') {
$row = DB::table('approach')->where('id', $gets['id'])->first();
DB::table('approach')->where('id', $gets['id'])->update([
'is_close' => !$row['is_close']
]);
return $this->json('操作成功。', true);
}
}
// 产品明细
public function product()
{
$query = Request::all();
if (Request::method() == 'POST') {
$rows = DB::table('approach_data')
->leftJoin('product', 'product.id', '=', 'approach_data.product_id')
->where('approach_id', $query['id'])
->orderBy('product.code', 'asc')
->get(['product.*']);
return $this->json($rows, true);
}
return $this->render(['query' => $query]);
}
// 核销单选择
public function serviceReview()
{
$header = Grid::header([
'code' => 'approach',
'prefix' => '',
]);
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
if ($query['master']) {
$model = DB::table('approach');
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->leftJoin('approach_market', 'approach_market.id', '=', 'approach.market_id')
->where('approach.status', 1)
->orderBy('approach.id', 'desc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->selectRaw('
distinct(approach.id),
approach.id,
approach.sn,
approach.status,
approach.barcode_cast,
approach.apply2_money,
approach.created_at,
approach.customer_id,
customer_id_customer.region_id,
approach_market.name as market_name,
region_id_customer_region.name as region_name,
customer_id_customer.code as customer_code,
customer_id_customer.name as customer_name,
customer_id_customer.warehouse_contact,
customer_id_customer.warehouse_phone,
customer_id_customer.warehouse_address
');
$rows = $model->get();
$rows = Grid::dataFilters($rows, $header);
return $rows;
} else {
$model = DB::table('approach_data')
->leftJoin('product', 'product.id', '=', 'approach_data.product_id')
->leftJoin('approach', 'approach.id', '=', 'approach_data.approach_id')
->leftJoin('product_unit', 'product_unit.id', '=', 'product.unit_id')
->whereIn('approach.id', (array)$query['ids']);
if ($query['sort'] && $query['order']) {
$model->orderBy($query['sort'], $query['order']);
}
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->selectRaw("
approach_data.*,
approach.id as approach_id,
approach.sn as approach_sn,
product.code as product_code,
product.name as product_name,
product.spec as product_spec,
product.barcode as product_barcode,
product.unit_id as unit_id,
product_unit.name as product_unit,
product.weight
");
$rows = $model->get();
return ['data' => $rows];
}
}
return $this->render([
'search' => $search,
'query' => $query,
]);
}
// 费用申请明细
public function serviceCostDetail()
{
$query = Request::all();
$customer_id = (int)$query['customer_id'];
$date = empty($query['date']) ? date('Y-m-d') : $query['date'];
$year = date('Y', strtotime($date));
if (Request::method() == 'POST') {
if ($query['type'] == 'promotion') {
$rows = DB::table('promotion')
->where('type_id', 2)
->whereRaw('customer_id=? and '.sql_year('actived_dt').'=? and isnull(is_close, 0) = 0 and isnull(status, 0) <> 0', [$customer_id, $year])
->get();
}
if ($query['type'] == 'approach') {
$rows = DB::table('approach')
->whereRaw('customer_id=? and '.sql_year('actived_dt').'=? and isnull(is_close, 0) = 0 and isnull(status, 0) <> 0', [$customer_id, $year])
->get();
}
if ($query['type'] == 'material') {
$rows = DB::table('promotion')
->where('type_id', 1)
->whereRaw('customer_id=? and '.sql_year('actived_dt').'=? and isnull(is_close, 0) = 0 and isnull(status, 0) <> 0', [$customer_id, $year])
->get();
}
return $this->json($rows, true);
}
$approach = DB::table('approach')
->whereRaw('customer_id=? and '.sql_year('actived_dt').'=? and isnull(is_close, 0) = 0 and isnull(status, 0) <> 0', [$customer_id, $year])
->selectRaw('sum(barcode_cast) as apply_money,sum(apply2_money) as support_money')
->first();
$promotion = DB::table('promotion')
->whereRaw('customer_id=? and '.sql_year('actived_dt').'=? and isnull(is_close, 0) = 0 and isnull(status, 0) <> 0', [$customer_id, $year])
->selectRaw('sum(apply_fee) as apply_money,sum(undertake_money) as support_money')
->first();
$apply_money = $approach['apply_money'] + $promotion['apply_money'];
$support_money = $approach['support_money'] + $promotion['support_money'];
// 发货
$delivery = DB::table('stock_delivery_data as d')
->leftJoin('stock_delivery as m', 'm.id', '=', 'd.delivery_id')
->leftJoin('product', 'product.id', '=', 'd.product_id')
->whereRaw('m.customer_id=? and '.sql_year('m.invoice_dt').'=? and d.product_id <> 20226 and isnull(product.product_type, 0) = 1', [$customer_id, $year])
->selectRaw('sum(isnull(d.money, 0) - isnull(d.other_money, 0)) money');
// 退货
$cancel = DB::table('stock_cancel_data as d')
->leftJoin('stock_cancel as m', 'm.id', '=', 'd.cancel_id')
->leftJoin('product', 'product.id', '=', 'd.product_id')
->whereRaw('m.customer_id=? and '.sql_year('m.invoice_dt').'=? and d.product_id <> 20226 and isnull(product.product_type, 0) = 1', [$customer_id, $year])
->selectRaw('sum(isnull(d.money, 0) - isnull(d.other_money, 0)) money');
// 直营
$direct = DB::table('stock_direct_data as d')
->leftJoin('stock_direct as m', 'm.id', '=', 'd.direct_id')
->leftJoin('product', 'product.id', '=', 'd.product_id')
->whereRaw('m.customer_id=? and '.sql_year('m.invoice_dt').'=? and d.product_id <> 20226 and isnull(product.product_type, 0) = 1', [$customer_id, $year])
->selectRaw('sum(isnull(d.money, 0) - isnull(d.other_money, 0)) money');
$rows = $cancel->unionAll($delivery)->unionAll($direct)->get();
$money = $rows->sum('money');
$apply_percent = $support_percent = 0;
if ($money > 0) {
$apply_percent = ($apply_money / $money) * 100;
$support_percent = ($support_money / $money) * 100;
}
$all = [
'money' => $money,
'apply_money' => $apply_money,
'support_money' => $support_money,
'apply_percent' => $apply_percent,
'support_percent' => $support_percent,
];
return $this->render([
'all' => $all,
'query' => $query,
]);
}
// 批量编辑
public function batchEdit()
{
$gets = Request::all();
if (Request::method() == 'POST') {
$ids = explode(',', $gets['ids']);
DB::table('approach')->whereIn('id', $ids)->update([
$gets['field'] => $gets['search_0'],
]);
return $this->json('修改完成。', true);
}
$header = Grid::batchEdit([
'code' => 'approach',
'columns' => ['customer_id', 'tax_id'],
]);
return view('batchEdit', [
'gets' => $gets,
'header' => $header
]);
}
public function delete()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'approach', 'ids' => $ids]);
}
}
}

View File

@ -1,156 +0,0 @@
<?php namespace Gdoo\Approach\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\Approach\Models\ApproachMarket;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\Index\Controllers\DefaultController;
class MarketController extends DefaultController
{
public $permission = ['dialog'];
public function index()
{
// 客户权限
$region = regionCustomer('customer_id_customer');
$header = Grid::header([
'code' => 'approach_market',
'referer' => 1,
'search' => ['by' => ''],
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '编辑',
'action' => 'edit',
'display' => $this->access['edit'],
]];
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['cols'] = $cols;
$header['tabs'] = ApproachMarket::$tabs;
$header['bys'] = ApproachMarket::$bys;
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order']);
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
if ($region['authorise']) {
foreach ($region['whereIn'] as $key => $where) {
$model->whereIn($key, $where);
}
}
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
return Grid::dataFilters($rows, $header);
}
return $this->display([
'header' => $header,
]);
}
public function create($action = 'edit')
{
$id = (int) Request::get('id');
$header['action'] = $action;
$header['code'] = 'approach_market';
$header['id'] = $id;
$form = Form::make($header);
return $this->render([
'form' => $form,
], 'create');
}
public function edit()
{
return $this->create();
}
public function audit()
{
return $this->create('audit');
}
public function show()
{
return $this->create('show');
}
public function delete()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'approach_market', 'ids' => $ids]);
}
}
// 对话框
public function dialog()
{
$header = Grid::header([
'code' => 'approach_market',
]);
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table('approach_market');
if ($query['sort'] && $query['order']) {
$model->orderBy($query['sort'], $query['order']);
}
if (isset($query['customer_id'])) {
$model->where('approach_market.customer_id', $query['customer_id']);
}
if ($query['q']) {
$model->where('approach_market.name', 'like', '%'.$query['q'].'%');
}
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$sql = 'name as text,code,name,customer_id,market_count,type_id,single_cast,total_cast,fax,market_address,market_area,market_person_name,market_person_phone,status';
if ($query['related'] == '0') {
$sql = $sql.',name as id';
} else {
$sql = $sql.',id as id';
}
$model->selectRaw($sql);
$rows = $model->paginate();
return Grid::dataFilters($rows, $header);
}
}
}

View File

@ -1,165 +0,0 @@
<?php namespace Gdoo\Approach\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\User\Models\User;
use Gdoo\Approach\Models\ApproachReview;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\Index\Controllers\WorkflowController;
class ReviewController extends WorkflowController
{
public $permission = ['dialog', 'reference', 'useCount', 'feeDetail'];
public function index()
{
// 客户权限
$region = regionCustomer('customer_id_customer');
$header = Grid::header([
'code' => 'approach_review',
'referer' => 1,
'search' => ['by' => ''],
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '显示',
'action' => 'show',
'display' => $this->access['show'],
]];
$header['buttons'] = [
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['left_buttons'] = [
['name' => '批量编辑', 'color' => 'default', 'icon' => 'fa-pencil-square-o', 'action' => 'batchEdit', 'display' => $this->access['batchEdit']],
];
$header['cols'] = $cols;
$header['tabs'] = ApproachReview::$tabs;
$header['bys'] = ApproachReview::$bys;
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order']);
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
if ($region['authorise']) {
foreach ($region['whereIn'] as $key => $where) {
$model->whereIn($key, $where);
}
}
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
return Grid::dataFilters($rows, $header);
}
return $this->display([
'header' => $header,
]);
}
public function create($action = 'edit')
{
$id = (int) Request::get('id');
// 客户权限
$header['region'] = ['field' => 'customer_id'];
$header['authorise'] = ['action' => 'index', 'field' => 'created_id'];
$header['action'] = $action;
$header['code'] = 'approach_review';
$header['id'] = $id;
$header['joint'] = [
['name' => '申请单', 'action' => 'apply', 'field' => 'apply_id'],
['name' => '兑现明细', 'action' => 'cash_detail', 'field' => 'apply_id'],
];
$form = Form::make($header);
$tpl = $action == 'print' ? 'print' : 'create';
return $this->display([
'form' => $form,
], $tpl);
}
public function edit()
{
return $this->create();
}
public function audit()
{
return $this->create('audit');
}
public function show()
{
return $this->create('show');
}
public function print()
{
$this->layout = 'layouts.print_html';
return $this->create('print');
}
// 批量编辑
public function batchEdit()
{
$gets = Request::all();
if (Request::method() == 'POST') {
$ids = explode(',', $gets['ids']);
DB::table('approach_review')->whereIn('id', $ids)->update([
$gets['field'] => $gets['search_0'],
]);
return $this->json('修改完成。', true);
}
$header = Grid::batchEdit([
'code' => 'approach_review',
'columns' => ['customer_id', 'tax_id'],
]);
return view('batchEdit', [
'gets' => $gets,
'header' => $header
]);
}
// 兑现明细
public function feeDetail()
{
$query = Request::all();
if (Request::method() == 'POST') {
$rows = DB::table('approach_review')->where('apply_id', $query['id'])->orderBy('id', 'desc')->get();
return $this->json($rows, true);
}
return $this->render(['query' => $query]);
}
public function delete()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'approach_review', 'ids' => $ids]);
}
}
}

View File

@ -1,114 +0,0 @@
<?php namespace Gdoo\Approach\Hooks;
use DB;
use Gdoo\User\Models\User;
class ApproachHook
{
public function onBeforeForm($params) {
$views = $params['views'];
$view = $views[3];
$view['fields'][] = [
'field' => 'apply_percentage',
'hidden' => 1,
'width' => 40,
'readonly' => 0,
'hide_title' => 1,
'type' => 0,
'name' => '按回款核销(%)',
];
$view['fields'][] = [
'field' => 'order_payment_scale',
'hidden' => 1,
'width' => 40,
'readonly' => 0,
'hide_title' => 1,
'type' => 0,
'name' => '按订单进行兑付(%)',
];
$views[3] = $view;
$params['views'] = $views;
return $params;
}
public function onFieldFilter($params) {
$values = $params['values'];
$field = $params['field'];
$f = $field['field'];
$value = $values[$f];
if ($f == 'market_name') {
if (strpos($value, 'draft_') === 0) {
$name = str_replace('draft_', '', $value);
$market = [
'customer_id' => $values['customer_id'],
'name' => $name,
'market_count' => $values['market_totol'],
'type_id' => $values['type_id'],
'single_cast' => $values['single_cast'],
'total_cast' => $values['totol_cast'],
'fax' => $values['fax'],
'market_address' => $values['market_address'],
'market_area' => $values['market_size'],
'market_person_name' => $values['market_contact'],
'market_person_phone' => $values['market_contact_phone'],
];
$values['market_name'] = $name;
$values['market_id'] = DB::table('approach_market')->insertGetId($market);
}
}
$params['values'] = $values;
return $params;
}
public function onFormFieldFilter($params) {
$_replace = $params['_replace'];
$verification_info = $_replace['{verification_info}'];
if ($verification_info) {
$verification_info = $verification_info.'
<div class="m-xs">
贵司出具发票:按回款(回款以我司批复之日起算) '.$_replace['{apply_percentage}'].'% 核销;
贵司未出具发票:按订单(订单以提交审核资料核销后) '.$_replace['{order_payment_scale}'].'% 进行兑付。直到核完我司支持费用为止。
</div>
<div class="red">
客户进场后必须在2个月内提交资料核销否则不予受理。开始核销后超过一年未核完的将不再核销。
</div>
';
$_replace['{verification_info}'] = $verification_info;
unset($_replace['{apply_percentage}']);
unset($_replace['{order_payment_scale}']);
}
$params['_replace'] = $_replace;
return $params;
}
public function onAfterForm($params) {
return $params;
}
public function onBeforeAudit($params) {
// 流程结束写入生效日期
$master = $params['master'];
$master['actived_dt'] = date('Y-m-d');
$params['master'] = $master;
return $params;
}
public function onBeforeStore($params) {
return $params;
}
public function onAfterStore($params) {
return $params;
}
public function onBeforeDelete($params) {
return $params;
}
public function onBeforeImport($params) {
}
}

View File

@ -1,88 +0,0 @@
<?php namespace Gdoo\Approach\Hooks;
use DB;
use Gdoo\User\Models\User;
class ReviewHook
{
public function onBeforeForm($params) {
return $params;
}
public function onFieldFilter($params) {
return $params;
}
public function onFormFieldFilter($params) {
return $params;
}
public function onAfterForm($params) {
return $params;
}
public function onBeforeStore($params)
{
$gets = $params['gets'];
$approach_review = $gets['approach_review'];
$count = count($gets['approach_review_data']['rows']);
$apply_id = $approach_review['apply_id'];
$count2 = DB::table('approach_data')->where('approach_id', $apply_id)->count();
if ($count <> $count2) {
abort_error('进店申请条码数量和核销条码数量不一致。');
}
return $params;
}
public function onBeforeAudit($params) {
$id = $params['id'];
// 生效费用
$row = DB::table('approach_review')->where('id', $id)->first();
if ($row['use_order'] == 1) {
// 生成费用类型
$categorys = [1 => 4, 3 => 5];
$master = [
'sn' => $row['sn'],
'date' => $row['date'],
'category_id' => $categorys[$row['pay_type']],
'type_id' => 57,
'remark' => $row['remark'],
'status' => 1,
];
$cost_id = DB::table('customer_cost')->insertGetId($master);
DB::table('customer_cost_data')->insert([
'cost_id' => $cost_id,
'customer_id' => $row['customer_id'],
'money' => $row['fact_verification_cost'],
'remain_money' => $row['fact_verification_cost'],
'src_id' => $row['id'],
'src_sn' => $row['sn'],
'src_type_id' => 57,
'status' => 1,
]);
}
return $params;
}
public function onBeforeAbort($params) {
$id = $params['id'];
$review = DB::table('approach_review')->where('id', $id)->first();
$cost_count = DB::table('customer_cost')->where('sn', $review['sn'])->count();
if ($cost_count > 0) {
abort_error('客户费用单号['.$review['sn'].']已经存在无法弃审。');
}
return $params;
}
public function onAfterStore($params) {
return $params;
}
public function onBeforeDelete($params) {
// 删除生成的费用
return $params;
}
public function onBeforeImport($params) {
}
}

View File

@ -1,41 +0,0 @@
<?php namespace Gdoo\Approach\Models;
use Gdoo\Index\Models\BaseModel;
class Approach extends BaseModel
{
protected $table = 'approach';
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'approach', 'url' => 'approach/approach/index', 'name' => '进店列表'],
]
];
public static $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
public function customer()
{
return $this->belongsTo('Gdoo\Customer\Models\Customer');
}
public function datas()
{
return $this->hasMany('Gdoo\Promotion\Models\PromotionData');
}
public function scopeDialog($q, $value)
{
return $q->whereIn('id', $value)->pluck('sn', 'id');
}
}

View File

@ -1,8 +0,0 @@
<?php namespace Gdoo\Approach\Models;
use Gdoo\Index\Models\BaseModel;
class ApproachData extends BaseModel
{
protected $table = 'approach_data';
}

View File

@ -1,31 +0,0 @@
<?php namespace Gdoo\Approach\Models;
use Gdoo\Index\Models\BaseModel;
class ApproachMarket extends BaseModel
{
protected $table = 'approach_market';
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'market', 'url' => 'approach/market/index', 'name' => '超市列表'],
]
];
public static $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
public function customer()
{
return $this->belongsTo('Gdoo\Customer\Models\Customer');
}
}

View File

@ -1,26 +0,0 @@
<?php namespace Gdoo\Approach\Models;
use Gdoo\Index\Models\BaseModel;
class ApproachReview extends BaseModel
{
protected $table = 'approach_review';
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'review', 'url' => 'approach/review/index', 'name' => '进店核销'],
]
];
public static $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
}

View File

@ -1,15 +0,0 @@
<?php namespace Gdoo\Approach\Services;
use DB;
use Gdoo\Index\Services\BadgeService;
class ApproachService
{
/**
* 获取待办的进店申请
*/
public static function getBadge()
{
return BadgeService::getModelTodo('approach');
}
}

View File

@ -1,117 +0,0 @@
<?php
return [
"name" => "进店管理",
"version" => "1.0",
"description" => "条码进店。",
"listens" => [
'approach' => 'Gdoo\Approach\Hooks\ApproachHook',
'approach_review' => 'Gdoo\Approach\Hooks\ReviewHook',
],
'dialogs' => [
'approach' => [
'name' => '进店申请',
'model' => 'Gdoo\Approach\Models\Approach::Dialog',
'url' => 'approach/approach/dialog',
],
'approach_market' => [
'name' => '进店超市',
'model' => 'Gdoo\Approach\Models\ApproachMarket::Dialog',
'url' => 'approach/market/dialog',
],
],
'badges' => [
'approach_approach_index' => 'Gdoo\Approach\Services\ApproachService::getBadge',
],
"controllers" => [
"approach" => [
"name" => "进店申请",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"audit" => [
"name" => "审核"
],
"recall" => [
"name" => "撤回"
],
"abort" => [
"name" => "弃审"
],
"print" => [
"name" => "打印"
],
"delete" => [
"name" => "删除"
],
"close" => [
"name" => "关闭"
],
"batchEdit" => [
"name" => "批量编辑"
],
]
],
"review" => [
"name" => "进店核销",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"audit" => [
"name" => "审核"
],
"recall" => [
"name" => "撤回"
],
"abort" => [
"name" => "弃审"
],
"print" => [
"name" => "打印"
],
"delete" => [
"name" => "删除"
],
"batchEdit" => [
"name" => "批量编辑"
],
]
],
"market" => [
"name" => "进店超市",
"actions" => [
"index" => [
"name" => "列表"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"delete" => [
"name" => "删除"
],
]
]
]
];

View File

@ -1,176 +0,0 @@
<div class="form-panel">
<div class="form-panel-header">
<div class="pull-right">
</div>
{{$form['btn']}}
<a href="javascript:costDetailDialog();" class="btn btn-sm btn-default">
费用申请明细
</a>
@if($form['access']['close'])
<a href="javascript:closeDialog();" class="btn btn-sm btn-default">
关闭(打开)
</a>
@endif
</div>
<div class="form-panel-body panel-form-{{$form['action']}}">
<form class="form-horizontal form-controller" method="post" id="{{$form['table']}}" name="{{$form['table']}}">
{{$form['tpl']}}
</form>
</div>
</div>
<script>
var table = '{{$form["table"]}}';
var id = '{{$form["row"]["id"]}}';
var actived_dt = '{{$form["row"]["actived_dt"]}}';
var customer_id = '{{$form["row"]["customer_id"]}}';
function costDetailDialog() {
viewDialog({
title: '费用申请明细',
dialogClass: 'modal-md',
url: app.url('approach/approach/serviceCostDetail', {date: actived_dt, customer_id: customer_id}),
close: function() {
$(this).dialog("close");
}
});
}
function closeDialog() {
$.post(app.url('approach/approach/close'), {id: id}, function(res) {
toastrSuccess(res.data);
location.reload();
});
}
function get_customer_id() {
var customer_id = $('#approach_customer_id').val();
return customer_id;
}
function undertake_ratio() {
var v1 = $('#approach_barcode_cast').val();
var v2 = $('#approach_market_cast').val();
var v3 = (toNumber(v2) / toNumber(v1)) * 100;
$('#approach_barcode_cast_ratio').val(v3 > 100 ? 100 : v3.toFixed(2));
}
function undertake_ratio2() {
var v1 = $('#approach_barcode_cast').val();
var v2 = $('#approach_apply2_money').val();
var v3 = (toNumber(v2) / toNumber(v1)) * 100;
$('#approach_apply2_ratio').val(v3 > 100 ? 100 : v3.toFixed(2));
var v4 = $('#approach_apply_bccount').val();
var v5 = $('#approach_apply_market_count').val();
var v6 = (toNumber(v2) / toNumber(v4)) / toNumber(v5);
$('#approach_apply2_single_cast').val(toNumber(v6).toFixed(2));
}
function undertake_ratio3() {
var v1 = $('#approach_barcode_cast').val();
var v2 = $('#approach_apply_money').val();
var v3 = (toNumber(v2) / toNumber(v1)) * 100;
$('#approach_fee_support_ratio').val(v3 > 100 ? 100 : v3.toFixed(2));
}
(function($) {
$('#approach_barcode_cast,#approach_market_cast').bind('input propertychange', function() {
undertake_ratio();
undertake_ratio2();
});
$('#approach_apply2_money,#approach_apply_bccount,#approach_apply_market_count').bind('input propertychange', function() {
undertake_ratio();
undertake_ratio2();
});
$('#approach_apply_money').bind('input propertychange', function() {
undertake_ratio3();
});
$('#approach_field001').prop('checked', true);
$('#approach_field004').prop('checked', true);
})(jQuery);
// grid初始化事件
gdoo.event.set('grid.approach_data', {
ready(me) {
grid = me;
grid.dataKey = 'product_id';
},
editable: {
product_name(params) {
var customer_id = $('#approach_customer_id').val();
if (customer_id.trim() == '') {
toastrError('请先选择客户');
return false;
} else {
return true;
}
}
}
});
// 子表对话框
gdoo.event.set('approach_data.product_id', {
open(params) {
params.url = 'product/product/serviceCustomer';
},
query(query) {
var customer_id = $('#approach_customer_id').val();
query.customer_id = customer_id;
},
onSelect(row, selectedRow) {
row.price = selectedRow.price;
return true;
}
});
// 选择客户事件
gdoo.event.set('approach.customer_id', {
onSelect(row) {
if (row) {
$('#customer_region_region_id').val(row.region_id);
$('#customer_region_region_id_text').val(row.region_id_name || '');
$('#approach_phone').val(row.tel);
$('#approach_fax').val(row.fax);
return true;
}
}
});
// 选择超市事件
gdoo.event.set('approach.market_name', {
init(params) {
params.ajax.url = app.url('approach/market/dialog');
params.resultCache = false;
},
query(query) {
query.field_0 = 'approach_market.name';
var customer_id = $('#approach_customer_id').val();
query.customer_id = customer_id;
},
onSelect(row) {
if (row) {
$('#approach_market_fax').val(row.fax);
$('#approach_market_totol').val(row.market_count);
$('#approach_single_cast').val(row.single_cast);
$('#approach_totol_cast').val(row.total_cast);
$('#approach_market_size').val(row.market_area);
$('#approach_market_address').val(row.market_address);
$('#approach_market_contact').val(row.market_person_name);
$('#approach_market_contact_phone').val(row.market_person_phone);
$('#approach_market_type_id_select').val(row.type_id);
$('#approach_market_type_id').val(row.type_id);
return true;
}
}
});
</script>

View File

@ -1,137 +0,0 @@
<style>
.modal-body { overflow:hidden; }
</style>
<div class="wrapper-sm" style="padding-bottom:0;">
<div id="dialog-approach-toolbar">
<form id="dialog-approach-search-form" name="dialog_approach_search_form" class="form-inline" method="get">
@include('searchForm3')
</form>
</div>
</div>
<div class="m-t-sm">
<div id="ref_approach" class="ag-theme-balham" style="width:100%;height:140px;"></div>
</div>
<div class="m-t-sm">
<div id="ref_approach_data" class="ag-theme-balham" style="width:100%;height:240px;"></div>
</div>
<script>
var $ref_approach = null;
var $ref_approach_data = null;
var params = JSON.parse('{{json_encode($query)}}');
(function($) {
params['master'] = 1;
var mGridDiv = document.querySelector("#ref_approach");
var mGrid = new agGridOptions();
mGrid.remoteDataUrl = '{{url()}}';
var option = gdoo.formKey(params);
var event = gdoo.event.get(option.key);
event.trigger('query', params);
mGrid.remoteParams = params;
mGrid.rowMultiSelectWithClick = false;
mGrid.rowSelection = 'multiple';
mGrid.autoColumnsToFit = false;
mGrid.defaultColDef.suppressMenu = true;
mGrid.defaultColDef.sortable = false;
mGrid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, width: 40},
{cellClass:'text-center', field: 'sn', headerName: '单据编号', minWidth: 160},
{cellClass:'text-center', field: 'created_at', headerName: '单据日期', width: 120},
{cellClass:'text-center', field: 'status', cellRenderer: 'htmlCellRenderer', headerName: '状态', width: 160},
{cellClass:'text-center', field: 'customer_code', headerName: '客户编码', width: 120},
{field:'customer_name', headerName: '客户名称', width: 160},
{cellClass:'text-center',field:'region_name', headerName: '销售组', width: 120},
{cellClass:'text-right',field:'barcode_cast', headerName: '申请费用', width: 100},
{cellClass:'text-right',field:'apply2_money', headerName: '批复费用', width: 100},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
mGrid.onSelectionChanged = function() {
var rows = mGrid.api.getSelectedRows();
var ids = [];
for (let i = 0; i < rows.length; i++) {
ids.push(rows[i].id);
}
params.ids = ids;
sGrid.remoteData(params);
};
mGrid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
};
mGrid.onRowDoubleClicked = function (row) {
var ret = gdoo.dialogSelected(event, params, option, mGrid);
if (ret === true) {
$('#gdoo-dialog-' + params.dialog_index).dialog('close');
}
};
gdoo.dialogs[option.id] = mGrid;
new agGrid.Grid(mGridDiv, mGrid);
mGrid.remoteData();
$ref_approach = mGrid;
params['master'] = 0;
var sGridDiv = document.querySelector("#ref_approach_data");
var sGrid = new agGridOptions();
sGrid.remoteDataUrl = '{{url()}}';
sGrid.remoteParams = params;
sGrid.rowSelection = 'multiple';
sGrid.defaultColDef.suppressMenu = true;
sGrid.defaultColDef.sortable = false;
sGrid.suppressRowClickSelection = true;
sGrid.getRowClass = function(params) {
params.node.setSelected(true);
};
sGrid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, width: 40},
{cellClass:'text-center', field: 'product_code', headerName: '产品编码', width: 100},
{field: 'product_name', headerName: '商品名称', minWidth: 180},
{cellClass:'text-center', field: 'product_spec', headerName: '商品规格', width: 140},
{cellClass:'text-center', field: 'product_barcode', headerName: '商品条码', width: 120},
{cellClass:'text-center', field: 'product_unit', headerName: '计量单位', width: 80},
{cellClass:'text-right', field: 'price1', headerName: '报价', width: 80},
{cellClass:'text-right', field: 'price2', headerName: '售价', width: 80},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
sGrid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
};
new agGrid.Grid(sGridDiv, sGrid);
sGrid.remoteData();
$ref_approach_data = sGrid;
var data = JSON.parse('{{json_encode($search["forms"])}}');
var search = $('#dialog-approach-search-form').searchForm({
data: data
});
search.find('#search-submit').on('click', function() {
var query = search.serializeArray();
$.map(query, function(row) {
params[row.name] = row.value;
});
params['master'] = 1;
mGrid.remoteData(params);
params['master'] = 0;
sGrid.remoteData(params);
return false;
});
})(jQuery);
</script>

View File

@ -1,65 +0,0 @@
<div class="gdoo-list-page" id="{{$header['master_table']}}-page">
<div class="gdoo-list panel">
<div class="gdoo-list-header">
<gdoo-grid-header :header="header" :grid="grid" :action="action" />
</div>
<div class='gdoo-list-grid'>
<div id="{{$header['master_table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
</div>
<script>
Vue.createApp({
components: {
gdooGridHeader,
},
setup(props, ctx) {
var table = '{{$header["master_table"]}}';
var config = new gdoo.grid(table);
var grid = config.grid;
grid.remoteDataUrl = '{{url()}}';
var action = config.action;
// 详情页打开方式
action.dialogType = 'layer';
// 双击行执行的方法
action.rowDoubleClick = action.show;
action.fee_detail = function(data) {
viewDialog({
title: '兑现明细',
dialogClass: 'modal-md',
url: app.url('approach/review/feeDetail', {id: data.master_id}),
close: function() {
$(this).dialog("close");
}
});
}
action.product = function(data) {
viewDialog({
title: '产品明细',
dialogClass: 'modal-md',
url: app.url('approach/approach/product', {id: data.master_id}),
close: function() {
$(this).dialog("close");
}
});
}
var setup = config.setup;
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据
grid.remoteData({page: 1}, function(res) {
config.init(res);
});
});
return setup;
}
}).mount("#{{$header['master_table']}}-page");
</script>

View File

@ -1 +0,0 @@
{{$form['tpl']}}

View File

@ -1,32 +0,0 @@
<style>
.modal-body { overflow:hidden; }
</style>
<div id="approach_product" class="ag-theme-balham" style="width:100%;height:320px;"></div>
<script>
(function($) {
var gridDiv = document.querySelector("#approach_product");
var grid = new agGridOptions();
grid.remoteDataUrl = '{{url()}}';
var params = JSON.parse('{{json_encode($query)}}');
grid.remoteParams = params;
grid.rowMultiSelectWithClick = false;
grid.rowSelection = 'multiple';
// grid.autoColumnsToFit = false;
grid.defaultColDef.suppressMenu = true;
grid.defaultColDef.sortable = false;
grid.columnDefs = [
{cellClass:'text-center', headerName: '', type: 'sn', width: 40},
{cellClass:'text-left', field: 'name', headerName: '产品名称', minWidth: 140},
{cellClass:'text-center', field: 'spec', headerName: '规格型号', width: 100},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
new agGrid.Grid(gridDiv, grid);
grid.remoteData();
})(jQuery);
</script>

View File

@ -1,119 +0,0 @@
<style>
.modal-body { overflow:hidden; }
</style>
<div class="wrapper-sm" style="padding-bottom:0;">
<div id="dialog-approach-toolbar">
<form id="dialog-approach-search-form" name="dialog_approach_search_form" class="form-inline" method="get">
@include('searchForm3')
</form>
</div>
</div>
<div class="m-t-sm">
<div id="ref_approach" class="ag-theme-balham" style="width:100%;height:140px;"></div>
</div>
<div class="m-t-sm">
<div id="ref_approach_data" class="ag-theme-balham" style="width:100%;height:240px;"></div>
</div>
<script>
var $ref_approach = null;
var $ref_approach_data = null;
var params = JSON.parse('{{json_encode($query)}}');
(function($) {
params['master'] = 1;
var mGridDiv = document.querySelector("#ref_approach");
var mGrid = new agGridOptions();
mGrid.remoteDataUrl = '{{url()}}';
mGrid.remoteParams = params;
mGrid.rowSelection = 'multiple';
mGrid.autoColumnsToFit = false;
mGrid.rowMultiSelectWithClick = false;
mGrid.defaultColDef.suppressMenu = true;
mGrid.defaultColDef.sortable = false;
mGrid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, width: 40},
{cellClass:'text-center', field: 'sn', headerName: '促销编号', minWidth: 160},
{cellClass:'text-center', field: 'created_at', type: 'datetime', headerName: '单据日期', width: 120},
{cellClass:'text-center', field: 'status', headerName: '状态', width: 160},
{cellClass:'text-center', field: 'customer_code', headerName: '客户编码', width: 160},
{field:'customer_name', headerName: '客户名称', width: 160},
{field:'warehouse_contact', headerName: '收货人', width: 160},
{field:'warehouse_phone', headerName: '收货人电话', width: 160},
{field:'warehouse_address', headerName: '收货地址', width: 260},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
mGrid.onSelectionChanged = function() {
var rows = mGrid.api.getSelectedRows();
var ids = [];
for (let i = 0; i < rows.length; i++) {
ids.push(rows[i].id);
}
params.ids = ids;
sGrid.remoteData(params);
};
new agGrid.Grid(mGridDiv, mGrid);
mGrid.remoteData();
$ref_approach = mGrid;
params['master'] = 0;
var sGridDiv = document.querySelector("#ref_approach_data");
var sGrid = new agGridOptions();
sGrid.remoteDataUrl = '{{url()}}';
sGrid.remoteParams = params;
sGrid.rowSelection = 'multiple';
sGrid.autoColumnsToFit = false;
sGrid.defaultColDef.suppressMenu = true;
sGrid.defaultColDef.sortable = false;
sGrid.suppressRowClickSelection = true;
sGrid.getRowClass = function(params) {
var data = params.data;
params.node.setSelected(true);
};
sGrid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, width: 40},
{cellClass:'text-center', field: 'product_code', headerName: '存货编码', width: 100},
{field: 'product_name', headerName: '商品名称', minWidth: 180},
{cellClass:'text-center', field: 'product_spec', headerName: '商品规格', width: 140},
{cellClass:'text-center', field: 'unit_name', headerName: '计量单位', width: 80},
{cellClass:'text-center', field: 'discount_rate', headerName: '现存量', width: 80},
{cellClass:'text-right', field: 'total_quantity', headerName: '促销数量', width: 80},
{cellClass:'text-right', field: 'use_quantity', headerName: '已发数量', width: 80},
{cellClass:'text-right', field: 'quantity', headerName: '可用数量', width: 80},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
sGrid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
};
new agGrid.Grid(sGridDiv, sGrid);
sGrid.remoteData();
$ref_approach_data = sGrid;
var data = JSON.parse('{{json_encode($search["forms"])}}');
var search = $('#dialog-approach-search-form').searchForm({
data: data,
init:function(e) {}
});
search.find('#search-submit').on('click', function() {
var query = search.serializeArray();
$.map(query, function(row) {
params[row.name] = row.value;
});
params['master'] = 1;
mGrid.remoteData(params);
params['master'] = 0;
sGrid.remoteData(params);
return false;
});
})(jQuery);
</script>

View File

@ -1,121 +0,0 @@
<style>
.modal-body { overflow:hidden; }
.service-cost-detail .control-label {
padding-top: 11px;
text-align: right;
}
.service-cost-detail .form-group:first-child .col-xs-3:nth-child(3),
.service-cost-detail .form-group:first-child .col-xs-3:nth-child(4) {
border-top: 0 !important;
}
.service-cost-detail .ag-theme-balham .ag-root-wrapper {
border-left-width: 1px;
border-right-width: 1px;
}
</style>
<div class="service-cost-detail">
<div class="form-controller">
<div class="form-group">
<div class="col-xs-3 col-sm-2 control-label">费用合计</div>
<div class="col-xs-3 col-sm-2 control-text"><div class="form-control input-sm">@number($all['apply_money'], 2)</div></div>
<div class="col-xs-3 col-sm-2 control-label">支持合计</div>
<div class="col-xs-3 col-sm-2 control-text"><div class="form-control input-sm">@number($all['support_money'], 2)</div></div>
<div class="col-xs-3 col-sm-2 control-label">年度销售额</div>
<div class="col-xs-3 col-sm-2 control-text"><div class="form-control input-sm">@number($all['money'], 2)</div></div>
</div>
<div class="form-group">
<div class="col-xs-3 col-sm-2 control-label">申请产出比(%)</div>
<div class="col-xs-3 col-sm-2 control-text"><div class="form-control input-sm">@number($all['support_percent'], 2)</div></div>
<div class="col-xs-3 col-sm-2 control-label">兑现产出比(%)</div>
<div class="col-xs-3 col-sm-2 control-text"><div class="form-control input-sm">@number($all['apply_percent'], 2)</div></div>
<div class="col-xs-3 col-sm-2 control-label"></div>
<div class="col-xs-3 col-sm-2 control-text"></div>
</div>
</div>
<div class="clearfix"></div>
<div class="tabs-box">
<ul class="nav nav-tabs">
<li class="active">
<a class="text-sm" href="#tab_a" data-toggle="tab">促销</a>
</li>
<li>
<a class="text-sm" href="#tab_b" data-toggle="tab">进店</a>
</li>
<li>
<a class="text-sm" href="#tab_c" data-toggle="tab">物资</a>
</li>
</ul>
<div id="tab_ontent" class="tab-content" style="padding:5px;">
<div class="tab-pane active" id="tab_a">
<div id="ref_tab_a" class="ag-theme-balham" style="width:100%;height:280px;"></div>
</div>
<div class="tab-pane" id="tab_b">
<div id="ref_tab_b" class="ag-theme-balham" style="width:100%;height:280px;"></div>
</div>
<div class="tab-pane" id="tab_c">
<div id="ref_tab_c" class="ag-theme-balham" style="width:100%;height:280px;"></div>
</div>
</div>
</div>
</div>
<script>
var params = JSON.parse('{{json_encode($query)}}');
(function($) {
var tabDiv = document.querySelector("#ref_tab_a");
var grid = new agGridOptions();
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = params;
grid.rowSelection = 'single';
grid.defaultColDef.suppressMenu = true;
grid.defaultColDef.sortable = false;
grid.columnDefs = [
{cellClass:'text-center', field: 'start_dt', headerName: '开始日期', width: 100},
{cellClass:'text-center', field: 'end_dt', headerName: '结束日期', width: 100},
{cellClass:'text-center', field: 'promote_scope', headerName: '超市', minWidth: 160},
//{cellClass:'text-center', field: 'created_at', headerName: '促销方式', width: 100},
{cellClass:'text-right',field:'pro_total_cost', headerName: '总费用', width: 100},
{cellClass:'text-right',field:'undertake_money', headerName: '支持费用', width: 100}
];
new agGrid.Grid(tabDiv, grid);
grid.remoteData({type: 'promotion'});
var tabDiv2 = document.querySelector("#ref_tab_b");
var grid2 = new agGridOptions();
grid2.remoteDataUrl = '{{url()}}';
grid2.remoteParams = params;
grid2.rowSelection = 'single';
grid2.defaultColDef.suppressMenu = true;
grid2.defaultColDef.sortable = false;
grid2.columnDefs = [
{cellClass:'text-center', field: 'created_at', type: 'date', headerName: '申请日期', width: 120},
{cellClass:'text-center', field: 'market_name', headerName: '超市名称', minWidth: 160},
{cellClass:'text-right',field:'barcode_cast', headerName: '总费用', width: 140},
{cellClass:'text-right',field:'apply2_money', headerName: '支持费用', width: 140}
];
new agGrid.Grid(tabDiv2, grid2);
grid2.remoteData({type: 'approach'});
var tabDiv3 = document.querySelector("#ref_tab_c");
var grid3 = new agGridOptions();
grid3.remoteDataUrl = '{{url()}}';
grid3.remoteParams = params;
grid3.rowSelection = 'single';
grid3.defaultColDef.suppressMenu = true;
grid3.defaultColDef.sortable = false;
grid3.columnDefs = [
{cellClass:'text-center', field: 'created_at', type: 'date', headerName: '申请日期', minWidth: 120},
{cellClass:'text-right',field:'pro_total_cost', headerName: '总费用', width: 140},
{cellClass:'text-right',field:'undertake_money', headerName: '支持费用', width: 140}
];
new agGrid.Grid(tabDiv3, grid3);
grid3.remoteData({type: 'material'});
})(jQuery);
</script>

View File

@ -1,132 +0,0 @@
<style>
.modal-body { overflow:hidden; }
</style>
<div class="wrapper-xs">
<div id="dialog-approach-toolbar">
<form id="dialog-approach-search-form" name="dialog_approach_search_form" class="form-inline" method="get">
@include('searchForm3')
</form>
</div>
</div>
<div id="ref_approach" class="ag-theme-balham" style="width:100%;height:140px;"></div>
<div class="m-t-xs">
<div id="ref_approach_data" class="ag-theme-balham" style="width:100%;height:240px;"></div>
</div>
<script>
var $ref_approach = null;
var $ref_approach_data = null;
var params = JSON.parse('{{json_encode($query)}}');
(function($) {
params['master'] = 1;
var mGrid = new agGridOptions();
mGrid.remoteDataUrl = '{{url()}}';
var option = gdoo.formKey(params);
var event = gdoo.event.get(option.key);
event.trigger('query', params);
mGrid.remoteParams = params;
mGrid.rowSelection = 'single';
mGrid.autoColumnsToFit = false;
mGrid.defaultColDef.suppressMenu = true;
mGrid.defaultColDef.sortable = false;
mGrid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, width: 40},
{cellClass:'text-center', field: 'sn', headerName: '单据编号', minWidth: 160},
{cellClass:'text-center', field: 'created_at', headerName: '单据日期', width: 120},
{cellClass:'text-center', field: 'status', cellRenderer: 'htmlCellRenderer', headerName: '状态', width: 160},
{cellClass:'text-center', field: 'customer_code', headerName: '客户编码', width: 120},
{field:'customer_name', headerName: '客户名称', width: 160},
{cellClass:'text-center',field:'region_name', headerName: '销售组', width: 120},
{cellClass:'text-right',field:'barcode_cast', headerName: '申请费用', width: 100},
{cellClass:'text-right',field:'apply2_money', headerName: '批复费用', width: 100},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
mGrid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
var rows = mGrid.api.getSelectedRows();
var ids = [];
for (let i = 0; i < rows.length; i++) {
ids.push(rows[i].id);
}
params.ids = ids;
sGrid.remoteData(params);
};
mGrid.onRowDoubleClicked = function (row) {
var ret = gdoo.dialogSelected(event, params, option, mGrid);
if (ret == true) {
$('#gdoo-dialog-' + params.dialog_index).dialog('close');
}
};
$ref_approach = mGrid;
gdoo.dialogs[option.id] = mGrid;
var mGridDiv = document.querySelector("#ref_approach");
new agGrid.Grid(mGridDiv, mGrid);
mGrid.remoteData();
params['master'] = 0;
var sGridDiv = document.querySelector("#ref_approach_data");
var sGrid = new agGridOptions();
sGrid.remoteDataUrl = '{{url()}}';
sGrid.remoteParams = params;
sGrid.rowSelection = 'multiple';
sGrid.defaultColDef.suppressMenu = true;
sGrid.defaultColDef.sortable = false;
sGrid.suppressRowClickSelection = true;
sGrid.getRowClass = function(params) {
params.node.setSelected(true);
};
sGrid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, width: 40},
{cellClass:'text-center', field: 'product_code', headerName: '产品编码', width: 100},
{field: 'product_name', headerName: '商品名称', minWidth: 180},
{cellClass:'text-center', field: 'product_spec', headerName: '商品规格', width: 140},
{cellClass:'text-center', field: 'product_barcode', headerName: '商品条码', width: 120},
{cellClass:'text-center', field: 'product_unit', headerName: '计量单位', width: 80},
{cellClass:'text-right', field: 'price1', headerName: '报价', width: 80},
{cellClass:'text-right', field: 'price2', headerName: '售价', width: 80},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
sGrid.onRowClicked = function(row) {
var selected = row.node.isSelected();
if (selected === false) {
row.node.setSelected(true, true);
}
};
$ref_approach_data = sGrid;
new agGrid.Grid(sGridDiv, sGrid);
sGrid.remoteData();
var data = JSON.parse('{{json_encode($search["forms"])}}');
var search = $('#dialog-approach-search-form').searchForm({
data: data,
init:function(e) {}
});
search.find('#search-submit').on('click', function() {
var query = search.serializeArray();
$.map(query, function(row) {
params[row.name] = row.value;
});
params['master'] = 1;
mGrid.remoteData(params);
params['master'] = 0;
sGrid.remoteData(params);
return false;
});
})(jQuery);
</script>

View File

@ -1,3 +0,0 @@
<form class="form-horizontal form-controller" method="post" id="{{$form['table']}}" name="{{$form['table']}}">
{{$form['tpl']}}
</form>

View File

@ -1,106 +0,0 @@
<style>
.modal-body { overflow:hidden; }
</style>
<div class="wrapper-sm" style="padding-bottom:0;">
<div id="dialog-approach-toolbar">
<form id="dialog-approach-search-form" name="dialog_approach_search_form" class="form-inline" method="get">
@include('searchForm3')
</form>
</div>
</div>
<div class="m-t-sm">
<div id="ref_approach" class="ag-theme-balham" style="width:100%;height:140px;"></div>
</div>
<div class="m-t-sm">
<div id="ref_approach_data" class="ag-theme-balham" style="width:100%;height:240px;"></div>
</div>
<script>
var $ref_approach = null;
var $ref_approach_data = null;
var params = JSON.parse('{{json_encode($query)}}');
(function($) {
params['master'] = 1;
var mGridDiv = document.querySelector("#ref_approach");
var mGrid = new agGridOptions();
mGrid.remoteDataUrl = '{{url()}}';
mGrid.remoteParams = params;
mGrid.rowMultiSelectWithClick = false;
mGrid.rowSelection = 'multiple';
mGrid.autoColumnsToFit = false;
mGrid.defaultColDef.suppressMenu = true;
mGrid.defaultColDef.sortable = false;
mGrid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, width: 40},
{cellClass:'text-center', field: 'sn', headerName: '促销编号', minWidth: 160},
{cellClass:'text-center', field: 'created_at', type: 'datetime', headerName: '单据日期', width: 120},
{cellClass:'text-center', field: 'status', headerName: '状态', width: 160},
{cellClass:'text-center', field: 'customer_code', headerName: '客户编码', width: 160},
{field:'customer_name', headerName: '客户名称', width: 160},
{field:'warehouse_contact', headerName: '收货人', width: 160},
{field:'warehouse_phone', headerName: '收货人电话', width: 160},
{field:'warehouse_address', headerName: '收货地址', width: 260},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
mGrid.onSelectionChanged = function() {
var rows = mGrid.api.getSelectedRows();
var ids = [];
for (let i = 0; i < rows.length; i++) {
ids.push(rows[i].id);
}
params.approach_ids = ids;
sGrid.remoteData(params);
};
new agGrid.Grid(mGridDiv, mGrid);
mGrid.remoteData();
$ref_approach = mGrid;
params['master'] = 0;
var sGridDiv = document.querySelector("#ref_approach_data");
var sGrid = new agGridOptions();
sGrid.remoteDataUrl = '{{url()}}';
sGrid.remoteParams = params;
sGrid.rowSelection = 'multiple';
sGrid.autoColumnsToFit = false;
sGrid.defaultColDef.suppressMenu = true;
sGrid.defaultColDef.sortable = false;
sGrid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, width: 40},
{cellClass:'text-center', field: 'product_code', headerName: '存货编码', width: 100},
{field: 'product_name', headerName: '商品名称', minWidth: 180},
{cellClass:'text-center', field: 'product_spec', headerName: '商品规格', width: 140},
{cellClass:'text-center', field: 'unit_name', headerName: '计量单位', width: 80},
{cellClass:'text-center', field: 'discount_rate', headerName: '现存量', width: 80},
{cellClass:'text-right', field: 'total_quantity', headerName: '促销数量', width: 80},
{cellClass:'text-right', field: 'use_quantity', headerName: '已发数量', width: 80},
{cellClass:'text-right', field: 'quantity', headerName: '可用数量', width: 80},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
new agGrid.Grid(sGridDiv, sGrid);
sGrid.remoteData();
$ref_approach_data = sGrid;
var data = JSON.parse('{{json_encode($search["forms"])}}');
var search = $('#dialog-approach-search-form').searchForm({
data: data,
init:function(e) {}
});
search.find('#search-submit').on('click', function() {
var query = search.serializeArray();
$.map(query, function(row) {
params[row.name] = row.value;
});
params['master'] = 1;
mGrid.remoteData(params);
params['master'] = 0;
sGrid.remoteData(params);
return false;
});
})(jQuery);
</script>

View File

@ -1,42 +0,0 @@
<div class="gdoo-list-page" id="{{$header['master_table']}}-page">
<div class="gdoo-list panel">
<div class="gdoo-list-header">
<gdoo-grid-header :header="header" :grid="grid" :action="action" />
</div>
<div class='gdoo-list-grid'>
<div id="{{$header['master_table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
</div>
<script>
Vue.createApp({
components: {
gdooGridHeader,
},
setup(props, ctx) {
var table = '{{$header["master_table"]}}';
var config = new gdoo.grid(table);
var grid = config.grid;
grid.remoteDataUrl = '{{url()}}';
grid.autoColumnsToFit = true;
var action = config.action;
// 双击行执行的方法
action.rowDoubleClick = action.edit;
var setup = config.setup;
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据
grid.remoteData({page: 1}, function(res) {
config.init(res);
});
});
return setup;
}
}).mount("#{{$header['master_table']}}-page");
</script>

View File

@ -1,120 +0,0 @@
<div class="form-panel">
<div class="form-panel-header">
<div class="pull-right">
</div>
{{$form['btn']}}
</div>
<div class="form-panel-body panel-form-{{$form['action']}}">
<form class="form-horizontal form-controller" method="post" id="{{$form['table']}}" name="{{$form['table']}}">
{{$form['tpl']}}
</form>
</div>
</div>
<script>
var table = '{{$form["table"]}}';
var grid = null;
function get_customer_id() {
var customer_id = $('#approach_review_customer_id').val();
return customer_id;
}
$(function($) {
$(document).on('click', '[data-toggle="joint"]', function(event) {
var data = $(this).data();
// 联查进店申请
if (data.action == 'apply') {
top.addTab('approach/approach/show?id=' + data.id, 'approach_approach_show', '进店申请(联查)');
}
// 联查费用明细
if (data.action == 'cash_detail') {
viewDialog({
title: '兑现明细',
dialogClass: 'modal-md',
url: app.url('approach/review/feeDetail', {id: data.id}),
close: function() {
$(this).dialog("close");
}
});
}
});
});
// grid初始化事件
gdoo.event.set('grid.approach_review_data', {
ready(me) {
grid = me;
grid.dataKey = 'product_id';
},
editable: {
product_name(params) {
var approach_id = $('#approach_review_approach_id').val();
if (approach_id.trim() == '') {
toastrError('请先选择申请编号');
return false;
} else {
return true;
}
}
}
});
// 子表对话框
gdoo.event.set('approach_review_data.product_id', {
open(params) {
params.url = 'product/product/serviceCustomer';
},
query(query) {
var customer_id = $('#approach_review_customer_id').val();
query.customer_id = customer_id;
},
onSelect(row, selectedRow) {
return true;
}
});
$(function() {
$('#approach_review_pay_type').on('change', function() {
if (this.value == 1 || this.value == 3) {
$('#approach_review_use_order').val(1);
} else {
$('#approach_review_use_order').val(0);
}
});
});
// 进场核销申请编号
gdoo.event.set('approach_review.apply_id', {
open(params) {
params.url = 'approach/approach/serviceReview';
},
query(query) {
},
onSelect() {
var approach = $ref_approach.api.getSelectedRows()[0];
var rows = $ref_approach_data.api.getSelectedRows();
$('#approach_review_apply_id').val(approach.id);
$('#approach_review_apply_id_text').val(approach.sn);
$('#approach_review_apply_dt').val(approach.created_at);
$('#approach_review_apply_money').val(approach.apply2_money);
$('#approach_review_verification_cost').val(approach.apply2_money);
$('#approach_review_fact_verification_cost').val(approach.apply2_money);
$('#approach_review_market_name').val(approach.market_name);
$('#approach_review_customer_id').val(approach.customer_id);
$('#approach_review_customer_id_text').val(approach.customer_name);
$('#customer_region_region_id').val(approach.region_id);
$('#customer_region_region_id_text').val(approach.region_name);
grid.api.setRowData([]);
for (let i = 0; i < rows.length; i++) {
var row = rows[i];
row.is_store = 1;
grid.api.memoryStore.create(row);
}
return true;
}
});
</script>

View File

@ -1,32 +0,0 @@
<style>
.modal-body { overflow:hidden; }
</style>
<div id="approach_fee_detail" class="ag-theme-balham" style="width:100%;height:280px;"></div>
<script>
(function($) {
var gridDiv = document.querySelector("#approach_fee_detail");
var grid = new agGridOptions();
grid.remoteDataUrl = '{{url()}}';
var params = JSON.parse('{{json_encode($query)}}');
grid.remoteParams = params;
grid.rowMultiSelectWithClick = false;
grid.rowSelection = 'multiple';
grid.defaultColDef.suppressMenu = true;
grid.defaultColDef.sortable = false;
grid.columnDefs = [
{cellClass:'text-center', headerName: '', type: 'sn', width: 40},
{cellClass:'text-center', field: 'sn', headerName: '单据编号', minWidth: 140},
{cellClass:'text-center', field: 'date', headerName: '兑现日期', width: 100},
{cellClass:'text-right', field:'verification_cost', headerName: '兑现金额', width: 100},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
new agGrid.Grid(gridDiv, grid);
grid.remoteData();
})(jQuery);
</script>

View File

@ -1,42 +0,0 @@
<div class="gdoo-list-page" id="{{$header['master_table']}}-page">
<div class="gdoo-list panel">
<div class="gdoo-list-header">
<gdoo-grid-header :header="header" :grid="grid" :action="action" />
</div>
<div class='gdoo-list-grid'>
<div id="{{$header['master_table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
</div>
<script>
Vue.createApp({
components: {
gdooGridHeader,
},
setup(props, ctx) {
var table = '{{$header["master_table"]}}';
var config = new gdoo.grid(table);
var grid = config.grid;
grid.remoteDataUrl = '{{url()}}';
var action = config.action;
action.dialogType = 'layer';
// 双击行执行的方法
action.rowDoubleClick = action.edit;
var setup = config.setup;
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据
grid.remoteData({page: 1}, function(res) {
config.init(res);
});
});
return setup;
}
}).mount("#{{$header['master_table']}}-page");
</script>

View File

@ -1 +0,0 @@
{{$form['tpl']}}

View File

@ -22,6 +22,7 @@ class WidgetController extends DefaultController
->orderBy('created_at', 'desc');
$rows = $model->limit(15)->get(['id', 'name', 'created_at']);
$json['total'] = sizeof($rows);
$json['data'] = $rows;
return $json;
@ -44,7 +45,7 @@ class WidgetController extends DefaultController
->whereRaw('article_reader.article_id = article.id')
->where('article_reader.created_id', auth()->id());
})->whereRaw('('.$config['sql'].')')->count();
$count2 = DB::table('article')
->permission('receive_id')
->whereNotExists(function ($q) {
@ -56,18 +57,14 @@ class WidgetController extends DefaultController
$rate = 0;
if ($count2 > 0) {
$rate = $count / $count2 * 100;
$rate = ($count - $count2) / $count2 * 100;
$rate = number_format($rate, 2);
}
$res = [
'count' => $count,
'count2' => $count2,
'rate' => $rate,
];
return $this->render([
'dates' => $config['dates'],
'info' => $config['info'],
'res' => $res,
]);
return $this->json($res, true);
}
}

View File

@ -8,17 +8,11 @@ return [
],
'widgets' => [
'widget_article_index' => [
'name' => '新公告',
'name' => '公告',
'type' => 1,
'url' => 'article/widget/index',
'more_url' => 'article/article/index',
],
'info_article_index' => [
'name' => '未读公告',
'type' => 2,
'url' => 'article/widget/info',
'more_url' => 'article/article/index',
],
],
'badges' => [
'article_article_index' => 'Gdoo\Article\Services\ArticleService::getBadge',

View File

@ -1,15 +0,0 @@
<div class="panel panel-shadow info-skin1">
<div class="info-l hidden-xs" style="background-color:{{$info['color']}}">
<i class="fa fa-2x {{$info['icon']}}"></i>
</div>
<div class="info-c">
<div class="info-name">{{$info['name']}}</div>
<a href="javascript:;" data-toggle="addtab" data-url="{{$info['more_url']}}" data-id="{{str_replace(['/', '?', '='], ['_', '_', '_'], $info['more_url'])}}" data-name="{{$info['name']}}">
<div class="text-info info-item" data-id="{{$info['id']}}" data-more_url="{{$info['more_url']}}">{{$res['count']}}</div>
</a>
</div>
<div class="info-r">
<div>{{$dates[$info['params']['date']]}}</div>
<div class="rate @if($res['rate'] > 100) red @endif">{{$res['rate']}}%</div>
</div>
</div>

View File

@ -58,16 +58,16 @@ class CalendarController extends DefaultController
$url = url('event/index', ['calendar_id'=>$calendar['id']]);
}
$sources[] = [
'url' => $url,
'id' => $calendar['id'],
'userid' => $calendar['userid'],
'url' => $url,
'id' => $calendar['id'],
'userid' => $calendar['userid'],
'backgroundColor' => $calendar['calendarcolor'],
"borderColor" => $calendar['calendarcolor'],
"borderColor" => $calendar['calendarcolor'],
];
}
return $this->json([
'calendars' => $calendars,
'sources' => $sources,
'sources' => $sources,
], true);
}

View File

@ -17,7 +17,7 @@ use Illuminate\Support\Arr;
class EventController extends DefaultController
{
public $permission = ['share', 'items'];
public $permission = ['data'];
// 事件列表
public function index()
@ -60,8 +60,8 @@ class EventController extends DefaultController
return $events;
}
// 客户端显示事件列表
public function items()
// 客户端获取数据
public function data()
{
$gets = Request::all();
$start = strtotime($gets['start']);
@ -89,7 +89,7 @@ class EventController extends DefaultController
],
];
$repeat = CalendarObjectService::getEventRepeat($master, '1D', 'Y-n-j');
$repeat = CalendarObjectService::getEventRepeat($master, '1D', 'Y-m-d');
$items = array_merge($items, $repeat);
}
@ -117,7 +117,7 @@ class EventController extends DefaultController
'name' => $row['displayname'],
],
];
$repeat = CalendarObjectService::getEventRepeat($master, '1D', 'Y-n-j');
$repeat = CalendarObjectService::getEventRepeat($master, '1D', 'Y-m-d');
$items = array_merge($items, $repeat);
}
return $items;
@ -148,7 +148,7 @@ class EventController extends DefaultController
$vevent->setDateTime('LAST-MODIFIED', 'now', \Sabre\VObject\Property\DateTime::UTC);
$vevent->setDateTime('DTSTAMP', 'now', \Sabre\VObject\Property\DateTime::UTC);
CalendarService::edit($gets['id'], $vcalendar->serialize());
CalendarService::edit($gets, $vcalendar);
$lastmodified = $vevent->__get('LAST-MODIFIED')->getDateTime();
return $this->json(['lastmodified' => $lastmodified->format('U')], true);
@ -195,7 +195,7 @@ class EventController extends DefaultController
$vevent->setDateTime('DTSTAMP', 'now', \Sabre\VObject\Property\DateTime::UTC);
try {
CalendarService::edit($gets['id'], $vcalendar->serialize());
CalendarService::edit($gets, $vcalendar);
} catch (\Exception $e) {
return $this->json($e->getMessage());
}
@ -216,18 +216,10 @@ class EventController extends DefaultController
$vcalendar = CalendarService::createVCalendarFromRequest($gets);
try {
$attachment = join(',', array_filter((array)$gets['attachment']));
$id = CalendarService::add($gets['calendarid'], $vcalendar->serialize(), $attachment);
$id = CalendarService::add($gets, $vcalendar);
AttachmentService::publish($gets['attachment']);
// 写入共享数据
ShareService::addItem(array(
'source_id' => $id,
'source_type' => 'event',
'receive_id' => $gets['receive_id'],
'receive_name' => $gets['receive_name'],
));
return $this->json(['id'=>$id], true);
return $this->json(['id' => $id], true);
} catch (\Exception $e) {
return $this->json($e->getMessage());
}
@ -316,27 +308,9 @@ class EventController extends DefaultController
CalendarService::updateVCalendarFromRequest($gets, $vcalendar);
try {
$attachment = join(',', array_filter((array)$gets['attachment']));
CalendarService::edit($gets['id'], $vcalendar->serialize(), $attachment);
CalendarService::edit($gets, $vcalendar);
AttachmentService::publish($gets['attachment']);
$start_at = strtotime($gets['from'].' '.$gets['fromtime']);
$end_at = strtotime($gets['to'].' '.$gets['totime']);
$share_data = array(
'source_id' => $gets['id'],
'source_type' => 'event',
'receive_id' => $gets['receive_id'],
'receive_name' => $gets['receive_name'],
'start_at' => $start_at,
'end_at' => $end_at,
);
$share = ShareService::getItem('event', $gets['id']);
if (empty($share)) {
ShareService::addItem($share_data);
} else {
ShareService::editItem('event', $gets['id'], $share_data);
}
} catch (\Exception $e) {
return $this->json($e->getMessage());
}
@ -352,254 +326,252 @@ class EventController extends DefaultController
}
// 新增表单
if (Request::method() == 'GET') {
$event = CalendarService::getEvent($gets['id']);
$event = CalendarService::getEvent($gets['id']);
if (empty($event)) {
return $this->json('事件数据不正确。');
}
$object = VObject::parse($event['calendardata']);
$vevent = $object->VEVENT;
$dtstart = $vevent->DTSTART;
$dtend = CalendarService::getDTEndFromVEvent($vevent);
switch ($dtstart->getDateType()) {
case \Sabre\VObject\Property\DateTime::UTC:
$timezone = new \DateTimeZone(CalendarService::getTimezone());
$newDT = $dtstart->getDateTime();
$newDT->setTimezone($timezone);
$dtstart->setDateTime($newDT);
$newDT = $dtend->getDateTime();
$newDT->setTimezone($timezone);
$dtend->setDateTime($newDT);
// no break
case \Sabre\VObject\Property\DateTime::LOCALTZ:
case \Sabre\VObject\Property\DateTime::LOCAL:
$startdate = $dtstart->getDateTime()->format('Y-m-d');
$starttime = $dtstart->getDateTime()->format('H:i');
$enddate = $dtend->getDateTime()->format('Y-m-d');
$endtime = $dtend->getDateTime()->format('H:i');
$allday = false;
break;
case \Sabre\VObject\Property\DateTime::DATE:
$startdate = $dtstart->getDateTime()->format('Y-m-d');
$starttime = '';
$dtend->getDateTime()->modify('-1 day');
$enddate = $dtend->getDateTime()->format('Y-m-d');
$endtime = '';
$allday = true;
break;
}
$summary = strtr($vevent->getAsString('SUMMARY'), array('\,' => ',', '\;' => ';'));
$location = strtr($vevent->getAsString('LOCATION'), array('\,' => ',', '\;' => ';'));
$description = strtr($vevent->getAsString('DESCRIPTION'), array('\,' => ',', '\;' => ';'));
$categories = $vevent->getAsString('CATEGORIES');
if ($vevent->VALARM) {
$valarm = $vevent->VALARM->getAsString('TRIGGER');
}
if ($vevent->RRULE) {
$rrule = explode(';', $vevent->getAsString('RRULE'));
$rrulearr = array();
foreach ($rrule as $rule) {
list($attr, $val) = explode('=', $rule);
$rrulearr[$attr] = $val;
}
if (!isset($rrulearr['INTERVAL']) || $rrulearr['INTERVAL'] == '') {
$rrulearr['INTERVAL'] = 1;
}
if (array_key_exists('BYDAY', $rrulearr)) {
if (substr_count($rrulearr['BYDAY'], ',') == 0) {
if (strlen($rrulearr['BYDAY']) == 2) {
$repeat['weekdays'] = array($rrulearr['BYDAY']);
} elseif (strlen($rrulearr['BYDAY']) == 3) {
$repeat['weekofmonth'] = substr($rrulearr['BYDAY'], 0, 1);
$repeat['weekdays'] = array(substr($rrulearr['BYDAY'], 1, 2));
} elseif (strlen($rrulearr['BYDAY']) == 4) {
$repeat['weekofmonth'] = substr($rrulearr['BYDAY'], 0, 2);
$repeat['weekdays'] = array(substr($rrulearr['BYDAY'], 2, 2));
}
} else {
$byday_days = explode(',', $rrulearr['BYDAY']);
foreach ($byday_days as $byday_day) {
if (strlen($byday_day) == 2) {
$repeat['weekdays'][] = $byday_day;
} elseif (strlen($byday_day) == 3) {
$repeat['weekofmonth'] = substr($byday_day, 0, 1);
$repeat['weekdays'][] = substr($byday_day, 1, 2);
} elseif (strlen($byday_day) == 4) {
$repeat['weekofmonth'] = substr($byday_day, 0, 2);
$repeat['weekdays'][] = substr($byday_day, 2, 2);
}
}
}
}
if (array_key_exists('BYMONTHDAY', $rrulearr)) {
if (substr_count($rrulearr['BYMONTHDAY'], ',') == 0) {
$repeat['bymonthday'][] = $rrulearr['BYMONTHDAY'];
} else {
$bymonthdays = explode(',', $rrulearr['BYMONTHDAY']);
foreach ($bymonthdays as $bymonthday) {
$repeat['bymonthday'][] = $bymonthday;
}
}
}
if (array_key_exists('BYYEARDAY', $rrulearr)) {
if (substr_count($rrulearr['BYYEARDAY'], ',') == 0) {
$repeat['byyearday'][] = $rrulearr['BYYEARDAY'];
} else {
$byyeardays = explode(',', $rrulearr['BYYEARDAY']);
foreach ($byyeardays as $yearday) {
$repeat['byyearday'][] = $yearday;
}
}
}
if (array_key_exists('BYWEEKNO', $rrulearr)) {
if (substr_count($rrulearr['BYWEEKNO'], ',') == 0) {
$repeat['byweekno'][] = (string) $rrulearr['BYWEEKNO'];
} else {
$byweekno = explode(',', $rrulearr['BYWEEKNO']);
foreach ($byweekno as $weekno) {
$repeat['byweekno'][] = (string) $weekno;
}
}
}
if (array_key_exists('BYMONTH', $rrulearr)) {
if (substr_count($rrulearr['BYMONTH'], ',') == 0) {
$repeat['bymonth'][] = $month;
} else {
$bymonth = explode(',', $rrulearr['BYMONTH']);
foreach ($bymonth as $month) {
$repeat['bymonth'][] = $month;
}
}
}
switch ($rrulearr['FREQ']) {
case 'DAILY':
$repeat['repeat'] = 'daily';
break;
case 'WEEKLY':
if ($rrulearr['INTERVAL'] % 2 == 0) {
$repeat['repeat'] = 'biweekly';
$rrulearr['INTERVAL'] = $rrulearr['INTERVAL'] / 2;
} elseif ($rrulearr['BYDAY'] == 'MO,TU,WE,TH,FR') {
$repeat['repeat'] = 'weekday';
} else {
$repeat['repeat'] = 'weekly';
}
break;
case 'MONTHLY':
$repeat['repeat'] = 'monthly';
if (array_key_exists('BYDAY', $rrulearr)) {
$repeat['month'] = 'weekday';
} else {
$repeat['month'] = 'monthday';
}
break;
case 'YEARLY':
$repeat['repeat'] = 'yearly';
if (array_key_exists('BYMONTH', $rrulearr)) {
$repeat['year'] = 'bydaymonth';
} elseif (array_key_exists('BYWEEKNO', $rrulearr)) {
$repeat['year'] = 'byweekno';
} else {
$repeat['year'] = 'byyearday';
}
}
$repeat['interval'] = $rrulearr['INTERVAL'];
if (array_key_exists('COUNT', $rrulearr)) {
$repeat['end'] = 'count';
$repeat['count'] = $rrulearr['COUNT'];
} elseif (array_key_exists('UNTIL', $rrulearr)) {
$repeat['end'] = 'date';
$endbydate_year = substr($rrulearr['UNTIL'], 0, 4);
$endbydate_month = substr($rrulearr['UNTIL'], 4, 2);
$endbydate_day = substr($rrulearr['UNTIL'], 6, 2);
$repeat['date'] = $endbydate_year . '-' . $endbydate_month . '-' . $endbydate_day;
} else {
$repeat['end'] = 'never';
}
if (array_key_exists('weekdays', $repeat)) {
$repeat_weekdays_ = array();
foreach ($repeat['weekdays'] as $weekday) {
$repeat_weekdays_[] = $weekday;
}
$repeat['weekdays'] = $repeat_weekdays_;
}
} else {
$repeat['repeat'] = 'doesnotrepeat';
}
$options['calendar_options']= CalendarService::getCalendars(Auth::id(), false);
$options['access_class_options'] = CalendarService::getAccessClassOptions();
$options['valarm_options'] = CalendarService::getValarmOptions();
$options['repeat_options'] = CalendarService::getRepeatOptions();
$options['repeat_end_options'] = CalendarService::getEndOptions();
$options['repeat_month_options'] = CalendarService::getMonthOptions();
$options['repeat_year_options'] = CalendarService::getYearOptions();
$options['repeat_weekly_options'] = CalendarService::getWeeklyOptions();
$options['repeat_weekofmonth_options'] = CalendarService::getWeekofMonth();
$options['repeat_byyearday_options'] = CalendarService::getByYearDayOptions();
$options['repeat_bymonth_options'] = CalendarService::getByMonthOptions();
$options['repeat_byweekno_options'] = CalendarService::getByWeekNoOptions();
$options['repeat_bymonthday_options'] = CalendarService::getByMonthDayOptions();
$options['id'] = $gets['id'];
$options['lastmodified'] = $event['lastmodified'];
$options['title'] = $summary;
$options['location'] = $location;
$options['categories'] = $categories;
$options['calendarid'] = $event['calendarid'];
$options['allday'] = $allday;
$options['valarm'] = $valarm;
$options['startdate'] = $startdate;
$options['starttime'] = $starttime;
$options['enddate'] = $enddate;
$options['endtime'] = $endtime;
$options['description'] = $description;
$repeats['repeat'] = $repeat['repeat'];
if ($repeat['repeat'] != 'doesnotrepeat') {
$repeats['repeat_month'] = isset($repeat['month']) ? $repeat['month'] : 'monthday';
$repeats['repeat_weekdays'] = isset($repeat['weekdays']) ? $repeat['weekdays'] : array();
$repeats['repeat_interval'] = isset($repeat['interval']) ? $repeat['interval'] : '1';
$repeats['repeat_end'] = isset($repeat['end']) ? $repeat['end'] : 'never';
$repeats['repeat_count'] = isset($repeat['count']) ? $repeat['count'] : '10';
$repeats['repeat_weekofmonth'] = $repeat['weekofmonth'];
$repeats['repeat_date'] = isset($repeat['date']) ? $repeat['date'] : '';
$repeats['repeat_year'] = isset($repeat['year']) ? $repeat['year'] : array();
$repeats['repeat_byyearday'] = isset($repeat['byyearday']) ? $repeat['byyearday'] : array();
$repeats['repeat_bymonthday'] = isset($repeat['bymonthday']) ? $repeat['bymonthday'] : array();
$repeats['repeat_bymonth'] = isset($repeat['bymonth']) ? $repeat['bymonth'] : array();
$repeats['repeat_byweekno'] = isset($repeat['byweekno']) ? $repeat['byweekno'] : array();
} else {
$repeats['repeat_month'] = 'monthday';
$repeats['repeat_weekdays'] = array();
$repeats['repeat_byyearday'] = array();
$repeats['repeat_bymonthday'] = array();
$repeats['repeat_bymonth'] = array();
$repeats['repeat_byweekno'] = array();
$repeats['repeat_interval'] = '1';
$repeats['repeat_end'] = 'never';
$repeats['repeat_count'] = '10';
$repeats['repeat_weekofmonth'] = 'auto';
$repeats['repeat_date'] = '';
$repeats['repeat_year'] = 'bydate';
}
$attachment = AttachmentService::edit($event['attachment'], 'calendar_object', 'attachment', 'calendar');
$share = ShareService::getItem('event', $gets['id']);
return $this->render(array(
'attachment' => $attachment,
'repeats' => $repeats,
'options' => $options,
'share' => $share,
), 'add');
if (empty($event)) {
return $this->json('事件数据不正确。');
}
$object = VObject::parse($event['calendardata']);
$vevent = $object->VEVENT;
$dtstart = $vevent->DTSTART;
$dtend = CalendarService::getDTEndFromVEvent($vevent);
switch ($dtstart->getDateType()) {
case \Sabre\VObject\Property\DateTime::UTC:
$timezone = new \DateTimeZone(CalendarService::getTimezone());
$newDT = $dtstart->getDateTime();
$newDT->setTimezone($timezone);
$dtstart->setDateTime($newDT);
$newDT = $dtend->getDateTime();
$newDT->setTimezone($timezone);
$dtend->setDateTime($newDT);
// no break
case \Sabre\VObject\Property\DateTime::LOCALTZ:
case \Sabre\VObject\Property\DateTime::LOCAL:
$startdate = $dtstart->getDateTime()->format('Y-m-d');
$starttime = $dtstart->getDateTime()->format('H:i');
$enddate = $dtend->getDateTime()->format('Y-m-d');
$endtime = $dtend->getDateTime()->format('H:i');
$allday = false;
break;
case \Sabre\VObject\Property\DateTime::DATE:
$startdate = $dtstart->getDateTime()->format('Y-m-d');
$starttime = '';
$dtend->getDateTime()->modify('-1 day');
$enddate = $dtend->getDateTime()->format('Y-m-d');
$endtime = '';
$allday = true;
break;
}
$summary = strtr($vevent->getAsString('SUMMARY'), array('\,' => ',', '\;' => ';'));
$location = strtr($vevent->getAsString('LOCATION'), array('\,' => ',', '\;' => ';'));
$description = strtr($vevent->getAsString('DESCRIPTION'), array('\,' => ',', '\;' => ';'));
$categories = $vevent->getAsString('CATEGORIES');
if ($vevent->VALARM) {
$valarm = $vevent->VALARM->getAsString('TRIGGER');
}
if ($vevent->RRULE) {
$rrule = explode(';', $vevent->getAsString('RRULE'));
$rrulearr = array();
foreach ($rrule as $rule) {
list($attr, $val) = explode('=', $rule);
$rrulearr[$attr] = $val;
}
if (!isset($rrulearr['INTERVAL']) || $rrulearr['INTERVAL'] == '') {
$rrulearr['INTERVAL'] = 1;
}
if (array_key_exists('BYDAY', $rrulearr)) {
if (substr_count($rrulearr['BYDAY'], ',') == 0) {
if (strlen($rrulearr['BYDAY']) == 2) {
$repeat['weekdays'] = array($rrulearr['BYDAY']);
} elseif (strlen($rrulearr['BYDAY']) == 3) {
$repeat['weekofmonth'] = substr($rrulearr['BYDAY'], 0, 1);
$repeat['weekdays'] = array(substr($rrulearr['BYDAY'], 1, 2));
} elseif (strlen($rrulearr['BYDAY']) == 4) {
$repeat['weekofmonth'] = substr($rrulearr['BYDAY'], 0, 2);
$repeat['weekdays'] = array(substr($rrulearr['BYDAY'], 2, 2));
}
} else {
$byday_days = explode(',', $rrulearr['BYDAY']);
foreach ($byday_days as $byday_day) {
if (strlen($byday_day) == 2) {
$repeat['weekdays'][] = $byday_day;
} elseif (strlen($byday_day) == 3) {
$repeat['weekofmonth'] = substr($byday_day, 0, 1);
$repeat['weekdays'][] = substr($byday_day, 1, 2);
} elseif (strlen($byday_day) == 4) {
$repeat['weekofmonth'] = substr($byday_day, 0, 2);
$repeat['weekdays'][] = substr($byday_day, 2, 2);
}
}
}
}
if (array_key_exists('BYMONTHDAY', $rrulearr)) {
if (substr_count($rrulearr['BYMONTHDAY'], ',') == 0) {
$repeat['bymonthday'][] = $rrulearr['BYMONTHDAY'];
} else {
$bymonthdays = explode(',', $rrulearr['BYMONTHDAY']);
foreach ($bymonthdays as $bymonthday) {
$repeat['bymonthday'][] = $bymonthday;
}
}
}
if (array_key_exists('BYYEARDAY', $rrulearr)) {
if (substr_count($rrulearr['BYYEARDAY'], ',') == 0) {
$repeat['byyearday'][] = $rrulearr['BYYEARDAY'];
} else {
$byyeardays = explode(',', $rrulearr['BYYEARDAY']);
foreach ($byyeardays as $yearday) {
$repeat['byyearday'][] = $yearday;
}
}
}
if (array_key_exists('BYWEEKNO', $rrulearr)) {
if (substr_count($rrulearr['BYWEEKNO'], ',') == 0) {
$repeat['byweekno'][] = (string) $rrulearr['BYWEEKNO'];
} else {
$byweekno = explode(',', $rrulearr['BYWEEKNO']);
foreach ($byweekno as $weekno) {
$repeat['byweekno'][] = (string) $weekno;
}
}
}
if (array_key_exists('BYMONTH', $rrulearr)) {
if (substr_count($rrulearr['BYMONTH'], ',') == 0) {
$repeat['bymonth'][] = $month;
} else {
$bymonth = explode(',', $rrulearr['BYMONTH']);
foreach ($bymonth as $month) {
$repeat['bymonth'][] = $month;
}
}
}
switch ($rrulearr['FREQ']) {
case 'DAILY':
$repeat['repeat'] = 'daily';
break;
case 'WEEKLY':
if ($rrulearr['INTERVAL'] % 2 == 0) {
$repeat['repeat'] = 'biweekly';
$rrulearr['INTERVAL'] = $rrulearr['INTERVAL'] / 2;
} elseif ($rrulearr['BYDAY'] == 'MO,TU,WE,TH,FR') {
$repeat['repeat'] = 'weekday';
} else {
$repeat['repeat'] = 'weekly';
}
break;
case 'MONTHLY':
$repeat['repeat'] = 'monthly';
if (array_key_exists('BYDAY', $rrulearr)) {
$repeat['month'] = 'weekday';
} else {
$repeat['month'] = 'monthday';
}
break;
case 'YEARLY':
$repeat['repeat'] = 'yearly';
if (array_key_exists('BYMONTH', $rrulearr)) {
$repeat['year'] = 'bydaymonth';
} elseif (array_key_exists('BYWEEKNO', $rrulearr)) {
$repeat['year'] = 'byweekno';
} else {
$repeat['year'] = 'byyearday';
}
}
$repeat['interval'] = $rrulearr['INTERVAL'];
if (array_key_exists('COUNT', $rrulearr)) {
$repeat['end'] = 'count';
$repeat['count'] = $rrulearr['COUNT'];
} elseif (array_key_exists('UNTIL', $rrulearr)) {
$repeat['end'] = 'date';
$endbydate_year = substr($rrulearr['UNTIL'], 0, 4);
$endbydate_month = substr($rrulearr['UNTIL'], 4, 2);
$endbydate_day = substr($rrulearr['UNTIL'], 6, 2);
$repeat['date'] = $endbydate_year . '-' . $endbydate_month . '-' . $endbydate_day;
} else {
$repeat['end'] = 'never';
}
if (array_key_exists('weekdays', $repeat)) {
$repeat_weekdays_ = array();
foreach ($repeat['weekdays'] as $weekday) {
$repeat_weekdays_[] = $weekday;
}
$repeat['weekdays'] = $repeat_weekdays_;
}
} else {
$repeat['repeat'] = 'doesnotrepeat';
}
$options['calendar_options']= CalendarService::getCalendars(Auth::id(), false);
$options['access_class_options'] = CalendarService::getAccessClassOptions();
$options['valarm_options'] = CalendarService::getValarmOptions();
$options['repeat_options'] = CalendarService::getRepeatOptions();
$options['repeat_end_options'] = CalendarService::getEndOptions();
$options['repeat_month_options'] = CalendarService::getMonthOptions();
$options['repeat_year_options'] = CalendarService::getYearOptions();
$options['repeat_weekly_options'] = CalendarService::getWeeklyOptions();
$options['repeat_weekofmonth_options'] = CalendarService::getWeekofMonth();
$options['repeat_byyearday_options'] = CalendarService::getByYearDayOptions();
$options['repeat_bymonth_options'] = CalendarService::getByMonthOptions();
$options['repeat_byweekno_options'] = CalendarService::getByWeekNoOptions();
$options['repeat_bymonthday_options'] = CalendarService::getByMonthDayOptions();
$options['id'] = $gets['id'];
$options['lastmodified'] = $event['lastmodified'];
$options['title'] = $summary;
$options['location'] = $location;
$options['categories'] = $categories;
$options['calendarid'] = $event['calendarid'];
$options['allday'] = $allday;
$options['valarm'] = $valarm;
$options['startdate'] = $startdate;
$options['starttime'] = $starttime;
$options['enddate'] = $enddate;
$options['endtime'] = $endtime;
$options['description'] = $description;
$repeats['repeat'] = $repeat['repeat'];
if ($repeat['repeat'] != 'doesnotrepeat') {
$repeats['repeat_month'] = isset($repeat['month']) ? $repeat['month'] : 'monthday';
$repeats['repeat_weekdays'] = isset($repeat['weekdays']) ? $repeat['weekdays'] : array();
$repeats['repeat_interval'] = isset($repeat['interval']) ? $repeat['interval'] : '1';
$repeats['repeat_end'] = isset($repeat['end']) ? $repeat['end'] : 'never';
$repeats['repeat_count'] = isset($repeat['count']) ? $repeat['count'] : '10';
$repeats['repeat_weekofmonth'] = $repeat['weekofmonth'];
$repeats['repeat_date'] = isset($repeat['date']) ? $repeat['date'] : '';
$repeats['repeat_year'] = isset($repeat['year']) ? $repeat['year'] : array();
$repeats['repeat_byyearday'] = isset($repeat['byyearday']) ? $repeat['byyearday'] : array();
$repeats['repeat_bymonthday'] = isset($repeat['bymonthday']) ? $repeat['bymonthday'] : array();
$repeats['repeat_bymonth'] = isset($repeat['bymonth']) ? $repeat['bymonth'] : array();
$repeats['repeat_byweekno'] = isset($repeat['byweekno']) ? $repeat['byweekno'] : array();
} else {
$repeats['repeat_month'] = 'monthday';
$repeats['repeat_weekdays'] = array();
$repeats['repeat_byyearday'] = array();
$repeats['repeat_bymonthday'] = array();
$repeats['repeat_bymonth'] = array();
$repeats['repeat_byweekno'] = array();
$repeats['repeat_interval'] = '1';
$repeats['repeat_end'] = 'never';
$repeats['repeat_count'] = '10';
$repeats['repeat_weekofmonth'] = 'auto';
$repeats['repeat_date'] = '';
$repeats['repeat_year'] = 'bydate';
}
$attachment = AttachmentService::edit($event['attachment'], 'calendar_object', 'attachment', 'calendar');
$share = ShareService::getItem('event', $gets['id']);
return $this->render(array(
'attachment' => $attachment,
'repeats' => $repeats,
'options' => $options,
'share' => $share,
), 'add');
}
public function view()

View File

@ -0,0 +1,17 @@
<?php namespace Gdoo\Calendar\Controllers;
use DB;
use Request;
use Gdoo\Index\Controllers\DefaultController;
class WidgetController extends DefaultController
{
public $permission = ['index'];
// 日程
public function index()
{
return $this->render();
}
}

View File

@ -0,0 +1,8 @@
<?php namespace Gdoo\Calendar\Models;
use Gdoo\Index\Models\BaseModel;
class CalendarReminder extends BaseModel
{
public $table = 'calendar_reminder';
}

View File

@ -392,15 +392,15 @@ class CalDAV extends \Sabre\CalDAV\Backend\AbstractBackend
{
$extraData = $this->getDenormalizedData($calendarData);
$data = array(
'calendarid' => $calendarId,
'calendardata' => $calendarData,
'uri' => $objectUri,
'etag' => $extraData['etag'],
'size' => $extraData['size'],
'componenttype' => $extraData['componentType'],
'calendarid' => $calendarId,
'uri' => $objectUri,
'calendardata' => $calendarData,
'lastmodified' => time(),
'etag' => $extraData['etag'],
'size' => $extraData['size'],
'componenttype' => $extraData['componentType'],
'firstoccurence' => $extraData['firstOccurence'],
'lastoccurence' => $extraData['lastOccurence'],
'lastmodified' => time(),
'lastoccurence' => $extraData['lastOccurence'],
);
CalendarObject::insert($data);
CalendarService::touchCalendar($calendarId);
@ -427,13 +427,13 @@ class CalDAV extends \Sabre\CalDAV\Backend\AbstractBackend
{
$extraData = $this->getDenormalizedData($calendarData);
$update = array(
'calendardata' => $calendarData,
'etag' => $extraData['etag'],
'size' => $extraData['size'],
'componenttype' => $extraData['componentType'],
'calendardata' => $calendarData,
'lastmodified' => time(),
'etag' => $extraData['etag'],
'size' => $extraData['size'],
'componenttype' => $extraData['componentType'],
'firstoccurence' => $extraData['firstOccurence'],
'lastoccurence' => $extraData['lastOccurence'],
'lastmodified' => time(),
'lastoccurence' => $extraData['lastOccurence'],
);
CalendarObject::where('calendarid', $calendarId)->where('uri', $objectUri)->update($update);
CalendarService::touchCalendar($calendarId);

View File

@ -26,6 +26,8 @@ class CalendarObjectService
if ($data['allday']) {
foreach ($ranges as $date) {
$item['date'] = $date->format($format);
$item['_start'] = $start->format($format);
$item['_end'] = $end->format($format);
$items[] = $item;
}
} else {

View File

@ -9,6 +9,8 @@ use App\Support\VObject;
use Gdoo\Index\Services\AttachmentService;
use Gdoo\Calendar\Models\Calendar;
use Gdoo\Calendar\Models\CalendarObject;
use Gdoo\Calendar\Models\CalendarReminder;
use Gdoo\Index\Services\ShareService;
class CalendarService
{
@ -94,7 +96,7 @@ class CalendarService
{
$calendar = self::getCalendar($id, false);
if ($calendar['userid'] != Auth::id()) {
throw new \Exception('您没有权限编辑此日历。');
abort_error('您没有权限编辑此日历。');
}
if (is_null($name)) {
@ -154,7 +156,7 @@ class CalendarService
$calendar = self::getCalendar($id, false);
if ($calendar['userid'] != Auth::id()) {
throw new \Exception('您没有权限删除此日历。');
abort_error('您没有权限删除此日历。');
}
$events = CalendarObject::where('calendarid', $id)->get();
if (sizeof($events)) {
@ -187,15 +189,6 @@ class CalendarService
$start = strtotime($start);
$end = strtotime($end);
/*
$model = CalendarObject::where(function ($q) use ($start, $end) {
$q->where('rrule', 0);
$q->whereBetween('firstoccurence', [$start, $end]);
$q->orWhereBetween('lastoccurence', [$start, $end]);
})->orWhere(function ($q) use ($start, $end) {
$q->where('rrule', 1)->where('firstoccurence', '<=', $end);
});
*/
$model = CalendarObject::whereRaw('(
(firstoccurence between '.$start.' and '.$end.' or lastoccurence between '.$start.' and '.$end.')
or (rrule = 1 and firstoccurence <= '.$end.')
@ -231,13 +224,13 @@ class CalendarService
$allday = ($vcalendar->VEVENT->DTSTART->getDateType() == \Sabre\VObject\Property\DateTime::DATE) ? true : false;
$output = array(
'id' => (int)$row->id,
'calendarid' => (int)$row->calendarid,
'title' => (isset($vevent->SUMMARY) && $vevent->SUMMARY->value) ? strtr($vevent->SUMMARY->value, array('\,' => ',', '\;' => ';')) : 'unnamed',
'description' => (isset($vevent->DESCRIPTION) && $vevent->DESCRIPTION->value) ? strtr($vevent->DESCRIPTION->value, array('\,' => ',', '\;' => ';')) : '',
'location' => (isset($vevent->LOCATION) && $vevent->LOCATION->value) ? strtr($vevent->LOCATION->value, array('\,' => ',', '\;' => ';')) : '',
'id' => (int)$row->id,
'calendarid' => (int)$row->calendarid,
'title' => (isset($vevent->SUMMARY) && $vevent->SUMMARY->value) ? strtr($vevent->SUMMARY->value, array('\,' => ',', '\;' => ';')) : 'unnamed',
'description' => (isset($vevent->DESCRIPTION) && $vevent->DESCRIPTION->value) ? strtr($vevent->DESCRIPTION->value, array('\,' => ',', '\;' => ';')) : '',
'location' => (isset($vevent->LOCATION) && $vevent->LOCATION->value) ? strtr($vevent->LOCATION->value, array('\,' => ',', '\;' => ';')) : '',
'lastmodified' => $row->lastmodified,
'allDay' => $allday,
'allDay' => $allday,
);
if ($vcalendar->VEVENT->RRULE) {
@ -277,31 +270,60 @@ class CalendarService
* @param string $attachment
* @return integer
*/
public static function add($id, $calendardata, $attachment = null)
public static function add($params, $vcalendar)
{
$calendar = self::getCalendar($id);
$calendarid = $params['calendarid'];
$calendar = self::getCalendar($calendarid);
if ($calendar['userid'] != Auth::id()) {
throw new \Exception('您没有权限添加事件到此日历。');
abort_error('您没有权限添加事件到此日历。');
}
$calendardata = $vcalendar->serialize();
$extraData = self::getDenormalizedData($calendardata);
$uri = self::createURI().'.ics';
$data = [
'calendarid' => $id,
'calendarid' => $calendarid,
'calendardata' => $calendardata,
'attachment' => $attachment,
'uri' => $uri,
'rrule' => $extraData['rrule'],
'etag' => $extraData['etag'],
'size' => $extraData['size'],
'uri' => $uri,
'lastmodified' => time(),
'attachment' => $params['attachment'],
'componenttype' => $extraData['componentType'],
'firstoccurence' => $extraData['firstOccurence'],
'lastoccurence' => $extraData['lastOccurence'],
'lastmodified' => time(),
];
$objectId = CalendarObject::insertGetId($data);
self::touchCalendar($id);
// 是重复事件
$is_recurring = $vcalendar->VEVENT->RRULE ? 1 : 0;
// 事件提醒
if (isset($vcalendar->VEVENT->VALARM)) {
$triggerTime = $vcalendar->VEVENT->VALARM->getEffectiveTriggerTime();
$valarm_at = $triggerTime->getTimeStamp();
CalendarReminder::insert([
'calendar_id' => $calendarid,
'object_id' => $objectId,
'is_recurring' => $is_recurring,
'alarm_at' => $valarm_at,
]);
}
// 写入共享数据
ShareService::addItem([
'source_id' => $objectId,
'source_type' => 'event',
'is_repeat' => $is_recurring,
'receive_id' => $params['receive_id'],
'receive_name' => $params['receive_name'],
'start_at' => $extraData['firstOccurence'],
'end_at' => $extraData['lastOccurence'],
]);
self::touchCalendar($calendarid);
return $objectId;
}
@ -311,32 +333,72 @@ class CalendarService
* @param string $data object
* @return boolean
*/
public static function edit($id, $calendardata, $attachment = null)
public static function edit($params, $vcalendar)
{
$event = self::getEvent($id);
$event = self::getEvent($params['id']);
$calendar = self::getCalendar($event['calendarid']);
if ($calendar['userid'] != Auth::id()) {
throw new \Exception('您没有权限编辑此事件。');
}
if (empty($attachment)) {
$attachment = $event['attachment'];
abort_error('您没有权限编辑此事件。');
}
$calendardata = $vcalendar->serialize();
$extraData = self::getDenormalizedData($calendardata);
$data = [
'calendardata' => $calendardata,
'attachment' => $attachment,
'lastmodified' => time(),
'rrule' => $extraData['rrule'],
'etag' => $extraData['etag'],
'size' => $extraData['size'],
'componenttype' => $extraData['componentType'],
'firstoccurence' => $extraData['firstOccurence'],
'lastoccurence' => $extraData['lastOccurence'],
'lastmodified' => time(),
];
CalendarObject::where('id', $id)->update($data);
// 存在附件字段
if (isset($params['attachment'])) {
$data['attachment'] = $params['attachment'];
}
CalendarObject::where('id', $params['id'])->update($data);
// 是重复事件
$is_recurring = $vcalendar->VEVENT->RRULE ? 1 : 0;
// 事件提醒
if ($vcalendar->VEVENT->VALARM->TRIGGER) {
$triggerTime = $vcalendar->VEVENT->VALARM->getEffectiveTriggerTime();
$valarm_at = $triggerTime->getTimeStamp();
$reminder = CalendarReminder::firstOrNew(['calendar_id' => $event['calendarid'], 'object_id' => $event['id']]);
$reminder->is_recurring = $is_recurring;
$reminder->alarm_at = $valarm_at;
$reminder->save();
} else {
CalendarReminder::where('object_id', $event['id'])->delete();
}
// 修改共享数据
$share_data = [
'source_id' => $params['id'],
'source_type' => 'event',
'is_repeat' => $is_recurring,
'start_at' => $extraData['firstOccurence'],
'end_at' => $extraData['lastOccurence'],
];
// 存在接收人字段
if (isset($params['receive_id'])) {
$share_data['receive_id'] = $params['receive_id'];
$share_data['receive_name'] = $params['receive_name'];
}
$share = ShareService::getItem('event', $params['id']);
if (empty($share)) {
ShareService::addItem($share_data);
} else {
ShareService::editItem('event', $params['id'], $share_data);
}
self::touchCalendar($event['calendarid']);
return true;
}
@ -352,11 +414,12 @@ class CalendarService
$calendar = self::getCalendar($event['calendarid']);
if ($calendar['userid'] != Auth::id()) {
throw new \Exception('您没有权限删除此事件。');
abort_error('您没有权限删除此事件。');
}
AttachmentService::remove($event['attachment']);
CalendarObject::where('id', $id)->delete();
CalendarReminder::where('object_id', $id)->delete();
self::touchCalendar($event['calendarid']);
return true;
}
@ -365,7 +428,7 @@ class CalendarService
{
$calendar = self::getCalendar($calendarid);
if ($calendar['userid'] != Auth::id()) {
throw new \Exception('您没有权限添加事件到此日历。');
abort_error('您没有权限添加事件到此日历。');
}
CalendarObject::where('id', $id)->update(array('calendarid'=>$calendarid));
self::touchCalendar($calendarid);
@ -440,14 +503,14 @@ class CalendarService
}
}
return [
return array(
'etag' => md5($calendarData),
'size' => strlen($calendarData),
'rrule' => $rrule,
'componentType' => $componentType,
'firstOccurence' => $firstOccurence,
'lastOccurence' => $lastOccurence,
];
);
}
/**
@ -1103,6 +1166,7 @@ class CalendarService
if ($allday) {
$return['start'] = $start_dt->format('Y-m-d');
//$end_dt->modify('-1 minute');
while ($start_dt >= $end_dt) {
$end_dt->modify('+1 day');
}

View File

@ -7,6 +7,14 @@ return [
['name' => '工作', 'id' => 'work'],
['name' => '日程管理', 'id' => 'calendar_calendar_index', 'parent' => 'work', 'url' => 'calendar/calendar/index'],
],
'widgets' => [
'widget_calendar_index' => [
'name' => '日程管理',
'type' => 1,
'url' => 'calendar/widget/index',
'more_url' => 'calendar/calendar/index',
],
],
"controllers" => [
"calendar" => [
"name" => "日历",
@ -28,6 +36,9 @@ return [
],
"delete" => [
"name" => "删除"
],
"help" => [
"name" => "帮助"
]
]
],

View File

@ -67,8 +67,8 @@ function InitCalendar(sources)
allDayText:'全天',
slotLabelFormat: 'HH:mm',
timeFormat: 'HH:mm',
minTime:'07:00:00',
maxTime:'23:00:00',
//minTime:'07:00:00',
//maxTime:'23:00:00',
titleRangeSeparator:' - ',
monthNames: ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'],
monthNamesShort: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
@ -87,13 +87,11 @@ function InitCalendar(sources)
});
},
viewRender:function(view) {
/*
window.clearInterval(timelineInterval);
timelineInterval = window.setInterval(function() {
timeLine(view);
}, 10000);
timeLine(view);
*/
},
loading:function(status, view) {
if (status) {
@ -105,33 +103,29 @@ function InitCalendar(sources)
// 改变大小事件 event, dayDelta, minuteDelta, revertFunc
eventResize: function(event, delta, revertFunc) {
if(auth_id == user_id) {
if (auth_id == user_id) {
resizeEvent(event, delta, revertFunc);
} else {
toastrError('不能给下属调整事件。');
revertFunc();
}
},
// 拖动事件
eventDrop: function(event, delta, revertFunc) {
if(auth_id == user_id) {
if (auth_id == user_id) {
moveEvent(event, delta, revertFunc);
} else {
toastrError('不能给下属移动事件。');
revertFunc();
}
},
// 点击事件
eventClick: function(event, jsEvent, view) {
if(event.shared == true) {
if (event.shared == true) {
viewEvent(event, jsEvent, view);
} else if(auth_id == event.userid) {
if(event.id > 0) {
} else if (auth_id == event.userid) {
if (event.id > 0) {
editEvent(event, jsEvent, view);
} else {
addEvent(event, jsEvent, view);
@ -143,8 +137,7 @@ function InitCalendar(sources)
// 选择后弹出
select: function(start, end, jsEvent, view) {
if(auth_id == user_id) {
if (auth_id == user_id) {
addEvent({start: start, end: end}, jsEvent, view);
} else {
toastrError('不能给下属添加事件。');
@ -155,7 +148,6 @@ function InitCalendar(sources)
if(view.type == 'listMonth') {
return;
}
overlay.find('#overlay-title').text(calEvent.title);
overlay.find('#overlay-start').text(calEvent.start.format());
overlay.find('#overlay-end').text(calEvent.end.format());
@ -207,7 +199,7 @@ function timeLine(curView) {
var timeline = parentDiv.children(".timeline");
if (timeline.length == 0) {
//添加时间线标签
// 添加时间线标签
timeline = $("<hr>").addClass("timeline");
parentDiv.prepend(timeline);
}
@ -222,7 +214,7 @@ function timeLine(curView) {
var percentOfDay = curSeconds / 86400;
var topPos = Math.floor(parentDiv.height() * percentOfDay);
timeline.css("top", topPos+"px");
timeline.css("top", topPos + "px");
// 周视图时设置时间线的位置和宽度
if (curView.name == "agendaWeek") {
@ -332,8 +324,8 @@ function moveEvent(event, delta, revertFunc)
function editEvent(event, jsEvent, view)
{
var data = dateFormat(event);
data.id = event.id;
data.title = event.title;
data.id = event.id;
data.title = event.title;
data.location = event.location;
data.description = event.description;
data.lastmodified = event.lastmodified;
@ -351,7 +343,6 @@ function editEvent(event, jsEvent, view)
text: '提交',
'class': 'btn-info',
click: function() {
var $this = $(this);
if ($('#title').val().length == 0) {
toastrError('主题必须填写。');
@ -461,15 +452,16 @@ function getCalendars(callback)
if(this.active == 1) {
var checkbox = 'checked';
}
if(this.id == 'shared') {
var checkbox = 'checked disabled';
var checkbox = 'checked';
}
rows.push('<li class="list-group-item">'+ edit +'<label class="checkbox-inline"><input data-calendar="active" data-id="'+this.id+'" type="checkbox" '+checkbox+' /> <span class="text" style="color:'+this.calendarcolor+'">'+this.displayname+'</span></label></li>');
});
rows.push('</ul>');
$('#calendars').html(rows.join(''));
if(callback) {
if (callback) {
callback(res.data.sources);
}
});
@ -520,7 +512,7 @@ $(function() {
#loading { background:red; color:#fff; padding:3px; position:absolute; top:5px;right:5px;z-index:9999;}
.category .tree ul {padding:5px 0;}
.category .tree ul { padding:5px 0; }
.category .tree ul li.me {padding:5px; color:#666;}
.category .tree ul li ul {padding:5px 0 0;}
.category .tree ul li ul li {padding:5px 5px 0 5px; border:0;border-top:1px solid #eee;}
@ -542,13 +534,13 @@ $(function() {
<div class="tree">
<ul class="list-group">
<li class="list-group-item"><strong>下属日历</strong></li>
@if($underling['role'])
@foreach($underling['role'] as $role_id => $role)
<li class="list-group-item">
{{$role['title']}}
<i class="fa fa-angle-down"></i> {{$role['name']}}
<ul>
@if($underling['user'][$role_id])
@foreach($underling['user'][$role_id] as $user)

View File

@ -0,0 +1,189 @@
<div class="gdoo-list-grid">
<div id="widget_calendar_datetime" class="m-t-xs"></div>
@verbatim
<div class="b-t" id="widget_calendar_event_list" style="width:100%;height:200px;">
<div v-for="row in data.dayEvents">
<li class="calendar-day-event">
<div v-if="row.allday" class="day-tag">
<span title="全天">全天</span>
</div>
<div class="day-tag time-tag" v-else>
<span :title="row.start">{{row.start}}</span>
<span :title="row.end">{{row.end}}</span>
</div>
<div class="title-tag" v-if="row.allday" :title="row.title">
<div class="text_overflow" style="cursor:pointer;">{{row.title}}</div>
<i class="text_overflow">{{row._start}} - {{row._end}}&nbsp;&nbsp;</i>
</div>
<div class="title-tag title-time-tag" v-else :title="row.title">
<div class="text_overflow" style="cursor:pointer;">{{row.title}}</div>
</div>
</li>
</div>
</div>
@endverbatim
</div>
<style>
#widget_calendar_event_list {
overflow: hidden;
overflow-y: auto;
padding: 5px;
}
.calendar-day-event {
list-style: none;
position: relative;
border-bottom: 1px solid #efefef;
padding: 6px 0 0;
height: 44px;
}
.calendar-day-event .day-tag {
position: absolute;
left: 0;
top: 6px;
width: 46px;
border-right: 2px solid #53aaff;
height: 30px;
text-align: center;
line-height: 30px;
}
.calendar-day-event .time-tag {
line-height: 14px;
}
.calendar-day-event .day-tag span {
display: block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.calendar-day-event .title-tag {
position: absolute;
padding-left: 56px;
margin: 0;
}
.calendar-day-event .title-time-tag {
line-height: 30px;
height: 30px;
}
.calendar-day-event .title-tag i {
line-height: 14px;
height: 14px;
overflow: hidden;
font-size: 12px;
margin: 0;
padding: 0;
font-style: normal;
color: #999;
}
</style>
<script>
$.fn.datetimepicker.Constructor.Default = $.extend({}, $.fn.datetimepicker.Constructor.Default, {
dayViewHeaderFormat:'YYYY年MM月',
icons: {
today: 'fa fa-caret-square-o-right',
clear: 'fa fa-trash-o',
close: 'fa fa-close',
time: "fa fa-clock-o",
date: "fa fa-calendar-check-o",
up: "fa fa-arrow-up",
down: "fa fa-arrow-down",
previous: 'fa fa-angle-left',
next: 'fa fa-angle-right',
},
tooltips:{
today: '今天',
time: '时间',
clear: '清除',
close: '关闭',
selectMonth: '选择月份',
prevMonth: '上个月',
nextMonth: '下个月',
selectYear: '选择年份',
prevYear: '上一年',
nextYear: '下一年',
selectDecade: '选择时期',
prevDecade: '上个年代',
nextDecade: '下个年代',
prevCentury: '上个世纪',
nextCentury: '下个世纪',
incrementHour: '增加一小时',
pickHour: '选择小时',
decrementHour:'减少一小时',
incrementMinute: '增加一分钟',
pickMinute: '选择分',
decrementMinute:'减少一分钟',
incrementSecond: '增加一秒',
pickSecond: '选择秒',
decrementSecond:'减少一秒'
}
});
(function ($) {
var datas = [];
var $calendar = $('#widget_calendar_datetime');
$calendar.datetimepicker({
format: 'YYYY-MM-DD',
inline: true,
sideBySide: true,
onSelectDay: function(clsName, day) {
if (datas[day]) {
clsName += ' todo';
}
return clsName;
}
});
var picker = $calendar.data('datetimepicker');
function getStartEndDate(viewDate, callback) {
datas = {};
let start = viewDate.clone().startOf('M').startOf('w').startOf('d');
let end = start.clone().add(41, 'd').format('L');
start = start.format('L');
$.getJSON(app.url('calendar/event/data', {start, end}), function(rows) {
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
datas[row.date] = datas[row.date] || [];
datas[row.date].push(row);
}
picker._fillDate();
if (typeof callback === 'function') {
callback(datas);
}
});
}
// 初始化数据
getStartEndDate(picker._viewDate, function() {
let day = picker.date().format('L');
vueData.dayEvents = datas[day] || [];
});
$calendar.on('update.datetimepicker', function(e) {
getStartEndDate(e.viewDate);
});
$calendar.on('change.datetimepicker', function(e) {
let day = e.date.format('L');
vueData.dayEvents = datas[day] || [];
});
let vueData = Vue.reactive({dayEvents:[]});
let vm = Vue.createApp({
setup(props, ctx) {
return {data: vueData};
}
}).mount("#widget_calendar_event_list");
gdoo.widgets['calendar_widget_index'] = {
remoteData: function() {
picker._doAction({}, 'today');
getStartEndDate(picker._viewDate);
}
};
})(jQuery);
</script>

View File

@ -1,621 +0,0 @@
<?php namespace Gdoo\Chat\Controllers;
use Illuminate\Http\Request;
use URL;
use DB;
use Log;
use Session;
use Config;
use Auth;
use App\Support\JWT;
use Gdoo\Chat\Models\History;
use Gdoo\Chat\Models\Message;
use Gdoo\Chat\Services\ChatService;
use Gdoo\Index\Controllers\Controller;
use Str;
class ChatController extends Controller
{
public $user = null;
public function __construct()
{
parent::__construct();
$this->middleware(function ($request, $next) {
$this->user = $request->user();
$action = $request->action();
// 如果没有登录跳转到登录页面
if (Auth::guest()) {
if ($action == 'login' || $action == 'start') {
} else {
return redirect("/chat/chat/login");
}
} else {
// 已经登录了访问登录页面
if ($action == 'login') {
return redirect("/chat/chat/index");
}
}
return $next($request);
});
}
public function start()
{
return $this->return_json([
'title' => $this->setting['title'],
'auth_id' => (int)$this->user['id'],
]);
}
public function index()
{
return $this->render([
'user' => $this->user,
]);
}
public function getServerURL()
{
return ChatService::getServerURL($this->user);
}
public function upload(Request $request)
{
if ($request->method() == 'POST') {
$user = $this->user;
$file = $request->file('file');
$path = 'chat'.date('/Ym/');
$extension = $file->getClientOriginalExtension();
$upload_path = upload_path().'/'.$path;
// 文件新名字
$filename = date('dhis_').Str::random(4).'.'.$extension;
$filename = mb_strtolower($filename);
$size = $file->getSize();
$name = mb_strtolower($file->getClientOriginalName());
$mime = $file->getMimeType();
if ($file->move($upload_path, $filename)) {
$data = [
'name' => $name,
'node' => 'chat',
'path' => $path.$filename,
'type' => $extension,
'key' => 'chat.file',
'size' => $size,
];
$insertId = DB::table('attachment')->insertGetId($data);
$src = url($path.$filename);
if (in_array($extension, ['jpg', 'gif', 'png', 'jpeg'])) {
list($picw, $pich, $t) = getimagesize($upload_path.$filename);
}
$json = [
"adddt" => date('Y-m-d H:i:s'),
"comid" => 1,
"fileext" => $extension,
"filename" => $name,
"filepath" => $src,
"filesize" => $size,
"filesizecn" => human_filesize($size),
"filetype" => $mime,
"id" => $insertId,
"ip" => $request->getClientIp(),
"mknum" => "",
"optid" => $user['id'],
"optname" => $user['name'],
"pich" => (int)$pich,
"picw" => (int)$picw,
"thumbpath" => $src,
"valid" => 1,
"web" => "Chrome",
];
return json_encode($json);
}
}
}
public function getHistory()
{
$auth_id = $this->user['id'];
$json = ChatService::getHistory($auth_id);
return $this->return_json($json);
}
public function getMaxUpload()
{
return $this->return_json(['maxUpload' => $this->setting['upload_max']]);
}
public function getGroupUser(Request $request)
{
$gets = $request->all();
$auth_id = $this->user['id'];
$json = ChatService::getGroupUser($gets['gid'], $auth_id);
return $this->return_json($json);
}
public function clearRecord(Request $request)
{
$gets = $request->all();
$auth_id = $this->user['id'];
ChatService::clearRecord($gets['type'], $gets['gid'], $auth_id, $gets['ids']);
return $this->return_json('删除成功');
}
public function inviteUser(Request $request)
{
$gets = $request->all();
ChatService::inviteUser($this->user, $gets['gid'], $gets['val']);
return $this->return_json('邀请成功');
}
public function getReceiver(Request $request)
{
$gets = $request->all();
$auth_id = $this->user['id'];
$json = ChatService::getReceiver($gets['type'], $gets['gid'], $auth_id);
return $this->return_json(['receinfor' => $json]);
}
public function exitGroup(Request $request)
{
$gets = $request->all();
$auth_id = $this->user['id'];
ChatService::exitGroup($gets['gid'], $auth_id);
return $this->return_json('退出会话成功');
}
public function createGroup(Request $request)
{
$gets = $request->all();
$auth_id = $this->user['id'];
$group_id = DB::table('chat_group')->insertGetId([
'name' => $gets['val'],
'logo' => '/assets/chat/images/group.png',
]);
DB::table('chat_group_user')->insert([
'group_id' => $group_id,
'user_id' => $auth_id,
]);
return $this->return_json('创建会话成功');
}
public function clearHistory(Request $request)
{
$gets = $request->all();
$auth_id = $this->user['id'];
ChatService::clearHistory($gets['type'], $gets['gid'], $auth_id);
return $this->return_json('退出会话成功');
}
public function getDepartmentUserData()
{
$roles = DB::table('role')->get()->toNested();
$departments = DB::table('department')
->leftJoin(DB::raw('(select count(id) utotal, department_id
FROM [user]
GROUP BY department_id
) u
'), 'u.department_id', '=', 'department.id')
->selectRaw('department.*, isnull(u.utotal, 0) as ntotal')
->get()->toNested();
$deptjson = [];
foreach($departments as $department) {
$department['stotal'] = 0;
// 显示部门下的用户数
$department['ntotal'] = 0;
foreach($department['child'] as $child) {
$department['ntotal'] += $departments[$child]['ntotal'];
}
$department['pid'] = $department['parent_id'];
$deptjson[] = $department;
}
$users = ChatService::getUser(1, 1);
$userjson = [];
foreach($users as $user) {
$user['pingyin'] = '';
$user['deptname'] = $departments[$user['department_id']]['name'];
$user['deptallname'] = $departments[$user['department_id']]['text'];
$user['ranking'] = $roles[$user['role_id']]['name'];
$user['face'] = avatar($user['avatar']);
$userjson[] = $user;
}
$groupjson = [];
$json = [
'userjson' => $userjson,
'deptjson' => $deptjson,
'groupjson' => $groupjson,
];
return $this->return_json($json);
}
public function login(Request $request)
{
if ($request->method() == 'POST') {
$gets = $request->all();
$credentials = [
'username' => $gets['adminuser'],
'password' => $gets['adminpass'],
'status' => 1,
];
if (Auth::attempt($credentials)) {
return $this->return_json('登录成功');
} else {
abort_error('成功失败,请检查用户名或者密码');
}
}
return $this->render();
}
public function logout()
{
Auth::logout();
Session::flush();
return $this->return_json('登出成功');
}
/**
* 撤回消息功能
*/
public function recallMessage(Request $request)
{
$auth_id = $this->user['id'];
$gets = $request->all();
$json = ChatService::recallMessage($gets['type'], $auth_id, $gets['gid'], $gets['id']);
return $this->return_json($json);
}
public function sendMessage(Request $request)
{
$gets = $request->all();
$auth = $this->user;
$send_id = (int)$auth['id'];
$receive_id = (int)$gets['gid'];
$type = $gets['type'];
$json = ChatService::sendMessage($type, $send_id, $receive_id, $gets);
return $this->return_json($json);
}
public function getRecord(Request $request)
{
$auth = $this->user;
$auth_id = (int)$auth['id'];
$gid = (int)$request->get('gid');
$type = $request->get('type');
$page = $request->get('page');
$lastdt = $request->get('lastdt');
$minid = (int)$request->get('minid');
$roles = DB::table('role')->get()->toNested();
$departments = DB::table('department')->get()->toNested();
$json = [
"nowdt" => time(),
"servernow" => date('Y-m-d H:i:s'),
];
$receiver = $sender = [];
if ($type == 'user') {
$receiver = DB::table('user')
->where('id', $gid)
->selectRaw('id, name, role_id, department_id, department_id as deptid, avatar')
->first();
$receiver['ranking'] = $roles[$receiver['role_id']]['name'];
$receiver['unitname'] = $departments[$receiver['department_id']]['text'];
$receiver['deptname'] = $departments[$receiver['department_id']]['name'];
$receiver['face'] = avatar($receiver['avatar']);
$receiver['type'] = 'user';
$receiver['utotal'] = 0;
$receiver['gid'] = $receiver['id'];
$json['receinfor'] = $receiver;
}
else if ($type == 'group') {
$receiver = DB::table('chat_group')
->where('id', $gid)
->selectRaw('id, name, logo')
->first();
$receiver['face'] = $receiver['logo'];
$receiver['type'] = 'group';
// 查询用户数量
$receiver['utotal'] = DB::table('chat_group_user')
->where('group_id', $gid)
->count();
// 查询自己是否在组中
$receiver['innei'] = DB::table('chat_group_user')
->where('group_id', $gid)
->where('user_id', $auth_id)
->count();
$receiver['gid'] = $receiver['id'];
$json['receinfor'] = $receiver;
}
if ($page == 0) {
$sender = DB::table('user')
->where('id', $auth_id)
->selectRaw('id, name, role_id, department_id, department_id as deptid, avatar')
->first();
$sender['ranking'] = $roles[$sender['role_id']]['name'];
$sender['unitname'] = $departments[$sender['department_id']]['text'];
$sender['deptname'] = $departments[$sender['department_id']]['name'];
$sender['face'] = avatar($sender['avatar']);
$json['sendinfo'] = $sender;
}
$rows = [];
$unread_total = 0;
// 获取用户
if ($type == 'user') {
// 获取全部未读
$unread_total = DB::table('chat_message')
->whereRaw("(send_id = $gid and receive_id = $auth_id) and type = '$type' and id in(select message_id from chat_message_status where status = 0 and user_id = '$auth_id')")
->count();
$model = DB::table('chat_message as cm')
->leftJoin('user', 'user.id', '=', 'cm.send_id')
->leftJoin('chat_message_status as cms', 'cm.id', '=', 'cms.message_id')
->where('cm.type', $type)
->orderBy('cm.id', 'desc');
$model->whereRaw("((cm.send_id = '$gid' and cm.receive_id = '$auth_id') or (cm.receive_id = '$gid' and cm.send_id = '$auth_id')) and cms.user_id = '$auth_id'");
// 这里有一点bug如果只有一条未读只能显示一条
if ($unread_total > 0) {
$model->where('cms.status', 0);
}
// 获取大于当前时间的记录
if ($lastdt > 0) {
$model->where('cm.created_dt', '>', date('Y-m-d H:i:s', $lastdt));
}
// 获取小于当前id的记录
if ($minid > 0) {
$model->where('cm.id', '<', $minid);
}
$messages = $model->selectRaw('
cm.*,
cm.send_id as sendid,
cm.content as cont,
cm.created_dt as optdt,
cms.status as zt,
[user].name as sendname,
[user].avatar
')
->limit(10)
->get();
$message_ids = [];
foreach($messages as $message) {
$message_ids[] = $message['id'];
$message['optdt'] = date('Y-m-d H:i:s', strtotime($message['created_dt']));
$message['face'] = avatar($message['avatar']);
$rows[] = $message;
$unread_total--;
}
// 设置已读
DB::table('chat_message_status')
->where('user_id', $auth_id)
->whereIn('message_id', $message_ids)
->update(['status' => 1]);
}
// 获取讨论组
else if ($type == 'group') {
// 获取全部未读
$unread_total = DB::table('chat_message')
->whereRaw("type = '$type' and receive_id = '$gid' and id in(select message_id from chat_message_status where status = 0 and user_id = '$auth_id')")
->count();
$model = DB::table('chat_message as cm')
->leftJoin('user', 'user.id', '=', 'cm.send_id')
->leftJoin('chat_message_status as cms', 'cm.id', '=', 'cms.message_id')
->where('cm.type', $type)
->orderBy('cm.id', 'desc');
$model->whereRaw("(cm.receive_id = '$gid') and cms.user_id = '$auth_id'");
// 这里有一点bug如果只有一条未读只能显示一条
if ($unread_total > 0) {
$model->where('cms.status', 0);
}
// 获取大于当前时间的记录
if ($lastdt > 0) {
$model->where('cm.created_dt', '>', date('Y-m-d H:i:s', $lastdt));
}
// 获取小于当前id的记录
if ($minid > 0) {
$model->where('cm.id', '<', $minid);
}
$messages = $model->selectRaw('
cm.*,
cm.send_id as sendid,
cm.content as cont,
cm.created_dt as optdt,
cms.status as zt,
[user].name as sendname,
[user].avatar
')
->limit(10)
->get();
$message_ids = [];
foreach($messages as $message) {
$message_ids[] = $message['id'];
$message['optdt'] = date('Y-m-d H:i:s', strtotime($message['created_dt']));
$message['face'] = avatar($message['avatar']);
$rows[] = $message;
$unread_total--;
}
// 设置未读为已读
DB::table('chat_message_status')
->where('group_id', $gid)
->where('user_id', $auth_id)
->whereIn('message_id', $message_ids)
->update(['status' => 1]);
}
$rows = ChatService::formatMessage($rows);
$unread_total = $unread_total < 0 ? 0 : $unread_total;
$json['wdtotal'] = $unread_total;
// 设置会话已读
DB::table('chat_history')
->where('send_id', $auth_id)
->where('receive_id', $gid)
->where('type', $type)
->update(['unread_total' => $unread_total]);
$json['rows'] = $rows;
return $this->return_json($json);
}
public function init(Request $request)
{
$auth_id = $this->user['id'];
$roles = DB::table('role')->get()->toNested();
$departments = DB::table('department')
->leftJoin(DB::raw('(select count(id) utotal, department_id
FROM [user]
GROUP BY department_id
) u
'), 'u.department_id', '=', 'department.id')
->selectRaw('department.*, isnull(u.utotal, 0) as ntotal')
->get()->toNested();
$deptjson = [];
foreach($departments as $department) {
$department['stotal'] = 0;
// 显示部门下的用户数
$department['ntotal'] = 0;
foreach($department['child'] as $child) {
$department['ntotal'] += $departments[$child]['ntotal'];
}
$department['pid'] = $department['parent_id'];
$deptjson[] = $department;
}
$users = ChatService::getUser(1, 1);
$userjson = [];
foreach($users as $user) {
$user['deptname'] = $departments[$user['department_id']]['name'];
$user['deptallname'] = $departments[$user['department_id']]['text'];
$user['ranking'] = $roles[$user['role_id']]['name'];
$user['face'] = avatar($user['avatar']);
$userjson[] = $user;
}
// 获取组
$groups = ChatService::getGroup($auth_id);
$groupjson = [];
foreach ($groups as $group) {
$group['deptid'] = $group['department_id'];
$groupjson[] = $group;
}
$agentjson = array(
array('id' => '1',
'name' => 'Gdoo Team',
'url' => 'link',
'face' => 'images/logo.png',
'num' => 'xinhu',
'pid' => '0',
'iconfont' => 'cf-c90',
'iconcolor' => '#1ABC9C',
'types' => '官网(1)',
'urlpc' => 'http://www.gdoo.net',
'urlm' => NULL,
'titles' => '',
'menu' => array(
array('pid' => '0', 'mid' => '1', 'id' => '18', 'name' => '最新信息', 'type' => '0', 'url' => 'new', 'num' => NULL, 'color' => NULL, 'receid' => NULL, 'submenu' => array()),
array('pid' => '0', 'mid' => '1', 'id' => '89', 'name' => '打开官网', 'type' => '1', 'url' => 'http://www.gdoo.net', 'num' => NULL, 'color' => NULL, 'receid' => NULL, 'submenu' => array(),),
array('pid' => '0', 'mid' => '1', 'id' => '19', 'name' => '+建议反馈', 'type' => '1', 'url' => 'http://www.gdoo.net/fankui.html', 'num' => NULL, 'color' => NULL, 'receid' => NULL, 'submenu' => array(),),
),
'stotal' => 0,
'totals' => 0
)
);
$agentjson = [];
$historyjson = ChatService::getHistory($auth_id);
$json = [
'deptjson' => $deptjson,
'userjson' => $userjson,
'groupjson' => $groupjson,
'agentjson' => $agentjson,
'historyjson' => $historyjson,
"modearr" => [],
"config" => [
"recid" => "gdoo",
"title" => "Gdoo",
"chehui" => 5,
"wsurl" => env('REALTIME_URL'),
],
"loaddt" => date('Y-m-d H:i:s'),
"ip" => $request->getClientIp(),
"editpass" => 1,
"companyinfo" => [
"id" => "1",
"logo" => "images/logo.png",
"name" => "Gdoo Team",
"nameen" => null,
"oaname" => null,
"oanemes" => null,
"tel" => "028-123456",
"fax" => "028-123456",
"pid" => "0",
"sort" => "0",
"fuzeid" => "5",
"fuzename" => "乐风",
"address" => "软件园",
"city" => "眉山",
"num" => null,
"comid" => "0"
]
];
return $this->return_json($json);
}
public function return_json($data, $success = true, $code = 200, $msg = '') {
$json = [
'data' => $data,
'success' => $success,
'code' => $code,
'msg' => $msg,
];
return $json;
}
}

View File

@ -1,8 +0,0 @@
<?php namespace Gdoo\Chat\Models;
use Gdoo\Index\Models\BaseModel;
class GroupUser extends BaseModel
{
protected $table = 'chat_group_user';
}

View File

@ -1,8 +0,0 @@
<?php namespace Gdoo\Chat\Models;
use Gdoo\Index\Models\BaseModel;
class History extends BaseModel
{
protected $table = 'chat_history';
}

View File

@ -1,8 +0,0 @@
<?php namespace Gdoo\Chat\Models;
use Gdoo\Index\Models\BaseModel;
class Message extends BaseModel
{
protected $table = 'chat_message';
}

View File

@ -1,723 +0,0 @@
<?php namespace Gdoo\Chat\Services;
use DB;
use URL;
use Gdoo\Chat\Models\History;
use Gdoo\Chat\Models\GroupUser;
use Gdoo\Chat\Models\Message;
class ChatService
{
/**
* 构建ws连接url
*
* @param array $user
* @access public
* @return array
*/
public static function getServerURL($user) {
$key = env('REALTIME_KEY');
$url = env('REALTIME_URL');
$timestamp = time();
$nonce = rand(10000, 99999);
$signature = hash_hmac('sha256', $key.$timestamp.$nonce, $key);
$query = [
'signature' => $signature,
'timestamp' => $timestamp,
'nonce' => $nonce,
'user_id' => $user['id'],
'user_name' => $user['name'],
];
return ['url' => $url. '?'. http_build_query($query)];
}
/**
* 获取组
*
* @param int $admin_id
* @access public
* @return array
*/
public static function getGroup($auth_id = 0, $admin_id = 0)
{
static $rows = null;
if ($rows == null) {
$model = DB::table('chat_group as cg')
->leftJoin('chat_group_user', 'chat_group_user.group_id', '=', 'cg.id');
if ($auth_id > 0) {
$model->where('chat_group_user.user_id', $auth_id);
}
if ($admin_id > 0) {
$model->whereRaw(db_instr('admin_ids', $admin_id));
}
$model->leftJoin(DB::raw('(select count(id) utotal, group_id
FROM chat_group_user
GROUP BY group_id
) cgu
'), 'cg.id', '=', 'cgu.group_id')
->selectRaw('cg.*, cgu.utotal, cg.logo as face');
$rows = $model->get()->keyBy('id');
}
return $rows;
}
/**
* 撤回消息
*
* @param int $type
* @param int $auth_id
* @param int $group_id
* @param int $id
* @access public
* @return array
*/
public static function recallMessage($type, $auth_id, $group_id, $id)
{
$chehui = 5;
if ($chehui <= 0) {
abort_error('没有开启此功能');
}
$message = DB::table('chat_message')->where('id', $id)->first();
if(!$message) {
abort_error('记录不存在了');
}
$outtime = time() - strtotime($message['created_dt']);
if($outtime > $chehui * 60) {
abort_error('已经超过'.$chehui.'分钟无法撤回');
}
if ($type == 'user') {
$receiver = [$auth_id, (int)$message['receive_id']];
} elseif ($type == 'group') {
$user_ids = DB::table('chat_group_user')->where('group_id', $group_id)->pluck('user_id');
foreach($user_ids as $user_id) {
$receiver[] = (int)$user_id;
}
}
$msg = '已撤回';
DB::table('chat_message')->where('id', $message['id'])->update([
'file_id' => 0,
'content' => $msg,
]);
$pushData = [
'send_id' => $auth_id,
'content' => $msg,
'event' => 'recallMessage',
'receive_ids' => $receiver,
'message_id' => (int)$message['id'],
];
$push = new PushService();
$push->send($pushData);
return $pushData;
}
/**
* 格式化消息
*
* @param array $rows
* @access public
* @return array
*/
public static function formatMessage($rows)
{
$file_ids = [];
foreach($rows as $row) {
if ($row['file_id'] > 0) {
$file_ids[] = $row['file_id'];
}
}
$imgext = ['gif','png','jpg','jpeg','bmp'];
if (count($file_ids) > 0) {
$model = DB::table('attachment');
$farr = [];
$files = $model->whereIn('id', $file_ids)->get();
foreach ($files as $file)
$farr[$file['id']] = $file;
if ($farr) {
foreach ($rows as $k => $row) {
$frs = [];
$fid = $row['file_id'];
if (isset($farr[$fid])) {
$frs = $farr[$fid];
$frs['fileext'] = $frs['type'];
$frs['fileid'] = $fid;
}
if ($frs) {
$type = $frs['type'];
$path = $frs['path'];
$boc = false;
if (substr($path, 0, 4) == 'http') {
$boc = true;
} else {
if (is_file(upload_path().'/'.$path)) {
$path = url('uploads/'.$path);
$frs['thumbpath'] = $path;
$frs['filepath'] = $path;
$frs['filesize'] = $frs['size'];
$frs['filesizecn'] = human_filesize($frs['size']);
$frs['filename'] = $frs['name'];
$boc = true;
}
}
if ($boc) {
if (in_array($type, $imgext)) {
// $frs['thumbpath'] = $fobj->getthumbpath($frs);
$rows[$k]['cont'] = '<img fid="'.$fid.'" src="'.$path.'">';
}
$rows[$k]['filers'] = $frs;
} else {
$rows[$k]['fileid'] = 0;
}
}
}
}
}
return $rows;
}
/**
* 获取用户
*
* @param int $user_id
* @param int $group_id
* @access public
* @return array
*/
public static function getUser($status = 1, $group_id = 1)
{
static $rows = null;
if ($rows == null) {
$model = DB::table('user');
if (is_numeric($status)) {
$model->where('status', $status);
}
if (is_numeric($group_id)) {
$model->where('group_id', $group_id);
}
$model->selectRaw("''as pingyin,tel,(CASE WHEN (gender = 1) THEN '男' ELSE '女' END) as sex, email, id, name, phone, phone as mobile, role_id, department_id, department_id as deptid");
$rows = $model->get()->keyBy('id');
}
return $rows;
}
/**
* 邀请用户到组
*
* @param string $ids
* @param int $group_id
*/
public static function inviteUser($auth, $group_id, $ids)
{
$user_ids = explode(',', $ids);
if (count($user_ids) > 0) {
foreach($user_ids as $index => $user_id) {
$model = GroupUser::firstOrNew([
'user_id' => $user_id,
'group_id' => $group_id,
]);
if ($model->exists == true) {
unset($user_ids[$index]);
}
$model->save();
}
if (count($user_ids) > 0) {
$users = DB::table('user')->whereIn('id', $user_ids)->get()->pluck('name')->implode(',');
$gets = [
"cont" => $auth['name'].'邀请['.$users.']加入本会话',
"sendid" => $auth['id'],
"receid" => $group_id,
"type" => 'group',
"optdt" => date('Y-m-d H:i:s'),
"zt" => 0,
"fileid" => '',
"msgid" => "",
"gid" => $group_id,
"nuid" => time(),
];
$json = ChatService::sendMessage('group', $auth['id'], $group_id, $gets);
}
}
}
/**
* 退出用户组
*
* @param int $group_id
* @param int $auth_id
* @access public
* @return void
*/
public static function exitGroup($group_id, $auth_id)
{
// 删除用户组权限
GroupUser::where('group_id', $group_id)
->where('user_id', $auth_id)
->delete();
// 删除组聊天记录
DB::table('chat_message_status')
->where('type', 'group')
->where('group_id', $group_id)
->where('user_id', $auth_id)
->delete();
// 删除会话记录
DB::table('chat_history')
->where('type', 'group')
->where('receive_id', $group_id)
->where('send_id', $auth_id)
->delete();
}
/**
* 删除服务器上记录
*
* @param string $type
* @param int $group_id
* @param int $auth_id
* @param string $ids
* @param int $day
* @access public
* @return void
*/
public static function clearRecord($type, $group_id, $auth_id, $ids = [], $day = 0)
{
DB::beginTransaction();
try {
// 获取聊天记录数量
$model = DB::table('chat_message_status')
->where('type', $type);
if (count($ids) > 0) {
$model->whereIn('message_id', $ids);
}
if ($type == 'group') {
$model->where('group_id', $group_id);
} else if ($type == 'user') {
$model->whereRaw("((group_id = '$group_id' and user_id = '$auth_id') or (group_id = '$auth_id' and user_id = '$group_id'))");
}
$messages = $model->groupBy('message_id')
->selectRaw('message_id, count(id) as count')
->get();
$model = DB::table('chat_message_status')
->where('group_id', $group_id)
->where('user_id', $auth_id);
if (count($ids) > 0) {
$model->whereIn('message_id', $ids);
}
$model->delete();
// 获取回话的最后消息id
$last_message_id = DB::table('chat_message_status')
->where('type', $type)
->where('group_id', $group_id)
->where('user_id', $auth_id)
->orderBy('message_id', 'desc')
->value('message_id');
// 更新回话的最后消息id
DB::table('chat_history')
->where('type', $type)
->where('receive_id', $group_id)
->where('send_id', $auth_id)
->update(['last_message_id' => (int)$last_message_id]);
// 删除消息状统计为1的数据
foreach($messages as $message) {
if ($message['count'] == 1) {
DB::table('chat_message')->where('id', $message['message_id'])->delete();
}
}
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
abort_error($e->getMessage());
}
}
/**
* 删除会话记录
*
* @param string $type
* @param int $group_id
* @param int $auth_id
* @access public
* @return void
*/
public static function clearHistory($type, $group_id, $auth_id)
{
DB::beginTransaction();
try {
// 获取聊天记录数量
$model = DB::table('chat_message_status')
->where('type', $type);
if ($type == 'group') {
$model->where('group_id', $group_id);
} else if ($type == 'user') {
$model->whereRaw("((group_id = '$group_id' and user_id = '$auth_id') or (group_id = '$auth_id' and user_id = '$group_id'))");
}
$messages = $model->groupBy('message_id')
->selectRaw('message_id, count(id) as count')
->get();
// 删除聊天记录
$model = DB::table('chat_message_status')
->where('type', $type)
->where('group_id', $group_id)
->where('user_id', $auth_id)
->delete();
// 删除会话记录
DB::table('chat_history')
->where('type', $type)
->where('receive_id', $group_id)
->where('send_id', $auth_id)
->delete();
// 删除消息状统计为1的数据
foreach($messages as $message) {
if ($message['count'] == 1) {
DB::table('chat_message')->where('id', $message['message_id'])->delete();
}
}
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
abort_error($e->getMessage());
}
}
/**
* 获取组和用户
*
* @param int $group_id
* @param int $auth_id
* @access public
* @return array
*/
public static function getGroupUser($group_id, $auth_id)
{
$group = DB::table('chat_group')->where('id', $group_id)->first();
$group['face'] = $group['logo'];
$group['deptid'] = $group['department_id'];
$group['utotal'] = DB::table('chat_group_user')->where('group_id', $group_id)->count();
$group['innei'] = DB::table('chat_group_user')->where('user_id', $auth_id)->count();
$rows = DB::table('chat_group_user as cgu')
->leftJoin('user', 'user.id', 'cgu.user_id')
->where('cgu.group_id', $group_id)
->get(['user.id', 'user.name', 'user.avatar as face']);
$users = [];
foreach($rows as $row) {
$row['face'] = avatar($row['avatar']);
$users[] = $row;
}
$json['infor'] = $group;
$json['uarr'] = $users;
return $json;
}
/**
* 获取发送者
* @access public
* @param int $type 回话类型
* @param int $send_id 发送人
* @param int $receive_id 接受者id如果是group那就是group_id
* @param int $user_id group的user_id
* @param int $message_id 消息id
* @return array
*/
public static function getReceiver($type, $receive_id, $send_id)
{
if ($type == 'user') {
$receiver = DB::table('user')
->where('id', $receive_id)
->selectRaw('id, name, role_id, department_id as deptid, avatar')
->first();
$receiver['face'] = avatar($receiver['avatar']);
$receiver['type'] = 'user';
$receiver['utotal'] = 0;
$receiver['gid'] = $receiver['id'];
}
else if ($type == 'group') {
$receiver = DB::table('chat_group')
->where('id', $receive_id)
->selectRaw('id, name, logo')
->first();
$receiver['face'] = $receiver['logo'];
$receiver['type'] = 'group';
// 查询用户数量
$receiver['utotal'] = DB::table('chat_group_user')
->where('group_id', $receive_id)
->count();
// 查询自己是否在组中
$receiver['innei'] = DB::table('chat_group_user')
->where('group_id', $receive_id)
->where('user_id', $send_id)
->count();
$receiver['gid'] = $receiver['id'];
}
return $receiver;
}
/**
* 获取发送者
* @access public
* @param int $type 回话类型
* @param int $send_id 发送人
* @param int $receive_id 接受者id如果是group那就是group_id
* @param array $data 发送内容
* @param int $client 0=app发送 1=web客户端
* @return array
*/
public static function sendMessage($type, $send_id, $receive_id, $data, $client = 1)
{
$gets = $data;
$data = [
'send_id' => $send_id,
'receive_id' => $receive_id,
"content" => $gets['cont'],
'type' => $type,
'url' => $gets['url'],
'file_id' => $gets['fileid'],
'created_dt' => date('Y-m-d H:i:s')
];
$message_id = Message::insertGetId($data);
// 返回数据
$json = [
"cont" => $gets['cont'],
"sendid" => $send_id,
"receid" => $receive_id,
"type" => $type,
"optdt" => date('Y-m-d H:i:s'),
"zt" => 0,
"fileid" => $gets['fileid'],
"msgid" => "",
"gid" => $receive_id,
"id" => $message_id,
"nuid" => $gets['nuid'],
];
$json['event'] = 'message';
$json['content'] = $gets['cont'];
$json['send_id'] = $send_id;
// 写入历史记录
$user_ids = ChatService::setHistory($type, $send_id, $receive_id, $message_id);
if ($type == 'user') {
// 写入已读(自己)
DB::table('chat_message_status')->insert([
'group_id' => $receive_id,
'user_id' => $send_id,
'message_id' => $message_id,
'status' => 1,
'type' => $type,
]);
// 写入未读(对方)
DB::table('chat_message_status')->insert([
'group_id' => $send_id,
'user_id' => $receive_id,
'message_id' => $message_id,
'status' => 0,
'type' => $type,
]);
} else if ($type == 'group') {
// 写入未读(讨论组)
foreach($user_ids as $user_id) {
// 设置为已读(自己)
$status = $send_id == $user_id ? 1 : 0;
DB::table('chat_message_status')->insert([
'group_id' => $receive_id,
'user_id' => $user_id,
'message_id' => $message_id,
'status' => $status,
'type' => $type,
]);
}
// 组的名称
$group = DB::table('chat_group')->where('id', $receive_id)->first();
$json['gname'] = $group['name'];
}
$json['receuid'] = join(',', $user_ids);
$json['receive_ids'] = $user_ids;
return $json;
}
/**
* 写入会话
* @access public
* @param int $type 会话类型
* @param int $send_id 发送人
* @param int $receive_id 接受者id如果是group那就是group_id
* @param int $user_id group的user_id
* @param int $message_id 消息id
* @return array
*/
public static function setHistory($type, $send_id, $receive_id, $message_id)
{
$model = History::firstOrNew([
'send_id' => $send_id,
'receive_id' => $receive_id,
'type' => $type,
]);
$model->last_message_id = $message_id;
$model->updated_dt = date('Y-m-d H:i:s');
$model->save();
if ($type == 'user') {
$receive_ids = [$send_id, $receive_id];
$model = History::firstOrNew([
'send_id' => $receive_id,
'receive_id' => $send_id,
'type' => $type,
]);
$model->last_message_id = $message_id;
$model->updated_dt = date('Y-m-d H:i:s');
if ($send_id != $receive_id) {
$model->unread_total = $model->unread_total + 1;
}
$model->save();
} else if($type == 'group') {
$user_ids = DB::table('chat_group_user')
->where('group_id', $receive_id)
->pluck('user_id');
// 写入接收者历史记录
foreach($user_ids as $user_id) {
// 返回所有接受者
$receive_ids[] = (int)$user_id;
// 发送人和接收人相同
if ($send_id == $user_id) {
continue;
}
$model = History::firstOrNew([
'send_id' => $user_id,
'receive_id' => $receive_id,
'type' => $type,
]);
$model->last_message_id = $message_id;
$model->updated_dt = date('Y-m-d H:i:s');
if ($send_id != $user_id) {
$model->unread_total = $model->unread_total + 1;
}
$model->save();
}
}
return array_unique($receive_ids);
}
/**
* 获取回话历史
*
* @param int $user_id
* @param datetime $updated_dt
* @param int $unread
* @access public
* @return array
*/
public static function getHistory($user_id, $updated_dt = '', $unread = 0)
{
$model = DB::table('chat_history as ch')
->leftJoin('chat_message as cm', 'cm.id', '=', 'ch.last_message_id')
->where('ch.send_id', $user_id)
->orderBy('ch.updated_dt', 'desc')
->selectRaw("
ch.type type,
ch.send_id uid,
ch.receive_id receid,
ch.send_id sendid,
".sql_month_day('ch.updated_dt')." optdts,
cm.content cont,
cm.id messid,
cm.send_id,
ch.unread_total stotal,
0 utotal,
ch.updated_dt as optdt
");
if ($updated_dt) {
$model->where('ch.updated_dt', '>', $updated_dt);
}
if ($unread) {
$model->where('ch.unread_total', '>', $unread);
}
$rows = $model->get();
$users = static::getUser();
$groups = static::getGroup();
$historys = [];
foreach ($rows as $row) {
if ($row['type'] == 'user') {
$row['face'] = avatar($users[$row['receid']]['avatar']);
$row['name'] = $users[$row['receid']]['name'];
if (empty($row['cont'])) {
$row['cont'] = '';
}
}
if ($row['type'] == 'group') {
$row['deptid'] = $groups[$row['receid']]['department_id'];
$row['face'] = $groups[$row['receid']]['face'];
$row['name'] = $groups[$row['receid']]['name'];
if (empty($row['cont'])) {
$row['cont'] = '';
} else {
$row['cont'] = $users[$row['send_id']]['name'].':'.$row['cont'];
}
}
$historys[] = $row;
}
return $historys;
}
}

View File

@ -1,100 +0,0 @@
<?php namespace Gdoo\Chat\Services;
class PushService
{
private $api;
private $key;
private $cert;
private $caPath;
private $connectTimeout;
private $timeout;
private $useSSL = false;
public function __construct() {
$this->api = env('REALTIME_API');
$this->key = env('REALTIME_KEY');
$this->api = $this->api.'?'.$this->generateSignature();
}
public function generateSignature() {
$timestamp = time();
$nonce = rand(10000, 99999);
$signature = hash_hmac('sha256', $this->key.$timestamp.$nonce, $this->key);
$query = "signature={$signature}&amp;timestamp={$timestamp}&amp;nonce={$nonce}";
return $query;
}
public function send(array $data) {
return $this->request($data);
}
public function useSSL(bool $value) {
$this->useSSL = $value;
return $this;
}
public function setCert(string $cert) {
$this->cert = $cert;
return $this;
}
public function setCAPath(string $caPath) {
$this->caPath = $caPath;
return $this;
}
public function setConnectTimeout(int $connectTimeout) {
$this->connectTimeout = $connectTimeout;
return $this;
}
public function setTimeout(int $timeout) {
$this->timeout = $timeout;
return $this;
}
private function request(array $params) {
$ch = curl_init();
if ($this->connectTimeout) {
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
}
if ($this->timeout) {
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
}
if ($this->useSSL) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
if ($this->cert) {
curl_setopt($ch, CURLOPT_CAINFO, $this->cert);
}
if ($this->caPath) {
curl_setopt($ch, CURLOPT_CAPATH, $this->caPath);
}
} else {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
}
curl_setopt($ch, CURLOPT_USERAGENT, 'realtime/1.0');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->getHeaders());
curl_setopt($ch, CURLOPT_URL, $this->api);
$data = curl_exec($ch);
$error = curl_error($ch);
$headers = curl_getinfo($ch);
curl_close($ch);
if (empty($headers["http_code"]) || ($headers["http_code"] != 200)) {
$data = '{"success":false,"code":'.$headers["http_code"].',"msg":"'.$error.'"}';
}
$json = json_decode($data, true);
return $json;
}
private function getHeaders() {
return [
'Content-Type: application/json',
];
}
}

View File

@ -1,124 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>{{$setting['title']}}</title>
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta name="format-detection" content="telephone=no"/>
<meta name="format-detection" content="email=no"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0"/>
<link rel="stylesheet" type="text/css" href="{{$asset_url}}/chat/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="{{$asset_url}}/chat/css/webimcss.css"/>
<link rel="stylesheet" type="text/css" href="{{$asset_url}}/chat/jquery/perfectscrollbar/perfect-scrollbar.css"/>
<link rel="stylesheet" type="text/css" href="{{$asset_url}}/chat/jquery/menu/jquery-rockmenu.css"/>
<link rel="stylesheet" type="text/css" href="{{$asset_url}}/chat/css/chat.css"/>
<link rel="shortcut icon" id="ico" href="{{$asset_url}}/chat/images/web/logo.png" />
<script type="text/javascript" src="{{$asset_url}}/vendor/jquery.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/js/js.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/js/nwjs.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/jquery/menu/jquery-rockmenu.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/js/notify.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/js/strformat.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/js/realtime.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/js/websocket.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/jquery/perfectscrollbar/perfect-scrollbar.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/jquery/perfectscrollbar/jquery.mousewheel.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/jquery/jquery-imgview.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/jquery/jquery-rockupload.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/jquery/jquery-rockmodels.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/jquery/jquery-changeuser.js"></script>
<script>
js.servernow = '{{date("Y-m-d H:i:s")}}';
companymode = false;
function globalbody() {
adminid = '{{$user["id"]}}';
adminface = '{{avatar($user["avatar"])}}';
adminname = '{{$user["name"]}}';
adminuser = '{{$user["username"]}}';
deptallname = '{{$user->department->name}}';
adminranking = '{{$user->role->name}}';
}
function initbody() {
reim.init();
}
function winfocus() {
window.focus();
}
</script>
</head>
<body style="overflow:hidden;" oncontextmenu="return true">
<div style="position:absolute;bottom:15px;left:0;width:60px;">
<div align="center" id="reimcog" class="cursor" style="color:#fff;font-size:16px">
<i class="fa fa-cog"></i>
</div>
</div>
<div id="mindivshow" style="height:538px;overflow:hidden;" class="mindivshow">
<table style="width:100%;" height="100%">
<tr valign="top">
<td height="100%" width="60" style="background:#1890ff;">
<div align="center" style="width:60px;overflow:hidden;">
<div style="margin-top:20px"><img title="{{$user['name']}}" onclick="reim.openmyinfo()" src="{{avatar($user['avatar'])}}" id="myface" style="border-radius:50%;" align="absmiddle" height="40" width="40">
</div>
<div style="margin-top:20px;">
<div class="cursor lefticons active" id="changetabs0" onclick="reim.changetabs(0)" title="消息">
<i class="fa fa-comments-o"></i>
<span id="chat_stotal" class="badge"></span>
</div>
</div>
<div style="margin-top:10px;">
<div class="cursor lefticons" id="changetabs1" onclick="reim.changetabs(1)" title="组织结构">
<i class="fa fa-sitemap"></i>
</div>
</div>
<div style="margin-top:10px;">
<div class="cursor lefticons" id="changetabs2" onclick="reim.changetabs(2)" title="应用">
<i class="fa fa-th-large"></i>
<span id="agenh_stotal" class="badge"></span>
</div>
</div>
</div>
</td>
<td width="220px" id="maincenter" style="background:#fff;border-right:1px solid #ddd">
<div class="chat_search">
<input id="reim_keysou" placeholder="搜索通讯录/会话/应用" class="msousou" />
<a class="plus" title="创建会话" onclick="reim.creategroup();">+</a>
</div>
<div id="centlist" style="height:300px;overflow:hidden;position:relative;">
<div id="centshow0">
<div id="historylist"></div>
<div id="historylist_tems" style="padding-top:150px;text-align:center;color:#ddd">
<span style="font-size:40px"><i class="fa fa-comment"></i></span><br>暂无消息
</div>
</div>
<div id="centshow1" style="display:none">
<div style="padding:5px;color:#aaaaaa;border-bottom:1px solid #f1f1f1">组织结构</div>
<div id="showdept"></div>
<div id="showgroup"></div>
<div align="center" style="padding:10px;"><a onclick="reim.initload(true)" style="font-size:12px;color:#bbbbbb" href="javascript:;"><i class="icon-refresh"></i> 刷新</a></div>
</div>
</div>
</td>
<td>
<div id="viewzhulist" style="height:300px;overflow:hidden;background:#f0f3f4;">
<div align="center" tabs="home" id="tabs_home" style="margin-top:100px;font-size:150px;color:#edf4fb">
<i class="fa fa-comment-o"></i>
</div>
</div>
</td>
</tr>
</table>
</div>
</body>
</html>

View File

@ -1,347 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{$setting['title']}}</title>
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="format-detection" content="telephone=no" />
<meta name="format-detection" content="email=no" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0" />
<link rel="stylesheet" type="text/css" href="{{$asset_url}}/chat/css/webimcss.css" />
<link rel="shortcut icon" id="icon_show" href="{{$asset_url}}/chat/images/web/logo.png" />
<script type="text/javascript" src="{{$asset_url}}/vendor/jquery.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/js/js.js"></script>
<script type="text/javascript" src="{{$asset_url}}/chat/js/nwjs.js"></script>
<style>
.lmaisft {
text-align: center;
-webkit-app-region: no-drag;
}
</style>
<script>
var temp_token = '';
var logifouct = false;
function initbody() {
js.xpbodysplit = 5;
nwjs.init();
resize();
$(window).resize(resize);
var face = js.getoption('loginface');
if (face) get('myface').src = face;
if (get('checkautologin')) {
get('checkautologin').checked = js.getoption('autologin') == '1';
form('adminuser').value = js.getoption('adminuser');
getpassobj().val(js.getoption('adminpass'));
autologin(3);
}
if (form('adminmobile')) form('adminmobile').value = js.getoption('adminmobile');
if (nwjsgui) {
$('#footerts').append('<a style="font-size:12px" onclick="return clearchater()" href="javascript:;">清缓存</a>');
}
// 禁止后退
try {
history.pushState(null, null, document.URL);
window.addEventListener('popstate', function() {
history.pushState(null, null, document.URL);
});
} catch (e) {}
if (winWb() > 320) {
rewinheight(400, 300);
}
if (jisxobo()) {
js.xpbodysplit = 0;
get('mindivshowzhu').style.margin = '0px';
}
}
// 是不是xp和win7的版本
function jisxobo() {
var llq = navigator.userAgent.toLowerCase();
if (llq.indexOf('windows nt 5') > 0 || llq.indexOf('windows nt 6.1') > 0) {
return true;
}
return false;
}
function clearchater() {
nwjsgui.App.clearCache();
localStorage.clear();
var na = nwjsgui.App.manifest.name;
js.confirm('基本缓存已删除,更多缓存删除,是否打开对应[' + na + ']目录?需手动全部删除目录。', function(jg) {
if (jg == 'yes') {
var naea = nwjsgui.App.dataPath;
var oru = naea.split(na)[0] + na;
nwjsgui.Shell.openItem(oru);
nwjsgui.App.quit();
}
});
}
function autologin(ms) {
if (!logifouct && get('checkautologin') && get('checkautologin').checked && form('adminuser').value != '' && getpassobj().val()) {
form('submitbtn').value = ms + ' 秒后自动登录';
if (ms == 0) {
loginsubmit();
} else {
setTimeout('autologin(' + (ms - 1) + ')', 1000);
}
} else {
form('submitbtn').value = '登录';
}
}
function bodyunload() {
nwjs.removetray();
}
function resize() {
var tt = $(window).height() - $('.lmaisft').height();
var ts = (tt * 0.5) - 20;
if (ts < 10) ts = 10;
var lx1 = 0;
if (jisxobo()) lx1 = 10;
$('#mindivshow').css('height', (winHb() - 42 + lx1) + 'px');
}
var loginyzm = '';
function loginsubmit(lx) {
var ltype = form('logintype').value,
user = '',
pass = '';
if (ltype == '0') {
user = form('adminuser').value;
pass = getpassobj().val();
if (user == '') {
js.msg('msg', '用户名不能为空');
form('adminuser').focus();
return false;
}
if (pass == '') {
js.msg('msg', '密码不能为空');
getpassobj().focus();
return false;
}
} else {
user = form('adminmobile').value;
if (user == '') {
js.msg('msg', '手机号不能为空');
form('adminmobile').focus();
return false;
}
js.setoption('adminmobile', user);
loginyzm = form('adminmobileyzm').value;
if (loginyzm == '' || loginyzm.length != 6) {
js.msg('msg', '手机验证码格式不对');
form('adminmobileyzm').focus();
return false;
}
}
js.setoption('adminuser', user);
js.setoption('adminpass', pass);
var btnobj = form('submitbtn');
btnobj.value = '登录中...';
btnobj.disabled = true;
var data = {};
var base_url = "{{$public_url}}/";
data.device = device;
data.cfrom = 'reim';
data.ltype = ltype;
data.adminuser = user;
data.adminpass = pass;
data.yanzm = loginyzm;
js.bool = true;
loginyzm = '';
js.ajax(base_url + 'chat/chat/login', data, function(a) {
if (a.success) {
get('myface').src = a.face;
btnobj.value = '登录成功';
js.setoption('loginface', a.face);
var url = base_url + 'chat/chat/index';
loginsuccess(a);
js.location(url);
} else {
btnobj.value = '登录';
js.msg('msg', a.msg);
btnobj.disabled = false;
if (a.shouji) {
mobilejsho = a.mobile;
js.prompt('输入手机验证码', '手机号:' + a.shouji + '&nbsp;<span><a class="zhu" href="javascript:;" onclick="getcodes(this)">[获取验证码]</a></span>', function(jg, txt) {
if (jg == 'yes' && txt) {
loginyzm = txt;
loginsubmit();
}
});
}
}
}, 'post,json');
}
function loginsuccess(a) {
$('#mindivshows').hide();
if (nwjsgui) {
rewinheight(600, 900);
}
}
function getpassobj() {
return $('input[type=password]');
}
function changeauto(o) {
var oi = '0';
if (o.checked) oi = '1';
js.setoption('autologin', oi);
}
function winclose() {
nwjs.closebool = true;
nwjs.win.close();
}
function rewinheight(hei, wid) {
var l = (screen.width - wid) * 0.5;
var t = (screen.height - hei) * 0.5 - 20;
nwjs.win.moveTo(parseInt(l), parseInt(t));
nwjs.win.resizeTo(wid, hei);
}
function getcodes(o1) {
var da = {
'mobile': mobilejsho,
'device': device
};
var o2 = $(o1).parent();
o2.html(js.getmsg('获取中...'));
js.ajax('api.php?m=yanzm', da, function(a) {
if (a.success) {
o2.html(js.getmsg('获取成功', 'green'));
} else {
o2.html(js.getmsg(a.msg));
}
}, 'post,json');
}
// 获取验证码
function getyzm(o1) {
mobilejsho = form('adminmobile').value;
if (!mobilejsho) {
js.msg('msg', '请输入手机号');
form('adminmobile').focus();
return;
}
var da = {
'mobile': mobilejsho,
'device': device
};
o1.value = '获取中...';
js.setmsg();
o1.disabled = true;
js.ajax('api.php?m=yanzm&a=glogin', da, function(a) {
if (a.success) {
o1.value = '获取成功';
js.msg('success', '验证码已发送到手机上');
dshitime(60, o1);
} else {
o1.value = '重新获取';
o1.disabled = false;
js.msg('msg', a.msg);
}
}, 'post,json');
}
function dshitime(sj, o1) {
if (sj == 0) {
o1.disabled = false;
o1.value = '重新获取';
return;
}
o1.disabled = true;
o1.value = sj + '';
setTimeout(function() {
dshitime(sj - 1, o1)
}, 1000);
}
function changlogin() {
$('#loginview0').hide();
$('#loginview1').show();
form('logintype').value = '1';
}
</script>
</head>
<body style="overflow:hidden;">
<div id="mindivshowzhu" style="background:#f5f5f5;overflow:hidden;height:100vh;">
<div align="center" id="mindivshow" style="height:348px;overflow:hidden;margin-top:30px;">
<div id="mindivshows">
<div class="lmaisft">
<div id="topblank" style="height:5px;overflow:hidden"></div>
<div style="user-select:none;-webkit-user-select: none;" align="center"><img onclick="location.reload()" title="{{url()}}" src="{{$asset_url}}/chat/images/web/logo.png" id="myface" style="border-radius:50%;" align="absmiddle" height="80" width="80"></div>
<div class="blank10"></div>
<form style="padding:10px;" name="myform">
<div id="loginview0">
<div>
<div><input type="text" onfocus="logifouct=true" style="height:35px;width:190px;border-radius:5px" class="input" onKeyUp="if(event.keyCode==13)getpassobj().focus()" maxlength="20" placeholder="请输入用户名" id="adminuser" name="adminuser"></div>
</div>
<div class="blank20"></div>
<div>
<div><input onfocus="logifouct=true" style="height:35px;width:190px;border-radius:5px" class="input" onKeyUp="if(event.keyCode==13)loginsubmit(1)" value="" type="password" placeholder="请输入密码"></div>
</div>
<div class="blank10"></div>
<div align="center">
<div style="width:190px" align="left"><label><input onclick="changeauto(this)" id="checkautologin" type="checkbox">下次自动登录</label></div>
</div>
</div>
<div id="loginview1" style="display:none">
<input type="hidden" name="logintype" value="0">
<div>
<input type="text" style="height:35px;width:190px;border-radius:5px" class="input" onKeyUp="if(event.keyCode==13)get('adminmobileyzm').focus()" maxlength="11" name="adminmobile" placeholder="请输入手机号">
</div>
<div class="blank20"></div>
<div align="center">
<table>
<tr>
<td>
<input class="input" style="height:35px;width:100px;border-top-left-radius:5px;border-bottom-left-radius:5px" name="adminmobileyzm" id="adminmobileyzm" onKeyUp="if(event.keyCode==13)loginsubmit(1)" maxlength="6" placeholder="请输入验证码">
</td>
<td><input type="button" onclick="getyzm(this)" style="height:35px;width:90px;border-top-right-radius:5px;border-bottom-right-radius:5px" value="获取验证码" class="webbtn"></td>
</tr>
</table>
</div>
</div>
<div class="blank20"></div>
<div align="center">
<input type="button" id="btn0" style="height:35px;width:190px;border-radius:5px;font-size:16px" onClick="loginsubmit(1)" class="btn" name="submitbtn" value="登录">
</div>
<span id="msgview"></span>
</form>
</div>
<div align="center" id="footerts" style="color:#888888;font-size:12px"></div>
</div>
</div>
</div>
</body>
</html>

View File

@ -2,15 +2,15 @@
use DB;
use Request;
use Gdoo\Index\Services\InfoService;
use Gdoo\Index\Controllers\DefaultController;
use Gdoo\Index\Services\InfoService;
class WidgetController extends DefaultController
{
public $permission = ['birthday', 'customerCount', 'customerContactCount'];
// 生日提醒
// 客户生日
public function birthday()
{
if (Request::method() == 'POST') {
@ -30,12 +30,11 @@ class WidgetController extends DefaultController
(datediff(dd, getdate(), dateadd(year, datediff(year, head_birthday, getdate())+1, head_birthday)) between 0 and 7)')
->selectRaw('id, code, name, head_name, head_phone, head_birthday')
->get();
}
else if($this->dbType == 'mysql') {
} else if($this->dbType == 'mysql') {
$model->whereRaw("
(concat(year(now()), DATE_FORMAT(head_birthday,'-%m-%d')) BETWEEN DATE_FORMAT(now(),'%Y-%m-%d') AND DATE_FORMAT(DATE_ADD(now(), interval 10 day),'%Y-%m-%d'))
(concat(year(now()), DATE_FORMAT(head_birthday,'-%m-%d')) BETWEEN DATE_FORMAT(now(),'%Y-%m-%d') AND DATE_FORMAT(DATE_ADD(now(), interval 7 day),'%Y-%m-%d'))
OR
(concat(year(now()) + 1, DATE_FORMAT(head_birthday,'-%m-%d')) BETWEEN DATE_FORMAT(now(),'%Y-%m-%d') AND DATE_FORMAT(DATE_ADD(now(), interval 10 day),'%Y-%m-%d'))")
(concat(year(now()) + 1, DATE_FORMAT(head_birthday,'-%m-%d')) BETWEEN DATE_FORMAT(now(),'%Y-%m-%d') AND DATE_FORMAT(DATE_ADD(now(), interval 7 day),'%Y-%m-%d'))")
->selectRaw("id, code, name, head_name, head_phone, concat(year(now()), DATE_FORMAT(head_birthday,'-%m-%d')) as head_birthday");
}
@ -78,12 +77,7 @@ class WidgetController extends DefaultController
'count2' => $count2,
'rate' => $rate,
];
return $this->render([
'dates' => $config['dates'],
'info' => $config['info'],
'res' => $res,
]);
return $this->json($res, true);
}
/**
@ -107,11 +101,6 @@ class WidgetController extends DefaultController
'count2' => $count2,
'rate' => $rate,
];
return $this->render([
'dates' => $config['dates'],
'info' => $config['info'],
'res' => $res,
]);
return $this->json($res, true);
}
}

View File

@ -65,6 +65,8 @@ class CustomerApplyHook
bank_account,
bank_address
')->first();
$apply['status'] = 1;
// 新建用户
$_user = [

View File

@ -19,7 +19,7 @@ class CustomerHook
public function onBeforeStore($params)
{
$master = $params['master'];
$_user = [
'role_id' => 2,
'group_id' => 2,
@ -45,7 +45,7 @@ class CustomerHook
// 客户开票单位为空
$count = CustomerTax::where('customer_id', $master['id'])->count();
if ($count == 0) {
// 自动新建开票单位
// 新建开票单位
CustomerTax::insert([
'code' => $master['code'],
'name' => $master['name'],
@ -65,6 +65,7 @@ class CustomerHook
if ($ret['error_code'] > 0) {
abort_error($ret['msg']);
}
return $params;
}

View File

@ -21,6 +21,7 @@ class TaxHook
}
public function onAfterStore($params) {
$master = $params['master'];
// 开票单位同步外部接口

View File

@ -50,19 +50,22 @@ return [
'name' => '客户生日',
'type' => 1,
'url' => 'customer/widget/birthday',
'more_url' => 'customer/customer/birthday',
'more_url' => 'customer/customer/index',
'params' => ['permission' => 'dept2', 'date' => 'last_day7'],
],
'info_customer_count' => [
'name' => '客户',
'type' => 2,
'url' => 'customer/widget/customerCount',
'more_url' => 'customer/customer/index',
'params' => ['permission' => 'dept2', 'date' => 'month'],
],
'info_customer_contact_count' => [
'name' => '客户联系人',
'type' => 2,
'url' => 'customer/widget/customerContactCount',
'more_url' => 'customer/contact/index',
'params' => ['permission' => 'dept2', 'date' => 'month'],
],
],
"listens" => [

View File

@ -31,8 +31,6 @@ Vue.createApp({
var setup = config.setup;
console.log(setup);
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据

View File

@ -34,7 +34,8 @@ Vue.createApp({
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据
grid.remoteData({page: 1}, function(res) {
grid.remoteData({page: 1}, function(res)
{
config.init(res);
});
});

View File

@ -8,12 +8,12 @@
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = {};
var columnDefs = [
{suppressMenu: true, cellClass:'text-center', field: "code", headerName: '客户编码', width: 120},
{suppressMenu: true, cellClass:'text-center', field: "name", headerName: '客户名称', minWidth: 160},
{suppressMenu: true, cellClass:'text-center', field: "head_name", headerName: '法人', width: 120},
{suppressMenu: true, cellClass:'text-center', field: "head_phone", headerName: '法人手机', width: 120},
{suppressMenu: true, cellClass:'text-center', field: "head_birthday", headerName: '法人生日', width: 120},
{suppressMenu: true, cellClass:'text-center', field: "id", headerName: 'ID', width: 80}
{suppressMenu: true, type:'sn', cellClass:'text-center', headerName: '序号', width: 60},
{suppressMenu: true, field: "code", cellClass:'text-center', headerName: '客户编码', width: 120},
{suppressMenu: true, field: "name", cellClass:'text-center', headerName: '客户名称', minWidth: 260},
{suppressMenu: true, field: "head_name", cellClass:'text-center', headerName: '法人', width: 120},
{suppressMenu: true, field: "head_phone", cellClass:'text-center', headerName: '法人手机', width: 120},
{suppressMenu: true, field: "head_birthday", cellClass:'text-center', headerName: '法人生日', width: 120},
];
grid.onRowDoubleClicked = function(row) {

View File

@ -1,15 +0,0 @@
<div class="panel panel-shadow info-skin1">
<div class="info-l hidden-xs" style="background-color:{{$info['color']}}">
<i class="fa fa-2x {{$info['icon']}}"></i>
</div>
<div class="info-c">
<div class="info-name">{{$info['name']}}</div>
<a href="javascript:;" data-toggle="addtab" data-url="{{$info['more_url']}}" data-id="{{str_replace(['/', '?', '='], ['_', '_', '_'], $info['more_url'])}}" data-name="{{$info['name']}}">
<div class="text-info info-item" data-id="{{$info['id']}}" data-more_url="{{$info['more_url']}}">{{$res['count']}}</div>
</a>
</div>
<div class="info-r">
<div>{{$dates[$info['params']['date']]}}</div>
<div class="rate @if($res['rate'] > 100) red @endif">{{$res['rate']}}%</div>
</div>
</div>

View File

@ -1,15 +0,0 @@
<div class="panel panel-shadow info-skin1">
<div class="info-l hidden-xs" style="background-color:{{$info['color']}}">
<i class="fa fa-2x {{$info['icon']}}"></i>
</div>
<div class="info-c">
<div class="info-name">{{$info['name']}}</div>
<a href="javascript:;" data-toggle="addtab" data-url="{{$info['more_url']}}" data-id="{{str_replace(['/', '?', '='], ['_', '_', '_'], $info['more_url'])}}" data-name="{{$info['name']}}">
<div class="text-info info-item" data-id="{{$info['id']}}" data-more_url="{{$info['more_url']}}">{{$res['count']}}</div>
</a>
</div>
<div class="info-r">
<div>{{$dates[$info['params']['date']]}}</div>
<div class="rate @if($res['rate'] > 100) red @endif">{{$res['rate']}}%</div>
</div>
</div>

View File

@ -1,120 +0,0 @@
<?php namespace Gdoo\CustomerCost\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\User\Models\User;
use Gdoo\CustomerCost\Models\Adjust;
use Gdoo\CustomerCost\Models\CostData;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\Index\Controllers\AuditController;
class AdjustController extends AuditController
{
public $permission = [];
public function index()
{
$header = Grid::header([
'code' => 'customer_cost_adjust',
'referer' => 1,
'search' => ['by' => ''],
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '显示',
'action' => 'show',
'display' => $this->access['show'],
]];
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['right_buttons'] = [
['name' => '关闭', 'color' => 'default', 'icon' => 'fa-lock', 'action' => 'close', 'display' => $this->access['close']],
];
$header['cols'] = $cols;
$header['tabs'] = Adjust::$tabs;
$header['bys'] = Adjust::$bys;
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order']);
$model->where('customer_cost.type_id', 86);
// 客户权限
$region = regionCustomer('customer_id_customer');
if ($region['authorise']) {
foreach ($region['whereIn'] as $key => $where) {
$model->whereIn($key, $where);
}
}
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$header['select'][] = 'customer_cost_data.cost_id';
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
return Grid::dataFilters($rows, $header);
}
return $this->display([
'header' => $header,
]);
}
public function create($action = 'edit')
{
$id = (int)Request::get('id');
// 客户权限
$header['region'] = ['field' => 'customer_id'];
$header['authorise'] = ['action' => 'index', 'field' => 'created_id'];
$header['code'] = 'customer_cost_adjust';
$header['id'] = $id;
$header['action'] = $action;
$form = Form::make($header);
return $this->display([
'form' => $form,
], 'create');
}
public function edit()
{
return $this->create();
}
public function show()
{
return $this->create('show');
}
public function delete()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'customer_cost_adjust', 'ids' => $ids]);
}
}
}

View File

@ -1,111 +0,0 @@
<?php namespace Gdoo\CustomerCost\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\CustomerCost\Models\Category;
use Gdoo\Index\Controllers\DefaultController;
class CategoryController extends DefaultController
{
public $permission = ['dialog'];
public function index()
{
$header = Grid::header([
'code' => 'customer_cost_category',
'referer' => 1,
'search' => ['by' => ''],
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '编辑',
'action' => 'edit',
'display' => $this->access['edit'],
]];
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['cols'] = $cols;
$header['tabs'] = Category::$tabs;
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy('sort', 'asc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
return Grid::dataFilters($rows, $header);
}
return $this->display([
'header' => $header,
]);
}
public function create()
{
$id = (int)Request::get('id');
$form = Form::make(['code' => 'customer_cost_category', 'id' => $id]);
return $this->render([
'form' => $form,
], 'create');
}
public function edit()
{
return $this->create();
}
public function dialog()
{
$search = search_form([], [
['text','customer_cost_category.name','名称'],
['text','customer_cost_category.id','ID'],
]);
if (Request::method() == 'POST') {
$model = Category::orderBy('sort', 'asc');
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$rows = $model->get(['*', 'name as text']);
return ['data' => $rows];
}
return $this->render([
'get' => Request::all()
]);
}
// 删除
public function delete()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'customer_cost_category', 'ids' => $ids]);
}
}
}

View File

@ -1,160 +0,0 @@
<?php namespace Gdoo\CustomerCost\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\User\Models\User;
use Gdoo\CustomerCost\Models\Compen;
use Gdoo\CustomerCost\Models\CostData;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\Index\Controllers\AuditController;
class CompenController extends AuditController
{
public $permission = ['importExcel'];
public function index()
{
$header = Grid::header([
'code' => 'customer_cost_compen',
'referer' => 1,
'search' => ['by' => ''],
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '显示',
'action' => 'show',
'display' => $this->access['show'],
]];
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['cols'] = $cols;
$header['tabs'] = Compen::$tabs;
$header['bys'] = Compen::$bys;
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order']);
$model->where('customer_cost.type_id', 87);
// 客户权限
$region = regionCustomer('customer_id_customer');
if ($region['authorise']) {
foreach ($region['whereIn'] as $key => $where) {
$model->whereIn($key, $where);
}
}
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$header['select'][] = 'customer_cost_data.cost_id';
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
return Grid::dataFilters($rows, $header);
}
return $this->display([
'header' => $header,
]);
}
public function create($action = 'edit')
{
$id = (int)Request::get('id');
// 客户权限
$header['region'] = ['field' => 'customer_id'];
$header['authorise'] = ['action' => 'index', 'field' => 'created_id'];
$header['code'] = 'customer_cost_compen';
$header['id'] = $id;
$header['action'] = $action;
$form = Form::make($header);
return $this->display([
'form' => $form,
], 'create');
}
public function edit()
{
return $this->create();
}
public function show()
{
return $this->create('show');
}
public function importExcel()
{
if (Request::method() == 'POST') {
$file = Request::file('file');
if ($file->isValid()) {
$types = DB::table('customer_order_type')->get()->keyBy('name');
/*
[0] => 客户编码
[1] => 客户名称
[2] => 金额
*/
$rows = readExcel($file->getPathName());
$items = [];
$codes = [];
foreach($rows as $i => $row) {
if ($i > 1) {
$codes[] = $row[0];
}
}
$customers = DB::table('customer')->whereIn('code', $codes)->get()->keyBy('code');
foreach($rows as $i => $row) {
if ($i > 1) {
$customer = $customers[$row[0]];
if (empty($customer)) {
return $this->json('客户编码'.$row[0].'不存在。');
}
$item = [
'customer_id' => $customer['id'],
'customer_id_name' => $customer['name'],
'money' => $row[2],
];
$items[] = $item;
}
}
return $this->json($items, true);
}
}
return view('importExcel');
}
public function delete()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'customer_cost_compen', 'ids' => $ids]);
}
}
}

View File

@ -1,243 +0,0 @@
<?php namespace Gdoo\CustomerCost\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\User\Models\User;
use Gdoo\CustomerCost\Models\Cost;
use Gdoo\CustomerCost\Models\CostData;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\Index\Controllers\AuditController;
class CostController extends AuditController
{
public $permission = ['dialog', 'serviceSaleOrder', 'useCount'];
public function index()
{
$header = Grid::header([
'code' => 'customer_cost',
'referer' => 1,
'search' => ['by' => ''],
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '显示',
'action' => 'show',
'display' => $this->access['show'],
]];
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['right_buttons'] = [
['name' => '关闭', 'color' => 'default', 'icon' => 'fa-lock', 'action' => 'close', 'display' => $this->access['close']],
['name' => '费用调整单', 'color' => 'info', 'icon' => 'fa-plus', 'action' => 'create4', 'display' => $this->access['create4']],
];
$header['cols'] = $cols;
$header['tabs'] = Cost::$tabs;
$header['bys'] = Cost::$bys;
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order']);
// 客户权限
$region = regionCustomer('customer_id_customer');
if ($region['authorise']) {
foreach ($region['whereIn'] as $key => $where) {
$model->whereIn($key, $where);
}
}
foreach ($search['where'] as $where) {
if ($where['active']) {
if ($where['field'] == 'customer_cost_data.tax_id') {
$customer_ids = DB::table('customer_tax')->where('id', $where['search'])->pluck('customer_id');
$model->whereIn('customer_cost_data.customer_id', $customer_ids);
} else {
$model->search($where);
}
}
}
$header['select'][] = 'customer_cost_data.src_id';
$header['select'][] = 'customer_cost_data.src_type_id';
$header['select'][] = 'customer_cost_data.cost_id';
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
return Grid::dataFilters($rows, $header);
}
return $this->display([
'header' => $header,
]);
}
public function create($action = 'edit')
{
$id = (int)Request::get('id');
// 客户权限
$header['region'] = ['field' => 'customer_id'];
$header['authorise'] = ['action' => 'index', 'field' => 'created_id'];
$header['code'] = 'customer_cost';
$header['id'] = $id;
$header['action'] = $action;
$form = Form::make($header);
return $this->display([
'form' => $form,
], 'create');
}
public function edit()
{
return $this->create();
}
public function show()
{
return $this->create('show');
}
// 费用参照到订单
public function serviceSaleOrder()
{
$header = Grid::header([
'code' => 'customer_cost',
'type' => 'dialog',
]);
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table('customer_cost_data')
->leftJoin('customer_cost', 'customer_cost.id', '=', 'customer_cost_data.cost_id')
->leftJoin('customer', 'customer.id', '=', 'customer_cost_data.customer_id')
->leftJoin('customer_cost_category', 'customer_cost_category.id', '=', 'customer_cost.category_id')
->whereRaw('(isnull(customer_cost_data.remain_money, 0) > 0 and isnull(customer_cost_data.use_close, 0) = 0)')
->where('customer_cost_data.customer_id', $query['customer_id'])
->selectRaw("
customer_cost_data.*,
customer.name as customer_name,
customer.code as customer_code,
customer_cost.sn,
customer_cost_data.src_sn as fee_src_sn,
customer_cost_data.src_type_id as fee_src_type_id,
customer_cost_data.src_id as fee_src_id,
customer_cost_data.id as fee_data_id,
customer_cost_category.name as fee_category_id_name,
customer_cost.category_id as fee_category_id,
'99001' as product_code,
'20226' as product_id,
'折扣额' as product_name,
'元' as product_unit,
'5' as type_id,
'费用' as type_id_name,
customer_cost_data.money as total_money,
customer_cost_data.use_money,
isnull(customer_cost_data.remain_money, 0) as money
");
if ($query['sort'] && $query['order']) {
$model->orderBy($query['sort'], $query['order']);
}
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$rows = $model->get();
$rows->transform(function($row) {
return $row;
});
return ['data' => $rows];
}
return $this->render([
'search' => $search,
'query' => $query,
]);
}
// 可用列表
public function useCount()
{
$customer_id = Request::get('customer_id');
$count = DB::table('customer_cost_data')
->where('customer_id', $customer_id)
->whereRaw('(isnull(remain_money, 0) > 0 and isnull(use_close, 0) = 0)')
->count();
return $this->json($count, true);
}
// 批量编辑
public function batchEdit()
{
$gets = Request::all();
if (Request::method() == 'POST') {
$ids = explode(',', $gets['ids']);
DB::table('customer_cost_data')->whereIn('id', $ids)->update([
$gets['field'] => $gets['search_0'],
]);
return $this->json('修改完成。', true);
}
$header = Grid::batchEdit([
'code' => 'customer_cost',
'columns' => ['customer_id'],
]);
return view('batchEdit', [
'gets' => $gets,
'header' => $header
]);
}
// 费用关闭
public function close()
{
$gets = Request::all();
if (Request::method() == 'POST') {
if (empty($gets['close_remark'])) {
return $this->json('原因必须填写。');
}
$cost = CostData::find($gets['id']);
$cost->close_remark = $gets['close_remark'];
$cost->use_close = $cost->use_close == 1 ? 0 : 1;
$cost->save();
return $this->json('恭喜你,操作成功。', url_referer('index'));
}
return $this->render([
'gets' => $gets,
]);
}
public function delete()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'customer_cost', 'ids' => $ids]);
}
}
}

View File

@ -1,156 +0,0 @@
<?php namespace Gdoo\CustomerCost\Controllers;
use DB;
use Request;
use Validator;
use Gdoo\User\Models\User;
use Gdoo\CustomerCost\Models\Rebate;
use Gdoo\CustomerCost\Models\CostData;
use Gdoo\Model\Grid;
use Gdoo\Model\Form;
use Gdoo\Index\Controllers\AuditController;
class RebateController extends AuditController
{
public $permission = ['importExcel'];
public function index()
{
$header = Grid::header([
'code' => 'customer_cost_rebate',
'referer' => 1,
'search' => ['by' => ''],
]);
$cols = $header['cols'];
$cols['actions']['options'] = [[
'name' => '显示',
'action' => 'show',
'display' => $this->access['show'],
]];
$header['buttons'] = [
['name' => '删除', 'icon' => 'fa-remove', 'action' => 'delete', 'display' => $this->access['delete']],
['name' => '导出', 'icon' => 'fa-share', 'action' => 'export', 'display' => 1],
];
$header['cols'] = $cols;
$header['tabs'] = Rebate::$tabs;
$header['bys'] = Rebate::$bys;
$search = $header['search_form'];
$query = $search['query'];
if (Request::method() == 'POST') {
$model = DB::table($header['table'])->setBy($header);
foreach ($header['join'] as $join) {
$model->leftJoin($join[0], $join[1], $join[2], $join[3]);
}
$model->orderBy($header['sort'], $header['order']);
$model->where('customer_cost.type_id', 88);
// 客户权限
$region = regionCustomer('customer_id_customer');
if ($region['authorise']) {
foreach ($region['whereIn'] as $key => $where) {
$model->whereIn($key, $where);
}
}
foreach ($search['where'] as $where) {
if ($where['active']) {
$model->search($where);
}
}
$header['select'][] = 'customer_cost_data.cost_id';
$model->select($header['select']);
$rows = $model->paginate($query['limit'])->appends($query);
return Grid::dataFilters($rows, $header);
}
return $this->display([
'header' => $header,
]);
}
public function create($action = 'edit')
{
$id = (int)Request::get('id');
// 客户权限
$header['region'] = ['field' => 'customer_id'];
$header['authorise'] = ['action' => 'index', 'field' => 'created_id'];
$header['code'] = 'customer_cost_rebate';
$header['id'] = $id;
$header['action'] = $action;
$form = Form::make($header);
return $this->display([
'form' => $form,
], 'create');
}
public function edit()
{
return $this->create();
}
public function show()
{
return $this->create('show');
}
public function importExcel()
{
if (Request::method() == 'POST') {
$file = Request::file('file');
if ($file->isValid()) {
/*
[0] => 客户编码
[1] => 客户名称
[2] => 金额
*/
$rows = readExcel($file->getPathName());
$items = [];
$codes = [];
foreach($rows as $i => $row) {
if ($i > 1) {
$codes[] = $row[0];
}
}
$customers = DB::table('customer')->whereIn('code', $codes)->get()->keyBy('code');
foreach($rows as $i => $row) {
if ($i > 1) {
$customer = $customers[$row[0]];
if (empty($customer)) {
return $this->json('客户编码'.$row[0].'不存在。');
}
$item = [
'customer_id' => $customer['id'],
'customer_id_name' => $customer['name'],
'money' => $row[2],
];
$items[] = $item;
}
}
return $this->json($items, true);
}
}
return view('importExcel');
}
public function delete()
{
if (Request::method() == 'POST') {
$ids = Request::get('id');
return Form::remove(['code' => 'customer_cost_rebate', 'ids' => $ids]);
}
}
}

View File

@ -1,97 +0,0 @@
<?php namespace Gdoo\CustomerCost\Controllers;
use DB;
use View;
use Request;
use Gdoo\Customer\Models\CustomerType;
use Gdoo\Index\Controllers\DefaultController;
class ReportController extends DefaultController
{
/**
* 费用使用统计
*/
public function saleOrderDetail()
{
$sdate = date('Y-m-01');
$edate = date('Y-m-d');
$search = search_form([],
[['form_type' => 'date2', 'name' => '订单日期', 'field' => 'date', 'value' => [$sdate, $edate], 'options' => []],
['form_type' => 'text', 'name' => '订单编号', 'field' => 'm.sn', 'options' => []],
['form_type' => 'text', 'name' => '单据编号', 'field' => 'd.fee_src_sn', 'options' => []],
[
'form_type' =>'dialog',
'field' => 'm.customer_id',
'name' => '所属客户',
'options' => ['url' => 'customer/customer/dialog', 'query' => []]
]/*,[
'form_type' =>'dialog',
'field' => 'region_id',
'name' => '销售组',
'options' => ['url' => 'customer/region/dialog', 'query' => ['layer' => 3]]
],*/
], 'model');
if (Request::method() == 'POST') {
$fields = [];
foreach($search['forms']['field'] as $i => $field) {
$fields[$field] = $search['forms']['search'][$i];
}
$model = DB::table('customer_order_data as d')
->leftJoin('product', 'product.id', '=', 'd.product_id')
->leftJoin('customer_order as m', 'm.id', '=', 'd.order_id')
->leftJoin('customer as c', 'c.id', '=', 'm.customer_id')
->leftJoin('customer_cost_category as ccc', 'ccc.id', '=', 'd.fee_category_id')
->selectRaw("
m.sn,
d.fee_src_sn,
d.fee_src_type_id,
Sum(d.money) as money,
c.code as customer_code,
c.name as customer_name,
ccc.name as category_name,
".sql_year_month('m.created_at', 'ts')." as [ym]
")
->whereRaw('d.fee_src_sn is not null')
->groupBy(DB::raw('c.code,c.name,ccc.name,m.sn,d.fee_src_sn,d.fee_src_type_id,'.sql_year_month('m.created_at', 'ts')));
foreach ($search['where'] as $where) {
if ($where['active']) {
if ($where['field'] == 'date') {
continue;
}
$model->search($where);
}
}
$rows = $model->orderBy('m.id', 'asc')
->get()->toArray();
foreach($rows as &$row) {
$money = abs($row['money']);
$row['money'] = $money;
}
return $this->json($rows, true);
}
$header = [
'table' => 'customer_cost',
'master_table' => 'customer_cost',
'buttons' => [],
'search_form' => $search,
'simple_search_form' => 0,
];
$header['left_buttons'] = [
['name' => '导出', 'color' => 'default', 'icon' => 'fa-mail-forward', 'action' => 'export', 'display' => 1],
];
return $this->display([
'search' => $search,
'header' => $header,
]);
}
}

View File

@ -1,15 +0,0 @@
<?php namespace Gdoo\CustomerCost\Hooks;
class CostDataHook
{
public function onBeforeStore($params)
{
$master = $params['master'];
$row = $params['row'];
$row['src_id'] = $master['id'];
$row['src_sn'] = $master['sn'];
$row['src_type_id'] = $master['type_id'];
$params['row'] = $row;
return $params;
}
}

View File

@ -1,27 +0,0 @@
<?php namespace Gdoo\CustomerCost\Hooks;
class CostHook
{
public function onBeforeForm($params)
{
return $params;
}
public function onAfterForm($params) {
return $params;
}
public function onBeforeStore($params)
{
return $params;
}
public function onAfterStore($params) {
return $params;
}
public function onBeforeDelete($params) {
return $params;
}
}

View File

@ -1,22 +0,0 @@
<?php namespace Gdoo\CustomerCost\Models;
class Adjust extends Cost
{
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'adjust.index', 'url' => 'customerCost/adjust/index', 'name' => '费用调整单'],
]
];
public static $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
}

View File

@ -1,15 +0,0 @@
<?php namespace Gdoo\CustomerCost\Models;
use Gdoo\Index\Models\BaseModel;
class Category extends BaseModel
{
protected $table = 'customer_cost_category';
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'category.index', 'url' => 'customerCost/category/index', 'name' => '费用类别'],
]
];
}

View File

@ -1,22 +0,0 @@
<?php namespace Gdoo\CustomerCost\Models;
class Compen extends Cost
{
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'compen.index', 'url' => 'customerCost/compen/index', 'name' => '合同补损'],
]
];
public static $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
}

View File

@ -1,31 +0,0 @@
<?php namespace Gdoo\CustomerCost\Models;
use Gdoo\Index\Models\BaseModel;
class Cost extends BaseModel
{
protected $table = 'customer_cost';
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'cost.index', 'url' => 'customerCost/cost/index', 'name' => '费用管理'],
]
];
public static $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
public function customer()
{
return $this->belongsTo('Gdoo\Customer\Models\Customer');
}
}

View File

@ -1,13 +0,0 @@
<?php namespace Gdoo\CustomerCost\Models;
use Gdoo\Index\Models\BaseModel;
class CostData extends BaseModel
{
protected $table = 'customer_cost_data';
public function customer()
{
return $this->belongsTo('Gdoo\Customer\Customer');
}
}

View File

@ -1,22 +0,0 @@
<?php namespace Gdoo\CustomerCost\Models;
class Rebate extends Cost
{
public static $tabs = [
'name' => 'tab',
'items' => [
['value' => 'rebate.index', 'url' => 'customerCost/rebate/index', 'name' => '合同返利'],
]
];
public static $bys = [
'name' => 'by',
'items' => [
['value' => '', 'name' => '全部'],
['value' => 'divider'],
['value' => 'day', 'name' => '今日创建'],
['value' => 'week', 'name' => '本周创建'],
['value' => 'month', 'name' => '本月创建'],
]
];
}

View File

@ -1,179 +0,0 @@
<?php
return [
"name" => "客户费用",
"version" => "1.0",
"description" => "客户费用管理。",
"listens" => [
'customer_cost' => 'Gdoo\CustomerCost\Hooks\CostHook',
'customer_cost_data' => 'Gdoo\CustomerCost\Hooks\CostDataHook',
],
'dialogs' => [
'customer_cost' => [
'name' => '客户费用列表',
'model' => 'Gdoo\Market\Models\Cost::Dialog',
'url' => 'customerCost/cost/dialog',
],
'customer_cost_data' => [
'name' => '客户费用明细表',
'model' => 'Gdoo\Market\Models\CostData::Dialog',
'url' => 'customerCost/cost/dialog',
],
'customer_cost_category' => [
'name' => '费用类别',
'model' => 'Gdoo\Market\Models\Category::Dialog',
'url' => 'customerCost/category/dialog',
],
],
"controllers" => [
"cost" => [
"name" => "客户费用",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"close" => [
"name" => "关闭"
],
"edit" => [
"name" => "编辑"
],
"audit" => [
"name" => "审核"
],
"abort" => [
"name" => "弃审"
],
"print" => [
"name" => "打印"
],
"delete" => [
"name" => "删除"
],
'batchEdit' => [
"name" => "批量编辑",
],
]
],
"adjust" => [
"name" => "费用调整单",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"audit" => [
"name" => "审核"
],
"abort" => [
"name" => "弃审"
],
"print" => [
"name" => "打印"
],
"delete" => [
"name" => "删除"
],
]
],
"compen" => [
"name" => "合同补损",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"audit" => [
"name" => "审核"
],
"abort" => [
"name" => "弃审"
],
"print" => [
"name" => "打印"
],
"delete" => [
"name" => "删除"
],
]
],
"rebate" => [
"name" => "合同返利",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"audit" => [
"name" => "审核"
],
"abort" => [
"name" => "弃审"
],
"print" => [
"name" => "打印"
],
"delete" => [
"name" => "删除"
],
]
],
"category" => [
"name" => "费用类别",
"actions" => [
"index" => [
"name" => "列表"
],
"show" => [
"name" => "查看"
],
"create" => [
"name" => "新建"
],
"edit" => [
"name" => "编辑"
],
"delete" => [
"name" => "删除"
],
]
],
"report" => [
"name" => "客户费用报表",
"actions" => [
"saleOrderDetail" => [
"name" => "费用使用明细表"
]
]
]
],
];

View File

@ -1,36 +0,0 @@
<div class="form-panel">
<div class="form-panel-header">
<div class="pull-right">
</div>
{{$form['btn']}}
</div>
<div class="form-panel-body panel-form-{{$form['action']}}">
<form class="form-horizontal form-controller" method="post" id="{{$form['table']}}" name="{{$form['table']}}">
{{$form['tpl']}}
<input type="hidden" name="customer_cost[type_id]" value="86">
</form>
</div>
</div>
<script>
var table = '{{$form["table"]}}';
(function($) {
// grid初始化事件
gdoo.event.set('grid.customer_cost_data', {
ready(me) {
grid = me;
grid.dataKey = 'customer_id';
}
});
// 子表对话框
gdoo.event.set('customer_cost_data.customer_id', {
query(query) {
},
onSelect(row, selectedRow) {
return true;
}
});
})(jQuery);
</script>

View File

@ -1,43 +0,0 @@
<div class="gdoo-list-page" id="{{$header['master_table']}}-page">
<div class="gdoo-list panel">
<div class="gdoo-list-header">
<gdoo-grid-header :header="header" :grid="grid" :action="action" />
</div>
<div class='gdoo-list-grid'>
<div id="{{$header['master_table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
</div>
<script>
Vue.createApp({
components: {
gdooGridHeader,
},
setup(props, ctx) {
var table = '{{$header["master_table"]}}';
var config = new gdoo.grid(table);
var grid = config.grid;
grid.remoteDataUrl = '{{url()}}';
var action = config.action;
// 详情页打开方式
action.dialogType = 'layer';
// 双击行执行的方法
action.rowDoubleClick = action.show;
var setup = config.setup;
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据
grid.remoteData({page: 1}, function(res) {
config.init(res);
});
});
return setup;
}
}).mount("#{{$header['master_table']}}-page");
</script>

View File

@ -1,3 +0,0 @@
<form class="form-horizontal form-controller" method="post" id="{{$form['table']}}" name="{{$form['table']}}">
{{$form['tpl']}}
</form>

View File

@ -1,87 +0,0 @@
<div class="form-panel">
<div class="form-panel-header">
<div class="pull-right">
</div>
{{$form['btn']}}
</div>
<div class="form-panel-body panel-form-{{$form['action']}}">
<form class="form-horizontal form-controller" method="post" id="{{$form['table']}}" name="{{$form['table']}}">
{{$form['tpl']}}
<input type="hidden" name="customer_cost[type_id]" value="87">
</form>
</div>
</div>
<script>
var table = '{{$form["table"]}}';
(function($) {
$('#customer_cost_data_tool').append('<a class="btn btn-sm btn-default" href="javascript:importExcel();">导入</a>');
$('#customer_cost_category_id').val(3);
$('#customer_cost_category_id_select').val(3);
// 导入记录
function importExcel() {
var url = app.url('customerCost/compen/importExcel');
formDialog({
title: '导入数据',
url: url,
id: 'import_excel',
dialogClass:'modal-md',
onSubmit: function() {
var me = this;
var form = $('#import_excel');
var file = document.querySelector("#import_file").files[0];
var formData = new FormData();
formData.append('file', file);
var loading = showLoading();
$.ajax(url, {
method: "post",
data: formData,
processData: false,
contentType: false,
complete: function() {
layer.close(loading);
},
success: function (res) {
if (res.status) {
grid.api.setRowData([]);
for (var i = 0; i < res.data.length; i++) {
var row = res.data[i];
grid.api.memoryStore.create(row);
}
grid.generatePinnedBottomData();
$(me).dialog('close');
toastrSuccess('导入数据成功。');
} else {
toastrError(res.data);
}
},
error: function (res) {
toastrError(res.data);
}
});
}
});
}
window.importExcel = importExcel;
// grid初始化事件
gdoo.event.set('grid.customer_cost_data', {
ready(me) {
grid = me;
grid.dataKey = 'customer_id';
}
});
// 子表对话框
gdoo.event.set('customer_cost_data.customer_id', {
query(query) {
},
onSelect(row, selectedRow) {
return true;
}
});
})(jQuery);
</script>

View File

@ -1,43 +0,0 @@
<div class="gdoo-list-page" id="{{$header['master_table']}}-page">
<div class="gdoo-list panel">
<div class="gdoo-list-header">
<gdoo-grid-header :header="header" :grid="grid" :action="action" />
</div>
<div class='gdoo-list-grid'>
<div id="{{$header['master_table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
</div>
<script>
Vue.createApp({
components: {
gdooGridHeader,
},
setup(props, ctx) {
var table = '{{$header["master_table"]}}';
var config = new gdoo.grid(table);
var grid = config.grid;
grid.remoteDataUrl = '{{url()}}';
var action = config.action;
// 详情页打开方式
action.dialogType = 'layer';
// 双击行执行的方法
action.rowDoubleClick = action.show;
var setup = config.setup;
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据
grid.remoteData({page: 1}, function(res) {
config.init(res);
});
});
return setup;
}
}).mount("#{{$header['master_table']}}-page");
</script>

View File

@ -1,6 +0,0 @@
<div class="wrapper-sm">
<form id="customer_cost_data_form-close" name="customer_cost_data_form-close" class="form-horizontal" method="post">
<textarea class="form-control" name="close_remark" placeholder="请输入关闭或恢复原因"></textarea>
<input value="{{$gets['id']}}" name="id" type="hidden">
</form>
</div>

View File

@ -1,36 +0,0 @@
<div class="form-panel">
<div class="form-panel-header">
<div class="pull-right">
</div>
{{$form['btn']}}
</div>
<div class="form-panel-body panel-form-{{$form['action']}}">
<form class="form-horizontal form-controller" method="post" id="{{$form['table']}}" name="{{$form['table']}}">
{{$form['tpl']}}
<input type="hidden" name="customer_cost[type_id]" value="46">
</form>
</div>
</div>
<script>
var table = '{{$form["table"]}}';
(function($) {
// grid初始化事件
gdoo.event.set('grid.customer_cost_data', {
ready(me) {
grid = me;
grid.dataKey = 'customer_id';
}
});
// 子表对话框
gdoo.event.set('customer_cost_data.customer_id', {
query(query) {
},
onSelect(row, selectedRow) {
return true;
}
});
})(jQuery);
</script>

View File

@ -1,122 +0,0 @@
<div class="wrapper" style="padding-bottom:0;">
<div id="dialog-customer-toolbar">
<form id="dialog-customer-search-form" name="dialog_customer_search_form" class="form-inline" method="get">
@include('searchForm')
</form>
</div>
<div class="m-t">
<table id="dialog-customer" class="table-condensed"></table>
<div id="dialog-customer-page"></div>
</div>
</div>
<script>
(function($) {
var selectBox = {};
var params = {{json_encode($gets)}};
var $table = $("#dialog-customer");
var model = [
{name: "text", index: 'user.name', label: '客户名称', width: 220, align: 'left'},
{name: "username", index: 'user.username', label: '客户代码', minWidth: 180, align: 'center'},
{name: "id", index: 'user.id', label: 'ID', width: 60, align: 'center'}
];
$table.jqGrid({
caption: '',
datatype: 'json',
mtype: 'POST',
url: app.url('customer/customer/dialog'),
colModel: model,
rowNum: 25,
multiboxonly: params.multi == 0 ? true : false,
multiselect: true,
viewrecords: true,
rownumbers: false,
height: 340,
footerrow: false,
postData: params,
pager: '#dialog-customer-page',
gridComplete: function() {
// 单选时禁用全选按钮
if(params.multi == 0) {
$("#cb_" + this.p.id).prop('disabled', true);
}
$(this).jqGrid('setColsWidth');
},
loadComplete: function(res) {
var me = $(this);
me.jqGrid('initPagination', res);
// 设置默认选中
setSelecteds(res);
},
// 双击选中
ondblClickRow: function(id) {
if(params.multi == 1) {
$table.jqGrid('setSelection', id);
}
getSelecteds();
},
});
function setSelecteds(res) {
var ids = $('#'+params.id).val();
ids = ids.split(',');
$.each(ids, function(k, v) {
if(v) {
$table.jqGrid('setSelection', v);
}
});
}
function getSelecteds(dialog) {
var rows = $table.jqGrid('getSelections');
if(params.multi == 0) {
if(rows.length > 1) {
toastrError('只能选择一项。');
return false;
}
}
var id = [], text = [];
for (var i = 0; i < rows.length; i++) {
id.push(rows[i].id);
text.push(rows[i].text);
}
// 回写数据
$('#'+params.id).val(id.join(','));
$('#'+params.id+'_text').val(text.join(','));
// 关闭窗口
$(dialog).dialog("close");
return true;
}
window.selectBox = {getSelecteds: getSelecteds};
var data = {{json_encode($search['forms'])}};
var search = $('#dialog-customer-search-form').searchForm({
data: data,
init:function(e) {}
});
search.find('#search-submit').on('click', function() {
var query = search.serializeArray();
$.map(query, function(row) {
params[row.name] = row.value;
});
$table.jqGrid('setGridParam', {
postData: params,
page: 1
}).trigger('reloadGrid');
return false;
});
})(jQuery);
</script>

View File

@ -1,94 +0,0 @@
<div class="gdoo-list-page" id="{{$header['master_table']}}-page">
<div class="gdoo-list panel">
<div class="gdoo-list-header">
<gdoo-grid-header :header="header" :grid="grid" :action="action" />
</div>
<div class='gdoo-list-grid'>
<div id="{{$header['master_table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
</div>
<script>
Vue.createApp({
components: {
gdooGridHeader,
},
setup(props, ctx) {
var table = '{{$header["master_table"]}}';
var config = new gdoo.grid(table);
var grid = config.grid;
grid.remoteDataUrl = '{{url()}}';
var action = config.action;
// 详情页打开方式
action.dialogType = 'layer';
// 双击行执行的方法
action.rowDoubleClick = function (data) {
if (data.master_id > 0) {
var index = data.master_sn.indexOf('QTFY');
if (index >= 0) {
data.src_type_id = 46;
}
if (data.src_type_id == 46) {
top.addTab('customerCost/cost/show?id=' + data.master_id, 'customerCost_cost_show', '其他费用');
}
if (data.src_type_id == 55) {
top.addTab('promotion/review/show?id=' + data.src_id, 'promotion_review_show', '促销核销');
}
if (data.src_type_id == 57) {
top.addTab('approach/review/show?id=' + data.src_id, 'approach_review_show', '进店核销');
}
if (data.src_type_id == 87) {
top.addTab('customerCost/compen/show?id=' + data.master_id, 'customerCost_compen_show', '合同补损');
}
if (data.src_type_id == 88) {
top.addTab('customerCost/rebate/show?id=' + data.master_id, 'customerCost_rebate_show', '合同返利');
}
if (data.src_type_id == 86) {
top.addTab('customerCost/adjust/show?id=' + data.master_id, 'customerCost_adjust_show', '费用调整');
}
}
};
// 关闭费用
action.close = function(data) {
var me = this;
var grid = config.grid;
var selections = grid.api.getSelectedRows();
if (selections.length != 1) {
toastrError('只能选择一行记录');
return;
}
formDialog({
title: '关闭费用',
url: app.url('customerCost/cost/close', {id: selections[0].id}),
storeUrl: app.url('customerCost/cost/close'),
id: 'customer_cost_data_form-close',
dialogClass:'modal-sm',
success: function(res) {
toastrSuccess(res.data);
grid.remoteData();
$(this).dialog("close");
},
error: function(res) {
toastrError(res.data);
}
});
}
var setup = config.setup;
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据
grid.remoteData({page: 1}, function(res) {
config.init(res);
});
});
return setup;
}
}).mount("#{{$header['master_table']}}-page");
</script>

View File

@ -1,55 +0,0 @@
<style>
.modal-body { overflow:hidden; }
</style>
<div class="wrapper-xs">
<form id="dialog-customer_cost-search-form" name="dialog_customer_cost_search_form" class="form-inline search-inline-form" method="get">
@include('searchForm3')
</form>
</div>
<div id="ref_customer_cost" class="ag-theme-balham" style="width:100%;height:380px;"></div>
<script>
var $ref_customer_cost = null;
var params = JSON.parse('{{json_encode($query)}}');
(function($) {
var grid = new agGridOptions();
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = params;
grid.rowMultiSelectWithClick = false;
grid.rowSelection = 'multiple';
grid.columnDefs = [
{cellClass:'text-center', checkboxSelection: true, headerCheckboxSelection: true, suppressSizeToFit: true, sortable: false, width: 40},
{cellClass:'text-center', sortable: false, field: 'sn', headerName: '单据编号', minWidth: 160},
{cellClass:'text-center', sortable: false, field: 'fee_category_id_name', headerName: '费用类型', width: 100},
{cellClass:'text-center', sortable: false, field: 'customer_code', headerName: '客户编码', width: 100},
{cellClass:'text-center', sortable: false, field: 'customer_name', headerName: '客户名称', width: 100},
{cellClass:'text-right', sortable: false, type:'number', field: 'total_money', headerName: '费用金额', width: 100},
{cellClass:'text-right', sortable: false, type:'number', field: 'money', headerName: '可用金额', width: 100},
{cellClass:'text-right', sortable: false, type:'number', field: 'use_money', headerName: '已用金额', width: 100},
{cellClass:'text-center', field: 'id', headerName: 'ID', width: 60}
];
var gridDiv = document.querySelector("#ref_customer_cost");
new agGrid.Grid(gridDiv, grid);
grid.remoteData();
$ref_customer_cost = grid;
var data = JSON.parse('{{json_encode($search["forms"])}}');
var search = $('#dialog-customer_cost-search-form').searchForm({
data: data,
init:function(e) {}
});
search.find('#search-submit').on('click', function() {
var query = search.serializeArray();
$.map(query, function(row) {
params[row.name] = row.value;
});
grid.remoteData(params);
return false;
});
})(jQuery);
</script>

View File

@ -1,88 +0,0 @@
<div class="form-panel">
<div class="form-panel-header">
<div class="pull-right">
</div>
{{$form['btn']}}
</div>
<div class="form-panel-body panel-form-{{$form['action']}}">
<form class="form-horizontal form-controller" method="post" id="{{$form['table']}}" name="{{$form['table']}}">
{{$form['tpl']}}
<input type="hidden" name="customer_cost[type_id]" value="88">
</form>
</div>
</div>
<script>
var table = '{{$form["table"]}}';
(function($) {
$('#customer_cost-tool').html(' <a class="btn m-b-sm btn-sm btn-default" href="javascript:importExcel();">导入</a> ');
$('#customer_cost_category_id').val(2);
$('#customer_cost_category_id_select').val(2);
// 导入记录
function importExcel() {
var url = app.url('customerCost/rebate/importExcel');
formDialog({
title: '导入数据',
url: url,
id: 'import_excel',
dialogClass:'modal-md',
onSubmit: function() {
var me = this;
var form = $('#import_excel');
var file = document.querySelector("#import_file").files[0];
var formData = new FormData();
formData.append('file', file);
var loading = showLoading();
$.ajax(url, {
method: "post",
data: formData,
processData: false,
contentType: false,
complete: function() {
layer.close(loading);
},
success: function (res) {
if (res.status) {
grid.api.setRowData([]);
for (var i = 0; i < res.data.length; i++) {
var row = res.data[i];
grid.api.memoryStore.create(row);
}
grid.generatePinnedBottomData();
$(me).dialog('close');
toastrSuccess('导入数据成功。');
} else {
toastrError(res.data);
}
},
error: function (res) {
toastrError(res.data);
}
});
}
});
}
window.importExcel = importExcel;
// grid初始化事件
gdoo.event.set('grid.customer_cost_data', {
ready(me) {
grid = me;
grid.dataKey = 'customer_id';
}
});
// 子表对话框
gdoo.event.set('customer_cost_data.customer_id', {
query(query) {
},
onSelect(row, selectedRow) {
return true;
}
});
})(jQuery);
</script>

View File

@ -1,43 +0,0 @@
<div class="gdoo-list-page" id="{{$header['master_table']}}-page">
<div class="gdoo-list panel">
<div class="gdoo-list-header">
<gdoo-grid-header :header="header" :grid="grid" :action="action" />
</div>
<div class='gdoo-list-grid'>
<div id="{{$header['master_table']}}-grid" class="ag-theme-balham"></div>
</div>
</div>
</div>
<script>
Vue.createApp({
components: {
gdooGridHeader,
},
setup(props, ctx) {
var table = '{{$header["master_table"]}}';
var config = new gdoo.grid(table);
var grid = config.grid;
grid.remoteDataUrl = '{{url()}}';
var action = config.action;
// 详情页打开方式
action.dialogType = 'layer';
// 双击行执行的方法
action.rowDoubleClick = action.show;
var setup = config.setup;
Vue.onMounted(function() {
var gridDiv = config.div(136);
// 初始化数据
grid.remoteData({page: 1}, function(res) {
config.init(res);
});
});
return setup;
}
}).mount("#{{$header['master_table']}}-page");
</script>

View File

@ -1,103 +0,0 @@
<div class="panel b-a" id="{{$header['master_table']}}-controller">
@include('headers')
<div class='gdoo-list-grid'>
<div id="{{$header['master_table']}}-grid" style="width:100%;" class="ag-theme-balham"></div>
</div>
</div>
<script>
(function ($) {
var table = '{{$header["master_table"]}}';
var search = JSON.parse('{{json_encode($header["search_form"])}}');
var columns = [];
var params = search.query;
var grid = new agGridOptions();
grid.remoteDataUrl = '{{url()}}';
grid.remoteParams = params;
grid.defaultColDef.suppressMenu = true;
grid.defaultColDef.sortable = true;
grid.defaultColDef.filter = false;
grid.autoColumnsToFit = false;
grid.singleClickEdit = true;
grid.rowSelection = 'single';
grid.suppressCellSelection = false;
grid.defaultColDef.cellStyle = function(params) {
if (params.node.rowPinned) {
return;
}
var style = {};
var field = params.colDef.field;
if (params.data.status == '0' && (field == "customer_code" || field == "customer_name")) {
style = {'color':'red'};
}
return style;
};
grid.columnDefs = [
{cellClass:'text-center', field: 'sn', type: 'sn', headerName: '序号', width: 60},
//{cellClass:'text-center', field: 'region_name', headerName: '区域', width: 100},
{cellClass:'text-center', field: 'customer_code', headerName: '客户编码', width: 80},
{cellClass:'text-left', field: 'customer_name', headerName: '所属客户', width: 180},
{cellClass:'text-center', field: 'ym', headerName: '日期', width: 100},
{cellClass:'text-center', field: 'sn', headerName: '订单编号', width: 140},
{cellClass:'text-center', field: 'category_name', headerName: '单据类型', width: 140},
{cellClass:'text-center', field: 'fee_src_sn', headerName: '单据编号', width: 140},
{cellClass:'text-right', field: 'money', headerName: '金额', width: 100, type:'number', numberOptions: {places:2}, calcFooter: 'sum'},
];
var gridDiv = document.querySelector("#{{$header['master_table']}}-grid");
new agGrid.Grid(gridDiv, grid);
gridDiv.style.height = getPanelHeight(12);
grid.remoteData();
var search_advanced = $('#' + table + '-search-form-advanced').searchForm({
data: search.forms,
advanced: true,
});
gdoo.grids[table] = {grid: grid};
var action = new gridAction(table, '销售订单费用明细表');
var panel = $('#' + table + '-controller');
panel.on('click', '[data-toggle="' + table + '"]', function() {
var data = $(this).data();
if (data.action == 'filter') {
// 过滤数据
$('#' + table + '-search-form-advanced').dialog({
title: '条件筛选',
modalClass: 'no-padder',
buttons: [{
text: "取消",
'class': "btn-default",
click: function() {
$(this).dialog("close");
}
},{
text: "确定",
'class': "btn-info",
click: function() {
var query = search_advanced.serializeArray();
params = {};
$.map(query, function(row) {
params[row.name] = row.value;
});
grid.remoteData(params);
$(this).dialog("close");
return false;
}
}]
});
}
if (data.action == 'export') {
action.export(data, '销售订单费用明细表');
}
});
})(jQuery);
</script>

View File

@ -8,6 +8,7 @@ use App\Support\Pinyin;
use Gdoo\User\Models\User;
use Gdoo\Index\Models\Notification;
use Cron\CronExpression;
class ApiController extends Controller
{
@ -36,7 +37,7 @@ class ApiController extends Controller
$rows = DB::table('cron')->where('status', 1)->get();
if ($rows) {
foreach ($rows as $row) {
$cron = \Cron\CronExpression::factory($row['expression']);
$cron = new \Cron\CronExpression($row['expression']);
// 由于定时任务无法定义秒这里特殊处理一下
if (strtotime($row['next_run']) <= time()) {

View File

@ -15,7 +15,7 @@ class Controller extends BaseController
/**
* @var 程序版本
*/
public $version = '2.4.0';
public $version = '2.5.0';
/**
* @var 配置参数

View File

@ -29,6 +29,7 @@ class DashboardController extends DefaultController
$widgets->transform(function ($row) use($user_widgets) {
$user_widget = $user_widgets[$row['id']];
if (not_empty($user_widget)) {
$row['id'] = $user_widget['id'];
$row['status'] = $user_widget['status'];
$row['grid'] = $user_widget['grid'];
$row['sort'] = $user_widget['sort'];
@ -41,10 +42,11 @@ class DashboardController extends DefaultController
if ($user_widget['icon']) {
$row['icon'] = $user_widget['icon'];
}
$row['params'] = json_decode($user_widget['params'], true);
} else {
$row['status'] = $row['default'] == 1;
}
$row['params'] = json_decode($user_widget['params'], true);
$row['key'] = str_replace(['/', '?', '='], ['_', '_', '_'], $row['url']);
return $row;
});
$widgets = $widgets->sortBy('sort')->values();
@ -64,6 +66,7 @@ class DashboardController extends DefaultController
$infos->transform(function ($row) use($user_infos) {
$user_info = $user_infos[$row['id']];
if (not_empty($user_info)) {
$row['id'] = $user_info['id'];
$row['status'] = $user_info['status'];
$row['sort'] = $user_info['sort'];
if ($user_info['name']) {
@ -75,10 +78,13 @@ class DashboardController extends DefaultController
if ($user_info['icon']) {
$row['icon'] = $user_info['icon'];
}
$row['params'] = json_decode($user_info['params'], true);
$params = $user_info['params'];
} else {
$row['status'] = $row['default'] == 1;
$params = $row['params'];
}
$row['params'] = json_decode($params, true);
$row['key'] = str_replace(['/', '?', '='], ['_', '_', '_'], $row['more_url']);
return $row;
});
$infos = $infos->sortBy('sort')->values();
@ -99,14 +105,57 @@ class DashboardController extends DefaultController
return $row;
});
$dates = [
'day' => '今天',
'day2' => '昨天',
'week' => '本周',
'week2' => '上周',
'month' => '本月',
'month2' => '上月',
'season' => '本季度',
'season2' => '上季度',
'year' => '本年',
'year2' => '去年',
];
$dates2 = [
'day' => '昨天',
'day2' => '前天',
'week' => '上周',
'week2' => '前周',
'month' => '上月',
'month2' => '前月',
'season' => '上季度',
'season2' => '前季度',
'year' => '去年',
'year2' => '前年',
];
$dates3 = [
'last_day7' => '最近7天',
'last_day28' => '最近28天',
'last_month' => '上个月',
'last_year' => '去年',
];
$cards = [];
$grids = ['8', '4'];
return $this->display([
$vars = [
'dates' => $dates,
'dates2' => $dates2,
'dates3' => $dates3,
'cards' => $cards,
'widgets' => $widgets,
'infos' => $infos,
'grids' => $grids,
'quicks' => $quicks,
]);
];
if (Request::method() == 'POST') {
return $this->json($vars, true);
}
return $this->display($vars);
}
// 仪表板设置
@ -120,6 +169,9 @@ class DashboardController extends DefaultController
$sort = 1;
foreach($widgets as $widget) {
$widget['sort'] = $sort;
if ($widget['permission'] && $widget['date']) {
$widget['params'] = json_encode(['permission' => $widget['permission'], 'date' => $widget['date']], JSON_UNESCAPED_UNICODE);
}
$sort ++;
$model = UserWidget::firstOrNew(['type' => 1, 'node_id' => $widget['id'], 'user_id' => $auth['id']]);
$model->fill($widget);
@ -185,6 +237,8 @@ class DashboardController extends DefaultController
if ($user_widget['icon']) {
$row['icon'] = $user_widget['icon'];
}
} else {
$row['status'] = 0;
}
return $row;
});
@ -219,6 +273,8 @@ class DashboardController extends DefaultController
$row['icon'] = $user_info['icon'];
}
$row['params'] = json_decode($user_info['params'], true);
} else {
$row['status'] = 0;
}
return $row;
});
@ -261,6 +317,41 @@ class DashboardController extends DefaultController
// 设置单个组件
public function settingInfo()
{
$auth = auth()->user();
$id = Request::input('id');
$info = Widget::where('id', $id)
->selectRaw('*,name as info_name')
->first();
$user_info = UserWidget::where('user_id', $auth['id'])
->where('node_id', $info['id'])
->first();
$params = json_decode($info['params'], true);
$user_params = json_decode($user_info['params'], true);
$params['date'] = not_empty($params['date']) ? $params['date'] : 'month';
$params['permission'] = not_empty($params['permission']) ? $params['permission'] : 'dept2';
if ($user_info['name']) {
$info['name'] = $user_info['name'];
}
if ($user_info['icon']) {
$info['icon'] = $user_info['icon'];
}
if ($user_info['color']) {
$info['color'] = $user_info['color'];
}
if ($user_params['date']) {
$params['date'] = $user_params['date'];
}
if ($user_params['permission']) {
$params['permission'] = $user_params['permission'];
}
$info['params'] = $params;
// 定义权限
$permissions = option('role.access')->pluck('name', 'id');
$dates = [
@ -275,49 +366,68 @@ class DashboardController extends DefaultController
'year' => '本年',
'year2' => '去年',
];
$info_id = Request::input('info_id');
$row = UserWidget::where('id', $info_id)->first();
$widget = Widget::where('id', $row['node_id'])->first();
$params = json_decode($row['params'], true);
if (empty($params['date'])) {
$params['date'] = 'month';
}
if (empty($params['permission'])) {
$params['permission'] = 'dept';
}
$row['params'] = $params;
$row['widget_name'] = $widget['name'];
return $this->render([
'permissions' => $permissions,
'dates' => $dates,
'row' => $row,
'info' => $info,
]);
}
// 设置单个组件
public function settingWidget()
{
$widget_id = Request::input('widget_id');
$row = UserWidget::where('id', $widget_id)->first();
$widget = Widget::where('id', $row['node_id'])->first();
$params = json_decode($row['params'], true);
$auth = auth()->user();
$id = Request::input('id');
if (empty($params['date'])) {
$params['date'] = 'month';
$widget = Widget::where('id', $id)
->selectRaw('*,name as widget_name')
->first();
$user_widget = UserWidget::where('user_id', $auth['id'])
->where('node_id', $widget['id'])
->first();
$params = json_decode($widget['params'], true);
$user_params = json_decode($user_widget['params'], true);
if ($params['date']) {
if ($user_params['date']) {
$params['date'] = $user_params['date'];
}
}
if (empty($params['permission'])) {
$params['permission'] = 'dept';
if ($params['permission']) {
if ($user_params['permission']) {
$params['permission'] = $user_params['permission'];
}
}
$row['params'] = $params;
$row['widget_name'] = $widget['name'];
if ($user_widget['name']) {
$info['name'] = $user_widget['name'];
}
if ($user_widget['icon']) {
$widget['icon'] = $user_widget['icon'];
}
if ($user_widget['color']) {
$widget['color'] = $user_widget['color'];
}
$widget['params'] = $params;
// 定义权限
$permissions = option('role.access')->pluck('name', 'id');
$dates = [
'last_day7' => '最近7天',
'last_day28' => '最近28天',
'last_month' => '上个月',
'last_year' => '去年',
];
return $this->render([
'row' => $row,
'permissions' => $permissions,
'dates' => $dates,
'widget' => $widget,
]);
}
}

View File

@ -62,6 +62,7 @@ class DefaultController extends Controller
if (Request::method() == 'POST') {
// 检查表单
$valid = Form::flowRules($models, $gets);
if ($valid['rules']) {
$v = Validator::make($gets, $valid['rules'], $valid['messages'], $valid['attributes']);
if ($v->fails()) {

View File

@ -1,5 +1,6 @@
<?php namespace Gdoo\Index\Controllers;
use App\Jobs\SendSms;
use DB;
use URL;
use Request;
@ -14,5 +15,7 @@ class DemoController extends Controller
public function hello()
{
$abc = SendSms::dispatch([1], '我是测试', '我也是测试');
print_r($abc);
}
}

View File

@ -18,50 +18,34 @@ class InfoService
return [$a, $b];
}
public static function getInfo($table)
public static function getInfo($table, $field = 'created_at', $type = 'ts')
{
$auth = auth()->user();
$gets = Request::all();
$dates = [
'day' => '昨天',
'day2' => '前天',
'week' => '上周',
'week2' => '前周',
'month' => '上月',
'month2' => '前月',
'quarter' => '上季度',
'quarter2' => '前季度',
'year' => '去年',
'year2' => '前年',
];
$params = $gets['params'];
$info = Widget::where('id', $gets['id'])
->first();
$user_info = UserWidget::where('user_id', $auth['id'])
->where('node_id', $gets['id'])->first();
->where('node_id', $gets['id'])
->first();
if (not_empty($user_info)) {
$info['id'] = $user_info['id'];
if ($user_info['name']) {
$info['name'] = $user_info['name'];
}
if ($user_info['color']) {
$info['color'] = $user_info['color'];
}
if ($user_info['icon']) {
$info['icon'] = $user_info['icon'];
}
if ($user_info['name']) {
$info['name'] = $user_info['name'];
}
if ($user_info['color']) {
$info['color'] = $user_info['color'];
}
if ($user_info['icon']) {
$info['icon'] = $user_info['icon'];
}
if ($user_info['params']) {
$info['params'] = json_decode($user_info['params'], true);
}
$params = $info['params'];
$permission = empty($params['permission']) ? 'department' : $params['permission'];
$permission = empty($params['permission']) ? 'dept2' : $params['permission'];
$date = empty($params['date']) ? 'month' : $params['date'];
$params['permission'] = $permission;
$params['date'] = $date;
$info['params'] = $params;
switch ($date) {
case 'day':
@ -100,53 +84,116 @@ class InfoService
// 年
$year = date('Y');
$year2 = $year - 1;
$year3 = $year - 2;
$year3 = $year - 2;
break;
}
$sql = $sql2 = '';
$key = $table.'.'.$field;
switch ($date) {
case 'day':
$sql = sql_year_month_day($table.'.created_at','ts')."='$day'";
$sql2 = sql_year_month_day($table.'.created_at','ts')."='$day2'";
$sql = sql_year_month_day($key, $type)." = '$day'";
$sql2 = sql_year_month_day($key, $type)." = '$day2'";
break;
case 'day2':
$sql = sql_year_month_day($table.'.created_at','ts')."='$day2'";
$sql2 = sql_year_month_day($table.'.created_at','ts')."='$day3'";
$sql = sql_year_month_day($key, $type)." = '$day2'";
$sql2 = sql_year_month_day($key, $type)." = '$day3'";
break;
case 'week':
$sql = sql_year_month_day($table.'.created_at','ts')." between '$week[0]' and '$week[1]'";
$sql2 = sql_year_month_day($table.'.created_at','ts')." between '$week2[0]' and '$week2[1]'";
$sql = sql_year_month_day($key, $type)." between '$week[0]' and '$week[1]'";
$sql2 = sql_year_month_day($key, $type)." between '$week2[0]' and '$week2[1]'";
break;
case 'week2':
$sql = sql_year_month_day($table.'.created_at','ts')." between '$week2[0]' and '$week2[1]'";
$sql2 = sql_year_month_day($table.'.created_at','ts')." between '$week3[0]' and '$week3[1]'";
$sql = sql_year_month_day($key, $type)." between '$week2[0]' and '$week2[1]'";
$sql2 = sql_year_month_day($key, $type)." between '$week3[0]' and '$week3[1]'";
break;
case 'month':
$sql = sql_year_month($table.'.created_at','ts')."='$month'";
$sql2 = sql_year_month($table.'.created_at','ts')."='$month2'";
$sql = sql_year_month($key, $type)." = '$month'";
$sql2 = sql_year_month($key, $type)." = '$month2'";
break;
case 'month2':
$sql = sql_year_month($table.'.created_at','ts')."='$month2'";
$sql2 = sql_year_month($table.'.created_at','ts')."='$month3'";
$sql = sql_year_month($key, $type)." = '$month2'";
$sql2 = sql_year_month($key, $type)." = '$month3'";
break;
case 'season':
$sql = sql_year_month_day($table.'.created_at','ts')." between '$season[0]' and '$season[1]'";
$sql2 = sql_year_month_day($table.'.created_at','ts')." between '$season2[0]' and '$season2[1]'";
$sql = sql_year_month_day($key, $type)." between '$season[0]' and '$season[1]'";
$sql2 = sql_year_month_day($key, $type)." between '$season2[0]' and '$season2[1]'";
break;
case 'season2':
$sql = sql_year_month_day($table.'.created_at','ts')." between '$season2[0]' and '$season2[1]'";
$sql2 = sql_year_month_day($table.'.created_at','ts')." between '$season3[0]' and '$season3[1]'";
$sql = sql_year_month_day($key, $type)." between '$season2[0]' and '$season2[1]'";
$sql2 = sql_year_month_day($key, $type)." between '$season3[0]' and '$season3[1]'";
break;
case 'year':
$sql = sql_year($table.'.created_at','ts')."='$year'";
$sql2 = sql_year($table.'.created_at','ts')."='$year2'";
$sql = sql_year($key, $type)." = '$year'";
$sql2 = sql_year($key, $type)." = '$year2'";
break;
case 'year2':
$sql = sql_year($table.'.created_at','ts')."='$year2'";
$sql2 = sql_year($table.'.created_at','ts')."='$year3'";
$sql = sql_year($key, $type)." = '$year2'";
$sql2 = sql_year($key, $type)." = '$year3'";
break;
}
return ['info' => $info, 'dates' => $dates, 'sql' => $sql, 'sql2' => $sql2, 'gets' => $gets, 'params' => $params, 'auth' => $auth];
return ['info' => $info, 'sql' => $sql, 'sql2' => $sql2, 'gets' => $gets, 'params' => $params, 'auth' => $auth];
}
public static function getWidget($table, $field = 'created_at', $type = 'ts')
{
$auth = auth()->user();
$gets = Request::all();
$params = $gets['params'];
$widget = Widget::where('id', $gets['id'])
->first();
$user_widget = UserWidget::where('user_id', $auth['id'])
->where('node_id', $gets['id'])
->first();
if ($user_widget['name']) {
$widget['name'] = $user_widget['name'];
}
if ($user_widget['color']) {
$widget['color'] = $user_widget['color'];
}
if ($user_widget['icon']) {
$widget['icon'] = $user_widget['icon'];
}
if ($user_widget['params']) {
$widget['params'] = json_decode($user_widget['params'], true);
}
$permission = empty($params['permission']) ? 'dept2' : $params['permission'];
$date = empty($params['date']) ? 'month' : $params['date'];
switch ($date) {
case 'last_day7':
$day = date('Y-m-d');
$day2 = date('Y-m-d', strtotime('-7 day'));
case 'last_day28':
$day = date('Y-m-d');
$day2 = date('Y-m-d', strtotime('-28 day'));
break;
case 'last_month':
$month2 = date('Y-m', strtotime("-1 month"));
break;
case 'year2':
$year2 = date('Y', strtotime("-1 year"));
break;
}
$sql = '';
$key = $table.'.'.$field;
switch ($date) {
case 'day7':
case 'day28':
$sql = sql_year_month_day($key, $type)." between '$day' and '$day2'";
break;
case 'last_month':
$sql = sql_year_month($key, $type)." = '$month2'";
break;
case 'year2':
$sql = sql_year($key, $type)." = '$year2'";
break;
}
return ['widget' => $widget, 'sql' => $sql, 'gets' => $gets, 'params' => $params, 'auth' => $auth];
}
}

View File

@ -11,20 +11,18 @@ class ShareService
public static function getItemsSourceBy(array $source_type, $user_id, $start_at = null, $end_at = null)
{
$user = User::find($user_id);
$model = Share::leftJoin('user', 'share.created_id', '=', 'user.id')
$model = Share::leftJoin('user', 'share.created_by', '=', 'user.id')
->permission('share.receive_id', $user)
->whereIn('share.source_type', $source_type);
$start_at = strtotime($start_at);
$end_at = strtotime($end_at) + 86400;
if ($start_at > 0 && $end_at > 0) {
$model->whereRaw('
$model->whereRaw('(
(share.start_at between '.$start_at.' and '.$end_at.' or share.end_at between '.$start_at.' and '.$end_at.')
or (share.is_repeat = 1 and share.start_at <= '.$end_at.')
');
)');
}
return $model->get(['share.*', 'user.name', 'user.username']);
}

View File

@ -1,3 +1,6 @@
<link href="{{$asset_url}}/vendor/element-plus/index.css" rel="stylesheet" type="text/css" />
<script src="{{$asset_url}}/vendor/element-plus/index.js" type="text/javascript"></script>
<style type="text/css">
html {
overflow: hidden;
@ -85,17 +88,23 @@ a { outline: none; }
text-align: center;
}
.row-info .panel { display: flex; padding-bottom: 10px; position: relative; text-align: center; border-radius: 4px !important; }
.info-skin1 .info-l { color: #fff; margin-top:16px; margin-left: 15px; border-radius: 50%; width: 50px; height:50px; line-height:58px; vertical-align: middle; }
.info-skin1 { padding-bottom: 10px; display: flex; position: relative; text-align: center; border-radius: 4px !important; }
.info-skin1 .info-l { color: #fff; margin-top:18px; margin-left: 15px; border-radius: 50%; width: 50px; height:50px; line-height:55px; vertical-align: middle; }
.info-skin1 .info-l .fa { font-size: 19px; }
.info-skin1 .info-c { flex:1; margin-left: 15px; text-align: left; }
.info-skin1 .info-c .info-name { margin-top:18px; font-size: 14px; color: #666; }
.info-skin1 .info-c .info-item { font-size: 24px; color: #333; }
.info-skin1 .info-r {
flex:1;
padding-right:5px;
}
.info-skin1 .info-a { display: flex; align-items:center; justify-content:space-between; padding-left: 15px; text-align: left; }
.info-skin1 .info-a .info-name { padding-top:15px; font-size: 14px; color: #666; }
.info-skin1 .info-a .el-input__inner { border: 0; text-align: right; }
.info-skin1 .info-r { margin-left: auto; margin-top:18px; width: 70px; line-height:22px; }
.info-skin1 .info-r .rate { color: #2bbf24; }
.info-skin1 .info-r .red { color:#f00; }
.info-skin1 .info-r::before { position:absolute;top:22px;content:"";width:1px;height:40px;background-color:#e6e6e6;display:block; }
.info-skin1 .info-b { padding-right:10px; display: flex; align-items:center; justify-content:space-between; padding-left: 15px; padding-top:5px; }
.info-skin1 .info-b .info-item { font-size: 24px; color: #333; }
.info-skin1 .info-b .rate { color: #999; }
.info-skin1 .info-b .red { color:#f00; }
.info-skin1 .info-b .green { color: #39c15b; }
.info-items { height: 94px; }
.app-title {
@ -119,16 +128,21 @@ a { outline: none; }
}
.row-widget .panel-heading {
padding: 10px;
padding: 8px;
height: 45px;
color: #2490f8;
font-size: 14px;
text-align: left;
}
.row-widget .panel-heading .widget_name {
font-size: 15px;
padding-top: 4px;
padding-left: 5px;
}
.row-widget .widget-item {
text-align: left;
}
.row-widget .widget-item .red {
font-size: 15px;
font-size: 16px;
font-weight: bold;
color: #333;
}
@ -173,7 +187,6 @@ a { outline: none; }
}
.row-quick {
margin-bottom: 10px;
padding: 10px;
}
.quick-text {
@ -200,7 +213,6 @@ a { outline: none; }
background: #f00;
border-radius: 100%;
border: solid 1px #f05050;
display: none;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12);
}
@ -222,76 +234,145 @@ a { outline: none; }
.dropdown-toggle {
border: solid 1px rgba(0, 0, 0, 0.1);
}
[v-cloak] {
display: none;
}
.gd-el-card { margin-left: 0; margin-right: 0; }
.gd-el-card .el-col { padding: 5px; }
.gd-el-card-header {
display:flex; align-items:center; justify-content:space-between; padding: 10px 0px;
}
.gd-el-card-header .gd-el-left {
font-size: 16px;
margin-left: 10px;
}
.gd-el-card-header .gd-el-right {
margin-right: 10px;
}
</style>
<div class="dashboard-widget">
@verbatim
<div id="gdoo-app" v-cloak>
<div class="pull-right hidden-xs">
<a class="dashboard-config" data-toggle="dashboard-config" title="仪表盘设置">
<a href="javascript:;" class="dashboard-config" @click="dashboardConfig" title="仪表盘设置">
<i class="fa fa-gear"></i>
</a>
</div>
<div class="row-quick">
<div class="row row-sm">
@forelse($quicks as $quick)
<div class="quick-text">
<a href="javascript:;" data-toggle="addtab" data-url="{{$quick['url']}}" data-id="{{$quick['key']}}" data-name="{{$quick['name']}}">
<div class="quick-icon quick-item" style="background-color:{{$quick['color']}}" data-url="{{$quick['url']}}" data-key="{{$quick['key']}}">
<i class="fa fa-3x {{$quick['icon']}}"></i>
<span class="quick-num">0</span>
</div>
<div class="title">{{$quick['name']}}</div>
</a>
</div>
@empty
<div class="quick-text">
<a href="javascript:;" data-toggle="dashboard-config">
<div class="quick-text" v-for="quick in dashboard.quicks">
<a href="javascript:;" data-toggle="addtab" :data-url="quick.url" :data-id="quick.key" :data-name="quick.name">
<div class="quick-icon quick-item" :style="'background-color:' + quick.color" :data-url="quick.url" :data-key="quick.key">
<i :class="'fa fa-3x ' + quick.icon"></i>
<span class="quick-num" v-if="quick.total > 0">{{quick.total}}</span>
</div>
<div class="title">{{quick.name}}</div>
</a>
</div>
<div class="quick-text" v-if="dashboard.add_quick">
<a href="javascript:;" @click="dashboardConfig">
<div class="quick-icon" style="background-color:#13D06C;">
<i class="fa fa-3x fa-plus"></i>
</div>
<div class="title">添加快捷</div>
</a>
</div>
@endforelse
</div>
</div>
<div class="row row-sm row-info">
@foreach($infos as $info)
@if($info['status'])
<div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">
<div class="info-items" data-id="{{$info['id']}}" data-url="{{$info['url']}}" data-more_url="{{$info['more_url']}}"></div>
</div>
@endif
@endforeach
</div>
<div class="row row-sm row-widget">
@foreach($grids as $grid)
<div class="col-xs-12 col-sm-{{$grid}}">
@foreach($widgets as $widget)
@if($widget['status'])
@if($widget['grid'] == $grid)
<div class="panel panel-shadow">
<div class="panel-heading text-base b-b">
<div class="pull-right"></div>
<a data-toggle='widget-refresh' data-url="{{$widget['url']}}" data-key="{{str_replace(['/', '?', '='], ['_', '_', '_'], $widget['url'])}}" data-id="{{$widget['id']}}">{{$widget['name']}}</a>
<div class="row row-sm gd-el-card">
<el-row>
<template v-for="info in dashboard.infos">
<el-col :xs="24" :sm="12" :md="8" :lg="6" v-if="info.status">
<el-card class="box-card panel-shadow" shadow="hover" body-style="padding:0px;">
<div class="info-skin1">
<div class="info-l" :style="'background-color:' + info.color">
<i :class="'fa fa-2x ' + info.icon"></i>
</div>
<div class="info-r">
<div class="info-a">
<div class="info-name">{{info.name}}</div>
<div>
<el-select @change="getInfoData(info)" style="width:90px;padding-top:10px;" v-model="info.params.date" size="mini" placeholder="请选择">
<el-option v-for="(v, k) in dashboard.dates" :key="k" :label="v" :value="k">
</el-option>
</el-select>
</div>
</div>
<div class="info-b">
<div>
<a href="javascript:;" data-toggle="addtab" :data-url="info.more_url" :data-id="info.key" :data-name="info.name">
<div class="text-info info-item">{{info.res.count || 0}}</div>
</a>
</div>
<div class="rate" v-if="info.params.date">
<span>{{dashboard.dates2[info.params.date]}}:</span>
<span :class="info.res.rate > 0 ? 'red' : 'green'">
{{info.res.rate}}%<i :class="info.res.rate > 0 ? 'el-icon-caret-top' : 'el-icon-caret-bottom'"></i>
</span>
</div>
<div class="widget-item" id="widget_item_{{$widget['id']}}" data-id="{{$widget['id']}}" data-url="{{$widget['url']}}">
</div>
</div>
@endif
@endif
@endforeach
</div>
@endforeach
</div>
</el-card>
</el-col>
</template>
</el-row>
</div>
<div class="row row-sm gd-el-card">
<el-row>
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-for="card in dashboard.cards">
<el-card class="box-card panel-shadow" shadow="hover" body-style="padding:0px;">
<div class="gd-el-card-header">
<span class="gd-el-left">名称</span>
<span class="gd-el-right">
<el-select style="width:90px;" v-model="value" size="mini" placeholder="请选择">
<el-option v-for="(v, k) in dashboard.dates" :key="k" :label="v" :value="k"></el-option>
</el-select>
</span>
</div>
</el-card>
</el-col>
</el-row>
</div>
<div class="row row-sm row-widget m-t-xs">
<div :class="'col-xs-12 col-sm-' + grid" v-for="grid in dashboard.grids">
<template v-for="widget in dashboard.widgets">
<div class="panel panel-shadow" v-if="widget.status && widget.grid == grid">
<div class="panel-heading text-base b-b">
<div class="pull-right">
<el-select @change="getWidgetData(widget)" style="width:100px;" v-if="widget.params && widget.params.date" v-model="widget.params.date" size="mini" placeholder="请选择">
<el-option v-for="(v, k) in dashboard.dates3" :key="k" :label="v" :value="k">
</el-option>
</el-select>
</div>
<div class="widget_name">
<a @click="widgetRefresh(widget.key)">{{widget.name}}</a>
</div>
</div>
<div class="widget-item" :id="'widget_item_' + widget.id"></div>
</div>
</template>
</div>
</div>
</div>
@endverbatim
</div>
<div class="dashboard-footer">
<div class="box">
{{$edition}} {{$version}}
{{$version}}
</div>
</div>
@ -318,28 +399,117 @@ a { outline: none; }
</style>
<script>
(function($) {
var $document = $(document);
(function(window, undefined) {
var myProcess = null;
function widgetRefresh() {
if (myProcess) {
var items = $('.widget-item');
items.each(function(index, item) {
var data = $(item).data();
if (data.key) {
gdoo.widgets[data.key].remoteData({page: 1});
console.log('refresh item:' + data.key);
const GdooApp = {
data() {
return {
dashboard: {
add_quick: 0,
infos: [],
quicks: [],
widgets: [],
cards: [],
grids: [],
dates: {},
dates2: {}
},
};
},
created() {
var me = this;
$.post('index/dashboard/index', function(res) {
if (res.status) {
me.dashboard = res.data;
me.dashboard.add_quick = me.dashboard.quicks.length > 0 ? 0 : 1;
me.dashboard.quicks.forEach((quick) => {
me.getBadge(quick);
});
me.dashboard.infos.forEach((info) => {
me.getInfoData(info);
});
me.dashboard.widgets.forEach((widget) => {
me.getWidgetData(widget);
});
} else {
toastrError(res.data);
}
});
me.widgetsRefresh();
},
methods: {
dashboardConfig() {
formDialog({
title: '仪表盘设置',
url: '/index/dashboard/config',
id: 'widget-edit',
dialogClass:'modal-lg',
onSubmit: function() {
var me = this;
var data = settingWidget.save();
$.post('/index/dashboard/config', data, function(res) {
if (res.status) {
location.reload();
toastrSuccess(res.data);
$(me).dialog("close");
} else {
toastrError(res.data);
}
});
}
});
},
getBadge(quick) {
$.get('/index/index/badge', {key: quick.key}, function(res) {
quick.total = res.total;
});
},
getInfoData(info) {
info.res = {};
$.post('/' + info.url, info, function(res) {
info.res = res.data;
});
},
getWidgetData(widget) {
if (widget.url) {
$.get('/' + widget.url, {id: widget.id}, function(res) {
$('#widget_item_' + widget.id).html(res);
});
}
},
widgetRefresh(key) {
if (key) {
gdoo.widgets[key].remoteData({page: 1});
}
},
widgetsRefresh() {
var me = this;
if (myProcess) {
me.dashboard.widgets.forEach((widget) => {
me.widgetRefresh(widget.key);
});
}
myProcess = setTimeout(function() {
me.widgetsRefresh();
}, 1000 * 60 * 3);
}
}
myProcess = setTimeout(function() {
widgetRefresh();
}, 1000 * 60 * 5);
}
};
const app = Vue.createApp(GdooApp);
app.use(ElementPlus);
app.mount("#gdoo-app");
})(window);
</script>
widgetRefresh();
<script>
(function($) {
var $document = $(document);
$document.on('click', '[data-toggle="addtab"]', function(event) {
event.preventDefault();
@ -357,69 +527,5 @@ a { outline: none; }
}
top.addTab(data.url, data.id, data.name);
});
$('[data-toggle="dashboard-config"]').on('click', function() {
formDialog({
title: '仪表盘设置',
url: app.url('index/dashboard/config'),
id: 'widget-edit',
dialogClass:'modal-lg',
onSubmit: function() {
var me = this;
var data = settingWidget.save();
$.post(app.url('index/dashboard/config'), data, function(res) {
if (res.status) {
location.reload();
toastrSuccess(res.data);
$(me).dialog("close");
} else {
toastrError(res.data);
}
});
}
});
});
$('[data-toggle="widget-refresh"]').on('click', function() {
var data = $(this).data();
if (data.key) {
gdoo.widgets[data.key].remoteData({page: 1});
}
});
function widgetInit() {
var items = $('.widget-item');
items.each(function(index, item) {
var data = $(item).data();
if (data == undefined) {
return false;
}
if (data.url) {
$(item).load(app.url(data.url, {id: data.id}));
}
});
var items = $('.info-items');
items.each(function(index, item) {
var me = $(item);
var data = me.data();
if (data.url) {
$(item).load(app.url(data.url, {id: data.id}));
}
});
var items = $('.quick-item');
items.each(function(index, item) {
var me = $(item);
var data = me.data();
$.get(app.url('index/index/badge', {key: data.key}), function(res) {
if(res.total > 0) {
me.find('.quick-num').show().text(res.total);
}
});
});
}
widgetInit();
})(jQuery);
</script>

View File

@ -3,13 +3,13 @@
<tr>
<td align="right">名称</td>
<td align="left">
<input type="text" autocomplete="off" class="form-control input-sm" readonly="readonly" value="{{$row['widget_name']}}">
<input type="text" autocomplete="off" class="form-control input-sm" readonly="readonly" value="{{$info['info_name']}}">
</td>
</tr>
<tr>
<td align="right">显示名称</td>
<td align="left">
<input type="text" autocomplete="off" class="form-control input-sm" id="name" name="name" value="{{$row['name']}}">
<input type="text" autocomplete="off" class="form-control input-sm" id="name" name="name" value="{{$info['name']}}">
</td>
</tr>
<tr>
@ -17,7 +17,7 @@
<td>
<select class="form-control input-sm" name="permission" id="permission">
@foreach($permissions as $key => $permission)
<option value="{{$key}}" @if($row['params']['permission'] == $key) selected="selected" @endif>{{$permission}}</option>
<option value="{{$key}}" @if($info['params']['permission'] == $key) selected="selected" @endif>{{$permission}}</option>
@endforeach
</select>
</td>
@ -27,7 +27,7 @@
<td>
<select class="form-control input-sm" name="date" id="date">
@foreach($dates as $key => $date)
<option value="{{$key}}" @if($row['params']['date'] == $key) selected="selected" @endif>{{$date}}</option>
<option value="{{$key}}" @if($info['params']['date'] == $key) selected="selected" @endif>{{$date}}</option>
@endforeach
</select>
</td>
@ -37,7 +37,7 @@
<td align="left">
<div class="input-group">
<span class="input-group-addon" id="icon-picker"></span>
<input data-placement="bottomLeft" type="text" autocomplete="off" value="{{$row['icon']}}" class="form-control icp icp-auto input-sm" id="icon" name="icon">
<input data-placement="bottomLeft" type="text" autocomplete="off" value="{{$info['icon']}}" class="form-control icp icp-auto input-sm" id="icon" name="icon">
</div>
</td>
</tr>
@ -45,9 +45,9 @@
<td align="right">图标颜色</td>
<td align="left">
<div class="colorpicker-controller" title="选择颜色">
<div id="color-picker" class="colorpicker" style="background-color:{{$row['color']}}"></div>
<div id="color-picker" class="colorpicker" style="background-color:{{$info['color']}}"></div>
</div>
<input type="hidden" id="color" name="color" value="{{$row['color']}}">
<input type="hidden" id="color" name="color" value="{{$info['color']}}">
</td>
</tr>
</table>

View File

@ -3,33 +3,58 @@
<tr>
<td align="right">名称</td>
<td align="left">
<input type="text" autocomplete="off" class="form-control input-sm" readonly="readonly" value="{{$row['widget_name']}}">
<input type="text" autocomplete="off" class="form-control input-sm" readonly="readonly" value="{{$widget['widget_name']}}">
</td>
</tr>
<tr>
<td align="right">显示名称</td>
<td align="left">
<input type="text" autocomplete="off" class="form-control input-sm" id="name" name="name" value="{{$row['name']}}">
<input type="text" autocomplete="off" class="form-control input-sm" id="name" name="name" value="{{$widget['name']}}">
</td>
</tr>
<!--
@if($widget['params']['permission'])
<tr>
<td align="right">权限</td>
<td>
<select class="form-control input-sm" name="permission" id="permission">
@foreach($permissions as $key => $permission)
<option value="{{$key}}" @if($widget['params']['permission'] == $key) selected="selected" @endif>{{$permission}}</option>
@endforeach
</select>
</td>
</tr>
@endif
@if($widget['params']['date'])
<tr>
<td align="right">日期</td>
<td>
<select class="form-control input-sm" name="date" id="date">
@foreach($dates as $key => $date)
<option value="{{$key}}" @if($widget['params']['date'] == $key) selected="selected" @endif>{{$date}}</option>
@endforeach
</select>
</td>
</tr>
@endif
<tr>
<td align="right">图标</td>
<td align="left">
<div class="input-group">
<span class="input-group-addon" id="icon-picker"></span>
<input data-placement="bottomLeft" type="text" autocomplete="off" class="form-control icp icp-auto input-sm" id="icon" name="icon">
<input data-placement="bottomLeft" type="text" autocomplete="off" value="{{$widget['icon']}}" class="form-control icp icp-auto input-sm" id="icon" name="icon">
</div>
</td>
</tr>
-->
<tr>
<td align="right">背景颜色</td>
<td align="left">
<div class="colorpicker-controller" title="选择颜色">
<div id="color-picker" class="colorpicker"></div>
<div id="color-picker" class="colorpicker" style="background-color:{{$widget['color']}}"></div>
</div>
<input type="hidden" id="color" name="color">
<input type="hidden" id="color" name="color" value="{{$widget['color']}}">
</td>
</tr>
</table>

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