Bladeren bron

文章分类增加pid
科目增加attr_type

罗永浩 5 maanden geleden
bovenliggende
commit
889b257a4e

+ 1 - 1
addons/admin/src/views/exam/articleList.vue

@@ -54,7 +54,7 @@
                     <el-table-column label="分类" width="120">
                         <template slot-scope="{ row }">
                             <el-tag type="primary">
-                                {{ getCategoryName(row.cate_id) }}
+                                {{ row.cate_name }}
                             </el-tag>
                         </template>
                     </el-table-column>

+ 37 - 3
addons/admin/src/views/exam/component/ArticleForm.vue

@@ -9,8 +9,13 @@
 
                 <el-form-item label="分类" prop="cate_id">
                     <el-select v-model="formData.cate_id" placeholder="请选择分类" class="ele-fluid" clearable>
-                        <el-option v-for="category in categoryOptions" :key="category.id" :label="category.name"
-                            :value="category.id" />
+                        <template v-for="category in categoryOptions">
+                            <el-option-group :label="category.name">
+                                <el-option :value="category.id" :label="category.name" />
+                                <el-option v-for="child in category.children" :key="child.id" :value="child.id"
+                                    :label="child.name" />
+                            </el-option-group>
+                        </template>
                     </el-select>
                 </el-form-item>
 
@@ -141,6 +146,34 @@ export default {
             }
         };
     },
