Commit 5593ebc6 authored by 朱招明's avatar 朱招明

客户、商机接口

parent b9127151
This source diff could not be displayed because it is too large. You can view the blob instead.
<?php
namespace Modules\Admin\Entities;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Kalnoy\Nestedset\NodeTrait;
class Area extends Model
{
use NodeTrait;
protected $table = 'area';
protected $fillable = ['name', 'disabled', 'parent_id'];
const CACHE_KEY_AREAS_ALL = 'package_area_all';
const CACHE_KEY_AREAS_ALL_JS = 'package_area_all_js';
/**
* 清除缓存
*/
public function clearCache()
{
Cache::forget(self::CACHE_KEY_AREAS_ALL);
Cache::forget(self::CACHE_KEY_AREAS_ALL_JS);
}
/**
* Settings constructor.
*
* @param array $attributes
*/
/*
public function __construct($attributes = [])
{
parent::__construct($attributes);
$this->setConnection(config('admin.database.connection') ?: config('database.default'));
$this->setTable(config('admin.extensions.config.table', 'area'));
}
*/
/**
* @param $query
*
* @return QueryBuilder
*/
public function scopeNotDeleted($query)
{
return $query->where('disabled', 0);
}
/**
* 返回包含有从顶级到当前级的字符串组合
*
* @param string $implode
*
* @return mixed|string
*/
public function getArea($implode = '')
{
if (!$this->id) {
throw \Exception('需要实例化的类');
}
if (!$this->parent_id) {
return $this->name;
}
return implode($implode, $this->ancestors->pluck('name')->toArray()).$implode.$this->name;
}
/**
* 返回当前区域的ID&父ID,以便供选择的时候设置默认选项
*
* @param string $implode
*
* @return mixed|string
*/
public function getAreaIds($implode = ',')
{
if (!$this->id) {
throw \Exception('需要实例化的类');
}
if (!$this->parent_id) {
return $this->id;
}
return implode($implode, $this->ancestors->pluck('id')->toArray()).$implode.$this->id;
}
/**
* 返回地区列表
*
* @param null $parent_id
*
* @return mixed
*/
public function getAreas($parent_id = null)
{
$area = $this->notDeleted()->withDepth();
if ($parent_id) {
$area->where('parent_id', $parent_id);
} else {
$area->whereNull('parent_id');
}
return $area->get();
}
public static function boot()
{
static::creating(function ($model) {
$level = 0;
if ($model->parent_id) {
$level = static::withDepth()->whereKey($model->parent_id)->value('depth') + 1;
$query = static::where('parent_id', $model->parent_id);
} else {
$query = static::whereNull('parent_id');
}
$step = pow(10, (3 - $level) * 2);
$parent_code = 0;
if ($model->parent_id) {
$parent_code = intval(static::whereKey($model->parent_id)->value('code'));
} else {
$parent_code = 10000000;
}
//按每级 100 个计算
$ids = (clone $query)->pluck('code')->toArray(); //同级下已用code
$ids2 = range($parent_code + 1 * $step, $parent_code + 99 * $step, $step); //同级下所有code
$diff = array_diff($ids2, $ids); //取出第一个可用的
$code = array_first($diff);
/*
$prev = (clone $query)->max('code');
//第一个
if (!$prev && $model->parent_id) {
$prev = $parent_code;
}
if (($prev + $step) > ($parent_code+100*$step) ) {
$ids = (clone $query)->pluck('code')->toArray();//同级下所有code
$ids2 = range(1*$step, 99*$step, $step );//同级下所有可用code
$diff = array_diff($ids2, $ids);//取出一个没有用到的
$code = array_first($diff);
} else {
$code = $prev + $step;
}
*/
$model->code = $code;
});
static::saved(function (Model $model){
$model->clearCache();
});
parent::boot(); // TODO: Change the autogenerated stub
}
/**
* 获得Root
*
* @return AreaModel
*/
public function getRoot()
{
return $this->isRoot() ? $this : $this->ancestors->first(function ($area) {
return $area->isRoot();
});
}
public static function guessId($name, $parent_id = null)
{
if (!$name) {
return null;
}
$name = Str::substr($name, 0, 2);
return static::when($parent_id, function ($query, $parent_id) {
$parent_id ? $query->where('parent_id', $parent_id) : $query->whereNull('parent_id');
})->where('name', 'like', "{$name}%")->value('id');
}
public static function guessId2($names)
{
if (!is_array($names) || count($names) < 1) {
return null;
}
$parent_id = null;
$area_id = null;
$i = 0;
do {
$area_id = static::guessId($names[$i], $parent_id);
$i++;
$area_id && $parent_id = $area_id;
} while ($area_id && isset($names[$i]));
return $parent_id;
}
/**
* @param bool $model
* @param int $depth
*
* @return bool|null
*/
public static function getAreaByIp($model = false, $depth = -1)
{
if (($return = static::getAreaByLocation($model, $depth)) !== false) {
return $return;
}
$ip = \Request::ip();
//检查是否是内网IP,是的话返回false
$result = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);
$ip_query = $result ? '&ip='.$ip : '';
$data = Cache::rememberForever('baidu_ip_to_location_'.$ip, function () use ($ip_query){
$url = 'http://api.map.baidu.com/location/ip?ak='.config('area.baidu_ak', '8d6687623e58af52fd73241ec01a224d').$ip_query;
return @json_decode(file_get_contents($url), true);
});
$province = $data['content']['address_detail']['province'] ?? null;
$city = $data['content']['address_detail']['city'] ?? null;
$district = $data['content']['address_detail']['district'] ?? null;
$querys = [$province, $city, $district];
return self::getAreaByLocationString($querys, $model, $depth);
}
/**
* @param array $querys 省市区三个字符串组成的数组
* @param bool $model 是返回查找到的ID还是对应模型
* @param int $depth 返回查找到的省市区级别,-1为最深,0为省,1为市,2为县
*
* @return null
*/
public static function getAreaByLocationString($querys = [], $model = false, $depth = -1)
{
if ($depth > -1) {
$querys = array_slice($querys, 0, ($depth + 1));
}
if (Str::substr($querys[0], 0, 2) == '北京') {
$querys[0] = '北京';
}elseif (Str::substr($querys[0], 0, 2) == '上海') {
$querys[0] = '上海';
}elseif (Str::substr($querys[0], 0, 2) == '重庆') {
$querys[0] = '重庆';
}elseif (Str::substr($querys[0], 0, 2) == '天津') {
$querys[0] = '天津';
}
$id = self::guessId2($querys);
if ($model) {
return $id ? static::find($id) : $id;
}
return $id;
}
public static function getAreaByLocation($model = false, $depth = -1, $lat = null, $lng = null)
{
if (is_null($lat) && is_null($lng)) {
$lat = request('lat', null);
$lng = request('lng', null);
}
if (is_null($lat) || is_null($lng)) {
return false;
}
$data = Cache::rememberForever('baidu_location_data_'.$lat.'_'.$lng, function () use ($lat, $lng){
$query = "output=json&location={$lat},{$lng}";
$url = 'http://api.map.baidu.com/reverse_geocoding/v3/?ak='.config('area.baidu_ak', '8d6687623e58af52fd73241ec01a224d').'&'.$query;
return @json_decode(file_get_contents($url), true);
});
$province = $data['result']['addressComponent']['province'] ?? null;
$city = $data['result']['addressComponent']['city'] ?? null;
$district = $data['result']['addressComponent']['district'] ?? null;
$querys = [$province, $city, $district];
return self::getAreaByLocationString($querys, $model, $depth);
}
}
...@@ -11,7 +11,7 @@ namespace Modules\Admin\Http\Controllers; ...@@ -11,7 +11,7 @@ namespace Modules\Admin\Http\Controllers;
use Dingo\Api\Http\Request; use Dingo\Api\Http\Request;
use Modules\Admin\Entities\Announcement; use Modules\Admin\Entities\Announcement;
use Modules\Admin\Http\Requests\AnnouncementRequest; use Modules\Admin\Http\Requests\AnnouncementRequest;
use Modules\Admin\Http\Transformers\AnnouncementTransformer; use Modules\Admin\Http\Transformer\AnnouncementTransformer;
class AnnouncementController extends BaseController class AnnouncementController extends BaseController
{ {
......
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/2
* @copyright
*/
namespace Modules\Admin\Http\Controllers;
use Illuminate\Support\Facades\Cache;
use Modules\Admin\Entities\Area;
class AreaController extends BaseController
{
/**
* * @OA\Get(
* tags={"地区"},
* summary="地区列表所有值",
* path="/api/package/areas/all",
* @OA\Response(
* response="200",
* description="成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/Area"),
* description="列表"
* ),
* )
* )
* )
* )
* @OA\Schema(
* description="地区列表",
* type="object",
* schema="Area",
* @OA\Property(property="id", type="integer", description="ID"),
* @OA\Property(property="name", type="string", description="名称"),
* @OA\Property(property="depth", type="integer", description="区域级别"),
* @OA\Property(property="parent_id", type="integer", description="父ID"),
* @OA\Property(property="children", type="array", description="子地区", @OA\Items(ref="#/components/schemas/Area"))
* )
*/
public function all()
{
$fields = ['id', 'name', 'parent_id', '_lft','_rgt', 'code'];
$data = Cache::rememberForever(Area::CACHE_KEY_AREAS_ALL, function () use ($fields) {
return Area::get($fields)->toTree()->toArray();
});
return $this->response->array(['data' => $data]);
}
}
\ No newline at end of file
...@@ -12,9 +12,9 @@ use Modules\Admin\Entities\AdminMenu; ...@@ -12,9 +12,9 @@ use Modules\Admin\Entities\AdminMenu;
use Modules\Admin\Entities\AdminUser; use Modules\Admin\Entities\AdminUser;
use Modules\Admin\Entities\Announcement; use Modules\Admin\Entities\Announcement;
use Modules\Admin\Events\UserLoginEvents; use Modules\Admin\Events\UserLoginEvents;
use Modules\Admin\Http\Transformers\AccessTokenTransformer; use Modules\Admin\Http\Transformer\AccessTokenTransformer;
use Modules\Admin\Http\Transformers\AdminUserTransformer; use Modules\Admin\Http\Transformer\AdminUserTransformer;
use Modules\Admin\Http\Transformers\BaseTransformer; use Modules\Admin\Http\Transformer\BaseTransformer;
use Modules\Admin\Http\Utils\Helper; use Modules\Admin\Http\Utils\Helper;
class AuthController extends BaseController class AuthController extends BaseController
......
...@@ -11,7 +11,7 @@ namespace Modules\Admin\Http\Controllers; ...@@ -11,7 +11,7 @@ namespace Modules\Admin\Http\Controllers;
use Modules\Admin\Entities\Department; use Modules\Admin\Entities\Department;
use Modules\Admin\Http\Requests\DepartmentRequest; use Modules\Admin\Http\Requests\DepartmentRequest;
use Modules\Admin\Http\Transformers\DepartmentTransformer; use Modules\Admin\Http\Transformer\DepartmentTransformer;
use Modules\Admin\Http\Utils\Helper; use Modules\Admin\Http\Utils\Helper;
class DepartmentController extends BaseController class DepartmentController extends BaseController
......
...@@ -4,7 +4,7 @@ namespace Modules\Admin\Http\Controllers; ...@@ -4,7 +4,7 @@ namespace Modules\Admin\Http\Controllers;
use Modules\Admin\Http\Requests\FileRequest; use Modules\Admin\Http\Requests\FileRequest;
use Modules\Admin\Http\Service\FileService; use Modules\Admin\Http\Service\FileService;
use Modules\Admin\Http\Transformers\FileTransformer; use Modules\Admin\Http\Transformer\FileTransformer;
class FilesController extends BaseController class FilesController extends BaseController
{ {
......
...@@ -13,7 +13,7 @@ use Illuminate\Support\Facades\DB; ...@@ -13,7 +13,7 @@ use Illuminate\Support\Facades\DB;
use Modules\Admin\Entities\AdminMenu; use Modules\Admin\Entities\AdminMenu;
use Modules\Admin\Entities\AdminRoleMenu; use Modules\Admin\Entities\AdminRoleMenu;
use Modules\Admin\Http\Requests\MenuRequest; use Modules\Admin\Http\Requests\MenuRequest;
use Modules\Admin\Http\Transformers\AdminMenuTransformer; use Modules\Admin\Http\Transformer\AdminMenuTransformer;
use Modules\Admin\Http\Utils\Helper; use Modules\Admin\Http\Utils\Helper;
class MenuController extends BaseController class MenuController extends BaseController
...@@ -200,7 +200,7 @@ class MenuController extends BaseController ...@@ -200,7 +200,7 @@ class MenuController extends BaseController
* @OA\Put( * @OA\Put(
* tags={"菜单"}, * tags={"菜单"},
* summary="保存数据更改", * summary="保存数据更改",
* path="api/menu/{id}/edit", * path="api/menu/save_change",
* security={ * security={
* {"jwt_auth": {}} * {"jwt_auth": {}}
* }, * },
...@@ -212,7 +212,8 @@ class MenuController extends BaseController ...@@ -212,7 +212,8 @@ class MenuController extends BaseController
* required={"change_data"}, * required={"change_data"},
* @OA\Property( * @OA\Property(
* property="change_data", * property="change_data",
* type="array" * description="变更数据",
* type="string"
* ), * ),
* ) * )
* ) * )
......
...@@ -16,7 +16,7 @@ use Modules\Admin\Entities\AdminRoleMenu; ...@@ -16,7 +16,7 @@ use Modules\Admin\Entities\AdminRoleMenu;
use Modules\Admin\Entities\AdminRoleUser; use Modules\Admin\Entities\AdminRoleUser;
use Modules\Admin\Entities\AdminUser; use Modules\Admin\Entities\AdminUser;
use Modules\Admin\Http\Requests\RoleRequest; use Modules\Admin\Http\Requests\RoleRequest;
use Modules\Admin\Http\Transformers\AdminRoleTransformer; use Modules\Admin\Http\Transformer\AdminRoleTransformer;
use Modules\Admin\Http\Utils\Helper; use Modules\Admin\Http\Utils\Helper;
class RoleController extends BaseController class RoleController extends BaseController
......
...@@ -14,7 +14,7 @@ use Modules\Admin\Entities\AdminRoleUser; ...@@ -14,7 +14,7 @@ use Modules\Admin\Entities\AdminRoleUser;
use Modules\Admin\Entities\AdminUser; use Modules\Admin\Entities\AdminUser;
use Modules\Admin\Http\Requests\UserRequest; use Modules\Admin\Http\Requests\UserRequest;
use Modules\Admin\Http\Service\UserService; use Modules\Admin\Http\Service\UserService;
use Modules\Admin\Http\Transformers\AdminUserTransformer; use Modules\Admin\Http\Transformer\AdminUserTransformer;
use Modules\Admin\Http\Utils\Helper; use Modules\Admin\Http\Utils\Helper;
class UserController extends BaseController class UserController extends BaseController
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Date: 2018/6/15 * Date: 2018/6/15
* Time: 9:47 * Time: 9:47
*/ */
namespace Modules\Admin\Http\Transformers; namespace Modules\Admin\Http\Transformer;
use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Macroable;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Date: 2018/6/13 * Date: 2018/6/13
* Time: 11:12 * Time: 11:12
*/ */
namespace Modules\Admin\Http\Transformers; namespace Modules\Admin\Http\Transformer;
use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Macroable;
use Modules\Admin\Entities\AdminMenu; use Modules\Admin\Entities\AdminMenu;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Date: 2018/6/13 * Date: 2018/6/13
* Time: 11:12 * Time: 11:12
*/ */
namespace Modules\Admin\Http\Transformers; namespace Modules\Admin\Http\Transformer;
use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Macroable;
use Modules\Admin\Entities\AdminRole; use Modules\Admin\Entities\AdminRole;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Date: 2018/6/13 * Date: 2018/6/13
* Time: 11:12 * Time: 11:12
*/ */
namespace Modules\Admin\Http\Transformers; namespace Modules\Admin\Http\Transformer;
use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Macroable;
use Modules\Admin\Entities\AdminUser; use Modules\Admin\Entities\AdminUser;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Date: 2018/6/13 * Date: 2018/6/13
* Time: 11:12 * Time: 11:12
*/ */
namespace Modules\Admin\Http\Transformers; namespace Modules\Admin\Http\Transformer;
use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Macroable;
use Modules\Admin\Entities\Announcement; use Modules\Admin\Entities\Announcement;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Date: 2018/6/27 * Date: 2018/6/27
* Time: 17:44 * Time: 17:44
*/ */
namespace Modules\Admin\Http\Transformers; namespace Modules\Admin\Http\Transformer;
use League\Fractal\TransformerAbstract; use League\Fractal\TransformerAbstract;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Date: 2018/6/13 * Date: 2018/6/13
* Time: 11:12 * Time: 11:12
*/ */
namespace Modules\Admin\Http\Transformers; namespace Modules\Admin\Http\Transformer;
use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Macroable;
use Modules\Admin\Entities\AdminUser; use Modules\Admin\Entities\AdminUser;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Date: 2018/6/15 * Date: 2018/6/15
* Time: 9:47 * Time: 9:47
*/ */
namespace Modules\Admin\Http\Transformers; namespace Modules\Admin\Http\Transformer;
use Modules\Admin\Entities\File; use Modules\Admin\Entities\File;
use Modules\Admin\Http\Utils\Helper; use Modules\Admin\Http\Utils\Helper;
......
...@@ -33,6 +33,8 @@ $api->version('v1', [ ...@@ -33,6 +33,8 @@ $api->version('v1', [
$api->get('configs', 'AuthController@apiConfig'); $api->get('configs', 'AuthController@apiConfig');
#上传文件 #上传文件
$api->post('files', 'FilesController@store'); $api->post('files', 'FilesController@store');
#获取地区列表
$api->get('/areas/all', 'AreaController@all');
$api->group(['middleware' => ['admin.permission','admin.log_operation']], function ($api){ $api->group(['middleware' => ['admin.permission','admin.log_operation']], function ($api){
#菜单 #菜单
......
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInita0dc2b1cb3bf0cf97958da9a77dfb137::getLoader();
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var \Closure(string):void */
private static $includeFile;
/** @var string|null */
private $vendorDir;
// PSR-4
/**
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
* @var list<string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var array<string, bool>
*/
private $missingClasses = array();
/** @var string|null */
private $apcuPrefix;
/**
* @var array<string, self>
*/
private static $registeredLoaders = array();
/**
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
* @return array<string, list<string>>
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return list<string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return list<string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
$paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
$paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
$paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
$paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
$paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
$paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders keyed by their corresponding vendor directories.
*
* @return array<string, self>
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}
Copyright (c) Nils Adermann, Jordi Boggiano
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
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'0be7e9e0829558786ef70afd7f14439f' => $baseDir . '/Utils/helpers.php',
);
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Modules\\Admin\\' => array($baseDir . '/'),
);
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInita0dc2b1cb3bf0cf97958da9a77dfb137
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInita0dc2b1cb3bf0cf97958da9a77dfb137', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInita0dc2b1cb3bf0cf97958da9a77dfb137', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInita0dc2b1cb3bf0cf97958da9a77dfb137::getInitializer($loader));
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInita0dc2b1cb3bf0cf97958da9a77dfb137::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}, null, null);
foreach ($filesToLoad as $fileIdentifier => $file) {
$requireFile($fileIdentifier, $file);
}
return $loader;
}
}
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInita0dc2b1cb3bf0cf97958da9a77dfb137
{
public static $files = array (
'0be7e9e0829558786ef70afd7f14439f' => __DIR__ . '/../..' . '/Utils/helpers.php',
);
public static $prefixLengthsPsr4 = array (
'M' =>
array (
'Modules\\Admin\\' => 14,
),
);
public static $prefixDirsPsr4 = array (
'Modules\\Admin\\' =>
array (
0 => __DIR__ . '/../..' . '/',
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInita0dc2b1cb3bf0cf97958da9a77dfb137::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInita0dc2b1cb3bf0cf97958da9a77dfb137::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInita0dc2b1cb3bf0cf97958da9a77dfb137::$classMap;
}, null, ClassLoader::class);
}
}
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/3
* @copyright
*/
namespace Modules\Customers\ApiDocs;
/**
* @OA\Get(
* tags={"客户"},
* summary="商机列表",
* path="api/customer/opportunity/list",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="search",
* in="query",
* description="搜索条件,如 search[customer_name]=1,
* ''expect_date','customer_name', 'customer_phone', 'title', 'id',",
* required=false,
* @OA\Schema(
* type="array",
* @OA\Items(type="string"),
* )
* ),
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/BusinessOpportunity"),
* description="列表"
* ),
* )
* )
* )
* )
*
* @OA\Post(
* tags={"客户"},
* summary="新增商机",
* path="api/customer/opportunity/add",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"customer_id","product_type","title","demand_doc","customer_desire_time","customer_expect_money",},
* @OA\Property(
* property="customer_id",
* type="string",
* description="客户ID",
* ),
* @OA\Property(
* property="product_type",
* type="string",
* description="产品类型",
* ),
* @OA\Property(
* property="title",
* type="string",
* description="标题",
* ),
* @OA\Property(
* property="demand_doc",
* type="string",
* description="需求文档",
* ),
* @OA\Property(
* property="customer_desire_time",
* type="string",
* description="客户期望时间",
* ),
* @OA\Property(
* property="customer_expect_money",
* type="string",
* description="客户预计金额",
* ),*
* )
* )
* ),
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/BusinessOpportunity")
* )
* )
* )
* )
*
* @OA\Put(
* tags={"客户"},
* summary="编辑商机",
* path="api/customer/opportunity/{id}/edit",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"customer_id","product_type","title","demand_doc","customer_desire_time","customer_expect_money",},
* @OA\Property(
* property="customer_id",
* type="string",
* description="客户ID",
* ),
* @OA\Property(
* property="product_type",
* type="string",
* description="产品类型",
* ),
* @OA\Property(
* property="title",
* type="string",
* description="标题",
* ),
* @OA\Property(
* property="demand_doc",
* type="string",
* description="需求文档",
* ),
* @OA\Property(
* property="customer_desire_time",
* type="string",
* description="客户期望时间",
* ),
* @OA\Property(
* property="customer_expect_money",
* type="string",
* description="客户预计金额",
* ),
* @OA\Property(
* property="expect_date",
* type="string",
* description="预计签单日期",
* ),
* @OA\Property(
* property="estimate_status",
* type="string",
* description="评估状态",
* ),
* @OA\Property(
* property="estimate_hour",
* type="string",
* description="工时",
* ),
* @OA\Property(
* property="estimate_price",
* type="string",
* description="评估价格",
* ),
* @OA\Property(
* property="estimate_people",
* type="string",
* description="评估人",
* ),
* @OA\Property(
* property="estimate_time",
* type="string",
* description="评估时间",
* ),
* )
* )
* ),
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/BusinessOpportunity")
* )
* )
* )
* )
*
* @OA\Get(
* tags={"客户"},
* summary="商机详情",
* path="api/customer/opportunity/{id}/detail",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/BusinessOpportunity")
* )
* )
* )
* )
*
*
* @OA\Get(
* tags={"客户"},
* summary="商机-字段数据",
* path="api/customer/opportunity/data_maps",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="类型、状态字段数据",
* )
* )
*
*
*
*
*/
class BusinessOpportunityDoc
{
}
\ No newline at end of file
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/10/23
* @copyright
*/
namespace Modules\Customers\ApiDocs;
/**
* @OA\Get(
* tags={"客户"},
* summary="客户列表",
* path="api/customer/{type}/list",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="type",
* in="path",
* description="客户类型 private=我的客户 public=公海客户 ",
* required=true,
* @OA\Schema(
* type="string",
* default="default",
* )
* ),
* @OA\Parameter(
* name="search",
* in="query",
* description="搜索条件,如 search[follow_status]=1,
* ''follow_status','type', 'from', 'name', 'mobile_phone', 'created_at,逗号分割 如 2023-11-02 12:05:41,2023-11-02 12:14:53', 'wechat'",
* required=false,
* @OA\Schema(
* type="array",
* @OA\Items(type="string"),
* )
* ),
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/Customer"),
* description="列表"
* ),
* )
* )
* )
* )
*
* @OA\Post(
* tags={"客户"},
* summary="新增客户",
* path="api/customer/{type}/add",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="type",
* in="path",
* description="客户类型 private=我的客户 public=公海客户 ",
* required=true,
* @OA\Schema(
* type="string",
* default="default",
* )
* ),
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"name","company","industry","department","duties",},
* @OA\Property(
* property="name",
* type="string",
* description="客户名称",
* ),
* @OA\Property(
* property="company",
* type="string",
* description="公司名称",
* ),
* @OA\Property(
* property="industry",
* type="string",
* description="行业",
* ),
* @OA\Property(
* property="department",
* type="string",
* description="部门",
* ),
* @OA\Property(
* property="duties",
* type="string",
* description="职位",
* ),
* @OA\Property(
* property="tel_phone",
* type="string",
* description="电话",
* ),
* @OA\Property(
* property="mobile_phone",
* type="string",
* description="手机号码",
* ),
* @OA\Property(
* property="wechat",
* type="string",
* description="微信号",
* ),
* @OA\Property(
* property="dy",
* type="string",
* description="抖音号",
* ),
* @OA\Property(
* property="email",
* type="string",
* description="邮箱",
* ),
* @OA\Property(
* property="province",
* type="string",
* description="省",
* ),
* @OA\Property(
* property="city",
* type="string",
* description="市",
* ),
* @OA\Property(
* property="area",
* type="string",
* description="区",
* ),
* @OA\Property(
* property="address",
* type="string",
* description="地址",
* ),
* @OA\Property(
* property="from",
* type="string",
* description="客户来源",
* ),
* @OA\Property(
* property="type",
* type="string",
* description="客户类型",
* ),
*
* )
* )
* ),
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Customer")
* )
* )
* )
* )
*
* @OA\Post(
* tags={"客户"},
* summary="批量导入客户",
* path="api/customer/{type}/add_import",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="type",
* in="path",
* description="客户类型 private=我的客户 public=公海客户 ",
* required=true,
* @OA\Schema(
* type="string",
* default="default",
* )
* ),
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"data"},
* @OA\Property(
* property="name",
* type="string",
* description="导入数据,json数组格式,字段同新增接口",
* ),
* )
* )
* ),
* @OA\Response(
* response="201",
* description="",
* )
* )
*
* @OA\Put(
* tags={"客户"},
* summary="编辑客户-普通资料",
* path="api/customer/{type}/{id}/edit",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="type",
* in="path",
* description="客户类型 private=我的客户 public=公海客户 ",
* required=true,
* @OA\Schema(
* type="string",
* default="default",
* )
* ),
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"name","company","industry","department","duties",},
* @OA\Property(
* property="name",
* type="string",
* description="客户名称",
* ),
* @OA\Property(
* property="company",
* type="string",
* description="公司名称",
* ),
* @OA\Property(
* property="industry",
* type="string",
* description="行业",
* ),
* @OA\Property(
* property="department",
* type="string",
* description="部门",
* ),
* @OA\Property(
* property="duties",
* type="string",
* description="职位",
* ),
* @OA\Property(
* property="tel_phone",
* type="string",
* description="电话",
* ),
* @OA\Property(
* property="mobile_phone",
* type="string",
* description="手机号码",
* ),
* @OA\Property(
* property="wechat",
* type="string",
* description="微信号",
* ),
* @OA\Property(
* property="dy",
* type="string",
* description="抖音号",
* ),
* @OA\Property(
* property="email",
* type="string",
* description="邮箱",
* ),
* @OA\Property(
* property="province",
* type="string",
* description="省",
* ),
* @OA\Property(
* property="city",
* type="string",
* description="市",
* ),
* @OA\Property(
* property="area",
* type="string",
* description="区",
* ),
* @OA\Property(
* property="address",
* type="string",
* description="地址",
* ),
* @OA\Property(
* property="from",
* type="string",
* description="客户来源",
* ),
* @OA\Property(
* property="type",
* type="string",
* description="客户类型",
* ),
*
* )
* )
* ),
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Customer")
* )
* )
* )
* )
*
* @OA\Get(
* tags={"客户"},
* summary="详情",
* path="api/customer/{type}/{id}/detail",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="type",
* in="path",
* description="客户类型 private=我的客户 public=公海客户 ",
* required=true,
* @OA\Schema(
* type="string",
* default="default",
* )
* ),
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Customer")
* )
* )
* )
* )
*
* @OA\Put(
* tags={"客户"},
* summary="编辑客户-私密资料",
* path="api/customer/{type}/{id}/edit_private",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="type",
* in="path",
* description="客户类型 private=我的客户 public=公海客户 ",
* required=true,
* @OA\Schema(
* type="string",
* default="default",
* )
* ),
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={},
* @OA\Property(
* property="business_license",
* type="string",
* description="营业执照",
* ),
* @OA\Property(
* property="identity",
* type="string",
* description="身份证",
* ),
* @OA\Property(
* property="bank_account",
* type="string",
* description="银行账户",
* ),
* @OA\Property(
* property="mobile_phone",
* type="string",
* description="手机号",
* ),
* )
* )
* ),
* @OA\Response(
* response="200",
* description="",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Customer")
* )
* )
* )
* )
*
* @OA\Put(
* tags={"客户"},
* summary="写跟进",
* path="api/customer/{type}/{id}/follow",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="type",
* in="path",
* description="客户类型 private=我的客户 public=公海客户 ",
* required=true,
* @OA\Schema(
* type="string",
* default="default",
* )
* ),
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"type","status","next_follow_time","content",},
* @OA\Property(
* property="type",
* type="string",
* description="跟进类型",
* ),
* @OA\Property(
* property="status",
* type="string",
* description="跟进状态",
* ),
* @OA\Property(
* property="next_follow_time",
* type="string",
* description="下次跟进时间",
* ),
* @OA\Property(
* property="content",
* type="string",
* description="跟进内容",
* ),
* )
* )
* ),
* @OA\Response(
* response="204",
* description="",
* )
* )
*
* @OA\Get(
* tags={"客户"},
* summary="字段数据",
* path="api/customer/{type}/data_maps",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="type",
* in="path",
* description="客户类型 private=我的客户 public=公海客户 ",
* required=true,
* @OA\Schema(
* type="string",
* default="default",
* )
* ),
* @OA\Response(
* response="200",
* description="类型、状态字段数据",
* )
* )
*
*/
class CustomerDoc
{
}
\ No newline at end of file
<?php
return [
'name' => 'Customers'
];
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('customers', function (Blueprint $table) {
$table->comment('客户表');
$table->id();
$table->string('name')->default('')->comment('客户名称');
$table->string('company')->default('')->comment('公司名称');
$table->string('industry')->default('')->comment('行业');
$table->string('department')->default('')->comment('部门');
$table->string('duties')->default('')->comment('职务');
$table->string('tel_phone')->default('')->comment('电话');
$table->string('mobile_phone')->default('')->comment('手机号码');
$table->string('wechat')->default('')->comment('微信号');
$table->string('dy')->default('')->comment('抖音号');
$table->string('email')->default('')->comment('邮箱');
$table->integer('province')->default(0)->comment('省');
$table->integer('city')->default(0)->comment('市');
$table->integer('area')->default(0)->comment('区');
$table->string('address')->default('')->comment('详细地址');
$table->tinyInteger('follow_status')->default(0)->comment('跟进状态');
$table->tinyInteger('from')->default(0)->comment('客户来源');
$table->tinyInteger('type')->default(0)->comment('客户类型');
$table->integer('founder')->default(0)->comment('创建人');
$table->integer('owner')->default(0)->comment('持有人');
$table->string('business_license')->default('')->comment('营业执照');
$table->string('identity')->default('')->comment('身份证');
$table->string('bank_account')->default('')->comment('银行对公账户');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('customers');
}
};
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('customer_follows', function (Blueprint $table) {
$table->comment('客户跟进记录表');
$table->id();
$table->integer('customer_id')->default(0)->comment('客户ID');
$table->tinyInteger('type')->default(0)->comment('跟进类型');
$table->tinyInteger('before_status')->default(0)->comment('上次跟进状态');
$table->tinyInteger('status')->default(0)->comment('跟进状态');
$table->dateTime('follow_time')->nullable()->comment('跟进时间');
$table->dateTime('next_follow_time')->nullable()->comment('下次跟进时间');
$table->string('content')->default('')->comment('跟进内容');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('customer_follows');
}
};
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('business_opportunities', function (Blueprint $table) {
$table->comment('商机表');
$table->id();
$table->integer('customer_id')->default(0)->comment('客户ID');
$table->integer('product_type')->default(0)->comment('产品类型');
$table->string('title')->default('')->comment('标题');
$table->string('demand_doc')->default('')->comment('需求文档');
$table->dateTime('customer_desire_time')->nullable()->comment('客户期望时间');
$table->decimal('customer_expect_money',13,2)->default(0)->comment('客户预期金额');
$table->date('expect_date')->nullable()->comment('预计签单日期');
$table->integer('estimate_status')->default(0)->comment('评估状态');
$table->integer('estimate_hour')->default(0)->comment('评估-工时');
$table->decimal('estimate_price',13,2)->default(0)->comment('评估-价格');
$table->string('estimate_people')->default('')->comment('评估人');
$table->dateTime('estimate_time')->nullable()->comment('评估时间');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('business_opportunitys');
}
};
<?php
namespace Modules\Customers\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class CustomersDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
// $this->call("OthersTableSeeder");
}
}
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/2
* @copyright
*/
namespace Modules\Customers\Entities;
use Illuminate\Database\Eloquent\Model;
class BaseModel extends Model
{
protected $search = [];
public function scopeParamsSearch($query,$params)
{
foreach ($params as $key => $value){
$value= (string)$value;
if(!in_array($key,$this->search)){
continue;
}
$this->searchRule($query,$key,$value);
}
}
protected function searchRule($query,$key,$value){
$query->where($key,$value);
}
}
\ No newline at end of file
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/2
* @copyright
*/
namespace Modules\Customers\Entities;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
class BusinessOpportunity extends BaseModel
{
protected $fillable = [
'customer_id', 'product_type', 'title', 'demand_doc', 'customer_desire_time', 'customer_expect_money',
'expect_date', 'estimate_status', 'estimate_hour', 'estimate_price', 'estimate_people', 'estimate_time',
];
protected $search = [
'expect_date', 'customer_name', 'customer_phone','title', 'id',
];
static public $product_type_maps = [
1 => '标准产品',
2 => '定制开发服务',
];
static public $estimate_status_maps = [
1 => '等待评估',
2 => '评估中',
3 => '评估完成',
];
protected function searchRule($query,$key,$value){
switch ($key){
case "customer_name":
$query->whereHas('customer',function ($query)use ($value) {
$query->where('name', 'like',"%{$value}%");
});
break;
case "customer_phone":
$query->whereHas('customer',function ($query)use ($value) {
$query->where('mobile_phone',$value);
});
break;
case "title":
$query->where($key,'like',"%{$value}%");
break;
default:
$query->where($key,$value);
break;
}
return $query;
}
public function getProductTypeTextAttribute()
{
return static::$product_type_maps[$this->product_type] ?? '';
}
public function getEstimateStatusTextAttribute()
{
return static::$estimate_status_maps[$this->estimate_status] ?? '';
}
public function customer(): BelongsTo{
return $this->belongsTo(Customer::class);
}
}
\ No newline at end of file
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/2
* @copyright
*/
namespace Modules\Customers\Entities;
class Customer extends BaseModel
{
protected $fillable = [
'name', 'company', 'industry', 'department', 'duties', 'tel_phone', 'mobile_phone',
'wechat', 'dy', 'email', 'province', 'city', 'area', 'address', 'follow_status',
'from', 'type', 'founder', 'owner', 'business_license', 'identity', 'bank_account',
];
protected $search = [
'name', 'tel_phone', 'mobile_phone','wechat', 'follow_status', 'from', 'type', 'created_at',
];
static public $type_maps = [
1 => '个人',
2 => '企业',
99 => '其他',
];
static public $from_maps = [
1 => '抖音',
2 => '客户转介绍',
3 => '社交推广',
4 => '空白',
99 => '其他',
];
protected function searchRule($query,$key,$value){
switch ($key){
case "name":
$query->where($key,'like',"%{$value}%");
break;
case "created_at":
$times = explode(',',$value);
$query->where(function ($query)use ($times){
$query->where('created_at','>=',$times[0]);
if(!empty($times[1])){
$query->where('created_at','<=',$times[1]);
}
});
break;
default:
$query->where($key,$value);
break;
}
return $query;
}
public function getTypeTextAttribute()
{
return static::$type_maps[$this->type] ?? '';
}
public function getFromTextAttribute()
{
return static::$from_maps[$this->from] ?? '';
}
public function getFollowStatusTextAttribute()
{
return CustomerFollow::$status_maps[$this->follow_status] ?? '';
}
public function scopePrivate($query)
{
$query->where('owner', auth()->user()->id);
}
public function scopePublic($query)
{
$query->where('owner', 0);
}
}
\ No newline at end of file
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/2
* @copyright
*/
namespace Modules\Customers\Entities;
class CustomerFollow extends BaseModel
{
protected $fillable = [
'customer_id', 'type', 'before_status', 'status', 'follow_time', 'next_follow_time', 'content',
];
static public $type_maps = [
1 => '个人',
2 => '企业',
99 => '其他',
];
static public $status_maps = [
1 => '初访',
2 => '意向',
3 => '报价',
4 => '成交',
5 => '暂时搁置',
6 => '未成交',
];
}
\ No newline at end of file
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/10/21
* @copyright
*/
namespace Modules\Customers\Http\Controllers;
use Dingo\Api\Routing\Helpers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller;
class BaseController extends Controller
{
use Helpers,AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
\ No newline at end of file
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/2
* @copyright
*/
namespace Modules\Customers\Http\Controllers;
use Modules\Admin\Http\Controllers\BaseController;
use Modules\Customers\Entities\BusinessOpportunity;
use Modules\Customers\Http\Requests\BusinessOpportunityRequest;
use Modules\Customers\Http\Service\BusinessOpportunityService;
use Modules\Customers\Http\Transformer\BusinessOpportunityTransformer;
class BusinessOpportunityController extends BaseController
{
/**
* 商机列表
* @desc
* @author [ZZM]
* @since 2023/11/3
* @modify
*/
public function list(BusinessOpportunityRequest $request){
$params = $request->input('search',[]);
$list = BusinessOpportunity::paramsSearch($params)->paginate(request('per_page'));
return $this->response->paginator($list, new BusinessOpportunityTransformer());
}
/**
* 新增商机
* @desc
* @author [ZZM]
* @since 2023/11/3
* @modify
*/
public function add(BusinessOpportunityRequest $request){
$params = $request->only(
[
'customer_id', 'product_type', 'title', 'demand_doc', 'customer_desire_time', 'customer_expect_money',
'expect_date', 'estimate_status', 'estimate_hour', 'estimate_price', 'estimate_people', 'estimate_time',
]
);
$params = array_filter($params);
$business_opportunity = BusinessOpportunity::create($params)->refresh();
return $this->response->item($business_opportunity, new BusinessOpportunityTransformer());
}
/**
* 编辑商机
* @desc
* @author [ZZM]
* @since 2023/11/3
* @modify
*/
public function edit(BusinessOpportunityRequest $request,$id){
$params = $request->only(
[
'customer_id', 'product_type', 'title', 'demand_doc', 'customer_desire_time', 'customer_expect_money',
'expect_date', 'estimate_status', 'estimate_hour', 'estimate_price', 'estimate_people', 'estimate_time',
]
);
$business_opportunity = BusinessOpportunity::where('id', $id)->first();
if (!$business_opportunity)
{
abort(500, '商机不存在');
}
$update = BusinessOpportunityService::formatUpdateParams($business_opportunity, $params);
$business_opportunity->update($update);
return $this->response->item($business_opportunity, new BusinessOpportunityTransformer());
}
/**
* 商机详情
* @desc
*
* @since 2023/11/3
* @modify
* @author [ZZM]
*/
public function show(BusinessOpportunityRequest $request,$id){
$business_opportunity = BusinessOpportunity::where('id', $id)->first();
if (!$business_opportunity)
{
abort(500, '商机不存在');
}
return $this->response->item($business_opportunity, new BusinessOpportunityTransformer());
}
/**
* 数据字典
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function dataMaps(){
$product_type_maps = BusinessOpportunity::$product_type_maps;
$product_type_maps = array_map(function ($id, $name) {
return ['id' => $id, 'name' => $name];
}, array_keys($product_type_maps), $product_type_maps);
$estimate_status_maps = BusinessOpportunity::$estimate_status_maps;
$estimate_status_maps = array_map(function ($id, $name) {
return ['id' => $id, 'name' => $name];
}, array_keys($estimate_status_maps), $estimate_status_maps);
$data = [
'product_type_maps' => $product_type_maps,
'estimate_status_maps' => $estimate_status_maps,
];
return $this->response->array(['data'=>$data]);
}
}
\ No newline at end of file
<?php
namespace Modules\Customers\Http\Controllers;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Modules\Admin\Entities\Area;
use Modules\Customers\Entities\Customer;
use Modules\Customers\Entities\CustomerFollow;
use Modules\Customers\Http\Requests\CustomerRequest;
use Modules\Customers\Http\Service\CustomerService;
use Modules\Customers\Http\Transformer\CustomerTransformer;
class CustomersController extends BaseController
{
protected $type;
/**
* 客户列表
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function list(CustomerRequest $request)
{
$params = $request->input('search',[]);
$list = Customer::{$this->type}()->paramsSearch($params)->paginate(request('per_page'));
return $this->response->paginator($list, new CustomerTransformer());
}
/**
* 新增客户
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function add(CustomerRequest $request)
{
$params = $request->only(
[
'name', 'company', 'industry', 'department', 'duties', 'tel_phone', 'mobile_phone',
'wechat', 'dy', 'email', 'province', 'city', 'area', 'address', 'follow_status',
'from', 'type','business_license', 'identity', 'bank_account',
]
);
$params = array_filter($params);
$params['founder'] = $this->user->id;
if($this->type == 'private'){
$params['owner'] = $this->user->id;
}
$customer = Customer::create($params)->refresh();
return $this->response->item($customer, new CustomerTransformer());
}
/**
* 批量导入客户
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function addImport(CustomerRequest $request)
{
$params = $request->input('data', []);
if (empty($params))
{
abort('500', '内容为空');
}
$data = CustomerService::formatImportData($params, $this->type);
Customer::insert($data);
return $this->response->created();
}
/**
* 客户详情
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function show(CustomerRequest $request, $id)
{
$customer = Customer::where('id', $id)->{$this->type}()->first();
if (!$customer)
{
abort(500, '客户不存在');
}
return $this->response->item($customer, new CustomerTransformer());
}
/**
* 编辑 普通资料
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function edit(CustomerRequest $request, $id)
{
$params = $request->only(
[
'name', 'company', 'industry', 'department', 'duties', 'tel_phone', 'mobile_phone',
'wechat', 'dy', 'email', 'province', 'city', 'area', 'address', 'follow_status',
'from', 'type', 'founder', 'owner',
]
);
$customer = Customer::where('id', $id)->{$this->type}()->first();
if (!$customer)
{
abort(500, '客户不存在');
}
$update = CustomerService::formatUpdateParams($customer, $params);
$customer->update($update);
return $this->response->item($customer, new CustomerTransformer());
}
/**
* 编辑 私密资料
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function editPrivate(CustomerRequest $request, $id)
{
$params = $request->only(
[
'business_license', 'identity', 'bank_account','mobile_phone',
]
);
$customer = Customer::where('id', $id)->{$this->type}()->first();
if (!$customer)
{
abort(500, '客户不存在');
}
$update = CustomerService::formatUpdateParams($customer, $params);
$customer->update($update);
return $this->response->item($customer, new CustomerTransformer());
}
/**
* 更新跟进状态
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function updateFollowStatus(CustomerRequest $request, $id)
{
$params = $request->only(['type', 'status', 'next_follow_time', 'content']);
$customer = Customer::where('id', $id)->{$this->type}()->first();
if (!$customer)
{
abort(500, '客户不存在');
}
DB::transaction(function ()use ($customer,$params){
$params['customer_id'] = $customer->id;
$params['before_status'] = $customer->follow_status;
$params['follow_time'] = Carbon::now();
CustomerFollow::create($params);
$customer->follow_status = $params['status'];
$customer->save();
});
return $this->response->noContent();
}
/**
* 数据字典
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function dataMaps(){
$type_maps = Customer::$type_maps;
$type_maps = array_map(function ($id, $name) {
return ['id' => $id, 'name' => $name];
}, array_keys($type_maps), $type_maps);
$from_maps = Customer::$from_maps;
$from_maps = array_map(function ($id, $name) {
return ['id' => $id, 'name' => $name];
}, array_keys($from_maps), $from_maps);
$follow_status_maps = CustomerFollow::$status_maps;
$follow_status_maps = array_map(function ($id, $name) {
return ['id' => $id, 'name' => $name];
}, array_keys($follow_status_maps), $follow_status_maps);
$follow_type_maps = CustomerFollow::$type_maps;
$follow_type_maps = array_map(function ($id, $name) {
return ['id' => $id, 'name' => $name];
}, array_keys($follow_type_maps), $follow_type_maps);
$data = [
'type_maps' => $type_maps,
'from_maps' => $from_maps,
'follow_status_maps' => $follow_status_maps,
'follow_type_maps' => $follow_type_maps,
];
return $this->response->array(['data'=>$data]);
}
}
<?php
namespace Modules\Customers\Http\Controllers;
use Modules\Customers\Entities\Customer;
use Modules\Customers\Http\Requests\CustomerRequest;
class PrivateCustomersController extends CustomersController
{
protected $type = 'private';
/**
* 客户退回公海 可批量
* @desc
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function backPublic(CustomerRequest $request)
{
$ids = $request->input('id', []);
if($ids){
Customer::whereIn('id', $ids)->private()->update(['owner' => 0]);
}
return $this->response->noContent();
}
}
<?php
namespace Modules\Customers\Http\Controllers;
use Modules\Customers\Entities\Customer;
use Modules\Customers\Http\Requests\CustomerRequest;
class PublicCustomersController extends CustomersController
{
protected $type = 'public';
/**
* 领取至我的客户
* @desc
*
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
public function receivePrivate(CustomerRequest $request){
$user = $this->user;
$ids = $request->input('id', []);
if($ids){
Customer::whereIn('id', $ids)->public()->update(['owner' => $user->id]);
}
return $this->response->noContent();
}
}
<?php
namespace Modules\Customers\Http\Requests;
use Dingo\Api\Facade\Route;
use Dingo\Api\Http\FormRequest;
use Dingo\Api\Http\Request;
class BaseRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$method = strtolower($this->getAction()).'Rules';
if(!method_exists($this, $method)){
return [];
}
$rules = $this->$method();
foreach ($rules as &$rule) {
if (is_string($rule) && strpos($rule, 'bail') === false) {
$rule = 'bail|'.$rule;
} elseif (is_array($rule) && !in_array('bail', $rule)) {
array_unshift($rule, 'bail');
}
}
return $rules;
}
public function messages()
{
$method = strtolower($this->getAction()).'Messages';
if(!method_exists($this, $method)){
return $this->commonMessages();
}
return $this->$method();
}
public function commonMessages(){
return [];
}
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* 获取请求的控制器方法
* @desc
* @return mixed|string
* @since 2023/11/2
* @modify
* @author [ZZM]
*/
public function getAction(){
$controllerAction = Route::currentRouteAction();;
[$controller, $method] = explode('@', $controllerAction);
return $method;
}
}
<?php
namespace Modules\Customers\Http\Requests;
use Illuminate\Validation\Rule;
use Modules\Admin\Entities\AdminUser;
use Modules\Customers\Entities\BusinessOpportunity;
use Modules\Customers\Entities\Customer;
use Modules\Customers\Entities\CustomerFollow;
class BusinessOpportunityRequest extends BaseRequest
{
public function addRules()
{
return [
'customer_id' => 'bail|required|exists:customers,id',
'product_type' => ['bail','required',Rule::in(array_keys(BusinessOpportunity::$product_type_maps))],
'title' => 'bail|required',
'demand_doc' => 'bail|required',
'customer_desire_time' => ['bail','required','date_format:Y-m-d H:i:s','after:now'],
'customer_expect_money' => 'bail|required',
];
}
public function editRules()
{
return [
'customer_id' => 'bail|required|exists:customers,id',
'product_type' => ['bail','required',Rule::in(array_keys(BusinessOpportunity::$product_type_maps))],
'title' => 'bail|required',
'demand_doc' => 'bail|required',
'customer_desire_time' => ['bail','required','date_format:Y-m-d H:i:s','after:now'],
'customer_expect_money' => 'bail|required',
];
}
public function commonMessages()
{
return [
'customer_id.required' => '客户不能为空',
'customer_id.exists' => '客户不存在',
'product_type.required' => '产品类型不能为空',
'product_type.in' => '产品类型不存在',
'title.required' => '标题不能为空',
'demand_doc.required' => '需求文档不能为空',
'customer_desire_time.required' => '期望完成时间不能为空',
'customer_desire_time.date_format' => '期望完成时间格式错误',
'customer_desire_time.after' => '期望完成时间必须大于当前时间',
'customer_expect_money.required' => '预期金额不能为空',
];
}
}
<?php
namespace Modules\Customers\Http\Requests;
use Illuminate\Validation\Rule;
use Modules\Admin\Entities\AdminUser;
use Modules\Customers\Entities\Customer;
use Modules\Customers\Entities\CustomerFollow;
class CustomerRequest extends BaseRequest
{
public function addRules()
{
return [
'name' => 'bail|required',
'company' => 'bail|required',
'industry' => 'bail|required',
'department' => 'bail|required',
'duties' => 'bail|required',
];
}
public function editRules()
{
return [
'name' => 'bail|required',
'company' => 'bail|required',
'industry' => 'bail|required',
'department' => 'bail|required',
'duties' => 'bail|required',
];
}
public function updateFollowStatusRules()
{
return [
'type' => ['bail','required',Rule::in(array_keys(CustomerFollow::$type_maps))],
'status' => ['bail','required',Rule::in(array_keys(CustomerFollow::$status_maps))],
'next_follow_time' => ['bail','required','date_format:Y-m-d H:i:s','after:now'],
'content' => ['bail','required'],
];
}
public function commonMessages()
{
return [
'name.required' => '客户名称不能为空',
'company.required' => '公司名称不能为空',
'industry.required' => '行业不能为空',
'department.required' => '部门不能为空',
'duties.required' => '职业不能为空',
];
}
public function updateFollowStatusMessages()
{
return [
'type.required' => '类型不能为空',
'type.in' => '类型不存在',
'status.required' => '状态不能为空',
'status.in' => '状态不存在',
'next_follow_time.required' => '下次跟进时间不能为空',
'next_follow_time.date_format' => '下次跟进时间格式错误',
'next_follow_time.after' => '下次跟进时间必须大于当前时间',
'content.required' => '内容不能为空',
];
}
}
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/3
* @copyright
*/
namespace Modules\Customers\Http\Service;
use Modules\Customers\Entities\BusinessOpportunity;
class BusinessOpportunityService
{
/**
* 格式化待更新参数
* @desc
*
* @param BusinessOpportunity $business_opportunity 数据模型
* @param array $params 请求参数
*
* @return array
* @since 2023/11/2
* @modify
* @author [ZZM]
*/
static public function formatUpdateParams(BusinessOpportunity $business_opportunity, array $params): array
{
$update = [];
foreach ($params as $field => $value)
{
switch ($field)
{
case "product_type":
case "estimate_status":
case "estimate_hour":
case "estimate_price":
$value = $value ?: 0;
break;
case "customer_desire_time":
case "estimate_time":
$value = $value ?: NULL;
break;
default:
$value = $value ?: '';
break;
}
if ($business_opportunity->{$field} != $value)
{
$update[ $field ] = $value;
}
}
return $update;
}
}
\ No newline at end of file
<?php
/**
* @desc
* @author [ZZM]
* @since 2023/11/2
* @copyright
*/
namespace Modules\Customers\Http\Service;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Modules\Admin\Entities\Area;
use Modules\Customers\Entities\Customer;
use Modules\Customers\Entities\CustomerFollow;
class CustomerService
{
/**
* 格式化待更新参数
* @desc
*
* @param Customer $customer 数据模型
* @param array $params 请求参数
*
* @return array
* @since 2023/11/2
* @modify
* @author [ZZM]
*/
static public function formatUpdateParams(Customer $customer, array $params): array
{
$update = [];
foreach ($params as $field => $value)
{
switch ($field)
{
case "province":
case "city":
case "area":
case "from":
case "type":
case "follow_status":
$value = $value ?: 0;
break;
default:
$value = $value ?: '';
break;
}
if ($customer->{$field} != $value)
{
$update[ $field ] = $value;
}
}
return $update;
}
/**
* 格式化导入数据
* @desc
*
* @param array $data
* @param string $type
*
* @return array
* @author [ZZM]
* @since 2023/11/2
* @modify
*/
static public function formatImportData(array $data, string $type = 'public'): array
{
$user = auth()->user();
$now = Carbon::now();
$default_field = [
'name' => '',
'company' => '',
'industry' => '',
'department' => '',
'duties' => '',
'tel_phone' => '',
'mobile_phone' => '',
'wechat' => '',
'dy' => '',
'email' => '',
'address' => '0',
'follow_status' => '0',
'from' => '0',
'type' => '0',
];
$required_field = ['name', 'company', 'industry', 'department', 'duties',];
$required_field_message = [
'name' => '客户名称不能为空',
'company' => '公司名称不能为空',
'industry' => '行业不能为空',
'department' => '部门不能为空',
'duties' => '职业不能为空',
];
$insert = [];
foreach ($data as $key => $item)
{
if (empty($item))
{
continue;
}
$insert_item = [];
foreach ($default_field as $field => $default_value)
{
$value = trim($item[$field]??$default_value);
#必选字段
if (in_array($field, $required_field) && empty($value))
{
abort(500, "第".($key + 1)."行数据有误:{$required_field_message[$field]}");
}
#跟进状态
if ($field == 'follow_status')
{
$value = array_search($value, CustomerFollow::$status_maps) ?: 0;
}
#客户来源
if ($field == 'from')
{
$value = array_search($value, Customer::$from_maps) ?: 0;
}
#客户类型
if ($field == 'type')
{
$value = array_search($value, Customer::$type_maps) ?: 0;
}
$insert_item[ $field ] = $value;
}
$insert_item['founder'] = $user->id;
$insert_item['created_at'] = $now;
$insert_item['updated_at'] = $now;
if ($type == 'private')
{
$insert_item['owner'] = $user->id;
}
$insert[] = $insert_item;
}
return $insert;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/27
* Time: 17:44
*/
namespace Modules\Customers\Http\Transformer;
use Illuminate\Support\Traits\Macroable;
use League\Fractal\TransformerAbstract;
class BaseTransformer extends TransformerAbstract
{
use Macroable;
protected static $extraIncludes = [];
protected static $extraDefaultIncludes = [];
public function __construct()
{
if (!isset(static::$extraIncludes[static::class])) {
static::$extraIncludes[static::class] = [];
}
if (!isset(static::$extraDefaultIncludes[static::class])) {
static::$extraDefaultIncludes[static::class] = [];
}
$this->availableIncludes = array_merge($this->availableIncludes, static::$extraIncludes[static::class]);
$this->defaultIncludes = array_merge($this->defaultIncludes, static::$extraDefaultIncludes[static::class]);
}
public static function addIncludes($name)
{
if (!isset(static::$extraIncludes[static::class])) {
static::$extraIncludes[static::class] = [];
}
$name = (array) $name;
$temp = [];
foreach ($name as $key => $value) {
if (is_string($key) && $value instanceof \Closure) {
static::macro('include'.ucfirst($key), $value);
$value = $key;
}
$temp[] = $value;
}
static::$extraIncludes[static::class] = array_merge(static::$extraIncludes[static::class], $temp);
}
public static function addDefaultIncludes($name)
{
if (!isset(static::$extraDefaultIncludes[static::class])) {
static::$extraDefaultIncludes[static::class] = [];
}
static::$extraDefaultIncludes[static::class] += (array) $name;
}
/**
* 修改返回
*
* @param $arr
*
* @return mixed
*/
public function alter($arr)
{
return $arr;
}
public static function checkExtraInclude($key)
{
static $extra_includes;
if ($extra_includes == null) {
$extra_includes = array_map('trim', explode(',', request('extra_include', '')));
}
return array_search($key, $extra_includes) === false ? false : true;
}
public function single($value, $transformer)
{
return $value ? $this->item($value, $transformer) : null;
}
protected function hasCount($model, $field)
{
return $this->primitive(optional($model->$field)->count??0);
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/13
* Time: 11:12
*/
namespace Modules\Customers\Http\Transformer;
use Modules\Admin\Http\Utils\Helper;
use Modules\Customers\Entities\BusinessOpportunity;
use Modules\Customers\Entities\Customer;
class BusinessOpportunityTransformer extends BaseTransformer
{
public function __construct()
{
parent::__construct();
}
/**
* @OA\Schema(
* description="用户信息",
* type="object",
* schema="BusinessOpportunity",
* @OA\Property(property="id", type="integer", description="ID"),
* @OA\Property(property="product_type", type="string", description="产品类型"),
* @OA\Property(property="title", type="string", description="标题"),
* @OA\Property(property="demand_doc", type="string", description="需求文档"),
* @OA\Property(property="customer_desire_time", type="string", description="客户期望时间"),
* @OA\Property(property="customer_expect_money", type="string", description="客户预估金额"),
* @OA\Property(property="expect_date", type="string", description="预计签单日期"),
* @OA\Property(property="estimate_status", type="string", description="评估状态"),
* @OA\Property(property="estimate_hour", type="string", description="评估工时"),
* @OA\Property(property="estimate_price", type="string", description="评估价格"),
* @OA\Property(property="estimate_people", type="string", description="评估人"),
* @OA\Property(property="estimate_time", type="string", description="评估时间"),
* @OA\Property(property="created_at", type="string", description="创建时间"),
* )
*/
public function transform(BusinessOpportunity $business_opportunity)
{
$return = [
'id','customer_id', 'product_type','product_type_text', 'title', 'demand_doc','demand_doc_full_url', 'customer_desire_time', 'customer_expect_money',
'expect_date', 'estimate_status','estimate_status_text', 'estimate_hour', 'estimate_price', 'estimate_people', 'estimate_time',
'created_at',
];
$return = Helper::mapAttr($business_opportunity,$return);
return $return;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/13
* Time: 11:12
*/
namespace Modules\Customers\Http\Transformer;
use Modules\Admin\Http\Utils\Helper;
use Modules\Customers\Entities\Customer;
class CustomerTransformer extends BaseTransformer
{
public function __construct()
{
parent::__construct();
}
/**
* @OA\Schema(
* description="用户信息",
* type="object",
* schema="Customer",
* @OA\Property(property="id", type="integer", description="ID"),
* @OA\Property(property="name", type="string", description="客户名称"),
* @OA\Property(property="company", type="string", description="公司名称"),
* @OA\Property(property="industry", type="string", description="行业"),
* @OA\Property(property="department", type="string", description="部门"),
* @OA\Property(property="duties", type="string", description="职业"),
* @OA\Property(property="tel_phone", type="string", description="电话"),
* @OA\Property(property="mobile_phone", type="string", description="手机号码"),
* @OA\Property(property="wechat", type="string", description="微信号"),
* @OA\Property(property="dy", type="string", description="抖音号"),
* @OA\Property(property="email", type="string", description="邮箱"),
* @OA\Property(property="province", type="string", description="省"),
* @OA\Property(property="city", type="string", description="市"),
* @OA\Property(property="area", type="string", description="区"),
* @OA\Property(property="address", type="string", description="地址"),
* @OA\Property(property="follow_status", type="string", description="跟进状态"),
* @OA\Property(property="from", type="string", description="客户来源"),
* @OA\Property(property="type", type="string", description="客户类型"),
* @OA\Property(property="founder", type="string", description="创建者"),
* @OA\Property(property="owner", type="string", description="持有者"),
* @OA\Property(property="business_license", type="string", description="营业执照"),
* @OA\Property(property="identity", type="string", description="身份证"),
* @OA\Property(property="bank_account", type="string", description="银行账户"),
* @OA\Property(property="created_at", type="string", description="注册时间"),
* )
*/
public function transform(Customer $customer)
{
$return = [
'id','name','company','industry', 'department', 'duties', 'tel_phone', 'mobile_phone',
'wechat','dy','email', 'province', 'city', 'area', 'address','follow_status','follow_status_text',
'from','from_text','type','type_text','founder', 'owner', 'business_license', 'identity', 'bank_account',
'created_at',
];
$return = Helper::mapAttr($customer,$return);
return $return;
}
}
<?php
namespace Modules\Customers\Providers;
use Illuminate\Support\ServiceProvider;
class CustomersServiceProvider extends ServiceProvider
{
/**
* @var string $moduleName
*/
protected $moduleName = 'Customers';
/**
* @var string $moduleNameLower
*/
protected $moduleNameLower = 'customers';
/**
* Boot the application events.
*
* @return void
*/
public function boot()
{
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations'));
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->register(RouteServiceProvider::class);
}
/**
* Register config.
*
* @return void
*/
protected function registerConfig()
{
$this->publishes([
module_path($this->moduleName, 'Config/config.php') => config_path($this->moduleNameLower . '.php'),
], 'config');
$this->mergeConfigFrom(
module_path($this->moduleName, 'Config/config.php'), $this->moduleNameLower
);
}
/**
* Register views.
*
* @return void
*/
public function registerViews()
{
$viewPath = resource_path('views/modules/' . $this->moduleNameLower);
$sourcePath = module_path($this->moduleName, 'Resources/views');
$this->publishes([
$sourcePath => $viewPath
], ['views', $this->moduleNameLower . '-module-views']);
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
}
/**
* Register translations.
*
* @return void
*/
public function registerTranslations()
{
$langPath = resource_path('lang/modules/' . $this->moduleNameLower);
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
$this->loadJsonTranslationsFrom($langPath);
} else {
$this->loadTranslationsFrom(module_path($this->moduleName, 'Resources/lang'), $this->moduleNameLower);
$this->loadJsonTranslationsFrom(module_path($this->moduleName, 'Resources/lang'));
}
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [];
}
private function getPublishableViewPaths(): array
{
$paths = [];
foreach (config('view.paths') as $path) {
if (is_dir($path . '/modules/' . $this->moduleNameLower)) {
$paths[] = $path . '/modules/' . $this->moduleNameLower;
}
}
return $paths;
}
}
<?php
namespace Modules\Customers\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* The module namespace to assume when generating URLs to actions.
*
* @var string
*/
protected $moduleNamespace = 'Modules\Customers\Http\Controllers';
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*
* @return void
*/
public function boot()
{
parent::boot();
}
/**
* Define the routes for the application.
*
* @return void
*/
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->moduleNamespace)
->group(module_path('Customers', '/Routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*
* @return void
*/
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->moduleNamespace)
->group(module_path('Customers', '/Routes/api.php'));
}
}
@extends('customers::layouts.master')
@section('content')
<h1>Hello World</h1>
<p>
This view is loaded from module: {!! config('customers.name') !!}
</p>
@endsection
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Module Customers</title>
{{-- Laravel Vite - CSS File --}}
{{-- {{ module_vite('build-customers', 'Resources/assets/sass/app.scss') }} --}}
</head>
<body>
@yield('content')
{{-- Laravel Vite - JS File --}}
{{-- {{ module_vite('build-customers', 'Resources/assets/js/app.js') }} --}}
</body>
</html>
<?php
use Illuminate\Http\Request;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
$api = app('Dingo\Api\Routing\Router');
$api->version('v1', [
'namespace' => 'Modules\Customers\Http\Controllers',
'prefix' => 'api/customer',
], function ($api) {
$api->group(['middleware' => ['api.auth', 'admin.permission', 'admin.log_operation']], function ($api) {
###我的客户
#客户列表
$api->get('private/list', 'PrivateCustomersController@list')->name('customer.private.list');
#新增客户
$api->post('private/add', 'PrivateCustomersController@add')->name('customer.private.add');
#批量导入客户
$api->post('private/add_import', 'PrivateCustomersController@addImport')->name('customer.private.add_import');
#编辑客户-基本信息
$api->put('private/{id}/edit', 'PrivateCustomersController@edit')->name('customer.private.edit');
#编辑客户-私密资料
$api->put('private/{id}/edit_private', 'PrivateCustomersController@editPrivate')->name('customer.private.edit_private');
#客户信息
$api->get('private/{id}/show', 'PrivateCustomersController@show')->name('customer.private.show');
#写跟进
$api->put('private/{id}/follow', 'PrivateCustomersController@updateFollowStatus')->name('customer.private.follow');
#退回公海
$api->put('private/back_public', 'PrivateCustomersController@backPublic')->name('customer.private.back_public');
#数据字段
$api->get('private/data_maps', 'PrivateCustomersController@dataMaps')->name('customer.private.data_maps');
###公海客户
#客户列表
$api->get('public/list', 'PublicCustomersController@list')->name('customer.public.list');
#新增客户
$api->post('public/add', 'PublicCustomersController@add')->name('customer.public.add');
#批量导入客户
$api->post('public/add_import', 'PublicCustomersController@addImport')->name('customer.public.add_import');
#编辑客户-基本信息
$api->put('public/{id}/edit', 'PublicCustomersController@edit')->name('customer.public.edit');
#编辑客户-私密资料
$api->put('public/{id}/edit_private', 'PublicCustomersController@editPrivate')->name('customer.public.edit_private');
#客户信息
$api->get('public/{id}/show', 'PublicCustomersController@show')->name('customer.public.show');
#写跟进
$api->put('public/{id}/follow', 'PublicCustomersController@updateFollowStatus')->name('customer.public.follow');
#退回公海
$api->put('public/receive_private', 'PublicCustomersController@receivePrivate')->name('customer.public.receive_private');
#数据字段
$api->get('public/data_maps', 'PublicCustomersController@dataMaps')->name('customer.public.data_maps');
###商机
#商机列表
$api->get('opportunity/list', 'BusinessOpportunityController@list')->name('customer.opportunity.list');
#新增商机
$api->post('opportunity/add', 'BusinessOpportunityController@add')->name('customer.opportunity.add');
#编辑商机
$api->put('opportunity/{id}/edit', 'BusinessOpportunityController@edit')->name('customer.opportunity.edit');
#商机信息
$api->get('opportunity/{id}/show', 'BusinessOpportunityController@show')->name('customer.opportunity.show');
#数据字段
$api->get('opportunity/data_maps', 'BusinessOpportunityController@dataMaps')->name('customer.opportunity.data_maps');
});
});
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::prefix('customers')->group(function() {
Route::get('/', 'CustomersController@index');
});
{
"name": "nwidart/customers",
"description": "",
"authors": [
{
"name": "Nicolas Widart",
"email": "n.widart@gmail.com"
}
],
"extra": {
"laravel": {
"providers": [],
"aliases": {
}
}
},
"autoload": {
"psr-4": {
"Modules\\Customers\\": ""
}
}
}
{
"name": "Customers",
"alias": "customers",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\Customers\\Providers\\CustomersServiceProvider"
],
"files": []
}
{
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^0.21.4",
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"laravel-vite-plugin": "^0.6.0",
"lodash": "^4.17.21",
"postcss": "^8.3.7",
"vite": "^3.0.9"
}
}
const dotenvExpand = require('dotenv-expand');
dotenvExpand(require('dotenv').config({ path: '../../.env'/*, debug: true*/}));
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
build: {
outDir: '../../public/build-customers',
emptyOutDir: true,
manifest: true,
},
plugins: [
laravel({
publicDirectory: '../../public',
buildDirectory: 'build-customers',
input: [
__dirname + '/Resources/assets/sass/app.scss',
__dirname + '/Resources/assets/js/app.js'
],
refresh: true,
}),
],
});
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class Test extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'Test';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*/
public function handle()
{
$data = [
[
'name' => '朱招明',
'company' => '圣马歌',
'industry' => '互联网',
'department' => '技术部',
'duties' => 'php开发',
'follow_status' => '初访',
'from' => '抖音',
'type' => '个人',
],
[
'name' => '朱招明',
'company' => '圣马歌',
'industry' => '互联网',
'department' => '技术部',
'duties' => 'php开发',
'follow_status' => '初访',
'from' => '抖音',
'type' => '个人1',
],
];
//var_dump(json_encode(['data'=>$data]));
var_dump(json_encode(['id'=>[8,9]]));
}
}
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
"api-ecosystem-for-laravel/dingo-api": "4.1.*", "api-ecosystem-for-laravel/dingo-api": "4.1.*",
"darkaonline/l5-swagger": "^8.5", "darkaonline/l5-swagger": "^8.5",
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"kalnoy/nestedset": "^6.0",
"laravel/framework": "10.*", "laravel/framework": "10.*",
"laravel/tinker": "^2.8", "laravel/tinker": "^2.8",
"namshi/jose": "^7.2", "namshi/jose": "^7.2",
......
...@@ -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": "c14b94053584d7feae995e94d306c004", "content-hash": "8aa861d1842f309ab3f04afd77002f7a",
"packages": [ "packages": [
{ {
"name": "api-ecosystem-for-laravel/dingo-api", "name": "api-ecosystem-for-laravel/dingo-api",
...@@ -1318,17 +1318,80 @@ ...@@ -1318,17 +1318,80 @@
"time": "2023-08-27T10:19:19+00:00" "time": "2023-08-27T10:19:19+00:00"
}, },
{ {
"name": "kalnoy/nestedset",
"version": "v6.0.2",
"source": {
"type": "git",
"url": "https://github.com/lazychaser/laravel-nestedset.git",
"reference": "2d5c99fe1bfbaa4004f8d6fb24475f7ff88bb526"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lazychaser/laravel-nestedset/zipball/2d5c99fe1bfbaa4004f8d6fb24475f7ff88bb526",
"reference": "2d5c99fe1bfbaa4004f8d6fb24475f7ff88bb526",
"shasum": ""
},
"require": {
"illuminate/database": "^7.0|^8.0|^9.0|^10.0",
"illuminate/events": "^7.0|^8.0|^9.0|^10.0",
"illuminate/support": "^7.0|^8.0|^9.0|^10.0",
"php": "^7.2.5|^8.0"
},
"require-dev": {
"phpunit/phpunit": "7.*|8.*|9.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "v5.0.x-dev"
},
"laravel": {
"providers": [
"Kalnoy\\Nestedset\\NestedSetServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Kalnoy\\Nestedset\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Alexander Kalnoy",
"email": "lazychaser@gmail.com"
}
],
"description": "Nested Set Model for Laravel 5.7 and up",
"keywords": [
"database",
"hierarchy",
"laravel",
"nested sets",
"nsm"
],
"support": {
"issues": "https://github.com/lazychaser/laravel-nestedset/issues",
"source": "https://github.com/lazychaser/laravel-nestedset/tree/v6.0.2"
},
"time": "2023-02-16T14:41:24+00:00"
},
{
"name": "laravel/framework", "name": "laravel/framework",
"version": "v10.29.0", "version": "v10.30.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "2d002849a16ad131110a50cbea4d64dbb78515a3" "reference": "7a2da50258c4d0f693b738d3f3c69b2693aea6c1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/2d002849a16ad131110a50cbea4d64dbb78515a3", "url": "https://api.github.com/repos/laravel/framework/zipball/7a2da50258c4d0f693b738d3f3c69b2693aea6c1",
"reference": "2d002849a16ad131110a50cbea4d64dbb78515a3", "reference": "7a2da50258c4d0f693b738d3f3c69b2693aea6c1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
...@@ -1517,20 +1580,20 @@ ...@@ -1517,20 +1580,20 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2023-10-24T13:48:53+00:00" "time": "2023-11-01T13:52:17+00:00"
}, },
{ {
"name": "laravel/prompts", "name": "laravel/prompts",
"version": "v0.1.12", "version": "v0.1.13",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/prompts.git", "url": "https://github.com/laravel/prompts.git",
"reference": "b35f249028c22016e45e48626e19e5d42fd827ff" "reference": "e1379d8ead15edd6cc4369c22274345982edc95a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/prompts/zipball/b35f249028c22016e45e48626e19e5d42fd827ff", "url": "https://api.github.com/repos/laravel/prompts/zipball/e1379d8ead15edd6cc4369c22274345982edc95a",
"reference": "b35f249028c22016e45e48626e19e5d42fd827ff", "reference": "e1379d8ead15edd6cc4369c22274345982edc95a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
...@@ -1572,9 +1635,9 @@ ...@@ -1572,9 +1635,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/laravel/prompts/issues", "issues": "https://github.com/laravel/prompts/issues",
"source": "https://github.com/laravel/prompts/tree/v0.1.12" "source": "https://github.com/laravel/prompts/tree/v0.1.13"
}, },
"time": "2023-10-18T14:18:57+00:00" "time": "2023-10-27T13:53:59+00:00"
}, },
{ {
"name": "laravel/serializable-closure", "name": "laravel/serializable-closure",
...@@ -2873,16 +2936,16 @@ ...@@ -2873,16 +2936,16 @@
}, },
{ {
"name": "nwidart/laravel-modules", "name": "nwidart/laravel-modules",
"version": "10.0.2", "version": "10.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nWidart/laravel-modules.git", "url": "https://github.com/nWidart/laravel-modules.git",
"reference": "ef67a7367223ab96539136116d69405d1c21c321" "reference": "786da1e6dfa2df6caa8718acb9c37a8fe94595b3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/ef67a7367223ab96539136116d69405d1c21c321", "url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/786da1e6dfa2df6caa8718acb9c37a8fe94595b3",
"reference": "ef67a7367223ab96539136116d69405d1c21c321", "reference": "786da1e6dfa2df6caa8718acb9c37a8fe94595b3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
...@@ -2942,15 +3005,19 @@ ...@@ -2942,15 +3005,19 @@
], ],
"support": { "support": {
"issues": "https://github.com/nWidart/laravel-modules/issues", "issues": "https://github.com/nWidart/laravel-modules/issues",
"source": "https://github.com/nWidart/laravel-modules/tree/10.0.2" "source": "https://github.com/nWidart/laravel-modules/tree/10.0.3"
}, },
"funding": [ "funding": [
{ {
"url": "https://github.com/dcblogdev",
"type": "github"
},
{
"url": "https://github.com/nwidart", "url": "https://github.com/nwidart",
"type": "github" "type": "github"
} }
], ],
"time": "2023-10-18T19:14:29+00:00" "time": "2023-11-02T17:47:33+00:00"
}, },
{ {
"name": "php-open-source-saver/jwt-auth", "name": "php-open-source-saver/jwt-auth",
......
{ {
"Admin": true "Admin": true,
"Customers": true
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment