1、编辑 /api/config/urlManager.php,定义路由以支持 PUT close/{id}
// 任务管理
[
'class' => 'yii/rest/UrlRule',
'controller' => ['v1/plan-task'],
'only' => ['index', 'create', 'view', 'update', 'claim', 'delete', 'finish', 'transfer', 'video-edit', 'write', 'commit-article', 'article-review', 'close'],
'tokens' => ['{id}' => '<id://w[//w,:;]*>'],
'extraPatterns' => [
'PUT claim/{id}' => 'claim',
'DELETE /{id}' => '',
'PUT finish/{id}' => 'finish',
'GET {id}' => 'view',
'PUT update' => 'update',
'PUT transfer/{id}' => 'transfer',
'GET video-edit/{id}' => 'video-edit',
'GET write/{id}' => 'write',
'GET commit-article/{id}' => 'commit-article',
'GET article-review/{id}' => 'article-review',
'PUT close/{id}' => 'close',
],
],
2、编辑 /api/controllers/PlanTaskController.php,定义动作以支持 close 方法
<?php
/**
* Created by PhpStorm.
* User: WangQiang
* Date: 2018/05/05
* Time: 11:43
*/
namespace api/controllers;
use yii/rest/ActiveController;
class PlanTaskController extends ActiveController
{
public $serializer = [
'class' => 'api/rests/plan_task/Serializer',
'collectionEnvelope' => 'items',
];
/**
* @inheritdoc
*/
public function actions()
{
$actions = parent::actions();
// 禁用"options"动作
unset($actions['options']);
$actions['index']['class'] = 'api/rests/plan_task/IndexAction';
$actions['create']['class'] = 'api/rests/plan_task/CreateAction';
$actions['view']['class'] = 'api/rests/plan_task/ViewAction';
$actions['update']['class'] = 'api/rests/plan_task/UpdateAction';
$actions['delete']['class'] = 'api/rests/plan_task/DeleteAction';
$actions['claim'] = [
'class' => 'api/rests/plan_task/ClaimAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['finish'] = [
'class' => 'api/rests/plan_task/FinishAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['transfer'] = [
'class' => 'api/rests/plan_task/TransferAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['video-edit'] = [
'class' => 'api/rests/plan_task/VideoEditAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['write'] = [
'class' => 'api/rests/plan_task/WriteAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['commit-article'] = [
'class' => 'api/rests/plan_task/CommitArticleAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['article-review'] = [
'class' => 'api/rests/plan_task/ArticleReviewAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['close'] = [
'class' => 'api/rests/plan_task/CloseAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
return $actions;
}
}
3、编辑 /api/rests/plan_task/Action.php,复制 public function findModel($id) 为 public function findModels($id),以支持查找多个模型
/**
* Returns the data model based on the primary key given.
* If the data model is not found, a 404 HTTP exception will be raised.
* @param string $id the ID of the model to be loaded. If the model has a composite primary key,
* the ID must be a string of the primary key values separated by commas.
* The order of the primary key values should follow that returned by the `primaryKey()` method
* of the model.
* @return ActiveRecordInterface the model found
* @throws NotFoundHttpException if the model cannot be found
*/
public function findModels($id)
{
if ($this->findModel !== null) {
return call_user_func($this->findModel, $id, $this);
}
/* @var $modelClass ActiveRecordInterface */
$modelClass = $this->modelClass;
$keys = $modelClass::primaryKey();
if (count($keys) > 1) {
$values = explode(',', $id);
if (count($keys) === count($values)) {
$model = $modelClass::find()->where(['in', $keys, $values])->indexBy($keys)->all();
}
} elseif ($id !== null) {
$values = explode(';', $id);
$model = $modelClass::find()->where(['in', 'id', $values])->indexBy('id')->all();
}
if (!empty($model)) {
// ID的数目与模型资源数目是否相等,如果不相等,响应失败
$flipValues = array_flip($values);
if (count($model) == count($flipValues)) {
return $model;
} else {
$id = implode(";", array_keys(array_diff_key($flipValues, $model)));
}
}
throw new NotFoundHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '20014'), ['id' => $id])), 20014);
}
4、所有ID皆必须存在,否则响应失败,如图1
5、新建 /api/rests/plan_task/CloseAction.php,支持 批量验证模型、批量更新模型
<?php
namespace api/rests/plan_task;
use Yii;
use yii/base/Model;
use yii/db/ActiveRecord;
use api/models/PlanTask;
use yii/web/ServerErrorHttpException;
/**
* 关闭(关闭任务)
*
* 1、请求参数列表
* (1)ids 必填,多个ID(以半角;分隔);
*
* 2、输入数据验证规则
* (1)必填:ids;
* (2)所有选题任务ID皆必须存在;
* (3)所有选题任务状态皆必须为,1:未开始;2:进行中(已认领);
* (4)选题创建用户ID为当前登录用户ID || (栏目人员配置租户ID为当前登录用户租户ID && 栏目人员配置角色标识包含栏目负责人标识 && 栏目人员配置状态的非取值范围 -1、0);
*
* 3、操作数据(事务)
* (1)更新选题任务的状态,4:关闭;
*
* For more details and usage information on CloseAction, see the [guide article on rest controllers](guide:rest-controllers).
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class CloseAction extends Action
{
/**
* Updates an existing model.
*
* @param string $id the primary key of the model.
*
* @return /yii/db/ActiveRecordInterface the model being updated
* @throws ServerErrorHttpException if there is any error when updating the model
*/
public function run($id)
{
/* @var $model ActiveRecord */
$models = $this->findModels($id);
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id, $models);
}
// 状态,不是 1:未开始;2:进行中(已认领) 的ID
$ids = [];
foreach ($models as $key => $model) {
$model->scenario = 'close';
$models[$key] = $model;
if ($model->status != PlanTask::PLAN_TASK_STATUS_NOT_BEGINNING && $model->status != PlanTask::PLAN_TASK_STATUS_BEGINNING) {
$ids[] = $model->id;
}
}
if (!empty($ids)) {
$ids = implode(";", $ids);
return ['code' => 20036, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20036'), ['ids' => $ids]))];
}
// 批量验证模型
if (Model::validateMultiple($models)) {
$modelResult = $model->closeMultiple($models);
if (!$modelResult) {
return ['code' => 20038, 'message' => Yii::t('error', '20038')];
}
} else {
foreach ($models as $model) {
if ($model->hasErrors()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(422, 'Data Validation Failed.');
foreach ($model->getFirstErrors() as $message) {
$firstErrors = $message;
break;
}
return ['code' => 20004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20004'), ['firstErrors' => $firstErrors]))];
}
}
throw new ServerErrorHttpException('Failed to update the object for unknown reason.');
}
foreach ($models as $key => $model) {
$model->task_data = unserialize($model->task_data);
$models[$key] = $model;
}
return ['code' => 10000, 'message' => Yii::t('success', '10017'), 'data' => ['items' => array_values($models)]];
}
}
6、编辑 /common/logics/PlanTask.php,支持 验证规则定义、批量更新模型
/**
* @inheritdoc
*/
public function rules()
{
$rules = [
/* 关闭(关闭任务) */
[['id'], 'validateClosePermission', 'on' => 'close'], //close
];
$parentRules = parent::rules();
return ArrayHelper::merge($rules, $parentRules);
}
/**
* Validates the close permission.
* This method serves as the inline validation for close permission.
*
* @param string $attribute the attribute currently being validated
* @param array $params the additional name-value pairs given in the rule
*/
public function validateClosePermission($attribute, $params)
{
if (!$this->hasErrors()) {
// 当前用户的身份实例,未认证用户则为 Null
$identity = Yii::$app->user->identity;
if (!$this->checkColumnOrPlanOwner($identity->group_id, $identity->login_name)) {
$this->addError($attribute, Yii::t('error', '20037'));
}
}
}
/**
* 批量关闭(关闭任务)
*
* @param $models
*
* @return bool the saved model or false if saving fails
* @throws /Throwable
*/
public function closeMultiple($models)
{
$transaction = Yii::$app->db->beginTransaction();
try {
foreach ($models as $model) {
$model->status = self::PLAN_TASK_STATUS_CLOSE;
if(!$model->save(false)) {
throw new ServerErrorHttpException(Yii::t('error', '20038'), 20038);
}
}
$transaction->commit();
return true;
} catch (/Throwable $e) {
$transaction->rollBack();
throw $e;
}
}
7、执行结果成功,批量更新模型成功,响应成功更新后的模型数据,如图2
{
"code": 10000,
"message": "关闭(关闭任务)成功",
"data": {
"items": [
{
"id": 14,
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"config_column_id": 1,
"plan_id": 1,
"sort_order": 1,
"title": "无线成都1的任务2",
"config_task_id": 1,
"create_user_id": 8,
"create_name": "13281105967",
"exec_user_id": 186,
"exec_name": "test2",
"place": "<p>选题摘要</p>",
"task_info": "",
"task_data": [],
"ended_at": 1530696654,
"current_step_id": 0,
"status": 4,
"created_at": 1528104654,
"updated_at": 1528270437
},
{
"id": 15,
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"config_column_id": 1,
"plan_id": 1,
"sort_order": 1,
"title": "无线成都1的任务1",
"config_task_id": 1,
"create_user_id": 8,
"create_name": "13281105967",
"exec_user_id": 185,
"exec_name": "test1",
"place": "地点",
"task_info": "<p>选题摘要</p>",
"task_data": [],
"ended_at": 1530754303,
"current_step_id": 90,
"status": 4,
"created_at": 1528162303,
"updated_at": 1528270437
}
]
}
}
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/webdev/181134.html