+    computed: {
+        // 扁平化分类选项,用于下拉选择
+        flatCategoryOptions() {
+            const options = [];
+            this.categoryOptions.forEach(category => {
+                // 添加一级分类
+                options.push({
+                    id: category.id,
+                    label: category.name,
+                    level: 1,
+                    parentId: null
+                });
+                // 添加子分类
+                if (category.children && category.children.length > 0) {
+                    category.children.forEach(child => {
+                        options.push({
+                            id: child.id,
+                            label: '  ' + child.name,
+                            level: 2,
+                            parentId: category.id
+                        });
+                    });
+                }
+            });
+            console.log('flatCategoryOptions', options);
+            return options;
+        }
+    },
     watch: {
         visible(val) {
             this.visibleInternal = val;
@@ -236,7 +269,8 @@ export default {
                     }
                 });
                 if (res.data.code === 0) {
-                    this.categoryOptions = res.data.data || [];
+                    // 确保数据是树形结构
+                    this.categoryOptions = res.data.data || []
                 }
                 this.loaded = true;
             } catch (error) {

+ 50 - 6
addons/admin/src/views/exam/component/CategoryManager.vue

@@ -7,13 +7,13 @@
             </div>
 
             <!-- 分类列表 -->
-            <el-table :data="categories" v-loading="loading" :border="true" :stripe="true">
-                <el-table-column label="排序" width="80" align="center">
+            <el-table :data="categories" v-loading="loading" :border="true" :stripe="true" row-key="id"
+                :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
+                <el-table-column label="分类名称" prop="name" min-width="150">
                     <template slot-scope="{ row }">
-                        <i class="el-icon-sort"></i>
+                        <span :style="{ paddingLeft: (row.level || 0) * 20 + 'px' }">{{ row.name }}</span>
                     </template>
                 </el-table-column>
-                <el-table-column label="分类名称" prop="name" min-width="150" />
                 <el-table-column label="图标" width="80" align="center">
                     <template slot-scope="{ row }">
                         <image-preview v-if="row.icon" size="xs" :images="[row.icon]" />
@@ -32,7 +32,7 @@
                         </el-tag>
                     </template>
                 </el-table-column>
-                <el-table-column label="操作" width="140" align="center" fixed="right">
+                <el-table-column label="操作" width="160" align="center" fixed="right">
                     <template slot-scope="{ row, $index }">
                         <el-button size="mini" type="primary" plain @click="editCategory(row)">编辑</el-button>
                         <el-button size="mini" type="danger" plain @click="deleteCategory(row, $index)">删除</el-button>
@@ -49,6 +49,13 @@
                     <el-input v-model="form.name" placeholder="请输入分类名称" />
                 </el-form-item>
 
+                <el-form-item label="父级分类" prop="pid">
+                    <el-select v-model="form.pid" placeholder="请选择父级分类" clearable>
+                        <el-option v-for="category in parentCategories" :key="category.id" :label="category.name"
+                            :value="category.id" :disabled="category.id === form.id" />
+                    </el-select>
+                </el-form-item>
+
                 <el-form-item label="图标" prop="icon">
                     <uploadImage :limit="1" v-model="form.icon" />
                 </el-form-item>
@@ -106,6 +113,7 @@ export default {
                 name: '',
                 icon: '',
                 type: 1,
+                pid: '',
                 sort: 0,
                 description: '',
                 status: 1
@@ -117,7 +125,8 @@ export default {
                 status: [
                     { required: true, message: '请选择状态', trigger: 'change' }
                 ]
-            }
+            },
+            parentCategories: [] // 父级分类选项
         }
     },
     watch: {
@@ -146,6 +155,8 @@ export default {
 
                 if (res.data.code === 0) {
                     this.categories = res.data.data || [];
+                    // 同时加载父级分类选项(扁平化结构)
+                    this.loadParentCategories();
                 } else {
                     this.$message.error(res.data.msg);
                 }
@@ -157,6 +168,38 @@ export default {
             }
         },
 
+        // 加载父级分类选项
+        async loadParentCategories() {
+            try {
+                const res = await this.$http.get('/articleCategory/parentOptions', {
+                    params: {
+                        type: this.article_cate_type
+                    }
+                });
+
+                if (res.data.code === 0) {
+                    // 扁平化树形结构,用于父级选择
+                    this.parentCategories = res.data.data
+                }
+            } catch (error) {
+                this.$message.error('加载父级分类失败');
+                console.error(error);
+            }
+        },
+
+        // 扁平化树形结构
+        flattenTree(tree, level = 0) {
+            let result = [];
+            tree.forEach(item => {
+                const flatItem = { ...item, level };
+                result.push(flatItem);
+                if (item.children && item.children.length > 0) {
+                    result = result.concat(this.flattenTree(item.children, level + 1));
+                }
+            });
+            return result;
+        },
+
         // 显示添加表单
         showAddForm() {
             this.isEdit = false;
@@ -237,6 +280,7 @@ export default {
                 name: '',
                 icon: '',
                 type: this.article_cate_type,
+                pid: '',
                 sort: 0,
                 description: '',
                 status: 1

+ 52 - 2
addons/admin/src/views/exam/component/SubjectManager.vue

@@ -6,6 +6,21 @@
                 <template slot-scope="{ row }">
                     <el-table-column prop="id" label="ID" width="60" align="center" />
                     <el-table-column prop="subject_name" label="课程名称" min-width="150" />
+                    <el-table-column prop="description" label="描述" min-width="120" show-overflow-tooltip />
+                    <el-table-column prop="icon" label="图标" width="100">
+                        <template slot-scope="{ row }">
+                            <img v-if="row.icon" :src="row.icon" style="width: 30px; height: 30px;" />
+                            <span v-else>-</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="attr_type" label="类别属性" width="120"
+                        v-if="defaultType === 2 || defaultType === 3">
+                        <template slot-scope="{ row }">
+                            <el-tag type="success" v-if="row.attr_type">{{ attrTypeOptions[row.attr_type] || '未知'
+                            }}</el-tag>
+                            <span v-else>-</span>
+                        </template>
+                    </el-table-column>
                     <el-table-column prop="sort" label="排序" width="100" />
                     <el-table-column prop="status" label="状态" width="100">
                         <template slot-scope="{ row }">
@@ -35,6 +50,19 @@
                 <el-form-item label="课程名称" prop="subject_name">
                     <el-input v-model="formData.subject_name" placeholder="请输入科目名称" />
                 </el-form-item>
+                <el-form-item label="描述" prop="description">
+                    <el-input v-model="formData.description" placeholder="请输入描述" />
+                </el-form-item>
+                <el-form-item label="图标" prop="icon">
+                    <uploadImage :limit="1" v-model="formData.icon" @upload-success="onImageUploadSuccess">
+                    </uploadImage>
+                </el-form-item>
+                <el-form-item label="类别属性" prop="attr_type" v-if="defaultType === 2 || defaultType === 3">
+                    <el-select v-model="formData.attr_type" placeholder="请选择类别属性" clearable>
+                        <el-option v-for="(label, key) in attrTypeOptions" :key="key" :label="label"
+                            :value="Number(key)" />
+                    </el-select>
+                </el-form-item>
                 <el-form-item label="排序" prop="sort">
                     <el-input-number v-model="formData.sort" :min="0" />
                 </el-form-item>
@@ -52,12 +80,17 @@
 </template>
 
 <script>
+import uploadImage from '@/components/uploadImage.vue'
+
 export default {
     name: "SubjectManager",
+    components: {
+        uploadImage
+    },
     props: {
         visible: { type: Boolean, default: false },
         defaultSceneType: { type: Number, default: null },
-        defaultType: { type: Number, default: null },
+        defaultType: { type: Number, default: null }, // type=1 单招,type=2 对口,type=3 专升本
     },
     data() {
         return {
@@ -73,6 +106,9 @@ export default {
                 id: null,
                 subject_name: '',
                 type: this.defaultType,
+                attr_type: null,
+                description: '',
+                icon: '',
                 sort: 0,
                 status: 1
             },
@@ -80,6 +116,7 @@ export default {
                 subject_name: [{ required: true, message: '请输入科目名称', trigger: 'blur' }],
                 type: [{ required: true, message: '请选择所属栏目', trigger: 'change' }]
             },
+            attrTypeOptions: { 1: "文化基础" },
         }
     },
     watch: {
@@ -96,7 +133,12 @@ export default {
         openForm(row) {
             if (row) {
                 this.isEdit = true
-                Object.assign(this.formData, row)
+                Object.assign(this.formData, {
+                    ...row,
+                    attr_type: row.attr_type ? Number(row.attr_type) : null,
+                    description: row.description || '',
+                    icon: row.icon || ''
+                })
             } else {
                 this.resetForm()
             }
@@ -143,6 +185,11 @@ export default {
             })
         },
 
+        // 图片上传成功回调
+        onImageUploadSuccess(data) {
+            this.$message.success('图标上传成功');
+        },
+
         // 重置表单数据和校验状态
         resetForm() {
             this.isEdit = false
@@ -150,6 +197,9 @@ export default {
                 id: null,
                 subject_name: '',
                 type: this.defaultType, // 使用父组件传入默认栏目
+                attr_type: this.defaultType === 1 ? 0 : null, // 单招默认为0,对口和专升本为null
+                description: '',
+                icon: '',
                 sort: 0,
                 status: 1
             })

+ 80 - 6
addons/admin/src/views/subject/subject.vue

@@ -18,6 +18,14 @@
                         </el-form-item>
                     </el-col>
                     <el-col :md="6" :sm="12">
+                        <el-form-item label="类别属性">
+                            <el-select v-model="table.where.attr_type" placeholder="请选择类别属性" clearable>
+                                <el-option v-for="(label, key) in attrTypeOptions" :key="key" :label="label"
+                                    :value="key" />
+                            </el-select>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :md="6" :sm="12">
                         <el-form-item label="状态">
                             <el-select v-model="table.where.status" placeholder="请选择" clearable>
                                 <el-option label="有效" :value="1" />
@@ -54,11 +62,25 @@
                     <el-table-column type="selection" width="45" align="center" fixed="left" />
                     <el-table-column type="index" label="编号" width="60" align="center" fixed="left" />
                     <el-table-column prop="subject_name" label="科目名称" min-width="150" />
+                    <el-table-column prop="description" label="描述" min-width="120" show-overflow-tooltip />
+                    <el-table-column prop="icon" label="图标" width="100">
+                        <template slot-scope="{ row }">
+                            <img v-if="row.icon" :src="row.icon" style="width: 30px; height: 30px;" />
+                            <span v-else>-</span>
+                        </template>
+                    </el-table-column>
                     <el-table-column prop="type" label="所属栏目" width="120">
                         <template slot-scope="{ row }">
                             <el-tag type="info">{{ typeOptions[row.type] || '未知' }}</el-tag>
                         </template>
                     </el-table-column>
+                    <el-table-column prop="attr_type" label="类别属性" width="120" v-if="showAttrTypeColumn">
+                        <template slot-scope="{ row }">
+                            <el-tag type="success" v-if="row.attr_type">{{ attrTypeOptions[row.attr_type] || '未知'
+                                }}</el-tag>
+                            <span v-else>-</span>
+                        </template>
+                    </el-table-column>
                     <el-table-column prop="sort" label="排序" width="100" />
                     <el-table-column label="状态" width="80">
                         <template slot-scope="{ row }">
@@ -84,11 +106,24 @@
                 <el-form-item label="科目名称" prop="subject_name">
                     <el-input v-model="formData.subject_name" placeholder="请输入科目名称" />
                 </el-form-item>
+                <el-form-item label="描述" prop="description">
+                    <el-input v-model="formData.description" placeholder="请输入描述" />
+                </el-form-item>
+                <el-form-item label="图标" prop="icon">
+                    <uploadImage :limit="1" v-model="formData.icon" @upload-success="onImageUploadSuccess">
+                    </uploadImage>
+                </el-form-item>
                 <el-form-item label="所属栏目" prop="type">
                     <el-select v-model="formData.type" placeholder="请选择栏目">
                         <el-option v-for="(label, key) in typeOptions" :key="key" :label="label" :value="Number(key)" />
                     </el-select>
                 </el-form-item>
+                <el-form-item label="类别属性" prop="attr_type" v-if="showAttrTypeField">
+                    <el-select v-model="formData.attr_type" placeholder="请选择类别属性" clearable>
+                        <el-option v-for="(label, key) in attrTypeOptions" :key="key" :label="label"
+                            :value="Number(key)" />
+                    </el-select>
+                </el-form-item>
                 <el-form-item label="排序" prop="sort">
                     <el-input-number v-model="formData.sort" :min="0" />
                 </el-form-item>
@@ -106,16 +141,21 @@
 
 <script>
 import { mapGetters } from 'vuex'
+import uploadImage from '@/components/uploadImage.vue'
+
 export default {
     name: "SubjectPage",
+    components: {
+        uploadImage
+    },
     data() {
         return {
             table: {
                 url: "/subjects/index",
-                where: { keyword: "", type: null, status: null }
+                where: { keyword: "", type: null, attr_type: null, status: null }
             },
             choose: [],
-            formData: { id: null, subject_name: "", type: 1, sort: 0, status: 1 },
+            formData: { id: null, subject_name: "", type: 1, attr_type: null, description: "", icon: "", sort: 0, status: 1 },
             isEdit: false,
             formVisible: false,
             formRules: {
@@ -123,6 +163,7 @@ export default {
                 type: [{ required: true, message: "请选择所属栏目", trigger: "change" }]
             },
             typeOptions: { 1: "单招", 2: "对口", 3: "专升本" },
+            attrTypeOptions: { 1: "文化基础" },
             permissionMap: {
                 delete: "sys:subject:delete",
                 edit: "sys:subject:edit",
@@ -131,19 +172,47 @@ export default {
             }
         };
     },
-    computed: { ...mapGetters(["permission"]) },
+    computed: {
+        ...mapGetters(["permission"]),
+        // 是否显示类别属性列(只有对口和专升本才显示)
+        showAttrTypeColumn() {
+            return this.table.where.type === 2 || this.table.where.type === 3;
+        },
+        // 是否显示类别属性字段(只有对口和专升本才显示)
+        showAttrTypeField() {
+            return this.formData.type === 2 || this.formData.type === 3;
+        }
+    },
+    watch: {
+        // 监听类型变化,自动设置 attr_type
+        'formData.type'(newType) {
+            if (newType === 1) {
+                // 单招时设置为0
+                this.formData.attr_type = 0;
+            } else if (newType === 2 || newType === 3) {
+                // 对口和专升本时设置为null(可选)
+                this.formData.attr_type = null;
+            }
+        }
+    },
     methods: {
         resetSearch() {
-            this.table.where = { keyword: "", type: null, status: null };
+            this.table.where = { keyword: "", type: null, attr_type: null, status: null };
             this.$refs.table.reload();
         },
         openForm(row) {
             if (row) {
                 this.isEdit = true;
-                this.formData = { ...row, type: Number(row.type) }; // 转成数字
+                this.formData = {
+                    ...row,
+                    type: Number(row.type),
+                    attr_type: row.attr_type ? Number(row.attr_type) : (Number(row.type) === 1 ? 0 : null),
+                    description: row.description || "",
+                    icon: row.icon || ""
+                }; // 转成数字
             } else {
                 this.isEdit = false;
-                this.formData = { id: null, subject_name: "", type: 1, sort: 0, status: 1 };
+                this.formData = { id: null, subject_name: "", type: 1, attr_type: 0, description: "", icon: "", sort: 0, status: 1 };
             }
             this.formVisible = true;
         },
@@ -188,6 +257,11 @@ export default {
             this.$http.post("/subjects/status", { id: row.id, status: row.status }).then(res => {
                 if (res.data.code !== 0) this.$message.error(res.data.msg);
             });
+        },
+
+        // 图片上传成功回调
+        onImageUploadSuccess(data) {
+            this.$message.success('图标上传成功');
         }
     }
 };

+ 9 - 0
app/Http/Controllers/Admin/ArticleCategoryController.php

@@ -51,6 +51,15 @@ class ArticleCategoryController extends Backend
     }
 
     /**
+     * 获取父级分类选项
+     */
+    public function parentOptions()
+    {
+        $list = $this->service->getParentOptions();
+        return response()->json(['code' => 0, 'msg' => '操作成功', 'data' => $list]);
+    }
+
+    /**
      * 获取分类详情
      */
     public function info()

+ 14 - 0
app/Models/ArticleCategoryModel.php

@@ -12,4 +12,18 @@ class ArticleCategoryModel extends BaseModel
 {
     // 设置数据表
     protected $table = 'article_cates';
+
+    // 设置可填充字段
+    protected $fillable = [
+        'name',
+        'icon',
+        'type',
+        'pid',
+        'sort',
+        'description',
+        'status',
+        'create_time',
+        'update_time',
+        'mark'
+    ];
 }

+ 14 - 1
app/Models/ExamSubjectsModel.php

@@ -9,4 +9,17 @@ class ExamSubjectsModel extends BaseModel
     protected $table = 'exam_subjects';
     public $timestamps = false;
 
-}
+    protected $fillable = [
+        'subject_name',
+        'pid',
+        'type',
+        'attr_type',
+        'description',
+        'icon',
+        'sort',
+        'create_time',
+        'update_time',
+        'status',
+        'mark'
+    ];
+}

+ 75 - 11
app/Services/Common/ArticleCategoryService.php

@@ -4,6 +4,7 @@ namespace App\Services\Common;
 
 use App\Models\ArticleCategoryModel;
 use App\Services\BaseService;
+use Illuminate\Support\Facades\DB;
 
 /**
  * 文章分类管理-服务类
@@ -26,7 +27,7 @@ class ArticleCategoryService extends BaseService
     }
 
     /**
-     * 获取分类数据列表
+     * 获取分类数据列表(树形结构)
      */
     public function getDataList($params, $pageSize = 15)
     {
@@ -47,14 +48,13 @@ class ArticleCategoryService extends BaseService
             $query->where('name', 'like', "%{$params['keyword']}%");
         }
 
-        $paginator = $query->orderBy('sort', 'desc')
+        $items = $query->orderBy('sort', 'desc')
             ->orderBy('id', 'desc')
-            ->paginate($pageSize > 0 ? $pageSize : 9999999);
+            ->get()
+            ->toArray();
 
-        $list = $paginator ? $paginator->toArray() : [];
 
         // 处理图片字段
-        $items = isset($list['data']) ? $list['data'] : [];
         foreach ($items as &$item) {
             if (!empty($item['icon'])) {
                 $item['icon'] = get_image_url($item['icon']);
@@ -63,15 +63,38 @@ class ArticleCategoryService extends BaseService
             $item['update_time'] = $item['update_time'] ? datetime($item['update_time'], 'Y-m-d H:i:s') : '';
         }
 
+        // 构建树形结构
+        $tree = $this->buildTree($items);
+
         return [
             'pageSize' => $pageSize,
-            'total' => isset($list['total']) ? $list['total'] : 0,
-            'list' => $items
+            'total' => count($items),
+            'list' => $tree
         ];
     }
 
     /**
-     * 获取分类选项列表
+     * 构建树形结构
+     */
+    private function buildTree($items, $pid = 0)
+    {
+        $tree = [];
+        foreach ($items as $item) {
+            // 确保 pid 字段存在,默认为 0
+            $itemPid = isset($item['pid']) ? $item['pid'] : 0;
+            if ($itemPid == $pid) {
+                $children = $this->buildTree($items, $item['id']);
+                if (!empty($children)) {
+                    $item['children'] = $children;
+                }
+                $tree[] = $item;
+            }
+        }
+        return $tree;
+    }
+
+    /**
+     * 获取分类选项列表(树形结构)
      * @return array
      */
     public function getOptions()
@@ -84,12 +107,52 @@ class ArticleCategoryService extends BaseService
             $query->where('type', $type);
         }
 
-        $datas = $query->select(['id', 'name'])
+
+        $datas = $query->select(['id', 'name', 'pid'])
+            ->orderBy('sort', 'desc')
+            ->orderBy('id', 'desc')
+            ->get()
+            ->toArray();
+
+        // 构建树形结构
+        return $this->buildTree($datas);
+    }
+
+    /**
+     * 获取父级分类选项(用于选择父级分类)
+     * @return array
+     */
+    public function getParentOptions()
+    {
+        $query = $this->model->where(['status' => 1, 'mark' => 1, 'pid' => 0]);
+
+        // 按类型过滤
+        $type = request()->get('type');
+        if ($type) {
+            $query->where('type', $type);
+        }
+
+        return $query->select(['id', 'name', 'pid'])
             ->orderBy('sort', 'desc')
             ->orderBy('id', 'desc')
-            ->get();
+            ->get()
+            ->toArray();
+    }
 
-        return $datas ? $datas->toArray() : [];
+    /**
+     * 检查表是否有 pid 字段
+     * @return bool
+     */
+    private function checkPidFieldExists()
+    {
+        try {
+            $tableName = $this->model->getTable();
+            $columns = DB::select("SHOW COLUMNS FROM `{$tableName}` LIKE 'pid'");
+            return !empty($columns);
+        } catch (\Exception $e) {
+            // 如果查询失败,假设没有 pid 字段
+            return false;
+        }
     }
 
     /**
@@ -105,6 +168,7 @@ class ArticleCategoryService extends BaseService
         }
 
         $id = $data['id'] ?? 0;
+        $data['pid'] = empty($data['pid']) ? 0 : $data['pid'];
 
         // 默认字段处理
         $data['update_time'] = time();

+ 1 - 1
app/Services/Common/ArticleService.php

@@ -92,7 +92,7 @@ class ArticleService extends BaseService
                     $query->where('a.title', 'like', "%{$keyword}%")->orWhere('a.tags', 'like', "%{$keyword}%");
                 }
             })
-            ->select(['a.*'])
+            ->select(['a.*', 'ac.name as cate_name'])
             ->orderBy('a.create_time', 'desc');
 
         $list = $query->paginate($pageSize > 0 ? $pageSize : 9999999);

+ 12 - 3
app/Services/Exam/SubjectService.php

@@ -1,4 +1,5 @@
 <?php
+
 namespace App\Services\Exam;
 
 use App\Models\ExamSubjectsModel;
@@ -41,10 +42,15 @@ class SubjectService extends BaseService
             $query->where('type', $param['type']);
         }
 
+        if (!empty($param['attr_type'])) {
+            $query->where('attr_type', $param['attr_type']);
+        }
+
         if (!empty($param['keyword'])) {
             $query->where(function ($q) use ($param) {
                 $q->where('id', $param['keyword'])
-                    ->orWhere('subject_name', 'like', "%{$param['keyword']}%");
+                    ->orWhere('subject_name', 'like', "%{$param['keyword']}%")
+                    ->orWhere('description', 'like', "%{$param['keyword']}%");
             });
         }
 
@@ -55,7 +61,6 @@ class SubjectService extends BaseService
             'total' => isset($list['total']) ? $list['total'] : 0,
             'list' => isset($list['data']) ? $list['data'] : []
         ];
-        return message("操作成功", true, $list);
     }
 
     /**
@@ -101,16 +106,20 @@ class SubjectService extends BaseService
         $keyword = getter($param, "keyword");
         $sceneType = getter($param, "scene_type");
         $type = getter($param, "type");
+        $attrType = getter($param, "attr_type");
         $datas = $this->model
             ->where('status', '=', 1)
             ->where('mark', '=', 1)
-            ->where(function ($query) use ($keyword, $sceneType, $type) {
+            ->where(function ($query) use ($keyword, $sceneType, $type, $attrType) {
                 if ($keyword) {
                     $query->where('subject_name', 'like', "%{$keyword}%");
                 }
                 if ($type) {
                     $query->where('type', '=', $type);
                 }
+                if ($attrType) {
+                    $query->where('attr_type', '=', $attrType);
+                }
             })
             ->select(['subject_name', 'id'])
             ->get();

+ 2 - 0
routes/web.php

@@ -137,6 +137,7 @@ Route::post('/articleCategory/edit', [\App\Http\Controllers\Admin\ArticleCategor
 Route::post('/articleCategory/delete', [\App\Http\Controllers\Admin\ArticleCategoryController::class, 'delete']);
 Route::post('/articleCategory/status', [\App\Http\Controllers\Admin\ArticleCategoryController::class, 'status']);
 Route::get('/articleCategory/options', [\App\Http\Controllers\Admin\ArticleCategoryController::class, 'options']);
+Route::get('/articleCategory/parentOptions', [\App\Http\Controllers\Admin\ArticleCategoryController::class, 'parentOptions']);
 
 // 广告管理
 Route::get('/ad/index', [AdController::class, 'index']);
@@ -227,6 +228,7 @@ Route::post('/subjects/delete', [SubjectController::class, 'delete']);
 Route::post('/subjects/status', [SubjectController::class, 'status']);
 Route::get('/subjects/options', [SubjectController::class, 'options']);
 
+
 // Papers
 Route::get('/papers/index', [PaperController::class, 'index']);
 Route::get('/papers/info', [PaperController::class, 'info']);