Commit cd06e008 by mushishixian

temp

parent be13c5d7
Showing with 4460 additions and 79 deletions
...@@ -5,14 +5,60 @@ APP_URL=http://localhost ...@@ -5,14 +5,60 @@ APP_URL=http://localhost
WEB_NAME=供应商系统 WEB_NAME=供应商系统
//主数据库 //CMS MYSQL配置
DB_CONNECTION=mysql
DB_HOST=192.168.2.232 DB_HOST=192.168.2.232
DB_DATABASE=liexin_scm_wms
DB_USERNAME=liexin_scm_wms
DB_PASSWORD=liexin_scm_wms#zsyM
DB_PORT=3306 DB_PORT=3306
DB_DATABASE=ichuntcms
DB_USERNAME=ichuntcms
DB_PASSWORD=ichuntcms#zsyM
//联营供应商系统数据库
WEB_DB_HOST=192.168.2.232
WEB_DB_PORT=3306
WEB_DB_DATABASE=liexin_ass
WEB_DB_USERNAME=liexin_ass
WEB_DB_PASSWORD=liexin_ass#zsyM
//采购系统数据库
WMS_DB_HOST=192.168.2.232
WMS_DB_PORT=3306
WMS_DB_DATABASE=liexin_wms
WMS_DB_USERNAME=liexin_wms
WMS_DB_PASSWORD=liexin_wms#zsyM
//自营基石数据库
DB_SELF_HOST=192.168.1.235
DB_SELF_DATABASE=liexin_data
DB_SELF_USERNAME=spu
DB_SELF_PASSWORD=spu
DB_SELF_PORT=3306
//云芯 MYSQL配置
DB_HOST_YUNXIN=192.168.2.232
DB_DATABASE_YUNXIN=liexin_yunxin
DB_USERNAME_YUNXIN=liexin_yunxin
DB_PASSWORD_YUNXIN=liexin_yunxin#zsyM
DB_YUNXIN_PORT=3306
//联营sku数据库01
DB_SKU_HOST=192.168.1.235
DB_SKU_DATABASE=liexin_sku_1
DB_SKU_USERNAME=spu
DB_SKU_PASSWORD=spu
DB_SKU_PORT=3306
//联营SPU数据库
DB_SPU_HOST=192.168.1.235
DB_SPU_DATABASE=liexin_spu
DB_SPU_USERNAME=spu
DB_SPU_PASSWORD=spu
DB_SPU_PORT=3306
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=redis
//基石redis配置
REDIS_HOST=192.168.1.235 REDIS_HOST=192.168.1.235
REDIS_PASSWORD=icDb29mLy2s REDIS_PASSWORD=icDb29mLy2s
REDIS_PORT=6379 REDIS_PORT=6379
...@@ -21,10 +67,15 @@ REDIS_READ_HOST=192.168.1.237 ...@@ -21,10 +67,15 @@ REDIS_READ_HOST=192.168.1.237
REDIS_READ_PASSWORD=icDb29mLy2s REDIS_READ_PASSWORD=icDb29mLy2s
REDIS_READ_PORT=6379 REDIS_READ_PORT=6379
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
RABBITMQ_HOST=192.168.2.232
RABBITMQ_PORT=5672
RABBITMQ_VHOST=/
RABBITMQ_LOGIN=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_QUEUE=wms_service
ES_SKU_URL=http://soso12.ichunt.com/search/Es/searchSku
MAIL_DRIVER=smtp MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io MAIL_HOST=mailtrap.io
......
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Model\BrandModel;
use App\Model\SelfClassifyModel;
use Illuminate\Http\Request;
use GuzzleHttp\Client;
//通用API,比如获取品牌列表,分类列表等
class CommonApiController extends Controller
{
public function Entrance(Request $request, $id)
{
$this->$id($request, $id);
}
//获取分类列表(自营专属)
public function getSelfClassList($request)
{
$model = new SelfClassifyModel();
$result = $model->getClassList();
return $this->response(0, 'ok', $result);
}
//获取所有品牌
public function getBrandList($request)
{
$type = $request->get('type');
//如果传的type=0,默认给自营
$type = $type ?: 1;
$model = new BrandModel();
$brandList = $model->getBrandListByType($type);
return $this->response(0, 'ok', $brandList);
}
public function upload($request)
{
$upload = $request->file('qualification_photos');
$ext = $upload->getClientOriginalExtension();
$fileName = time() . '.' . $ext;
$upload->move(storage_path("uploads"), $fileName);
$path = storage_path("uploads") . '/' . $fileName;
$result = UploadToOss($path);
$result = json_decode($result, true);
unlink($path);
if (!empty($result) && $result['code'] === 200) {
echo json_encode([
'code' => 200,
'src' => $result['data'][0],
'msg' => 'ok',
]);
} else {
echo json_encode([
'code' => -1,
'msg' => '上传失败',
]);
}
exit();
}
}
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Services\AdminUserService;
use App\Http\Transformers\LogTransformer;
use App\Model\LogModel;
use Illuminate\Http\Request;
//通用API,比如获取品牌列表,分类列表等
class LogApiController extends Controller
{
public function Entrance(Request $request, $id)
{
$this->$id($request, $id);
}
//获取供应商信息变更记录
public function GetLogList($request)
{
$limit = $request->get('limit', 10);
$data = $request->only([
'type',
'admin_id'
]);
$model = new LogModel();
$query = $model->orderBy('id', 'desc');
if (!empty($data['type'])) {
$query->where('type', $data['type']);
}
if (!empty($data['admin_id'])) {
$adminUserService = new AdminUserService();
$user= $adminUserService->getAdminUserInfoByCodeId($data['admin_id']);
$adminId = array_get($user, 'userId');
$query->where('admin_id', $adminId);
}
$list = $query->paginate($limit)->toArray();
$transformer = new LogTransformer();
$list['data'] = $transformer->transformList($list['data']);
$this->response(0, 'ok', $list['data'], $list['total']);
}
}
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Transformers\LogTransformer;
use App\Http\Transformers\ReceiptTransformer;
use App\Http\Validators\ReceiptValidator;
use App\Model\LogModel;
use App\Model\SupplierReceiptModel;
use Illuminate\Http\Request;
//通用API,比如获取品牌列表,分类列表等
class ReceiptApiController extends Controller
{
public function Entrance(Request $request, $id)
{
$this->$id($request, $id);
}
//获取供应商收款信息
public function GetSupplierReceiptList($request)
{
$supplierId = $request->get('supplier_id');
$limit = $request->get('limit', 10);
$model = new SupplierReceiptModel();
$model->where('supplier_id',$supplierId)->paginate();
$list = $model->where('supplier_id', $supplierId)->orderBy('receipt_id', 'desc')
->paginate($limit)->toArray();
$transformer = new ReceiptTransformer();
$list['data'] = $transformer->transformList($list['data']);
$this->response(0, 'ok', $list['data'],$list['total']);
}
//获取供应商信息变更记录
public function AddSupplierReceipt($request)
{
//先去表单验证
$validator = new ReceiptValidator();
$validateResult = $validator->checkSave($request);
if ($validateResult) {
$this->response(-1, $validateResult);
}
$receipt = $request->get('receipt');
$receiptId = $request->get('receipt_id');
$supplierId = $request->get('supplier_id');
unset($receipt['currency']);
$model = new SupplierReceiptModel();
if (!empty($receiptId)) {
$result = $model->where('receipt_id', $receiptId)->update($receipt);
} else {
$receipt['supplier_id'] = $supplierId;
$result = $model->insert($receipt);
}
if ($result) {
$this->response(0, '操作成功');
}
$this->response(-1, '操作失败');
}
//删除
public function DeleteSupplierReceipt($request)
{
$receiptId = $request->get('receipt_id');
$model = new SupplierReceiptModel();
$result = $model->where('receipt_id', $receiptId)->delete();
if ($result) {
$this->response(0, '操作成功');
}
$this->response(-1, '操作失败');
}
}
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Services\SupplierContactService;
use App\Http\Transformers\SupplierLogTransformer;
use App\Http\Validators\SupplierContactValidator;
use App\Http\Validators\SupplierValidator;
use App\Model\SupplierContactModel;
use App\Model\SupplierLogModel;
use Illuminate\Http\Request;
//通用API,比如获取品牌列表,分类列表等
class SupplierContactApiController extends Controller
{
public function Entrance(Request $request, $id)
{
$this->$id($request, $id);
}
public function SaveSupplierContact($request)
{
$data = $request->only([
'contact_id',
'supplier_id',
'supplier_consignee',
'supplier_telephone',
'supplier_fax',
'supplier_qq',
'supplier_mobile',
'supplier_email',
'supplier_position',
]);
//先去表单验证
$validator = new SupplierContactValidator();
$validateResult = $validator->checkSave($request);
if ($validateResult) {
$this->response(-1, $validateResult);
}
$service = new SupplierContactService();
$result = $service->saveContact($data);
if (!$result) {
$this->response(-1, '操作失败');
}
$this->response(0, '操作成功');
}
public function DeleteSupplierContact($request)
{
$contactId = $request->get('contact_id');
if ($contactId) {
$model = new SupplierContactModel();
$result = $model->where('contact_id', $contactId)->delete();
if (!$result) {
$this->response(-1, '删除失败');
}
$this->response(0, '删除成功');
}
$this->response(-1, '找不到删除对象');
}
}
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Transformers\SupplierLogTransformer;
use App\Model\SupplierLogModel;
use Illuminate\Http\Request;
//通用API,比如获取品牌列表,分类列表等
class SupplierLogApiController extends Controller
{
public function Entrance(Request $request, $id)
{
$this->$id($request, $id);
}
//获取供应商信息变更记录
public function GetSupplierLogList($request)
{
$supplierId = $request->get('supplier_id');
$limit = $request->get('limit', 10);
$model = new SupplierLogModel();
$list = $model->where('supplier_id', $supplierId)->orderBy('id', 'desc')->paginate($limit)->toArray();
$transformer = new SupplierLogTransformer();
$list['data'] = $transformer->transformList($list['data']);
$this->response(0, 'ok', $list['data'],$list['total']);
}
//添加
public function AddSupplierLog($request)
{
$data = $request->only([
'supplier_id',
'type',
'desc'
]);
if (empty($data['type']) || empty($data['desc'])) {
$this->response(-1, '类型或者描述都不能为空');
}
$data['admin_id'] = $request->user->userId;
$data['admin_name'] = $request->user->name;
$data['add_time'] = time();
$model = new SupplierLogModel();
$result = $model->insert($data);
if ($result) {
$this->response(0, '添加成功');
}
$this->response(-1, '添加失败',$result);
}
//删除
public function DeleteSupplierLog($request)
{
$logId = $request->get('id');
$model = new SupplierLogModel();
$result = $model->where('id', $logId)->delete();
if ($result) {
$this->response(0, '删除成功');
}
$this->response(-1, '删除失败',$result);
}
}
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Filter\SupplierSyncLogFilter;
use App\Http\Transformers\LogTransformer;
use App\Http\Transformers\SupplierSyncLogTransformer;
use App\Model\LogModel;
use App\Model\SupplierSyncModel;
use Illuminate\Http\Request;
//通用API,比如获取品牌列表,分类列表等
class SupplierSyncLogApiController extends Controller
{
public function Entrance(Request $request, $id)
{
$this->$id($request, $id);
}
//获取供应商信息变更记录
public function GetSupplierSyncLogList($request)
{
$filter = new SupplierSyncLogFilter();
$limit = $request->get('limit', 10);
$query = $filter->listFilter($request);
$list = $query->paginate($limit)->toArray();
$transformer = new SupplierSyncLogTransformer();
$list['data'] = $transformer->transformList($list['data']);
$this->response(0, 'ok', $list['data'], $list['total']);
}
}
...@@ -32,8 +32,27 @@ class Controller extends BaseController ...@@ -32,8 +32,27 @@ class Controller extends BaseController
return view($view, $this->data); return view($view, $this->data);
} }
protected function apiReturn($errCode = 0, $errMsg = 'OK', $data = '') //通用json返回方法
public function response($errCode = 0, $errMsg = '成功', $data = '', $count = 0)
{ {
return apiReturn($errCode, $errMsg, $data); if (is_array($errCode)) {
echo json_encode([
'code' => $errCode[0],
'err_code' => $errCode[0],
'err_msg' => $errCode[1],
'data' => !empty($errCode[2]) ? $errCode[2] : '',
'count' => $count,
]);
exit();
} else {
echo json_encode([
'err_code' => $errCode,
'code' => $errCode,
'err_msg' => $errMsg,
'data' => $data,
'count' => $count,
]);
exit();
}
} }
} }
...@@ -20,7 +20,7 @@ class ExampleController extends Controller ...@@ -20,7 +20,7 @@ class ExampleController extends Controller
'menus' => $request->menus, 'menus' => $request->menus,
'header' => $request->user->header, 'header' => $request->user->header,
'username' => $request->user->email, 'username' => $request->user->email,
'useremail' => $request->user->email, 'user_email' => $request->user->email,
'uri' => '/' . $path, 'uri' => '/' . $path,
'id' => $id 'id' => $id
]; ];
...@@ -32,7 +32,8 @@ class ExampleController extends Controller ...@@ -32,7 +32,8 @@ class ExampleController extends Controller
return $this->errhtml('Not', '没有这个页面'); return $this->errhtml('Not', '没有这个页面');
} }
public function example_list($request){ public function example_list($request)
{
return $this->view('示例列表'); return $this->view('示例列表');
} }
} }
<?php
namespace App\Http\Controllers\Filter;
use App\Http\Services\AdminUserService;
use App\Http\Services\DepartmentService;
use Illuminate\Support\Facades\DB;
class SupplierFilter
{
//查询条件
public function listFilter($request, $query)
{
$map = $request->all();
//判断权限,如果有审核权限的,可以查看所有成员的数据
//超管可以查看所有
$userId = $request->user->userId;
$isLeader = perm($userId, 'LeaderView');
$query = $query->with([
'blacklist'
]);
//先判断获取类型
$sourceType = array_get($map, 'source_type');
switch ($sourceType) {
case "all":
//这个页面会给部门老大查看的,只能看到自己下面的人员申请的供应商
//审核人或者超管,看全部
if ($isLeader) {
$departmentService = new DepartmentService();
//下属用户id
$subordinateUserIds = $departmentService->getSubordinateUserIds($userId);
$query->whereIn('create_uid', $subordinateUserIds);
}
$query->where('status', '!=', -3)->where('status', '!=', -1);
$query->orderBy('supplier_id', 'desc');
break;
case "own":
//自己的供应商,只显示属于自己的(排除黑名单)
$adminUserService = new AdminUserService();
$userCode = $adminUserService->getCodeIdByUserId($userId);
if ($userCode && empty($map['create_uid'])) {
$query->whereRaw(DB::raw("(create_uid = $userId or purchase_uid = $userCode or channel_uid like '%${userCode}%') "));
// $query->whereRaw(DB::raw("(create_uid = $userId or channel_uid like '%${userCode}%') "));
} else {
$query->where('create_uid', $userId);
}
$query->where('status', '!=', -3);
$query->orderBy('supplier_id', 'desc');
break;
case "audited":
//已审核列表只显示 启用,禁用,驳回
$query->whereIn('status', [2, 3, -2]);
$query->orderBy('audit_time', 'desc');
break;
default:
$status = $request->get('status', 0);
$statusArray = explode(',', $status);
if (!empty($statusArray)) {
$query->whereIn('status', $statusArray);
}
$query->orderBy('supplier_id', 'desc');
break;
}
//判断筛选参数
if ($request->user->userId != 1443) {
$query->where('is_type', 0);
}
if (!empty($map['supplier_name'])) {
$query->where('supplier_name', 'like', "%{$map['supplier_name']}%");
}
if (!empty($map['supplier_code'])) {
$codes = explode(',', $map['supplier_code']);
$query->whereIn('supplier_code', $codes);
}
if (!empty($map['supplier_group'])) {
$query->where('supplier_group', $map['supplier_group']);
}
if (!empty($map['stockup_type'])) {
$query->where('stockup_type', 'like', "%{$map['stockup_type']}%");
}
if (!empty($map['channel_uid'])) {
$query->where('channel_uid', $map['channel_uid']);
}
if (!empty($map['purchase_uid'])) {
$query->where('purchase_uid', 'like', "%{$map['purchase_uid']}%");
}
if (!empty($map['create_uid'])) {
$query->where('create_uid', $map['create_uid']);
}
if (!empty($map['status'])) {
$query->where('status', $map['status']);
}
if (!empty($map['create_time'])) {
$times = explode('~', $map['create_time']);
$startTime = strtotime($times[0]);
$endTime = strtotime($times[1]);
$query->whereBetween('create_time', [$startTime, $endTime]);
}
if (!empty($map['blacklist_uid'])) {
$query = $query->whereHas('blacklist', function ($q) use ($map) {
if (!empty($map['blacklist_uid'])) {
$q->where('blacklist_uid', $map['blacklist_uid']);
}
});
}
return $query;
}
}
\ No newline at end of file
<?php
namespace App\Http\Controllers\Filter;
use App\Http\Services\AdminUserService;
use App\Http\Services\DepartmentService;
use App\Model\SupplierSyncModel;
use Illuminate\Support\Facades\DB;
class SupplierSyncLogFilter
{
//查询条件
public function listFilter($request)
{
$map = $request->all();
$model = new SupplierSyncModel();
$query = $model->orderBy('id', 'desc');
if (!empty($map['supplier_id'])) {
$query->where('supplier_id', $map['supplier_id']);
}
if (!empty($map['erp_sync_status']) || (isset($map['erp_sync_status']) && $map['erp_sync_status'] == "0")) {
$query->where('erp_sync_status', $map['erp_sync_status']);
}
if (!empty($map['erp_supplier_code'])) {
$query->where('erp_supplier_code', 'like', "%${map['erp_supplier_code']}%");
}
if (!empty($map['erp_supplier_name'])) {
$query->where('erp_supplier_name', 'like', "%${map['erp_supplier_name']}%");
}
if (!empty($map['last_update_source'])) {
$query->where('last_update_source', $map['last_update_source']);
}
return $query;
}
}
\ No newline at end of file
<?php
namespace App\Http\Controllers;
use App\Http\Services\IndexService;
use App\Http\Services\MessageService;
use App\Model\IntracodeModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class IndexController extends Controller
{
public function Entrance(Request $request, $id = 'index')
{
if ($request->path() == '/') {
$path = 'web/index';
} else {
$path = $request->path();
}
$this->data = [
'menus' => $request->menus,
'header' => $request->user->header,
'username' => $request->user->email,
'user_email' => $request->user->email,
'uri' => '/' . $path,
'id' => $id
];
$userId = $request->user->userId;
$canAudit = perm($userId, 'AuditSupplier');
$this->data['canAudit'] = $canAudit;
//把是否是领导查看放到模板,用来区分部门老大能干的权限
$leaderView = perm($userId, 'LeaderView');
$this->data['leaderView'] = $leaderView;
return $this->$id($request);
}
public function __call($method, $parameters)
{
return $this->errhtml('Not', '没有这个页面');
}
//操作日志列表
public function Index($request)
{
$service = new IndexService();
$statistics = $service->getDailySupplierAddStatistics();
$this->data['dates'] = array_values(array_column($statistics['all'], 'date'));
$this->data['all_increase_statistics'] = array_values(array_column($statistics['all'], 'count'));
$this->data['user_increase_statistics'] = array_values(array_column($statistics['user'], 'count'));
$intracodeModel = new IntracodeModel();
$userCodes = $intracodeModel->getSampleEncode();
$this->data['user'] = $userCodes;
$this->data['purchase_users'] = [];
foreach ($userCodes as $userId => $code) {
$this->data['purchase_users'][] = [
'name' => $code,
'value' => $userId,
];
}
return $this->view('首页');
}
}
\ No newline at end of file
<?php
namespace App\Http\Controllers;
use App\Http\Services\RoleService;
use App\Http\Services\SupplierContactService;
use App\Http\Services\SupplierService;
use App\Http\Services\ViewCheckService;
use App\Model\IntracodeModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class SupplierController extends Controller
{
public function info(Request $request, $id = '')
{
{
if ($request->path() == '/') {
$path = 'web/index';
} else {
$path = $request->path();
}
$this->data = [
'menus' => $request->menus,
'header' => $request->user->header,
'username' => $request->user->email,
'user_email' => $request->user->email,
'uri' => '/' . $path,
'id' => $id
];
$userId = $request->user->userId;
$canAudit = perm($userId, 'AuditSupplier');
$this->data['canAudit'] = $canAudit;
//把是否是领导查看放到模板,用来区分部门老大能干的权限
$leaderView = perm($userId, 'LeaderView');
$this->data['leaderView'] = $leaderView;
return $this->$id($request);
}
}
public function __call($name, $arr)
{
$data['errinfo'] = '访问路径错误';
return view('errors.error', $data);
}
//供应商列表
public function SupplierList($request)
{
$intracodeModel = new IntracodeModel();
$this->data['userCodes'] = $intracodeModel->getSampleEncode();
$this->data['users'] = $intracodeModel->getAdminUserAndCode();
$this->data['validPerms'] = [];
return $this->view('供应商列表');
}
//添加供应商
public function AddSupplier($request, $data)
{
$supplierId = $request->get('supplier_id');
$supplierService = new SupplierService();
$intracodeModel = new IntracodeModel();
$data['outside_contact_status'] = Config('fixed.OutsideContactStatus');
$data['outside_contact_type'] = Config('fixed.OutsideContactType');
$userCodes = $intracodeModel->getSampleEncode();
$data['userCodes'] = $userCodes;
$data['user'] = $userCodes;
$data['purchase_users'] = [];
foreach ($userCodes as $userId => $code) {
$data['purchase_users'][] = [
'name' => $code,
'value' => $userId,
];
}
//编辑
if (!empty($supplierId)) {
$data['title'] = '编辑供应商';
$data['supplierInfo'] = $supplierService->getSupplier($supplierId);
$DB = DB::connection('yunxin');
$supplierAccountInfo = $DB->table('supplier_account')->where("supplier_com_id", "=",
$supplierId)->select('mobile', "password_raw")->first();
$data['supplier_account_info'] = $supplierAccountInfo;
$data['address'] = $supplierService->getAddress($supplierId);
}else{
$data['title'] = '添加供应商';
}
//审核人已经查看
if ($data['canAudit']) {
$viewCheckService = new ViewCheckService();
$viewCheckService->addSupplierView($supplierId);
}
return view('web', $data);
}
//操作日志列表
public function LogList($request, $data)
{
$intracodeModel = new IntracodeModel();
$data['userCodes'] = $intracodeModel->getSampleEncode();
$data['title'] = '操作日志记录';
return view('web', $data);
}
}
\ No newline at end of file
<?php
namespace App\Http\Controllers;
use App\Http\Services\RoleService;
use App\Http\Services\SupplierContactService;
use App\Http\Services\SupplierService;
use App\Http\Services\ViewCheckService;
use App\Model\IntracodeModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class SupplierSyncLogController extends Controller
{
public function info(Request $request, $id = '')
{
$userId = $request->user->userId;
$data = $this->baseInfo($request, $id);
//把是否能审核权限放到模板(重要)
$canAudit = perm($userId, 'AuditSupplier');
//超管和审批人相同权限
$data['canAudit'] = ($canAudit == true) || ($userId == 1000);
//把是否是领导查看放到模板,用来区分部门老大能干的权限
$leaderView = perm($userId, 'LeaderView');
$data['leaderView'] = $leaderView;
if (!empty($data['errcode'])) {
return view('errors.error', $data);
}
return $this->$id($request, $data, $id);
}
public function __call($name, $arr)
{
$data['errinfo'] = '访问路径错误';
return view('errors.error', $data);
}
//操作日志列表
public function SupplierSyncLogList($request, $data)
{
$intracodeModel = new IntracodeModel();
$data['userCodes'] = $intracodeModel->getSampleEncode();
$data['title'] = '供应商同步日志记录';
return view('web', $data);
}
}
\ No newline at end of file
...@@ -24,7 +24,7 @@ class WebController extends Controller ...@@ -24,7 +24,7 @@ class WebController extends Controller
'menus' => $request->menus, 'menus' => $request->menus,
'header' => $request->user->header, 'header' => $request->user->header,
'username' => $request->user->email, 'username' => $request->user->email,
'useremail' => $request->user->email, 'user_email' => $request->user->email,
'uri' => '/' . $path, 'uri' => '/' . $path,
'id' => $id 'id' => $id
]; ];
......
...@@ -24,6 +24,7 @@ class Kernel extends HttpKernel ...@@ -24,6 +24,7 @@ class Kernel extends HttpKernel
*/ */
protected $middlewareGroups = [ protected $middlewareGroups = [
'web' => [ 'web' => [
\App\Http\Middleware\CheckLogin::class,
// \App\Http\Middleware\EncryptCookies::class, // \App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
// \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\StartSession::class,
......
...@@ -24,9 +24,9 @@ class CheckLogin ...@@ -24,9 +24,9 @@ class CheckLogin
$userId = $request->cookie('oa_user_id'); $userId = $request->cookie('oa_user_id');
$skey = $request->cookie('oa_skey'); $skey = $request->cookie('oa_skey');
$isApi = false; $isApi = false;
$pos = strpos($request->path(), 'api/'); $hasApiRoute = strpos($request->path(), 'api/');
if ($pos === 0) if ($hasApiRoute === 0)
$isApi = true; $isApi = true;
if (!$userId || !$skey || (string)((int)$userId) != $userId || !preg_match('/^[a-zA-Z0-9]+$/', $skey)) { if (!$userId || !$skey || (string)((int)$userId) != $userId || !preg_match('/^[a-zA-Z0-9]+$/', $skey)) {
if ($isApi) if ($isApi)
......
...@@ -23,38 +23,57 @@ class Menu ...@@ -23,38 +23,57 @@ class Menu
empty($action) && $action = 'Dashboard'; empty($action) && $action = 'Dashboard';
//获取菜单 //获取菜单
if(!$isApi){ if (!$isApi) {
$menuconfig = json_decode(curl($permArr['menuUrl'].$permArr['menuId']), true); $menuconfig = json_decode(curl($permArr['menuUrl'] . $permArr['menuId']), true);
if(empty($menuconfig['data'])){ if (empty($menuconfig['data'])) {
return $this->view('error','菜单生成错误,请联系技术'); return $this->view('error', '菜单生成错误,请联系技术');
}else{ } else {
$menuconfig = $menuconfig['data']; $menuconfig = $menuconfig['data'];
} }
$menus = !in_array($request->user->userId,$permArr['adminGroup']) ? $menus = !in_array($request->user->userId, $permArr['adminGroup']) ?
menu($menuconfig, $request->user->userId) : $menuconfig; menu($menuconfig, $request->user->userId) : $menuconfig;
if(empty($menus)){ if (empty($menus)) {
return $this->view('Auth','没有访问权限',$permArr['goUrl']); return $this->view('Auth', '没有访问权限', $permArr['goUrl']);
} }
//还要判断是否是基石的url,是的话,要返回绝对地址
$menus = $this->getAbsoluteUrl($menus);
$request->menus = $menus; $request->menus = $menus;
} }
if(!in_array($user->userId,$permArr['adminGroup']) && $action!='Dashboard'){//不是超级管理员 if (!in_array($user->userId, $permArr['adminGroup']) && $action != 'Dashboard') {//不是超级管理员
$perm=perm($request->user->userId,$action); $perm = perm($request->user->userId, $action);
if($perm!==true){ if ($perm !== true) {
if($isApi) if ($isApi) {
return apiReturn(10001,'没有权限'); return apiReturn(10001, '没有权限');
return $this->view('Auth','没有访问权限',$permArr['goUrl']);
} }
return $this->view('Auth', '没有访问权限', $permArr['goUrl']);
} }
return $next($request,$action); }
return $next($request, $action);
} }
private function view($errcode,$errinfo,$goUrl=''){ //获取绝对地址,有一些是嵌入到其它系统内部的,所以要是外链地址
$data=[ private function getAbsoluteUrl($menus)
'errcode'=>$errcode, {
'errinfo'=>$errinfo, foreach ($menus as &$menu) {
'url'=>$goUrl foreach ($menu['childs'] as $k => &$v) {
$href = $v['href'];
$array = explode('/', $href);
$routerName = end($array);
$urls = config('website.AbsoluteUrls');
$v['href'] = !empty($urls[$routerName]) ? $urls[$routerName] : $v['href'];
}
}
return $menus;
}
private function view($errcode, $errinfo, $goUrl = '')
{
$data = [
'errcode' => $errcode,
'errinfo' => $errinfo,
'url' => $goUrl
]; ];
return view('errors.error', $data); return view('errors.error', $data);
} }
......
<?php
namespace App\Http\Services;
//后台用户相关信息服务
use Illuminate\Support\Facades\DB;
class AdminUserService
{
public function getAdminUserInfoByCodeId($codeId)
{
$adminId = DB::connection()->table('lie_intracode')->where('code_id', $codeId)->value('admin_id');
return DB::connection()->table('user_info')->where('userId', $adminId)->first();
}
public function getCodeIdByUserId($userId)
{
return DB::connection()->table('lie_intracode')->where('admin_id', $userId)->value('code_id');
}
public function getAdminUserInfo($userId)
{
$user = DB::connection()->table('user_info')->where('userId', $userId)->first();
return $user ? : [];
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
//后台用户相关信息服务
use App\Model\SupplierBlacklistModel;
use App\Model\SupplierChannelModel;
use Illuminate\Support\Facades\DB;
class BlacklistService
{
public function addSupplierToBlacklist($supplierId, $reason)
{
$supplierModel = new SupplierChannelModel();
$result = $supplierModel->where('supplier_id', $supplierId)->update([
'status' => -3,
'update_time' => time(),
]);
if ($result) {
$model = new SupplierBlacklistModel();
$data = [
'supplier_id' => $supplierId,
'blacklist_uid' => request()->user->userId,
'blacklist_name' => request()->user->name,
'reason' => $reason,
'add_time' => time(),
];
if ($model->where('supplier_id', $supplierId)->count()) {
$res = $model->where('supplier_id', $supplierId)->update($data);
} else {
$res = $model->insert($data);
}
return $res;
}
return false;
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
//后台用户相关信息服务
use App\Model\SupplierChannelModel;
use Illuminate\Support\Facades\DB;
class DataService
{
//清除不合理的开发员
public function clearPurchaseUid()
{
$model = new SupplierChannelModel();
$suppliers = $model->where('purchase_uid', '!=', '')->where('is_type', 0)->get();
$validPurchaseUserIds = [10039, 10201, 10177];
foreach ($suppliers as $supplier) {
//如果不是开发员id不属于上面的有效id,就清空
if (!in_array($supplier['purchase_uid'], $validPurchaseUserIds)) {
$model->where('supplier_id', $supplier['supplier_id'])->update(['purchase_uid' => '']);
var_dump($supplier['purchase_uid']);
} else {
// var_dump($supplier['purchase_uid']);
}
}
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
use DB;
//部门数据服务
class DepartmentService
{
public function getSubordinateUserIds($adminId)
{
$departmentId = DB::table('user_info')->where('userId', $adminId)->value('department_id');
$users = $this->getUserByDepartmentId($departmentId);
return array_column($users, 'userId');
}
// 获取部门人员
public function getUserByDepartmentId($departmentId, $status='', $filter='')
{
$departmentIds = [];
$this->getSubDepartmentId($departmentId, $departmentIds);
return DB::table('user_info')->whereIn('department_id', $departmentIds)
->where(function($query) use($status) {
if ($status !== '') {
$query->where('status', '=', $status);
}
})
->where(function($query) use($filter) {
if ($filter) {
$query->whereRaw($filter);
}
})
->select('userId', 'name', 'status')
->get();
}
// 获取下级部门ID
public function getSubDepartmentId($departmentId, &$departmentIds)
{
// 获取下级部门
$sub_department = DB::table('user_department')->where('parent_id', $departmentId)->select('department_id', 'department_name')->get();
if ($sub_department) {
foreach ($sub_department as $v) {
$this->getSubDepartmentId($v['department_id'], $departmentIds);
}
}
$departmentIds[] = $departmentId;
return $departmentIds;
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
//后台用户相关信息服务
use App\Model\SupplierChannelModel;
use Carbon\Carbon;
use DateInterval;
use DatePeriod;
use DateTime;
use Illuminate\Support\Facades\DB;
class IndexService
{
//获取每日新增统计
public function getDailySupplierAddStatistics()
{
//获取最近10天的数据
$date = Carbon::now()->subDays(9)->getTimestamp();
$today = time();
$period = new DatePeriod(
new DateTime(date('Y-m-d H:i:s', $date)),
new DateInterval('P1D'),
new DateTime(date('Y-m-d H:i:s', $today + 86400))
);
$days = [];
foreach ($period as $key => $value) {
$days[] = $value->format('Y-m-d');
}
$userId = request()->user->userId;
//先统计全局的
$data = DB::connection('web')->select("select FROM_UNIXTIME( create_time, '%Y-%m-%d' ) AS date, count(1) as count from lie_supplier_channel" .
" where create_time >= ${date} and create_time <= ${today} and status = 2 group by date order by date asc;");
//再统计个人的
$userData = DB::connection('web')->select("select FROM_UNIXTIME( create_time, '%Y-%m-%d' ) AS date, count(1) as count from lie_supplier_channel" .
" where create_time >= ${date} and create_time <= ${today} and status =2 and create_uid = ? group by date order by date asc;",
[$userId]);
//组装数据
$allResult = $userResult = [];
foreach ($days as $k => $day) {
foreach ($userData as $key => $item) {
if ($item['date'] == $day) {
$userResult[$k] = [
'date' => $day,
'count' => $item['count']
];
} else {
if (!in_array($day, array_column($userResult, 'date'))) {
$userResult[$k] = [
'date' => $day,
'count' => 0
];
}
}
}
foreach ($data as $key => $item) {
if ($item['date'] == $day) {
$allResult[$k] = [
'date' => $day,
'count' => $item['count']
];
} else {
if (!in_array($day, array_column($allResult, 'date'))) {
$allResult[$k] = [
'date' => $day,
'count' => 0
];
}
}
}
}
if (empty($data) || empty($userData)) {
foreach ($days as $key => $day) {
$allResult[$key] = [
'date' => $day,
'count' => 0,
];
}
}
return [
'all' => $allResult,
'user' => $userResult,
];
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
//后台用户相关信息服务
use App\Model\LogModel;
use Illuminate\Support\Facades\DB;
class LogService
{
//添加日志
public function AddLog($supplierId, $type, $action, $content, $remark = '')
{
$adminId = request()->user->userId;
$adminName = request()->user->name;
$data = [
'supplier_id' => $supplierId,
'type' => $type,
'action' => $action,
'content' => $content,
'remark' => $remark,
'admin_id' => $adminId,
'admin_name' => $adminName,
'add_time' => time(),
];
$model = new LogModel();
$model->insert($data);
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
//后台消息相关服务
use App\Model\SupplierBlacklistModel;
use App\Model\SupplierChannelModel;
class MessageService
{
public function sendSupplierMessage($supplierId, $status)
{
//先去判断状态是否需要通知
if (!in_array($status, [1, -2, 2, 3, -3])) {
return false;
}
$model = new SupplierChannelModel();
$supplier = $model->where('supplier_id', $supplierId)->first();
if (empty($supplier)) {
return false;
}
$supplier = $supplier->toArray();
$blacklistModel = new SupplierBlacklistModel();
$blacklist = $blacklistModel->where('supplier_id', $supplierId)->first();
$blacklist = !empty($blacklist) ? $blacklist->toArray() : [];
$createName = $supplier['create_name'];
$createUid = $supplier['create_uid'];
$adminUserService = new AdminUserService();
$user = $adminUserService->getAdminUserInfo($supplier['audit_uid']);
$auditName = array_get($user, 'name');
$supplierCode = $supplier['supplier_code'];
$supplierName = $supplier['supplier_name'];
$rejectReason = $supplier['reject_reason'];
//还要获取自己的审批人
$auditUserId = 0;
$statusName = array_get(config('fixed.SupplierStatus'), $status);
//状态为2的话,有两个情况,一种是审核通过,一种是重新启用
$messagePass = empty($supplier['audit_time']) ? $auditName . '已审核通过供应商' . $supplierName . ',编码为' . $supplierCode :
$supplierName . '供应商已经被重新启用';
$messageMap = [
-2 => $supplierName . '供应商已经被禁用',
1 => $createName . '已提交审核供应商' . $supplierName . ',编码为' . $supplierCode,
2 => $messagePass,
3 => $auditName . '已驳回审核供应商' . $supplierName . ',编码为' . $supplierCode . ',驳回原因为 : ' . $rejectReason,
-3 => $supplierName . '供应商已经被加入黑名单,原因是' . array_get($blacklist, 'reason'),
];
$sendUserMap = [
-2 => $createUid,
1 => $auditUserId,
2 => $createUid,
3 => $createUid,
-3 => $createUid,
];
$data['supplier_remark'] = array_get($messageMap, $status);
$sendUerId = array_get($sendUserMap, $status);
$user = $adminUserService->getAdminUserInfo($sendUerId);
$mobile = array_get($user, 'mobile', '');
if (!$mobile) {
$result = SendMessage($data, 'supplier-audit-alarm', $mobile);
}
//再找出邮箱
$email = array_get($user, 'email');
if (!$email) {
$result = SendMessage($data, 'supplier-audit-email', $email, 1);
}
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
//后台用户相关信息服务
use Illuminate\Support\Facades\DB;
class RoleService
{
//根据user_id获取角色
public function getRolesByUserId($userId)
{
$bid = config('website.PermId');
$roleIds = DB::connection()->table('t_user_perm')->where('userId', $userId)->where('bid',$bid)->value('roles');
$roleIds = json_decode($roleIds, true);
return DB::connection()->table('t_role_perm')->where('bid',$bid)->whereIn('roleId', $roleIds)->pluck('name');
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
use App\Model\SupplierContactModel;
class SupplierContactService
{
//获取组装后给数据库使用的联系人数据
public function getContactData($supplierId, $contact)
{
$contactData = [];
foreach ($contact['supplier_mobile'] as $key => $value) {
$contactData[] = [
'supplier_id' => $supplierId,
'contact_id' => $contact['contact_id'][$key],
'supplier_consignee' => $contact['supplier_consignee'][$key],
'supplier_telephone' => $contact['supplier_telephone'][$key],
'supplier_mobile' => $contact['supplier_mobile'][$key],
'supplier_qq' => $contact['supplier_qq'][$key],
'supplier_fax' => $contact['supplier_fax'][$key],
'supplier_email' => $contact['supplier_email'][$key],
'supplier_position' => $contact['supplier_position'][$key],
'add_time' => time(),
'can_check_uids' => request()->user->userId,
];
$contactData = array_filter($contactData, function ($contact) {
if (empty($contact['supplier_consignee']) && empty($contact['supplier_telephone'])
&& empty($contact['supplier_mobile'])) {
return false;
}
return true;
});
}
return $contactData;
}
public function saveContact($contact)
{
$model = new SupplierContactModel();
//判断新增还是编辑
if (!empty($contact['contact_id'])) {
$contact['update_time'] = time();
return $model->where('contact_id', $contact['contact_id'])->update($contact);
} else {
$contact['can_check_uids'] = request()->user->userId;
$contact['add_time'] = time();
return $model->insert($contact);
}
}
//批量保存联系方式,要区分新增还是修改还是删除
public function saveContacts($supplierId, $contacts)
{
//先找到原来所有contact
$model = new SupplierContactModel();
$originContactIds = $model->where('supplier_id', $supplierId)->pluck('contact_id')->toArray();
$newContactIds = array_column($contacts, 'contact_id');
$needDeleteContactIds = array_diff_assoc($originContactIds,$newContactIds);
$model->whereIn('contact_id',$needDeleteContactIds)->delete();
foreach ($contacts as $key => $contact) {
//新增
if (empty($contact['contact_id'])) {
$contact['can_check_uids'] = request()->user->userId;
$model->insert($contact);
} else {
unset($contact['can_check_uids']);
//修改
$model->where('contact_id', $contact['contact_id'])->update($contact);
}
}
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
use App\Http\Transformers\SupplierTransformer;
use App\Model\SupplierAddressModel;
use App\Model\SupplierChannelModel;
use App\Model\SupplierContactModel;
use Illuminate\Support\Facades\DB;
use RedisDB;
class SupplierService
{
public function getSupplier($supplierId)
{
$model = new SupplierChannelModel();
$supplier = $model->where('supplier_id', $supplierId)->with('contact')->first();
$transformer = new SupplierTransformer();
$supplier = $transformer->transformInfo($supplier);
return $supplier ? $supplier->toArray() : [];
}
//生成供应商编码(外部用,展示用),supplierCode是供应商的核心编码,内部使用,可以理解为唯一标识
public function generateSupplierSn($supplierId, $supplierGroup)
{
$model = new SupplierChannelModel();
$supplier = $model->where('supplier_id', $supplierId)->first()->toArray();
$snMap = config('fixed.SupplierSnMap');
$supplierCodeNumber = substr($supplier['supplier_code'], 1);
return array_get($snMap, $supplierGroup, "ERR") . $supplierCodeNumber;
}
public function saveSupplier($channel, $contact)
{
//先处理下数据
if (!empty($channel['stockup_type'])) {
$stockupType = array_keys($channel['stockup_type']);
$stockupType = !empty($stockupType) ? implode(",", $stockupType) : '';
$channel['stockup_type'] = $stockupType;
}
if (!empty($channel['currency'])) {
if ($channel['currency'] != 1) {
$channel['tax_number'] = '';
}
}
// $channel['qualification_photos'] = $channel['qualification_photos'] ? json_encode($channel['qualification_photos']) : '';
$channel['established_time'] = strtotime($channel['established_time']);
//走事务
return DB::connection('web')->transaction(function () use ($channel, $contact) {
$model = new SupplierChannelModel();
$contactModel = new SupplierContactModel();
$contactService = new SupplierContactService();
//插入
if (empty($channel['supplier_id'])) {
//先去插入到channel表
$channel['create_uid'] = request()->user->userId;
$channel['create_name'] = request()->user->name;
$channel['create_time'] = time();
$supplierId = $model->insertGetId($channel);
$contactData = $contactService->getContactData($supplierId, $contact);
$contactModel->insert($contactData);
$this->saveSupplierCode($supplierId);
} else {
$supplierId = $channel['supplier_id'];
$contactData = $contactService->getContactData($supplierId, $contact);
$model->where('supplier_id', $supplierId)->update($channel);
$contactService->saveContacts($supplierId,$contactData);
$this->saveSupplierCode($supplierId);
}
$supplierSn = $this->generateSupplierSn($supplierId, $channel['supplier_group']);
//修改数据
$model->where('supplier_id', $supplierId)->update(['supplier_sn' => $supplierSn]);
$messageService = new MessageService();
$messageService->sendSupplierMessage($supplierId, $channel['status']);
return true;
});
}
//报错供应商编码,包括系统生成的和自定义规则生成的
private function saveSupplierCode($supplierId)
{
$model = new SupplierChannelModel();
$supplier = $model->where('supplier_id', $supplierId)->first();
if (!empty($supplier)) {
$supplier = $supplier->toArray();
$supplierCode = 'L' . str_pad($supplierId, 7, "0", STR_PAD_LEFT);
return $model->where('supplier_id', $supplierId)->update([
'supplier_code' => $supplierCode,
]);
} else {
return false;
}
}
public function getMainBrands($mainBrandIds)
{
$mainBrandIds = explode(',', $mainBrandIds);
if (!$mainBrandIds) {
return [];
}
$mainBrands = [];
if ($mainBrandIds) {
$redis = RedisDB::connection();
$mainBrands = $redis->hmGet('brand', $mainBrandIds);
}
return $mainBrands;
}
public function getAddress($supplierId)
{
$model = new SupplierAddressModel();
$address = $model->where('supplier_id', $supplierId)->limit(2)->get();
$data = [
'shipping_address' => '',
'return_address' => '',
'return_consignee' => '',
'return_phone' => '',
];
if ($address) {
$address = $address->toArray();
//区分发货还是退货,1是发货,2是退货
foreach ($address as $key => $item) {
if ($item['address_type'] == 1) {
$data['shipping_address'] = $item['address'];
} else {
$data['return_address'] = $item['address'];
$data['return_consignee'] = $item['consignee'];
$data['return_phone'] = $item['phone'];
}
}
return $data;
}
return [];
}
//保存收退货地址
public function saveAddress($map)
{
$supplierModel = new SupplierChannelModel();
$supplierCode = $supplierModel->where('supplier_id', $map['supplier_id'])->value('supplier_code');
//组装成两条数据(鬼知道以前为啥存两条)
$shippingData = [
'supplier_id' => $map['supplier_id'],
'supplier_code' => $supplierCode,
'address' => $map['shipping_address'],
'address_type' => 1,
];
$addressModel = new SupplierAddressModel();
$infoId = $addressModel->where('supplier_id', $map['supplier_id'])->where('address_type', 1)->value('info_id');
if ($infoId) {
$result = $addressModel->where('info_id', $infoId)->update($shippingData);
} else {
$result = $addressModel->insert($shippingData);
}
if (!$result) {
return $result;
}
$returnData = [
'supplier_id' => $map['supplier_id'],
'supplier_code' => $supplierCode,
'address' => $map['return_address'],
'address_type' => 2,
'consignee' => $map['return_consignee'],
'phone' => $map['return_phone'],
];
$infoId = $addressModel->where('supplier_id', $map['supplier_id'])->where('address_type', 2)->value('info_id');
if ($infoId) {
$result = $addressModel->where('info_id', $infoId)->update($returnData);
} else {
$result = $addressModel->insert($returnData);
}
$logService = new LogService();
$logService->AddLog($map['supplier_id'], 2, '保存地址信息', ' ');
return $result;
}
//保存接口信息
public function saveApiData($map)
{
$data = [
'supplier_id' => $map['supplier_id'],
'outside_contact_status' => $map['outside_contact_status'],
'outside_contact_type' => $map['outside_contact_type'],
'outside_contact_url' => $map['outside_contact_url'],
'outside_contact_username' => $map['outside_contact_username'],
'outside_contact_password' => $map['outside_contact_password'],
];
$supplierModel = new SupplierChannelModel();
$logService = new LogService();
$logService->AddLog($map['supplier_id'], 2, '保存接口对接信息', ' ');
return $supplierModel->where('supplier_id', $map['supplier_id'])->update($data);
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
//后台用户相关信息服务
use App\Model\SupplierChannelModel;
use App\Model\SupplierContactModel;
use App\Model\SupplierSyncModel;
use Illuminate\Support\Facades\DB;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
class SyncSupplierService
{
//同步供应商到erp
public function syncSupplierToErp($supplierId)
{
//先去获取供应商的信息
$supplierModel = new SupplierChannelModel();
$supplier = $supplierModel->where('supplier_id', $supplierId)->first();
if (empty($supplier)) {
return false;
}
//只推送禁用和启用状态的
if (!in_array($supplier['status'], [2, -2, -3])) {
return true;
}
//先去sync表查询记录是否存在,不存在新增,存在修改
$supplierSyncModel = new SupplierSyncModel();
$exist = $supplierSyncModel->where('supplier_id', $supplierId)->count();
if (!empty($exist)) {
$supplierSyncModel->where('supplier_id', $supplierId)->update([
'erp_sync_status' => 0,
'update_time' => time(),
'last_update_source' => 2,
]);
} else {
$supplierSyncModel->insert([
'erp_sync_status' => 0,
'supplier_id' => $supplierId,
'add_time' => time(),
'last_update_source' => 2,
]);
}
$contactModel = new SupplierContactModel();
$contact = $contactModel->where('supplier_id', $supplier['supplier_id'])->orderBy('contact_id', 'asc')->first();
$purchases = $this->getPurchases($supplier['channel_uid']);
$message = [
'name' => $supplier['supplier_name'],
'PTID' => $supplier['supplier_code'],
'STATUS' => $supplier['status'] == 2 ? 1 : 2,
];
if (!empty($supplier['supplier_group'])) {
$message['groupNumber'] = array_get(config('sync.SyncSupplierType'), $supplier['supplier_group'], '');
}
if (!empty($supplier['tax_number'])) {
$message['taxRegisterNo'] = $supplier['tax_number'];
}
if (!empty($purchases)) {
$message['personName'] = $purchases;
}
if (!empty($supplier['supplier_address'])) {
$message['address'] = $supplier['supplier_address'];
}
if (!empty(array_get($contact, 'supplier_consignee'))) {
$message['contactPerson'] = array_get($contact, 'supplier_consignee');
}
if (!empty(array_get($contact, 'supplier_telephone'))) {
$message['phone'] = array_get($contact, 'supplier_telephone');
}
if (!empty($supplier['currency'])) {
$message['currencyNumber'] = array_get(config('sync.SyncCurrencyType'), $supplier['currency']);
}
$conn = new AMQPStreamConnection(config('database.connections.rabbitmq.host'),
config('database.connections.rabbitmq.port'),
config('database.connections.rabbitmq.login'),
config('database.connections.rabbitmq.password'));
$channel = $conn->channel();
$channel->queue_declare('supplier_sync', false, true, false, false);
$msg = new AMQPMessage(json_encode($message),
array('content_type' => 'text/plain'));
$result = $channel->basic_publish($msg, '', 'supplier_sync');
// $result = $channel->basic_publish($msg);
}
//获取采购人员列表
private function getPurchases($purchaseUid)
{
$purchaseUid = explode(',', $purchaseUid);
if (empty($purchaseUid)) {
return [];
}
$adminIds = DB::connection()->table('lie_intracode')->whereIn('code_id', $purchaseUid)->pluck('admin_id');
return DB::connection()->table('user_info')->whereIn('userId', $adminIds)->pluck('name');
}
}
\ No newline at end of file
<?php
namespace App\Http\Services;
//后台用户相关信息服务
use App\Model\RedisModel;
use Illuminate\Support\Facades\DB;
//用于判断是否已经查看的服务
class ViewCheckService
{
//将供应商是否查看放入哈希
public function addSupplierView($supplierId)
{
$redis = new RedisModel();
if (!$redis->hget('supplier_view_check', $supplierId)) {
$redis->hset('supplier_view_check', $supplierId, 1);
}
}
//检查供应商编辑页面是否被审核人查看过
public function checkSupplierView($supplierIds = [])
{
if (!$supplierIds) {
return [];
}
$redis = new RedisModel();
$data = [];
$result = $redis->hmGet('supplier_view_check', $supplierIds);
foreach ($supplierIds as $key => $supplierId) {
if (!empty($result[$key])) {
$data[$supplierId] = true;
}else{
$data[$supplierId] = false;
}
}
return $data;
}
}
\ No newline at end of file
<?php
namespace App\Http\Transformers;
class LogTransformer
{
public function transformList($list)
{
foreach ($list as &$item) {
$item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
$item['type'] = array_get(config('fixed.LogType'), $item['type']);
}
unset($item);
return $list;
}
}
\ No newline at end of file
<?php
namespace App\Http\Transformers;
class ReceiptTransformer
{
public function transformList($list)
{
foreach ($list as &$item) {
}
unset($item);
return $list;
}
}
\ No newline at end of file
<?php
namespace App\Http\Transformers;
class SupplierLogTransformer
{
public function transformList($list)
{
foreach ($list as &$item) {
$item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
$item['type'] = array_get(config('fixed.SupplierLogType'), $item['type']);
}
unset($item);
return $list;
}
}
\ No newline at end of file
<?php
namespace App\Http\Transformers;
class SupplierSyncLogTransformer
{
//同步日志转换
public function transformList($list)
{
foreach ($list as &$item) {
$item['erp_sync_status'] = $item['erp_sync_status'] == 1 ? "是" : "否";
$item['last_update_source'] = $item['last_update_source'] == 1 ? "平台修改" : "其他";
$item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
$item['update_time'] = date('Y-m-d H:i:s', $item['update_time']);
}
unset($item);
return $list;
}
}
\ No newline at end of file
<?php
namespace App\Http\Transformers;
use App\Http\Services\AdminUserService;
use App\Http\Services\ViewCheckService;
use App\Model\IntracodeModel;
class SupplierTransformer
{
public function transformList($list)
{
$intracodeModel = new IntracodeModel();
$users = $intracodeModel->getSampleEncode();
$supplierIds = array_column($list, 'supplier_id');
$viewCheckService = new ViewCheckService();
$viewData = $viewCheckService->checkSupplierView($supplierIds);
$adminUserService = new AdminUserService();
foreach ($list as &$item) {
$item['viewed'] = array_get($viewData, $item['supplier_id'], false);
$item['stockup_type'] = explode(',', $item['stockup_type']);
$item['stockup_type'] = array_map(function ($value) {
return array_get(config('fixed.StockupType'), $value);
}, $item['stockup_type']);
$item['stockup_type'] = implode(' | ', $item['stockup_type']);
$item['supplier_group'] = array_get(config('fixed.SupplierGroup'), $item['supplier_group'], '未设置');
$item['create_time'] = date('Y-m-d H:i:s', $item['create_time']);
$item['audit_time'] = $item['audit_time'] ? date('Y-m-d H:i:s', $item['audit_time']) : '';
$item['update_time'] = $item['update_time'] ? date('Y-m-d H:i:s', $item['update_time']) : '';
$item['channel_username'] = $this->getChannelNames($item['channel_uid']);
$item['purchase_username'] = array_get($users, $item['purchase_uid']);
$item['status_name'] = array_get(config('fixed.SupplierStatus'), $item['status']);
$item['contact_num'] = 1;
$item['is_own'] = $item['create_uid'] == request()->user->userId ? "创建" : "指派";
if (empty($item['create_name'])) {
$userInfo = $adminUserService->getAdminUserInfo($item['create_uid']);
$item['create_name'] = array_get($userInfo, 'name');
}
$item['is_channel_or_purchase_user_view'] = $this->getIsChannelOrPurchaseUserView($item);
//黑名单
if (!empty($item['blacklist'])) {
$item['blacklist_name'] = $item['blacklist']['blacklist_name'];
$item['blacklist_time'] = date('Y-m-d H:i:s', $item['blacklist']['add_time']);
$item['blacklist_reason'] = $item['blacklist']['reason'];
}
}
unset($item);
return $list;
}
public function getChannelNames($channelUid)
{
$intracodeModel = new IntracodeModel();
$userCodes = $intracodeModel->getSampleEncode();
$channelUidArr = explode(',', $channelUid);
$channelUidArr = array_map(function ($userId) use ($userCodes) {
return array_get($userCodes, $userId);
}, $channelUidArr);
return implode(',', $channelUidArr);
}
//判断当前登陆的用户,是不是非创建者,但是是属于该供应商的采购或者开发,如果是采购或者开发,就没有操作权限
private function getIsChannelOrPurchaseUserView($supplier)
{
$supplier['is_channel_or_purchase_user_view'] = false;
$viewUserId = request()->user->userId;
$adminUserService = new AdminUserService();
$viewUserCode = $adminUserService->getCodeIdByUserId($viewUserId);
if (empty($viewUserCode)) {
return false;
}
if ($viewUserId != $supplier['create_uid']) {
if ($viewUserCode == $supplier['purchase_uid'] ||
strpos($supplier['channel_uid'], (string)$viewUserCode) !== false) {
return true;
}
}
return false;
}
public function transformInfo($supplier)
{
$supplier['qualification_photos'] = trim($supplier['qualification_photos']);
$supplier['stockup_type_data'] = $this->transformStockupTypeData($supplier['stockup_type']);
$supplier['established_time'] = !empty($supplier['established_time']) ? date('Y-m-d',
$supplier['established_time']) : '';
$supplier['is_channel_or_purchase_user_view'] = $this->getIsChannelOrPurchaseUserView($supplier);
if (!empty($supplier['contact'])) {
$adminUserService = new AdminUserService();
foreach ($supplier['contact'] as &$contact) {
$user = $adminUserService->getAdminUserInfo($contact['can_check_uids']);
$contact['can_check_name'] = array_get($user, 'name');
if (empty($contact['can_check_name'])) {
$user = $adminUserService->getAdminUserInfo($supplier['create_uid']);
$contact['can_check_name'] = array_get($user, 'name');
}
}
}
$previewConfigs = $this->getPreviewConfigs($supplier);
$supplier['previewConfigs'] = json_encode($previewConfigs);
return $supplier;
}
private function getPreviewConfigs($supplier)
{
//处理一些图片的数据给前端插件用
$previewConfigs = [];
if (!empty($supplier['qualification_photos'])) {
$photos = json_decode($supplier['qualification_photos'], true);
foreach ($photos as $photo) {
$arr = parse_url($photo);
$arr = pathinfo($arr['path']);
$type = "image";
if ($arr['extension'] == "pdf") {
$type = "pdf";
}
if ($arr['extension'] == "zip") {
$type = "other";
}
$previewConfigs[] = [
'type' => $type,
'downloadUrl' => $photo,
'caption' => $photo,
];
}
}
return $previewConfigs;
}
public function transformStockupTypeData($stockupType)
{
if (!empty($stockupType)) {
$stockupType = explode(',', $stockupType);
return $stockupType;
}
return [];
}
}
\ No newline at end of file
<?php
namespace App\Http\Validators;
use App\Model\SupplierChannelModel;
use Validator;
class ReceiptValidator
{
//保存相关的验证,别问我为什么不用laravel自带的form-request类
//因为控制器那边已经被之前的人魔改的难用的一比,而且控制器那边还接收了一大堆统一变量
public function checkSave($request)
{
//整理下请求数据
$receipt = $request->get('receipt');
$receiptType = $receipt['receipt_type'];
if ($receiptType == 1) {
$rules = [
"bank_name" => "required",
"bank_adderss" => "required",
"account_no" => "required",
"account_name" => "required",
"certificate" => "required",
];
} else {
$rules = [
"bank_name" => "required",
"bank_adderss" => "required",
"account_no" => "required",
"swift_code" => "required",
"account_name" => "required",
"certificate" => "required",
];
}
$messages = $this->messages();
$validator = Validator::make($receipt, $rules, $messages);
//判断联系方式的表单验证
if ($validator->fails()) {
return $validator->errors()->first();
}
}
private function messages()
{
return [
'bank_name.required' => '银行名称不能为空',
'bank_adderss.required' => '银行地址不能为空',
'account_no.required' => '账户号码不能为空',
'swift_code.required' => '电汇号码不能为空',
'account_name.required' => '账户名称不能为空',
'certificate.required' => '银行信息凭证不能为空',
];
}
}
\ No newline at end of file
<?php
namespace App\Http\Validators;
use Validator;
class SampleValidator
{
//保存相关的验证,别问我为什么不用laravel自带的form-request类
//因为控制器那边已经被之前的人魔改的难用的一比,而且控制器那边还接收了一大堆统一变量
public function checkSave($request)
{
$messages = $this->messages();
$validator = Validator::make($request->all(), [
'activity_name' => 'required|max:50',
'start_time' => 'required',
'end_time' => 'required',
'goods_scope' => 'in:1,2',
'allow_coupon' => 'required',
'amount' => 'required|max:9999999999',
'amount.*' => 'required',
'item_name' => 'required',
'item_name.*' => 'required',
'num' => 'required|max:1000',
'num.*' => 'required',
'total' => 'required',
'total.*' => 'required',
'pic' => 'required',
'pic.*' => 'required',
'supplier_ids' => 'required',
], $messages);
if ($validator->fails()) {
return $validator->errors()->first();
}
//开始结束时间的判断
$oneDaySeconds = 3600 * 24;
if (strtotime($request->get('end_time')) - strtotime($request->get('start_time')) < $oneDaySeconds) {
return '结束时间必须大于开始时间一天或以上';
}
//满赠商品规则最多设置3个
if (count($request->get('amount')) > 3) {
return '满赠商品规则最多设置3个';
}
$service = new GiftActivityService();
$itemList = $service->getGiftItemList($request);
if (count($itemList) != 1) {
foreach ($itemList as $key => $item) {
if ($key == 0) {
continue;
}
if ($itemList[$key]['amount'] <= $itemList[$key - 1]['amount']) {
return '设置满赠规则的满赠金额需逐级递增';
}
}
}
//通用逻辑判断
$result = $this->commonLogicCheck($request, 2);
if ($result !== true) {
return $result;
}
return null;
}
private function messages()
{
return [
'activity_name.max' => '展示名称最长50个汉字',
'show_name.max' => '展示名称最长3个汉字',
'sign.max' => '标识最长1个汉字',
'sign_text.max' => '展示名称最长16个汉字',
'ratio.numeric' => '活动系数只能为纯数字',
'amount.required' => '至少要有一个满赠商品规则',
'activity_name.required' => '活动名称不能为空',
'start_time.required' => '活动开始时间不能为空',
'end_time.required' => '活动结束时间不能为空',
'show_name.required' => '活动展示名称不能为空',
'sign.required' => '活动标识不能为空',
'sign_text.required' => '活动标识文本不能为空',
'allow_coupon.required' => '是否能使用优惠券不能为空',
'amount.*.required' => '请补全满赠商品规则的满赠金额',
'amount.*.max' => '请补全满赠商品规则的满赠金额',
'item_name.*.required' => '请补全满赠商品规则的赠品名称',
'item_name.*.between' => '满赠商品规则的赠品名称必须在2到20个字之间',
'num.*.required' => '请补全满赠商品规则的数量',
'total.*.required' => '请补全满赠商品规则的发行量',
'pic.*.required' => '请补全满赠商品规则的商品图片',
'supplier_ids.required' => '供应商不能为空',
'goods_scope.in' => '商品范围不符合规范',
];
}
}
\ No newline at end of file
<?php
namespace App\Http\Validators;
use App\Model\SupplierChannelModel;
use Validator;
class SupplierContactValidator
{
public function checkSave($request)
{
$data = $request->all();
$rules = [
"supplier_consignee" => "required",
"supplier_email" => "required",
"supplier_telephone" => "required",
];
$messages = $this->messages();
$validator = Validator::make($data, $rules, $messages);
//判断联系方式的表单验证
if ($validator->fails()) {
return $validator->errors()->first();
}
}
private function messages()
{
return [
'supplier_consignee.required' => '联系人不能为空',
'supplier_email.required' => '联系人邮箱不能为空',
'supplier_telephone.required' => '联系人座机不能为空',
];
}
}
\ No newline at end of file
<?php
namespace App\Http\Validators;
use App\Model\SupplierChannelModel;
use Validator;
class SupplierValidator
{
//保存相关的验证,别问我为什么不用laravel自带的form-request类
//因为控制器那边已经被之前的人魔改的难用的一比,而且控制器那边还接收了一大堆统一变量
public function checkSave($request)
{
//整理下请求数据
$requestData = $request->all();
$requestData = $this->transformRequestData($requestData);
$rules = [
'supplier_name' => 'required',
'stockup_type' => 'required',
'supplier_group' => 'required',
'region' => 'required',
'contact.supplier_consignee.*' => 'required|max:50',
'contact.supplier_mobile.*' => 'required|max:30',
'contact.supplier_telephone.*' => 'max:30',
'contact.supplier_email.*' => 'required|email',
'contact.supplier_position.*' => 'required|max:30',
];
//币种为人民币的话需要验证税号
if ($requestData['currency'] == 1) {
$rules['tax_number'] = 'required';
}
if ($requestData['status'] == -1) {
$rules = ['supplier_name' => 'required'];
}
$messages = $this->messages();
$validator = Validator::make($requestData, $rules, $messages);
//判断联系方式的表单验证
if ($validator->fails()) {
// dd($validator->errors());
return $validator->errors()->first();
}
//检验名称是否已经存在数据库
$supplierModel = new SupplierChannelModel();
if (empty($request->get('supplier_id'))) {
$count = $supplierModel->where('supplier_name', $request->get('supplier_name'))->count();
} else {
$count = $supplierModel->where('supplier_name', $request->get('supplier_name'))
->where('supplier_id', '!=', $request->get('supplier_id'))->count();
}
if ($count) {
return "该供应商名称已经存在,请核验后再提交";
}
}
private function messages()
{
return [
'supplier_name.required' => '供应商名称不能为空',
'stockup_type.required' => '合作类型不能为空',
'supplier_group.required' => '行业性质不能为空',
'region.required' => '所属区域不能为空',
'purchase_uid.required' => '渠道开发员不能为空',
'tax_number.required' => '如果选择币种为人民币,则公司税号不能为空',
'contact.supplier_consignee.*.required' => '联系方式的联系人不能为空',
'contact.supplier_consignee.*.max' => '联系方式的联系人不能超过50个字符',
'contact.supplier_position.*.required' => '联系方式的职称不能为空',
'contact.supplier_position.*.max' => '联系方式的职称不能超过30个字符',
'contact.supplier_mobile.*.required' => '联系方式的手机号不能为空',
'contact.supplier_mobile.*.max' => '联系方式的手机号不能超过30个字符',
'contact.supplier_email.*.required' => '联系方式的邮箱不能为空',
'contact.supplier_email.*.email' => '联系方式的邮箱格式不对',
];
}
public function transformRequestData($requestData)
{
return $requestData;
}
}
\ No newline at end of file
<?php
namespace App\Http\Validators;
class Validator
{
}
\ No newline at end of file
...@@ -11,14 +11,28 @@ ...@@ -11,14 +11,28 @@
| |
*/ */
Route::get('/', function () {
return view('welcome');
});
Route::group(['middleware' => ['web', 'menu']], function () { Route::group(['middleware' => ['web', 'menu']], function () {
Route::get('/', 'WebController@Entrance'); Route::get('/', 'WebController@Entrance');
Route::match(['get', 'post'], '/web/{key}', 'WebController@Entrance'); Route::match(['get', 'post'], '/web/{key}', 'WebController@Entrance');
Route::match(['get', 'post'], '/common/api/{key}', 'BaseController@Entrance'); // Route::get('/', 'WebController@info');
Route::match(['get', 'post'], '/example/{key}', 'ExampleController@Entrance'); // Route::match(['get', 'post'], '/web/{key}', 'WebController@info');
Route::match(['get', 'post'], '/supplier/{key}', 'SupplierController@info');
// Route::match(['get', 'post'], '/supplier_sync_log/{key}', 'SupplierSyncLogController@info');
Route::match(['get', 'post'], '/index/{key}', 'IndexController@Entrance');
// Route::match(['get', 'post'], '/api/{key}', 'ApiController@Entrance');
// Route::match(['get', 'post'], '/hd/{key}', 'HandleController@Entrance');
Route::get('/pushAmq', 'QueuedController@pushAmq');
Route::get('/pullAmq', 'QueuedController@pullAmq');
});
Route::group(['middleware' => ['web'], 'namespace' => 'Api'], function () {
Route::match(['get', 'post'], '/api/common/{key}', 'CommonApiController@Entrance');
Route::match(['get', 'post'], '/api/supplier_log/{key}', 'SupplierLogApiController@Entrance');
Route::match(['get', 'post'], '/api/supplier_contact/{key}', 'SupplierContactApiController@Entrance');
Route::match(['get', 'post'], '/api/supplier/{key}', 'SupplierApiController@Entrance');
Route::match(['get', 'post'], '/api/log/{key}', 'LogApiController@Entrance');
Route::match(['get', 'post'], '/api/receipt/{key}', 'ReceiptApiController@Entrance');
Route::match(['get', 'post'], '/api/supplier_sync_log/{key}', 'SupplierSyncLogApiController@Entrance');
}); });
\ No newline at end of file
<?php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
class IntracodeModel extends Model
{
protected $table = 'lie_intracode';
protected $primaryKey = 'code_id';
public function getEncode()
{
$redis = new RedisModel();
$codeList = json_decode($redis->get('EncodedList_supplier'), true);
if (!$codeList) {
$codeList = $this->where('admin_id', '>', 0)->join('user_info', 'lie_intracode.admin_id', '=',
'user_info.userId')->select('code_id', 'admin_id', 'name', 'email')->get();
if ($codeList) {
$codeList = $codeList->toArray();
foreach ($codeList as $k => &$v) {
if (empty($v['name'])) {
$v['name'] = $v['email'];
}
}
$redis->set('EncodedList_supplier', json_encode($codeList));
$redis->expire('EncodedList_supplier', 60 * 10);//缓存10分钟
}
}
return $codeList;
}
//获取简单的内部用户数据
public function getSampleEncode()
{
$codeList = $this->getEncode();
$result = [];
foreach ($codeList as $code) {
$result[$code['code_id']] = $code['name'] . '(' . $code['code_id'] . ')';
}
return $result;
}
//获取admin_id对应user_code的用户数据
public function getAdminUserAndCode()
{
$codeList = $this->getEncode();
$result = [];
foreach ($codeList as $code) {
$result[$code['admin_id']] = $code['name'] . '(' . $code['code_id'] . ')';
}
return $result;
}
public function getEncodeByUserId($userId)
{
$code = $this->where('admin_id', '>', 0)->join('user_info', 'lie_intracode.admin_id', '=', 'user_info.userId')
->where('user_info.userId', $userId)
->select('code_id', 'admin_id', 'name', 'email', 'mobile')->first();
if ($code) {
$code = $code->toArray();
}
return $code;
}
}
<?php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Redis;
class RedisModel extends Model
{
private $WRITE_CONNECT_METHOD = ['set', 'del', 'rpush','lpush', 'expire', 'hset', 'hmset', 'hdel'];
private $read = [];
private $write = [];
public function __construct($ConnectWrite = 'default', $ConnectRead = 'read')
{
parent::__construct();
$this->read = Redis::connection($ConnectRead);
$this->write = Redis::connection($ConnectWrite);
}
public function __call($method, $args)
{
if (in_array($method, $this->WRITE_CONNECT_METHOD)) {
return $this->write->$method(...$args);
} else {
try {
return $this->read->$method(...$args);
} catch (ConnectionException $e) {
return $this->write->$method(...$args);
}
}
}
//管道
public function pipeline_to_hset($data){
return $this->write->pipeline(function ($pipe) use ($data) {
foreach ($data['data'] as $k => $v) {
$pipe->hset($data['key'],$k,$v);
}
});
}
}
<?php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
class SupplierBlacklistModel extends Model
{
protected $connection='web';
protected $table='supplier_blacklist';
protected $primaryKey = 'id';
public $timestamps = false;
}
<?php
namespace App\Presenters;
class BrandSelectorPresenter
{
public function render($name, $text, $value = null, $data = [0 => '禁用', 1 => '启用'], $option = [])
{
$isRequired = array_get($option, 'required', false);
$requiredHtml = $isRequired ? '<span style="color: red">*</span>' : "";
$html = <<<EOF
<label class="layui-form-label">
$requiredHtml
$text</label>
<div class="layui-input-inline">
<div id="$name" class="layui-input-inline" value="$value" style="width: 700px;">
</div>
<input type="hidden" name="$name" id="$name">
</div>
<script>
//渲染品牌多选
let brandUrl = '/api/common/getBrandList';
let brandSelector = xmSelect.render({
el: '#$name',
name: '$name',
searchTips: '请输入要查找的制造商',
paging: true,
empty: '没有查找到数据',
prop: {
name: 'brand_name',
value: 'brand_id'
},
height: "1300px",
remoteSearch: true,
autoRow: true,
pageRemote: true,
pageSize: 10,
filterable: true,
remoteMethod: function (val, cb, show, pageIndex) {
//val: 搜索框的内容, 不开启搜索默认为空, cb: 回调函数, show: 当前下拉框是否展开, pageIndex: 当前第几页
$.ajax({
url: brandUrl,
type: 'post',
data: {
brand_ids: $('#$name').val(),
brand_name: val,
page: pageIndex
},
dataType: 'json',
timeout: 10000,
success: function (res) {
if (!res) return layer.msg('网络错误,请重试', {icon: 5});
if (res.code === 0) {
cb(res.data, res.count/10);
}
},
error: function () {
return layer.msg('网络错误,请重试', {icon: 5});
}
});
},
on: function (data) {
let brandIds = '';
for (let x in data.arr) // x 为属性名
{
brandIds = brandIds + data.arr[x].brand_id + ',';
}
$("#brand_ids").val(brandIds);
}
});
let brandIds = $('#brand_selector').attr('value');
brandSelector.setValue(brandIds.split(','));
</script>
EOF;
return $html;
}
}
\ No newline at end of file
<?php
namespace App\Presenters;
class DateTimePresenter
{
public function render($name, $text, $value)
{
$time = $value;
return <<<EOF
<label class="layui-form-label">$text</label>
<div class="layui-input-inline">
<input type="text" id="$name" name="$name"
placeholder="请输入$text"
class="layui-input"
value="$time">
</div>
<script>
window.onload = function(){
layui.use('laydate', function(){
let laydate = layui.laydate;
laydate.render({
elem: 'input[name=$name]'
,type: 'datetime'
,format: 'yyyy-MM-dd H:i:s'
});
});
}
</script>
EOF;
}
}
\ No newline at end of file
<?php
namespace App\Presenters;
class ImageUploadPresenter
{
public function render($name, $text, $value = null, $option = [])
{
$isRequired = array_get($option, 'required', false);
$requiredHtml = $isRequired ? '<span style="color: red">*</span>' : "";
$uploadUrl = config('website.UploadUrl');
$value = !empty(trim($value)) ? $value : "[]";
$Autograph = Autograph();
return <<<EOF
<label class="layui-form-label">
$requiredHtml
$text
</label>
<div class="layui-input-inline" style="width: 700px">
<input type="hidden" id="$name" name="$name" value='$value'>
<input id="uploadContainer" type="file" multiple name="upload">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/bootstrap-fileinput/5.1.4/css/fileinput.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-fileinput/5.1.4/js/fileinput.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-fileinput/5.1.4/js/locales/zh.min.js"></script>
<script>
$Autograph
let element = $("#uploadContainer");
let arr = $("#$name").val()?JSON.parse($("#$name").val()):[];
element.fileinput({
uploadUrl : "$uploadUrl",//上传图片的url
allowedFileExtensions : [ 'jpg', 'png','jepg','jpeg' ],
overwriteInitial : false,
uploadAsync:true,
showRemove:false,
showUpload:false,
initialPreviewShowPreview:false,
language:'zh',
maxFileSize : 5000,
maxFileCount: 5,
initialCaption: "请上传$text",
initialPreview: $value,
initialPreviewAsData: true,
uploadExtraData:function(){
let data = {
k1:k1,
k2:k2,
source:1
}
return data;
}
}).on("filebatchselected", function(event, files) {
element.fileinput('upload');
}).on('fileuploaded', function(event, data, previewId, index) {
let response = data.response
arr.push(response.data.shift())
$("#$name").val(JSON.stringify(arr))
});
</script>
EOF;
}
}
\ No newline at end of file
<?php
namespace App\Presenters;
class MultiSelectorByClassPresenter
{
public function render($name, $text, $value = null, $data = [], $option = [])
{
$data = $data ?: [['name' => '启用', 'value' => 1], ['name' => '禁用', 'value' => -1]];
$isRequired = array_get($option, 'required', false);
$requiredHtml = $isRequired ? '<span style="color: red">*</span>' : "";
$elemId = $name . "Selector";
$data = json_encode($data);
$html = <<<EOF
<label class="layui-form-label">
$requiredHtml
$text</label>
<div class="layui-input-inline">
<div id="$elemId" class="layui-input-inline" value="$value" style="width: 300px;">
</div>
<input type="hidden" name="$name" id="$name" value="$value">
</div>
<script>
window.onload = function(){
layui.config({
base: '/js/web/layui/exts/xmSelect/'
}).extend({
xmSelect: 'xm-select'
}).use(['xmSelect', 'element'], function () {
let xmSelect = layui.xmSelect;
//渲染多选
let selector = xmSelect.render({
el: '.$elemId',
name: '$name',
searchTips: '请输入要查找的$text',
paging: true,
empty: '没有数据',
prop: {
name: 'name',
value: 'value'
},
data : $data,
height: "1300px",
autoRow: true,
pageSize: 10,
filterable: true,
on: function (data) {
let values = [];
for (let x in data.arr) // x 为属性名
{
values.push(data.arr[x].value);
}
$("#$name").val(values.join(','));
}
});
let values = $('#$elemId').attr('value');
selector.setValue(values.split(','));
});
}
</script>
EOF;
return $html;
}
}
\ No newline at end of file
<?php
namespace App\Presenters;
class MultiSelectorPresenter
{
public function render($name, $text, $value = null, $data = [], $option = [])
{
$data = $data ?: [['name' => '启用', 'value' => 1], ['name' => '禁用', 'value' => -1]];
$isRequired = array_get($option, 'required', false);
$requiredHtml = $isRequired ? '<span style="color: red">*</span>' : "";
$elemId = $name . "Selector";
$data = json_encode($data);
$html = <<<EOF
<label class="layui-form-label">
$requiredHtml
$text</label>
<div class="layui-input-inline">
<div id="$elemId" class="layui-input-inline" value="$value" style="width: 300px;">
</div>
<input type="hidden" name="$name" id="$name" value="$value">
</div>
<script>
window.onload = function(){
layui.config({
base: '/js/web/layui/exts/xmSelect/'
}).extend({
xmSelect: 'xm-select'
}).use(['xmSelect', 'element'], function () {
let xmSelect = layui.xmSelect;
//渲染多选
let selector = xmSelect.render({
el: '#$elemId',
name: '$name',
searchTips: '请输入要查找的$text',
paging: true,
empty: '没有数据',
prop: {
name: 'name',
value: 'value'
},
direction: 'down',
data : $data,
height: "1300px",
autoRow: true,
pageSize: 10,
filterable: true,
on: function (data) {
let values = [];
for (let x in data.arr) // x 为属性名
{
values.push(data.arr[x].value);
}
console.log(values)
$("#$name").val(values.join(','));
}
});
let values = $('#$elemId').attr('value');
selector.setValue(values.split(','));
});
}
</script>
EOF;
return $html;
}
}
\ No newline at end of file
<?php
namespace App\Presenters;
class RegionSelectorPresenter
{
public function render($name, $text, $status = null, $data = [0 => '禁用', 1 => '启用'], $option = [])
{
$isRequired = array_get($option, 'required', false);
$requiredHtml = $isRequired ? '<span style="color: red">*</span>' : "";
return <<<EOF
<label class="layui-form-label">
$requiredHtml
$text
</label>
<div class="layui-input-inline" style="width: 400px">
<input type="text" autocomplete="on" class="layui-input" id="city-picker" name="city-picker" readonly="readonly"
data-toggle="city-picker" placeholder="请选择">
</div>
<script src="/js/web/layui/exts/city-picker/city-picker.data.js"></script>
<link href="/js/web/layui/exts/city-picker/city-picker.css" rel="stylesheet" />
<script>
layui.config({
base: '/js/web/layui/exts' //静态资源所在路径
}).extend({
citypicker: 'city-picker/city-picker'
}).use(['jquery', 'index', 'table', 'citypicker'], function () {
var $ = layui.$
, table = layui.table
, form = layui.form
, cityPicker = layui.citypicker;
var currentPicker = new cityPicker("#city-picker", {
provincename:"provinceId",
cityname:"cityId",
districtname: "districtId",
level: 'districtId',// 级别
});
currentPicker.setValue("河南省/信阳市/新县");
});
</script>
EOF;
}
}
\ No newline at end of file
<?php
namespace App\Presenters;
class StatusPresenter
{
public function render($name, $text, $status = null, $data = [0 => '禁用', 1 => '启用'], $option = [])
{
$isRequired = array_get($option, 'required', false);
$requiredHtml = $isRequired ? '<span style="color: red">*</span>' : "";
$html = <<<EOF
<label class="layui-form-label">
$requiredHtml
$text
</label>
<div class="layui-input-inline">
<select name="$name" id="$name" lay-filter="$name" lay-search="">
{$this->optionsRender($data, $status)}
</select>
</div>
EOF;
return $html;
}
public function optionsRender($data, $status)
{
$optionsHtml = ' <option value="">请选择</option>';
$checked = '';
foreach ($data as $key => $value) {
if ($status !== null) {
$checked = ($key == $status) ? "selected='selected'" : '';
}
$optionsHtml = $optionsHtml . "<option value='$key' $checked>$value</option>";
}
return $optionsHtml;
}
}
\ No newline at end of file
<?php
namespace App\Presenters;
class TimeIntervalPresenter
{
public function render($name, $text)
{
$time = request()->get($name);
$html = <<<EOF
<label class="layui-form-label">$text</label>
<div class="layui-input-inline" style="min-width: 300px">
<input type="text" name="{$name}" placeholder="请选择时间区间" autocomplete="off" class="layui-input">
</div>
<script>
window.onload = function(){
layui.use('laydate', function(){
let laydate = layui.laydate;
laydate.render({
elem: 'input[name=$name]'
,type: 'datetime'
,trigger:'click'
,range: '~' //或 range: '~' 来自定义分割字符
,value: '$time'
});
});
}
</script>
EOF;
return $html;
}
}
\ No newline at end of file
...@@ -5,10 +5,11 @@ ...@@ -5,10 +5,11 @@
"license": "MIT", "license": "MIT",
"type": "project", "type": "project",
"require": { "require": {
"php": ">=5.5.9", "php": ">=5.6",
"laravel/framework": "5.2.*", "laravel/framework": "5.2.*",
"ext-json": "*", "ext-json": "*",
"ext-curl": "*" "ext-curl": "*",
"predis/predis": "^1.1"
}, },
"require-dev": { "require-dev": {
"fzaninotto/faker": "~1.4", "fzaninotto/faker": "~1.4",
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "8b1485987e7c5949da82435d403e52e8", "content-hash": "0f1afe014feaa70879e650091e283d00",
"packages": [ "packages": [
{ {
"name": "classpreloader/classpreloader", "name": "classpreloader/classpreloader",
...@@ -934,6 +934,68 @@ ...@@ -934,6 +934,68 @@
"time": "2018-04-04T21:48:54+00:00" "time": "2018-04-04T21:48:54+00:00"
}, },
{ {
"name": "predis/predis",
"version": "v1.1.7",
"source": {
"type": "git",
"url": "https://github.com/predis/predis.git",
"reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/predis/predis/zipball/b240daa106d4e02f0c5b7079b41e31ddf66fddf8",
"reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3.9"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"suggest": {
"ext-curl": "Allows access to Webdis when paired with phpiredis",
"ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol"
},
"type": "library",
"autoload": {
"psr-4": {
"Predis\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniele Alessandri",
"email": "suppakilla@gmail.com",
"homepage": "http://clorophilla.net",
"role": "Creator & Maintainer"
},
{
"name": "Till Krüss",
"homepage": "https://till.im",
"role": "Maintainer"
}
],
"description": "Flexible and feature-complete Redis client for PHP and HHVM",
"homepage": "http://github.com/predis/predis",
"keywords": [
"nosql",
"predis",
"redis"
],
"time": "2021-04-04T19:34:46+00:00"
},
{
"name": "psr/log", "name": "psr/log",
"version": "1.1.3", "version": "1.1.3",
"source": { "source": {
...@@ -3667,7 +3729,9 @@ ...@@ -3667,7 +3729,9 @@
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": ">=5.5.9" "php": ">=5.5.9",
"ext-json": "*",
"ext-curl": "*"
}, },
"platform-dev": [] "platform-dev": []
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| PDO Fetch Style | PDO Fetch Style
...@@ -13,7 +14,7 @@ return [ ...@@ -13,7 +14,7 @@ return [
| |
*/ */
'fetch' => PDO::FETCH_CLASS, 'fetch' => PDO::FETCH_ASSOC,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
...@@ -60,12 +61,26 @@ return [ ...@@ -60,12 +61,26 @@ return [
'username' => env('DB_USERNAME', 'forge'), 'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''), 'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8', 'charset' => 'utf8',
'collation' => 'utf8_unicode_ci', 'collation' => 'utf8_general_ci',
'prefix' => '', 'prefix' => '',
'strict' => false, 'strict' => false,
'engine' => null, 'engine' => null,
], ],
'sys'=>[
'driver' => 'mysql',
'host' => env('ZT_DB_HOST', 'localhost'),
'port' => env('ZT_DB_PORT', '3306'),
'database' => env('ZT_DB_DATABASE', 'forge'),
'username' => env('ZT_DB_USERNAME', 'forge'),
'password' => env('ZT_DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => 'lie_',
'strict' => false,
'engine' => null,
],
'pgsql' => [ 'pgsql' => [
'driver' => 'pgsql', 'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'), 'host' => env('DB_HOST', 'localhost'),
...@@ -78,6 +93,107 @@ return [ ...@@ -78,6 +93,107 @@ return [
'schema' => 'public', 'schema' => 'public',
], ],
'web' => [
'driver' => 'mysql',
'host' => env('WEB_DB_HOST', 'localhost'),
'port' => env('WEB_DB_PORT', '3306'),
'database' => env('WEB_DB_DATABASE', 'forge'),
'username' => env('WEB_DB_USERNAME', 'forge'),
'password' => env('WEB_DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => 'lie_',
'strict' => false,
'engine' => null,
],
'order' => [
'driver' => 'mysql',
'host' => env('ORDER_DB_HOST', 'localhost'),
'port' => env('ORDER_DB_PORT', '3306'),
'database' => env('ORDER_DB_DATABASE', 'forge'),
'username' => env('ORDER_DB_USERNAME', 'forge'),
'password' => env('ORDER_DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => 'lie_',
'strict' => false,
'engine' => null,
],
'wms' => [
'driver' => 'mysql',
'host' => env('WMS_DB_HOST', 'localhost'),
'port' => env('WMS_DB_PORT', '3306'),
'database' => env('WMS_DB_DATABASE', 'forge'),
'username' => env('WMS_DB_USERNAME', 'forge'),
'password' => env('WMS_DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => 'lie_',
'strict' => false,
'engine' => null,
],
'self'=>[
'driver' => 'mysql',
'host' => env('DB_SELF_HOST', ''),
'database' => env('DB_SELF_DATABASE', ''),
'username' => env('DB_SELF_USERNAME', ''),
'password' => env('DB_SELF_PASSWORD', ''),
'port' => env('DB_SELF_PORT', 3306),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => 'lie_',
'strict' => false,
],
'sku'=>[
'driver' => 'mysql',
'host' => env('DB_SKU_HOST', ''),
'database' => env('DB_SKU_DATABASE', ''),
'username' => env('DB_SKU_USERNAME', ''),
'password' => env('DB_SKU_PASSWORD', ''),
'port' => env('DB_SKU_PORT', 3306),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => 'lie_',
'strict' => false,
],
'spu'=>[
'driver' => 'mysql',
'host' => env('DB_SPU_HOST', ''),
'database' => env('DB_SPU_DATABASE', ''),
'username' => env('DB_SPU_USERNAME', ''),
'password' => env('DB_SPU_PASSWORD', ''),
'port' => env('DB_SPU_PORT', 3306),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => 'lie_',
'strict' => false,
],
'yunxin'=>[
'driver' => 'mysql',
'host' => env('DB_HOST_YUNXIN', ''),
'database' => env('DB_DATABASE_YUNXIN', ''),
'username' => env('DB_USERNAME_YUNXIN', ''),
'password' => env('DB_PASSWORD_YUNXIN', ''),
'port' => env('DB_YUNXIN_PORT', 3306),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => 'lie_',
'strict' => false,
],
'rabbitmq' => [
'driver' => 'rabbitmq',
'host' => env('RABBITMQ_HOST', '127.0.0.1'),
'port' => env('RABBITMQ_PORT', 5672),
'vhost' => env('RABBITMQ_VHOST', '/'),
'login' => env('RABBITMQ_LOGIN', 'guest'),
'password' => env('RABBITMQ_PASSWORD', 'guest'),
'queue' => env('RABBITMQ_QUEUE'), // name of the default queue,
],
], ],
/* /*
...@@ -105,16 +221,15 @@ return [ ...@@ -105,16 +221,15 @@ return [
*/ */
'redis' => [ 'redis' => [
'cluster' => false, 'cluster' => false,
// 'options'=>['cluster'=>'redis'],
'default' => [ 'default' => [
'host' => env('REDIS_HOST', 'localhost'), 'host' => env('REDIS_HOST',''),
'password' => env('REDIS_PASSWORD', null), 'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379), 'port' => env('REDIS_PORT', 6379),
'database' => 0, 'database' => 0,
'read_write_timeout' => 0,//new
], ],
'read' =>[ 'read' =>[
'host' => env('REDIS_READ_HOST', ''), 'host' => env('REDIS_READ_HOST', ''),
'password' => env('REDIS_READ_PASSWORD', null), 'password' => env('REDIS_READ_PASSWORD', null),
...@@ -122,7 +237,6 @@ return [ ...@@ -122,7 +237,6 @@ return [
'database' => 0, 'database' => 0,
'read_write_timeout' => 0,//new 'read_write_timeout' => 0,//new
] ]
], ],
]; ];
<?php
return [
//网页不用验证授权方法
'NotAuth' => [
'ChoiceSupplierList',
'HoldItems',
'ObtainSkuList'
],
//api不用授权方法
'ApiNotAuth' => [
'ApiSpecialList',
'ApiSpeciaModulelList',
'ApiModuleConfigList',
'ApiLogList',
'ApiInitSupplier',
'ApiChoiceSupplier'
],
'MenuSign' => '/web/',//菜单去除掉标记,生成菜单时用
'UploadKey' => 'fh6y5t4rr351d2c3bryi',//上传加密
'MD5KEY' => 'LX@ichunt.com82560956-0755',//接口加密密钥
'WMSKEY' => 'j9q##VRhaXBEtznIEeDiR@1Hvy0sW3wp',//WMS加密密钥
//1代理商,2贸易商,3财务供应商,4原厂,5代工厂,6黑名单
'SupplierGroup' => [
0 => '其它',
1 => '代理商',
2 => '贸易商',
3 => '方案商IDH/IDM',
4 => '原厂',
5 => '分销商/平台',
6 => 'FEMS/OEM/ODM',
],
//供应商编码规则映射表,用于根据供应商类型生成编码
//比如 : 原厂=>M+7位数 代理=>D+7位数
'SupplierSnMap' => [
1 => 'D',
2 => 'MY',
3 => 'F',
4 => 'M',
5 => 'FP',
6 => 'FOO',
7 => 'O',
],
'Region' => [
//1欧美,2国内,3日韩,4港台,5其它
1 => '欧美',
2 => '国内',
3 => '日韩',
4 => '港台',
5 => '其它',
],
//1 是否接口对接
'OutsideContactStatus' => [
1 => '否',
2 => '是',
],
//1 接口对接方式
'OutsideContactType' => [
1 => 'API',
//2 => 'FTP',
3 => '云芯',
],
'SupplierStockupType' => [
1 => '猎芯联营',
// 1 => '猎芯自采',
// 2 => '商家寄售',
// 3 => '猎芯自采+商家寄售'
],
'StockupType' => [
1 => '联营',
2 => '自营',
3 => '代购',
4 => '寄售',
5 => '云芯',
],
'UploadLogType' => [
'建立任务',
'处理中',
'处理成功',
'处理失败',
],
'SupplierCode' => [
1 => 'ZC',
2 => 'JS',
3 => 'ZJ'
],
'SupplierPayType' => [
1 => '账期-周期结算',
2 => '账期-定期结算',
3 => '全款',
4 => '定金'
],
'SupplierApiType' => [
1 => 'API',
2 => 'FTP',
3 => '云芯',
],
'SupplierPayTypeAB' => [
1 => ['MonthLy ', 'th,st,nd,rd'],
2 => ['NET ', ' Days'],
3 => 'T/T in advanced',
4 => ['DEposti ', '%']
],
'SupplierStatus' => [
-3 => '已拉黑',
-2 => '禁用',
-1 => '草稿',
1 => '待审核',
2 => '启用',
3 => '驳回'
],
'Currency' => [
1 => '人民币CNY(含税13%)',
2 => '美金USD',
3 => '港元HKD',
4 => '欧元EUR',
5 => '英镑GBP',
6 => '瑞士法郎CHF'
],
'WmsCurrency' => [
1 => 'CNY',
2 => 'USD',
3 => 'HKD',
4 => 'EUR',
5 => 'GBP',
6 => 'CHF'
],
'HLCurrency' => [
1 => '人民币',
2 => '美元',
3 => '港币',
4 => '欧元',
5 => '英镑',
6 => '瑞士法郎'
],
'CurrencySyb' => [
1 => '¥',
2 => '$',
3 => 'HK$',
4 => '€',
5 => '£',
6 => 'CHF'
],
'ReceiptType' => [
1 => '大陆',
2 => '港澳台和国外'
],
'PurchaseStatus' => [
-10 => '作废',
-2 => '创建中',
-1 => '草稿',
1 => '待审核',
4 => '待收货',
6 => '部分收货',
10 => '完全收货',
11 => '强制完成',
],
'PurchaseAuthStatus' => [
-1 => '草稿',
1 => '待审核',
],
'DeliveryUnit' => [
1 => '天',
2 => '工作日',
3 => '周',
4 => '月'
],
'DeliveryUnitAB' => [
1 => ' days',
2 => ' Working days',
3 => ' weeks',
4 => ' months'
],
'clause' => [
0 => 'EXW',
1 => 'FCA',
2 => 'CPT',
3 => 'CIP',
4 => 'DAT',
5 => 'DAP',
6 => 'DDP',
7 => 'FAS',
8 => 'FOB',
9 => 'CFR',
10 => 'CIF'
],
'ExcelSet' => [
'values' => [
'A' => [
[24, 'picking_info', 'address'],
[25, 'Requirement'],
[5, 'picking_sn']
],
'B' => [
[8, 'UserInfo', 'name'],
[9, 'picking_info', 'tel'],
[10, 'picking_info', 'fax']
],
'G' => [
[7, 'supplier_name'],
[8, 'supplier_info', 'channel', 'supplier_consignee'],
[9, 'supplier_info', 'channel', 'supplier_mobile'],
[10, 'supplier_info', 'channel', 'supplier_fax'],
[11, 'supplier_info', 'channel', 'supplier_address']
],
'C' => [
[16, 'picking_amount'],
[17, 'picking_amount_s']
],
],
'abvales' => [
'B' => [
[5, 'data'],
[8, 'UserInfo', 'email'],
[10, 'supplier_name'],
[11, 'supplier_info', 'channel', 'supplier_mobile'],
[12, 'supplier_info', 'channel', 'supplier_fax'],
[13, 'supplier_info', 'channel', 'supplier_email'],
[14, 'supplier_info', 'channel', 'supplier_consignee']
],
'H' => [
[5, 'picking_sn'],
[6, 'picking_info', 'clause'],
[8, 'Requirement']
],
'J' => [
[17, 'picking_amount']
]
]
],
'ProductStatus' => [
'1' => '上架',
'3' => '下架',
'0' => '待入库',
],
//v3订单状态
'ORDER_STATUS' => [
'-1' => '已取消',
'-2' => '审核不通过',
'1' => '待审核',
'2' => '待付款',
'3' => '待付尾款',
'4' => '待发货',
'7' => '部分发货',
'8' => '待收货',
'10' => '交易成功',
],
// 订单类型
'ORDER_TYPE' => [
'1' => '平台',
'2' => 'ERP',
// '3' => '京东',
],
'SEARCH_TYPE' => [
'1' => '会员账号',
'2' => '订单编号',
'3' => '型号名称',
],
//订单付款方式
'ORDER_PAY_TYPE_NAME' => [
'1' => '全款订单',
'2' => '预付订单',
'3' => '账期订单',
],
'SafeStockStatus' => [
'1' => '库存数量<安全库存',
'2' => '安全库存=库存数量',
'3' => '安全库存=0',
],
'SUPPLIER_REDIS_PRE' => 'supp_extend_fee',
'SUPPLIER_INFO_REDIS_PRE' => 'supp_info_',
'SUPPLIER_ID' => '17', // 供应商id
'SUPPLIER_RATION' => 'supp_ratio',
'SupplierLogType' => [
1 => '异常',
2 => '利好',
3 => '其它'
],
'LogType' => [
1 => '审核操作',
2 => '财务维护',
],
];
...@@ -5,21 +5,31 @@ return [ ...@@ -5,21 +5,31 @@ return [
'login' => [ 'login' => [
'login' => 'http://' . env('LOGIN_DOMAIN', '') . '/login', 'login' => 'http://' . env('LOGIN_DOMAIN', '') . '/login',
'logout'=> 'http://' . env('LOGIN_DOMAIN', '') . '/logout', 'logout' => 'http://' . env('LOGIN_DOMAIN', '') . '/logout',
'check' => 'http://' . env('LOGIN_DOMAIN', '') . '/api/checklogin', 'check' => 'http://' . env('LOGIN_DOMAIN', '') . '/api/checklogin',
'search'=> 'http://' . env('LOGIN_DOMAIN', '') . '/api/search', 'search' => 'http://' . env('LOGIN_DOMAIN', '') . '/api/search',
'dingtalk_check' => 'http://' . env('LOGIN_DOMAIN', '') . '/dingtalk/me' 'dingtalk_check' => 'http://' . env('LOGIN_DOMAIN', '') . '/dingtalk/me'
], ],
'data' => env('DATA_DOMAIN', 'scm.liexin.net'), 'data' => env('DATA_DOMAIN', 'scm.liexin.net'),
"domain" => env('DOMAIN'), "domain" => env('DOMAIN'),
'webTitle' => env('WEB_NAME','供应商系统'), 'webTitle' => env('WEB_NAME', '供应商系统'),
'UploadUrl'=> env('API_DOMAIN').'/oss/upload', 'UploadUrl' => env('API_DOMAIN') . '/oss/upload',
'UploadKey'=>'fh6y5t4rr351d2c3bryi', 'UploadKey' => 'fh6y5t4rr351d2c3bryi',
'WarningRobot'=>'https://oapi.dingtalk.com/robot/send?access_token=7ff88e1ee208e3a637c17bc51c1c879bccbf101fef5885d22ad70d21ea2f966a', 'WarningRobot' => 'https://oapi.dingtalk.com/robot/send?access_token=7ff88e1ee208e3a637c17bc51c1c879bccbf101fef5885d22ad70d21ea2f966a',
'CSWarningRobot'=>'https://oapi.dingtalk.com/robot/send?access_token=92917a6e090a8a39832c4843a579d6c6f9dfecc46fa275f8753ddee2b4399045', 'CSWarningRobot' => 'https://oapi.dingtalk.com/robot/send?access_token=92917a6e090a8a39832c4843a579d6c6f9dfecc46fa275f8753ddee2b4399045',
//根据路由选择调用外链的不同路径
'AbsoluteUrls' => [
'skulist' => 'http://footstone.liexin.net/footstone/skulist?',
'addsku' => 'http://footstone.liexin.net/footstone/addsku?',
'uploadskulist' => 'http://footstone.liexin.net/footstone/uploadskulist',
'batch' => 'http://footstone.liexin.net/footstone/Batches?', // 批量下架
'exportMonopoly' => 'http://footstone.liexin.net/footstone/exportMonopoly?', // 专卖商品批量导出
'templet' => 'http://footstone.liexin.com/footstone/templet?', // 专卖商品批量导出
],
]; ];
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("echarts")):"function"==typeof define&&define.amd?define(["exports","echarts"],t):t((e=e||self).bmap={},e.echarts)}(this,function(e,d){"use strict";function l(e,t){this._bmap=e,this.dimensions=["lng","lat"],this._mapOffset=[0,0],this._api=t,this._projection=new BMap.MercatorProjection}function t(a,r){return r=r||[0,0],d.util.map([0,1],function(e){var t=r[e],o=a[e]/2,n=[],i=[];return n[e]=t-o,i[e]=t+o,n[1-e]=i[1-e]=r[1-e],Math.abs(this.dataToPoint(n)[e]-this.dataToPoint(i)[e])},this)}var c;function f(e){for(var t in e)if(e.hasOwnProperty(t))return;return 1}l.prototype.dimensions=["lng","lat"],l.prototype.setZoom=function(e){this._zoom=e},l.prototype.setCenter=function(e){this._center=this._projection.lngLatToPoint(new BMap.Point(e[0],e[1]))},l.prototype.setMapOffset=function(e){this._mapOffset=e},l.prototype.getBMap=function(){return this._bmap},l.prototype.dataToPoint=function(e){var t=new BMap.Point(e[0],e[1]),e=this._bmap.pointToOverlayPixel(t),t=this._mapOffset;return[e.x-t[0],e.y-t[1]]},l.prototype.pointToData=function(e){var t=this._mapOffset;return[(e=this._bmap.overlayPixelToPoint({x:e[0]+t[0],y:e[1]+t[1]})).lng,e.lat]},l.prototype.getViewRect=function(){var e=this._api;return new d.graphic.BoundingRect(0,0,e.getWidth(),e.getHeight())},l.prototype.getRoamTransform=function(){return d.matrix.create()},l.prototype.prepareCustoms=function(){var e=this.getViewRect();return{coordSys:{type:"bmap",x:e.x,y:e.y,width:e.width,height:e.height},api:{coord:d.util.bind(this.dataToPoint,this),size:d.util.bind(t,this)}}},l.dimensions=l.prototype.dimensions,l.create=function(e,p){var s,m=p.getDom();e.eachComponent("bmap",function(e){var t,o=p.getZr().painter,n=o.getViewportRoot();if("undefined"==typeof BMap)throw new Error("BMap api is not loaded");function i(e){this._root=e}if(c=c||((i.prototype=new BMap.Overlay).initialize=function(e){return e.getPanes().labelPane.appendChild(this._root),this._root},i.prototype.draw=function(){},i),s)throw new Error("Only one bmap component can exist");e.__bmap||((a=m.querySelector(".ec-extension-bmap"))&&(n.style.left="0px",n.style.top="0px",m.removeChild(a)),(a=document.createElement("div")).className="ec-extension-bmap",a.style.cssText="position:absolute;width:100%;height:100%",m.appendChild(a),(r=e.get("mapOptions"))&&delete(r=d.util.clone(r)).mapType,t=e.__bmap=new BMap.Map(a,r),a=new c(n),t.addOverlay(a),o.getViewportRootOffset=function(){return{offsetLeft:0,offsetTop:0}}),t=e.__bmap;var a,r=e.get("center"),n=e.get("zoom");r&&n&&(a=t.getCenter(),o=t.getZoom(),e.centerOrZoomChanged([a.lng,a.lat],o)&&(o=new BMap.Point(r[0],r[1]),t.centerAndZoom(o,n))),(s=new l(t,p)).setMapOffset(e.__mapOffset||[0,0]),s.setZoom(n),s.setCenter(r),e.coordinateSystem=s}),e.eachSeries(function(e){"bmap"===e.get("coordinateSystem")&&(e.coordinateSystem=s)})},d.extendComponentModel({type:"bmap",getBMap:function(){return this.__bmap},setCenterAndZoom:function(e,t){this.option.center=e,this.option.zoom=t},centerOrZoomChanged:function(e,t){var o,n=this.option;return o=e,e=n.center,!(o&&e&&o[0]===e[0]&&o[1]===e[1]&&t===n.zoom)},defaultOption:{center:[104.114129,37.550339],zoom:5,mapStyle:{},mapStyleV2:{},mapOptions:{},roam:!1}}),d.extendComponentView({type:"bmap",render:function(r,e,p){var s=!0,t=r.getBMap(),m=p.getZr().painter.getViewportRoot(),l=r.coordinateSystem,o=function(e,t){var o,n,i,a;s||(a=m.parentNode.parentNode.parentNode,o=[-parseInt(a.style.left,10)||0,-parseInt(a.style.top,10)||0],n=m.style,i=o[0]+"px",a=o[1]+"px",n.left!==i&&(n.left=i),n.top!==a&&(n.top=a),l.setMapOffset(o),r.__mapOffset=o,p.dispatchAction({type:"bmapRoam",animation:{duration:0}}))};function n(){s||p.dispatchAction({type:"bmapRoam",animation:{duration:0}})}t.removeEventListener("moving",this._oldMoveHandler),t.removeEventListener("moveend",this._oldMoveHandler),t.removeEventListener("zoomend",this._oldZoomEndHandler),t.addEventListener("moving",o),t.addEventListener("moveend",o),t.addEventListener("zoomend",n),this._oldMoveHandler=o,this._oldZoomEndHandler=n;var i=r.get("roam");i&&"scale"!==i?t.enableDragging():t.disableDragging(),i&&"move"!==i?(t.enableScrollWheelZoom(),t.enableDoubleClickZoom(),t.enablePinchToZoom()):(t.disableScrollWheelZoom(),t.disableDoubleClickZoom(),t.disablePinchToZoom());var a=r.__mapStyle,o=r.get("mapStyle")||{},i=JSON.stringify(o);JSON.stringify(a)!==i&&(f(o)||t.setMapStyle(d.util.clone(o)),r.__mapStyle=JSON.parse(i));a=r.__mapStyle2,o=r.get("mapStyleV2")||{},i=JSON.stringify(o);JSON.stringify(a)!==i&&(f(o)||t.setMapStyleV2(d.util.clone(o)),r.__mapStyle2=JSON.parse(i)),s=!1}}),d.registerCoordinateSystem("bmap",l),d.registerAction({type:"bmapRoam",event:"bmapRoam",update:"updateLayout"},function(e,t){t.eachComponent("bmap",function(e){var t=e.getBMap(),o=t.getCenter();e.setCenterAndZoom([o.lng,o.lat],t.getZoom())})});e.version="1.0.0",Object.defineProperty(e,"__esModule",{value:!0})});
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("echarts")):"function"==typeof define&&define.amd?define(["exports","echarts"],t):t((e=e||self).dataTool={},e.echarts)}(this,function(e,t){"use strict";var r=Array.prototype,i=r.slice,l=r.map,o=function(){}.constructor,r=o?o.prototype:null;function a(e,t,r){if(!e)return[];if(!t)return function(e){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];return i.apply(e,t)}(e);if(e.map&&e.map===l)return e.map(t,r);for(var o=[],n=0,a=e.length;n<a;n++)o.push(t.call(r,e[n],n,e));return o}r&&"function"==typeof r.bind&&r.call.bind(r.bind);function p(e,t){return e.getAttribute(t)}function c(e,t){for(var r=e.firstChild;r;){if(1===r.nodeType&&r.nodeName.toLowerCase()===t.toLowerCase())return r;r=r.nextSibling}return null}function d(e,t){for(var r=e.firstChild,o=[];r;)r.nodeName.toLowerCase()===t.toLowerCase()&&o.push(r),r=r.nextSibling;return o}o=Object.freeze({__proto__:null,parse:function(e){if(!(t="string"==typeof e?(new DOMParser).parseFromString(e,"text/xml"):e)||t.getElementsByTagName("parsererror").length)return null;if(!(e=c(t,"gexf")))return null;for(var f,t=c(e,"graph"),r=(e=c(t,"attributes"))?a(d(e,"attribute"),function(e){return{id:p(e,"id"),title:p(e,"title"),type:p(e,"type")}}):[],o={},n=0;n<r.length;n++)o[r[n].id]=r[n];return{nodes:(e=c(t,"nodes"),f=o,e?a(d(e,"node"),function(e){var t={id:p(e,"id"),name:p(e,"label"),itemStyle:{normal:{}}},r=c(e,"viz:size"),o=c(e,"viz:position"),n=c(e,"viz:color"),e=c(e,"attvalues");if(r&&(t.symbolSize=parseFloat(p(r,"value"))),o&&(t.x=parseFloat(p(o,"x")),t.y=parseFloat(p(o,"y"))),n&&(t.itemStyle.normal.color="rgb("+[0|p(n,"r"),0|p(n,"g"),0|p(n,"b")].join(",")+")"),e){var a=d(e,"attvalue");t.attributes={};for(var i=0;i<a.length;i++){var l=a[i],u=p(l,"for"),s=p(l,"value"),l=f[u];if(l){switch(l.type){case"integer":case"long":s=parseInt(s,10);break;case"float":case"double":s=parseFloat(s);break;case"boolean":s="true"===s.toLowerCase()}t.attributes[u]=s}}}return t}):[]),links:(t=c(t,"edges"))?a(d(t,"edge"),function(e){var t={id:p(e,"id"),name:p(e,"label"),source:p(e,"source"),target:p(e,"target"),lineStyle:{normal:{}}},r=t.lineStyle.normal,o=c(e,"viz:thickness"),e=c(e,"viz:color");return o&&(r.width=parseFloat(o.getAttribute("value"))),e&&(r.color="rgb("+[0|p(e,"r"),0|p(e,"g"),0|p(e,"b")].join(",")+")"),t}):[]}}});function y(e,t){var r=(e.length-1)*t+1,o=Math.floor(r),t=+e[o-1],r=r-o;return r?t+r*(e[o]-t):t}function n(e,t){for(var r=[],o=[],n=[],a=(t=t||{}).boundIQR,i="none"===a||0===a,l=0;l<e.length;l++){n.push(l+"");var u=((g=e[l].slice()).sort(function(e,t){return e-t}),g),s=y(u,.25),f=y(u,.5),p=y(u,.75),c=u[0],d=u[u.length-1],g=(null==a?1.5:a)*(p-s),v=i?c:Math.max(c,s-g),b=i?d:Math.min(d,p+g);r.push([v,s,f,p,b]);for(var h=0;h<u.length;h++){var m=u[h];(m<v||b<m)&&(m=[l,m],"vertical"===t.layout&&m.reverse(),o.push(m))}}return{boxData:r,outliers:o,axisData:n}}r="1.0.0";t.dataTool&&(t.dataTool.version=r,t.dataTool.gexf=o,t.dataTool.prepareBoxplotData=n),e.gexf=o,e.prepareBoxplotData=n,e.version=r,Object.defineProperty(e,"__esModule",{value:!0})});
\ No newline at end of file
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{$WebInfo['title'] or '资讯管理系统'}} | Error</title> <title>{{$WebInfo['title'] or '资讯管理系统'}} | Error</title>
<link href="/css/bootstrap.min.css" rel="stylesheet"> {{-- <link href="/css/bootstrap.min.css" rel="stylesheet">--}}
<link href="/font-awesome/css/font-awesome.css" rel="stylesheet"> {{-- <link href="/font-awesome/css/font-awesome.css" rel="stylesheet">--}}
<link href="/css/animate.css" rel="stylesheet"> {{-- <link href="/css/animate.css" rel="stylesheet">--}}
<link href="/css/style.css" rel="stylesheet"> {{-- <link href="/css/style.css" rel="stylesheet">--}}
</head> </head>
<body class="gray-bg"> <body class="gray-bg">
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
<title>控制台</title> <title>控制台</title>
<link rel="stylesheet" href="/plugins/assets/libs/layui/css/layui.css"/> <link rel="stylesheet" href="/plugins/assets/libs/layui/css/layui.css"/>
<link rel="stylesheet" href="/plugins/assets/module/admin.css"/> <link rel="stylesheet" href="/plugins/assets/module/admin.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="/plugins/assets/libs/layui/layui.js"></script>
<script type="text/javascript" src="/plugins/assets/js/common.js"></script>
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
...@@ -15,8 +18,11 @@ ...@@ -15,8 +18,11 @@
<body> <body>
<!-- 正文开始 --> <!-- 正文开始 -->
<div class="layui-fluid ew-console-wrapper"> <div class="layui-fluid ew-console-wrapper">
<div class="layui-card">
<div class="layui-card-body">
@include("web.$id") @include("web.$id")
</div>
</div>
</div> </div>
<!-- 加载动画 --> <!-- 加载动画 -->
{{--<div class="page-loading">--}} {{--<div class="page-loading">--}}
...@@ -25,11 +31,9 @@ ...@@ -25,11 +31,9 @@
{{-- </div>--}} {{-- </div>--}}
{{--</div>--}} {{--</div>--}}
<!-- js部分 --> <!-- js部分 -->
<script type="text/javascript" src="/plugins/assets/libs/layui/layui.js"></script>
<script type="text/javascript" src="/plugins/assets/js/common.js"></script>
<!-- 引入同名的js,默认引入 --> <!-- 引入同名的js,默认引入 -->
@if(empty($lead_in_js) || $lead_in_js === true) @if(empty($lead_in_js) || $lead_in_js === true)
{{-- <script type="text/javascript" src="/js/{{$id}}.js?v={{random(3,true)}}"></script>--}} {{-- <script type="text/javascript" src="/js/{{$id}}.js?v={{random(3,true)}}"></script>--}}
@include('script.'.$id) @include('script.'.$id)
@endif @endif
...@@ -73,9 +73,8 @@ ...@@ -73,9 +73,8 @@
</nav> </nav>
@yield('content') @yield('content')
<!-- JavaScripts --> <!-- JavaScripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> {{-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>--}}
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
{{-- <script src="{{ elixir('js/app.js') }}"></script> --}} {{-- <script src="{{ elixir('js/app.js') }}"></script> --}}
</body> </body>
......
<script>
layui.use(['table', 'form', 'element', 'layer'], function () {
var table = layui.table;
var form = layui.form;
table.render({
elem: '#list'
, url: '/api/supplier/GetSupplierList'
, method: 'post'
, cellMinWidth: 80 //全局定义常规单元格的最小宽度
, where: {
status: 1
}
, size: 'sm'
, limit: 8
, loading: true
, first: true //不显示首页
, last: false //不显示尾页
, cols: [[
{field: 'supplier_code', title: '供应商编码', align: 'center'},
{field: 'supplier_name', title: '供应商名称', align: 'center'},
{field: 'supplier_group', title: '供应商性质', align: 'center'},
{field: 'stockup_type', title: '合作类型', align: 'center'},
{field: 'channel_username', title: '渠道开发员', align: 'center'},
{field: 'create_name', title: '创建人', align: 'center'},
{field: 'create_time', title: '创建时间', align: 'center'},
{field: 'status_name', title: '状态', align: 'center'},
{field: 'operate', title: '操作', templet: '#operate', align: 'center'},
]]
, id: 'SupplierList'
, page: false
});
form.on('submit(load)', function (data) {
form.render();
//执行重载
table.reload('SupplierList', {
page: {
curr: 1
}
, where: data.field
});
return false;
});
table.on('tool(list)', function (obj) {
let data = obj.data;
let layEvent = obj.event;
let datas = {
group_id: data.group_id,
id: data.id
};
if (layEvent === 'edit') {
window.location = '/supplier'
} else if (layEvent === 'Del') {
datas.status = 3;
up_status(datas, '删除');
}
});
function up_status(data, info) {
layer.confirm('确定' + info + '组成员吗', {
title: info + '组成员'
, btn: ['确定', '取消']
}, function () {
layer.closeAll('dialog'); // 确定时关闭弹框
let res = ajax('/api/save_group_user', data);
if (!res) {
return layer.msg('禁用失败', {icon: 6});
} else {
layer.msg(res.errmsg, {icon: 6});
$('.load').click();
}
}, function () {
layer.close();
});
}
//我的供应商----------------------------------------------------
table.render({
elem: '#own'
, url: '/api/supplier/GetSupplierList'
, method: 'post'
, cellMinWidth: 80 //全局定义常规单元格的最小宽度
, where: {
source_type: 'own'
}
, limit: 8
, loading: true
, first: true //不显示首页
, last: false //不显示尾页
, cols: [[
{field: 'supplier_code', title: '供应商编码', align: 'center', width: 120},
{field: 'supplier_name', title: '供应商名称', align: 'center'},
{field: 'supplier_group', title: '供应商性质', align: 'center', width: 120},
{field: 'stockup_type', title: '合作类型', align: 'center', width: 100},
{field: 'channel_username', title: '采购员', align: 'center', width: 130},
{field: 'create_time', title: '创建时间', align: 'center', width: 170},
{field: 'purchase_username', title: '渠道开发员', align: 'center', width: 130},
{field: 'audit_time', title: '审批时间', align: 'center', width: 170},
{
field: 'status_name', title: '状态', align: 'center', width: 80, templet: function (data) {
if (data.status_name === "驳回") {
return "<span style='color: red' title='" + data.reject_reason + "'>" + data.status_name + "</sspan>";
}
return data.status_name;
}
},
{field: 'operate', title: '操作', templet: '#operate_own', align: 'center', width: 180},
]]
, id: 'SupplierList'
, page: false
});
form.on('submit(load)', function (data) {
form.render();
//执行重载
table.reload('SupplierList', {
page: {
curr: 1
}
, where: data.field
});
return false;
});
table.on('tool(own)', function (obj) {
let data = obj.data;
let layEvent = obj.event;
if (layEvent === 'draft') {
let map = {
supplier_id: data.supplier_id,
status: -1
};
updateStatus(map, '转为草稿');
}
});
});
</script>
\ No newline at end of file
<script>
layui.use(['table', 'form', 'element', 'layer', 'Split'], function () {
let $ = layui.jquery;
let Split = layui.Split;
// 水平分割,需要分割的元素(id)、默认大小(百分比)、最小值(单位px)
Split(['#s1', '#s2', '#s3', '#s4', '#s5'], {sizes: [7, 10, 10, 10, 63], minSize: 100});
let table = layui.table;
let form = layui.form;
table.render({
elem: '#list'
, url: '/api/supplier/GetSupplierList'
, method: 'post'
, size: 'sm'
, cellMinWidth: 80 //全局定义常规单元格的最小宽度
, where: {
source_type: 'all'
}
, loading: true
, first: true //不显示首页
, last: false //不显示尾页
, cols: [[
{type: 'radio'},
{field: 'supplier_id', title: '供应商ID', align: 'center', width: 80},
{field: 'supplier_code', title: '供应商编码', align: 'center', width: 90},
{field: 'supplier_name', title: '供应商名称', align: 'center'},
{field: 'supplier_group', title: '供应商性质', align: 'center', width: 120},
{
field: 'stockup_type', title: '合作类型', align: 'center', width: 120, templet: function (data) {
return "<span title='" + data.stockup_type + "'>" + data.stockup_type + "</span>"
}
},
{
field: 'contact_num', title: '联系人', align: 'center', width: 80, templet: function (data) {
return "<a title='点击跳转查看联系人列表'>" + data.contact_num + "</a>"
}
},
{field: 'has_sku', title: 'SKU上传', align: 'center', width: 80},
{field: 'status_name', title: '状态', align: 'center',width: 80},
{field: 'channel_username', title: '采购员', align: 'center', width: 150},
{field: 'purchase_username', title: '渠道开发员', align: 'center', width: 110},
{field: 'create_name', title: '创建人', align: 'center', width: 80},
{field: 'update_time', title: '最近修改时间', align: 'center', width: 150},
{field: 'create_time', title: '创建时间', align: 'center', width: 150},
]]
, id: 'SupplierList'
, page: {}
});
form.on('submit(load)', function (data) {
form.render();
//执行重载
table.reload('SupplierList', {
page: {
curr: 1
}
, where: data.field
});
return false;
});
table.on('tool(list)', function (obj) {
let data = obj.data;
let layEvent = obj.event;
let datas = {
group_id: data.group_id,
id: data.id
};
if (layEvent === 'edit') {
window.location = '/supplier'
} else if (layEvent === 'Del') {
datas.status = 3;
up_status(datas, '删除');
}
});
form.on('submit(export)', function (data) {
data.field.source_type = 'all';
let urlWithParams = convertObjToUrlParams(data.field);
window.open('/api/supplier/export?' + urlWithParams);
return false;
});
function up_status(data, info) {
layer.confirm('确定' + info + '组成员吗', {
title: info + '组成员'
, btn: ['确定', '取消']
}, function () {
layer.closeAll('dialog'); // 确定时关闭弹框
let res = ajax('/api/save_group_user', data);
if (!res) {
return layer.msg('禁用失败', {icon: 6});
} else {
layer.msg(res.errmsg, {icon: 6});
$('.load').click();
}
}, function () {
layer.close();
});
}
});
</script>
\ No newline at end of file
<script>
console.log('index');
</script>
\ No newline at end of file
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{{config('website.webTitle')}} | {{$title or ''}}</title> <title>{{config('website.webTitle')}} | {{$title or ''}}</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<link rel="stylesheet" href="/plugins/assets/libs/layui/css/layui.css"/> <link rel="stylesheet" href="/plugins/assets/libs/layui/css/layui.css"/>
<link rel="stylesheet" href="/plugins/assets/module/admin.css?v=317"/> <link rel="stylesheet" href="/plugins/assets/module/admin.css?v=317"/>
<!--[if lt IE 9]> <!--[if lt IE 9]>
...@@ -12,6 +13,11 @@ ...@@ -12,6 +13,11 @@
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]--> <![endif]-->
</head> </head>
<style>
.layui-layout-admin .layui-body {
buttom: 1px;
}
</style>
<body class="layui-layout-body"> <body class="layui-layout-body">
<div class="layui-layout layui-layout-admin"> <div class="layui-layout layui-layout-admin">
<!-- 头部 --> <!-- 头部 -->
...@@ -38,7 +44,7 @@ ...@@ -38,7 +44,7 @@
<script type="text/javascript" src="/plugins/assets/libs/layui/layui.js"></script> <script type="text/javascript" src="/plugins/assets/libs/layui/layui.js"></script>
<script type="text/javascript" src="/plugins/assets/js/common.js?v=317"></script> <script type="text/javascript" src="/plugins/assets/js/common.js?v=317"></script>
<script> <script>
layui.use(['index','layer','admin'], function () { layui.use(['index', 'layer', 'admin'], function () {
var $ = layui.jquery; var $ = layui.jquery;
var layer = layui.layer; var layer = layui.layer;
var index = layui.index; var index = layui.index;
......
<div class="layui-row">
<div class="layui-col-md3">
<h2><b>供应商新增统计</b></h2>
</div>
<div class="layui-col-md9" style="text-align: right">
</div>
</div>
<div style="width: 100%">
<div id="main" style="width: 100%;height:400px;"></div>
</div>
<script src="/plugins/echarts/echarts.min.js"></script>
<script>
let myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
let option = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['所有新增供应商', '我的新增供应商']
},
toolbox: {
show: true,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: {readOnly: false},
magicType: {type: ['line', 'bar']},
restore: {},
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: {!! json_encode($dates) !!}
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value}'
}
},
series: [
{
name: '所有新增供应商',
type: 'line',
data: {{json_encode($all_increase_statistics)}},
markPoint: {
data: [
{type: 'max', name: '最大值'},
{type: 'min', name: '最小值'}
]
},
markLine: {
data: [
{type: 'average', name: '平均值'}
]
}
},
{
name: '我的新增供应商',
type: 'line',
data: {{json_encode($user_increase_statistics)}},
markPoint: {
data: [
{name: '周最低', value: -2, xAxis: 1, yAxis: -1.5}
]
},
markLine: {
data: [
{type: 'average', name: '平均值'},
[{
symbol: 'none',
x: '90%',
yAxis: 'max'
}, {
symbol: 'circle',
label: {
position: 'start',
formatter: '最大值'
},
type: 'max',
name: '最高点'
}]
]
}
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
\ No newline at end of file
<style>
html *
{
font-size: 12px !important;
}
.layui-input {
height: 30px;
}
.layui-input-inline {
margin-top: 5px;
}
</style>
@include('web.supplier.SupplierListCommon')
<div class="layui-btn-group demoTable" style="margin-bottom: 15px;margin-top: 15px">
<button class="layui-btn layui-btn-sm" id="add">新增</button>
<button class="layui-btn layui-btn-sm" id="disable">禁用</button>
<button class="layui-btn layui-btn-sm" id="audit">审核</button>
<button class="layui-btn layui-btn-sm" id="allocate_purchase_user">分配渠道员</button>
</div>
<table class="layui-table" id="list" lay-filter="list"></table>
<script>
</script>
<script type="text/html" id="operate">
<div style="text-align: left;">
@if($canAudit)
<a href="/supplier/AddSupplier?supplier_id=@{{ d.supplier_id}}" class="btn btn-xs btn-outline btn-success"
target="_blank">修改</a>
@else
<a href="/supplier/AddSupplier?supplier_id=@{{ d.supplier_id}}" class="btn btn-xs btn-outline btn-success"
target="_blank">查看</a>
@endif
</div>
</script>
\ No newline at end of file
<div class="layui-fluid" id="type_filter">
<div class="layui-card">
<div class="layui-card-body" style="padding: 0;">
<div class="split-group" style="height: 130px;">
<div class="split-item" id="s1">
<a href="/supplier/SupplierList?view=iframe&type=all" id="all">全部(125)</a>
</div>
<div class="split-item" id="s2" style="text-align: center">
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=pending" id="pending"> 待审核(125)</a>
</div>
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=in_review" id="in_review"> 审核中(125)</a>
</div>
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=passed" id="passed"> 已通过(125)</a>
</div>
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=rejected" id="rejected"> 未通过(125)</a>
</div>
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=disable" id="disable"> 禁止交易(125)</a>
</div>
</div>
<div class="split-item" id="s3" style="text-align: center">
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=no_purchase_uid" id="no_purchase_uid">
渠道未分配(125)</a>
</div>
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=invalid_channel_uid" id="invalid_channel_uid">
无效采购员(125)</a>
</div>
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=invalid_purchase_uid"
id="invalid_purchase_uid"> 无效渠道员(125)</a>
</div>
</div>
<div class="split-item" id="s4" style="text-align: center">
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=to_follow_up" id="to_follow_up"> 待跟进(125)</a>
</div>
<div class="layui-row">
<a href="/supplier/SupplierList?view=iframe&type=no_sku" id="no_sku"> 无sku(125)</a>
</div>
</div>
<div class="split-item" id="s5">
</div>
</div>
</div>
</div>
</div>
<div class="layui-collapse">
<!--通用的筛选-->
<form class="layui-form" style="margin-top: 15px">
<?php
$routerName = explode('/', request()->path())[1];
?>
<div class="layui-row">
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('supplier_group','供应商性质','',
config('fixed.SupplierGroup')) !!}
</div>
<div class="layui-inline">
<label class="layui-form-label">
供应商名称 :
</label>
<div class="layui-input-inline">
<input type="text" name="supplier_name" placeholder="名称模糊匹配" class="layui-input">
</div>
</div>
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('status','状态','',
[2=>'启用',3=>'驳回']) !!}
</div>
{{-- <div class="layui-inline">--}}
{{-- <label class="layui-form-label">--}}
{{-- 供应商编码 :--}}
{{-- </label>--}}
{{-- <div class="layui-input-inline">--}}
{{-- <input type="text" name="supplier_code" placeholder="多个用英文逗号分隔" class="layui-input">--}}
{{-- </div>--}}
{{-- </div>--}}
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('stockup_type','合作类型','',
config('fixed.StockupType')) !!}
</div>
</div>
<div class="layui-row">
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('channel_uid','采购员','',$userCodes) !!}
</div>
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('purchase_uid','渠道开发员','',$userCodes) !!}
</div>
@if($routerName=='SupplierBlackList')
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('blacklist_uid','操作人','',$users) !!}
</div>
@elseif($routerName!='SupplierListOwn')
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('create_uid','创建人','',$users) !!}
</div>
@endif
<div class="layui-inline">
@inject('timeIntervalPresenter','App\Presenters\TimeIntervalPresenter')
{!! $timeIntervalPresenter->render('create_time','创建时间 : ') !!}
</div>
</div>
@if($routerName=='SupplierListOwn')
<div class="layui-form-item">
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('status','状态','',
config('fixed.SupplierStatus')) !!}
</div>
</div>
@endif
@if($routerName=='SupplierListAll')
<div class="layui-form-item">
<div class="layui-inline">
@inject('statusPresenter','App\Presenters\StatusPresenter')
{!! $statusPresenter->render('status','状态','',
[2=>'启用',-2=>'禁用']) !!}
</div>
</div>
@endif
<div class="layui-row" style="margin:10px;">
<button class="layui-btn layui-btn-sm layui-btn-normal load" lay-submit="" lay-filter="load">查询</button>
<a class="layui-btn layui-btn-sm layui-btn-normal " href="">重置</a>
<button type="button" class="layui-btn layui-btn-sm layui-btn-normal hide_filter_type">隐藏罗盘</button>
<button type="button" class="layui-btn layui-btn-sm layui-btn-normal show_filter_type" style="display: none">显示罗盘</button>
@if($routerName=='SupplierListOwn')
<a href="/supplier/AddSupplier" target="_blank" class="layui-btn load">新增供应商</a>
@endif
</div>
</form>
</div>
<script>
let type = "{{request()->get('type','all')}}";
$('#' + type).attr('class', 'layui-badge layui-bg-green');
$('.hide_filter_type').click(function () {
$(this).hide();
$('#type_filter').hide();
$('.show_filter_type').show();
});
$('.show_filter_type').click(function () {
$(this).hide();
$('#type_filter').show();
$('.hide_filter_type').show();
});
</script>
This diff could not be displayed because it is too large.
...@@ -30,6 +30,7 @@ return array( ...@@ -30,6 +30,7 @@ return array(
'Psy\\' => array($vendorDir . '/psy/psysh/src/Psy'), 'Psy\\' => array($vendorDir . '/psy/psysh/src/Psy'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'), 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
'Predis\\' => array($vendorDir . '/predis/predis/src'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'), 'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
......
This diff could not be displayed because it is too large.
...@@ -297,7 +297,8 @@ ...@@ -297,7 +297,8 @@
"data", "data",
"faker", "faker",
"fixtures" "fixtures"
] ],
"abandoned": true
}, },
{ {
"name": "hamcrest/hamcrest-php", "name": "hamcrest/hamcrest-php",
...@@ -1734,7 +1735,8 @@ ...@@ -1734,7 +1735,8 @@
"homepage": "https://github.com/sebastianbergmann/php-token-stream/", "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
"keywords": [ "keywords": [
"tokenizer" "tokenizer"
] ],
"abandoned": true
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
...@@ -1882,6 +1884,70 @@ ...@@ -1882,6 +1884,70 @@
"abandoned": true "abandoned": true
}, },
{ {
"name": "predis/predis",
"version": "v1.1.7",
"version_normalized": "1.1.7.0",
"source": {
"type": "git",
"url": "https://github.com/predis/predis.git",
"reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/predis/predis/zipball/b240daa106d4e02f0c5b7079b41e31ddf66fddf8",
"reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3.9"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"suggest": {
"ext-curl": "Allows access to Webdis when paired with phpiredis",
"ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol"
},
"time": "2021-04-04T19:34:46+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Predis\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniele Alessandri",
"email": "suppakilla@gmail.com",
"homepage": "http://clorophilla.net",
"role": "Creator & Maintainer"
},
{
"name": "Till Krüss",
"homepage": "https://till.im",
"role": "Maintainer"
}
],
"description": "Flexible and feature-complete Redis client for PHP and HHVM",
"homepage": "http://github.com/predis/predis",
"keywords": [
"nosql",
"predis",
"redis"
]
},
{
"name": "psr/log", "name": "psr/log",
"version": "1.1.3", "version": "1.1.3",
"version_normalized": "1.1.3.0", "version_normalized": "1.1.3.0",
...@@ -3717,12 +3783,12 @@ ...@@ -3717,12 +3783,12 @@
"version_normalized": "1.7.0.0", "version_normalized": "1.7.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozart/assert.git", "url": "https://github.com/webmozarts/assert.git",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598" "reference": "aed98a490f9a8f78468232db345ab9cf606cf598"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", "url": "https://api.github.com/repos/webmozarts/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598", "reference": "aed98a490f9a8f78468232db345ab9cf606cf598",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
......
## Filing bug reports ##
Bugs or feature requests can be posted on the [GitHub issues](http://github.com/predis/predis/issues)
section of the project.
When reporting bugs, in addition to the obvious description of your issue you __must__ always provide
some essential information about your environment such as:
1. version of Predis (check the `VERSION` file or the `Predis\Client::VERSION` constant).
2. version of Redis (check `redis_version` returned by [`INFO`](http://redis.io/commands/info)).
3. version of PHP.
4. name and version of the operating system.
5. when possible, a small snippet of code that reproduces the issue.
__Think about it__: we do not have a crystal ball and cannot predict things or peer into the unknown
so please provide as much details as possible to help us isolating issues and fix them.
__Never__ use GitHub issues to post generic questions about Predis! When you have questions about
how Predis works or how it can be used, please just hop me an email and I will get back to you as
soon as possible.
## Contributing code ##
If you want to work on Predis, it is highly recommended that you first run the test suite in order
to check that everything is OK and report strange behaviours or bugs. When modifying Predis please
make sure that no warnings or notices are emitted by PHP running the interpreter in your development
environment with the `error_reporting` variable set to `E_ALL | E_STRICT`.
The recommended way to contribute to Predis is to fork the project on GitHub, create topic branches
on your newly created repository to fix bugs or add new features (possibly with tests covering your
modifications) and then open a pull request with a description of the applied changes. Obviously you
can use any other Git hosting provider of your preference.
We always aim for consistency in our code base so you should follow basic coding rules as defined by
[PSR-1](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)
and [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
and stick with the conventions used in Predis to name classes and interfaces. Indentation should be
done with 4 spaces and code should be wrapped at 100 columns (please try to stay within this limit
even if the above mentioned official coding guidelines set the soft limit to 120 columns).
Please follow these [commit guidelines](http://git-scm.com/book/ch5-2.html#Commit-Guidelines) when
committing your code to Git and always write a meaningful (not necessarily extended) description of
your changes before opening pull requests.
# Some frequently asked questions about Predis #
________________________________________________
### What is the point of Predis? ###
The main point of Predis is about offering a highly customizable and extensible client for Redis,
that can be easily extended by developers while still being reasonabily fast. With Predis you can
swap almost any class with your own custom implementation: you can have custom connection classes,
new distribution strategies for client-side sharding, or handlers to replace or add Redis commands.
All of this can be achieved without messing with the source code of the library and directly in your
own application. Given the fast pace at which Redis is developed and adds new features, this can be
a great asset since it allows developers to add new and still missing features or commands or change
the standard behaviour of the library without the need to break dependencies in production code (at
least to some degree).
### Does Predis support UNIX domain sockets and persistent connections? ###
Yes. Obviously persistent connections actually work only when using PHP configured as a persistent
process reused by the web server (see [PHP-FPM](http://php-fpm.org)).
### Does Predis support SSL-encrypted connections? ###
Yes. Encrypted connections are mostly useful when connecting to Redis instances exposed by various
cloud hosting providers without the need to configure an SSL proxy, but you should also take into
account the general performances degradation especially during the connect() operation when the TLS
handshake must be performed to secure the connection. Persistent SSL-encrypted connections may help
in that respect, but they are supported only when running on PHP >= 7.0.0.
### Does Predis support transparent (de)serialization of values? ###
No and it will not ever do that by default. The reason behind this decision is that serialization is
usually something that developers prefer to customize depending on their needs and can not be easily
generalized when using Redis because of the many possible access patterns for your data. This does
not mean that it is impossible to have such a feature since you can leverage the extensibility of
this library to define your own serialization-aware commands. You can find more details about how to
do that [on this issue](http://github.com/predis/predis/issues/29#issuecomment-1202624).
### How can I force Predis to connect to Redis before sending any command? ###
Explicitly connecting to Redis is usually not needed since the client initializes connections lazily
only when they are needed. Admittedly, this behavior can be inconvenient in certain scenarios when
you absolutely need to perform an upfront check to determine if the server is up and running and
eventually catch exceptions on failures. Forcing the client to open the underlying connection can be
done by invoking `Predis\Client::connect()`:
```php
$client = new Predis\Client();
try {
$client->connect();
} catch (Predis\Connection\ConnectionException $exception) {
// We could not connect to Redis! Your handling code goes here.
}
$client->info();
```
### How Predis abstracts Redis commands? ###
The approach used to implement Redis commands is quite simple: by default each command follows the
same signature as defined on the [Redis documentation](http://redis.io/commands) which makes things
pretty easy if you already know how Redis works or you need to look up how to use certain commands.
Alternatively, variadic commands can accept an array for keys or values (depending on the command)
instead of a list of arguments. Commands such as [`RPUSH`](http://redis.io/commands/rpush) and
[`HMSET`](http://redis.io/commands/hmset) are great examples:
```php
$client->rpush('my:list', 'value1', 'value2', 'value3'); // plain method arguments
$client->rpush('my:list', ['value1', 'value2', 'value3']); // single argument array
$client->hmset('my:hash', 'field1', 'value1', 'field2', 'value2'); // plain method arguments
$client->hmset('my:hash', ['field1'=>'value1', 'field2'=>'value2']); // single named array
```
An exception to this rule is [`SORT`](http://redis.io/commands/sort) for which modifiers are passed
[using a named array](tests/Predis/Command/KeySortTest.php#L54-L75).
# Speaking about performances... #
_________________________________________________
### Predis is a pure-PHP implementation: it can not be fast enough! ###
It really depends, but most of the times the answer is: _yes, it is fast enough_. I will give you a
couple of easy numbers with a simple test that uses a single client and is executed by PHP 5.5.6
against a local instance of Redis 2.8 that runs under Ubuntu 13.10 on a Intel Q6600:
```
21000 SET/sec using 12 bytes for both key and value.
21000 GET/sec while retrieving the very same values.
0.130 seconds to fetch 30000 keys using _KEYS *_.
```
How does it compare with [__phpredis__](http://github.com/nicolasff/phpredis), a nice C extension
providing an efficient client for Redis?
```
30100 SET/sec using 12 bytes for both key and value
29400 GET/sec while retrieving the very same values
0.035 seconds to fetch 30000 keys using "KEYS *"".
```
Wow __phpredis__ seems much faster! Well, we are comparing a C extension with a pure-PHP library so
lower numbers are quite expected but there is a fundamental flaw in them: is this really how you are
going to use Redis in your application? Are you really going to send thousands of commands using a
for-loop on each page request using a single client instance? If so... well I guess you are probably
doing something wrong. Also, if you need to `SET` or `GET` multiple keys you should definitely use
commands such as `MSET` and `MGET`. You can also use pipelining to get more performances when this
technique can be used.
There is one more thing: we have tested the overhead of Predis by connecting on a localhost instance
of Redis but how these numbers change when we hit the physical network by connecting to remote Redis
instances?
```
Using Predis:
3200 SET/sec using 12 bytes for both key and value
3200 GET/sec while retrieving the very same values
0.132 seconds to fetch 30000 keys using "KEYS *".
Using phpredis:
3500 SET/sec using 12 bytes for both key and value
3500 GET/sec while retrieving the very same values
0.045 seconds to fetch 30000 keys using "KEYS *".
```
There you go, you get almost the same average numbers and the reason is simple: network latency is a
real performance killer and you cannot do (almost) anything about that. As a disclaimer, remember
that we are measuring the overhead of client libraries implementations and the effects of network
round-trip times, so we are not really measuring how fast Redis is. Redis shines best with thousands
of concurrent clients doing requests! Also, actual performances should be measured according to how
your application will use Redis.
### I am convinced, but performances for multi-bulk responses are still worse ###
Fair enough, but there is an option available if you need even more speed and consists on installing
__[phpiredis](http://github.com/nrk/phpiredis)__ (note the additional _i_ in the name) and let the
client use it. __phpiredis__ is another C extension that wraps __hiredis__ (the official C client
library for Redis) with a thin layer exposing its features to PHP. You can then choose between two
different connection classes:
- `Predis\Connection\PhpiredisStreamConnection` (using native PHP streams).
- `Predis\Connection\PhpiredisSocketConnection` (requires `ext-socket`).
You will now get the benefits of a faster protocol serializer and parser just by adding a couple of
lines of code:
```php
$client = new Predis\Client('tcp://127.0.0.1', array(
'connections' => array(
'tcp' => 'Predis\Connection\PhpiredisStreamConnection',
'unix' => 'Predis\Connection\PhpiredisSocketConnection',
),
));
```
Dead simple. Nothing changes in the way you use the library in your application. So how fast is it
our basic benchmark script now? There are not much improvements for inline or short bulk responses
like the ones returned by `SET` and `GET`, but the speed for parsing multi-bulk responses is now on
par with phpredis:
```
Fatching 30000 keys with _KEYS *_ using Predis paired with phpiredis::
0.035 seconds from a local Redis instance
0.047 seconds from a remote Redis instance
```
### If I need an extension to get better performances, why not using phpredis? ###
Good question. Generically speaking if you need absolute uber-speed using Redis on the localhost and
you do not care about abstractions built around some Redis features such as MULTI / EXEC, or if you
do not need any kind of extensibility or guaranteed backwards compatibility with different versions
of Redis (Predis currently supports from 1.2 up to 2.8 and the current development version), then
using __phpredis__ makes absolutely sense. Otherwise, Predis is perfect for the job and by adding
__phpiredis__ you can get a nice speed bump almost for free.
Copyright (c) 2009-2016 Daniele Alessandri
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/src/Autoloader.php';
Predis\Autoloader::register();
#!/usr/bin/env php
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
// -------------------------------------------------------------------------- //
// This script can be used to automatically generate a file with the scheleton
// of a test case to test a Redis command by specifying the name of the class
// in the Predis\Command namespace (only classes in this namespace are valid).
// For example, to generate a test case for SET (which is represented by the
// Predis\Command\StringSet class):
//
// $ ./bin/generate-command-test --class=StringSet
//
// Here is a list of optional arguments:
//
// --realm: each command has its own realm (commands that operate on strings,
// lists, sets and such) but while this realm is usually inferred from the name
// of the specified class, sometimes it can be useful to override it with a
// custom one.
//
// --output: write the generated test case to the specified path instead of
// the default one.
//
// --overwrite: pre-existing test files are not overwritten unless this option
// is explicitly specified.
// -------------------------------------------------------------------------- //
use Predis\Command\CommandInterface;
use Predis\Command\PrefixableCommandInterface;
class CommandTestCaseGenerator
{
private $options;
public function __construct(array $options)
{
if (!isset($options['class'])) {
throw new RuntimeException("Missing 'class' option.");
}
$this->options = $options;
}
public static function fromCommandLine()
{
$parameters = array(
'c:' => 'class:',
'r::' => 'realm::',
'o::' => 'output::',
'x::' => 'overwrite::'
);
$getops = getopt(implode(array_keys($parameters)), $parameters);
$options = array(
'overwrite' => false,
'tests' => __DIR__.'/../tests/Predis',
);
foreach ($getops as $option => $value) {
switch ($option) {
case 'c':
case 'class':
$options['class'] = $value;
break;
case 'r':
case 'realm':
$options['realm'] = $value;
break;
case 'o':
case 'output':
$options['output'] = $value;
break;
case 'x':
case 'overwrite':
$options['overwrite'] = true;
break;
}
}
if (!isset($options['class'])) {
throw new RuntimeException("Missing 'class' option.");
}
$options['fqn'] = "Predis\\Command\\{$options['class']}";
$options['path'] = "Command/{$options['class']}.php";
$source = __DIR__.'/../src/'.$options['path'];
if (!file_exists($source)) {
throw new RuntimeException("Cannot find class file for {$options['fqn']} in $source.");
}
if (!isset($options['output'])) {
$options['output'] = sprintf("%s/%s", $options['tests'], str_replace('.php', 'Test.php', $options['path']));
}
return new self($options);
}
protected function getTestRealm()
{
if (isset($this->options['realm'])) {
if (!$this->options['realm']) {
throw new RuntimeException('Invalid value for realm has been sepcified (empty).');
}
return $this->options['realm'];
}
$fqnParts = explode('\\', $this->options['fqn']);
$class = array_pop($fqnParts);
list($realm,) = preg_split('/([[:upper:]][[:lower:]]+)/', $class, 2, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
return strtolower($realm);
}
public function generate()
{
$reflection = new ReflectionClass($class = $this->options['fqn']);
if (!$reflection->isInstantiable()) {
throw new RuntimeException("Class $class must be instantiable, abstract classes or interfaces are not allowed.");
}
if (!$reflection->implementsInterface('Predis\Command\CommandInterface')) {
throw new RuntimeException("Class $class must implement Predis\Command\CommandInterface.");
}
/*
* @var CommandInterface
*/
$instance = $reflection->newInstance();
$buffer = $this->getTestCaseBuffer($instance);
return $buffer;
}
public function save()
{
$options = $this->options;
if (file_exists($options['output']) && !$options['overwrite']) {
throw new RuntimeException("File {$options['output']} already exist. Specify the --overwrite option to overwrite the existing file.");
}
file_put_contents($options['output'], $this->generate());
}
protected function getTestCaseBuffer(CommandInterface $instance)
{
$id = $instance->getId();
$fqn = get_class($instance);
$fqnParts = explode('\\', $fqn);
$class = array_pop($fqnParts) . "Test";
$realm = $this->getTestRealm();
$buffer =<<<PHP
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @group commands
* @group realm-$realm
*/
class $class extends PredisCommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand()
{
return '$fqn';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId()
{
return '$id';
}
/**
* @group disconnected
*/
public function testFilterArguments()
{
\$this->markTestIncomplete('This test has not been implemented yet.');
\$arguments = array(/* add arguments */);
\$expected = array(/* add arguments */);
\$command = \$this->getCommand();
\$command->setArguments(\$arguments);
\$this->assertSame(\$expected, \$command->getArguments());
}
/**
* @group disconnected
*/
public function testParseResponse()
{
\$this->markTestIncomplete('This test has not been implemented yet.');
\$raw = null;
\$expected = null;
\$command = \$this->getCommand();
\$this->assertSame(\$expected, \$command->parseResponse(\$raw));
}
PHP;
if ($instance instanceof PrefixableCommandInterface) {
$buffer .=<<<PHP
/**
* @group disconnected
*/
public function testPrefixKeys()
{
\$this->markTestIncomplete('This test has not been implemented yet.');
\$arguments = array(/* add arguments */);
\$expected = array(/* add arguments */);
\$command = \$this->getCommandWithArgumentsArray(\$arguments);
\$command->prefixKeys('prefix:');
\$this->assertSame(\$expected, \$command->getArguments());
}
/**
* @group disconnected
*/
public function testPrefixKeysIgnoredOnEmptyArguments()
{
\$command = \$this->getCommand();
\$command->prefixKeys('prefix:');
\$this->assertSame(array(), \$command->getArguments());
}
PHP;
}
return "$buffer}\n";
}
}
// ------------------------------------------------------------------------- //
require __DIR__.'/../autoload.php';
$generator = CommandTestCaseGenerator::fromCommandLine();
$generator->save();
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 sign in to comment