feat : city

This commit is contained in:
2024-10-31 16:30:29 +08:00
parent 39b5df9f0a
commit ceeeea7c34
9 changed files with 534 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Cache\Redis\Common;
use App\Cache\Redis\RedisCache;
use App\Model\SystemCityConfig;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class CityCache
{
/**
* @var RedisCache
*/
#[Inject]
protected RedisCache $redis;
/**
* @var SystemCityConfig
*/
#[Inject]
protected SystemCityConfig $systemCityConfigModel;
/**
* 获取数据
* @param int $deep 0 = 省份 1 = 市 2 = 区 other = all
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws \RedisException
*/
public function getCityList(int $deep = -1): array
{
$type = match ($deep) {
1 => 'province',
2 => 'city',
3 => 'district',
default => 'all',
};
$key = CommonRedisKey::getSystemRegionList($type);
if ($this->redis->exists($key)) return json_decode($this->redis->get($key), true);
if ($type == 'all') {
$data = $this->systemCityConfigModel->getAll();
} else {
$data = $this->systemCityConfigModel->getListByDeep($deep);
}
$this->redis->set($key, json_encode($data));
return $data;
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Cache\Redis\Common;
class CommonRedisKey
{
/**
* @var $type
* @return string
*/
public static function getSystemRegionList($type = 'all')
{
return '__system:address:list:'.$type;
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Constants\Common;
class CityCode
{
/**
* 禁用
*/
const STATUS_DISABLE = 2;
/**
* 启用
*/
const STATUS_ENABLE = 1;
/**
* 删除
*/
const IS_DELETE = 2;
/**
* 不删除
*/
const IS_NOT_DELETE = 1;
}

View File

@@ -0,0 +1,81 @@
<?php
declare(strict_types=1);
namespace App\Controller\Admin;
use App\Controller\AbstractController;
use App\Middleware\Admin\JwtAuthMiddleware;
use App\Request\Admin\CityRequest;
use App\Service\Admin\System\CityService;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\Validation\Annotation\Scene;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use RedisException;
#[Controller(prefix: "admin/city")]
#[Middlewares([
JwtAuthMiddleware::class,
])]
class CityController extends AbstractController
{
/**
* @param CityRequest $request
* @return array
*/
#[RequestMapping(path: "add", methods: "POST")]
#[Scene(scene: "add")]
public function add(CityRequest $request): array
{
return (new CityService)->add();
}
/**
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws RedisException
*/
#[RequestMapping(path: "list", methods: "GET")]
#[Scene(scene: "list")]
public function list(): array
{
return (new CityService)->handle();
}
/**
* @return array
*/
#[RequestMapping(path: "edit", methods: "GET")]
#[Scene(scene: "edit")]
public function edit(): array
{
return (new CityService)->changeStatus();
}
/**
* @return array
*/
#[RequestMapping(path: "del", methods: "GET")]
#[Scene(scene: "del")]
public function delete(): array
{
return (new CityService)->delete();
}
/**
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws RedisException
*/
#[RequestMapping(path: "info", methods: "GET")]
#[Scene(scene: "info")]
public function info(): array
{
return (new CityService)->info();
}
}

61
app/Model/SystemCity.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace App\Model;
use App\Constants\Common\CityCode;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Model\Model;
/**
* @property int $id
* @property string $title
* @property int $status
* @property int $city_id
* @property int $province_id
* @property string $create_time
* @property string $update_time
* @property int $is_del
*/
class SystemCity extends Model
{
/**
* The table associated with the model.
*/
protected ?string $table = 'system_city';
/**
* The attributes that are mass assignable.
*/
protected array $fillable = [];
protected array $guarded = [];
/**
* The attributes that should be cast to native types.
*/
protected array $casts = ['id' => 'integer', 'status' => 'integer', 'city_id' => 'integer', 'province_id' => 'integer', 'is_del' => 'integer'];
const CREATED_AT = 'create_time';
const UPDATED_AT = 'update_time';
/**
* @param int $cityId
* @return Builder|\Hyperf\Database\Model\Model|null
*/
public function getInfoByCityId(int $cityId): \Hyperf\Database\Model\Model|Builder|null
{
return $this->where('city_id', $cityId)->where('is_del',CityCode::IS_NOT_DELETE)->first();
}
/**
* @param int $id
* @return Builder|\Hyperf\Database\Model\Model|null
*/
public function getInfoById(int $id): \Hyperf\Database\Model\Model|Builder|null
{
return $this->where('id', $id)->where('is_del',CityCode::IS_NOT_DELETE)->first();
}
}

View File

@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace App\Model;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Model\Model;
/**
* @property int $id
* @property int $pid
* @property int $deep
* @property string $title
*/
class SystemCityConfig extends Model
{
/**
* The table associated with the model.
*/
protected ?string $table = 'system_city_config';
/**
* The attributes that are mass assignable.
*/
protected array $fillable = [];
/**
* The attributes that should be cast to native types.
*/
protected array $casts = ['id' => 'integer', 'pid' => 'integer', 'deep' => 'integer'];
private array $selectFiled = ['id','pid','title'];
/**
* @return array
*/
public function getAll(): array
{
return $this->get($this->selectFiled)->toArray();
}
/**
* @param int $deep
* @return array
*/
public function getListByDeep(int $deep): array
{
return $this->where('deep',$deep)->get($this->selectFiled)->toArray();
}
/**
* @param int $id
* @return Builder|\Hyperf\Database\Model\Model|null
*/
public function getInfoById(int $id): \Hyperf\Database\Model\Model|Builder|null
{
return $this->where('id',$id)->first();
}
/**
* @param int $id
* @param int $pid
* @return \Hyperf\Database\Model\Model|Builder|null
*/
public function getAddressByIdAndPid(int $id, int $pid): \Hyperf\Database\Model\Model|Builder|null
{
return $this->where('id',$id)->where('pid',$pid)->first();
}
}

View File

@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace App\Request\Admin;
use Hyperf\Validation\Request\FormRequest;
class CityRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
return [
];
}
}

