feat:公共文件夹新增排序类,TOOL文件修改、咨询文章模块修改

This commit is contained in:
xjh 2023-05-12 00:45:49 +08:00
parent 694a2394be
commit c0ab336e8b
4 changed files with 325 additions and 127 deletions

View File

@ -52,6 +52,9 @@ class InfoArticle extends BaseController
*/
public function editinfoArticle(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('info_article');
try {
$params = $request->param();
$this->validate($params, [
'info_article_type_guid|文章类型' => 'require',
@ -72,7 +75,14 @@ class InfoArticle extends BaseController
'info_article_order',
'info_article_status',
])->save($params);
Db::commit();
Tool::unlockTable();
return msg('编辑成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
@ -80,15 +90,16 @@ class InfoArticle extends BaseController
*/
public function addinfoArticle(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('info_article');
try {
$params = $request->param();
$this->validate($params, [
'info_article_type_guid|文章类型' => 'require',
'info_article_title|文章标题' => 'require',
'info_article_cover|文章封面' => 'require',
'info_article_content|文章内容' => 'require',
'info_article_order|文章排序' => 'require'
]);
$model = ModelinfoArticle::create($params, [
'info_article_guid',
'info_article_create_user_guid',
@ -100,7 +111,14 @@ class InfoArticle extends BaseController
'info_article_order',
'info_article_status',
]);
Db::commit();
Tool::unlockTable();
return msg('添加成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**
@ -108,6 +126,9 @@ class InfoArticle extends BaseController
*/
public function deleteinfoArticle(Request $request): array
{
Db::startTrans();
Tool::adminLockTableWrite('info_article');
try {
$params = $request->param();
$this->validate($params, [
'info_article_guid' => 'require',
@ -117,7 +138,14 @@ class InfoArticle extends BaseController
])->select();
$info_article->delete();
Db::commit();
Tool::unlockTable();
return msg('删除成功!');
} catch (\Throwable $th) {
Db::rollback();
Tool::unlockTable();
throw $th;
}
}
/**

View File

@ -0,0 +1,203 @@
<?php
namespace app\common\exception;
use DateTime;
use think\facade\Request;
use think\facade\Log;
use think\helper\Arr;
use think\facade\Db;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
/**
* 排序类(调用此类的方法需要进行事务与锁表操作)
*/
class Sort
{
/**
* 模型层实例
* @var \think\model
*/
private $model;
/**
* 主键字段名
* @var string
*/
private $pk;
/**
* 排序字段名
* @var string
*/
private $sort_field;
/**
* 表名
* @var string
*/
private $table_name;
/**
* 构造器
*
* @param string $model 模型命名空间
*/
public function __construct(string $model)
{
//模型实例化
$this->model = new $model();
//主键字段名初始化
$this->pk = $this->model->db()->getPk();
//表名初始化
$this->table_name = $this->model->db()->getTable();
//排序字段名初始化
$this->initSortField();
}
/**
* 获取排序字段名
*/
public function getSortField(): string
{
return $this->sort_field;
}
/**
* 排序号新增处理
*
* @param array $extra_wheres 关联类型 :["xxx_type" => 1]
* @return int 返回新增所需的最新排序号
*/
public function add(array $extra_wheres = []): int
{
$sort_field = $this->sort_field;
$max_sort = $this->model->where($extra_wheres)->order($sort_field, 'desc')->value($sort_field) ?? 0;
return ++$max_sort;
}
/**
* 排序号互换处理(数据A <=> 数据B)
*
* @param string $guid 主键值
* @param int $sort 新排序号
* @param array $extra_wheres 关联类型 :["xxx_type" => 1]
*/
public function swap(string $guid, int $sort, array $extra_wheres = []): void
{
$model = $this->model;
$table_name = $this->table_name;
$pk = $this->pk;
$sort_field = $this->sort_field;
//数据A
$data_a = $model->where($pk, $guid)->find();
if (!$data_a) {
throwErrorMsg('Tool::sortEditProc() : 找不到该数据原排序号', 444);
}
//数据B
//查找当前数据所想更换的新排序号是否已有数据占用(排除自己)这个占用数据则视为数据B
$data_b = $model->where($sort_field, $sort)->where($pk, '<>', $guid)->where($extra_wheres)->find();
//数据B存在开始进行互换处理
if ($data_b) {
//【互换内容初始化】
$update_data = [];
//检查模型是否有父祖级主键,有则也加入互换
if ($this->isExistFathersAndAncestors()) {
$update_data[$model->parent_guid_field] = $data_a[$model->parent_guid_field];
$update_data[$model->ancestors_guid_field] = $data_a[$model->ancestors_guid_field];
}
//原字段排序加入互换
$update_data = [$sort_field => $data_a[$sort_field]];
//关联类型也加入互换
foreach ($extra_wheres as $key => $value) {
$update_data[$key] = $data_a[$key];
};
//【数据逻辑处理】
//互换数据A与B的关联类型不相同时候,则代表为数据互换跨类型情况
if (self::isAssociationTypeDataSame($data_a, $data_b, $extra_wheres)) {
//数据互换不同类型情况-正常互换操作
Db::name($table_name)->where($sort_field, $sort)->where($extra_wheres)->update($update_data);
} else {
//数据互换跨类型情况-腾位操作
$this->vacate($sort, $extra_wheres);
}
}
}
/**
* 排序号腾位处理
*
* @param int|null $sort 当前排序号
* @param array $wheres 当前指定数据的额外查询条件(tp批量查询数组) :["xxx_type" => 1,...]
*/
public function vacate($sort, array $wheres = []): void
{
$sort_field = $this->sort_field;
$table_name = $this->table_name;
//新增数据的所属排序号已有数据占用,则腾位处理(已占用的数据及其后面所有数据一起排序号腾位+1)
if ($this->model->where($sort_field, $sort)->where($wheres)->value($sort_field) !== null) {
Db::name($table_name)->where($wheres)->where($sort_field, '>=', $sort)->inc($sort_field)->update();
}
}
/**
* 排序号退位处理
*
* @param string $guid 当前主键值
* @param array $correl_fields 关联类型字段 :["xxx_guid",...] 代表删除排序号时会根据这些字段来关联(:所属xxx类型、所属xxx系列)来进行排序处理
*/
public function back(string $guid, array $correl_fields): void
{
$model = $this->model;
$sort_field = $this->sort_field;
//在所删除的数据之后的数据所属排序号将进行减位处理减位-1
$deleted_find = $model->where($this->pk, $guid)->find();
if ($deleted_find) {
$con = [];
foreach ($correl_fields as $correl_field) {
$con[$correl_field] = $deleted_find[$correl_field];
}
$model->where($sort_field, '>', $deleted_find[$sort_field])->where($con)->dec($sort_field)->save();
}
}
/**
* 对比数据关联类型是否相同【排序号互换处理】
*
* @param object $data_a 互换数据A
* @param object $data_b 互换数据B
* @param array $extra_wheres 关联类型数组 :["xxx_type" => 1]
*/
private static function isAssociationTypeDataSame(object $data_a, object $data_b, array $extra_wheres): bool
{
foreach ($extra_wheres as $key => $val) {
if ($data_a[$key] != $data_b[$key]) {
return false;
}
};
return true;
}
/**
* 检查模型实例父祖级主键字段是否存在【排序号互换处理】
*/
private function isExistFathersAndAncestors(): bool
{
return isset($this->model->parent_guid_field) && isset($this->model->ancestors_guid_field);
}
/**
*初始化排序字段名
*/
private function initSortField(): void
{
if (!isset($this->model->order_field)) {
throwErrorMsg('排序处理失败!模型层未定义排序字段$order_field');
}
$this->sort_field = $this->model->order_field;
}
}

View File

@ -7,6 +7,7 @@ use think\facade\Request;
use think\facade\Log;
use think\helper\Arr;
use think\facade\Db;
use app\common\exception\Sort;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
class Tool
@ -371,101 +372,67 @@ class Tool
}
/**
* 排序号更换处理
* 后台接口锁表(排他锁/写锁/独占锁)操作
*
* 注意:使用该方法时候要启动事务!!
* @param string $model 模型层命名空间地址
* @param string $table 被锁表名
*/
public static function adminLockTableWrite(string $table)
{
Db::execute("LOCK TABLES {$table} WRITE,token WRITE,user WRITE");
}
/**
* 解除表锁
*/
public static function unlockTable()
{
Db::execute("UNLOCK TABLES");
}
/**
* 排序数据修改前处理
*
* 注意:(调用此类的方法需要进行事务与锁表操作)
* @param string $model_namespace 模型层命名空间地址
* @param string $guid 主键
* @param int $order 新排序号
* @param array $extra_wheres 关联类型 :["xxx_type" => 1]
*/
public static function sortEditProc(string $model, string $guid, int $order, array $extra_wheres = []): void
public static function sortEditProc(string $model_namespace, string $guid, int $order, array $extra_wheres = []): void
{
//模型层实例化
$model = new $model;
//表名
$table_name = $model->db()->getTable();
//获取当前的主键字段名
$guld_field = $model->db()->getPk();
//排序字段名
if (!isset($model->order_field)) throwErrorMsg('排序处理失败!模型层未定义排序字段$order_field');
$order_field_name = $model->order_field;
//当前数据原信息
$original_oreder_find = $model->where($guld_field, $guid)->find();
if (!$original_oreder_find) throwErrorMsg('Tool::sortEditProc() : 找不到该数据原排序号', 444);
//查找当前数据所想更换的新排序号是否已有数据占用(排除自己)
//已被占用,则将它们的排序号互换
if ($model->where($order_field_name, $order)->where($guld_field, '<>', $guid)->where($extra_wheres)->find()) {
$update_data = [$order_field_name => $original_oreder_find[$order_field_name]];
//检查是否有父祖级主键,有则也加入互换
if (isset($model->parent_guid_field) && isset($model->ancestors_guid_field)) {
$update_data[$model->parent_guid_field] = $original_oreder_find[$model->parent_guid_field];
$update_data[$model->ancestors_guid_field] = $original_oreder_find[$model->ancestors_guid_field];
}
//关联类型也加入互换
foreach ($extra_wheres as $key => $value) {
$update_data[$key] = $original_oreder_find[$key];
};
Db::name($table_name)->where($order_field_name, $order)->where($extra_wheres)->update($update_data);
}
(new Sort($model_namespace))->swap($guid, $order, $extra_wheres);
}
/**
* 排序号腾位处理
* 排序数据新增前处理
*
* 注意:使用该方法时候要启动事务!!
* @param string $model 模型层命名空间地址
* @param int $order 当前排序号
* 注意:(调用此类的方法需要进行事务与锁表操作)
* @param string $model_namespace 模型层命名空间地址
* @param \think\model &$model 模型实例引用
* @param int|null $order 当前排序号
* @param array $wheres 当前指定数据的额外查询条件(tp批量查询数组) :["xxx_type" => 1,...]
*/
public static function sortInsertProc(string $model, int $order, array $wheres = []): void
public static function sortInsertProc(string $model_namespace, \think\model &$model, $order, array $wheres = []): void
{
//模型层实例化
$model = new $model;
//表名
$table_name = $model->db()->getTable();
//排序字段名
if (!isset($model->order_field)) throwErrorMsg('排序处理失败!模型层未定义排序字段$order_field');
$order_field_name = $model->order_field;
//新增数据的所属排序号已有数据占用,则腾位处理(已占用的数据及其后面所有数据一起排序号腾位+1)
if ($model->where($order_field_name, $order)->where($wheres)->value($order_field_name) !== null) {
Db::name($table_name)
->where($wheres)
->where($order_field_name, '>=', $order)
->inc($order_field_name)
->update();
$sort = new Sort($model_namespace);
if ($order) {
$sort->vacate($order, $wheres);
} else {
$model[$sort->getSortField()] = $sort->add($wheres);
}
}
/**
* 排序号删除处理
* 注意:使用该方法时候要启动事务!!
* @param string $model 模型层命名空间地址
* @param array $guid 主键
* 排序删除前处理
*
* 注意:(调用此类的方法需要进行事务与锁表操作)
* @param string $model_namespace 模型层命名空间地址
* @param string $guid 主键
* @param array $correl_fields 关联类型字段 :["xxx_guid",...] 代表删除排序号时会根据这些字段来关联(:所属xxx类型、所属xxx系列)来进行排序处理
*/
public static function sortDeleteProc(string $model, string $guid, array $correl_fields = []): void
public static function sortDeleteProc(string $model_namespace, string $guid, array $correl_fields = []): void
{
//模型层实例化
$model = new $model;
//获取当前的主键字段名
$guld_field_name = $model->db()->getPk();
//获取当前表排序字段名
if (!isset($model->order_field)) throwErrorMsg('排序处理失败!模型层未定义排序字段$order_field');
$order_field_name = $model->order_field;
//在所删除的数据之后的数据所属排序号将进行减位处理减位-1
if ($find = $model->where($guld_field_name, $guid)->find()) {
$con = [];
foreach ($correl_fields as $correl_field) {
$con[$correl_field] = $find[$correl_field];
}
$model->where($order_field_name, '>', $find[$order_field_name])
->where($con)
->dec($order_field_name)
->save();
}
(new Sort($model_namespace))->back($guid, $correl_fields);
}
/**

View File

@ -82,10 +82,10 @@ class InfoArticle extends BaseModel
{
Tool::sortInsertProc(
self::class,
$model,
$model->info_article_order,
['info_article_type_guid' => $model->info_article_type_guid]
);
// self::checkRepeatData($model);
$model->completeCreateField();
}