api 培训考试结果

main
panliang 2024-04-17 13:26:41 +08:00
parent 0a9fe3dc4a
commit 9bf3c45c88
27 changed files with 620 additions and 31 deletions

View File

@ -35,14 +35,16 @@ class BookController extends AdminController
->columnRatio(3)
->clearable(),
amisMake()->TextControl()->name('search')->label(__('train_book.title'))->columnRatio(3)->clearable(),
amisMake()->SelectControl()->options(BookType::options())->name('type')->label(__('train_book.type'))->columnRatio(3)->clearable(),
]),
]))
->columns([
amisMake()->TableColumn()->name('id')->label(__('train_book.id')),
amisMake()->TableColumn()->name('category.name')->label(__('train_book.category_id')),
amisMake()->TableColumn()->name('title')->label(__('train_book.title')),
amisMake()->TableColumn()->name('description')->label(__('train_book.description')),
amisMake()->TableColumn()->name('cover_image')->label(__('train_book.cover_image'))->set('type', 'image')->set('width', '80px')->set('height', '60px'),
amisMake()->TableColumn()->name('title')->label(__('train_book.title')),
// amisMake()->TableColumn()->name('description')->label(__('train_book.description')),
amisMake()->TableColumn()->name('type')->label(__('train_book.type'))->set('type', 'mapping')->map(BookType::options()),
amisMake()->TableColumn()->name('created_at')->label(__('train_book.created_at')),
$this->rowActions([
$this->rowShowButton()->visible(Admin::user()->can('admin.train.books.view')),
@ -79,17 +81,17 @@ class BookController extends AdminController
amisMake()->Link()->body('${name}')->href('${url}')->blank()
)
);
return $this->baseDetail()->title('')->body(amisMake()->Property()->items([
$items = [
['label' => __('train_book.category_id'), 'content' => '${category.name}'],
['label' => __('train_book.title'), 'content' => '${title}'],
['label' => __('train_book.description'), 'content' => '${description}'],
['label' => __('train_book.cover_image'), 'content' => amisMake()->Image()->name('cover_image')->width('80px')->height('60px')],
['label' => __('train_book.type'), 'content' => amisMake()->Mapping()->map(BookType::options())->name('type')],
['label' => __('train_book.created_at'), 'content' => '${created_at}'],
['label' => __('train_book.content'), 'content' => Components::make()->fuEditorControl('content', false, 'auto')->static(), 'span' => 3],
['label' => __('train_book.video'), 'content' => amisMake()->Video()->src('${video}'), 'span' => 3],
// amisMake()->Each()->name('files')->items(amisMake()->Link()->body('${name}')->href('${url}')->blank())
['label' => __('train_book.files'), 'content' => $list, 'span' => 3],
]));
['label' => __('train_book.content'), 'content' => Components::make()->fuEditorControl('content', false, 'auto')->static(), 'span' => 3, 'visibleOn' => '${type == '.BookType::Text->value.'}'],
['label' => __('train_book.video'), 'content' => amisMake()->Video()->src('${video}'), 'span' => 3, 'visibleOn' => '${type == '.BookType::Video->value.'}'],
['label' => __('train_book.files'), 'content' => $list, 'span' => 3, 'visibleOn' => '${type == '.BookType::File->value.'}'],
];
return $this->baseDetail()->title('')->body(amisMake()->Property()->items($items));
}
}

View File

