作者 ZhengBing He

售后工单后端接口测试

  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\WorkOrder;
  4 +
  5 +use App\Enums\Common\Code;
  6 +use App\Http\Controllers\Aside\BaseController;
  7 +use App\Http\Requests\Aside\WorkOrder\WorkOrderListRequest;
  8 +use App\Http\Requests\Aside\WorkOrder\WorkOrderUpdateRequest;
  9 +use App\Models\WorkOrder\WorkOrder;
  10 +use App\Models\WorkOrder\WorkOrderLog;
  11 +
  12 +class WorkOrderController extends BaseController
  13 +{
  14 + /**
  15 + * A端工单列表
  16 + * 显示有我参与的工单列表
  17 + */
  18 + public function index(WorkOrderListRequest $request)
  19 + {
  20 + /*
  21 + * A端工程师工单列表, 查询我的工单
  22 + */
  23 + $request->validated();
  24 + # manage_id 或 engineer_id 是我
  25 + $lists = WorkOrderLog::with([
  26 + 'workOrder.logs.manager:id,name',
  27 + ])
  28 + ->where('manage_id', $this->manage['id'])
  29 + ->when($request->has('status'), function ($query) use ($request) {
  30 + return $query->where('status', $request->input('status'));
  31 + })
  32 + ->when($request->has('search'), function ($query) use ($request) {
  33 + return $query->whereHas('workOrder', function ($q) use ($request) {
  34 + $q->where('product', 'like', '%' . $request->input('search') . '%')
  35 + ->orWhere('content', 'like', '%' . $request->input('search') . '%');
  36 + });
  37 + })
  38 + ->orderBy('id', 'desc')
  39 + ->paginate($this->row, ['*'], 'page', $this->page);
  40 + $this->response('success', Code::SUCCESS, $lists);
  41 + }
  42 +
  43 +
  44 + /**
  45 + * @param WorkOrderListRequest $request
  46 + * @return void
  47 + * A端管理员的工单列表
  48 + */
  49 + public function manager(WorkOrderListRequest $request)
  50 + {
  51 + $request->validated();
  52 + // 管理员查看所有工单
  53 + $lists = WorkOrder::with([
  54 + 'user:id,name',
  55 + 'manager:id,name',
  56 + 'engineer:id,name',
  57 + 'logs.manager:id,name',
  58 + ])
  59 + ->when($request->has('status'), function ($query) use ($request) {
  60 + return $query->where('status', $request->input('status'));
  61 + })
  62 + ->when($request->has('search'), function ($query) use ($request) {
  63 + return $query->where('product', 'like', '%' . $request->input('search') . '%')
  64 + ->orWhere('content', 'like', '%' . $request->input('search') . '%');
  65 + })
  66 + ->orderBy('id', 'desc')
  67 + ->paginate($this->row, ['*'], 'page', $this->page);
  68 + $this->response('success', Code::SUCCESS, $lists);
  69 + }
  70 +
  71 + /**
  72 + * A端工单详情
  73 + *
  74 + * @param int $id
  75 + * @return \Illuminate\Http\Response
  76 + */
  77 + public function show($id)
  78 + {
  79 + $workOrder = WorkOrder::with([
  80 + 'logs.manager:id,name',
  81 + 'user:id,name',
  82 + 'manager:id,name',
  83 + 'engineer:id,name',
  84 + ])->find($id);
  85 +
  86 + if (!$workOrder)
  87 + $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);
  88 +
  89 + // TODO 判断是否有查看工单详情权限,待添加
  90 + $this->response('success', Code::SUCCESS, $workOrder->toArray());
  91 + }
  92 +
  93 + /**
  94 + * A端更新工单
  95 + * 要么更新状态,要么分配工程师
  96 + */
  97 + public function update(WorkOrderUpdateRequest $request, $id)
  98 + {
  99 + $request->validated();
  100 + // 更新工单状态
  101 + $workOrder = WorkOrder::find($id);
  102 + if (!$workOrder) {
  103 + $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);
  104 + }
  105 + if ($request->has('status'))
  106 + $workOrder->status = $request->input('status');
  107 + if ($request->has('engineer_id'))
  108 + {
  109 + try {
  110 + // 利用唯一索引去重
  111 + $log = new WorkOrderLog();
  112 + $log->manage_id = $request->input('engineer_id');
  113 + $workOrder->logs()->save($log);
  114 + }catch (\Exception $exception){}
  115 + $workOrder->engineer_id = $request->input('engineer_id');
  116 + }
  117 + $workOrder->save();
  118 + $this->response('success', Code::SUCCESS, $workOrder->toArray());
  119 + }
  120 +
  121 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Bside\WorkOrder;
  4 +
  5 +use App\Enums\Common\Code;
  6 +use App\Http\Controllers\Bside\BaseController;
  7 +use App\Http\Requests\Aside\WorkOrder\WorkOrderListRequest;
  8 +use App\Http\Requests\Bside\WorkOrder\WorkOrderCreateRequest;
  9 +use App\Http\Requests\Bside\WorkOrder\WorkOrderUpdateRequest;
  10 +use App\Models\Project\Project;
  11 +use App\Models\WorkOrder\WorkOrder;
  12 +use App\Models\WorkOrder\WorkOrderLog;
  13 +use Illuminate\Support\Facades\DB;
  14 +
  15 +class WorkOrderController extends BaseController
  16 +{
  17 + /**
  18 + * B端售后工单列表
  19 + *
  20 + * @return \Illuminate\Http\Response
  21 + */
  22 + public function index(WorkOrder $workOrder, WorkOrderListRequest $request)
  23 + {
  24 + $request->validated();
  25 + $where = [
  26 + 'project_id' => $this->user['project_id'],
  27 + ];
  28 + // 分页查询
  29 + $lists = $workOrder->where($where)
  30 + ->when($request->input('status'), function ($query) use ($request) {
  31 + return $query->where('status', $request->input('status'));
  32 + })
  33 + ->when($request->input('search'), function ($query) use ($request) {
  34 + return $query->where('product', 'like', '%' . $request->input('search') . '%')
  35 + ->orWhere('content', 'like', '%' . $request->input('search') . '%');
  36 + })
  37 + ->orderBy('id', 'desc')->paginate($this->row, ['*'], 'page', $this->page);
  38 + $this->response('success', Code::SUCCESS, $lists);
  39 + }
  40 +
  41 + /**
  42 + * B端用户提交工单
  43 + *
  44 + * @return \Illuminate\Http\Response
  45 + */
  46 + public function store(WorkOrderCreateRequest $request)
  47 + {
  48 + $request->validated();
  49 + $result = DB::transaction(function () use ($request) {
  50 + $workOrder = new WorkOrder;
  51 + $workOrder->product = $request->input('product');
  52 + $workOrder->content = $request->input('content');
  53 + $workOrder->files = json_encode($request->input('files'));
  54 + $workOrder->project_user_id = $this->user['id'];
  55 + $workOrder->project_id = $this->user['project_id'];
  56 + $workOrder->engineer_id = 0;
  57 + if ($this->project['type'] == 3){
  58 + // 项目类型是优化推广,项目负责人找优化
  59 + $seo = Project::find($this->user['project_id'])->deploy_optimize;
  60 + $workOrder->manage_id = $seo->manager_mid ?? $seo->optimist_mid ?? 0;
  61 + }else{
  62 + // 非优化推广项目,项目负责人找技术组长
  63 + $build = Project::find($this->user['project_id'])->deploy_build;
  64 + $workOrder->manage_id = $build->leader_mid ?? 0;
  65 + }
  66 + $workOrder->save();
  67 + // 添加工单日志
  68 + $log = new WorkOrderLog();
  69 + $log->manage_id = $workOrder->manage_id;
  70 + $workOrder->logs()->save($log);
  71 + return $workOrder;
  72 + });
  73 + $this->response('success', Code::SUCCESS, $result->toArray());
  74 + }
  75 +
  76 + /**
  77 + * Display the specified resource.
  78 + *
  79 + * @param int $id
  80 + * @return \Illuminate\Http\Response
  81 + */
  82 + public function show($id)
  83 + {
  84 + $workOrder = WorkOrder::with([
  85 + 'logs.manager:id,name',
  86 + 'user:id,name',
  87 + 'manager:id,name',
  88 + 'engineer:id,name',
  89 + ])->find($id);
  90 + if (!$workOrder) {
  91 + $this->response('error', 404, '工单未找到');
  92 + }
  93 + if ($workOrder->project_id != $this->user['project_id'] && $workOrder->engineer_id != $this->user['id']) {
  94 + $this->response('error', 403, '无权限查看该工单');
  95 + }
  96 + $this->response('success', Code::SUCCESS, $workOrder->toArray());
  97 + }
  98 +
  99 + /**
  100 + * B端用户修改工单,只能是修改工单状态
  101 + *
  102 + * @param \Illuminate\Http\Request $request
  103 + * @param int $id
  104 + * @return \Illuminate\Http\Response
  105 + */
  106 + public function update(WorkOrderUpdateRequest $request, $id)
  107 + {
  108 + $request->validated();
  109 + $workOrder = WorkOrder::find($id);
  110 + if (!$workOrder) {
  111 + $this->response('error', 404, '工单未找到');
  112 + }
  113 + // b端只有自己项目下的账号可以更新工单
  114 + if ($workOrder->project_id != $this->user['project_id']) {
  115 + $this->response('error', 403, '无权限更新该工单');
  116 + }
  117 + // 更新工单状态
  118 + $workOrder->status = $request->input('status');
  119 + $workOrder->save();
  120 + $this->response('success', Code::SUCCESS);
  121 + }
  122 +
  123 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Requests\Aside\WorkOrder;
  4 +
  5 +use Illuminate\Foundation\Http\FormRequest;
  6 +
  7 +class WorkOrderListRequest extends FormRequest
  8 +{
  9 + /**
  10 + * Determine if the user is authorized to make this request.
  11 + *
  12 + * @return bool
  13 + */
  14 + public function authorize()
  15 + {
  16 + return true;
  17 + }
  18 +
  19 + /**
  20 + * Get the validation rules that apply to the request.
  21 + *
  22 + * @return array
  23 + */
  24 + public function rules()
  25 + {
  26 + return [
  27 + 'page' => 'nullable|integer',
  28 + 'size' => 'nullable|integer',
  29 + 'project_id' => 'nullable|integer', // 产品ID
  30 + 'status' => 'nullable|in:0,1,2,3|integer',
  31 + 'search' => 'nullable|string', // 搜索关键词
  32 + ];
  33 + }
  34 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Requests\Aside\WorkOrder;
  4 +
  5 +use Illuminate\Foundation\Http\FormRequest;
  6 +
  7 +class WorkOrderUpdateRequest extends FormRequest
  8 +{
  9 + /**
  10 + * Determine if the user is authorized to make this request.
  11 + *
  12 + * @return bool
  13 + */
  14 + public function authorize()
  15 + {
  16 + return true;
  17 + }
  18 +
  19 + /**
  20 + * Get the validation rules that apply to the request.
  21 + *
  22 + * @return array
  23 + * A端更新售后工单
  24 + */
  25 + public function rules()
  26 + {
  27 + return [
  28 + 'status' => 'nullable|in:0,1,2,3|integer',
  29 + 'engineer_id' => 'nullable|integer',
  30 + ];
  31 + }
  32 +
  33 + public function withValidator($validator)
  34 + {
  35 + $validator->after(function ($validator) {
  36 + $status = $this->input('status');
  37 + $engineerId = $this->input('engineer_id');
  38 + if (is_null($status) && is_null($engineerId)) {
  39 + $validator->errors()->add('status', 'status 和 engineer_id 不能全是空');
  40 + }
  41 + });
  42 + }
  43 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Requests\Bside\WorkOrder;
  4 +
  5 +use Illuminate\Foundation\Http\FormRequest;
  6 +
  7 +class WorkOrderCreateRequest extends FormRequest
  8 +{
  9 + /**
  10 + * Determine if the user is authorized to make this request.
  11 + *
  12 + * @return bool
  13 + */
  14 + public function authorize()
  15 + {
  16 + return true;
  17 + }
  18 +
  19 + /**
  20 + * Get the validation rules that apply to the request.
  21 + *
  22 + * @return array
  23 + */
  24 + public function rules()
  25 + {
  26 + return [
  27 + 'product' => 'required|string',
  28 + 'content' => 'required|string',
  29 + 'files' => 'nullable|array',
  30 + ];
  31 + }
  32 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Requests\Bside\WorkOrder;
  4 +
  5 +use Illuminate\Foundation\Http\FormRequest;
  6 +
  7 +class WorkOrderUpdateRequest extends FormRequest
  8 +{
  9 + /**
  10 + * Determine if the user is authorized to make this request.
  11 + *
  12 + * @return bool
  13 + */
  14 + public function authorize()
  15 + {
  16 + return true;
  17 + }
  18 +
  19 + /**
  20 + * Get the validation rules that apply to the request.
  21 + *
  22 + * @return array
  23 + */
  24 + public function rules()
  25 + {
  26 + return [
  27 + 'status' => 'required|in:0,1,2,3|integer',
  28 + ];
  29 + }
  30 +}
  1 +<?php
  2 +
  3 +namespace App\Models\WorkOrder;
  4 +
  5 +use App\Models\Base;
  6 +use App\Models\Manage\Manage;
  7 +use App\Models\Project\Project;
  8 +use App\Models\User\User;
  9 +
  10 +class WorkOrder extends Base
  11 +{
  12 + protected $table = 'gl_work_orders';
  13 +
  14 + const STATUS_PEDDING = 0; // 待处理
  15 + const STATUS_PROCESSING = 1; // 处理中
  16 + const STATUS_COMPLETED = 2; // 已完成
  17 + const STATUS_CLOSED = 3; // 已关闭
  18 +
  19 +
  20 + /**
  21 + * 工单操作日志
  22 + */
  23 + public function logs()
  24 + {
  25 + return $this->hasMany(WorkOrderLog::class, 'work_order_id', 'id');
  26 + }
  27 +
  28 + /**
  29 + * 提交工单的用户
  30 + */
  31 + public function user()
  32 + {
  33 + return $this->belongsTo(User::class, 'project_user_id', 'id');
  34 + }
  35 +
  36 + /**
  37 + * 工单分配的管理员
  38 + */
  39 + public function manager()
  40 + {
  41 + return $this->belongsTo(Manage::class, 'manage_id', 'id');
  42 + }
  43 +
  44 + /**
  45 + * 工单分配的工程师
  46 + */
  47 + public function engineer()
  48 + {
  49 + return $this->belongsTo(Manage::class, 'engineer_id', 'id');
  50 + }
  51 +
  52 + /** 工单所属项目 */
  53 + public function project()
  54 + {
  55 + return $this->belongsTo(Project::class, 'project_id', 'id');
  56 + }
  57 +}
  1 +<?php
  2 +
  3 +namespace App\Models\WorkOrder;
  4 +
  5 +use App\Models\Base;
  6 +use App\Models\Manage\Manage;
  7 +
  8 +class WorkOrderLog extends Base
  9 +{
  10 + protected $table = 'gl_work_order_logs';
  11 +
  12 + const STATUS_PEDDING = 0; // 待处理
  13 + const STATUS_PROCESSING = 1; // 处理中
  14 + const STATUS_COMPLETED = 2; // 已完成
  15 + const STATUS_CLOSED = 3; // 已关闭
  16 +
  17 + /**
  18 + * 所属工单
  19 + */
  20 + public function workOrder()
  21 + {
  22 + return $this->belongsTo(WorkOrder::class, 'work_order_id');
  23 + }
  24 +
  25 + /**
  26 + * 分配的工单负责人,工程师等
  27 + */
  28 + public function manager()
  29 + {
  30 + return $this->belongsTo(Manage::class, 'manage_id', 'id');
  31 + }
  32 +}
@@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
12 "beyondcode/laravel-websockets": "^1.14", 12 "beyondcode/laravel-websockets": "^1.14",
13 "doctrine/dbal": "^3.6", 13 "doctrine/dbal": "^3.6",
14 "fruitcake/laravel-cors": "^2.0", 14 "fruitcake/laravel-cors": "^2.0",
  15 + "g4t/swagger": "^4.0",
15 "guzzlehttp/guzzle": "^7.0.1", 16 "guzzlehttp/guzzle": "^7.0.1",
16 "hashids/hashids": "^4.1", 17 "hashids/hashids": "^4.1",
17 "intervention/image": "^2.7", 18 "intervention/image": "^2.7",
  1 +<?php
  2 +
  3 +return [
  4 + /*
  5 + |--------------------------------------------------------------------------
  6 + | API Title
  7 + |--------------------------------------------------------------------------
  8 + |
  9 + | The title of your API documentation.
  10 + |
  11 + */
  12 + "title" => env("SWAGGER_TITLE", "Globalso V6 Api Documentation"),
  13 +
  14 + /*
  15 + |--------------------------------------------------------------------------
  16 + | API Description
  17 + |--------------------------------------------------------------------------
  18 + |
  19 + | The description of your API.
  20 + |
  21 + */
  22 + "description" => env("SWAGGER_DESCRIPTION", "Laravel autogenerate swagger"),
  23 +
  24 + /*
  25 + |--------------------------------------------------------------------------
  26 + | API Email
  27 + |--------------------------------------------------------------------------
  28 + |
  29 + | The email associated with your API documentation.
  30 + |
  31 + */
  32 + "email" => env("SWAGGER_EMAIL", "bill@ai.cc"),
  33 +
  34 + /*
  35 + |--------------------------------------------------------------------------
  36 + | API Version
  37 + |--------------------------------------------------------------------------
  38 + |
  39 + | The version of your API.
  40 + |
  41 + */
  42 + "version" => env("SWAGGER_VERSION", "3.0.7"),
  43 +
  44 + /*
  45 + |--------------------------------------------------------------------------
  46 + | Documentation Auth
  47 + |--------------------------------------------------------------------------
  48 + |
  49 + | This options to enable documentation auth
  50 + |
  51 + */
  52 + "enable_auth" => false,
  53 + "username" => "admin",
  54 + "password" => "pass",
  55 + "sesson_ttl" => 100000,
  56 +
  57 + /*
  58 + |--------------------------------------------------------------------------
  59 + | Enable Response Schema
  60 + |--------------------------------------------------------------------------
  61 + |
  62 + | Whether to enable response schema or not.
  63 + |
  64 + */
  65 + "enable_response_schema" => true,
  66 +
  67 + "suggestions_select_input" => false,
  68 +
  69 + "load_from_json" => false,
  70 +
  71 + /*
  72 + |--------------------------------------------------------------------------
  73 + | Authentication Middlewares
  74 + |--------------------------------------------------------------------------
  75 + |
  76 + | List of middleware names used for authentication.
  77 + |
  78 + */
  79 + "auth_middlewares" => [
  80 + "auth",
  81 + "auth:api",
  82 + "aloginauth",
  83 + "bloginauth",
  84 + ],
  85 +
  86 + /*
  87 + |--------------------------------------------------------------------------
  88 + | API URL
  89 + |--------------------------------------------------------------------------
  90 + |
  91 + | The URL path for accessing your API documentation.
  92 + |
  93 + */
  94 + "url" => env("SWAGGER_URL", "swagger/documentation"),
  95 +
  96 + /*
  97 + |--------------------------------------------------------------------------
  98 + | Issues URL
  99 + |--------------------------------------------------------------------------
  100 + |
  101 + | The URL path for accessing issues related to your API documentation.
  102 + |
  103 + */
  104 + "issues_url" => env("SWAGGER_ISSUE_URL", "swagger/issues"),
  105 +
  106 + /*
  107 + |--------------------------------------------------------------------------
  108 + | Enable Swagger
  109 + |--------------------------------------------------------------------------
  110 + |
  111 + | Whether Swagger is enabled or not.
  112 + |
  113 + */
  114 + "enable" => env('SWAGGER_ENABLED', true),
  115 +
  116 + /*
  117 + |--------------------------------------------------------------------------
  118 + | Show Prefix
  119 + |--------------------------------------------------------------------------
  120 + |
  121 + | List of prefixes to show in Swagger.
  122 + |
  123 + */
  124 + "show_prefix" => [],
  125 +
  126 + /*
  127 + |--------------------------------------------------------------------------
  128 + | Include Web Routes
  129 + |--------------------------------------------------------------------------
  130 + |
  131 + | If you want to includes web.php routes, then enable this
  132 + |
  133 + */
  134 + "include_web_routes" => env('SWAGGER_INCLUDE_WEB_ROUTES', true),
  135 +
  136 +
  137 + /*
  138 + |--------------------------------------------------------------------------
  139 + | API Versions
  140 + |--------------------------------------------------------------------------
  141 + |
  142 + | List of versions to show in Swagger.
  143 + |
  144 + */
  145 + "versions" => [
  146 + "all",
  147 + // "v1"
  148 + ],
  149 +
  150 + "default" => "all",
  151 +
  152 +
  153 + /*
  154 + |--------------------------------------------------------------------------
  155 + | Servers
  156 + |--------------------------------------------------------------------------
  157 + |
  158 + | List of servers associated with your API.
  159 + |
  160 + */
  161 + "servers" => [
  162 + [
  163 + "url" => env("APP_URL"),
  164 + "description" => "localhost"
  165 + ]
  166 + ],
  167 +
  168 +
  169 + /*
  170 + |--------------------------------------------------------------------------
  171 + | Security Schemes
  172 + |--------------------------------------------------------------------------
  173 + |
  174 + | Security schemes used in your API.
  175 + |
  176 + */
  177 + "security_schemes" => [
  178 + "APIKeyHeader" => [
  179 + "type" => "apiKey",
  180 + "name" => "token",
  181 + "in" => "header"
  182 + ],
  183 + ],
  184 +
  185 + /*
  186 + |--------------------------------------------------------------------------
  187 + | Spatie Query Builder
  188 + |--------------------------------------------------------------------------
  189 + |
  190 + | Enable it if you using Spatie query builder package to add spatie filters in all GET routes.
  191 + |
  192 + */
  193 + "spatie_query_builder" => false,
  194 +
  195 +
  196 + /*
  197 + |--------------------------------------------------------------------------
  198 + | Status
  199 + |--------------------------------------------------------------------------
  200 + |
  201 + | HTTP response statuses for various methods.
  202 + |
  203 + */
  204 + "status" => [
  205 + "GET" => [
  206 + "200" => [
  207 + "description" => "Successful Operation",
  208 + ],
  209 + "404" => [
  210 + "description" => "Not Found"
  211 + ]
  212 + ],
  213 + "POST" => [
  214 + "200" => [
  215 + "description" => "Successful Operation",
  216 + ],
  217 + "422" => [
  218 + "description" => "Validation Issues"
  219 + ]
  220 + ],
  221 + "PUT" => [
  222 + "200" => [
  223 + "description" => "Successful Operation",
  224 + ],
  225 + "404" => [
  226 + "description" => "Not Found"
  227 + ],
  228 + "405" => [
  229 + "description" => "Validation exception"
  230 + ]
  231 + ],
  232 + "PATCH" => [
  233 + "200" => [
  234 + "description" => "Successful Operation",
  235 + ],
  236 + "404" => [
  237 + "description" => "Not Found"
  238 + ],
  239 + "405" => [
  240 + "description" => "Validation exception"
  241 + ]
  242 + ],
  243 + "DELETE" => [
  244 + "200" => [
  245 + "description" => "successful Operation",
  246 + ],
  247 + "404" => [
  248 + "description" => "page Not Found"
  249 + ]
  250 + ],
  251 + ],
  252 +
  253 +];
1 -<?php  
2 -  
3 -use Illuminate\Database\Migrations\Migration;  
4 -use Illuminate\Database\Schema\Blueprint;  
5 -use Illuminate\Support\Facades\Schema;  
6 -  
7 -class CreatePasswordResetsTable extends Migration  
8 -{  
9 - /**  
10 - * Run the migrations.  
11 - *  
12 - * @return void  
13 - */  
14 - public function up()  
15 - {  
16 - Schema::create('password_resets', function (Blueprint $table) {  
17 - $table->string('email')->index();  
18 - $table->string('token');  
19 - $table->timestamp('created_at')->nullable();  
20 - });  
21 - }  
22 -  
23 - /**  
24 - * Reverse the migrations.  
25 - *  
26 - * @return void  
27 - */  
28 - public function down()  
29 - {  
30 - Schema::dropIfExists('password_resets');  
31 - }  
32 -}  
1 -<?php  
2 -  
3 -use Illuminate\Database\Migrations\Migration;  
4 -use Illuminate\Database\Schema\Blueprint;  
5 -use Illuminate\Support\Facades\Schema;  
6 -  
7 -class CreateFailedJobsTable extends Migration  
8 -{  
9 - /**  
10 - * Run the migrations.  
11 - *  
12 - * @return void  
13 - */  
14 - public function up()  
15 - {  
16 - Schema::create('failed_jobs', function (Blueprint $table) {  
17 - $table->id();  
18 - $table->string('uuid')->unique();  
19 - $table->text('connection');  
20 - $table->text('queue');  
21 - $table->longText('payload');  
22 - $table->longText('exception');  
23 - $table->timestamp('failed_at')->useCurrent();  
24 - });  
25 - }  
26 -  
27 - /**  
28 - * Reverse the migrations.  
29 - *  
30 - * @return void  
31 - */  
32 - public function down()  
33 - {  
34 - Schema::dropIfExists('failed_jobs');  
35 - }  
36 -}  
@@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration; @@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
4 use Illuminate\Database\Schema\Blueprint; 4 use Illuminate\Database\Schema\Blueprint;
5 use Illuminate\Support\Facades\Schema; 5 use Illuminate\Support\Facades\Schema;
6 6
7 -class CreatePersonalAccessTokensTable extends Migration 7 +class CreateWorkOrdersTable extends Migration
8 { 8 {
9 /** 9 /**
10 * Run the migrations. 10 * Run the migrations.
@@ -13,15 +13,21 @@ class CreatePersonalAccessTokensTable extends Migration @@ -13,15 +13,21 @@ class CreatePersonalAccessTokensTable extends Migration
13 */ 13 */
14 public function up() 14 public function up()
15 { 15 {
16 - Schema::create('personal_access_tokens', function (Blueprint $table) { 16 + Schema::create('gl_work_orders', function (Blueprint $table) {
17 $table->id(); 17 $table->id();
18 - $table->morphs('tokenable');  
19 - $table->string('name');  
20 - $table->string('token', 64)->unique();  
21 - $table->text('abilities')->nullable();  
22 - $table->timestamp('last_used_at')->nullable();  
23 $table->timestamps(); 18 $table->timestamps();
  19 + $table->string('product')->nullable()->comment('相关产品,工单类型');
  20 + $table->longText('content')->comment('工单图文描述');
  21 + $table->json('files')->nullable()->comment('附件');
  22 + $table->integer('status')->index()->default(0)->comment('工单状态,0:待处理, 1:处理中,2:已完成, 3:已关闭');
  23 + $table->integer('project_user_id')->index()->comment('客户ID');
  24 + $table->integer('project_id')->index()->comment('项目ID');
  25 + $table->integer('manage_id')->index()->comment('A端项目负责人ID, gl_manage 表ID');
  26 + $table->integer('engineer_id')->index()->comment('处理技术,工程师id, gl_manage 表ID');
  27 + $table->timestamp('end_at')->nullable()->comment('完成时间');
24 }); 28 });
  29 + # 添加表注释
  30 + \Illuminate\Support\Facades\DB::statement("ALTER TABLE gl_work_orders comment '工单表'");
25 } 31 }
26 32
27 /** 33 /**
@@ -31,6 +37,6 @@ class CreatePersonalAccessTokensTable extends Migration @@ -31,6 +37,6 @@ class CreatePersonalAccessTokensTable extends Migration
31 */ 37 */
32 public function down() 38 public function down()
33 { 39 {
34 - Schema::dropIfExists('personal_access_tokens'); 40 + Schema::dropIfExists('gl_work_orders');
35 } 41 }
36 } 42 }
@@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration; @@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
4 use Illuminate\Database\Schema\Blueprint; 4 use Illuminate\Database\Schema\Blueprint;
5 use Illuminate\Support\Facades\Schema; 5 use Illuminate\Support\Facades\Schema;
6 6
7 -class CreateUsersTable extends Migration 7 +class CreateWorkOrderLogsTable extends Migration
8 { 8 {
9 /** 9 /**
10 * Run the migrations. 10 * Run the migrations.
@@ -13,15 +13,19 @@ class CreateUsersTable extends Migration @@ -13,15 +13,19 @@ class CreateUsersTable extends Migration
13 */ 13 */
14 public function up() 14 public function up()
15 { 15 {
16 - Schema::create('users', function (Blueprint $table) { 16 + Schema::create('gl_work_order_logs', function (Blueprint $table) {
17 $table->id(); 17 $table->id();
18 - $table->string('name');  
19 - $table->string('email')->unique();  
20 - $table->timestamp('email_verified_at')->nullable();  
21 - $table->string('password');  
22 - $table->rememberToken();  
23 $table->timestamps(); 18 $table->timestamps();
  19 + $table->integer('work_order_id')->index();
  20 + $table->integer('manage_id')->comment('gl_manage 表ID,操作人ID');
  21 + $table->boolean('ding')->default(false)->comment('是否钉钉通知');
  22 + $table->longText('content')->nullable()->comment('处理结果,图文描述');
  23 + $table->json('files')->nullable()->comment('附件');
  24 + $table->integer('status')->index()->default(0)->comment('工单状态,0:待处理, 1:处理中, 2:已完成');
  25 + $table->timestamp('end_at')->nullable()->comment('完成时间');
  26 + $table->unique(['work_order_id', 'manage_id'], 'work_order_manage_unique'); # 唯一索引,防止同一工单被同一人多次操作,同一工单,可以多人协作
24 }); 27 });
  28 + \Illuminate\Support\Facades\DB::statement('ALTER TABLE gl_work_order_logs comment "工单操作日志表,分配工程师时创建,工程师完成时修改状态"');
25 } 29 }
26 30
27 /** 31 /**
@@ -31,6 +35,6 @@ class CreateUsersTable extends Migration @@ -31,6 +35,6 @@ class CreateUsersTable extends Migration
31 */ 35 */
32 public function down() 36 public function down()
33 { 37 {
34 - Schema::dropIfExists('users'); 38 + Schema::dropIfExists('gl_work_order_logs');
35 } 39 }
36 } 40 }
不能预览此文件类型
@@ -245,6 +245,13 @@ Route::middleware(['aloginauth'])->group(function () { @@ -245,6 +245,13 @@ Route::middleware(['aloginauth'])->group(function () {
245 Route::post('/save_follow', [Aside\Task\TaskController::class, 'save_follow'])->name('admin.task_save_follow'); 245 Route::post('/save_follow', [Aside\Task\TaskController::class, 'save_follow'])->name('admin.task_save_follow');
246 Route::any('/getUserTaskList', [Aside\Task\TaskController::class, 'getUserTaskList'])->name('admin.task_getUserTaskList'); 246 Route::any('/getUserTaskList', [Aside\Task\TaskController::class, 'getUserTaskList'])->name('admin.task_getUserTaskList');
247 }); 247 });
  248 + // 售后工单
  249 + Route::prefix('workorder')->group(function () {
  250 + Route::get('/', [Aside\WorkOrder\WorkOrderController::class, 'index'])->name('admin.workorder.index')->summary('A端工程师的工单列表');
  251 + Route::get('/manager', [Aside\WorkOrder\WorkOrderController::class, 'manager'])->name('admin.workorder.manager')->summary('A端管理员的工单列表');
  252 + Route::get('/{id}', [Aside\WorkOrder\WorkOrderController::class, 'show'])->name('admin.workorder.show')->summary('A端工单详情');
  253 + Route::put('/{id}', [Aside\WorkOrder\WorkOrderController::class, 'update'])->name('admin.workorder.update')->summary('A端更新工单');
  254 + });
248 //服务器配置 255 //服务器配置
249 Route::prefix('devops')->group(function () { 256 Route::prefix('devops')->group(function () {
250 Route::any('/', [Aside\Devops\ServerConfigController::class, 'lists'])->name('admin.devops.lists'); 257 Route::any('/', [Aside\Devops\ServerConfigController::class, 'lists'])->name('admin.devops.lists');
@@ -353,11 +360,6 @@ Route::middleware(['aloginauth'])->group(function () { @@ -353,11 +360,6 @@ Route::middleware(['aloginauth'])->group(function () {
353 Route::any('/save', [Aside\Optimize\ProjectGscController::class, 'save'])->name('admin.gsc_save'); 360 Route::any('/save', [Aside\Optimize\ProjectGscController::class, 'save'])->name('admin.gsc_save');
354 Route::any('/del', [Aside\Optimize\ProjectGscController::class, 'del'])->name('admin.gsc_del'); 361 Route::any('/del', [Aside\Optimize\ProjectGscController::class, 'del'])->name('admin.gsc_del');
355 }); 362 });
356 - //上线审核  
357 - Route::prefix('process')->group(function () {  
358 - Route::any('/', [Aside\Optimize\ProcessController::class, 'lists'])->name('admin.process_lists');  
359 - Route::any('/save', [Aside\Optimize\ProcessController::class, 'save'])->name('admin.process_save');  
360 - });  
361 363
362 //询盘 364 //询盘
363 Route::prefix('inquiry')->group(function () { 365 Route::prefix('inquiry')->group(function () {
@@ -261,6 +261,15 @@ Route::middleware(['bloginauth'])->group(function () { @@ -261,6 +261,15 @@ Route::middleware(['bloginauth'])->group(function () {
261 Route::any('/save',[\App\Http\Controllers\Bside\Setting\WebSettingAmpController::class, 'save'])->name('amp_save'); 261 Route::any('/save',[\App\Http\Controllers\Bside\Setting\WebSettingAmpController::class, 'save'])->name('amp_save');
262 }); 262 });
263 }); 263 });
  264 +
  265 + // 售后工单
  266 + Route::prefix('workorder')->group(function () {
  267 + Route::get('/', [\App\Http\Controllers\Bside\WorkOrder\WorkOrderController::class, 'index'])->name('workorder.index')->summary('B端售后工单列表');
  268 + Route::post('/', [\App\Http\Controllers\Bside\WorkOrder\WorkOrderController::class, 'store'])->name('workorder.store')->summary('B端创建工单');
  269 + Route::get('/{id}', [\App\Http\Controllers\Bside\WorkOrder\WorkOrderController::class, 'show'])->name('workorder.show')->summary('B端查看工单');
  270 + Route::put('/{id}', [\App\Http\Controllers\Bside\WorkOrder\WorkOrderController::class, 'update'])->name('workorder.update')->summary('B端完结工单');
  271 + });
  272 +
264 //产品 273 //产品
265 Route::prefix('product')->group(function () { 274 Route::prefix('product')->group(function () {
266 //产品 275 //产品
@@ -516,11 +525,6 @@ Route::middleware(['bloginauth'])->group(function () { @@ -516,11 +525,6 @@ Route::middleware(['bloginauth'])->group(function () {
516 Route::any('/getKeyword', [\App\Http\Controllers\Bside\HomeCount\MonthCountController::class, 'getKeyword'])->name('month_getKeyword'); 525 Route::any('/getKeyword', [\App\Http\Controllers\Bside\HomeCount\MonthCountController::class, 'getKeyword'])->name('month_getKeyword');
517 }); 526 });
518 527
519 - //更新tdk  
520 - Route::prefix('tdk')->group(function () {  
521 - Route::any('/', [\App\Http\Controllers\Bside\BCom\UpdateController::class, 'updateSeoTdk'])->name('tdk_updateSeoTdk');  
522 - });  
523 -  
524 //导入任务 528 //导入任务
525 Route::prefix('import')->group(function () { 529 Route::prefix('import')->group(function () {
526 Route::any('/add_task', [\App\Http\Controllers\Bside\Import\ImportController::class, 'save'])->name('import_add_task'); 530 Route::any('/add_task', [\App\Http\Controllers\Bside\Import\ImportController::class, 'save'])->name('import_add_task');