View File

@@ -0,0 +1,160 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
*/
declare(strict_types=1);
namespace App\Service\Admin\System;
use App\Cache\Redis\Common\CityCache;
use App\Constants\Common\CityCode;
use App\Exception\AdminException;
use App\Model\SystemCity;
use App\Model\SystemCityConfig;
use App\Service\Admin\BaseService;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use function Swoole\Coroutine\Http\request;
class CityService extends BaseService
{
/**
* @var SystemCity
*/
#[Inject]
protected SystemCity $systemCityModel;
/**
* @var SystemCityConfig
*/
#[Inject]
protected SystemCityConfig $systemCityConfigModel;
/**
* @var CityCache
*/
#[Inject]
protected CityCache $cityCache;
/**
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws \RedisException
*/
public function handle(): array
{
$limit = (int)$this->request->input('limit', 10);
$list = $this->systemCityModel
->where('is_del', CityCode::IS_NOT_DELETE)
->paginate($limit,['id','title','status','city_id','province_id'])
->toArray();
$allInfo = array_column($this->cityCache->getCityList(),'title','id');
if (!empty($list['data'])) {
foreach ($list['data'] as &$v) {
$v['city_name'] = $allInfo[$v['city_id']];
$v['province_name'] = $allInfo[$v['province_id']];
}
}
return $this->return->success('success', ['list' => $list]);
}
/**
* @return array
*/
public function add(): array
{
$provinceId = (int)$this->request->input('province_id');
$cityId = (int)$this->request->input('city_id');
$info = $this->systemCityConfigModel->getAddressByIdAndPid($cityId,$provinceId);
if (empty($info)) throw new AdminException('城市选择错误');
if ($this->systemCityModel->getInfoByCityId($cityId)) throw new AdminException('城市已存在');
$model = new SystemCity();
$model->province_id = $info->pid;
$model->city_id = $info->id;
$model->title = $info->title;
$model->status = $this->request->input('status', 1);
$model->is_del = 1;
if (!$model->save()) throw new AdminException('添加失败');
return $this->return->success();
}
public function changeStatus(): array
{
$id = (int)$this->request->input('id');
$model = $this->systemCityModel->getInfoById($id);
if (!$model) throw new AdminException('数据不存在');
$model->status = $model->status == CityCode::STATUS_ENABLE ? CityCode::STATUS_DISABLE : CityCode::STATUS_ENABLE;
if (!$model->save()) throw new AdminException('修改失败');
return $this->return->success();
}
/**
* @return array
*/
public function delete(): array
{
$id = (int)$this->request->input('id');
$model = $this->systemCityModel->getInfoById($id);
if (!$model) throw new AdminException('数据不存在');
$model->is_del = CityCode::IS_DELETE;
if (!$model->save()) throw new AdminException('删除失败');
return $this->return->success();
}
/**
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws \RedisException
*/
public function info(): array
{
$id = (int)$this->request->input('id');
$info = $this->systemCityModel->getInfoById($id);
if (!$info) throw new AdminException('数据不存在');
$allInfo = $this->cityCache->getCityList();
$allInfo = array_column($allInfo,'title','id');
$res = [
'id' => $info->id,
'title' => $info->title,
'status' => $info->status,
'province_id' => $info->province_id,
'province_name' => $allInfo[$info->province_id] ?? '',
'city_id' => $info->city_id,
'city_name' => $allInfo[$info->city_id]?? '',
];
return $this->return->success('success',$res);
}
}

View File

@@ -0,0 +1,37 @@
### 登录
POST {{host}}/admin/login/user
Content-Type: application/x-www-form-urlencoded
account=13632877014&password=123456
> {%
client.global.set("admin_token", response.body.data.token);
%}
###添加城市
POST {{host}}/admin/city/add
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {{admin_token}}
city_id=1410&province_id=14&status=1
###城市详情
GET {{host}}/admin/city/info?id=1
Content-Type: application/json
Authorization: Bearer {{admin_token}}
###城市列表
GET {{host}}/admin/city/list?limit=10
Content-Type: application/json
Authorization: Bearer {{admin_token}}
###城市修改状态
GET {{host}}/admin/city/edit?id=1
Content-Type: application/json
Authorization: Bearer {{admin_token}}
###城市删除
GET {{host}}/admin/city/del?id=1
Content-Type: application/json
Authorization: Bearer {{admin_token}}