Commit 6bfae684 authored by 冯超鹏's avatar 冯超鹏

Merge branch 'master' of ssh://111.61.77.35:15/fengchaopeng/laravelzh into develop

parents b054bd4b ac49bb84
Pipeline #198 failed with stage
......@@ -25,3 +25,4 @@ yarn-error.log
composer.lock
/resources/js/api/configurl.js
devicelistdata.text
cert/test
......@@ -57,14 +57,18 @@ class alarm extends Command
{
$url = config('public.swoolwebsocketurl');
$por = config('public.swoolwebsocketurlpor');
$this->ws = new \swoole_websocket_server('0.0.0.0', 9601,SWOOLE_PROCESS); //创建一个端口
$this->ws = new \swoole_websocket_server('0.0.0.0', 9601,SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); //创建一个端口
//$this->ws = new \swoole_websocket_server('0.0.0.0', 9601,SWOOLE_PROCESS); //创建一个端口
$this->ws->set(array(
'reactor_num' => 2, //reactor线程数
'worker_num' => 4, //worker进程数
'backlog' => 128, //Listen队列长度
'max_request' => 10,//最大连接
'daemonize'=>0,//守护进程
'ssl_cert_file' => base_path() . config('app.ssl_cert_file'),
'ssl_key_file' => base_path() . config('app.ssl_key_file'),
));
$this->ws->on('open', function ($ws, $request) {
// //链接成功
// $userdata = new SwooleCommandController();
......
......@@ -57,13 +57,15 @@ class chemicalswb extends Command
{
$url = config('public.swoolwebsocketurl');
$por = config('public.swoolwebsocketurlpor');
$this->ws = new \swoole_websocket_server('0.0.0.0', 9507,SWOOLE_PROCESS); //创建一个端口
$this->ws = new \swoole_websocket_server('0.0.0.0', 9507,SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); //创建一个端口
$this->ws->set(array(
'reactor_num' => 2, //reactor线程数
'worker_num' => 4, //worker进程数
'backlog' => 128, //Listen队列长度
'max_request' => 10,//最大连接
'daemonize'=>0,//守护进程
'ssl_cert_file' => base_path() . config('app.ssl_cert_file'),
'ssl_key_file' => base_path() . config('app.ssl_key_file'),
));
$this->ws->on('open', function ($ws, $request) {
// //链接成功
......
......@@ -57,13 +57,15 @@ class firewb extends Command
{
$url = config('public.swoolwebsocketurl');
$por = config('public.swoolwebsocketurlpor');
$this->ws = new \swoole_websocket_server('0.0.0.0', 9508,SWOOLE_PROCESS); //创建一个端口
$this->ws = new \swoole_websocket_server('0.0.0.0', 9508,SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); //创建一个端口
$this->ws->set(array(
'reactor_num' => 2, //reactor线程数
'worker_num' => 4, //worker进程数
'backlog' => 128, //Listen队列长度
'max_request' => 10,//最大连接
'daemonize'=>0,//守护进程
'ssl_cert_file' => base_path() . config('app.ssl_cert_file'),
'ssl_key_file' => base_path() . config('app.ssl_key_file'),
));
$this->ws->on('open', function ($ws, $request) {
// //链接成功
......
......@@ -57,13 +57,15 @@ class swoole extends Command
{
$url = config('public.swoolwebsocketurl');
$por = config('public.swoolwebsocketurlpor');
$this->ws = new \swoole_websocket_server('0.0.0.0', 9502); //创建一个端口
$this->ws = new \swoole_websocket_server('0.0.0.0', 9502|SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); //创建一个端口
$this->ws->set(array(
'reactor_num' => 2, //reactor线程数
'worker_num' => 4, //worker进程数
'backlog' => 128, //Listen队列长度
'max_request' => 10,//最大连接
'daemonize'=>0,//守护进程
'ssl_cert_file' => base_path() . config('app.ssl_cert_file'),
'ssl_key_file' => base_path() . config('app.ssl_key_file'),
));
$this->ws->on('open', function ($ws, $request) {
// //链接成功
......
......@@ -81,6 +81,7 @@ class swooleMeTcp extends Command
});
//监听数据接收事件
$this->tcp->on('Receive', function ($serv, $fd, $from_id, $data) {
Log::channel('slack')->info($data);
//验证数据格式
// $serv->send($fd,$data);
// if($this->formatData($data)){
......
<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Database\QueryException;
use Illuminate\Http\Request;
use App\Models\AlarmOrder;
use Illuminate\Support\Facades\DB;
use App\Models\AlarmOrderSchedule;
class AlarmOrderController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if($this->isadmin()) {
$limit = 20;
$offset = $limit * ($request->input('page') - 1);
$orders = AlarmOrder::selectRaw('
FROM_UNIXTIME(r.starttime) AS start_time,
FROM_UNIXTIME(r.endtime) AS end_time,
alarm_order.*,
r.devicenumber, r.concentration, r.location, r.policestatus, r.shutoff_status,
d.devicecoord, d.username,
u.name, u.phone_number,
s.status_name
')
->leftjoin('reportpolice AS r', 'r.id', '=', 'alarm_order.reportpolice_id')
->leftjoin('device AS d', 'd.id', '=', 'alarm_order.device_id')
->leftjoin('users AS u', 'alarm_order.user_id', '=', 'u.id')
->leftjoin('status AS s', 's.id', '=', 'alarm_order.reportpolice_id')
->offset($offset)
->limit($limit)
->get()->toArray();
return $this->jsonSuccessData($orders);
}else{
return $this->jsonErrorData(500, '没有权限,请联系管理员');
}
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$reportpolice_id = $request->input('reportpolice_id');
$orderNum = date('YmdHis') .
substr($request->input('device_num'), -4).
$request->input('policestatus').
$request->input('shutoff_status');
DB::beginTransaction();
try {
$order = new AlarmOrder();
$insertId = $order->insertGetId([
'order_num' => $orderNum,
'device_id' => $request->input('device_id'),
'user_id' => $request->input('user_id'),
'reportpolice_id' => $reportpolice_id,
'created_at' => Carbon::now(),
]);
// 进度表新增
$orderSchedule = new AlarmOrderSchedule();
$orderSchedule->alarm_order_id = $insertId;
$orderSchedule->schedule = 1;
$orderSchedule->created_at = Carbon::now();
$orderSchedule->save();
DB::commit();
} catch (QueryException $exception) {
DB::rollBack();
return $this->jsonErrorData('工单创建失败');
}
if($insertId) {
return $this->jsonSuccessData('已生成工单!');
}else{
return $this->jsonErrorData('工单创建失败');
}
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$order = AlarmOrder::select('*')
->join('reportpolice AS r', 'r.id', '=', 'alarm_order.reportpolice_id')
->where('alarm_order.id', '=', $id)
->get();
$this->jsonSuccessData($order);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$data = $request->all();
if(isset($data['schedule'])) {
DB::beginTransaction();
try {
AlarmOrderSchedule::insert(array_merge(
$data['schedule'],
['created_at' => Carbon::now(), 'alarm_order_id' => $id]));
unset($data['schedule']);
$order = AlarmOrder::where('id', $id)
->update(array_merge($data, ['updated_at' => Carbon::now()]));
DB::commit();
} catch (QueryException $exception) {
DB::rollBack();
return $this->jsonErrorData(500, '工单更新失败!');
}
}else{
$order = AlarmOrder::where('id', $id)
->update(array_merge($data, ['updated_at' => Carbon::now()]));
}
if($order) {
return $this->jsonSuccessData('工单更新成功');
}else{
return $this->jsonErrorData(500, '工单更新失败!');
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$state = AlarmOrder::destroy($id);
if($state) {
return $this->jsonSuccessData('删除成功');
}else{
return $this->jsonErrorData(500, '删除工单失败!');
}
}
}
......@@ -28,7 +28,7 @@ class Controller extends BaseController
'msg' => $message,
'data' => $data
];
return json_encode($content);
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
/**
......
......@@ -27,27 +27,48 @@ class HomepageController extends Controller
if ($type == 'user') {
$usercount = Users::count();
$devicecount = Device::where('uid','=',Auth::id())->count();
$devicepolice = Device::where('devicepolice', '>', '1')->where('uid','=',Auth::id())->count();
$devicepolice = Device::where('uid','=',Auth::id())->where('devicepolice', '>', '1')->count();
// 设备在线数量
$device_online = Device::where('uid','=',Auth::id())->whereNotIn('devicepolice', [9, 15])->count();
// 设备报警数量
$device_alarm = Device::where('uid','=',Auth::id())->whereIn('devicepolice', [4, 5, 6, 16])->count();
// 未报警设备数量
$device_normal = Device::where('uid','=',Auth::id())->where('devicepolice', 1)->count();
// 故障设备
$device_offline = Device::where('uid','=',Auth::id())->whereNotIn('devicepolice', [1, 4, 5, 6, 16])->count();
$t = time();//当前时间
$start = mktime(0, 0, 0, date("m", $t), date("d", $t), date("Y", $t));//今天的开始
$end = mktime(23, 59, 59, date("m", $t), date("d", $t), date("Y", $t));//今天的结束
$timedevicepolice = DB::table('reportpolice')->where('status', '=', '1')->whereBetween('starttime', [$start, $end])->count();
$offdevice = Device::where('devicepolice', '=', '1')->where('uid','=',Auth::id())->count();
//计算设备在线
$deviceurt = $devicecount / $offdevice;
} else {
$usercount = Users::count();
$devicecount = Device::count();
$devicepolice = Device::where('devicepolice', '>', '1')->count();
// 设备在线数量
$device_online = Device::whereNotIn('devicepolice', [9, 15])->count();
// 设备报警数量
$device_alarm = Device::whereIn('devicepolice', [4, 5, 6, 16])->count();
// 未报警设备数量
$device_normal = Device::where('devicepolice', 1)->count();
// 故障设备
$device_offline = Device::whereNotIn('devicepolice', [1, 4, 5, 6, 16])->count();
$t = time();//当前时间
$start = mktime(0, 0, 0, date("m", $t), date("d", $t), date("Y", $t));//今天的开始
$end = mktime(23, 59, 59, date("m", $t), date("d", $t), date("Y", $t));//今天的结束
$timedevicepolice = DB::table('reportpolice')->where('status', '=', '1')->whereBetween('starttime', [$start, $end])->count();
$offdevice = Device::where('devicepolice', '=', '1')->count();
//计算设备在线
$deviceurt = $devicecount / $offdevice;
}
return $this->jsonSuccessData(['usercount' => $usercount, 'devicecount' => $devicecount, 'devicepolice' => $devicepolice, 'timedevicepolice' => $timedevicepolice, 'offdevice' => $offdevice, 'deviceurt' => round($deviceurt)]);
return $this->jsonSuccessData([
'usercount' => $usercount,
'devicecount' => $devicecount,
'devicepolice' => $devicepolice,
'timedevicepolice' => $timedevicepolice,
'device_online' => $device_online,
'device_alarm' => $device_alarm,
'device_normal' => $device_normal,
'device_offline' => $device_offline,
'percent_alarm' => (float)number_format(($device_alarm/$devicecount) * 100, '2'),
'percent_online' => (float)number_format(($device_online/$devicecount) * 100, '2'),
]);
}
public function gettimeline()
......
......@@ -280,8 +280,21 @@ class UserController extends Controller
->leftjoin('areachina as p', 'b.provinceid', '=', 'p.areaid')
->leftjoin('areachina as c', 'b.cityid', '=', 'c.areaid')
->leftjoin('areachina as a', 'b.areaid', '=', 'a.areaid')
->leftJoin('user_roles AS ur', 'b.user_role_id', '=', 'ur.id')
->orderBy('b.id', 'desc')
->select('b.username', 'b.id', 'b.created_at', 'b.name', 'b.email', 'b.state', 'a.area_name as area', 'c.area_name as city', 'p.area_name as province')
->select(
'b.username',
'b.id',
'b.created_at',
'b.name',
'b.email',
'b.state',
'b.phone_number',
'ur.name AS role_name',
'a.area_name as area',
'c.area_name as city',
'p.area_name as province'
)
->offset($pagenNum)
->limit($limit)
->get();
......@@ -434,7 +447,7 @@ class UserController extends Controller
return $this->jsonErrorData(105, '用户id不能为空');
}
$userdata = Users::where('id', '=', $userid)
->select('username', 'name', 'email', 'title', 'company', 'mapcenter')
->select('username', 'name', 'email', 'title', 'company', 'mapcenter', 'phone_number', 'user_role_id')
->first();
if ($userdata) {
return $this->jsonSuccessData($userdata);
......
......@@ -30,7 +30,7 @@ class UserResource extends JsonResource
},
$this->getAllPermissions()->toArray()
),
'avatar' => 'https://i.pravatar.cc',
'avatar' => '/images/timg.jpeg',
];
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
class AlarmOrder extends Model
{
protected $table = 'alarm_order';
public $timestamps = false;
// 获取报警记录
public function reportpolices()
{
return $this->hasOne('Reportpolice');
}
public function getCreatedAtAttribute($value)
{
return Carbon::parse($value)->toDateTimeString();
}
public function getUpdatedAtAttribute($value)
{
return Carbon::parse($value)->toDateTimeString();
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
class AlarmOrderSchedule extends Model
{
protected $table = 'alarm_order_schedule';
public $timestamps = false;
public function getCreatedAtAttribute($value)
{
return Carbon::parse($value)->toDateTimeString();
}
public function getUpdatedAtAttribute($value)
{
return Carbon::parse($value)->toDateTimeString();
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Reportpolice extends Model
{
//
}
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAmMlz7AwFgrbgetOTO/rYX6r7BzrL1EN6ilUroByqo09z7o5j
ZaTmhMoDSUNrlsldjnGG/8A7e2r2cx4iJ2keinJE5+dnb+3Xq6/vT466kHqhrBXv
qxXAOpCdaf1+Eh4BTMxJWXzmxTHCr++alg9wwVi/dkucrhkMiWwQla/WovZKalWt
aNs4pYsFFXEFhW+XsGur2HSxe1tHxiIzbJQCndnN7BH78E1i4bV4dkkHoIe/uELX
SyTt4M+wOvYKK2k1eHhwP8a0plRANWk5JBcxBBvhpMmEqd4ogwRHYqMe6qZSwRv6
LiTPMEG4aVr/pWlWRL823MeQauJt1rGibZGf6wIDAQABAoIBAEDvFUpTzZ/BM2Rg
OSn7sSvvkeJ/tZMP3queCP1yUX84zE+tykavr5zt8jmX4sjh6dYZH8PgIieQzQ8d
1mwje+xhJjHdIhPq5Ic+LZoFUfsHc2CcrhBrHRiGz6/1ITh38ht+kwnqUHWscU6u
qWdvRn+VxUF0XzGKyc451E6ZvcHh/JCAcS/0AAwmtutNzWXgxFJYjPn+ZqMuHCyn
9EfF5qK1MBmkofkEiZUARtz35p133L5Vot2lea/NWKf40YGe/ADG+jrqMMD3n3Jo
voY05pqzJgXy0dYFBd/gO57WFfkvgc3/tGhS2SET4jyWIimB4+NJG1tUVjtU3o5F
yYd/BoECgYEAy1jyij1sg0xLbZ/YQqOQwVJsPnw77xfCoIUs14jRPMzpODZeLIfN
eGWUZMw7r/SVB4BzAiYPigxfYxtUmgByk0hEkJLsklV4pg1aFK5GBmiX1AVtSp6F
0OvoCPFFAKjPoDX3StN/AnLV3dze+iGIzMisBNwLgMx6F/YgsRi94CsCgYEAwFkP
ObPfbZxRcKw2fh4LC3aTcnJ18qx+SjuP48FUSrRwlPw4EuR+BF8MwasJqSEMNGEA
vu/A66wBtakK5H7kYipK/UMrOJf5pOQzDX35kCeQJF6emQR9ZHol7UHTIci5FXHF
alZ4+HZ05RYuqYsCSH4iQ0mPAENzjxAghNPjn0ECgYBZRTQ9EhgoT/8xIiJLpwju
heO1Ts70+OZdl/mGqa7J1V9xaRTQ0dGXUGjkE3EEnwgp4e8be2AJB8N8e8wZS6cB
F5HaMlYfK9yqcWQhfhyJxbMZxkQjpRI0FMyp2Fmln3Z+7BIjTFQO3CEdpFBTWRN4
a4RxIbT/F0VmbYwOk0EQPwKBgAv6P8F3GvWnY0bh4m7ODiADnUDmMcQPy7lxpg8n
rckNHWmZnyBGDDbXeGLi9LIMdccZN0OsiFXkmyKlySDbaftW6N6GfT2D8S68axVu
/8hjPk2VesjKh8hm9s+kZrJW3negYwuxIM1QCw1s6TDzkAvVluqbvQTmLl79QRkk
XKtBAoGAaV5QdJNStltDVs3iVtvb5lawSSGWXtOv0QlHoNKA2oN2Ugrny0A3kg6h
5vkNwL2xSgY1NtYoSGyd3taDBGPfc500uNtOe7DsIO9Rw9IvAYT2ZVtjnyAPhm9v
WFxEdcOL/HNLk21vC3MW6xkEKW+fql9EBhq9yGXfjCVYtwzdctM=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
/WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFhDCCBGygAwIBAgIQAUZz7qaPZMwpjZC/pIhMpzANBgkqhkiG9w0BAQsFADBu
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
RFYgVExTIENBIC0gRzEwHhcNMjAxMjAyMDAwMDAwWhcNMjExMjAyMjM1OTU5WjAZ
MRcwFQYDVQQDEw5pb3QuemhramdmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAJjJc+wMBYK24HrTkzv62F+q+wc6y9RDeopVK6AcqqNPc+6OY2Wk
5oTKA0lDa5bJXY5xhv/AO3tq9nMeIidpHopyROfnZ2/t16uv70+OupB6oawV76sV
wDqQnWn9fhIeAUzMSVl85sUxwq/vmpYPcMFYv3ZLnK4ZDIlsEJWv1qL2SmpVrWjb
OKWLBRVxBYVvl7Brq9h0sXtbR8YiM2yUAp3ZzewR+/BNYuG1eHZJB6CHv7hC10sk
7eDPsDr2CitpNXh4cD/GtKZUQDVpOSQXMQQb4aTJhKneKIMER2KjHuqmUsEb+i4k
zzBBuGla/6VpVkS/NtzHkGribdaxom2Rn+sCAwEAAaOCAnEwggJtMB8GA1UdIwQY
MBaAFFV0T7JyT/VgulDR1+ZRXJoBhxrXMB0GA1UdDgQWBBQ5Mgx0gUQ5hithuCX/
W4Cp72pebDAZBgNVHREEEjAQgg5pb3QuemhramdmLmNvbTAOBgNVHQ8BAf8EBAMC
BaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEwGA1UdIARFMEMwNwYJ
YIZIAYb9bAECMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNv
bS9DUFMwCAYGZ4EMAQIBMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0
dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBKBggrBgEFBQcwAoY+aHR0cDovL2NhY2Vy
dHMuZGlnaWNlcnQuY29tL0VuY3J5cHRpb25FdmVyeXdoZXJlRFZUTFNDQS1HMS5j
cnQwCQYDVR0TBAIwADCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1APZclC/RdzAi
FFQYCDCUVo7jTRMZM7/fDC8gC8xO8WTjAAABdiFmaE4AAAQDAEYwRAIgGW+IDNGf
s5VlgkSJt3GliVpbVn+o/9uKUSgX7Kc3wtcCIC4cwy/BQFYUw81o/BZb+yzCwr7Z
x7OtrRqSe62Si6mKAHYAXNxDkv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbHDsoA
AAF2IWZoqQAABAMARzBFAiEAwtUcOpXJ6HcmD3bkldv5pxHLXKT5kEwlm1YfrKRb
wpACIBTcal1S+BGT5FtM2HMuli0+THCAmiQziT72+BU1/4FfMA0GCSqGSIb3DQEB
CwUAA4IBAQB7vKZPBhyFR98bk1+jfd/eievadE4c69a9hzxRZ/FI1JPc1PlSCtoH
TEtLq5qL2KC3mp/yCLsgerPGciYimAPfXHQt67t5qboS+iIZDHFn2Zcp/29Jhwmm
GGYx+2I3ssfaqY9Cp8SUcPxL5QnsoPKTz9BmF30T/Vbn0dr9wq2evZwRzuKqwkMj
6+dF0QenTJUlMW9u+oVSApJbpAlWaJve2nLvjI79Eaqv4ArZiyvHF4aGLdNeIEo1
p7LGovG9FCyYRSd7W6Fqj9MKe1L7YM+81svGaZ9UxRKuTD/yIK6Wl6pnbDITcW3u
dohg8chkpORn//k/gQAtn2Dn+pbRUltG
-----END CERTIFICATE-----
......@@ -123,6 +123,12 @@ return [
'cipher' => 'AES-256-CBC',
/*
* SSL 证书路径
*/
'ssl_cert_file' => env('SSL_CERT_FILE','/cert/apache/iot.zhkjgf.com_public.crt'),
'ssl_key_file' => env('SSL_KEY_FILE','/cert/apache/iot.zhkjgf.com.key'),
/*
|--------------------------------------------------------------------------
| Autoloaded Service Providers
......
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddShutOffToDeviceTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('device', function (Blueprint $table) {
$table->integer('shutoff_status')->default(0)->comment('切断装置状态,0初始化状态,1开启,2关闭');
$table->integer('shutoff_type')->default(0)->comment('切断装置类型,0未绑定,1电磁阀,2机械手');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('device', function (Blueprint $table) {
$table->dropColumn('shutoff_status');
$table->dropColumn('shutoff_type');
});
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUserRolesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('user_roles', function (Blueprint $table) {
$table->increments('id')->comment('主键');
$table->string('name')->unique()->comment('角色名称');
$table->tinyInteger('state')->comment('状态:1:启用,2:停用');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_roles');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPhoneAndUserRoleIdToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('phone_number',11)->default(null)->comment('手机号码');
$table->integer('user_role_id')->comment('用户角色ID');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('phone_number');
$table->dropColumn('user_role_id');
});
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAlarmOrderTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('alarm_order', function (Blueprint $table) {
$table->increments('id')->comment('主键');
$table->string('order_num', 32)->unique()->comment('工单号');
$table->integer('user_id')->comment('用户ID');
$table->integer('device_id')->comment('设备ID');
$table->integer('reportpolice_id')->comment('报警记录id');
$table->tinyInteger('is_live')->comment('1到达现场,2未到达现场');
$table->tinyInteger('is_verified')->comment('1属实,2不属实');
$table->string('content')->comment('反馈内容');
$table->tinyInteger('state')->comment('工单状态,0:进行中, 1完成,2,异常终止。');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('alarm_order');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAlarmOrderScheduleTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('alarm_order_schedule', function (Blueprint $table) {
$table->increments('id');
$table->integer('alarm_order_id')->comment('报警工单ID');
$table->tinyInteger('schedule')->comment('进度ID');
$table->string('content')->comment('进度详情');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('alarm_order_schedule');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddShutOffToReportpoliceTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('reportpolice', function (Blueprint $table) {
$table->tinyInteger('shutoff_status')->comment('切断装置状态,0初始化状态,1开启,2关闭');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('reportpolice', function (Blueprint $table) {
$table->dropColumn('shutoff_status');
});
}
}
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class UserRolesSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Db::table('user_roles')->insert([
['name' => '行业主管部门负责人', 'created_at' => date('Y-m-d H:i:s')],
['name' => '燃气用户', 'created_at' => date('Y-m-d H:i:s')],
['name' => '应急抢修人员', 'created_at' => date('Y-m-d H:i:s')],
['name' => '村内“两员”', 'created_at' => date('Y-m-d H:i:s')]
]);
}
}
......@@ -19,7 +19,7 @@
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper">
<img :src="avatar+'/128'" class="user-avatar">
<img :src="avatar_url" class="user-avatar">
<i class="el-icon-caret-bottom" />
</div>
<el-dropdown-menu slot="dropdown">
......@@ -55,6 +55,7 @@ import Screenfull from '@/components/Screenfull';
import SizeSelect from '@/components/SizeSelect';
import LangSelect from '@/components/LangSelect';
import Search from '@/components/HeaderSearch';
import imgUrl from '@/assets/avatar.png';
export default {
components: {
......@@ -65,6 +66,11 @@ export default {
LangSelect,
Search,
},
data() {
return {
avatar_url: imgUrl,
};
},
computed: {
...mapGetters([
'sidebar',
......
......@@ -39,6 +39,11 @@
<span>{{ scope.row.status_name }}</span>
</template>
</el-table-column>
<el-table-column label="切断装置状态" width="150">
<template slot-scope="scope">
<span>{{ shutoffStatus(scope.row.shutoff_status) }}</span>
</template>
</el-table-column>
<el-table-column label="设备状态" width="155">
<template slot-scope="scope">
<el-tag :type="scope.row.status==1 ? 'danger' : 'success' " effect="dark">{{ scope.row.status==1 ? '报警' : '正常' }}</el-tag>
......@@ -49,6 +54,11 @@
<el-tag :type="scope.row.status==1 ? 'danger' : 'success' " effect="dark">{{ scope.row.status==1 ? '当前正在报警' : '已结束报警' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template>
<el-button type="primary" effect="dark">生成工单</el-button>
</template>
</el-table-column>
</el-table>
<el-tooltip placement="top" content="tooltip">
<back-to-top :custom-style="myBackToTopStyle" :visibility-height="300" :back-position="50" transition-name="fade" />
......@@ -88,6 +98,13 @@ export default {
this.historydevicetype(); // 设备搜索所需数据
},
methods: {
shutoffStatus(id) {
const shutoff = [];
shutoff[0] = '初始化';
shutoff[1] = '开启';
shutoff[2] = '关闭';
return shutoff[id];
},
police() {
police()
.then(response => {
......
......@@ -33,6 +33,7 @@
:stroke-color="'#ccc'"
:stroke-opacity="0.9"
:events="markerClickEvent(marker)"
:check="playAudio(marker.devicepolice)"
></el-amap-circle-marker>
<!-- 右上角设备和用户切换按钮 -->
<div class="toolbar">
......@@ -54,7 +55,7 @@
<el-dialog
:title="dialogTitle"
:visible.sync="dialogTableVisible"
width="20%"
width="40%"
:modal="false"
custom-class="zero-dialog"
>
......@@ -70,7 +71,7 @@
<template slot="title">
设备列表 - {{ leftDeviceName }}
</template>
<el-table :data="markersDevice" style="100%" max-height="700">
<el-table :data="markersDevice" style="100%" max-height="700" @row-click="openDeviceBox">
<el-table-column property="devicenum" label="设备编号" width="200px"></el-table-column>
<el-table-column property="deviceinfo" label="位置" width="200px"></el-table-column>
<el-table-column property="nd" label="值" width="40px"></el-table-column>
......@@ -184,6 +185,9 @@ export default {
data(){
const _this = this;
return {
audio: new Audio('/audio/alarm.wav'),
audio_play: false,
intervalId: null,
map: {},
amapManager: new AMapManager(),
zoom: 6,
......@@ -247,10 +251,17 @@ export default {
.then(res => {
this.markersDevice = res.data;
});
this.dataRefresh();
},
destroyed(){
// 在页面销毁后,清除计时器
this.clearIntv();
},
methods: {
checkPermission,
allDevices() {
this.clearIntv();
this.dataRefresh();
devices()
.then(res => {
this.leftDeviceName = '全部设备';
......@@ -290,10 +301,13 @@ export default {
},
// 获取单个用户下的设备
getUserDeviceList(uid) {
// 停止定时器
this.clearIntv();
devices({ uid: uid })
.then(res => {
this.markersDevice = res.data;
});
this.dataRefresh(uid);
},
// 获取设备详细信息
getUserDeviceInfo(id) {
......@@ -322,6 +336,14 @@ export default {
title: '检测介质',
content: deviceInfo.gas,
},
{
title: '切断装置',
content: this.shutoffDevice(deviceInfo.shutoff_type),
},
{
title: '切断装置状态',
content: this.shutoffStatus(deviceInfo.shutoff_status),
},
{
title: '状态',
content: deviceInfo.status_name,
......@@ -341,6 +363,83 @@ export default {
];
});
},
// 切断装置
shutoffDevice(id) {
const shutoff_types = [];
shutoff_types[0] = '未绑定';
shutoff_types[1] = '电磁阀';
shutoff_types[2] = '机械手';
return shutoff_types[id];
},
shutoffStatus(id) {
const shutoff = [];
shutoff[0] = '初始化';
shutoff[1] = '开启';
shutoff[2] = '关闭';
return shutoff[id];
},
openDeviceBox(row, column, event) {
this.getUserDeviceInfo(row.id);
},
// 定时刷新数据
dataRefresh(uid = null) {
// 计时器正在进行中,退出函数
if (this.intervalId != null) {
return;
}
// 计时器为空,操作
this.intervalId = setInterval(() => {
console.log('刷新' + uid + '--' + new Date());
if (uid > 0) {
users({ uid: uid })
.then(res => {
this.markers = res.data;
});
devices({ uid: uid })
.then(res => {
this.markersDevice = res.data;
});
} else {
users()
.then(res => {
this.markers = res.data;
});
devices({})
.then(res => {
this.markersDevice = res.data;
});
}
}, 3000);
},
// 停止定时器
clearIntv() {
clearInterval(this.intervalId); // 清除计时器
this.intervalId = null; // 设置为null
},
// 播放报警声音
playAudio(state) {
if (this.audio_play === false && (state === 4 || state === 5 || state === 6 || state === 16)) {
const playPromise = this.audio.play();
const that = this;
if (playPromise) {
playPromise.then(() => {
// 音频加载成功
// 音频的播放需要耗时
that.tiemr = setInterval(() => {
that.second--;
if (that.second <= 0) {
this.audio.pause();
this.audio_play = true;
clearInterval(that.tiemr);
}
}, 1000);
}).catch((e) => {
// 音频加载失败
console.error(e);
});
}
}
},
},
};
</script>
......
......@@ -40,6 +40,11 @@
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
<el-form-item>
<el-button v-if="device != '' " v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">
{{ $t('table.export') }}
</el-button>
</el-form-item>
</el-form>
<el-table :key="tableKey" v-loading="loading" :data="device" border fit highlight-current-rows>
<el-table-column align="center" label="ID" width="80">
......@@ -72,6 +77,11 @@
<span>{{ scope.row.gas }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="切断装置" width="170">
<template slot-scope="scope">
<span>{{ shutoffDevice(scope.row.shutoff_type) }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="检测值" width="100">
<template slot-scope="scope">
<span>{{ scope.row.nd }}</span>
......@@ -82,6 +92,27 @@
<span>{{ scope.row.danwei }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="切断装置状态" width="120">
<template slot-scope="scope">
<span>
<el-popconfirm
:title="'确定' + unshutoff_status(scope.row.shutoff_status) + scope.row.username + shutoffDevice(scope.row.shutoff_type) + '吗?'"
@onConfirm="changeShutoffStatus(scope.row.id, scope.row.shutoff_status, scope.row.dtype)"
@onCancel="()=>{}"
>
<el-button
slot="reference"
:loading="shutoff_loading"
size="mini"
:type=" scope.row.shutoff_status==1 ? 'success' : 'warning' "
@click="shutoff_visible = true"
>
{{ shutoffStatus(scope.row.shutoff_status) }}
</el-button>
</el-popconfirm>
</span>
</template>
</el-table-column>
<el-table-column align="center" label="实时状态" width="120">
<template slot-scope="scope">
<span>
......@@ -113,15 +144,21 @@
</template>
<script>
import { control } from '@/api/device';
import { control, updedata } from '@/api/device';
import Pagination from '@/components/Pagination'; // 分页
import websocketurl from '@/api/configurl';
import clip from '@/utils/clipboard';
import waves from '@/directive/waves'; // 水波纹效果
import { parseTime } from '@/utils';
export default {
name: 'Devicetype',
directives: { waves },
components: { Pagination },
data() {
return {
shutoff_visible: false,
shutoff_loading: false,
downloadLoading: false,
tableKey: 0,
loading: true,
device: [],
......@@ -223,6 +260,34 @@ export default {
},
methods: {
// 切断装置
shutoffDevice(id) {
const shutoff_types = [];
shutoff_types[0] = '未绑定';
shutoff_types[1] = '电磁阀';
shutoff_types[2] = '机械手';
return shutoff_types[id];
},
shutoffStatus(id) {
const shutoff = [];
shutoff[0] = '初始化';
shutoff[1] = '开启';
shutoff[2] = '关闭';
return shutoff[id];
},
unshutoff_status(state) {
return state === 1 ? '关闭' : '开启';
},
// 修改切断装置状态
changeShutoffStatus(id, shutoff_status, tid) {
updedata({ deid: id, shutoff_status: shutoff_status !== 1 ? 1 : 2, tid: tid })
.then(response => {
// this.devicelist();
})
.catch(err => {
console.log(err);
});
},
onSubmit() {
this.formSearch.page = 1;
this.devicelist();
......@@ -294,6 +359,34 @@ export default {
handleCopyphone(text, event){
clip(text, event);
},
// 导出到excel
handleDownload() {
this.downloadLoading = true;
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['ID', '设备编号', '设备名称', '设备详情', '设备类型', '检测介质', '切断装置', '单位', '切断装置状态', '实时状态', '最后更新时间'];
const filterVal = ['id', 'devicenum', 'username', 'deviceinfo', 'tname', 'gas', 'shutoff_type', 'danwei', 'shutoff_status', 'status_name', 'update_time'];
const data = this.formatJson(filterVal, this.device);
excel.export_json_to_excel({
header: tHeader,
data,
filename: '消防监测',
});
this.downloadLoading = false;
});
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if (j === 'shutoff_type') {
return this.shutoffDevice(v[j]);
} else if (j === 'shutoff_status') {
return this.shutoffStatus(v[j]);
} else if (j === 'update_time') {
return parseTime(v[j]);
} else {
return v[j];
}
}));
},
},
};
</script>
......
......@@ -47,6 +47,13 @@ Route::group(['middleware' => 'auth:api'], function () {
Route::get('user/paperBasketList','UserController@paperBasketList');//返回废纸篓和用户状态
Route::get('user/userLocation','UserController@userLocation');//返回用户安装位置
Route::get('user/textcountuser','UserController@textcountuser');//用户测试接口
// 报警工单
Route::get('alarm_order', 'AlarmOrderController@index'); // 工单列表
Route::post('alarm_order', 'AlarmOrderController@store'); // 创建工单
Route::patch('alarm_order/{id}', 'AlarmOrderController@update'); // 修改工单
Route::delete('alarm_order/{id}', 'AlarmOrderController@destroy'); // 删除工单
Route::get('alarm_order/show/{id}', 'AlarmOrderController@show'); // 工单详情
});
//上传图片路由
......@@ -106,7 +113,7 @@ Route::group(['middleware'=>'auth:api'],function (){
Route::get('devices/device_info/{id}','DevicesController@device_info');//返回设备地图详情信息
Route::get('devices/devicepolice','DevicesController@devicepolice');//设备消警
Route::get('devices/devicepoliceinfo','DevicesController@devicepoliceinfo');//设备报警弹窗详情
Route::get('login/history_device_type','DevicesController@history_device_type');//报警数据搜索所需数据
Route::get('devices/history_device_type','DevicesController@history_device_type');//报警数据搜索所需数据
Route::get('devices/companyuser','DevicesController@companyuser');//用户获取自定义公司名称
// 设备型号
Route::get('device/models', 'ModelNumberController@index');
......@@ -132,108 +139,4 @@ Route::group(['middleware'=>'auth:api'],function (){
Route::post('huinapphome/setseachdata','UinappHomeController@setseachdata');//指定查询
Route::get('huinapphome/devicetype','UinappHomeController@devicetype');//测试添加页面选择数组数据
});
// Fake APIs
Route::get('/table/list', function () {
$rowsNumber = mt_rand(20, 30);
$data = [];
for ($rowIndex = 0; $rowIndex < $rowsNumber; $rowIndex++) {
$row = [
'author' => Faker::randomString(mt_rand(5, 10)),
'display_time' => Faker::randomDateTime()->format('Y-m-d H:i:s'),
'id' => mt_rand(100000, 100000000),
'pageviews' => mt_rand(100, 10000),
'status' => Faker::randomInArray(['deleted', 'published', 'draft']),
'title' => Faker::randomString(mt_rand(20, 50)),
];
$data[] = $row;
}
return response()->json(new JsonResponse(['items' => $data]));
});
Route::get('/orders', function () {
$rowsNumber = 8;
$data = [];
for ($rowIndex = 0; $rowIndex < $rowsNumber; $rowIndex++) {
$row = [
'order_no' => 'LARAVUE' . mt_rand(1000000, 9999999),
'price' => mt_rand(10000, 999999),
'status' => Faker::randomInArray(['success', 'pending']),
];
$data[] = $row;
}
return response()->json(new JsonResponse(['items' => $data]));
});
Route::get('/articles', function () {
$rowsNumber = 10;
$data = [];
for ($rowIndex = 0; $rowIndex < $rowsNumber; $rowIndex++) {
$row = [
'id' => mt_rand(100, 10000),
'display_time' => Faker::randomDateTime()->format('Y-m-d H:i:s'),
'title' => Faker::randomString(mt_rand(20, 50)),
'author' => Faker::randomString(mt_rand(5, 10)),
'comment_disabled' => Faker::randomBoolean(),
'content' => Faker::randomString(mt_rand(100, 300)),
'content_short' => Faker::randomString(mt_rand(30, 50)),
'status' => Faker::randomInArray(['deleted', 'published', 'draft']),
'forecast' => mt_rand(100, 9999) / 100,
'image_uri' => 'https://via.placeholder.com/400x300',
'importance' => mt_rand(1, 3),
'pageviews' => mt_rand(10000, 999999),
'reviewer' => Faker::randomString(mt_rand(5, 10)),
'timestamp' => Faker::randomDateTime()->getTimestamp(),
'type' => Faker::randomInArray(['US', 'VI', 'JA']),
];
$data[] = $row;
}
return response()->json(new JsonResponse(['items' => $data, 'total' => mt_rand(1000, 10000)]));
});
Route::get('articles/{id}', function ($id) {
$article = [
'id' => $id,
'display_time' => Faker::randomDateTime()->format('Y-m-d H:i:s'),
'title' => Faker::randomString(mt_rand(20, 50)),
'author' => Faker::randomString(mt_rand(5, 10)),
'comment_disabled' => Faker::randomBoolean(),
'content' => Faker::randomString(mt_rand(100, 300)),
'content_short' => Faker::randomString(mt_rand(30, 50)),
'status' => Faker::randomInArray(['deleted', 'published', 'draft']),
'forecast' => mt_rand(100, 9999) / 100,
'image_uri' => 'https://via.placeholder.com/400x300',
'importance' => mt_rand(1, 3),
'pageviews' => mt_rand(10000, 999999),
'reviewer' => Faker::randomString(mt_rand(5, 10)),
'timestamp' => Faker::randomDateTime()->getTimestamp(),
'type' => Faker::randomInArray(['US', 'VI', 'JA']),
];
return response()->json(new JsonResponse($article));
});
Route::get('articles/{id}/pageviews', function ($id) {
$pageviews = [
'PC' => mt_rand(10000, 999999),
'Mobile' => mt_rand(10000, 999999),
'iOS' => mt_rand(10000, 999999),
'android' => mt_rand(10000, 999999),
];
$data = [];
foreach ($pageviews as $device => $pageview) {
$data[] = [
'key' => $device,
'pv' => $pageview,
];
}
return response()->json(new JsonResponse(['pvData' => $data]));
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment