From 7ff2185f8e7c314e46db450361225fe54c83f269 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sat, 21 Jun 2025 16:39:10 +0800 Subject: [PATCH] Init --- composer.json | 39 +++++ src/Service.php | 24 +++ src/controller/Dept.php | 120 ++++++++++++++ src/controller/User.php | 151 ++++++++++++++++++ src/model/StaffDept.php | 77 +++++++++ src/model/StaffUser.php | 38 +++++ src/view/dept/form.html | 29 ++++ src/view/dept/headman.html | 26 +++ src/view/dept/index.html | 89 +++++++++++ src/view/dept/index_search.html | 27 ++++ src/view/main.html | 23 +++ src/view/table.html | 23 +++ src/view/user/form.html | 91 +++++++++++ src/view/user/index.html | 131 +++++++++++++++ src/view/user/index_search.html | 27 ++++ .../20250621000000_install_staff_db.php | 89 +++++++++++ .../20250621000000_install_staff_menu.php | 54 +++++++ 17 files changed, 1058 insertions(+) create mode 100644 composer.json create mode 100644 src/Service.php create mode 100644 src/controller/Dept.php create mode 100644 src/controller/User.php create mode 100644 src/model/StaffDept.php create mode 100644 src/model/StaffUser.php create mode 100644 src/view/dept/form.html create mode 100644 src/view/dept/headman.html create mode 100644 src/view/dept/index.html create mode 100644 src/view/dept/index_search.html create mode 100644 src/view/main.html create mode 100644 src/view/table.html create mode 100644 src/view/user/form.html create mode 100644 src/view/user/index.html create mode 100644 src/view/user/index_search.html create mode 100644 stc/database/20250621000000_install_staff_db.php create mode 100644 stc/database/20250621000000_install_staff_menu.php diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..59c5fc3 --- /dev/null +++ b/composer.json @@ -0,0 +1,39 @@ +{ + "name": "q792602257/think-plugs-staff", + "description": "ThinkAdmin Plugin: Staff with Dept Support", + "version": "dev-master", + "minimum-stability": "dev", + "license": "WTFPL", + "authors": [ + { + "name": "Jerry Yan", + "email": "792602257@qq.com" + } + ], + "extra": { + "config": { + "type": "module", + "name": "员工及组织架构模块", + "platforms": ["h5web"], + "description": "员工及组织架构模块" + }, + "plugin": { + "copy": { + "stc/database": "database/migrations" + } + }, + "think": { + "services": [ + "jerryyan\\staff\\Service" + ] + } + }, + "autoload": { + "psr-4": { + "jerryyan\\staff\\": "src" + } + }, + "require": { + + } +} \ No newline at end of file diff --git a/src/Service.php b/src/Service.php new file mode 100644 index 0000000..cf1151e --- /dev/null +++ b/src/Service.php @@ -0,0 +1,24 @@ + '组织架构', + 'subs' => [ + ['name' => '员工管理', 'icon' => 'layui-icon layui-icon-group', 'url' => 'staff/user/index'], + ['name' => '部门管理', 'icon' => 'layui-icon layui-icon-cols', 'url' => 'staff/dept/index'], +// ['name' => '角色管理', 'icon' => 'layui-icon layui-icon-auz', 'url' => 'staff/role/index'], + ] + ] + ]; + } +} \ No newline at end of file diff --git a/src/controller/Dept.php b/src/controller/Dept.php new file mode 100644 index 0000000..cdbb600 --- /dev/null +++ b/src/controller/Dept.php @@ -0,0 +1,120 @@ +layTable(function () { + $this->title = '员工部门'; + }, static function (QueryHelper $query) { + $query->with('parent.parent')->append(['headman_name']); + $query->equal('status')->like('name'); + }); + } + + /** + * 添加部门 + * @auth true + * @menu true + * @return void + */ + public function add() + { + StaffDept::mForm('form'); + } + + /** + * 编辑部门 + * @auth true + * @return void + */ + public function edit() + { + StaffDept::mForm('form'); + } + + protected function _form_filter(array &$data) + { + if ($this->request->isPost()) { + $this->_vali([ + 'name.require' => '部门名称不能为空!', + ]); + } else { + $this->depts = StaffDept::topItems(); + } + } + + /** + * 部门排序 + * @auth true + * @return void + */ + public function sort() + { + StaffDept::mSave($this->_vali([ + 'sort.require' => '排序参数不能为空!', + 'sort.number' => '排序参数格式错误!', + ])); + } + + /** + * 设置部门领导人 + * @auth true + * @return void + */ + public function headman() + { + $data = $this->_vali([ + 'id.require' => '部门不能为空!', + ]); + if ($this->request->isGet()) { + $this->title = '设置部门负责人'; + $this->dept = StaffDept::mk()->where(['id' => $data['id']])->findOrEmpty(); + if ($this->dept->isEmpty()) $this->error('部门不存在!'); + $this->users = StaffUser::mk()->where(['status' => 1, 'dept_id' => $this->dept['id']])->select(); + $this->fetch(); + } else { + StaffDept::mSave($this->_vali([ + 'headman_id.require' => '部门领导人不能为空!', + 'headman_id.number' => '部门领导人格式错误!', + ])); + } + } + + /** + * 启用禁用部门 + * @auth true + * @return void + */ + public function state() + { + StaffDept::mSave($this->_vali([ + 'status.in:0,1' => '状态值范围异常!', + 'status.require' => '状态值不能为空!', + ])); + } + + /** + * 删除部门 + * @auth true + * @return void + */ + public function del() + { + StaffDept::mDelete(); + } + +} \ No newline at end of file diff --git a/src/controller/User.php b/src/controller/User.php new file mode 100644 index 0000000..0fbc5b7 --- /dev/null +++ b/src/controller/User.php @@ -0,0 +1,151 @@ +layTable(function () { + $this->title = '部门员工'; + $this->dept = StaffDept::tree(); + }, static function (QueryHelper $query) { + $query->equal('dept_id,status')->like('name'); + $query->with('dept')->append(['dept_name']); + }); + } + + /** + * 添加员工 + * @auth true + * @menu true + * @return void + */ + public function add() + { + StaffUser::mForm('form'); + } + + /** + * 编辑员工 + * @auth true + * @return void + */ + public function edit() + { + StaffUser::mForm('form'); + } + + protected function _form_filter(array &$data) + { + if ($this->request->isPost()) { + // 检查资料是否完整 + $this->_vali([ + 'name.require' => '用户名称不能为空!', + 'phone.require' => '手机号码不能为空!', + 'phone.mobile' => '手机号码格式错误!', + 'email.email' => '邮箱地址格式错误!', + 'dept_id.require' => '部门名称不能为空!', + 'authorize.require' => '未配置权限!' + ]); + if (!empty($data['password'])) { + if (strlen($data['password']) < 6) { + $this->error('密码长度不能少于6位!'); + }; + } + } else { + if (!empty($data['id'])) { + $user = SystemUser::mk()->find($data['id']); + $data['authorize'] = str2arr($user['authorize'] ?? '');; + } else { + $data['authorize'] = []; + } + $data['dept_id'] = $data['dept_id'] ?? ''; + $this->auths = SystemAuth::items(); + $this->depts = StaffDept::items(); + } + } + + protected function _form_result(bool $state, $data) + { + if ($state) { + $user = []; + // 检查账号是否重复 + $map = ['username' => $data['phone'], 'is_deleted' => 0]; + $systemUser = SystemUser::mk()->where($map)->findOrEmpty(); + if ($systemUser->isExists() && $systemUser->id != $data['id']) { + $this->error("账号已经存在,请使用其它账号!"); + } + $user['id'] = $data['id']; + $user['username'] = $data['phone']; + if (!empty($data['password'])) { + $user['password'] = md5($data['password']); + } + $user['nickname'] = $data['name']; + $user['contact_mail'] = $data['email']; + // 处理上传的权限格式 + $user['authorize'] = arr2str($data['authorize'] ?? []); + SystemUser::mk()->save($user); + } + } + + /** + * 启用禁用员工 + * @return void + */ + public function state() + { + StaffUser::mSave($this->_vali([ + 'status.in:0,1' => '状态值范围异常!', + 'status.require' => '状态值不能为空!', + ])); + } + + protected function _state_save_result(bool $state, $data) + { + if ($state) { + $systemUser = SystemUser::mk()->findOrEmpty($this->request->post('id')); + if ($systemUser->isExists()) { + $systemUser->status = $this->request->post('status'); + $systemUser->save(); + } + } + } + + /** + * 删除员工 + * @auth true + * @return void + */ + public function del() + { + StaffUser::mDelete(); + } + + protected function _del_delete_result(bool $state) + { + if ($state) { + $systemUser = SystemUser::mk()->findOrEmpty($this->request->post('id')); + if ($systemUser->isExists()) { + $systemUser->is_deleted = 1; + $systemUser->save(); + } + } + } +} \ No newline at end of file diff --git a/src/model/StaffDept.php b/src/model/StaffDept.php new file mode 100644 index 0000000..19c86ca --- /dev/null +++ b/src/model/StaffDept.php @@ -0,0 +1,77 @@ + 0])->field("id, name")->select()->unshift([ + 'id' => 0, + 'name' => '顶级部门', + ]); + } + + public function scopeDeleted(Query $query): void + { + $query->where(['is_deleted' => 1]); + } + + public function scopeNotDeleted(Query $query): void + { + $query->where(['is_deleted' => 0]); + } + + public static function items() + { + return self::mk()->where(['status' => 1])->select(); + } + + public function staffs(): HasMany + { + return $this->hasMany(StaffUser::class, 'dept_id', 'id')->where([ + 'status' => 1, 'is_deleted' => 0, + ]); + } + + public function headman(): HasOne + { + return $this->hasOne(StaffUser::class, 'id', 'headman_id')->where([ + 'status' => 1, 'is_deleted' => 0, + ]); + } + + public function children(): HasMany + { + return $this->hasMany(StaffDept::class, 'pid', 'id'); + } + + public function parent(): HasOne + { + return $this->hasOne(StaffDept::class, 'id', 'pid'); + } + + public static function tree() + { + return static::mk()->where(['is_deleted' => 0, 'pid' => 0])->with('children.children')->select(); + } + + public function getHeadmanNameAttr() + { + if (!$this->headman_id) { + return '无'; + } + return $this->headman ? $this->headman['name'] : '无'; + } +} \ No newline at end of file diff --git a/src/model/StaffUser.php b/src/model/StaffUser.php new file mode 100644 index 0000000..f340ac3 --- /dev/null +++ b/src/model/StaffUser.php @@ -0,0 +1,38 @@ +where('is_deleted', '=', 1); + } + + public function scopeNotDeleted(Query $query): void + { + $query->where('is_deleted', '=', 0); + } + + public function dept(): HasOne + { + return $this->hasOne(StaffDept::class, 'id', 'dept_id')->where([ + 'status' => 1, 'is_deleted' => 0, + ]); + } + + public function getDeptNameAttr($value, $data) + { + return $this->dept ? $this->dept['name'] : ''; + } +} \ No newline at end of file diff --git a/src/view/dept/form.html b/src/view/dept/form.html new file mode 100644 index 0000000..f1cfa63 --- /dev/null +++ b/src/view/dept/form.html @@ -0,0 +1,29 @@ +
\ No newline at end of file diff --git a/src/view/dept/headman.html b/src/view/dept/headman.html new file mode 100644 index 0000000..b1dd2c5 --- /dev/null +++ b/src/view/dept/headman.html @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/src/view/dept/index.html b/src/view/dept/index.html new file mode 100644 index 0000000..2adc397 --- /dev/null +++ b/src/view/dept/index.html @@ -0,0 +1,89 @@ +{extend name='table'} + +{block name="button"} + + + +{/block} + +{block name="content"} +