Merge branch 'develop' into feature/mzl_dev_curd
This commit is contained in:
@@ -22,4 +22,57 @@ class UserController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
public function getUser(Request $request)
|
||||
{
|
||||
try {
|
||||
$uid = $request->user->uid;
|
||||
$corp_abbr = $request->basic_data['corp_abbr'];
|
||||
$result = (new UserService())->getUser($uid,$corp_abbr);
|
||||
return $this->success($result, '获取用户信息');
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑用户
|
||||
*/
|
||||
public function edit(Request $request)
|
||||
{
|
||||
try {
|
||||
$uid = $request->user->uid;
|
||||
$data = $request->all();
|
||||
$result = (new UserService())->edit($uid,$data);
|
||||
unset($result['password']);
|
||||
unset($result['union_id']);
|
||||
unset($result['open_id']);
|
||||
unset($result['tenant_key']);
|
||||
return $this->success($result, '编辑成功');
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
* @throws \Random\RandomException
|
||||
*/
|
||||
public function savePassword(Request $request)
|
||||
{
|
||||
try {
|
||||
$uid = $request->user->uid;
|
||||
$data = $request->all();
|
||||
$result = (new UserService())->savePassword($uid,$data);;
|
||||
return $this->success($result, '编辑成功');
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class PermLogic
|
||||
// component 字段规则:
|
||||
// 1. 存在子菜单,固定 '/index/index'
|
||||
// 2. 否则为当前完整路径(或其它你想要的)
|
||||
$componentValue = $hasChildrenMenu ? '/index/index' : $currentPath;
|
||||
$componentValue = ($hasChildrenMenu && !$node->url && $node->type !== 'directory') ? '/index/index' : $currentPath;
|
||||
|
||||
$tree[] = [
|
||||
'id' => $node->id,
|
||||
|
||||
@@ -24,4 +24,33 @@ class UserLogic
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
public function edit(int $uid, array $data)
|
||||
{
|
||||
$user = User::find($uid);
|
||||
|
||||
if (!$user) {
|
||||
throw new BusinessException('账户不存在', 404);
|
||||
}
|
||||
|
||||
$user->fill($data);
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*/
|
||||
public function savePassword(int $uid, array $data)
|
||||
{
|
||||
$password = password_hash($data['password_new'], PASSWORD_DEFAULT);
|
||||
$res = User::where('id',$uid)->update(['password' => $password]);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -53,6 +53,6 @@ class Role extends Model
|
||||
// 角色拥有的资源(权限点、菜单)
|
||||
public function resources()
|
||||
{
|
||||
return $this->belongsToMany(Resource::class, 'role_resources', 'role_id', 'resource_id')->orderBy('sort', 'asc');
|
||||
return $this->belongsToMany(Resource::class, 'role_resources', 'role_id', 'resource_id');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ class User extends Model
|
||||
'sn',
|
||||
'name',
|
||||
'avatar',
|
||||
'sex',
|
||||
'password',
|
||||
'phone',
|
||||
'email',
|
||||
@@ -63,7 +64,11 @@ class User extends Model
|
||||
'union_id',
|
||||
'user_id',
|
||||
'open_id',
|
||||
'tenant_key'
|
||||
'tenant_key',
|
||||
'country_id',
|
||||
'position',
|
||||
'socialize',
|
||||
'socialize_pic',
|
||||
];
|
||||
|
||||
// 用户所有角色
|
||||
|
||||
@@ -31,7 +31,7 @@ class AuthService
|
||||
|
||||
return match ($loginType) {
|
||||
'feishu' => $logic->feishuLogin($data),
|
||||
// 'qrcode' => $logic->qrCodeLogin($data),
|
||||
'qrcode' => $logic->qrCodeLogin($data),
|
||||
default => $logic->uPwdLogin($data),
|
||||
};
|
||||
}
|
||||
@@ -86,13 +86,4 @@ class AuthService
|
||||
{
|
||||
(new AuthLogic())->blockToken($token, $systemCode);
|
||||
}
|
||||
|
||||
|
||||
// public function perms()
|
||||
// {
|
||||
// $permService = new PermService();
|
||||
// $menuTree = $permService->getMenuTree($uid);
|
||||
// $permissionCodes = $permService->getPermissionCodes($uid);
|
||||
// return (new PermService())->getMenuTree($this->userId)
|
||||
// }
|
||||
}
|
||||
@@ -3,6 +3,10 @@
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\logic\UserLogic;
|
||||
use app\common\model\Corp;
|
||||
use app\common\model\User;
|
||||
use app\crm\model\Country;
|
||||
use support\exception\BusinessException;
|
||||
|
||||
class UserService
|
||||
{
|
||||
@@ -37,4 +41,62 @@ class UserService
|
||||
'permissions' => $permissionCodes
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户信息(包括菜单和权限)
|
||||
*/
|
||||
public function getUser(int $uid, $corp_abbr)
|
||||
{
|
||||
$user = $this->logic->userInfo($uid);
|
||||
$corp_name = Corp::where('abbr', $corp_abbr)->value('name');
|
||||
$ossservice = new OssService();
|
||||
return [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'position' => $user->position,
|
||||
'socialize' => $user->socialize,
|
||||
'socialize_pic' => $user->socialize_pic,
|
||||
'socialize_pic_full' => (!empty($user->socialize_pic))?$ossservice->generatePrivateUrl($user->socialize_pic):'',
|
||||
'country_id' => $user->country_id,
|
||||
'country_txt' => Country::where('id',$user->country_id)->value('cn_addr'),
|
||||
'avatar' => $user->avatar,
|
||||
'avatar_full' => (!empty($user->avatar))?$ossservice->generatePrivateUrl($user->avatar):'',
|
||||
'phone' => $user->phone,
|
||||
'corp_name' => $corp_name,
|
||||
'email' => $user->email,
|
||||
'status' => $user->status,
|
||||
'roles' => $user->roles->pluck('name')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑用户信息
|
||||
*/
|
||||
public function edit(int $uid, array $data)
|
||||
{
|
||||
unset($data['password']);
|
||||
unset($data['phone']);
|
||||
unset($data['email']);
|
||||
unset($data['sn']);
|
||||
|
||||
$user = $this->logic->edit($uid,$data);
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户密码
|
||||
*/
|
||||
public function savePassword(int $uid, array $data)
|
||||
{
|
||||
// 对密码进行哈希处理
|
||||
$password = $data['password'];
|
||||
$user = User::find($uid);
|
||||
if (!password_verify($password, $user->password)) {
|
||||
throw new BusinessException('密码错误');
|
||||
}
|
||||
|
||||
$user = $this->logic->savePassword($uid,$data);
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
@@ -64,4 +64,14 @@ class IndexController
|
||||
return json(['code' => 1, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// test function
|
||||
public function test(Request $request)
|
||||
{
|
||||
$user = User::find(1);
|
||||
$user->roles()->sync([1]);
|
||||
$user->systems()->sync([1]);
|
||||
return json(['code' => 0, 'msg' => 'success']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\controller;
|
||||
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use support\exception\BusinessException;
|
||||
use app\common\traits\ResponseTrait;
|
||||
use think\Validate;
|
||||
|
||||
abstract class BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected mixed $validator = null;
|
||||
|
||||
/**
|
||||
* 验证数据
|
||||
*
|
||||
* @param Validate $validator 验证器实例
|
||||
* @param array $data 待验证的数据
|
||||
* @param string $scene 验证场景
|
||||
* @return array 验证后的数据
|
||||
* @throws BusinessException 验证失败时抛出业务异常
|
||||
*/
|
||||
public function validate(Validate $validator, array $data, string $scene = ''): array
|
||||
{
|
||||
// 如果指定了验证场景,并且验证器支持场景方法,则设置验证场景
|
||||
if ($scene && method_exists($validator, 'scene')) {
|
||||
$validator->scene($scene);
|
||||
}
|
||||
// 执行数据验证
|
||||
if (!$validator->check($data)) {
|
||||
// 验证失败,抛出业务异常,异常信息为验证器返回的错误信息
|
||||
throw new BusinessException($validator->getError());
|
||||
}
|
||||
// 验证成功,返回原始数据
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function page($result){
|
||||
$current = $result->currentPage();
|
||||
$total = $result->total();
|
||||
$size = $result->perPage();
|
||||
$result = $result->toArray();
|
||||
$result['current'] = $current;
|
||||
$result['total'] = $total;
|
||||
$result['size'] = $size;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use app\crm\controller\BaseController;
|
||||
use app\crm\model\CarType;
|
||||
use app\crm\model\Customer;
|
||||
use app\crm\utils\Util;
|
||||
use PDO;
|
||||
use support\Db;
|
||||
use support\Redis;
|
||||
use support\Request;
|
||||
|
||||
class CarTypeController extends BaseController
|
||||
{
|
||||
|
||||
public function getAll(Request $request)
|
||||
{
|
||||
$list = CarType::getAll();
|
||||
|
||||
if($request->user['language'] != 'zh_CN'){
|
||||
foreach ($list as &$value) {
|
||||
$value['name'] = $value['name_en'];
|
||||
}
|
||||
}elseif ($request->user['language'] == 'ru'){
|
||||
foreach ($list as &$value) {
|
||||
$value['name'] = $value['name_ru'];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,527 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\controller;
|
||||
|
||||
use app\common\model\User;
|
||||
use app\crm\model\Channel;
|
||||
use app\crm\model\Country;
|
||||
use app\crm\model\Customer;
|
||||
use app\crm\model\CustomerHis;
|
||||
use app\crm\model\Follow;
|
||||
use app\crm\service\CustomerService;
|
||||
use app\crm\utils\Util;
|
||||
use config\constants\Constants;
|
||||
use support\Request;
|
||||
|
||||
class CustomerController extends BaseController
|
||||
{
|
||||
|
||||
/**
|
||||
* 不需要头信息的方法
|
||||
*/
|
||||
protected $noNeedHeader = [];
|
||||
|
||||
protected $noNeedLogin = ['getChannel', 'getCountry'];
|
||||
|
||||
/**
|
||||
* 客户分级
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function getGrade(Request $request)
|
||||
{
|
||||
$grade = [];
|
||||
$gradeConstants = Constants::GRADE_EN;
|
||||
if('zh_CN' == 'zh_CN'){
|
||||
$gradeConstants = Constants::GRADE_ZH;
|
||||
}elseif ('zh_CN' == 'ru'){
|
||||
$gradeConstants = Constants::GRADE_RU;
|
||||
}
|
||||
foreach ($gradeConstants as $key => $value) {
|
||||
$grade[] = [
|
||||
'id' => $key,
|
||||
'name' => $value,
|
||||
];
|
||||
}
|
||||
return $this->success($grade);
|
||||
}
|
||||
|
||||
/**
|
||||
* 商机
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function getMagnitude(Request $request)
|
||||
{
|
||||
$grade = [];
|
||||
$magnitudeConstants = Constants::MAGNITUDE_EN;
|
||||
if('zh_CN' == 'zh_CN'){
|
||||
$magnitudeConstants = Constants::MAGNITUDE;
|
||||
}elseif ('zh_CN' == 'ru'){
|
||||
$magnitudeConstants = Constants::MAGNITUDE_RU;
|
||||
}
|
||||
foreach ($magnitudeConstants as $key => $value) {
|
||||
$grade[] = [
|
||||
'id' => $key,
|
||||
'name' => $value,
|
||||
];
|
||||
}
|
||||
return $this->success($grade);
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户渠道
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function getChannel(Request $request)
|
||||
{
|
||||
$list = Channel::getAll();
|
||||
|
||||
if('zh_CN' != 'zh_CN'){
|
||||
foreach ($list as &$value) {
|
||||
$value['name'] = $value['name_en'];
|
||||
}
|
||||
}elseif ('zh_CN' == 'ru'){
|
||||
foreach ($list as &$value) {
|
||||
$value['name'] = $value['name_ru'];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success($list);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 国家
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function getCountry(Request $request)
|
||||
{
|
||||
$list = Country::getAll();
|
||||
|
||||
if('zh_CN' != 'zh_CN'){
|
||||
foreach ($list as &$value) {
|
||||
$value['name'] = $value['name_en'];
|
||||
}
|
||||
}elseif ('zh_CN' == 'ru'){
|
||||
foreach ($list as &$value) {
|
||||
$value['name'] = $value['name_ru'];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success($list);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 待跟进客户列表
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function waitFollow(Request $request)
|
||||
{
|
||||
$userId = $request->user->uid;
|
||||
$filter = Util::getParam($request, 'filter');
|
||||
$page = $request->input('page', 1);
|
||||
$perPage = $request->input('per_page', 10);
|
||||
$where = [
|
||||
['user_id', '=', $userId],
|
||||
['corp_abbr', '=', $request->basic_data['corp_abbr']],
|
||||
['follow_next', '<>', 0],
|
||||
];
|
||||
|
||||
if($filter == 0){
|
||||
$where[] = ['follow_next', '<=', time() + 3600 * 24];
|
||||
} elseif ($filter == 1) {
|
||||
$where[] = ['follow_next', '<=', time() + 3600 * 24 * 3];
|
||||
} elseif ($filter == 2) {
|
||||
$where[] = ['follow_next', '<=', time() + 3600 * 24 * 7];
|
||||
}
|
||||
$customer = Customer::where($where)
|
||||
->whereNotNull('follow_next')
|
||||
->orderBy('follow_next')
|
||||
->paginate($perPage, ['*'], 'page', $page);
|
||||
|
||||
foreach ($customer as &$item) {
|
||||
$item['follow_remaining'] = $item->follow_next-time();
|
||||
$item['follow_next'] = date('Y-m-d H:i:s',$item->follow_next);
|
||||
}
|
||||
return $this->success($this->page($customer));
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户列表
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
try {
|
||||
$param = $request->all();
|
||||
$param['user_id'] = $request->user->uid;
|
||||
$param['corp_abbr'] = $request->basic_data['corp_abbr'];
|
||||
$result = (new CustomerService())->list($param);
|
||||
|
||||
return $this->success($this->page($result));
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage().$e->getFile().$e->getLine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户恢复
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function restore(Request $request)
|
||||
{
|
||||
$id = Util::getParam($request,'id', '');
|
||||
if (Util::isEmpty($id)) {
|
||||
return $this->error(trans('id_empty'));
|
||||
}
|
||||
$userId = $request->user->uid;
|
||||
$where = [
|
||||
'id' => $id,
|
||||
'user_id' => $userId,
|
||||
];
|
||||
$res = Customer::where($where)->restore();
|
||||
if($res){
|
||||
return $this->success($res, trans('success'));
|
||||
}else{
|
||||
return $this->error(trans('fail'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 客户详情
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function detail(Request $request)
|
||||
{
|
||||
$id = Util::getParam($request, 'id');
|
||||
if (Util::isEmpty($id)) {
|
||||
return $this->error('id' . trans('not_null'));
|
||||
}
|
||||
|
||||
// $res = Customer::with('tags')->select('id', 'user_id', 'grade', 'channel_id', 'car_type_id', 'country_id', 'magnitude', 'email', 'phone', 'WhatsApp', 'contacts', 'describe', 'address', 'lat', 'lng', 'follow_next', 'follow_remark', 'sex')
|
||||
// ->where('id', $id)
|
||||
// ->first();
|
||||
$res = (new CustomerService)->detail($request->all());
|
||||
if ($res) {
|
||||
$res->toArray();
|
||||
} else {
|
||||
return $this->error('记录不存在');
|
||||
}
|
||||
|
||||
$res = CustomerService::getCustomer($res, 'zh_CN', true);
|
||||
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户录入
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
$id = Util::getParam($request, 'id');
|
||||
$channel_id = Util::getParam($request, 'channel_id');
|
||||
if (Util::isEmpty($channel_id)) {
|
||||
return $this->error(trans('channel_not_null'));
|
||||
}
|
||||
$country_id = Util::getParam($request, 'country_id', 0);
|
||||
if (Util::isEmpty($country_id)) {
|
||||
// return $this->error('country_id'.trans('not_null'));
|
||||
}
|
||||
// $car_type_id = Util::getParam($request, 'car_type_id');
|
||||
// if (Util::isEmpty($car_type_id)) {
|
||||
// return $this->error(trans('car_type_not_null'));
|
||||
// }
|
||||
$contacts = Util::getParam($request, 'contacts');
|
||||
$email = Util::getParam($request, 'email');
|
||||
$phone = Util::getParam($request, 'phone');
|
||||
if (Util::isEmpty($contacts) && Util::isEmpty($email) && Util::isEmpty($phone)) {
|
||||
return $this->error(trans('contacts_not_null'));
|
||||
}
|
||||
|
||||
$data = [
|
||||
'user_id' => $request->user->uid,
|
||||
'corp_abbr' => $request->basic_data['corp_abbr'],
|
||||
'grade' => Util::getParam($request, 'grade', 0),
|
||||
'channel_id' => $channel_id,
|
||||
'country_id' => $country_id,
|
||||
'car_type_id' => $car_type_id,
|
||||
'magnitude' => Util::getParam($request, 'magnitude', 0),
|
||||
'email' => $email,
|
||||
'phone' => $phone,
|
||||
'WhatsApp' => Util::getParam($request, 'WhatsApp', ''),
|
||||
'contacts' => $contacts,
|
||||
'describe' => Util::getParam($request, 'describe'),
|
||||
'lat' => Util::getParam($request, 'lat', 0),
|
||||
'lng' => Util::getParam($request, 'lng', 0),
|
||||
'address' => Util::getParam($request, 'address', ''),
|
||||
'sex' => Util::getParam($request, 'sex', 0),
|
||||
];
|
||||
|
||||
if (Util::isEmpty($id)) {
|
||||
$res = Customer::create($data);
|
||||
} else {
|
||||
unset($data['grade']);
|
||||
$res = Customer::where('id', $id)
|
||||
->update($data);
|
||||
// Log::info('update', ['res' => $res]);
|
||||
(!$res) ?: $res = Customer::find($id)->toArray();
|
||||
}
|
||||
|
||||
if ($res) {
|
||||
return $this->success($res, trans('save_success'));
|
||||
} else {
|
||||
return $this->error(trans('save_fail'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 更新下次跟进时间
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function followNext(Request $request)
|
||||
{
|
||||
$id = Util::getParam($request, 'id');
|
||||
if (Util::isEmpty($id)) {
|
||||
return $this->error('id' . trans('not_null'));
|
||||
}
|
||||
$data = [
|
||||
'follow_next' => Util::getParam($request, 'follow_next', 0),
|
||||
'follow_remark' => Util::getParam($request, 'follow_remark', 0),
|
||||
'warn' => 0,
|
||||
];
|
||||
|
||||
$res = Customer::where('id', $id)
|
||||
->update($data);
|
||||
|
||||
if ($res) {
|
||||
return $this->success($res, trans('save_success'));
|
||||
} else {
|
||||
return $this->error(trans('save_fail'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除客户
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function delete(Request $request)
|
||||
{
|
||||
$id = Util::getParam($request, 'id');
|
||||
$force = Util::getParam($request, 'force','');
|
||||
|
||||
$userId = $request->user->uid;
|
||||
$where = [
|
||||
'id' => $id,
|
||||
'user_id' => $userId,
|
||||
];
|
||||
$customer = Customer::where($where)->withTrashed()->first();
|
||||
if(empty($customer)){
|
||||
return $this->error( trans('fail'));
|
||||
}
|
||||
if($force == 'force'){
|
||||
$res = $customer->forceDelete();
|
||||
}else{
|
||||
$res = $customer->delete();
|
||||
}
|
||||
if ($res) {
|
||||
return $this->success($res, trans('success'));
|
||||
} else {
|
||||
return $this->error(trans('fail'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计客户
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function statistics(Request $request)
|
||||
{
|
||||
$created = Util::getParam($request, 'created');
|
||||
if (Util::isEmpty($created)) {
|
||||
return $this->error('created' . trans('not_null'));
|
||||
}
|
||||
$userId = $request->user->uid;
|
||||
//$created_at = $request->user['created_at'];
|
||||
$created_at = User::find($userId)->value('created_at');
|
||||
$created_at = strtotime($created_at);
|
||||
$day = ceil((time() - $created_at + 1) / 60 / 60 / 24);
|
||||
$where[] = ['user_id', '=', $userId];
|
||||
$where[] = ['corp_abbr', '=', $request->basic_data['corp_abbr']];
|
||||
$start = strtotime($created . '-01');
|
||||
$year = date('Y', $start);
|
||||
$month = date('n', $start); //获取月份
|
||||
$end = mktime(00, 00, 00, $month + 1, 1, $year);
|
||||
$where[] = ['created_at', '>=', $start];
|
||||
$where[] = ['created_at', '<', $end];
|
||||
$customer = Customer::where($where)->count();
|
||||
|
||||
//初步接触
|
||||
$whereGrade = $where;
|
||||
$whereGrade[] = ['grade', '<=', 2];
|
||||
$customerInit = Customer::where($whereGrade)->count();
|
||||
|
||||
//跟进中
|
||||
$customeroFllow = Customer::where($where)->whereIn('grade', [3, 4])->count();
|
||||
|
||||
//已成交
|
||||
$whereGrade = $where;
|
||||
$whereGrade[] = ['grade', '=', 5];
|
||||
$customerDeal = Customer::where($whereGrade)->count();
|
||||
|
||||
//拜访数
|
||||
$whereVisit = $where;
|
||||
$whereVisit[] = ['type', '=', 0];
|
||||
$visit = Follow::where($whereVisit)->distinct('customer_id')->count();
|
||||
|
||||
//跟进数
|
||||
$whereVisit = $where;
|
||||
$whereVisit[] = ['type', '=', 1];
|
||||
$follow = Follow::where($whereVisit)->distinct('customer_id')->count();
|
||||
|
||||
$res = [
|
||||
'customer' => $customer, //客户数
|
||||
'visit' => $visit, //拜访
|
||||
'follow' => $follow, //跟进
|
||||
'day' => $day, //注册天数
|
||||
'customer_init' => $customerInit, //初步接触
|
||||
'customero_fllow' => $customeroFllow, //跟进中
|
||||
'customer_deal' => $customerDeal, //已成交
|
||||
];
|
||||
if ($res) {
|
||||
return $this->success($res, trans('success'));
|
||||
} else {
|
||||
return $this->error(trans('fail'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取公海客户
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function claim(Request $request)
|
||||
{
|
||||
$customerId = Util::getParam($request, 'customer_id');
|
||||
$userId = $request->user->uid;
|
||||
if (Util::isEmpty($customerId)) {
|
||||
return $this->error(trans('customer_id').trans('not_null'));
|
||||
}
|
||||
$data = [
|
||||
'user_id' => $request->user->uid
|
||||
];
|
||||
$customer= Customer::withTrashed()->find($customerId);
|
||||
|
||||
if(empty($customer) || $customer->user_id != 0){
|
||||
return $this->error( trans('claim_fail'));
|
||||
}
|
||||
|
||||
$customer->restore();
|
||||
$res = $customer->update($data);
|
||||
|
||||
//记录客户关系变化
|
||||
$his = CustomerHis::create([
|
||||
'customer_id' => $customerId,
|
||||
'user_his' => 0,
|
||||
'user_id' => $userId,
|
||||
]);
|
||||
|
||||
if ($res) {
|
||||
return $this->success($res, trans('success'));
|
||||
} else {
|
||||
return $this->error(trans('fail'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 批量转让
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function cede(Request $request)
|
||||
{
|
||||
$customerId = Util::getParam($request, 'customer_id');
|
||||
$user_sn = Util::getParam($request, 'user_sn');
|
||||
$userId = $request->user->uid;
|
||||
if (Util::isEmpty($user_sn)) {
|
||||
return $this->error('ID'.trans('not_null'));
|
||||
}
|
||||
|
||||
$user = User::where(['sn' => $user_sn])->first();
|
||||
if (Util::isEmpty($user)) {
|
||||
return $this->error( trans('user_none'));
|
||||
}
|
||||
|
||||
if(Util::isEmpty($customerId)){
|
||||
$data = [
|
||||
'user_id' => $userId
|
||||
];
|
||||
$query= Customer::where($data);
|
||||
}else{
|
||||
$query= Customer::whereIn('id',explode(',',$customerId));
|
||||
}
|
||||
$customer = $query->get();
|
||||
|
||||
foreach ($customer as $item) {
|
||||
//记录客户关系变化
|
||||
$his = CustomerHis::create([
|
||||
'customer_id' => $item->id,
|
||||
'user_his' => $item->user_id,
|
||||
'user_id' => $user['id'],
|
||||
]);
|
||||
}
|
||||
$res = $query->update(['user_id' => $user->id]);
|
||||
|
||||
|
||||
if ($res) {
|
||||
return $this->success($res, trans('success'));
|
||||
} else {
|
||||
return $this->error(trans('fail'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跟进状态
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function grade(Request $request)
|
||||
{
|
||||
$id = Util::getParam($request, 'id');
|
||||
$grade = Util::getParam($request, 'grade');
|
||||
if (Util::isEmpty($id)) {
|
||||
return $this->error( 'id' . trans('not_null'));
|
||||
}
|
||||
if (Util::isEmpty($id)) {
|
||||
return $this->error( 'grade' . trans('not_null'));
|
||||
}
|
||||
$data = [
|
||||
'grade' => $grade,
|
||||
];
|
||||
$res = Customer::where('id', $id)
|
||||
->update($data);
|
||||
|
||||
if ($res) {
|
||||
return $this->success($res, trans('save_success'));
|
||||
} else {
|
||||
return $this->error(trans('save_fail'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\controller;
|
||||
|
||||
use app\crm\model\Customer;
|
||||
use app\crm\model\Follow;
|
||||
use app\crm\service\CustomerService;
|
||||
use app\crm\service\FollowService;
|
||||
use app\crm\utils\Util;
|
||||
use app\crm\validate\FollowValidate;
|
||||
use config\constants\Constants;
|
||||
use support\Request;
|
||||
|
||||
class FollowController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 客户分级
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function getFollowType(Request $request)
|
||||
{
|
||||
$grade = [];
|
||||
foreach (Constants::FOLLOW as $key => $value) {
|
||||
$grade[] = [
|
||||
'status' => $key,
|
||||
'text' => $value,
|
||||
];
|
||||
}
|
||||
return $this->success($grade);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 跟进列表
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
try {
|
||||
$data = $this->validate(new FollowValidate(), $request->get(), 'list');
|
||||
$request->setGet('corp_abbr', $request->basic_data['corp_abbr']);
|
||||
$result = (new FollowService())->list($request->all(), $request->user->uid);
|
||||
return $this->success($result);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跟进详情
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function detail(Request $request)
|
||||
{
|
||||
//跟进id
|
||||
$id = Util::getParam($request, 'id');
|
||||
if (Util::isEmpty($id)) {
|
||||
return $this->error('id' . trans('not_null'));
|
||||
}
|
||||
|
||||
$res = Follow::select('id', 'user_id', 'customer_id', 'type', 'picture', 'remark', 'audio', 'audio_text', 'lat', 'lng', 'address')
|
||||
->where('id', $id)
|
||||
->first();
|
||||
if ($res) {
|
||||
$res->toArray();
|
||||
} else {
|
||||
return $this->error('记录不存在');
|
||||
}
|
||||
|
||||
$res = FollowService::getFollow($res);
|
||||
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户录入
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
$customer_id = Util::getParam($request, 'customer_id');
|
||||
|
||||
if (Util::isEmpty($customer_id)) {
|
||||
return $this->error('customer_id' . trans('not_null'));
|
||||
}
|
||||
$type = Util::getParam($request, 'type');
|
||||
if (Util::isEmpty($type)) {
|
||||
return $this->error('type' . trans('not_null'));
|
||||
}
|
||||
$picture = Util::getParam($request, 'picture');
|
||||
if (Util::isEmpty($picture)) {
|
||||
return $this->error(trans('picture_not_null'));
|
||||
}
|
||||
|
||||
$data = [
|
||||
'user_id' => $request->user->uid,
|
||||
'corp_abbr' => $request->basic_data['corp_abbr'],
|
||||
'customer_id' => $customer_id,
|
||||
'type' => $type,
|
||||
'picture' => $picture,
|
||||
'remark' => Util::getParam($request, 'remark', ''),
|
||||
'audio' => Util::getParam($request, 'audio', ''),
|
||||
'audio_text' => Util::getParam($request, 'audio_text', ''),
|
||||
'lat' => Util::getParam($request, 'lat', 0),
|
||||
'lng' => Util::getParam($request, 'lng', 0),
|
||||
'address' => Util::getParam($request, 'address'),
|
||||
'follow_time' => strtotime(Util::getParam($request, 'firstFollowtime', 0)),
|
||||
];
|
||||
|
||||
$res = Follow::create($data);
|
||||
|
||||
$customer = Customer::find($customer_id);
|
||||
$customer->follow_last = strtotime($res->created_at);
|
||||
$customer->follow_next = null;
|
||||
$customer->warn = 0;
|
||||
$customer->save();
|
||||
|
||||
$follow_next = Util::getParam($request, 'follow_next', 0);
|
||||
$follow_remark = Util::getParam($request, 'follow_remark', 0);
|
||||
if ($res && (!empty($follow_next))) {
|
||||
$data = [
|
||||
'follow_next' => $follow_next,
|
||||
'follow_remark' => $follow_remark,
|
||||
'warn' => 0,
|
||||
];
|
||||
$res = Customer::where('id', $customer_id)
|
||||
->update($data);
|
||||
}
|
||||
|
||||
if ($res) {
|
||||
return $this->success($res, trans('save_success'));
|
||||
} else {
|
||||
return $this->error(trans('save_fail'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\controller;
|
||||
|
||||
use app\crm\controller\BaseController;
|
||||
use app\crm\model\Customer;
|
||||
use app\crm\model\CustomerTag;
|
||||
use app\crm\model\TagGroup;
|
||||
use app\crm\model\Tag;
|
||||
use app\crm\utils\Util;
|
||||
use config\constants\Constants;
|
||||
use support\Request;
|
||||
|
||||
class TagGroupController extends BaseController
|
||||
{
|
||||
|
||||
// 列表
|
||||
public function list(Request $request)
|
||||
{
|
||||
$uid = $request->user->uid;
|
||||
$scene = $request->input("scene");
|
||||
$list = TagGroup::with('tags')->get();
|
||||
$languageArr = Constants::LANGUAGE;
|
||||
$language = 'zh_CN';
|
||||
foreach ($list as &$item) {
|
||||
$item['names'] = unserialize($item['names']);
|
||||
if (in_array($language, $languageArr)) {
|
||||
$item['name'] = $item['names'][$language];
|
||||
}
|
||||
foreach ($item['tags'] as &$tag) {
|
||||
$tag['names'] = unserialize($tag['names']);
|
||||
if (in_array($language, $languageArr)) {
|
||||
$tag['name'] = $tag['names'][$language];
|
||||
}
|
||||
if($scene == 'customers'){
|
||||
// 统计每个标签关联的客户数量,增加user_id条件
|
||||
$tag['count'] = $tag->customers()->where('user_id', $uid)->count();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新客户标签关系
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function updatePivot(Request $request)
|
||||
{
|
||||
$customerId = Util::getParam($request, 'customer_id');
|
||||
$groupId = Util::getParam($request, 'group_id');
|
||||
$tagId = Util::getParam($request, 'tag_id');
|
||||
if (Util::isEmpty($customerId)) {
|
||||
return $this->error( trans('customer_id') . trans('not_null'));
|
||||
}
|
||||
if (Util::isEmpty($groupId)) {
|
||||
return $this->error( trans('tag_group_id') . trans('not_null'));
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
if(empty($tagId)){
|
||||
$res = CustomerTag::where(['customer_id' => $customerId, 'group_id' => $groupId])->delete();
|
||||
}else{
|
||||
$res = CustomerTag::updateOrCreate(['customer_id' => $customerId, 'group_id' => $groupId], ['tag_id' => $tagId]);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
|
||||
if($res){
|
||||
return $this->success($res, trans('success'));
|
||||
}else{
|
||||
return $this->error( trans('fail'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\logic;
|
||||
|
||||
use app\crm\model\Customer;
|
||||
|
||||
class CustomerLogic
|
||||
{
|
||||
|
||||
public function find(int $id)
|
||||
{
|
||||
$customer = Customer::find($id);
|
||||
return $customer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\logic;
|
||||
|
||||
class FollowLogic
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
|
||||
|
||||
use support\Model;
|
||||
class CarType extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'car_type';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
public static function getAll()
|
||||
{
|
||||
$list = self::get()->select('id','name','name_en','status')->where('status',0)->toArray();
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class Channel extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'inquiry_channel';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
//设置黑名单
|
||||
protected $guarded = ['id','created_at','updated_at'];
|
||||
|
||||
// 指定日期字段存储格式为时间戳
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
protected $casts = [
|
||||
// 'updated_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||
// 'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||
'updated_at' => 'timestamp', // 指定序列化格式
|
||||
'created_at' => 'timestamp', // 指定序列化格式
|
||||
];
|
||||
|
||||
public static function getAll()
|
||||
{
|
||||
$list = self::get()->select('id','name','name_en','status')->where('status',1)->toArray();
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class Country extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'country';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
//设置黑名单
|
||||
protected $guarded = ['id'];
|
||||
|
||||
// 指定日期字段存储格式为时间戳
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
public static function getAll()
|
||||
{
|
||||
$list = self::select('id','cn_addr','en_addr')->get();
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
|
||||
use app\crm\utils\Util;
|
||||
use config\constants\Constants;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Support\Carbon;
|
||||
use support\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use app\common\model\User;
|
||||
|
||||
class Customer extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'crm_customer';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
//设置黑名单
|
||||
protected $guarded = ['id','created_at','updated_at'];
|
||||
|
||||
// 指定日期字段存储格式为时间戳
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
use SoftDeletes;
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
protected $casts = [
|
||||
'updated_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||
'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||
];
|
||||
|
||||
/**
|
||||
* 重新格式化时间
|
||||
* @param DateTimeInterface $date
|
||||
* @return string
|
||||
*/
|
||||
protected function serializeDate(DateTimeInterface $date): string
|
||||
{
|
||||
return $date->format(Carbon::parse($date)->toDateTimeString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户的标签
|
||||
*/
|
||||
public function tags()
|
||||
{
|
||||
return $this->belongsToMany(Tag::class, 'crm_customer_tag', 'customer_id', 'tag_id')
|
||||
->withTimestamps(); // 如果需要记录关联时间
|
||||
}
|
||||
|
||||
|
||||
// 定义与 变更历史 的一对多关系
|
||||
public function his()
|
||||
{
|
||||
return $this->hasMany(CustomerHis::class, 'customer_id', 'id');
|
||||
}
|
||||
|
||||
// 定义反向多对一关联
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
|
||||
use app\crm\utils\Util;
|
||||
use config\constants\Constants;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Support\Carbon;
|
||||
use support\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class CustomerHis extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'crm_customer_his';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
//设置黑名单
|
||||
protected $guarded = ['id','created_at'];
|
||||
|
||||
// 指定日期字段存储格式为时间戳
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
protected $casts = [
|
||||
'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||
// 'created_at' => 'timestamp', // 指定序列化格式
|
||||
];
|
||||
|
||||
/**
|
||||
* 重新格式化时间
|
||||
* @param DateTimeInterface $date
|
||||
* @return string
|
||||
*/
|
||||
protected function serializeDate(DateTimeInterface $date): string
|
||||
{
|
||||
return $date->format(Carbon::parse($date)->toDateTimeString());
|
||||
}
|
||||
|
||||
// 定义反向多对一关联
|
||||
public function customer()
|
||||
{
|
||||
return $this->belongsTo(Customer::class, 'customer_id', 'id');
|
||||
}
|
||||
|
||||
// 禁用 updated_at 的自动更新
|
||||
public function setUpdatedAt($value)
|
||||
{
|
||||
return $this; // 不做任何操作
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
|
||||
use app\crm\utils\Util;
|
||||
use support\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class CustomerTag extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'crm_customer_tag';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
//设置黑名单
|
||||
protected $guarded = ['id', 'created_at'];
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
|
||||
use app\service\OssService;
|
||||
use app\crm\utils\Util;
|
||||
use config\constants\Constants;
|
||||
use support\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Follow extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'crm_follow';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
//设置黑名单
|
||||
protected $guarded = ['id','created_at','updated_at'];
|
||||
|
||||
// 指定日期字段存储格式为时间戳
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'follow_time'];
|
||||
|
||||
protected $casts = [
|
||||
'updated_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||
'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||
'follow_time' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||
// 'updated_at' => 'timestamp', // 指定序列化格式
|
||||
// 'created_at' => 'timestamp', // 指定序列化格式
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
|
||||
use app\util\Util;
|
||||
use config\constants\Constants;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Support\Carbon;
|
||||
use support\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Tag extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'crm_tag';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
//设置黑名单
|
||||
protected $guarded = ['id','created_at','updated_at'];
|
||||
|
||||
// 指定日期字段存储格式为时间戳
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
use SoftDeletes;
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
// 定义反向多对一关联
|
||||
public function group()
|
||||
{
|
||||
return $this->belongsTo(TagGroup::class, 'group_id', 'id');
|
||||
}
|
||||
|
||||
public function customers()
|
||||
{
|
||||
return $this->belongsToMany(Customer::class, 'crm_customer_tag', 'tag_id', 'customer_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\model;
|
||||
|
||||
|
||||
use app\crm\utils\Util;
|
||||
use config\constants\Constants;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Support\Carbon;
|
||||
use support\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class TagGroup extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'crm_tag_group';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
//设置黑名单
|
||||
protected $guarded = ['id','created_at','updated_at'];
|
||||
|
||||
// 指定日期字段存储格式为时间戳
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
use SoftDeletes;
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
// 定义与 Tag 的一对多关系
|
||||
public function tags()
|
||||
{
|
||||
return $this->hasMany(Tag::class, 'group_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\service;
|
||||
|
||||
use app\crm\logic\CustomerLogic;
|
||||
use app\crm\model\CarType;
|
||||
use app\crm\model\Channel;
|
||||
use app\crm\model\Country;
|
||||
use app\crm\model\Customer;
|
||||
use app\crm\model\Follow;
|
||||
use app\crm\utils\Util;
|
||||
use config\constants\Constants;
|
||||
|
||||
class CustomerService
|
||||
{
|
||||
public function list($params)
|
||||
{
|
||||
// $page = $request->input('page', 1);
|
||||
// $perPage = $request->input('per_page', 10);
|
||||
$perPage = $params['size'] ?? 10;
|
||||
$page = $params['current'] ?? 1;
|
||||
$keyword = $params['keyword'] ?? '';
|
||||
$recycle = $params['recycle'] ?? '';
|
||||
$follow = $params['follow'] ?? '';
|
||||
$follow_last = $params['follow_last'] ?? '';
|
||||
$tagId = $params['tag_id'] ?? [];
|
||||
$where = [];
|
||||
$user_id =$params['user_id'];
|
||||
if(empty($user_id) || $user_id == 0){
|
||||
$where[] = ['user_id', '=', $user_id];
|
||||
}
|
||||
|
||||
$seas = $params['seas'] ?? '';
|
||||
if($seas == 'seas'){
|
||||
$where[] = ['user_id', 0];
|
||||
}
|
||||
if($recycle == 'recycle'){
|
||||
$where[] = ['user_id', $user_id];
|
||||
}
|
||||
|
||||
|
||||
$grade = [];
|
||||
if (!Util::isEmpty($follow) && $follow == 0) {
|
||||
$where[] = ['grade', '<=', 2];
|
||||
} elseif (!Util::isEmpty($follow) && $follow == 1) {
|
||||
$grade = [3, 4];
|
||||
} elseif (!Util::isEmpty($follow) && $follow == 2) {
|
||||
$where[] = ['grade', '=', 5];
|
||||
}
|
||||
|
||||
if (!Util::isEmpty($follow_last) && $follow_last == 0) {
|
||||
$where[] = ['follow_last', '>', strtotime('-1 day')];
|
||||
} elseif (!Util::isEmpty($follow_last) && $follow_last == 1) {
|
||||
$where[] = ['follow_last', '>', strtotime('-3 day')];
|
||||
} elseif (!Util::isEmpty($follow_last) && $follow_last == 2) {
|
||||
$where[] = ['follow_last', '>', strtotime('-7 day')];
|
||||
}
|
||||
|
||||
$query = Customer::where($where);
|
||||
|
||||
if(!empty($tagId)){
|
||||
//查询有$tagId 里任意一个标签的客户
|
||||
//$query->whereHas('tags', function($query) use ($tagId){
|
||||
// $query->whereIn ('tag.id', $tagId);
|
||||
//});
|
||||
//查询有$tagId 里所有标签的客户
|
||||
foreach ($tagId as $id) {
|
||||
$query->whereHas('tags', function($query) use ($id){
|
||||
$query->where('tag.id', $id);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!Util::isEmpty($keyword)) {
|
||||
$query->where(function ($query) use ($keyword) {
|
||||
$query->where('contacts', 'like', "%{$keyword}%")
|
||||
->orWhere('phone', 'like', "%{$keyword}%");
|
||||
});
|
||||
}
|
||||
if (!Util::isEmpty($grade)) {
|
||||
$query->whereIn('grade', $grade);
|
||||
}
|
||||
|
||||
if ($recycle == 'recycle' || $seas == 'seas') {
|
||||
$query->onlyTrashed();
|
||||
}
|
||||
|
||||
$customer = Customer::where($where)->paginate($perPage, ['*'], 'page', $page);
|
||||
foreach ($customer as &$item) {
|
||||
$item = $this->getCustomer($item);
|
||||
if($seas == 'seas'){
|
||||
$item['seas_time'] = time()-strtotime($item['deleted_at']);
|
||||
}
|
||||
}
|
||||
unset($item);
|
||||
|
||||
return $customer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $customer
|
||||
* @param $request
|
||||
* @param $tag 是否返回客户标签
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getCustomer($customer, $language = 'zh_CN', $tag = false)
|
||||
{
|
||||
$customer['grade_txt'] = Util::language($language, Constants::GRADE_EN[$customer['grade']], Constants::GRADE_ZH[$customer['grade']], Constants::GRADE_RU[$customer['grade']]);
|
||||
$customer['magnitude_txt'] = Util::language($language, Constants::MAGNITUDE_EN[$customer['magnitude']], Constants::MAGNITUDE[$customer['magnitude']], Constants::MAGNITUDE_RU[$customer['magnitude']]);
|
||||
$customer['sex_txt'] = Util::language($language, Constants::SEX_EN[$customer['sex']], Constants::SEX[$customer['sex']], Constants::SEX_RU[$customer['sex']]);
|
||||
|
||||
if ($customer['grade']<=2) {
|
||||
$customer['follow'] = 0;
|
||||
$customer['follow_txt'] = Util::language($language,'Following','跟进中','Продолжение');
|
||||
}elseif ($customer['grade']<5) {
|
||||
$customer['follow'] = 1;
|
||||
$customer['follow_txt'] = Util::language($language,'transacted','已成交','Транзакция завершена');
|
||||
}else{
|
||||
$customer['follow'] = 2;
|
||||
$customer['follow_txt'] = Util::language($language,'lost','已流失','Потерянный');
|
||||
}
|
||||
|
||||
$where = [
|
||||
'customer_id' => $customer['id']
|
||||
];
|
||||
$begin_follow = Follow::select('id','created_at','updated_at')
|
||||
->where($where)
|
||||
->min('created_at');
|
||||
|
||||
|
||||
$customer['begin_follow'] = Util::timeTotDate($begin_follow);
|
||||
// $customer['created_at'] = Util::timeTotDate($customer['created_at']);
|
||||
// $customer['updated_at'] = Util::timeTotDate($customer['updated_at']);
|
||||
|
||||
$customer = Util::formatDate($customer,['follow_last']);
|
||||
$nameLang = $language=='en'?'name_en':($language=='ru'?'name_ru':'name');
|
||||
$countryLang = $language=='en'?'en_addr':'cn_addr';
|
||||
// $customer['car_type_name'] = empty($customer['car_type_id'])?'':CarType::where(['id'=>$customer['car_type_id']])->value($nameLang);
|
||||
$customer['country_name'] = empty($customer['country_id'])?'':Country::where(['id'=>$customer['country_id']])->value($countryLang);
|
||||
$customer['channel_name'] = empty($customer['channel_id'])?'':Channel::where(['id'=>$customer['channel_id']])->value($nameLang);
|
||||
// $customer['last_follow'] = $last_follow;
|
||||
|
||||
if ($tag) {
|
||||
foreach ($customer['tags'] as &$tag) {
|
||||
$tag['names'] = unserialize($tag['names']);
|
||||
$tag['name'] = $tag['names'][$language];
|
||||
}
|
||||
}
|
||||
|
||||
return $customer;
|
||||
}
|
||||
|
||||
|
||||
public function detail($params)
|
||||
{
|
||||
$id =$params['id'];
|
||||
$customer = Customer::with('tags')->select('id', 'user_id', 'grade', 'channel_id', 'car_type_id', 'country_id', 'magnitude', 'email', 'phone', 'WhatsApp', 'contacts', 'describe', 'address', 'lat', 'lng', 'follow_next', 'follow_remark', 'sex')
|
||||
->where('id', $id)
|
||||
->first();
|
||||
|
||||
return $customer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\service;
|
||||
|
||||
use app\common\service\OssService;
|
||||
use app\crm\model\Follow;
|
||||
use app\crm\utils\Util;
|
||||
use config\constants\Constants;
|
||||
|
||||
class FollowService
|
||||
{
|
||||
|
||||
public function list($param, $userId)
|
||||
{
|
||||
|
||||
|
||||
// $page = $request->input('page', 1);
|
||||
// $perPage = $request->input('per_page', 10);
|
||||
|
||||
//客户id
|
||||
$customer_id = $param['customer_id'];
|
||||
$corp_abbr = $param['corp_abbr'];
|
||||
|
||||
$where = [];
|
||||
$where['customer_id'] = $customer_id;
|
||||
$where['corp_abbr'] = $corp_abbr;
|
||||
|
||||
//用户角色
|
||||
|
||||
//跟进id
|
||||
$id = $param['id'] ?? null;
|
||||
if (!empty($id)) {
|
||||
$where['id'] = $id;
|
||||
}
|
||||
|
||||
// 执行分页查询
|
||||
$data = Follow::where($where)
|
||||
->orderBy('id', 'desc')->get();
|
||||
// ->paginate($perPage, ['*'], 'page', $page);
|
||||
|
||||
|
||||
// $host = $request->host();
|
||||
// $url = 'http:'.$request->url();
|
||||
foreach ($data as &$value) {
|
||||
$value = self::getFollow($value);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public static function getFollow($follow)
|
||||
{
|
||||
$follow['type_txt'] = Constants::FOLLOW[$follow['type']];
|
||||
$follow['firstFollowtime'] = $follow['follow_time'];
|
||||
$oss_picture = '';
|
||||
if (!empty($follow['picture'])) {
|
||||
$ossservice = new OssService();
|
||||
$oss_picture = $ossservice->generatePrivateUrl($follow['picture'], 86400);
|
||||
}
|
||||
$follow['picture_full'] = $oss_picture;
|
||||
// $follow = Util::formatDate($follow);
|
||||
return $follow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\utils;
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
use Firebase\JWT\ExpiredException;
|
||||
use Firebase\JWT\SignatureInvalidException;
|
||||
use support\exception\BusinessException;
|
||||
use support\Log;
|
||||
use support\Request;
|
||||
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* 参数是否为空
|
||||
*/
|
||||
public static function isEmpty($param)
|
||||
{
|
||||
if(!empty($param) || $param == 0){
|
||||
$result = false;
|
||||
}else{
|
||||
$result = true;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数是否为空
|
||||
*/
|
||||
public static function getParam(Request $request,$param,$default='')
|
||||
{
|
||||
$param = $request->input($param,$default);
|
||||
if(empty($param) && $default!==''){
|
||||
$param = $default;
|
||||
}
|
||||
return $param;
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
public static function fail($data = [],$message = '', $code = -1)
|
||||
{
|
||||
$result = [
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'data' => $data
|
||||
];
|
||||
return json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
public static function success($data = [],$message = '', $code = 0)
|
||||
{
|
||||
$result = [
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'data' => $data
|
||||
];
|
||||
return json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询返回
|
||||
*/
|
||||
public static function page($data,$message = '', $code = 0)
|
||||
{
|
||||
$result = [
|
||||
'code' => $code,
|
||||
'message' => $message
|
||||
];
|
||||
|
||||
$result['data'] = [
|
||||
'list' => $data->items(), // 当前页数据
|
||||
'total' => $data->total(), // 总记录数
|
||||
'current_page' => $data->currentPage(),
|
||||
'per_page' => $data->perPage(),
|
||||
'last_page' => $data->lastPage()
|
||||
];
|
||||
return json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式转化
|
||||
*/
|
||||
public static function timeTotDate($time = 0, $format = 'Y-m-d H:i:s')
|
||||
{
|
||||
if (empty($time)) {
|
||||
return '';
|
||||
}
|
||||
return date($format, $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化创建时间
|
||||
*/
|
||||
public static function formatDate($value,$key = ['created_at','updated_at'])
|
||||
{
|
||||
foreach ($key as $k){
|
||||
$value[$k]= self::timeTotDate($value[$k]);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化创建时间
|
||||
*/
|
||||
public static function language($language,$en,$zh_CN,$ru)
|
||||
{
|
||||
if ($language == 'zh_CN'){
|
||||
return $zh_CN;
|
||||
}elseif ($language == 'ru'){
|
||||
return $ru;
|
||||
}
|
||||
return $en;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace app\crm\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class FollowValidate extends Validate
|
||||
{
|
||||
|
||||
protected $rule = [
|
||||
'customer_id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'customer_id.require' => '用户id不能为空',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'list' => ['customer_id'],
|
||||
];
|
||||
}
|
||||
@@ -14,7 +14,7 @@ class CategorieService
|
||||
public function list($params)
|
||||
{
|
||||
$result = (new CategorieLogic())->list($params);
|
||||
$value=$result[0]->toArray();
|
||||
// $value=$result[0]->toArray();
|
||||
foreach ($result as $key => &$value) {
|
||||
$value['name'] = isset($value['translation']) ? $value['translation']['name'] : '';
|
||||
unset($value['translation']);
|
||||
|
||||
@@ -34,4 +34,104 @@ class Constants
|
||||
self::TICKET_STATUS['REJECTED'] => 'Закрыть',
|
||||
];
|
||||
|
||||
//客户分级 USTOMER_GRADE
|
||||
|
||||
public const GRADE = [
|
||||
'INITIAL' => 0, // 初步接触
|
||||
'COMMUNICATE' => 1, // 需求沟通
|
||||
'PLAN' => 2, // 方案推进
|
||||
'DEAL' => 3, // 成交阶段
|
||||
'SALES' => 4, // 售后阶段
|
||||
'LOSS' => 5, // 停滞或流失
|
||||
];
|
||||
|
||||
public const GRADE_ZH = [
|
||||
self::GRADE['INITIAL'] => '初步接触',
|
||||
self::GRADE['COMMUNICATE'] => '需求沟通',
|
||||
self::GRADE['PLAN'] => '方案推进',
|
||||
self::GRADE['DEAL'] => '成交阶段',
|
||||
self::GRADE['SALES'] => '售后阶段',
|
||||
self::GRADE['LOSS'] => '停滞或流失',
|
||||
];
|
||||
public const GRADE_EN = [
|
||||
self::GRADE['INITIAL'] => 'Initial contact',
|
||||
self::GRADE['COMMUNICATE'] => 'Demand Chat',
|
||||
self::GRADE['PLAN'] => 'promotion of the plan',
|
||||
self::GRADE['DEAL'] => 'Transaction Stage',
|
||||
self::GRADE['SALES'] => 'After Sales',
|
||||
self::GRADE['LOSS'] => 'Stagnation or loss',
|
||||
];
|
||||
public const GRADE_RU = [
|
||||
self::GRADE['INITIAL'] => 'Первоначальные контакты',
|
||||
self::GRADE['COMMUNICATE'] => 'Потребности в общении',
|
||||
self::GRADE['PLAN'] => 'Продвижение программы',
|
||||
self::GRADE['DEAL'] => 'Этап сделки',
|
||||
self::GRADE['SALES'] => 'Послепродажный этап',
|
||||
self::GRADE['LOSS'] => 'Застой или потеря',
|
||||
];
|
||||
|
||||
//客户重要性
|
||||
public const CUSTOMER_MAGNITUDE_INITIAL = 0; // 金牌商机
|
||||
public const CUSTOMER_MAGNITUDE_COMMUNICATE = 1; // 银牌商机
|
||||
public const CUSTOMER_MAGNITUDE_PLAN = 2; // 铜牌商机
|
||||
|
||||
public const MAGNITUDE = [
|
||||
self::CUSTOMER_MAGNITUDE_INITIAL => '金牌商机',
|
||||
self::CUSTOMER_MAGNITUDE_COMMUNICATE => '银牌商机',
|
||||
self::CUSTOMER_MAGNITUDE_PLAN => '铜牌商机',
|
||||
];
|
||||
public const MAGNITUDE_EN = [
|
||||
self::CUSTOMER_MAGNITUDE_INITIAL => 'Gold Medal',
|
||||
self::CUSTOMER_MAGNITUDE_COMMUNICATE => 'Silver Medal',
|
||||
self::CUSTOMER_MAGNITUDE_PLAN => 'Bronze Medal',
|
||||
];
|
||||
|
||||
public const MAGNITUDE_RU = [
|
||||
self::CUSTOMER_MAGNITUDE_INITIAL => 'Золотой бизнес',
|
||||
self::CUSTOMER_MAGNITUDE_COMMUNICATE => 'Серебряный бизнес',
|
||||
self::CUSTOMER_MAGNITUDE_PLAN => 'Бронзовый бизнес.',
|
||||
];
|
||||
|
||||
|
||||
//跟进类型
|
||||
public const CUSTOMER_FOLLOW_VISIT = 0; // 线下拜访
|
||||
public const CUSTOMER_FOLLOW_UP = 1; // 线上跟进
|
||||
|
||||
public const FOLLOW = [
|
||||
self::CUSTOMER_FOLLOW_VISIT => '线下拜访',
|
||||
self::CUSTOMER_FOLLOW_UP => '线上跟进',
|
||||
];
|
||||
public const FOLLOW_EN = [
|
||||
self::CUSTOMER_FOLLOW_VISIT => 'Visit',
|
||||
self::CUSTOMER_FOLLOW_UP => 'On line',
|
||||
];
|
||||
|
||||
//跟进类型
|
||||
public const CUSTOMER_SEX_UNKNOWN = 0; // 未知
|
||||
public const CUSTOMER_SEX_MAN = 1; // 男
|
||||
public const CUSTOMER_SEX_WOMAN = 2; // 女
|
||||
|
||||
public const SEX = [
|
||||
self::CUSTOMER_SEX_UNKNOWN => '未知',
|
||||
self::CUSTOMER_SEX_MAN => '男',
|
||||
self::CUSTOMER_SEX_WOMAN => '女',
|
||||
];
|
||||
public const SEX_EN = [
|
||||
self::CUSTOMER_SEX_UNKNOWN => 'unknown',
|
||||
self::CUSTOMER_SEX_MAN => 'man',
|
||||
self::CUSTOMER_SEX_WOMAN => 'woman',
|
||||
];
|
||||
|
||||
public const SEX_RU = [
|
||||
self::CUSTOMER_SEX_UNKNOWN => 'неизвестный',
|
||||
self::CUSTOMER_SEX_MAN => 'мужской',
|
||||
self::CUSTOMER_SEX_WOMAN => 'женский',
|
||||
];
|
||||
|
||||
public const SIGN = [
|
||||
['id' => 'xinyouhe', 'name' => '新友合'],
|
||||
['id' => 'mbaf', 'name' => 'MAGIC BRIDGE AUTO FZE']
|
||||
];
|
||||
|
||||
public const LANGUAGE = ['en', 'zh_CN','ru'];
|
||||
}
|
||||
+32
-2
@@ -25,8 +25,6 @@ use Webman\Route;
|
||||
// POST /admin/user/{user_id}/kickout // body: {"tokens": ["..."]} // 踢下线
|
||||
// POST /admin/user/{user_id}/kickout_all // 一键踢全部
|
||||
|
||||
// 调试
|
||||
Route::any('/perm', [app\controller\IndexController::class, 'perm']);
|
||||
|
||||
// 公共
|
||||
Route::group('/common', function () {
|
||||
@@ -43,6 +41,7 @@ Route::group('/common', function () {
|
||||
|
||||
Route::group('/user', function () {
|
||||
Route::any('/info', [app\common\controller\UserController::class, 'info']);
|
||||
Route::any('/get', [app\common\controller\UserController::class, 'getUser']);
|
||||
});
|
||||
|
||||
Route::group('/preset', function () {
|
||||
@@ -98,3 +97,34 @@ Route::group('/ticket', function () {
|
||||
|
||||
});
|
||||
|
||||
//crm
|
||||
Route::group('/crm', function () {
|
||||
//跟进
|
||||
Route::any('/follow/list', [app\crm\controller\FollowController::class, 'list']);
|
||||
Route::any('/follow/detail', [app\crm\controller\FollowController::class, 'detail']);
|
||||
Route::any('/follow/add', [app\crm\controller\FollowController::class, 'save']);
|
||||
Route::any('/follow/getFollowType', [app\crm\controller\FollowController::class, 'getFollowType']);
|
||||
|
||||
//客户
|
||||
Route::any('/customer/list', [app\crm\controller\CustomerController::class, 'list']);
|
||||
Route::any('/customer/detail', [app\crm\controller\CustomerController::class, 'detail']);
|
||||
Route::any('/customer/add', [app\crm\controller\CustomerController::class, 'save']);
|
||||
Route::any('/customer/claim', [app\crm\controller\CustomerController::class, 'claim']);
|
||||
Route::any('/customer/restore', [app\crm\controller\CustomerController::class, 'restore']);
|
||||
Route::any('/customer/delete', [app\crm\controller\CustomerController::class, 'delete']);
|
||||
Route::any('/customer/waitFollow', [app\crm\controller\CustomerController::class, 'waitFollow']);
|
||||
Route::any('/customer/statistics', [app\crm\controller\CustomerController::class, 'statistics']);
|
||||
Route::any('/customer/getChannel', [app\crm\controller\CustomerController::class, 'getChannel']);
|
||||
Route::any('/customer/getCountry', [app\crm\controller\CustomerController::class, 'getCountry']);
|
||||
Route::any('/customer/followNext', [app\crm\controller\CustomerController::class, 'followNext']);
|
||||
|
||||
Route::any('/tagGroup/list', [app\crm\controller\TagGroupController::class, 'list']);
|
||||
Route::any('/tagGroup/updatePivot', [app\crm\controller\TagGroupController::class, 'updatePivot']);
|
||||
|
||||
Route::any('/upload/image', [app\common\controller\UploadController::class, 'uploadImage']);
|
||||
|
||||
|
||||
Route::any('/user/edit', [app\common\controller\UserController::class, 'edit']);
|
||||
Route::any('/user/savePassword', [app\common\controller\UserController::class, 'savePassword']);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,4 +2,35 @@
|
||||
|
||||
return [
|
||||
'status_not_modified' => 'الدولة لا يمكن تعديلها عكسيا',
|
||||
'success' => ' النجاح',
|
||||
'fail' => ' الفشل',
|
||||
'login_success' => ' تم تسجيل الدخول بنجاح',
|
||||
'password_error' => ' كلمة المرور غير صحيحة',
|
||||
'user_none' => ' المستخدم غير موجود',
|
||||
'user_id' => ' معرف المستخدم',
|
||||
'user_login' => ' الرجاء تسجيل الدخول أولاً',
|
||||
'not_null' => ' لا يمكن أن يكون فارغًا',
|
||||
'code_error' => ' رمز التحقق غير صحيح',
|
||||
'format_error' => ' تنسيق غير صحيح',
|
||||
'email_repeat' => ' البريد الإلكتروني مكرر',
|
||||
'email_error' => ' تنسيق البريد الإلكتروني غير صحيح',
|
||||
'save_success' => ' تم الحفظ بنجاح',
|
||||
'save_fail' => ' فشل الحفظ',
|
||||
'register_success' => ' تم التسجيل بنجاح',
|
||||
'register_fail' => ' فشل التسجيل',
|
||||
'language_success' => ' تم تغيير اللغة بنجاح',
|
||||
'language_fail' => ' فشل تغيير اللغة',
|
||||
'param_error' => ' خطأ في المعلمات',
|
||||
'required_not_null' => ' الحقول المطلوبة لا يمكن أن تكون فارغة',
|
||||
'picture_not_null' => ' لا يمكن أن تكون الصورة فارغة',
|
||||
'contacts_not_null' => ' لا يمكن أن يكون جهة الاتصال أو البريد الإلكتروني أو الهاتف فارغين جميعًا في نفس الوقت',
|
||||
'car_type_not_null' => ' لا يمكن أن تكون التفضيلات فارغة',
|
||||
'channel_not_null' => ' لا يمكن أن تكون القناة فارغة',
|
||||
'email_consistent' => ' البريد الإلكتروني غير متطابق',
|
||||
'sign_not_null' => ' لم يتم تعيين الشركة التابعة',
|
||||
'password_short' => ' لا يمكن أن تكون كلمة المرور أقل من 6 أحرف',
|
||||
'id_empty' => ' لا يمكن أن يكون المعرف فارغًا',
|
||||
'customer_id' => ' معرف العميل',
|
||||
'tag_group_id' => ' معرف مجموعة العلامات',
|
||||
'claim_fail' => ' لا يمكن استلام العملاء الذين لديهم مالك بالفعل',
|
||||
];
|
||||
@@ -2,4 +2,35 @@
|
||||
|
||||
return [
|
||||
'status_not_modified' => 'The status cannot be reversed for modification',
|
||||
'success' => ' success',
|
||||
'fail' => ' fail',
|
||||
'login_success' => ' login success',
|
||||
'password_error' => ' password error',
|
||||
'user_none' => ' user none',
|
||||
'user_id' => ' user ID',
|
||||
'user_login' => ' Please log in first',
|
||||
'not_null' => ' not null',
|
||||
'code_error' => ' code error',
|
||||
'format_error' => ' format error',
|
||||
'email_repeat' => ' email repeat',
|
||||
'email_error' => ' Email format error',
|
||||
'save_success' => ' save success',
|
||||
'save_fail' => ' save fail',
|
||||
'register_success' => ' register success',
|
||||
'register_fail' => ' register fail',
|
||||
'language_success' => ' Successfully switched languages',
|
||||
'language_fail' => ' Language switching failed',
|
||||
'param_error' => ' param error',
|
||||
'required_not_null' => ' required not_ ull',
|
||||
'picture_not_null' => ' picture not null',
|
||||
'contacts_not_null' => ' Contact person, email, and phone cannot be empty at the same time',
|
||||
'car_type_not_null' => ' preference_not_null',
|
||||
'channel_not_null' => ' channel not null',
|
||||
'email_consistent' => ' Inconsistent email addresses',
|
||||
'sign_not_null' => ' No affiliated company has been set',
|
||||
'password_short' => ' Password cannot be less than 6 characters',
|
||||
'id_empty' => ' ID cannot be empty',
|
||||
'customer_id' => ' customer ID',
|
||||
'tag_group_id' => ' tag group ID',
|
||||
'claim_fail' => ' Cannot claim ownership of customers',
|
||||
];
|
||||
@@ -2,4 +2,35 @@
|
||||
|
||||
return [
|
||||
'status_not_modified' => 'Статус не может быть изменен в обратном направлении',
|
||||
'success' => ' Успех',
|
||||
'fail' => ' Неудача',
|
||||
'login_success' => ' Регистрация завершена',
|
||||
'password_error' => ' Ошибка пароля',
|
||||
'user_none' => ' Пользователь не существует',
|
||||
'user_id' => ' Идентификатор пользователя',
|
||||
'user_login' => ' Пожалуйста, войдите.',
|
||||
'not_null' => ' Нельзя быть пустым',
|
||||
'code_error' => ' Ошибка кода проверки',
|
||||
'format_error' => ' Ошибка формата',
|
||||
'email_repeat' => ' Почтовый ящик повторяется',
|
||||
'email_error' => ' Ошибка формата почтового ящика',
|
||||
'save_success' => ' Сохранить успешно',
|
||||
'save_fail' => ' Ошибка сохранения',
|
||||
'register_success' => ' Регистрация успешно',
|
||||
'register_fail' => ' Ошибка регистрации',
|
||||
'language_success' => ' Переключить язык успешно',
|
||||
'language_fail' => ' Ошибка переключения языка',
|
||||
'param_error' => ' Ошибка параметра',
|
||||
'required_not_null' => ' Обязательное заполнение не может быть пустым.',
|
||||
'picture_not_null' => ' Фотографии не могут быть пустыми',
|
||||
'contacts_not_null' => ' Контакты, почтовый ящик, телефон не может быть одновременно пустым',
|
||||
'car_type_not_null' => ' Предпочтения не могут быть пустыми',
|
||||
'channel_not_null' => ' Каналы не могут быть пустыми',
|
||||
'email_consistent' => ' Почтовый ящик не совпадает',
|
||||
'sign_not_null' => ' Компания не создана',
|
||||
'password_short' => ' Пароль не может быть меньше 6.',
|
||||
'id_empty' => ' ID не может быть пустым',
|
||||
'customer_id' => ' Идентификатор клиента',
|
||||
'tag_group_id' => ' Идентификатор группы меток',
|
||||
'claim_fail' => ' Невозможность получения принадлежащего клиенту',
|
||||
];
|
||||
@@ -2,4 +2,35 @@
|
||||
|
||||
return [
|
||||
'status_not_modified' => '状态不能逆向修改',
|
||||
'success' => ' 成功',
|
||||
'fail' => ' 失败',
|
||||
'login_success' => ' 登录成功',
|
||||
'password_error' => ' 密码错误',
|
||||
'user_none' => ' 用户不存在',
|
||||
'user_id' => ' 用户ID',
|
||||
'user_login' => ' 请先登录',
|
||||
'not_null' => ' 不能为空',
|
||||
'code_error' => ' 验证码错误',
|
||||
'format_error' => ' 格式错误',
|
||||
'email_repeat' => ' 邮箱重复',
|
||||
'email_error' => ' 邮箱格式错误',
|
||||
'save_success' => ' 保存成功',
|
||||
'save_fail' => ' 保存失败',
|
||||
'register_success' => ' 注册成功',
|
||||
'register_fail' => ' 注册失败',
|
||||
'language_success' => ' 切换语言成功',
|
||||
'language_fail' => ' 切换语言失败',
|
||||
'param_error' => ' 参数错误',
|
||||
'required_not_null' => ' 必填项不能为空',
|
||||
'picture_not_null' => ' 图片不能为空',
|
||||
'contacts_not_null' => ' 联系人,邮箱,电话不能同时为空',
|
||||
'car_type_not_null' => ' 偏好不能为空',
|
||||
'channel_not_null' => ' 渠道不能为空',
|
||||
'email_consistent' => ' 邮箱不一致',
|
||||
'sign_not_null' => ' 未设置所属公司',
|
||||
'password_short' => ' 密码不能少于6位',
|
||||
'id_empty' => ' id不能为空',
|
||||
'customer_id' => ' 客户ID',
|
||||
'tag_group_id' => ' 标签组ID',
|
||||
'claim_fail' => ' 不能领取有归属客户',
|
||||
];
|
||||
Reference in New Issue
Block a user