generated from liutk/owl-admin-base
admin 培训管理-题库管理
parent
9a9dca2681
commit
53684c9141
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers\Train;
|
||||
|
||||
use App\Admin\Controllers\AdminController;
|
||||
use App\Admin\Services\Train\QuestionService;
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use App\Enums\QuestionCate;
|
||||
|
||||
/**
|
||||
* 题库管理
|
||||
*/
|
||||
class QuestionController extends AdminController
|
||||
{
|
||||
protected string $serviceName = QuestionService::class;
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->tableLayout('fixed')
|
||||
->headerToolbar([
|
||||
$this->createTypeButton('drawer', 'xl')->visible(Admin::user()->can('admin.train.questions.create')),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->bulkActions([])
|
||||
->filter($this->baseFilter()->body([
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amisMake()->TextControl()->name('search')->label(__('train_question.title'))->columnRatio(3)->clearable(),
|
||||
amisMake()->SelectControl()->options(QuestionCate::options())->name('cate')->label(__('train_question.cate'))->columnRatio(3)->clearable(),
|
||||
]),
|
||||
]))
|
||||
->columns([
|
||||
amisMake()->TableColumn()->name('id')->label(__('train_question.id')),
|
||||
amisMake()->TableColumn()->name('title')->label(__('train_question.title')),
|
||||
amisMake()->TableColumn()->name('cate')->label(__('train_question.cate'))->set('type', 'mapping')->set('map', QuestionCate::options()),
|
||||
amisMake()->TableColumn()->name('created_at')->label(__('train_book.created_at')),
|
||||
$this->rowActions([
|
||||
$this->rowShowTypeButton('drawer', 'xl')->visible(Admin::user()->can('admin.train.questions.view')),
|
||||
$this->rowEditTypeButton('drawer', 'xl')->visible(Admin::user()->can('admin.train.questions.update')),
|
||||
$this->rowDeleteButton()->visible(Admin::user()->can('admin.train.questions.delete')),
|
||||
]),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form($edit): Form
|
||||
{
|
||||
return $this->baseForm()->data(['cate' => QuestionCate::Radio->value])->title('')->body([
|
||||
amisMake()->TextControl()->name('title')->label(__('train_book.title'))->required(),
|
||||
amisMake()->RadiosControl()->options(QuestionCate::options())->name('cate')->label(__('train_question.cate')),
|
||||
amisMake()->TableControl()
|
||||
->addable()
|
||||
->editable()
|
||||
->removable()
|
||||
->needConfirm(false)
|
||||
->columns([
|
||||
amisMake()->TextControl()->name('text')->label(__('train_question.text'))->required(),
|
||||
amisMake()->CheckboxControl()->name('is_true')->label(__('train_question.is_true')),
|
||||
])
|
||||
->name('options')
|
||||
->label(__('train_question.options')),
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
return $this->baseDetail()->title('')->body(amisMake()->Property()->items([
|
||||
['label' => __('train_question.title'), 'content' => '${title}'],
|
||||
['label' => __('train_question.cate'), 'content' => '${cate}'],
|
||||
['label' => __('train_question.created_at'), 'content' => '${created_at}'],
|
||||
['label' => __('train_question.options'), 'content' => amisMake()->Table()->source('${options}')->columns([
|
||||
['name' => 'text', 'label' => __('train_question.text')],
|
||||
['name' => 'is_true', 'label' => __('train_question.is_true'), 'type' => 'status'],
|
||||
]), 'span' => 3],
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Filters;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use EloquentFilter\ModelFilter;
|
||||
|
||||
class TrianQuestionFilter extends ModelFilter
|
||||
{
|
||||
public function search($key)
|
||||
{
|
||||
$condition = '%'.$key.'%';
|
||||
return $this->where('title', 'like', $condition);
|
||||
}
|
||||
|
||||
public function cate($key)
|
||||
{
|
||||
return $this->where('cate', $key);
|
||||
}
|
||||
|
||||
public function dateRange($dates)
|
||||
{
|
||||
$dates = explode(',', $dates);
|
||||
$start = Carbon::createFromTimestamp(data_get($dates, 0, time()))->startOfDay();
|
||||
$end = Carbon::createFromTimestamp(data_get($dates, 1, time()))->endOfDay();
|
||||
$this->whereBetween('created_at', [$start, $end]);
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ class BookService extends BaseService
|
|||
{
|
||||
$createRules = [
|
||||
'title' => ['required'],
|
||||
'catgeory_id' => ['required'],
|
||||
'category_id' => ['required'],
|
||||
'type' => ['required'],
|
||||
'files' => ['array'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Services\Train;
|
||||
|
||||
use App\Admin\Filters\TrianQuestionFilter;
|
||||
use App\Models\Train\Question;
|
||||
use App\Admin\Services\BaseService;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\{Validator, Storage};
|
||||
|
||||
class QuestionService extends BaseService
|
||||
{
|
||||
protected array $withRelationships = [];
|
||||
|
||||
protected string $modelName = Question::class;
|
||||
|
||||
protected string $modelFilterName = TrianQuestionFilter::class;
|
||||
|
||||
public function resloveData($data, $model = null)
|
||||
{
|
||||
if (isset($data['options']) && $data['options']) {
|
||||
$options = [];
|
||||
foreach($data['options'] as $key => $item) {
|
||||
$item['is_true'] = data_get($item, 'is_true', false);
|
||||
array_push($options, $item);
|
||||
}
|
||||
$data['options'] = $options;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
@ -187,7 +187,10 @@ Route::group([
|
|||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
$router->group(['prefix' => 'train', 'as' => 'train.'], function (Router $router) {
|
||||
// 课件管理
|
||||
$router->resource('books', \App\Admin\Controllers\Train\BookController::class);
|
||||
// 题库管理
|
||||
$router->resource('questions', \App\Admin\Controllers\Train\QuestionController::class);
|
||||
});
|
||||
|
||||
$router->post('agreement/download', [AgreementController::class, 'download'])->name('agreement.download');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Train;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Traits\HasDateTimeFormatter;
|
||||
use EloquentFilter\Filterable;
|
||||
|
||||
/**
|
||||
* 题库
|
||||
*/
|
||||
class Question extends Model
|
||||
{
|
||||
use HasFactory, HasDateTimeFormatter, Filterable;
|
||||
|
||||
protected $table = 'train_questions';
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'cate' => \App\Enums\QuestionCate::class,
|
||||
'options' => 'json',
|
||||
];
|
||||
}
|
||||
|
|
@ -27,30 +27,22 @@ return new class extends Migration
|
|||
$table->comment('培训-课件');
|
||||
});
|
||||
|
||||
Schema::create('train_question_banks', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment('题库名称');
|
||||
$table->string('remarks')->nullable()->comment('备注');
|
||||
$table->timestamps();
|
||||
|
||||
$table->comment('培训-题库');
|
||||
});
|
||||
|
||||
Schema::create('train_questions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('bank_id')->comment('题库');
|
||||
$table->text('title')->comment('题目');
|
||||
$table->tinyInteger('cate')->default(QuestionCate::Radio->value)->comment('类型');
|
||||
$table->json('options')->nullable()->comment('选项[{text: 选项1, is_true: 是否正确答案}]');
|
||||
|
||||
$table->timestamps();
|
||||
$table->comment('培训-考题');
|
||||
$table->comment('培训-题库');
|
||||
});
|
||||
|
||||
Schema::create('train_examinations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment('考试名称');
|
||||
$table->json('questions')->comment('考题内容[{title: 题目, cate: 类型, options: [选项1, 选项2], score: 分值, answer: 正确选项}]');
|
||||
$table->unsignedInteger('total_questions')->default(0)->comment('总题数');
|
||||
$table->unsignedInteger('total_score')->default(0)->comment('总分数');
|
||||
$table->string('remarks')->nullable()->comment('备注');
|
||||
$table->timestamps();
|
||||
|
||||
|
|
@ -59,10 +51,10 @@ return new class extends Migration
|
|||
|
||||
Schema::create('train_examination_papers', function ($table) {
|
||||
$table->id();
|
||||
$table->foreignId('employee_id')->comment('考生');
|
||||
$table->foreignId('examination_id')->comment('考试, train_examinations.id');
|
||||
$table->foreignId('employee_id')->comment('考生');
|
||||
$table->json('content')->comment('考卷内容[{title: 题目, cate: 类型, options: [选项1, 选项2], score: 分值, answer: 正确选项, user_score: 得分, user_answer: 回答}]');
|
||||
$table->decimal('mark', 12, 2)->nullable()->comment('分数');
|
||||
$table->unsignedInteger('mark')->nullable()->comment('分数');
|
||||
$table->timestamp('start_at')->nullable()->comment('答题开始时间');
|
||||
$table->timestamp('end_at')->nullable()->comment('答题结束时间');
|
||||
$table->timestamps();
|
||||
|
|
@ -78,7 +70,6 @@ return new class extends Migration
|
|||
{
|
||||
Schema::dropIfExists('train_books');
|
||||
Schema::dropIfExists('train_questions');
|
||||
Schema::dropIfExists('train_question_banks');
|
||||
Schema::dropIfExists('train_examination_papers');
|
||||
Schema::dropIfExists('train_examinations');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -255,12 +255,18 @@ class AdminPermissionSeeder extends Seeder
|
|||
'icon' => '',
|
||||
'uri' => '/train',
|
||||
'children' => [
|
||||
'book' => [
|
||||
'books' => [
|
||||
'name' => '课件管理',
|
||||
'icon' => '',
|
||||
'uri' => '/train/books',
|
||||
'resource' => true,
|
||||
]
|
||||
],
|
||||
'questions' => [
|
||||
'name' => '题库管理',
|
||||
'icon' => '',
|
||||
'uri' => '/train/questions',
|
||||
'resource' => true,
|
||||
],
|
||||
]
|
||||
],
|
||||
'agreement' => [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'created_at' => '创建时间',
|
||||
'updated_at' => '更新时间',
|
||||
|
||||
'title' => '题目',
|
||||
'options' => '选项',
|
||||
'cate' => '类型',
|
||||
'is_true' => '正确答案',
|
||||
'text' => '选项',
|
||||
];
|
||||
Loading…
Reference in New Issue