@ -8,7 +8,9 @@ use Slowlyo\OwlAdmin\Admin;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Renderers\Page;
use App\Enums\{ExamStatus, QuestionCate};
use App\Models\Train\Question;
use App\Models\Train\{Question, Examination};
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
/**
* 考试管理
@ -40,9 +42,39 @@ class ExaminationController extends AdminController
amisMake()->TableColumn()->name('total_questions')->label(__('train_examination.total_questions')),
amisMake()->TableColumn()->name('total_score')->label(__('train_examination.total_score')),
$this->rowActions([
$this->rowShowButton()->visible(Admin::user()->can('admin.train.examinations.view')),
$this->rowEditButton()->visible(Admin::user()->can('admin.train.examinations.update')),
$this->rowDeleteButton()->visible(Admin::user()->can('admin.train.examinations.delete')),
$this->rowShowButton()
->visible(Admin::user()->can('admin.train.examinations.view')),
$this->rowEditButton()
->visible(Admin::user()->can('admin.train.examinations.update'))
->visibleOn('${exam_status == '.ExamStatus::None->value.'}'),
$this->rowDeleteButton()
->visible(Admin::user()->can('admin.train.examinations.delete'))
->visibleOn('${exam_status == '.ExamStatus::None->value.'}'),
amisMake()->DialogAction()->dialog(
amisMake()->Dialog()->title('选择参考员工')->size('lg')->body(
amisMake()->Form()->api('post:' . admin_url('train/examinations/${id}/publish'))->body([
amisMake()->TransferControl()
->name('employee_id')
->source(admin_url('api/employees?enable=1&store_id_gt=0'))
->joinValues(false)
->extractValue()
->labelField('name')
->valueField('id')
->searchable()
->required(),
])
)
)
->label(__('train_examination.publish'))
->level('link')
->visible(Admin::user()->can('admin.train.examinations.publish'))
->visibleOn('${exam_status == '.ExamStatus::None->value.'}'),
amisMake()->AjaxAction()->api('post:' . admin_url('train/examinations/${id}/cancel'))
->label(__('train_examination.cancel'))
->level('link')
->confirmText('删除该考试下所有试卷记录, 是否确定?')
->visible(Admin::user()->can('admin.train.examinations.cancel'))
->visibleOn('${exam_status == '.ExamStatus::Published->value.'}'),
]),
]);
@ -57,6 +89,7 @@ class ExaminationController extends AdminController
->addable()
->editable()
->removable()
->showIndex()
->needConfirm(false)
->columns([
amisMake()->SelectControl()
@ -95,4 +128,43 @@ class ExaminationController extends AdminController
]);
return $this->baseDetail()->title('')->body([$detail, amisMake()->Divider(), $question]);
}
public function publish($id, Request $request)
{
$request->validate([
'employee_id' => 'required'
]);
$info = Examination::findOrFail($id);
try {
DB::beginTransaction();
if (!$this->service->publish($info, $request->input('employee_id'))) {
return $this->response()->fail($this->service->getError());
}
DB::commit();
return $this->response()->success();
} catch (\Exception $e) {
DB::rollBack();
return $this->response()->fail($e->getMessage());
}
}
public function cancel($id, Request $request)
{
$info = Examination::findOrFail($id);
try {
DB::beginTransaction();
if (!$this->service->cancel($info)) {
return $this->response()->fail($this->service->getError());
}
DB::commit();
return $this->response()->success();
} catch (\Exception $e) {
DB::rollBack();
return $this->response()->fail($e->getMessage());
}
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace App\Admin\Controllers\Train;
use App\Admin\Controllers\AdminController;
use App\Admin\Services\Train\PaperService;
use Slowlyo\OwlAdmin\Admin;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Renderers\Page;
use App\Enums\QuestionCate;
/**
* 成绩管理
*/
class PaperController extends AdminController
{
protected string $serviceName = PaperService::class;
public function list(): Page
{
$crud = $this->baseCRUD()
->tableLayout('fixed')
->headerToolbar([
...$this->baseHeaderToolBar(),
])
->bulkActions([])
->filter($this->baseFilter()->body([
amis()->GroupControl()->mode('horizontal')->body([
amisMake()->TextControl()->name('examination_search')->label(__('train_paper.examination_id'))->columnRatio(3)->clearable(),
amisMake()->TextControl()->name('employee_search')->label(__('train_paper.employee_id'))->columnRatio(3)->clearable(),
]),
]))
->columns([
amisMake()->TableColumn()->name('id')->label(__('train_paper.id')),
amisMake()->TableColumn()->name('examination.name')->label(__('train_paper.examination_id')),
amisMake()->TableColumn()->name('employee.name')->label(__('train_paper.employee_id')),
amisMake()->TableColumn()->name('mark')->label(__('train_paper.mark')),
amisMake()->TableColumn()->name('finished_at')->label(__('train_paper.finished_at')),
$this->rowActions([
$this->rowShowButton(),
]),
]);
return $this->baseList($crud);
}
public function detail(): Form
{
$detail = amisMake()->Property()->column(2)->items([
['label' => __('train_paper.examination_id'), 'content' => '${examination.name}'],
['label' => __('train_paper.employee_id'), 'content' => '${employee.name}'],
['label' => __('train_paper.mark'), 'content' => '${mark}'],
['label' => __('train_paper.finished_at'), 'content' => '${finished_at}'],
]);
$question = amisMake()->Table()->columnsTogglable(false)->source('${content}')->columns([
amisMake()->TableColumn()->name('title')->label(__('train_question.title')),
amisMake()->TableColumn()->name('cate')->label(__('train_question.cate'))->set('type', 'mapping')->map(QuestionCate::options()),
amisMake()->TableColumn()->name('options')->label(__('train_question.options'))->set('type', 'list')->source('${options}')->listItem([
'titleClassName' => 'text-${IF(is_true, "success", "danger")}',
'title' => '${text}',
'desc' => '${selected ? "已选择" : ""}',
]),
amisMake()->TableColumn()->name('score')->label(__('train_question.score')),
amisMake()->TableColumn()->name('user_score')->label(__('train_question.user_score')),
]);
return $this->baseDetail()->title('')->body([$detail, amisMake()->Divider(), $question]);
}
}

