在 Yii 2.0 中,编辑与更新租户的任务类型与步骤设置(多条记录、树形结构)的拆分实现 (三)
1、编辑与更新租户的任务类型与步骤设置的 UI 在接口实现后才设计完毕。上一版本的实现:http://www.shuijingwanwq.com/2019/11/14/3605/ ,在上一版本中,一个接口中同时实现:任务类型可(添加、删除、重命名其名称、排序),任务步骤可从 18 个任务步骤列表中选择(添加、删除、勾选、不勾选、排序)。
2、UI 出来后,前端开发人员希望能够拆分更新接口,拆分为:新建任务类型、删除任务类型、编辑某一任务类型与其下的任务步骤,因为,这样实现的话,与 UI 的界面更为一致,且降低了前端开发的难度。如图1
3、最初始的设计方案,是参考了 Zentao 与 Rap ,Rap 的更新请求,如图2
4、由于希望继续保留之前的路由实现,因此,路由配置如下
// 基础设置 - 任务配置 [ 'class' => 'yii\rest\UrlRule', 'controller' => ['v1/config-task'], 'only' => ['create', 'update', 'delete'], ],
5、编辑任务配置的模型文件,\api\models\ConfigTask.php
<?php namespace api\models; use Yii; use yii\helpers\ArrayHelper; class ConfigTask extends \common\logics\ConfigTask { const SCENARIO_CREATE = 'create'; const SCENARIO_UPDATE = 'update'; const SCENARIO_DELETE = 'delete'; public function scenarios() { $scenarios = parent::scenarios(); $scenarios[self::SCENARIO_CREATE] = ['group_id', 'code', 'name', 'sort_order', 'is_default', 'status', 'is_deleted', 'deleted_at']; $scenarios[self::SCENARIO_UPDATE] = ['name', 'sort_order', 'is_default', 'status']; return $scenarios; } /** * @inheritdoc */ public function rules() { $rules = [ /* 创建 */ [['code'], 'match', 'pattern' => '/^[a-z0-9]+$/', 'message' => Yii::t('application', '{attribute} should contain lowercase letters and numbers.'), 'on' => self::SCENARIO_CREATE], [['is_default'], 'in', 'range' => [static::IS_DEFAULT_NO, static::IS_DEFAULT_YES], 'on' => self::SCENARIO_CREATE], [['status'], 'in', 'range' => [self::STATUS_DISABLED, self::STATUS_ENABLED], 'on' => self::SCENARIO_CREATE], /* 更新 */ [['is_default'], 'in', 'range' => [static::IS_DEFAULT_NO, static::IS_DEFAULT_YES], 'on' => self::SCENARIO_UPDATE], [['status'], 'in', 'range' => [self::STATUS_DISABLED, self::STATUS_ENABLED], 'on' => self::SCENARIO_UPDATE], /* 删除 */ [['id'], 'validateDeletePermission', 'on' => self::SCENARIO_DELETE], ]; $parentRules = parent::rules(); return ArrayHelper::merge($rules, $parentRules); } /** * Validates the delete permission. * This method serves as the inline validation for delete permission. * * @param string $attribute the attribute currently being validated * @param array $params the additional name-value pairs given in the rule */ public function validateDeletePermission($attribute, $params) { if (!$this->hasErrors()) { // 基于 租户ID、任务配置ID 查找资源(选题任务)的任务配置ID列 $planTaskConfigTaskIds = PlanTask::find() ->select('config_task_id') ->where([ 'and', ['group_id' => $this->group_id], ['config_task_id' => $this->id]] ) ->isDeletedNo() ->distinct() ->column(); // 待删除的任务配置的代码,但是其下存在选题任务 if (!empty($planTaskConfigTaskIds)) { $codes = implode(";", [$this->code]); $this->addError($attribute, Yii::t('error', Yii::t('error', Yii::t('error', '226088'), ['codes' => $codes]))); } } } /** * {@inheritdoc} * @return ConfigTaskQuery the active query used by this AR class. */ public static function find() { return new ConfigTaskQuery(get_called_class()); } /** * 基于 租户ID、ID 批量设置资源为是否默认:否(场景:当某资源设置为是否默认:是时,需要设置其他资源为是否默认:否) * * @param array $groupId 租户ID * @param int $id ID * * @return int 设置资源为是否默认:否(更新)的行数 */ public static function updateAllIsDefaultNoByGroupIdAndId($groupId, $id) { return self::updateAll( [ 'is_default' => self::IS_DEFAULT_NO, ], [ 'and', ['group_id' => $groupId], ['is_deleted' => self::IS_DELETED_NO], ['!=', 'id', $id], ] ); } }
6、编辑任务步骤配置的模型文件,\api\models\ConfigTaskStep.php
<?php namespace api\models; use yii\helpers\ArrayHelper; class ConfigTaskStep extends \common\logics\ConfigTaskStep { const SCENARIO_CREATE = 'create'; const SCENARIO_UPDATE = 'update'; public function scenarios() { $scenarios = parent::scenarios(); $scenarios[self::SCENARIO_CREATE] = ['group_id', 'config_task_code', 'step_code', 'sort_order', 'is_default', 'is_deleted', 'deleted_at']; $scenarios[self::SCENARIO_UPDATE] = ['sort_order', 'is_default']; return $scenarios; } /** * @inheritdoc */ public function rules() { $rules = [ /* 创建 */ ['step_code', 'exist', 'targetClass' => '\api\models\ConfigStep', 'targetAttribute' => 'code', 'filter' => ['is_deleted' => ConfigStep::IS_DELETED_NO], 'on' => self::SCENARIO_CREATE], [['is_default'], 'in', 'range' => [static::IS_DEFAULT_NO, static::IS_DEFAULT_YES], 'on' => self::SCENARIO_CREATE], /* 添加、更新任务步骤配置 */ [['is_default'], 'in', 'range' => [static::IS_DEFAULT_NO, static::IS_DEFAULT_YES], 'on' => self::SCENARIO_UPDATE], ]; $parentRules = parent::rules(); return ArrayHelper::merge($rules, $parentRules); } /** * {@inheritdoc} * @return ConfigTaskStepQuery the active query used by this AR class. */ public static function find() { return new ConfigTaskStepQuery(get_called_class()); } }
7、编辑任务步骤配置的服务文件,\api\services\ConfigTaskStepService.php
<?php /** * Created by PhpStorm. * User: terryhong * Date: 2018/12/20 * Time: 3:09 PM */ namespace api\services; use Yii; use api\models\ConfigTask; use api\models\ConfigStep; use api\models\ConfigTaskStep; use yii\web\ServerErrorHttpException; class ConfigTaskStepService extends \common\services\ConfigTaskStepService { /** * 创建任务步骤配置 * * @param object $configTask 任务配置 * 格式如下: * [ * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'code' => 'zidingyisi', // 代码 * 'name' => '自定义四', // 名称 * 'sort_order' => 8, // 顺序 * 'is_default' => 0, // 是否默认,0:否;1:是 * 'status' => 1, // 状态,0:禁用;1:启用 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'deleted_at' => 0, // 删除时间 * ] * * @param array $configTaskSteps 任务步骤配置 * 格式如下: * [ * [ // object * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'config_task_code' => 'zidingyisi', // 任务配置代码 * 'step_code' => 'begin_shot', // 步骤代码 * 'sort_order' => 1, // 顺序 * 'is_default' => 1, // 是否默认步骤,1:是;0:否 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'deleted_at' => 0, // 删除时间 * ], * [ // object * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'config_task_code' => 'zidingyisi', // 任务配置代码 * 'step_code' => 'writing', // 步骤代码 * 'sort_order' => 2, // 顺序 * 'is_default' => 1, // 是否默认步骤,1:是;0:否 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'deleted_at' => 0, // 删除时间 * ], * ... * ] * * @param object $identity 当前用户的身份实例 * * @return array * 格式如下: * * [ * 'status' => true, // 成功 * ] * * @throws \Throwable */ public function create($configTask, $configTaskSteps, $identity) { /* 操作数据(事务) */ $transaction = Yii::$app->db->beginTransaction(); try { $configTaskService = new ConfigTaskService(); /* 创建 MySQL 模型(任务配置) */ $configTask->category = $configTask::CATEGORY_CUSTOMIZE; $configTask->parameter = serialize(''); $configTaskServiceCreateResult = $configTaskService->create($configTask, false); if ($configTaskServiceCreateResult['status'] === false) { throw new ServerErrorHttpException($configTaskServiceCreateResult['message'], $configTaskServiceCreateResult['code']); } // 基于 租户ID、ID 批量设置资源为是否默认:否(场景:当某资源设置为是否默认:是时,需要设置其他资源为是否默认:否) if ($configTask->is_default == ConfigTask::IS_DEFAULT_YES) { ConfigTask::updateAllIsDefaultNoByGroupIdAndId($identity->group_id, $configTask->id); } $configTaskItems = ConfigTask::find()->where(['group_id' => $identity->group_id])->indexBy(['code'])->all(); $configStepItems = ConfigStep::find()->isDeletedNo()->indexBy(['code'])->all(); /* 循环创建 MySQL 模型(任务步骤配置) */ foreach ($configTaskSteps as $configTaskStep) { /* @var $configTaskStep ConfigTaskStep */ $configTaskStep->config_task_id = $configTaskItems[$configTaskStep->config_task_code]->id; $configTaskStep->config_step_id = $configStepItems[$configTaskStep->step_code]->id; $configTaskStep->step_name = $configStepItems[$configTaskStep->step_code]->name; $configTaskStep->up_status_type = $configTaskStep::UP_STATUS_TYPE_ARTIFICIAL; $configTaskStep->status = $configTaskStep::STATUS_ENABLED; if ($configTaskStep->save(false)) { // return ['status' => true, 'data' => $configTaskStep]; } elseif ($configTaskStep->hasErrors()) { $firstError = ''; foreach ($configTaskStep->getFirstErrors() as $message) { $firstError = $message; break; } return ['status' => false, 'code' => 226084, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '226084'), ['first_error' => $firstError]))]; } elseif (!$configTaskStep->hasErrors()) { throw new ServerErrorHttpException('Failed to create the object (task step configuration) for unknown reason.'); } } $transaction->commit(); } catch(\Throwable $e) { $transaction->rollBack(); throw $e; } return ['status' => true]; } /** * 更新任务配置、添加|还原|更新|删除任务步骤配置 * * @param object $configTask 任务配置 * 格式如下: * [ // object * 'id' => 24, // ID * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'code' => 'zidingyisi', // 代码 * 'name' => '自定义四十', // 名称 * 'sort_order' => 9, // 顺序 * 'category' => 2, // 任务类型,1:系统内置;2:用户定义 * 'is_default' => 1, // 是否默认,0:否;1:是 * 'parameter' => 's:0:"";', // 自定义参数,序列化存储 * 'status' => 0, // 状态,0:禁用;1:启用 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'created_at' => 1574670316, // 创建时间 * 'updated_at' => 1574670316, // 更新时间 * 'deleted_at' => 0, // 删除时间 * ] * * @param array $deletedConfigTaskSteps 需要删除的任务步骤配置 * 格式如下: * [ * [ // object * 'id' => 127, // ID * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'config_task_id' => 24, // 任务配置ID * 'config_task_code' => 'zidingyisi', // 任务配置代码 * 'config_step_id' => 2, // 步骤配置ID * 'step_code' => 'begin_shot', // 步骤配置代码 * 'step_name' => '上传素材', // 步骤配置名称 * 'sort_order' => 1, // 步骤顺序,顺序排列 * 'is_default' => 1, // 是否默认步骤,1:是;0:否 * 'up_status_type' => 2, // 状态更新方式,1:接口;2:人工 * 'status' => 1, // 状态,0:禁用;1:启用 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'created_at' => 1574670316, // 创建时间 * 'updated_at' => 1574670316, // 更新时间 * 'deleted_at' => 0, // 删除时间 * ], * ... * ] * * * @param array $configTaskSteps 任务步骤配置 * 格式如下: * [ * [ // object * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'config_task_code' => 'zidingyisi', // 任务配置代码 * 'step_code' => 'begin_shot', // 步骤代码 * 'sort_order' => 6, // 顺序 * 'is_default' => 1, // 是否默认步骤,1:是;0:否 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'deleted_at' => 0, // 删除时间 * ], * [ // object * 'id' => 128, // ID * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'config_task_id' => 24, // 任务配置ID * 'config_task_code' => 'zidingyisi', // 任务配置代码 * 'config_step_id' => 4, // 步骤配置ID * 'step_code' => 'writing', // 步骤配置代码 * 'step_name' => '撰写稿件', // 步骤配置名称 * 'sort_order' => 3, // 步骤顺序,顺序排列 * 'is_default' => 0, // 是否默认步骤,1:是;0:否 * 'up_status_type' => 2, // 状态更新方式,1:接口;2:人工 * 'status' => 1, // 状态,0:禁用;1:启用 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'created_at' => 1574670316, // 创建时间 * 'updated_at' => 1574670316, // 更新时间 * 'deleted_at' => 0, // 删除时间 * ], * ... * ] * * @param object $identity 当前用户的身份实例 * * @return array * 格式如下: * * [ * 'status' => true, // 成功 * ] * * @throws \Throwable */ public function update($configTask, $deletedConfigTaskSteps, $configTaskSteps, $identity) { /* 操作数据(事务) */ $transaction = Yii::$app->db->beginTransaction(); try { $configTaskService = new ConfigTaskService(); /* 更新 MySQL 模型(任务配置) */ $configTaskServiceUpdateResult = $configTaskService->update($configTask, false); if ($configTaskServiceUpdateResult['status'] === false) { throw new ServerErrorHttpException($configTaskServiceUpdateResult['message'], $configTaskServiceUpdateResult['code']); } // 基于 租户ID、ID 批量设置资源为是否默认:否(场景:当某资源设置为是否默认:是时,需要设置其他资源为是否默认:否) if ($configTask->is_default == ConfigTask::IS_DEFAULT_YES) { ConfigTask::updateAllIsDefaultNoByGroupIdAndId($identity->group_id, $configTask->id); } // 使用键名比较计算数组的差集,如果不为空,则删除 (软删除) 出现在 任务步骤配置模型(MySQL) 中但是未出现在 任务步骤配置列表 中的记录 $this->deleteMultiple($deletedConfigTaskSteps); $configTaskItems = ConfigTask::find()->where(['group_id' => $identity->group_id])->indexBy(['code'])->all(); $configStepItems = ConfigStep::find()->isDeletedNo()->indexBy(['code'])->all(); // 遍历模型数组,判断在 任务步骤配置 中是否存在,如果不存在则插入,如果存在则更新(已删除则先还原) foreach ($configTaskSteps as $configTaskStep) { $configTaskStepItem = ConfigTaskStep::find()->where(['group_id' => $identity->group_id, 'config_task_code' => $configTaskStep->config_task_code, 'step_code' => $configTaskStep->step_code])->one(); /* @var $configTaskStep ConfigTaskStep */ if (!isset($configTaskStepItem)) { $configTaskStep->config_task_id = $configTaskItems[$configTaskStep->config_task_code]->id; $configTaskStep->config_step_id = $configStepItems[$configTaskStep->step_code]->id; $configTaskStep->step_name = $configStepItems[$configTaskStep->step_code]->name; $configTaskStep->up_status_type = $configTaskStep::UP_STATUS_TYPE_ARTIFICIAL; $configTaskStep->status = $configTaskStep::STATUS_ENABLED; if ($configTaskStep->save(false)) { // return ['status' => true, 'data' => $configTaskStep]; } elseif ($configTaskStep->hasErrors()) { $firstError = ''; foreach ($configTaskStep->getFirstErrors() as $message) { $firstError = $message; break; } return ['status' => false, 'code' => 226084, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '226084'), ['first_error' => $firstError]))]; } elseif (!$configTaskStep->hasErrors()) { throw new ServerErrorHttpException('Failed to create the object (task step configuration) for unknown reason.'); } } else if (isset($configTaskStepItem)) { if ($configTaskStepItem->is_deleted == ConfigTaskStep::IS_DELETED_YES && $configTaskStepItem->restore() === false) { throw new ServerErrorHttpException('Failed to restore the object (task step configuration) for unknown reason.'); } $configTaskStepItem->sort_order = $configTaskStep->sort_order; $configTaskStepItem->is_default = $configTaskStep->is_default; if ($configTaskStepItem->save(false)) { // return ['status' => true, 'data' => $configTaskStepItem]; } elseif ($configTaskStepItem->hasErrors()) { $firstError = ''; foreach ($configTaskStepItem->getFirstErrors() as $message) { $firstError = $message; break; } throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '226085'), ['first_error' => $firstError])), 226085); } elseif (!$configTaskStepItem->hasErrors()) { throw new ServerErrorHttpException('Failed to update the object (task step configuration) for unknown reason.'); } } } $transaction->commit(); } catch(\Throwable $e) { $transaction->rollBack(); throw $e; } return ['status' => true]; } /** * 添加|还原|更新|删除任务配置、添加|还原|更新|删除任务步骤配置 * * @param array $deletedConfigTasks 需要删除的任务配置 * 格式如下: * [ * [ // object * 'id' => 32, // ID * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'code' => 'other', // 代码 * 'name' => '手动任务', // 名称 * 'sort_order' => 1, // 顺序 * 'category' => 2, // 任务类型,1:系统内置;2:用户定义 * 'is_default' => 0, // 是否默认,0:否;1:是 * 'parameter' => 's:0:"";', // 自定义参数,序列化存储 * 'status' => 1, // 状态,0:禁用;1:启用 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'created_at' => 1573632826, // 创建时间 * 'updated_at' => 1573632826, // 更新时间 * 'deleted_at' => 0, // 删除时间 * ], * ... * ] * * @param array $configTasks 任务配置 * 格式如下: * [ * [ // object * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'code' => 'tv_broadcast', // 代码 * 'name' => '电视播出', // 名称 * 'sort_order' => 1, // 顺序 * 'is_default' => 0, // 是否默认,0:否;1:是 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'deleted_at' => 0, // 删除时间 * ], * [ // object * 'id' => 29, // ID * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'code' => 'tv_broadcast', // 代码 * 'name' => '电视播出', // 名称 * 'sort_order' => 1, // 顺序 * 'category' => 2, // 任务类型,1:系统内置;2:用户定义 * 'is_default' => 0, // 是否默认,0:否;1:是 * 'parameter' => 's:0:"";', // 自定义参数,序列化存储 * 'status' => 1, // 状态,0:禁用;1:启用 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'created_at' => 1573632826, // 创建时间 * 'updated_at' => 1573632826, // 更新时间 * 'deleted_at' => 0, // 删除时间 * ], * ... * ] * * @param array $deletedConfigTaskSteps 需要删除的任务步骤配置 * 格式如下: * [ * [ // object * 'id' => 145, // ID * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'config_task_id' => 32, // 任务配置ID * 'config_task_code' => 'other', // 任务配置代码 * 'config_step_id' => 2, // 步骤配置ID * 'step_code' => 'begin_shot', // 步骤配置代码 * 'step_name' => '上传素材', // 步骤配置名称 * 'sort_order' => 1, // 步骤顺序,顺序排列 * 'is_default' => 1, // 是否默认步骤,1:是;0:否 * 'up_status_type' => 2, // 状态更新方式,1:接口;2:人工 * 'status' => 1, // 状态,0:禁用;1:启用 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'created_at' => 1573632826, // 创建时间 * 'updated_at' => 1573632826, // 更新时间 * 'deleted_at' => 0, // 删除时间 * ], * ... * ] * * * @param array $configTaskSteps 任务步骤配置 * 格式如下: * [ * [ // object * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'config_task_code' => 'tv_broadcast', // 任务配置代码 * 'step_code' => 'begin_shot', // 步骤代码 * 'sort_order' => 1, // 顺序 * 'is_default' => 1, // 是否默认步骤,1:是;0:否 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'deleted_at' => 0, // 删除时间 * ], * [ // object * 'id' => 122, // ID * 'group_id' => '015ce30b116ce86058fa6ab4fea4ac63', // 租户ID * 'config_task_id' => 29, // 任务配置ID * 'config_task_code' => 'tv_broadcast', // 任务配置代码 * 'config_step_id' => 2, // 步骤配置ID * 'step_code' => 'begin_shot', // 步骤配置代码 * 'step_name' => '上传素材', // 步骤配置名称 * 'sort_order' => 1, // 步骤顺序,顺序排列 * 'is_default' => 1, // 是否默认步骤,1:是;0:否 * 'up_status_type' => 2, // 状态更新方式,1:接口;2:人工 * 'status' => 1, // 状态,0:禁用;1:启用 * 'is_deleted' => 0, // 是否被删除,0:否;1:是 * 'created_at' => 1573632826, // 创建时间 * 'updated_at' => 1573632826, // 更新时间 * 'deleted_at' => 0, // 删除时间 * ], * ... * ] * * @param object $identity 当前用户的身份实例 * * @return array * 格式如下: * * [ * 'status' => true, // 成功 * ] * * @throws \Throwable */ public function updateMultiple($deletedConfigTasks, $configTasks, $deletedConfigTaskSteps, $configTaskSteps, $identity) { /* 操作数据(事务) */ $transaction = Yii::$app->db->beginTransaction(); try { $configTaskService = new ConfigTaskService(); // 使用键名比较计算数组的差集,如果不为空,则删除 (软删除) 出现在 任务配置模型(MySQL) 中但是未出现在 任务配置列表 中的记录 $configTaskService->deleteMultiple($deletedConfigTasks); // 遍历模型数组,判断在 任务配置 中是否存在,如果不存在则插入,如果存在则更新(已删除则先还原) foreach ($configTasks as $configTask) { $configTaskItem = ConfigTask::find()->where(['group_id' => $identity->group_id, 'code' => $configTask->code])->one(); /* @var $configTask ConfigTask */ if (!isset($configTaskItem)) { $configTask->category = $configTask::CATEGORY_CUSTOMIZE; $configTask->parameter = serialize(''); $configTask->status = $configTask::STATUS_ENABLED; $configTask->is_deleted = $configTask::IS_DELETED_NO; $configTask->deleted_at = $configTask::DELETED_AT_DEFAULT; $configTaskServiceCreateResult = $configTaskService->create($configTask, false); if ($configTaskServiceCreateResult['status'] === false) { throw new ServerErrorHttpException($configTaskServiceCreateResult['message'], $configTaskServiceCreateResult['code']); } } else if (isset($configTaskItem)) { if ($configTaskItem->is_deleted == ConfigTask::IS_DELETED_YES && $configTaskItem->restore() === false) { throw new ServerErrorHttpException('Failed to restore the object (task configuration) for unknown reason.'); } $configTaskItem->name = $configTask->name; $configTaskItem->sort_order = $configTask->sort_order; $configTaskItem->is_default = $configTask->is_default; $configTaskItemServiceUpdateResult = $configTaskService->update($configTaskItem, false); if ($configTaskItemServiceUpdateResult['status'] === false) { throw new ServerErrorHttpException($configTaskItemServiceUpdateResult['message'], $configTaskItemServiceUpdateResult['code']); } } } // 使用键名比较计算数组的差集,如果不为空,则删除 (软删除) 出现在 任务步骤配置模型(MySQL) 中但是未出现在 任务步骤配置列表 中的记录 $this->deleteMultiple($deletedConfigTaskSteps); $configTaskItems = ConfigTask::find()->where(['group_id' => $identity->group_id])->indexBy(['code'])->all(); $configStepItems = ConfigStep::find()->isDeletedNo()->indexBy(['code'])->all(); // 遍历模型数组,判断在 任务步骤配置 中是否存在,如果不存在则插入,如果存在则更新(已删除则先还原) foreach ($configTaskSteps as $configTaskStep) { $configTaskStepItem = ConfigTaskStep::find()->where(['group_id' => $identity->group_id, 'config_task_code' => $configTaskStep->config_task_code, 'step_code' => $configTaskStep->step_code])->one(); /* @var $configTaskStep ConfigTaskStep */ if (!isset($configTaskStepItem)) { $configTaskStep->config_task_id = $configTaskItems[$configTaskStep->config_task_code]->id; $configTaskStep->config_step_id = $configStepItems[$configTaskStep->step_code]->id; $configTaskStep->step_name = $configStepItems[$configTaskStep->step_code]->name; $configTaskStep->up_status_type = $configTaskStep::UP_STATUS_TYPE_ARTIFICIAL; $configTaskStep->status = $configTaskStep::STATUS_ENABLED; if ($configTaskStep->save(false)) { // return ['status' => true, 'data' => $configTaskStep]; } elseif ($configTaskStep->hasErrors()) { $firstError = ''; foreach ($configTaskStep->getFirstErrors() as $message) { $firstError = $message; break; } return ['status' => false, 'code' => 226084, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '226084'), ['first_error' => $firstError]))]; } elseif (!$configTaskStep->hasErrors()) { throw new ServerErrorHttpException('Failed to create the object (task step configuration) for unknown reason.'); } } else if (isset($configTaskStepItem)) { if ($configTaskStepItem->is_deleted == ConfigTaskStep::IS_DELETED_YES && $configTaskStepItem->restore() === false) { throw new ServerErrorHttpException('Failed to restore the object (task step configuration) for unknown reason.'); } $configTaskStepItem->sort_order = $configTaskStep->sort_order; $configTaskStepItem->is_default = $configTaskStep->is_default; if ($configTaskStepItem->save(false)) { // return ['status' => true, 'data' => $configTaskStepItem]; } elseif ($configTaskStepItem->hasErrors()) { $firstError = ''; foreach ($configTaskStepItem->getFirstErrors() as $message) { $firstError = $message; break; } throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '226085'), ['first_error' => $firstError])), 226085); } elseif (!$configTaskStepItem->hasErrors()) { throw new ServerErrorHttpException('Failed to update the object (task step configuration) for unknown reason.'); } } } $transaction->commit(); } catch(\Throwable $e) { $transaction->rollBack(); throw $e; } return ['status' => true]; } /** * 批量删除(删除任务步骤配置) * * @param $models * * @return bool the saved model or false if saving fails * @throws \Throwable */ public function deleteMultiple($models) { $transaction = Yii::$app->db->beginTransaction(); try { foreach ($models as $model) { if($model->softDelete() === false) { throw new ServerErrorHttpException(Yii::t('error', '226086'), 226086); } } $transaction->commit(); return true; } catch (\Throwable $e) { $transaction->rollBack(); throw $e; } } }
8、编辑 更新租户的任务类型与步骤设置 的操作方法文件,以保留对于批量更新的支持,\api\rests\config_task_step\UpdateAction.php
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\config_task_step; use Yii; use api\models\ConfigTask; use api\models\ConfigTaskStep; use api\models\PlanTask; use api\models\redis\cmc_console\User as RedisCmcConsoleUser; use api\services\ConfigTaskStepService; use yii\base\Model; use yii\base\InvalidConfigException; use yii\helpers\ArrayHelper; use yii\web\UnprocessableEntityHttpException; use yii\web\ServerErrorHttpException; /** * 更新租户的任务类型与步骤设置:/config-task-steps/{group_id}(config-task-step/update) * * For more details and usage information on CreateAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class UpdateAction extends Action { /** * @var string the scenario to be assigned to the model before it is validated and updated. * $id {config_column_id} */ public $scenario = Model::SCENARIO_DEFAULT; /** * Updates an existing model. * @param string $id the primary key of the model. * @return array the model being updated * @throws InvalidConfigException if a registered parser does not implement the [[RequestParserInterface]]. * @throws ServerErrorHttpException if there is any error when updating the model * @throws \Throwable */ public function run($id) { // 当前用户的身份实例,未认证用户则为 Null /* @var $identity RedisCmcConsoleUser */ $identity = Yii::$app->user->identity; // 比对:group_id,检查其值是否等于:my-group-id if ($id != 'my-group-id') { throw new UnprocessableEntityHttpException(Yii::t('error', '226053'), 226053); } /* @var $modelClass ConfigTaskStep */ $modelClass = $this->modelClass; $requestParams = Yii::$app->getRequest()->getBodyParams(); /* @var $configGroupTaskItem ConfigTask */ // 基于租户ID查找资源(任务配置、是否被删除:否)列表 $configTaskIsDeletedNoItems = ConfigTask::find()->where(['group_id' => $identity->group_id])->isDeletedNo()->indexBy(['code'])->all(); // 基于租户ID查找资源(任务配置)列表 $configTaskItems = ConfigTask::find()->where(['group_id' => $identity->group_id])->indexBy(['code'])->all(); /* @var $configGroupTaskStepItem ConfigTaskStep */ // 基于租户ID查找资源(任务步骤配置、是否被删除:否)列表 $configTaskStepIsDeletedNoItems = $modelClass::find()->where(['group_id' => $identity->group_id])->isDeletedNo()->indexBy(function ($row) { return $row['config_task_code'] . ':' . $row['step_code']; })->all(); // 基于租户ID查找资源(任务步骤配置)列表 $configTaskStepItems = $modelClass::find()->where(['group_id' => $identity->group_id])->indexBy(function ($row) { return $row['config_task_code'] . ':' . $row['step_code']; })->all(); if (!is_array($requestParams)) { return ['code' => 226010, 'message' => Yii::t('error', '226010')]; } $configTasks = []; $configTaskSteps = []; foreach ($requestParams as $configTask) { // 检查 任务配置的(代码、名称、顺序) 是否存在 if (!ArrayHelper::keyExists('code', $configTask) || !ArrayHelper::keyExists('name', $configTask) || !ArrayHelper::keyExists('sort_order', $configTask)) { throw new UnprocessableEntityHttpException(Yii::t('error', '226080'), 226080); } $isDefault = isset($configTask['is_default']) ? $configTask['is_default'] : 0; $configTasks[$configTask['code']] = [ 'group_id' => $identity->group_id, 'code' => $configTask['code'], 'name' => $configTask['name'], 'sort_order' => $configTask['sort_order'], 'is_default' => isset($configTask['is_default']) ? $configTask['is_default'] : ConfigTask::IS_DEFAULT_NO, ]; // 检查 步骤配置列表 是否存在 if (ArrayHelper::keyExists('steps', $configTask)) { foreach ($configTask['steps'] as $configTaskStep) { // 检查 步骤代码、顺序、是否默认步骤 是否存在 if (!ArrayHelper::keyExists('code', $configTaskStep) || !ArrayHelper::keyExists('sort_order', $configTaskStep) || !ArrayHelper::keyExists('is_default', $configTaskStep)) { throw new UnprocessableEntityHttpException(Yii::t('error', '226080'), 226080); } $configTaskSteps[$configTask['code'] . ':' . $configTaskStep['code']] = [ 'group_id' => $identity->group_id, 'config_task_code' => $configTask['code'], 'step_code' => $configTaskStep['code'], 'sort_order' => $configTaskStep['sort_order'], 'is_default' => $configTaskStep['is_default'], ]; } } } /* 任务配置 */ // 使用键名比较计算数组的差集,如果不为空,则删除 (软删除) 出现在 任务配置模型(MySQL) 中但是未出现在 任务配置 中的记录 $configTaskDiffItems = array_diff_key($configTaskIsDeletedNoItems, $configTasks); // 获取 id 值列表 $configTaskDiffIds = ArrayHelper::getColumn($configTaskDiffItems, 'id'); // 基于 租户ID、任务配置ID 查找资源(选题任务)的任务配置ID列 $planTaskConfigTaskIds = PlanTask::find() ->select('config_task_id') ->where([ 'and', ['group_id' => $identity->group_id], ['in', 'config_task_id', $configTaskDiffIds]] ) ->isDeletedNo() ->distinct() ->column(); // 待删除的任务配置的代码,但是其下存在选题任务 $configTaskDiffCodes = []; foreach ($configTaskDiffIds as $configTaskDiffIdKey => $configTaskDiffId) { if (in_array($configTaskDiffId, $planTaskConfigTaskIds)) { $configTaskDiffCodes[] = $configTaskDiffIdKey; } } if (!empty($configTaskDiffCodes)) { $codes = implode(";", $configTaskDiffCodes); throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '226088'), ['codes' => $codes])), 226088); } $configTasks = array_values($configTasks); $configTaskModels = []; foreach ($configTasks as $configTask) { if (isset($configTaskItems[$configTask['code']])) { $configTaskItems[$configTask['code']]->scenario = ConfigTask::SCENARIO_UPDATE; $configTaskModels[] = $configTaskItems[$configTask['code']]; } else { $configTaskModels[] = new ConfigTask([ 'scenario' => ConfigTask::SCENARIO_CREATE, ]); } } // 批量填充模型属性 if (!empty($configTaskModels) && !Model::loadMultiple($configTaskModels, $configTasks, '')) { return ['code' => 226010, 'message' => Yii::t('error', '226010')]; } // 批量验证模型 if (!empty($configTaskModels) && !Model::validateMultiple($configTaskModels)) { $configTaskModelsResult = self::handleValidateMultipleError($configTaskModels); if ($configTaskModelsResult['status'] === false) { return ['code' => $configTaskModelsResult['code'], 'message' => $configTaskModelsResult['message']]; } } /* 任务步骤配置 */ // 使用键名比较计算数组的差集,如果不为空,则删除 (软删除) 出现在 任务步骤配置模型(MySQL) 中但是未出现在 任务步骤配置 中的记录 $configTaskStepDiffItems = array_diff_key($configTaskStepIsDeletedNoItems, $configTaskSteps); $configTaskSteps = array_values($configTaskSteps); $configTaskStepModels = []; foreach ($configTaskSteps as $configTaskStep) { $index = $configTaskStep['config_task_code'] . ':' . $configTaskStep['step_code']; if (isset($configTaskStepItems[$index])) { $configTaskStepItems[$index]->scenario = $modelClass::SCENARIO_UPDATE; $configTaskStepModels[] = $configTaskStepItems[$index]; } else { $configTaskStepModels[] = new $modelClass([ 'scenario' => $modelClass::SCENARIO_CREATE, ]); } } // 批量填充模型属性 if (!empty($configTaskStepModels) && !Model::loadMultiple($configTaskStepModels, $configTaskSteps, '')) { return ['code' => 226010, 'message' => Yii::t('error', '226010')]; } // 批量验证模型 if (!empty($configTaskStepModels) && !Model::validateMultiple($configTaskStepModels)) { $configTaskStepModelsResult = self::handleValidateMultipleError($configTaskStepModels); if ($configTaskStepModelsResult['status'] === false) { return ['code' => $configTaskStepModelsResult['code'], 'message' => $configTaskStepModelsResult['message']]; } } /* 操作数据(事务) */ $configTaskStepService = new ConfigTaskStepService(); $result = $configTaskStepService->updateMultiple($configTaskDiffItems, $configTaskModels, $configTaskStepDiffItems, $configTaskStepModels, $identity); if ($result['status'] === false) { throw new ServerErrorHttpException($result['message'], $result['code']); } return ['code' => 10000, 'message' => Yii::t('success', '126039')]; } }
9、在 Postman 中 GET:http://api.pcs-api.localhost/v1/config-task-steps/edit/my-group-id ,响应数据如下
{ "code": 10000, "message": "编辑租户的任务类型与步骤设置成功", "data": { "items": [ { "id": 5, "code": "tv_broadcast", "name": "电视播出", "sort_order": 1, "is_default": 0, "status": 1, "steps": [ { "id": 2, "code": "begin_shot", "name": "上传素材", "sort_order": 1, "is_default": 1, "status": 1 }, { "id": 4, "code": "writing", "name": "撰写稿件", "sort_order": 2, "is_default": 1, "status": 1 }, { "id": 7, "code": "manuscript_review", "name": "稿件审核", "sort_order": 3, "is_default": 1, "status": 1 }, { "id": 10, "code": "video_editing", "name": "视频编辑", "sort_order": 4, "is_default": 1, "status": 1 }, { "id": 11, "code": "tandem_list", "name": "串联单", "sort_order": 5, "is_default": 1, "status": 1 }, { "id": 14, "code": "program_render", "name": "节目上传", "sort_order": 6, "is_default": 1, "status": 1 }, { "id": 16, "code": "program_authen", "name": "节目审查", "sort_order": 7, "is_default": 1, "status": 1 } ] }, { "id": 6, "code": "inter_view", "name": "采访任务", "sort_order": 2, "is_default": 0, "status": 1, "steps": [ { "id": 2, "code": "begin_shot", "name": "上传素材", "sort_order": 1, "is_default": 1, "status": 1 }, { "id": 3, "code": "material_review", "name": "素材审核", "sort_order": 2, "is_default": 1, "status": 1 }, { "id": 4, "code": "writing", "name": "撰写稿件", "sort_order": 3, "is_default": 1, "status": 1 }, { "id": 8, "code": "writing_draft", "name": "撰写通稿", "sort_order": 4, "is_default": 1, "status": 1 }, { "id": 7, "code": "manuscript_review", "name": "稿件审核", "sort_order": 5, "is_default": 1, "status": 1 }, { "id": 13, "code": "finish_interview", "name": "结束采访", "sort_order": 6, "is_default": 1, "status": 1 } ] }, { "id": 7, "code": "rich_doc", "name": "互联网发布", "sort_order": 3, "is_default": 0, "status": 1, "steps": [ { "id": 1, "code": "retrieval", "name": "取稿", "sort_order": 1, "is_default": 1, "status": 1 }, { "id": 4, "code": "writing", "name": "撰写稿件", "sort_order": 2, "is_default": 1, "status": 1 }, { "id": 7, "code": "manuscript_review", "name": "稿件审核", "sort_order": 3, "is_default": 1, "status": 1 }, { "id": 9, "code": "newspaper_issued", "name": "报纸签发", "sort_order": 4, "is_default": 1, "status": 1 }, { "id": 12, "code": "wechat_group_reference", "name": "微信组稿引用", "sort_order": 5, "is_default": 1, "status": 1 }, { "id": 15, "code": "website_release", "name": "网站发布", "sort_order": 6, "is_default": 1, "status": 1 }, { "id": 17, "code": "app_release", "name": "APP发布", "sort_order": 7, "is_default": 1, "status": 1 }, { "id": 18, "code": "wechat_release", "name": "微信发布", "sort_order": 8, "is_default": 1, "status": 1 }, { "id": 19, "code": "blog_release", "name": "微博发布", "sort_order": 9, "is_default": 1, "status": 1 }, { "id": 20, "code": "qq_release", "name": "企鹅号发布", "sort_order": 10, "is_default": 1, "status": 1 } ] }, { "id": 8, "code": "other", "name": "手动任务", "sort_order": 4, "is_default": 0, "status": 1, "steps": [ { "id": 2, "code": "begin_shot", "name": "上传素材", "sort_order": 1, "is_default": 1, "status": 1 } ] }, { "id": 17, "code": "zidingyiyi", "name": "自定义一", "sort_order": 5, "is_default": 0, "status": 1, "steps": [ { "id": 2, "code": "begin_shot", "name": "上传素材", "sort_order": 1, "is_default": 1, "status": 1 } ] }, { "id": 22, "code": "zidingyier", "name": "自定义二", "sort_order": 6, "is_default": 0, "status": 1, "steps": [ { "id": 2, "code": "begin_shot", "name": "上传素材", "sort_order": 1, "is_default": 1, "status": 1 } ] }, { "id": 23, "code": "zidingyisan", "name": "自定义三", "sort_order": 7, "is_default": 0, "status": 1, "steps": [ { "id": 2, "code": "begin_shot", "name": "上传素材", "sort_order": 1, "is_default": 1, "status": 1 } ] }, { "id": 24, "code": "zidingyisi", "name": "自定义四十", "sort_order": 9, "is_default": 1, "status": 0, "steps": [ { "id": 4, "code": "writing", "name": "撰写稿件", "sort_order": 3, "is_default": 0, "status": 1 }, { "id": 15, "code": "website_release", "name": "网站发布", "sort_order": 6, "is_default": 1, "status": 1 } ] } ] } }
10、在 Postman 中 PUT:http://api.pcs-api.localhost/v1/config-task-steps/my-group-id ,请求数据(删除 1 项任务配置(自定义三)及其中的 1 项步骤配置;更新 1 项任务配置(自定义四十)及其中的 1 项步骤配置);在最后添加 1 项任务配置(自定义六)及在其中添加 1 项步骤配置与执行的 SQL ( 任务配置表:1 条插入语句、2 条更新语句;任务步骤配置表:1 条插入语句、2 条更新语句) 如下
[ { "code": "tv_broadcast", "name": "电视播出", "sort_order": 1, "is_default": 0, "steps": [ { "code": "begin_shot", "sort_order": 1, "is_default": 1 }, { "code": "writing", "sort_order": 2, "is_default": 1 }, { "code": "manuscript_review", "sort_order": 3, "is_default": 1 }, { "code": "video_editing", "sort_order": 4, "is_default": 1 }, { "code": "tandem_list", "sort_order": 5, "is_default": 1 }, { "code": "program_render", "sort_order": 6, "is_default": 1 }, { "code": "program_authen", "sort_order": 7, "is_default": 1 } ] }, { "code": "inter_view", "name": "采访任务", "sort_order": 2, "is_default": 0, "steps": [ { "code": "begin_shot", "sort_order": 1, "is_default": 1 }, { "code": "material_review", "sort_order": 2, "is_default": 1 }, { "code": "writing", "sort_order": 3, "is_default": 1 }, { "code": "writing_draft", "sort_order": 4, "is_default": 1 }, { "code": "manuscript_review", "sort_order": 5, "is_default": 1 }, { "code": "finish_interview", "sort_order": 6, "is_default": 1 } ] }, { "code": "rich_doc", "name": "互联网发布", "sort_order": 3, "is_default": 0, "steps": [ { "code": "retrieval", "sort_order": 1, "is_default": 1 }, { "code": "writing", "sort_order": 2, "is_default": 1 }, { "code": "manuscript_review", "sort_order": 3, "is_default": 1 }, { "code": "newspaper_issued", "sort_order": 4, "is_default": 1 }, { "code": "wechat_group_reference", "sort_order": 5, "is_default": 1 }, { "code": "website_release", "sort_order": 6, "is_default": 1 }, { "code": "app_release", "sort_order": 7, "is_default": 1 }, { "code": "wechat_release", "sort_order": 8, "is_default": 1 }, { "code": "blog_release", "sort_order": 9, "is_default": 1 }, { "code": "qq_release", "sort_order": 10, "is_default": 1 } ] }, { "code": "other", "name": "手动任务", "sort_order": 4, "is_default": 0, "steps": [ { "code": "begin_shot", "sort_order": 1, "is_default": 1 } ] }, { "code": "zidingyiyi", "name": "自定义一", "sort_order": 5, "is_default": 0, "steps": [ { "code": "begin_shot", "sort_order": 1, "is_default": 1 } ] }, { "code": "zidingyier", "name": "自定义二", "sort_order": 6, "is_default": 0, "steps": [ { "code": "begin_shot", "sort_order": 1, "is_default": 1 } ] }, { "code": "zidingyisi", "name": "自定义四十", "sort_order": 9, "is_default": 0, "steps": [ { "code": "writing", "sort_order": 1, "is_default": 0 }, { "code": "website_release", "sort_order": 6, "is_default": 1 } ] }, { "code": "zidingyiliu", "name": "自定义六", "sort_order": 10, "is_default": 0, "steps": [ { "code": "website_release", "sort_order": 1, "is_default": 1 } ] } ]
SELECT * FROM `pa_config_task` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`is_deleted`=0) SELECT * FROM `pa_config_task` WHERE `group_id`='015ce30b116ce86058fa6ab4fea4ac63' SELECT * FROM `pa_config_task_step` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`is_deleted`=0) SELECT * FROM `pa_config_task_step` WHERE `group_id`='015ce30b116ce86058fa6ab4fea4ac63' SELECT DISTINCT `config_task_id` FROM `pa_plan_task` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_id`=23) AND (`is_deleted`=0) SELECT EXISTS(SELECT * FROM `pa_config_task` WHERE (`pa_config_task`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task`.`code`='zidingyiliu') AND (`pa_config_task`.`is_deleted`=0) AND (`pa_config_task`.`deleted_at`=0)) // 总计 4 次执行 SELECT EXISTS(SELECT * FROM `pa_config_step` WHERE (`pa_config_step`.`code`='website_release') AND (`is_deleted`=0)) SELECT EXISTS(SELECT * FROM `pa_config_task_step` WHERE (`pa_config_task_step`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task_step`.`config_task_code`='zidingyiliu') AND (`pa_config_task_step`.`step_code`='website_release') AND (`pa_config_task_step`.`is_deleted`=0) AND (`pa_config_task_step`.`deleted_at`=0)) // 总计 5 次执行 Begin transaction UPDATE `pa_config_task` SET `is_deleted`=1, `deleted_at`=1574755354 WHERE `id`=23 SELECT * FROM `pa_config_task` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`code`='tv_broadcast') // 总计 8 次执行【SELECT * FROM `pa_config_task` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`code`=】 UPDATE `pa_config_task` SET `is_default`=0, `updated_at`=1574755354 WHERE `id`=24 INSERT INTO `pa_config_task` (`group_id`, `code`, `name`, `sort_order`, `is_default`, `is_deleted`, `deleted_at`, `category`, `parameter`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'zidingyiliu', '自定义六', 10, 0, 0, 0, 2, 's:0:\"\";', 1, 1574755354, 1574755354) UPDATE `pa_config_task_step` SET `is_deleted`=1, `deleted_at`=1574755354 WHERE `id`=126 SELECT * FROM `pa_config_task` WHERE `group_id`='015ce30b116ce86058fa6ab4fea4ac63' SELECT * FROM `pa_config_step` WHERE `is_deleted`=0 SELECT * FROM `pa_config_task_step` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_code`='tv_broadcast') AND (`step_code`='begin_shot') // 总计 29 次执行【SELECT * FROM `pa_config_task_step` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_code`=】 UPDATE `pa_config_task_step` SET `sort_order`=1, `updated_at`=1574755354 WHERE `id`=128 INSERT INTO `pa_config_task_step` (`group_id`, `config_task_code`, `step_code`, `sort_order`, `is_default`, `is_deleted`, `deleted_at`, `config_task_id`, `config_step_id`, `step_name`, `up_status_type`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'zidingyiliu', 'website_release', 1, 1, 0, 0, 26, 15, '网站发布', 2, 1, 1574755354, 1574755354) Commit transaction
11、新建 新建任务配置 的方法文件,\api\rests\config_task\CreateAction.php
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\config_task; use Yii; use api\models\ConfigTask; use api\models\ConfigTaskStep; use api\models\redis\cmc_console\User as RedisCmcConsoleUser; use api\services\ConfigTaskStepService; use yii\base\Model; use yii\base\InvalidConfigException; use yii\helpers\ArrayHelper; use yii\web\UnprocessableEntityHttpException; use yii\web\ServerErrorHttpException; /** * 新建任务配置:/config-tasks(config-task/create) * * For more details and usage information on CreateAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class CreateAction extends Action { /** * @var string the scenario to be assigned to the new model before it is validated and saved. */ public $scenario = Model::SCENARIO_DEFAULT; /** * @var string the name of the view action. This property is need to create the URL when the model is successfully created. */ public $viewAction = 'view'; /** * Creates a new model. * @return array the model newly created * @throws InvalidConfigException if a registered parser does not implement the [[RequestParserInterface]]. * @throws ServerErrorHttpException if there is any error when creating the model * @throws UnprocessableEntityHttpException * @throws \Throwable */ public function run() { if ($this->checkAccess) { call_user_func($this->checkAccess, $this->id); } // 当前用户的身份实例,未认证用户则为 Null /* @var $identity RedisCmcConsoleUser */ $identity = Yii::$app->user->identity; /* @var $modelClass ConfigTask */ $modelClass = $this->modelClass; $requestParams = Yii::$app->getRequest()->getBodyParams(); // 检查 任务配置的(代码、名称、顺序) 是否存在 if (!ArrayHelper::keyExists('code', $requestParams) || !ArrayHelper::keyExists('name', $requestParams) || !ArrayHelper::keyExists('sort_order', $requestParams)) { throw new UnprocessableEntityHttpException(Yii::t('error', '226080'), 226080); } $isDefault = isset($requestParams['is_default']) ? $requestParams['is_default'] : $modelClass::IS_DEFAULT_NO; $status = isset($requestParams['status']) ? $requestParams['status'] : $modelClass::STATUS_ENABLED; $configTask = [ 'group_id' => $identity->group_id, 'code' => $requestParams['code'], 'name' => $requestParams['name'], 'sort_order' => $requestParams['sort_order'], 'is_default' => $isDefault, 'status' => $status, ]; $configTaskSteps = []; // 检查 步骤配置列表 是否存在 if (ArrayHelper::keyExists('steps', $requestParams)) { foreach ($requestParams['steps'] as $configTaskStep) { // 检查 步骤代码、顺序、是否默认步骤 是否存在 if (!ArrayHelper::keyExists('code', $configTaskStep) || !ArrayHelper::keyExists('sort_order', $configTaskStep) || !ArrayHelper::keyExists('is_default', $configTaskStep)) { throw new UnprocessableEntityHttpException(Yii::t('error', '226080'), 226080); } $configTaskSteps[$requestParams['code'] . ':' . $configTaskStep['code']] = [ 'group_id' => $identity->group_id, 'config_task_code' => $requestParams['code'], 'step_code' => $configTaskStep['code'], 'sort_order' => $configTaskStep['sort_order'], 'is_default' => $configTaskStep['is_default'], ]; } } /* 任务配置 */ /* @var $model ConfigTask */ $model = new $modelClass([ 'scenario' => $modelClass::SCENARIO_CREATE, ]); // 把请求数据填充到模型中 if (!$model->load($configTask, '')) { return ['code' => 226010, 'message' => Yii::t('error', '226010')]; } // 验证模型 if (!$model->validate()) { $modelResult = self::handleValidateError($model); if ($modelResult['status'] === false) { return ['code' => $modelResult['code'], 'message' => $modelResult['message']]; } } /* 任务步骤配置 */ $configTaskSteps = array_values($configTaskSteps); $configTaskStepModels = []; $count = count($configTaskSteps); if ($count > 0) { // 创建一个初始的 $configTaskStepModels 数组包含一个默认的模型 $configTaskStepModels = [ new ConfigTaskStep([ 'scenario' => ConfigTaskStep::SCENARIO_CREATE, ]) ]; for ($i = 1; $i < $count; $i++) { $configTaskStepModels[] = new ConfigTaskStep([ 'scenario' => ConfigTaskStep::SCENARIO_CREATE, ]); } // 批量填充模型属性 if (!Model::loadMultiple($configTaskStepModels, $configTaskSteps, '')) { return ['code' => 226010, 'message' => Yii::t('error', '226010')]; } // 批量验证模型 if (!Model::validateMultiple($configTaskStepModels)) { $configTaskStepModelsResult = self::handleValidateMultipleError($configTaskStepModels); if ($configTaskStepModelsResult['status'] === false) { return ['code' => $configTaskStepModelsResult['code'], 'message' => $configTaskStepModelsResult['message']]; } } } /* 操作数据(事务) */ $configTaskStepService = new ConfigTaskStepService(); $result = $configTaskStepService->create($model, $configTaskStepModels, $identity); if ($result['status'] === false) { throw new ServerErrorHttpException($result['message'], $result['code']); } return ['code' => 10000, 'message' => Yii::t('success', '126043')]; } }
12、新建 更新任务配置 的方法文件,\api\rests\config_task\UpdateAction.php
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\config_task; use Yii; use api\models\ConfigTask; use api\models\ConfigTaskStep; use api\models\redis\cmc_console\User as RedisCmcConsoleUser; use api\services\ConfigTaskStepService; use yii\base\Model; use yii\base\InvalidConfigException; use yii\helpers\ArrayHelper; use yii\web\UnprocessableEntityHttpException; use yii\web\ServerErrorHttpException; /** * 更新任务配置:/config-tasks/{id}(config-task/update) * * For more details and usage information on CreateAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class UpdateAction extends Action { /** * @var string the scenario to be assigned to the model before it is validated and updated. * $id {config_column_id} */ public $scenario = Model::SCENARIO_DEFAULT; /** * Updates an existing model. * @param string $id the primary key of the model. * @return array the model being updated * @throws InvalidConfigException if a registered parser does not implement the [[RequestParserInterface]]. * @throws ServerErrorHttpException if there is any error when updating the model * @throws \Throwable */ public function run($id) { /* @var $model ConfigTask */ $model = $this->findModel($id); if ($this->checkAccess) { call_user_func($this->checkAccess, $this->id, $model); } // 当前用户的身份实例,未认证用户则为 Null /* @var $identity RedisCmcConsoleUser */ $identity = Yii::$app->user->identity; /* @var $modelClass ConfigTask */ $modelClass = $this->modelClass; $requestParams = Yii::$app->getRequest()->getBodyParams(); $model->scenario = $model::SCENARIO_UPDATE; // 把请求数据填充到模型中 if (!$model->load(Yii::$app->getRequest()->getBodyParams(), '')) { return ['code' => 226010, 'message' => Yii::t('error', '226010')]; } // 验证模型 if (!$model->validate()) { $modelResult = self::handleValidateError($model); if ($modelResult['status'] === false) { return ['code' => $modelResult['code'], 'message' => $modelResult['message']]; } } $configTaskSteps = []; // 检查 步骤配置列表 是否存在 if (ArrayHelper::keyExists('steps', $requestParams)) { foreach ($requestParams['steps'] as $configTaskStep) { // 检查 步骤代码、顺序、是否默认步骤 是否存在 if (!ArrayHelper::keyExists('code', $configTaskStep) || !ArrayHelper::keyExists('sort_order', $configTaskStep) || !ArrayHelper::keyExists('is_default', $configTaskStep)) { throw new UnprocessableEntityHttpException(Yii::t('error', '226080'), 226080); } $configTaskSteps[$configTaskStep['code']] = [ 'group_id' => $identity->group_id, 'config_task_code' => $model->code, 'step_code' => $configTaskStep['code'], 'sort_order' => $configTaskStep['sort_order'], 'is_default' => $configTaskStep['is_default'], ]; } } /* @var $configGroupTaskStepItem ConfigTaskStep */ // 基于 租户ID、任务配置ID 查找资源(任务步骤配置、是否被删除:否)列表 $configTaskStepIsDeletedNoItems = ConfigTaskStep::find()->where(['group_id' => $identity->group_id, 'config_task_id' => $model->id])->isDeletedNo()->indexBy(['step_code'])->all(); // 基于 租户ID、任务配置ID 查找资源(任务步骤配置)列表 $configTaskStepItems = ConfigTaskStep::find()->where(['group_id' => $identity->group_id, 'config_task_id' => $model->id])->indexBy(['step_code'])->all(); /* 任务步骤配置 */ // 使用键名比较计算数组的差集,如果不为空,则删除 (软删除) 出现在 任务步骤配置模型(MySQL) 中但是未出现在 任务步骤配置 中的记录 $configTaskStepDiffItems = array_diff_key($configTaskStepIsDeletedNoItems, $configTaskSteps); $configTaskSteps = array_values($configTaskSteps); $configTaskStepModels = []; foreach ($configTaskSteps as $configTaskStep) { $index = $configTaskStep['step_code']; if (isset($configTaskStepItems[$index])) { $configTaskStepItems[$index]->scenario = ConfigTaskStep::SCENARIO_UPDATE; $configTaskStepModels[] = $configTaskStepItems[$index]; } else { $configTaskStepModels[] = new ConfigTaskStep([ 'scenario' => ConfigTaskStep::SCENARIO_CREATE, ]); } } // 批量填充模型属性 if (!empty($configTaskStepModels) && !Model::loadMultiple($configTaskStepModels, $configTaskSteps, '')) { return ['code' => 226010, 'message' => Yii::t('error', '226010')]; } // 批量验证模型 if (!empty($configTaskStepModels) && !Model::validateMultiple($configTaskStepModels)) { $configTaskStepModelsResult = self::handleValidateMultipleError($configTaskStepModels); if ($configTaskStepModelsResult['status'] === false) { return ['code' => $configTaskStepModelsResult['code'], 'message' => $configTaskStepModelsResult['message']]; } } /* 操作数据(事务) */ $configTaskStepService = new ConfigTaskStepService(); $result = $configTaskStepService->update($model, $configTaskStepDiffItems, $configTaskStepModels, $identity); if ($result['status'] === false) { throw new ServerErrorHttpException($result['message'], $result['code']); } return ['code' => 10000, 'message' => Yii::t('success', '126039')]; } }
13、新建 删除任务配置 的方法文件,\api\rests\config_task\DeleteAction.php
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\config_task; use Yii; use api\models\ConfigTask; use api\models\ConfigTaskStep; use api\services\ConfigTaskStepService; use yii\base\Model; use yii\web\NotFoundHttpException; use yii\web\ServerErrorHttpException; /** * 删除任务配置:/config-tasks/{id}(config-task/delete) * * For more details and usage information on CreateAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class DeleteAction extends Action { /** * @var string the scenario to be assigned to the model before it is validated and updated. */ public $scenario = Model::SCENARIO_DEFAULT; /** * Updates an existing model. * @param string $id the primary key of the model. * @return array the model being updated * @throws NotFoundHttpException if the model cannot be found * @throws ServerErrorHttpException if there is any error when updating the model * @throws \Throwable */ public function run($id) { /* @var $model ConfigTask */ $model = $this->findModel($id); if ($this->checkAccess) { call_user_func($this->checkAccess, $this->id, $model); } $model->scenario = $model::SCENARIO_DELETE; if ($model->validate()) { // 基于 租户ID、任务配置ID 查找资源(任务步骤配置、是否被删除:否)列表 $configTaskStepIsDeletedNoItems = ConfigTaskStep::find()->where(['group_id' => $model->group_id, 'config_task_id' => $model->id])->isDeletedNo()->all(); /* 操作数据(事务) */ $transaction = Yii::$app->db->beginTransaction(); try { if ($model->softDelete() === false) { throw new ServerErrorHttpException('Failed to delete the object for unknown reason.'); } // 删除 (软删除) 出现在 任务步骤配置模型(MySQL) 中的记录 $configTaskStepService = new ConfigTaskStepService(); $configTaskStepService->deleteMultiple($configTaskStepIsDeletedNoItems); $transaction->commit(); } catch(\Throwable $e) { $transaction->rollBack(); throw $e; } } elseif ($model->hasErrors()) { $response = Yii::$app->getResponse(); $response->setStatusCode(422, 'Data Validation Failed.'); $firstError = ''; foreach ($model->getFirstErrors() as $message) { $firstError = $message; break; } return ['code' => 226004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '226004'), ['first_error' => $firstError]))]; } elseif (!$model->hasErrors()) { throw new ServerErrorHttpException('Failed to create the object for unknown reason.'); } return ['code' => 10000, 'message' => Yii::t('success', '126045')]; } }
14、在 Postman 中 POST:http://api.pcs-api.localhost/v1/config-tasks ,请求数据与执行的 SQL ( 任务配置表:1 条插入语句、1 条更新语句;任务步骤配置表:2 条插入语句) 如下
{ "code": "zidingyiqi", "name": "自定义七", "sort_order": 11, "is_default": 1, "status": 1, "steps": [ { "code": "begin_shot", "sort_order": 1, "is_default": 1 }, { "code": "writing", "sort_order": 2, "is_default": 1 } ] }
SELECT EXISTS(SELECT * FROM `pa_config_task` WHERE (`pa_config_task`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task`.`code`='zidingyiqi') AND (`pa_config_task`.`is_deleted`=0) AND (`pa_config_task`.`deleted_at`=0)) // 总计 4 次执行 SELECT EXISTS(SELECT * FROM `pa_config_step` WHERE (`pa_config_step`.`code`='begin_shot') AND (`is_deleted`=0)) // 总计 2 次执行【SELECT EXISTS(SELECT * FROM `pa_config_step` WHERE (`pa_config_step`.`code`=】 SELECT EXISTS(SELECT * FROM `pa_config_task_step` WHERE (`pa_config_task_step`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task_step`.`config_task_code`='zidingyiqi') AND (`pa_config_task_step`.`step_code`='begin_shot') AND (`pa_config_task_step`.`is_deleted`=0) AND (`pa_config_task_step`.`deleted_at`=0)) // 总计 10 次执行【SELECT EXISTS(SELECT * FROM `pa_config_task_step` WHERE (`pa_config_task_step`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task_step`.`config_task_code`='zidingyiqi') AND (`pa_config_task_step`.`step_code`=】 Begin transaction INSERT INTO `pa_config_task` (`group_id`, `code`, `name`, `sort_order`, `is_default`, `status`, `is_deleted`, `deleted_at`, `category`, `parameter`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'zidingyiqi', '自定义七', 11, 1, 1, 0, 0, 2, 's:0:\"\";', 1574756713, 1574756713) UPDATE `pa_config_task` SET `is_default`=0 WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`is_deleted`=0) AND (`id` != 27) SELECT * FROM `pa_config_task` WHERE `group_id`='015ce30b116ce86058fa6ab4fea4ac63' SELECT * FROM `pa_config_step` WHERE `is_deleted`=0 INSERT INTO `pa_config_task_step` (`group_id`, `config_task_code`, `step_code`, `sort_order`, `is_default`, `is_deleted`, `deleted_at`, `config_task_id`, `config_step_id`, `step_name`, `up_status_type`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'zidingyiqi', 'begin_shot', 1, 1, 0, 0, 27, 2, '上传素材', 2, 1, 1574756713, 1574756713) INSERT INTO `pa_config_task_step` (`group_id`, `config_task_code`, `step_code`, `sort_order`, `is_default`, `is_deleted`, `deleted_at`, `config_task_id`, `config_step_id`, `step_name`, `up_status_type`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'zidingyiqi', 'writing', 2, 1, 0, 0, 27, 4, '撰写稿件', 2, 1, 1574756713, 1574756713) Commit transaction
15、在 Postman 中 PUT:http://api.pcs-api.localhost/v1/config-tasks/27 ,请求数据与执行的 SQL ( 任务配置表:2 条更新语句;任务步骤配置表:2 条插入语句、2 条更新语句) 如下
{ "name": "自定义七", "sort_order": 11, "is_default": 1, "status": 0, "steps": [ { "code": "writing", "sort_order": 1, "is_default": 0 }, { "code": "website_release", "sort_order": 2, "is_default": 1 }, { "code": "wechat_release", "sort_order": 3, "is_default": 1 } ] }
SELECT * FROM `pa_config_task` WHERE (`id`='27') AND (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`is_deleted`=0) SELECT * FROM `pa_config_task_step` WHERE ((`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_id`=27)) AND (`is_deleted`=0) SELECT * FROM `pa_config_task_step` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_id`=27) SELECT EXISTS(SELECT * FROM `pa_config_step` WHERE (`pa_config_step`.`code`='website_release') AND (`is_deleted`=0)) // 总计 2 次执行【SELECT EXISTS(SELECT * FROM `pa_config_step` WHERE (`pa_config_step`.`code`=】 SELECT EXISTS(SELECT * FROM `pa_config_task_step` WHERE (`pa_config_task_step`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task_step`.`config_task_code`='zidingyiqi') AND (`pa_config_task_step`.`step_code`='website_release') AND (`pa_config_task_step`.`is_deleted`=0) AND (`pa_config_task_step`.`deleted_at`=0)) // 总计 10 次执行【SELECT EXISTS(SELECT * FROM `pa_config_task_step` WHERE (`pa_config_task_step`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task_step`.`config_task_code`=】 Begin transaction UPDATE `pa_config_task` SET `status`=0, `updated_at`=1574757171 WHERE `id`=27 UPDATE `pa_config_task` SET `is_default`=0 WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`is_deleted`=0) AND (`id` != 27) UPDATE `pa_config_task_step` SET `is_deleted`=1, `deleted_at`=1574757171 WHERE `id`=131 SELECT * FROM `pa_config_task` WHERE `group_id`='015ce30b116ce86058fa6ab4fea4ac63' SELECT * FROM `pa_config_step` WHERE `is_deleted`=0 SELECT * FROM `pa_config_task_step` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_code`='zidingyiqi') AND (`step_code`='writing') // 总计 3 次执行【SELECT * FROM `pa_config_task_step` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_code`=】 UPDATE `pa_config_task_step` SET `sort_order`=1, `is_default`=0, `updated_at`=1574757171 WHERE `id`=132 INSERT INTO `pa_config_task_step` (`group_id`, `config_task_code`, `step_code`, `sort_order`, `is_default`, `is_deleted`, `deleted_at`, `config_task_id`, `config_step_id`, `step_name`, `up_status_type`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'zidingyiqi', 'website_release', 2, 1, 0, 0, 27, 15, '网站发布', 2, 1, 1574757171, 1574757171) INSERT INTO `pa_config_task_step` (`group_id`, `config_task_code`, `step_code`, `sort_order`, `is_default`, `is_deleted`, `deleted_at`, `config_task_id`, `config_step_id`, `step_name`, `up_status_type`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'zidingyiqi', 'wechat_release', 3, 1, 0, 0, 27, 18, '微信发布', 2, 1, 1574757171, 1574757171) Commit transaction
16、在 Postman 中 DELETE:http://api.pcs-api.localhost/v1/config-tasks/27 ,执行的 SQL ( 任务配置表:1 条更新语句;任务步骤配置表:3 条更新语句) 如下
SELECT * FROM `pa_config_task` WHERE (`id`='27') AND (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`is_deleted`=0) SELECT DISTINCT `config_task_id` FROM `pa_plan_task` WHERE (`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_id`=27) AND (`is_deleted`=0) SELECT `pa_config_task`.`id` FROM `pa_config_task` WHERE (`pa_config_task`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task`.`code`='zidingyiqi') AND (`pa_config_task`.`is_deleted`=0) AND (`pa_config_task`.`deleted_at`=0) LIMIT 2 // 总计 4 次执行【SELECT `pa_config_task`.`id` FROM `pa_config_task` WHERE (`pa_config_task`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`pa_config_task`.`code`=】 SELECT * FROM `pa_config_task_step` WHERE ((`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`config_task_id`=27)) AND (`is_deleted`=0) Begin transaction UPDATE `pa_config_task` SET `is_deleted`=1, `deleted_at`=1574757947 WHERE `id`=27 UPDATE `pa_config_task_step` SET `is_deleted`=1, `deleted_at`=1574757947 WHERE `id`=133 UPDATE `pa_config_task_step` SET `is_deleted`=1, `deleted_at`=1574757947 WHERE `id`=134 UPDATE `pa_config_task_step` SET `is_deleted`=1, `deleted_at`=1574757947 WHERE `id`=132 Commit transaction
近期评论