diff --git a/backend/app/Http/Controllers/Admin/System/PositionController.php b/backend/app/Http/Controllers/Admin/System/PositionController.php index 2bea1b7..4ed08a4 100644 --- a/backend/app/Http/Controllers/Admin/System/PositionController.php +++ b/backend/app/Http/Controllers/Admin/System/PositionController.php @@ -21,7 +21,10 @@ class PositionController extends Controller { $data = $request->validate([ 'name' => 'required|string|max:50', + 'code' => 'nullable|string|max:50', 'sort' => 'nullable|integer', + 'status' => 'in:0,1', + 'description' => 'nullable|string|max:255', ]); $data['store_id'] = auth()->user()->store_id; @@ -34,7 +37,10 @@ class PositionController extends Controller { $data = $request->validate([ 'name' => 'string|max:50', + 'code' => 'nullable|string|max:50', 'sort' => 'nullable|integer', + 'status' => 'in:0,1', + 'description' => 'nullable|string|max:255', ]); $position->update($data); diff --git a/backend/app/Models/Position.php b/backend/app/Models/Position.php index d546705..b532308 100644 --- a/backend/app/Models/Position.php +++ b/backend/app/Models/Position.php @@ -9,5 +9,5 @@ class Position extends Model { use BelongsToStore; - protected $fillable = ['store_id', 'name', 'sort']; + protected $fillable = ['store_id', 'name', 'code', 'sort', 'status', 'description']; } diff --git a/backend/database/migrations/2026_03_14_000005_add_status_code_to_positions_table.php b/backend/database/migrations/2026_03_14_000005_add_status_code_to_positions_table.php new file mode 100644 index 0000000..35d58c8 --- /dev/null +++ b/backend/database/migrations/2026_03_14_000005_add_status_code_to_positions_table.php @@ -0,0 +1,24 @@ +string('code', 50)->nullable()->after('name')->comment('职务编码'); + $table->tinyInteger('status')->default(1)->after('sort')->comment('1启用 0停用'); + $table->string('description', 255)->nullable()->after('status')->comment('备注'); + }); + } + + public function down(): void + { + Schema::table('positions', function (Blueprint $table) { + $table->dropColumn(['code', 'status', 'description']); + }); + } +}; diff --git a/frontend/src/views/system/departments/index.vue b/frontend/src/views/system/departments/index.vue index 58a679c..1f38feb 100644 --- a/frontend/src/views/system/departments/index.vue +++ b/frontend/src/views/system/departments/index.vue @@ -74,9 +74,15 @@ async function fetchTree() { loading.value = true try { const res = await departmentApi.getList({ per_page: 500 }) - const flat = res.data?.list || res.data?.data || [] - flatDepts.value = flat.map(d => ({ id: d.id, name: d.name })) - treeData.value = buildTree(flat) + // Backend already returns a tree array directly in res.data + if (Array.isArray(res.data)) { + treeData.value = res.data + flatDepts.value = flattenTree(res.data) + } else { + const flat = res.data?.list || res.data?.data || [] + flatDepts.value = flat.map(d => ({ id: d.id, name: d.name })) + treeData.value = buildTree(flat) + } } catch { // } finally { @@ -84,9 +90,9 @@ async function fetchTree() { } } -function buildTree(nodes, parentId = null) { +function buildTree(nodes, parentId = 0) { return nodes - .filter(n => (n.parent_id ?? null) === parentId) + .filter(n => (n.parent_id ?? 0) === parentId) .map(n => ({ ...n, children: buildTree(nodes, n.id) })) }