View File

@ -40,7 +40,7 @@ class EmployeeFilter extends ModelFilter
public function storeIdGt($key)
{
$this->where('store_id', '>', 0);
$this->where('store_id', '>', $key);
}
public function masterStoreId($key)

View File

@ -18,6 +18,11 @@ class TrianBookFilter extends ModelFilter
return $this->where('category_id', $key);
}
public function type($key)
{
$this->where('type', $key);
}
public function dateRange($dates)
{
$dates = explode(',', $dates);

View File

@ -0,0 +1,19 @@
<?php
namespace App\Admin\Filters;
use Carbon\Carbon;
use EloquentFilter\ModelFilter;
class TrianPaperFilter extends ModelFilter
{
public $relations = [
'examination' => [
'examination_search' => 'search',
],
'employee' => [
'employee_name' => 'name',
'employee_search' => 'search',
],
];
}

View File

@ -20,24 +20,38 @@ class BookService extends BaseService
{
if (isset($data['cover_image']) && $data['cover_image']) {
$image = $data['cover_image'];
$data['cover_image'] = Str::startsWith($image, ['http://', 'https://']) ? $image : Storage::url($image);
$data['cover_image'] = $this->formatUrl($image);
}
if (isset($data['video']) && $data['video']) {
$image = $data['video'];
$data['video'] = Str::startsWith($image, ['http://', 'https://']) ? $image : Storage::url($image);
$video = $data['video'];
$data['video'] = $this->formatUrl($video);
}
if (isset($data['files']) && $data['files']) {
$files = [];
foreach ($data['files'] as $value) {
$path = data_get($value, 'value');
$value['url'] = Str::startsWith($path, ['http://', 'https://']) ? $path : Storage::url($path);
array_push($files, $value);
foreach ($data['files'] as $key => $value) {
if (is_array($value)) {
$path = data_get($value, 'value');
$value['url'] = $this->formatUrl($path);
array_push($files, $value);
} else {
array_push($files, [
'id' => $key + 1,
'name' => $value,
'url' => $this->formatUrl($value),
'state' => 'uploaded'
]);
}
}
$data['files'] = $files;
}
return $data;
}
protected function formatUrl($str)
{
return Str::startsWith($str, ['http://', 'https://']) ? $str : Storage::url($str);
}
public function validate($data, $model = null)
{
$createRules = [

View File

@ -8,6 +8,7 @@ use App\Admin\Services\BaseService;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\{Validator, Storage};
use App\Enums\ExamStatus;
use App\Models\Employee;
class ExaminationService extends BaseService
{
@ -45,10 +46,42 @@ class ExaminationService extends BaseService
return $data;
}
public function publish(Examination $examination)
public function publish(Examination $examination, array $ids)
{
if ($examination->exam_status == ExamStatus::Published) {
return $this->setError('已经发布了');
}
$questions = [];
foreach($examination->questions as $question) {
$question['options'] = array_map(function ($option) {
$option['selected'] = false;
return $option;
}, $question['options']);
array_push($questions, $question);
}
$employees = Employee::whereIn('id', $ids)->get();
// 为员工生成考卷
foreach ($employees as $employee) {
$examination->papers()->create([
'employee_id' => $employee->id,
'content' => $questions,
]);
}
$examination->update(['exam_status' => ExamStatus::Published, 'published_at' => now()]);
return true;
}
public function cancel(Examination $examination)
{
if ($examination->exam_status == ExamStatus::None) {
return $this->setError('已经取消了');
}
$examination->papers()->delete();
$examination->update(['exam_status' => ExamStatus::None, 'published_at' => null]);
return true;
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Admin\Services\Train;
use App\Admin\Filters\TrianPaperFilter;
use App\Models\Train\Paper;
use App\Admin\Services\BaseService;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\{Validator, Storage};
class PaperService extends BaseService
{
protected array $withRelationships = ['examination', 'employee'];
protected string $modelName = Paper::class;
protected string $modelFilterName = TrianPaperFilter::class;
/**
* 答题
*
* @param Paper $paper
* @param array $answers [[0, 1], [1], [2, 3]]
* @return boolean
*/
public function answer(Paper $paper, array $answers)
{
if ($paper->finished_at) {
return $this->setError('已经答过了');
}
$content = [];
$mark = 0;
foreach ($paper->content as $index => $item) {
$options = [];
$item['user_answer'] = data_get($answers, $index, []);
$score = $item['score'];
foreach ($item['options'] as $subIndex => $option) {
$option['selected'] = in_array($subIndex, $item['user_answer']);
if ((!$option['is_true'] && $option['selected']) || ($option['is_true'] && !$option['selected'])) {
$score = 0;
}
array_push($options, $option);
}
$item['user_score'] = $score;
$item['options'] = $options;
$item['user_right'] = $score == $item['score'];
array_push($content, $item);
$mark += $score;
}
$paper->update(['content' => $content, 'mark' => $mark, 'finished_at' => now()]);
return true;
}
}

View File

@ -198,7 +198,10 @@ Route::group([
// 题库管理
$router->resource('questions', \App\Admin\Controllers\Train\QuestionController::class);
// 考试管理
$router->post('examinations/{id}/publish', [\App\Admin\Controllers\Train\ExaminationController::class, 'publish'])->name('examinations.publish');
$router->post('examinations/{id}/cancel', [\App\Admin\Controllers\Train\ExaminationController::class, 'cancel'])->name('examinations.cancel');
$router->resource('examinations', \App\Admin\Controllers\Train\ExaminationController::class);
$router->resource('papers', \App\Admin\Controllers\Train\PaperController::class)->only(['index', 'show']);
});
$router->post('agreement/download', [AgreementController::class, 'download'])->name('agreement.download');

View File

@ -0,0 +1,30 @@
<?php
namespace App\Http\Controllers\Api\Train;
use App\Http\Controllers\Api\Controller;
use Illuminate\Http\Request;
use App\Models\Train\Book;
use App\Http\Resources\TrainBookResource;
/**
* 培训-课件
*/
class BookController extends Controller
{
public function index(Request $request)
{
$list = Book::filter($request->all())
->orderBy('created_at', 'desc')
->paginate($request->input('per_page'));
return TrainBookResource::collection($list);
}
public function show($id)
{
$info = Book::with(['category'])->findOrFail($id);
return TrainBookResource::make($info);
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace App\Http\Controllers\Api\Train;
use App\Http\Controllers\Api\Controller;
use Illuminate\Http\Request;
use App\Models\Train\{Paper, Examination};
use App\Http\Resources\{TrainExaminationResource, TrainPaperResource};
use App\Enums\ExamStatus;
use App\Admin\Services\Train\PaperService;
use Illuminate\Support\Facades\DB;
use App\Exceptions\RuntimeException;
/**
* 培训-考试
*/
class ExaminationController extends Controller
{
public function index(Request $request)
{
$user = $this->guard()->user();
$list = Paper::with(['examination'])
->where('employee_id', $user->id)
->whereHas('examination', fn($q) => $q->where('exam_status', ExamStatus::Published))
->orderBy('created_at', 'desc')
->paginate($request->input('per_page'));
return TrainPaperResource::collection($list);
}
public function show($id)
{
$user = $this->guard()->user();
$info = Paper::with(['examination'])->where('employee_id', $user->id)->findOrFail($id);
return TrainPaperResource::make($info);
}
public function answer($id, Request $request, PaperService $service)
{
$request->validate([
'answers' => ['required', 'array']
]);
$user = $this->guard()->user();
$info = Paper::with(['examination'])->where('employee_id', $user->id)->findOrFail($id);
try {
DB::beginTransaction();
if (!$service->answer($info, $request->input('answers'))) {
throw new RuntimeException($service->getError());
}
DB::commit();
return TrainPaperResource::make($info);
} catch (\Exception $e) {
DB::rollBack();
throw new RuntimeException($e->getMessage());
}
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class TrainBookResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'category_id' => $this->category_id,
'category' => KeywordResource::make($this->whenLoaded('category')),
'title' => $this->title,
'cover_image' => $this->cover_image,
'description' => $this->description,
'type' => $this->type,
'content' => $this->content,
'video' => $this->video,
'files' => $this->files,
'created_at' => $this->created_at->timestamp,
];
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class TrainExaminationResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
// 'questions' => $this->questions,
'total_questions' => $this->total_questions,
'total_score' => $this->total_score,
'published_at' => $this->published_at?->timestamp,
];
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class TrainPaperResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'examination_id' => $this->examination_id,
'examination' => TrainExaminationResource::make($this->whenLoaded('examination')),
'employee_id' => $this->employee_id,
'employee' => EmployeeResource::make($this->whenLoaded('employee')),
'content' => $this->content,
'mark' => $this->mark,
'finished_at' => $this->finished_at?->timestamp
];
}
}

View File

@ -15,8 +15,8 @@ class Book extends Model
protected $table = 'train_books';
protected $guarded = [];
protected $fillable = ['category_id', 'title', 'cover_image', 'description', 'type', 'content', 'video', 'files'];
protected $casts = [
'type' => \App\Enums\BookType::class,
'files' => 'json',

View File

@ -15,7 +15,7 @@ class Examination extends Model
protected $table = 'train_examinations';
protected $guarded = [];
protected $fillable = ['name', 'questions', 'total_questions', 'total_score', 'remarks', 'published_at', 'exam_status'];
protected $casts = [
// [{title: 题目, cate: 类型, options: 选项, score: 分值}]
@ -28,4 +28,9 @@ class Examination extends Model
{
return \App\Admin\Filters\TrainExaminationFilter::class;
}
public function papers()
{
return $this->hasMany(Paper::class, 'examination_id');
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Models\Train;
use Illuminate\Database\Eloquent\Model;
use App\Traits\HasDateTimeFormatter;
use EloquentFilter\Filterable;
use App\Models\Employee;
/**
* 培训-试卷
*/
class Paper extends Model
{
use HasDateTimeFormatter, Filterable;
protected $table = 'train_examination_papers';
protected $fillable = ['examination_id', 'employee_id', 'content', 'mark', 'finished_at'];
protected $casts = [
// [{title: 题目, cate: 类型, options: 选项, score: 分值 , user_score: 得分, user_answer: 回答}]
'content' => 'json',
'finished_at' => 'datetime',
];
public function modelFilter()
{
return \App\Admin\Filters\TrianPaperFilter::class;
}
public function examination()
{
return $this->belongsTo(Examination::class, 'examination_id');
}
public function employee()
{
return $this->belongsTo(Employee::class, 'employee_id');
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Train\Book;
use App\Models\Keyword;
use App\Enums\BookType;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Model>
*/
class BookFactory extends Factory
{
protected $model = Book::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'title' => $this->faker->sentence,
'category_id' => Keyword::where('parent_key', 'book_category')->inRandomOrder()->value('key'),
'cover_image' => 'https://via.placeholder.com/100x100.png',
'description' => $this->faker->paragraph,
'type' => $this->faker->randomElement(BookType::class),
'content' => '<h1>富文本 H1<h1><img src="https://via.placeholder.com/100x100.png" width="100%" height="100%" />',
'video' => 'https://qiniu.abcdefg.fun/mp4-1.mp4',
'files' => [
['id' => '1', 'name' => '1.png', 'url' => 'https://qiniu.abcdefg.fun/avatar/avatar.png', 'value' => 'https://qiniu.abcdefg.fun/avatar/avatar.png', "state" => "uploaded"],
['id' => '2','name' => '2.png', 'url' => 'https://qiniu.abcdefg.fun/avatar/avatar2.png', 'value' => 'https://qiniu.abcdefg.fun/avatar/avatar.png', "state" => "uploaded"],
],
];
}
}

View File

@ -17,10 +17,10 @@ return new class extends Migration
$table->string('category_id')->comment('分类(book_category), keywords.key');
$table->string('title')->comment('标题');
$table->string('cover_image')->nullable()->comment('封面图');
$table->string('description')->nullable()->comment('描述');
$table->text('description')->nullable()->comment('描述');
$table->unsignedInteger('type')->default(BookType::Text->value)->comment('课件类型');
$table->text('content')->nullable()->comment('文章内容');
$table->json('video')->nullable()->comment('视频');
$table->string('video')->nullable()->comment('视频');
$table->json('files')->nullable()->comment('附件');
$table->timestamps();
@ -57,8 +57,7 @@ return new class extends Migration
$table->foreignId('employee_id')->comment('考生');
$table->json('content')->comment('考卷内容[{title: 题目, cate: 类型, options: 选项, score: 分值 , user_score: 得分, user_answer: 回答}]');
$table->unsignedInteger('mark')->nullable()->comment('分数');
$table->timestamp('start_at')->nullable()->comment('答题开始时间');
$table->timestamp('end_at')->nullable()->comment('答题结束时间');
$table->timestamp('finished_at')->nullable()->comment('答题结束时间');
$table->timestamps();
$table->comment('培训-考卷记录');

View File

@ -315,6 +315,16 @@ class AdminPermissionSeeder extends Seeder
'icon' => 'material-symbols:checkbook-outline',
'uri' => '/train/examinations',
'resource' => true,
'children' => [
'publish' => '生成考卷',
'cancel' => '取消考试',
]
],
'papers' => [
'name' => '考试结果',
'icon' => 'material-symbols:checkbook-outline',
'uri' => '/train/papers',
'resource' => ['list', 'view']
],
]
],

View File

@ -28,8 +28,5 @@ class EmployeeSeeder extends Seeder
// EmployeeSign::truncate();
// EmployeeSignLog::truncate();
// EmployeeSignLog::factory()->count(100)->create();
Question::truncate();
(new QuestionFactory)->count(20)->create();
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Train\{Book, Question};
use Database\Factories\{BookFactory, QuestionFactory};
class TrainSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// Book::truncate();
// (new BookFactory)->count(50)->create();
Question::truncate();
(new QuestionFactory)->count(20)->create();
}
}

View File

@ -14,4 +14,7 @@ return [
'exam_status' => '状态',
'question_id' => '考题',
'score' => '分值',
'publish' => '生成考卷',
'cancel' => '取消考试',
];

View File

@ -0,0 +1,14 @@
<?php
return [
'id' => 'ID',
'created_at' => '创建时间',
'updated_at' => '更新时间',
'employee_id' => '员工',
'examination_id' => '考试',
'content' => '试卷',
'mark' => '得分',
'finished_at' => '答题时间',
'is_finished' => '是否完成答题',
];

View File

@ -10,4 +10,7 @@ return [
'cate' => '类型',
'is_true' => '正确答案',
'text' => '选项',
'score' => '分值',
'user_score' => '得分',
'user_answer' => '回答',
];

View File

@ -19,6 +19,7 @@ Route::get('keyword', [\App\Http\Controllers\Api\KeywordController::class, 'inde
// 字典表
Route::get('keywords', [KeywordController::class, 'index']);
Route::group([
'middleware' => ['auth:api'],
], function () {
@ -95,4 +96,13 @@ Route::group([
Route::get('workflow/{id}/logs', [\App\Http\Controllers\Api\WorkflowController::class, 'logs']);
Route::post('workflow/{id}/check', [\App\Http\Controllers\Api\WorkflowController::class, 'check']);
Route::post('workflow/{id}/cancel', [\App\Http\Controllers\Api\WorkflowController::class, 'cancel']);
// 培训-课件
Route::get('train/books', [\App\Http\Controllers\Api\Train\BookController::class, 'index']);
Route::get('train/books/{id}', [\App\Http\Controllers\Api\Train\BookController::class, 'show']);
// 培训-考试
Route::get('train/examinations', [\App\Http\Controllers\Api\Train\ExaminationController::class, 'index']);
Route::get('train/examinations/{id}', [\App\Http\Controllers\Api\Train\ExaminationController::class, 'show']);
Route::post('train/examinations/{id}/answer', [\App\Http\Controllers\Api\Train\ExaminationController::class, 'answer']);
});