diff --git a/webman/app/controller/AreaController.php b/webman/app/controller/AreaController.php new file mode 100644 index 0000000..7ba730d --- /dev/null +++ b/webman/app/controller/AreaController.php @@ -0,0 +1,42 @@ +getRegions($parentId, $level); + return json($list); + } + + + + function getRegions($parentId = null, $level = 1) { + $regions = []; + + $where= array(); + if(!Util::isEmpty($parentId)){ + $where['parent_id'] = $parentId; + } + $where['level'] = $level; + $results = Area::where($where)->get(); + + foreach ($results as $row) { +// $row['level'] = $level; // 添加层级信息 +// $regions = array_merge($regions, $this->getRegions($row['id'], $level + 1)); // 递归调用 + $row['children'] = $this->getRegions($row['id'], $row['level'] + 1); + $regions[] = $row; + } + + return $regions; + } + +} \ No newline at end of file diff --git a/webman/app/controller/CarTypeController.php b/webman/app/controller/CarTypeController.php new file mode 100644 index 0000000..7a69582 --- /dev/null +++ b/webman/app/controller/CarTypeController.php @@ -0,0 +1,21 @@ +toArray(); - return json($list); + $grade = []; + foreach (Constants::GRADE as $key => $value) { + $grade[] = [ + 'status' => $key, + 'text' => $value, + ]; + } + return json($grade); } + /** + * 客户偏好 + * @param Request $request + * @return \support\Response + */ + public function getCarType(Request $request) + { + $grade = []; + foreach (Constants::GRADE as $key => $value) { + $grade[] = [ + 'status' => $key, + 'text' => $value, + ]; + } + return json($grade); + } + + /** + * 客户列表 + * @param Request $request + * @return \support\Response + */ + public function list(Request $request) + { + + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + + $where = []; + + $userId = $request->user['id']; + if (Util::isEmpty($userId)) { + return Util::fail(['user_id' => $userId], trans('user_none')); + } + if ($request->user['role'] != 1) { + $where['user_id'] = $userId; + } + + // 执行分页查询 + $data = Customer::where($where) + ->orderBy('id', 'desc') + ->paginate($perPage, ['*'], 'page', $page); + + foreach ($data->items() as &$value) { + $value = Customer::getCustomer($value); + } + + return Util::page($data); + } + + /** + * 客户详情 + * @param Request $request + * @return \support\Response + */ + public function detail(Request $request) + { + $id = Util::getParam($request, 'id'); + if (Util::isEmpty($id)) { + return Util::fail([], 'id' . trans('not_null')); + } + + $res = Customer::select('id', 'user_id', 'grade', 'channel_id','car_type_id', 'country_id', 'magnitude', 'email', 'phone', 'WhatsApp', 'contacts', 'describe') + ->where('id', $id) + ->first(); + if ($res) { + $res->toArray(); + } else { + return Util::fail([], '记录不存在'); + } + + $res = Customer::getCustomer($res); + + return Util::success($res); + } + + /** + * 客户录入 + * @param Request $request + * @return \support\Response + */ + public function save(Request $request) + { + $id = Util::getParam($request, 'id'); + $channel_id = Util::getParam($request, 'channel_id'); + if (Util::isEmpty($channel_id)) { + return Util::fail([], 'channel_id' . trans('not_null')); + } + $country_id = Util::getParam($request, 'country_id'); + if (Util::isEmpty($country_id)) { +// return Util::fail([],'country_id'.trans('not_null')); + } + $car_type_id = Util::getParam($request, 'car_type_id'); + if (Util::isEmpty($car_type_id)) { + return Util::fail([], 'car_type_id' . trans('not_null')); + } + $contacts = Util::getParam($request, 'contacts'); + $email = Util::getParam($request, 'email'); + $phone = Util::getParam($request, 'phone'); + if (Util::isEmpty($contacts) && Util::isEmpty($email) && Util::isEmpty($phone)) { + return Util::fail([], 'country_id' . trans('not_null')); + } + + $data = [ + 'user_id' => $request->user['id'], + 'grade' => Util::getParam($request, 'grade', 0), + 'channel_id' => $channel_id, + 'country_id' => $country_id, + 'car_type_id' => $car_type_id, + 'magnitude' => Util::getParam($request, 'magnitude', 0), + 'email' => $email, + 'phone' => $phone, + 'WhatsApp' => Util::getParam($request, 'WhatsApp',''), + 'contacts' => $contacts, + 'describe' => Util::getParam($request, 'describe'), + 'lat' => Util::getParam($request, 'lat',0), + 'lng' => Util::getParam($request, 'lng',0), + 'address' => Util::getParam($request, 'address',''), + ]; + + if (Util::isEmpty($id)) { + $res = Customer::create($data); + } else { + $res = Customer::where('id', $id) + ->update($data); +// Log::info('update', ['res' => $res]); + (!$res)?: $res=Customer::find($id)->toArray(); + } + + if ($res) { + return Util::success($res); + } else { + return Util::fail($res); + } + } } \ No newline at end of file diff --git a/webman/app/controller/FollowController.php b/webman/app/controller/FollowController.php new file mode 100644 index 0000000..0ec5b25 --- /dev/null +++ b/webman/app/controller/FollowController.php @@ -0,0 +1,153 @@ + $value) { + $grade[] = [ + 'status' => $key, + 'text' => $value, + ]; + } + return Util::success($grade); + } + + + /** + * 跟进列表 + * @param Request $request + * @return \support\Response + */ + public function list(Request $request) + { + + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + + //客户id + $customer_id = Util::getParam($request,'customer_id'); + if(Util::isEmpty($customer_id)){ + return Util::fail([],'customer_id'.trans('not_null')); + } + + $where = []; + $where['customer_id'] = $customer_id; + + //用户角色 + $userId = $request->user['id']; + if(Util::isEmpty($userId)){ + return Util::fail(['user_id'=>$userId],trans('user_none')); + } + if($request->user['role']!=1){ + $where['user_id'] = $userId; + } + + //跟进id + $id = Util::getParam($request,'id'); + if(!Util::isEmpty($id)){ + $where['id'] = $id; + } + + // 执行分页查询 + $data = Follow::where($where) + ->orderBy('id', 'desc') + ->paginate($perPage, ['*'], 'page', $page); + + foreach ($data->items() as &$value){ + $value = Follow::getFollow($value); + } + + return Util::page($data); + } + + /** + * 跟进详情 + * @param Request $request + * @return \support\Response + */ + public function detail(Request $request) + { + //跟进id + $id = Util::getParam($request,'id'); + if(Util::isEmpty($id)){ + return Util::fail([],'id'.trans('not_null')); + } + + $res = Follow::select('id','user_id','customer_id','type','picture','remark','audio','audio_text','lat','lng','address') + ->where('id',$id) + ->first(); + if($res){ + $res->toArray(); + }else{ + return Util::fail([],'记录不存在'); + } + + $res = Follow::getFollow($res); + + return Util::success($res); + } + + /** + * 客户录入 + * @param Request $request + * @return \support\Response + */ + public function save(Request $request) + { + $customer_id = Util::getParam($request,'customer_id'); + if(Util::isEmpty($customer_id)){ + return Util::fail([],'customer_id'.trans('not_null')); + } + $type = Util::getParam($request,'type'); + if(Util::isEmpty($type)){ + return Util::fail([],'type'.trans('not_null')); + } + $picture = Util::getParam($request,'picture'); + if(Util::isEmpty($picture)){ + return Util::fail([],'picture'.trans('not_null')); + } + + $data = [ + 'user_id'=>$request->user['id'], + 'customer_id'=>$customer_id, + 'type'=>$type, + 'picture'=>$picture, + 'remark'=>Util::getParam($request,'remark',''), + 'audio'=>Util::getParam($request,'audio',''), + 'audio_text'=>Util::getParam($request,'audio',''), + 'lat'=>Util::getParam($request,'lat'), + 'lng'=>Util::getParam($request,'lng'), + 'address'=>Util::getParam($request,'address'), + ]; + + $res = Follow::create($data); + + $customer = Customer::find($customer_id); + $customer->follow_last = $res->created_at; + $customer->save(); + + if($res){ + return Util::success($res); + }else{ + return Util::fail($res); + } + } + +} \ No newline at end of file diff --git a/webman/app/controller/UserController.php b/webman/app/controller/UserController.php index 18f6e01..893aa7d 100644 --- a/webman/app/controller/UserController.php +++ b/webman/app/controller/UserController.php @@ -2,14 +2,61 @@ namespace app\controller; +use app\model\User; +use app\util\JwtUtil; +use app\util\Util; +use support\Redis; use support\Request; class UserController { + /** + * 不需要登录的方法 + */ + protected $noNeedLogin = ['login']; public function login(Request $request) { - return json([]); +// Util::isEmpty($request->post('email')); + $email = Util::getParam($request,'email'); + if(Util::isEmpty($email)){ + return Util::fail([],'email'.trans('not_null')); + } +// Util::isEmpty($request->post('password')); + $password = Util::getParam($request,'password'); + if(Util::isEmpty($password)){ + return Util::fail([],'password'.trans('not_null')); + } + $user = User::select(['id','name','sex','role','avatar','email','password']) + ->where('status',0) + ->where('email',$request->post('email')) + ->first(); + if(!$user){ + return Util::fail(['user'=>$user],trans('user_none')); + } + $user = $user->toArray(); + + $userPassword = $user['password']; + + //加密 + $hashedPassword = password_hash($password, PASSWORD_DEFAULT); + + //验证密码 + if (!password_verify($userPassword, $hashedPassword)) { + return Util::fail([],trans('password_error')); + } + $userId = $user['id']; // 实际从数据库获取 + + + Redis::set('user_'.$userId, $user); + + //密码验证成功后加密生成 Token + $token = JwtUtil::generateToken($userId); + $result = $user; + unset($result['password']); + $result['token'] = $token; + + return Util::success($result,trans('login_success')); } diff --git a/webman/app/middleware/AuthMiddleware.php b/webman/app/middleware/AuthMiddleware.php new file mode 100644 index 0000000..834f80c --- /dev/null +++ b/webman/app/middleware/AuthMiddleware.php @@ -0,0 +1,84 @@ +path() === '/api/login') { +// return $handler($request); +// } + // 通过反射获取控制器哪些方法不需要登录 + $controller = new ReflectionClass($request->controller); + $noNeedLogin = $controller->getDefaultProperties()['noNeedLogin'] ?? []; + + $isLogin = !in_array($request->action, $noNeedLogin); + // 访问的方法需要登录 +// if ($isLogin) { +// // 拦截请求,返回一个重定向响应,请求停止向洋葱芯穿越 +// throw new BusinessException('请先登录', 302); +// } + + // 从 Header 获取 Token + $token = $request->header('Authorization'); + + //需要登录并且未提供token + if ($isLogin && (!$token || !str_starts_with($token, 'Bearer '))) { + throw new BusinessException('请先登录', 302); +// throw new BusinessException('未提供 Token'.$isLogin, 401); + } + $token = substr($token, 7); + try { + // 验证 Token 并获取用户ID + $decoded = JwtUtil::verifyToken($token); + + $userId = $decoded->sub; + + $user = User::select(['id','name','sex','role','avatar','email','password']) + ->find($userId); + if(!$user){ + return Util::fail(['user'=>$user],trans('user_none')); + } + $user = $user->toArray(); + + // 将用户ID存入请求对象,供后续使用 +// $request->user = ['id' => $userId]; + $request->user = $user; + return $handler($request); + } catch (BusinessException $e) { + return json(['code' => 401, 'msg' => $e->getMessage()]); + } + } +} \ No newline at end of file diff --git a/webman/app/model/Area.php b/webman/app/model/Area.php new file mode 100644 index 0000000..dd5adbb --- /dev/null +++ b/webman/app/model/Area.php @@ -0,0 +1,25 @@ +select('id','name','status')->where('status',0)->toArray(); + return $list; + } +} \ No newline at end of file diff --git a/webman/app/model/Customer.php b/webman/app/model/Customer.php index 8608958..528a5f2 100644 --- a/webman/app/model/Customer.php +++ b/webman/app/model/Customer.php @@ -3,7 +3,10 @@ namespace app\model; -use Illuminate\Database\Eloquent\Model; +use app\util\Util; +use config\constants\Constants; +use support\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Customer extends Model { @@ -21,10 +24,51 @@ class Customer extends Model */ protected $primaryKey = 'id'; + //设置黑名单 + protected $guarded = ['id','created_at','updated_at']; + + // 指定日期字段存储格式为时间戳 + protected $dateFormat = 'U'; + /** * Indicates if the model should be timestamped. * * @var bool */ - public $timestamps = false; + public $timestamps = true; + + protected $casts = [ +// 'updated_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式 +// 'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式 + 'updated_at' => 'timestamp', // 指定序列化格式 + 'created_at' => 'timestamp', // 指定序列化格式 + ]; + + public static function getCustomer($customer) + { + $customer['grade_txt'] = Constants::GRADE[$customer['grade']]; + $customer['magnitude_txt'] = Constants::MAGNITUDE[$customer['magnitude']]; + + if ($customer['grade']<=2) { + $customer['follow'] = 0; + $customer['follow_txt'] = '跟进中'; + }elseif ($customer['grade']<=5) { + $customer['follow'] = 1; + $customer['follow_txt'] = '已成交'; + }else{ + $customer['follow'] = 2; + $customer['follow_txt'] = '已流失'; + } + + $where = [ + 'customer_id' => $customer['id'] + ]; + $begin_follow = Follow::select('id','created_at','updated_at') + ->where($where) + ->min('created_at'); + $customer['begin_follow'] = $begin_follow; +// $customer['last_follow'] = $last_follow; + + return $customer; + } } \ No newline at end of file diff --git a/webman/app/model/Follow.php b/webman/app/model/Follow.php new file mode 100644 index 0000000..09993a0 --- /dev/null +++ b/webman/app/model/Follow.php @@ -0,0 +1,51 @@ + 'datetime:Y-m-d H:i:s', // 指定序列化格式 +// 'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式 + 'updated_at' => 'timestamp', // 指定序列化格式 + 'created_at' => 'timestamp', // 指定序列化格式 + ]; + + public static function getFollow($follow) + { + $follow['type_txt'] = Constants::FOLLOW[$follow['type']]; + return $follow; + } +} \ No newline at end of file diff --git a/webman/app/model/User.php b/webman/app/model/User.php new file mode 100644 index 0000000..28fe73e --- /dev/null +++ b/webman/app/model/User.php @@ -0,0 +1,40 @@ +select(['id','name','sex','role','avatar','email','password']) + ->where('status',0) + ->toArray(); + return $user; + } +} \ No newline at end of file diff --git a/webman/app/util/JwtUtil.php b/webman/app/util/JwtUtil.php new file mode 100644 index 0000000..f28f5da --- /dev/null +++ b/webman/app/util/JwtUtil.php @@ -0,0 +1,50 @@ + 'webman', // 签发者 + 'aud' => 'client', // 接收方 + 'iat' => time(), // 签发时间 + 'exp' => time() + $config['expire'], // 过期时间 + 'sub' => $userId // 用户标识 + ]; + return JWT::encode($payload, $config['secret'], $config['algorithm']); + } + + /** + * 验证并解析 Token + * @param string $token + * @return object + * @throws BusinessException + */ + public static function verifyToken(string $token) + { + $config = config('jwt'); + try { + return JWT::decode($token, new Key($config['secret'], $config['algorithm'])); + } catch (ExpiredException $e) { + throw new BusinessException('Token 已过期', 401); + } catch (SignatureInvalidException $e) { + throw new BusinessException('Token 无效', 401); + } catch (\Exception $e) { + throw new BusinessException('鉴权失败', 401); + } + } +} \ No newline at end of file diff --git a/webman/app/util/Util.php b/webman/app/util/Util.php new file mode 100644 index 0000000..e3ddf23 --- /dev/null +++ b/webman/app/util/Util.php @@ -0,0 +1,83 @@ +input($param,$default); + return $param; + } + + /** + * 失败 + */ + public static function fail($data = [],$message = '', $code = '500') + { + $result = [ + 'code' => $code, + 'message' => $message, + 'data' => $data + ]; + return json($result); + } + + /** + * 成功 + */ + public static function success($data = [],$message = '', $code = '200') + { + $result = [ + 'code' => $code, + 'message' => $message, + 'data' => $data + ]; + return json($result); + } + + /** + * 分页查询返回 + */ + public static function page($data,$message = '', $code = '200') + { + $result = [ + 'code' => $code, + 'message' => $message + ]; + + $result['data'] = [ + 'list' => $data->items(), // 当前页数据 + 'total' => $data->total(), // 总记录数 + 'current_page' => $data->currentPage(), + 'per_page' => $data->perPage(), + 'last_page' => $data->lastPage() + ]; + return json($result); + } + + +} \ No newline at end of file diff --git a/webman/composer.json b/webman/composer.json index b5b2dfd..f6e38e9 100644 --- a/webman/composer.json +++ b/webman/composer.json @@ -30,7 +30,11 @@ "illuminate/events": "^11.44", "webman/database": "^2.1", "illuminate/pagination": "^11.44", - "symfony/var-dumper": "^7.2" + "symfony/var-dumper": "^7.2", + "webman/redis": "^2.1", + "symfony/translation": "^7.2", + "firebase/php-jwt": "^6.11", + "illuminate/database": "^11.44" }, "suggest": { "ext-event": "For better performance. " diff --git a/webman/composer.lock b/webman/composer.lock index 77dbb15..fecdec2 100644 --- a/webman/composer.lock +++ b/webman/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4e20de5533cd343aeb926809636ce49a", + "content-hash": "f3ffc56f1691457e45c7053ac636e4be", "packages": [ { "name": "brick/math", @@ -226,6 +226,69 @@ ], "time": "2024-02-18T20:23:39+00:00" }, + { + "name": "firebase/php-jwt", + "version": "v6.11.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/8f718f4dfc9c5d5f0c994cdfd103921b43592712", + "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.4", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^2.0||^3.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.11.0" + }, + "time": "2025-01-23T05:11:06+00:00" + }, { "name": "illuminate/bus", "version": "v11.44.1", @@ -482,16 +545,16 @@ }, { "name": "illuminate/database", - "version": "v11.44.1", + "version": "v11.44.2", "source": { "type": "git", "url": "https://github.com/illuminate/database.git", - "reference": "131dcdfcc6c838115d5e58c77d4fe816f735dff8" + "reference": "a63391e43a6d38beb40fa21fc020d16c9b5352ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/database/zipball/131dcdfcc6c838115d5e58c77d4fe816f735dff8", - "reference": "131dcdfcc6c838115d5e58c77d4fe816f735dff8", + "url": "https://api.github.com/repos/illuminate/database/zipball/a63391e43a6d38beb40fa21fc020d16c9b5352ea", + "reference": "a63391e43a6d38beb40fa21fc020d16c9b5352ea", "shasum": "" }, "require": { @@ -547,7 +610,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-02-21T13:01:45+00:00" + "time": "2025-03-12T14:13:54+00:00" }, { "name": "illuminate/events", @@ -748,6 +811,60 @@ }, "time": "2025-02-17T16:02:42+00:00" }, + { + "name": "illuminate/redis", + "version": "v11.44.1", + "source": { + "type": "git", + "url": "https://github.com/illuminate/redis.git", + "reference": "21eb42b3d3271b3365a3685cb552b31cda1de255" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/redis/zipball/21eb42b3d3271b3365a3685cb552b31cda1de255", + "reference": "21eb42b3d3271b3365a3685cb552b31cda1de255", + "shasum": "" + }, + "require": { + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" + }, + "suggest": { + "ext-redis": "Required to use the phpredis connector (^4.0|^5.0|^6.0).", + "predis/predis": "Required to use the predis connector (^2.3)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Redis\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Redis package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2025-02-17T15:53:37+00:00" + }, { "name": "illuminate/support", "version": "v11.44.1", @@ -2010,6 +2127,42 @@ }, "time": "2025-02-24T07:14:57+00:00" }, + { + "name": "webman/redis", + "version": "v2.1.2", + "source": { + "type": "git", + "url": "https://github.com/webman-php/redis.git", + "reference": "83893f0931e07906ba9dbf976126ad8338f40624" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webman-php/redis/zipball/83893f0931e07906ba9dbf976126ad8338f40624", + "reference": "83893f0931e07906ba9dbf976126ad8338f40624", + "shasum": "" + }, + "require": { + "illuminate/redis": "^10.0 || ^11.0", + "workerman/webman-framework": "^2.1 || dev-master" + }, + "type": "library", + "autoload": { + "psr-4": { + "support\\": "src/support", + "Webman\\Redis\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Webman redis", + "support": { + "issues": "https://github.com/webman-php/redis/issues", + "source": "https://github.com/webman-php/redis/tree/v2.1.2" + }, + "time": "2025-02-14T11:36:24+00:00" + }, { "name": "workerman/coroutine", "version": "v1.1.3", diff --git a/webman/config/constants/Constants.php b/webman/config/constants/Constants.php new file mode 100644 index 0000000..f25eb25 --- /dev/null +++ b/webman/config/constants/Constants.php @@ -0,0 +1,43 @@ + '初步接触', + self::CUSTOMER_GRADE_COMMUNICATE => '需求沟通', + self::CUSTOMER_GRADE_PLAN => '方案推进', + self::CUSTOMER_GRADE_DEAL => '成交阶段', + self::CUSTOMER_GRADE_SALES => '售后阶段', + self::CUSTOMER_GRADE_LOSS => '停滞或流失', + ]; + + //客户重要性 + public const CUSTOMER_MAGNITUDE_INITIAL = 0; // 金牌商机 + public const CUSTOMER_MAGNITUDE_COMMUNICATE = 1; // 银牌商机 + public const CUSTOMER_MAGNITUDE_PLAN = 2; // 铜牌商机 + + public const MAGNITUDE = [ + self::CUSTOMER_MAGNITUDE_INITIAL => '金牌商机', + self::CUSTOMER_MAGNITUDE_COMMUNICATE => '银牌商机', + self::CUSTOMER_MAGNITUDE_PLAN => '铜牌商机', + ]; + + + //跟进类型 + public const CUSTOMER_FOLLOW_VISIT = 0; // 线下拜访 + public const CUSTOMER_FOLLOW_UP = 1; // 线上跟进 + + public const FOLLOW = [ + self::CUSTOMER_FOLLOW_VISIT => '线下拜访', + self::CUSTOMER_FOLLOW_UP => '线上跟进', + ]; +} \ No newline at end of file diff --git a/webman/config/database.php b/webman/config/database.php index 69eaac8..15c3a1c 100644 --- a/webman/config/database.php +++ b/webman/config/database.php @@ -9,12 +9,12 @@ return [ 'driver' => 'mysql', 'host' => '127.0.0.1', 'port' => 3306, - 'database' => 'root', + 'database' => 'xyh_crm', 'username' => 'root', - 'password' => '', + 'password' => 'root', 'unix_socket' => '', 'charset' => 'utf8', - 'collation' => 'utf8mb4_general_ci', + 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => null, @@ -27,7 +27,7 @@ return [ ], ], - 'sqlite' => [ + /*'sqlite' => [ 'driver' => 'sqlite', 'database' => '', 'prefix' => '', @@ -76,6 +76,6 @@ return [ 'idle_timeout' => 60, // 连接池中连接最大空闲时间,超时后会关闭回收,直到连接数为min_connections 'heartbeat_interval' => 50, // 连接池心跳检测时间,单位秒,建议小于60秒 ], - ], + ],*/ ], ]; \ No newline at end of file diff --git a/webman/config/jwt.php b/webman/config/jwt.php new file mode 100644 index 0000000..7c5ff73 --- /dev/null +++ b/webman/config/jwt.php @@ -0,0 +1,6 @@ + 'Hj3$kLm8NpQrStUvXwZ1y2C4D6E8G', // 替换为高强度的密钥 + 'algorithm' => 'HS256', // 加密算法 + 'expire' => 3600 * 24 * 7, // 过期时间(7天) +]; \ No newline at end of file diff --git a/webman/config/middleware.php b/webman/config/middleware.php index 8e964ed..05b2336 100644 --- a/webman/config/middleware.php +++ b/webman/config/middleware.php @@ -12,4 +12,9 @@ * @license http://www.opensource.org/licenses/mit-license.php MIT License */ -return []; \ No newline at end of file +return [ + // 全局中间件 + '' => [ + app\middleware\AuthMiddleware::class, + ] +]; \ No newline at end of file diff --git a/webman/config/redis.php b/webman/config/redis.php new file mode 100644 index 0000000..37c5f12 --- /dev/null +++ b/webman/config/redis.php @@ -0,0 +1,30 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'password' => '', + 'host' => '127.0.0.1', + 'port' => 6379, + 'database' => 0, + // Connection pool, supports only Swoole or Swow drivers. + 'pool' => [ + 'max_connections' => 5, + 'min_connections' => 1, + 'wait_timeout' => 3, + 'idle_timeout' => 60, + 'heartbeat_interval' => 50, + ], + ] +]; diff --git a/webman/config/translation.php b/webman/config/translation.php index 96589b2..f7790ec 100644 --- a/webman/config/translation.php +++ b/webman/config/translation.php @@ -16,10 +16,10 @@ * Multilingual configuration */ return [ - // Default language + // 默认语言 'locale' => 'zh_CN', - // Fallback language + // 回退语言,当前语言中无法找到翻译时则尝试使用回退语言中的翻译 'fallback_locale' => ['zh_CN', 'en'], // Folder where language files are stored 'path' => base_path() . '/resource/translations', -]; \ No newline at end of file +]; diff --git a/webman/resource/translations/zh_CN/messages.php b/webman/resource/translations/zh_CN/messages.php new file mode 100644 index 0000000..93229a6 --- /dev/null +++ b/webman/resource/translations/zh_CN/messages.php @@ -0,0 +1,11 @@ + '成功', + 'fail' => '成功', + 'login_success' => '登录成功', + 'password_error' => '密码错误', + 'user_none' => '用户不存在', + 'not_null' => '不能为空', + +]; \ No newline at end of file diff --git a/webman/start.php b/webman/start.php index 41ad7ef..2399638 100644 --- a/webman/start.php +++ b/webman/start.php @@ -2,4 +2,5 @@