DolphinPHP实战,开发一个简单的员工管理系统.
主要有emp_employee员工表,emp_status_info员工状态表,emp_dept员工部门表,emp_position员工职位表,员工地址表:
create table emp_employee(
id int(10) primary key auto_increment,
name varchar(10) comment '姓名',
age int(2) comment '年龄',
phone varchar(30) not null comment '电话',
salary decimal not null comment '工资',
p_id int(10) not null comment '领导id',
position_id int(10) not null comment '职位id',
addr_id int(10) not null comment '地址id',
status_id int(10) not null comment '员工当前状态id',
join_in_time datetime not null comment '入职时间',
leave_out_time datetime comment '离职时间',
create_time datetime,
update_time datetime
);
create table emp_status_info(
id int(10) primary key auto_increment,
status int(1) not null comment '员工当前状态 -1离职 0正常 1请假 2调休',
reason text comment '事由',
begin_time datetime comment '开始时间',
end_time datetime comment '结束时间',
create_time datetime,
update_time datetime
);
create table emp_dept (
id int(10) primary key auto_increment,
name varchar(30) not null comment '部门名称',
manger_id int(10) comment '部门主管id',
create_time datetime,
update_time datetime
);
create table emp_position(
id int(10) primary key auto_increment,
name varchar(30) not null comment '职位名称',
dept_id int(10) not null comment '所属部门',
create_time datetime,
update_time datetime
);
create table emp_addr(
id int(10) primary key auto_increment,
street varchar(50) comment '街道',
number int(6) comment '门牌编号',
province varchar(50) comment '省',
city varchar(50) comment '市',
create_time datetime,
update_time datetime
);
向数据库中插入数据:
-- emp_employee
INSERT INTO dolphin.emp_employee (id, name, age, phone, salary, p_id, position_id, addr_id, status_id, join_in_time, leave_out_time, create_time, update_time) VALUES (1, '张三', 18, '13232323232', 8000, 0, 1, 1, 0, '2019-07-18 06:39:28', null, '2019-07-18 06:39:40', '2019-07-18 06:39:45');
INSERT INTO dolphin.emp_employee (id, name, age, phone, salary, p_id, position_id, addr_id, status_id, join_in_time, leave_out_time, create_time, update_time) VALUES (2, '李四', 20, '13443433333', 9000, 0, 2, 2, 0, '2019-07-18 06:41:22', null, '2019-07-18 06:41:25', '2019-07-18 06:41:26');
INSERT INTO dolphin.emp_employee (id, name, age, phone, salary, p_id, position_id, addr_id, status_id, join_in_time, leave_out_time, create_time, update_time) VALUES (3, '王五', 18, '13232323232', 8000, 0, 3, 3, 0, '2019-07-18 06:39:28', null, '2019-07-18 06:39:40', '2019-07-18 06:39:45');
-- emp_dept
INSERT INTO dolphin.emp_dept (id, name, manger_id, create_time, update_time) VALUES (1, '技术部', 0, '2019-07-18 06:50:13', '2019-07-18 06:50:16');
INSERT INTO dolphin.emp_dept (id, name, manger_id, create_time, update_time) VALUES (2, '财物部', 0, '2019-07-18 06:50:41', '2019-07-18 06:50:43');
INSERT INTO dolphin.emp_dept (id, name, manger_id, create_time, update_time) VALUES (3, '市场部', 0, '2019-07-18 06:51:09', '2019-07-18 06:51:15');
INSERT INTO dolphin.emp_dept (id, name, manger_id, create_time, update_time) VALUES (4, '运营部', 0, '2019-07-18 06:51:28', '2019-07-18 06:51:30');
-- emp_position
INSERT INTO dolphin.emp_position (id, name, dept_id, create_time, update_time) VALUES (1, 'Java开发工程师', 1, '2019-07-18 06:53:16', '2019-07-18 06:53:17');
INSERT INTO dolphin.emp_position (id, name, dept_id, create_time, update_time) VALUES (2, '前端开发工程师', 1, '2019-07-18 06:53:47', '2019-07-18 06:53:50');
INSERT INTO dolphin.emp_position (id, name, dept_id, create_time, update_time) VALUES (3, 'PHP开发工程师', 1, '2019-07-18 06:54:18', '2019-07-18 06:54:20');
INSERT INTO dolphin.emp_position (id, name, dept_id, create_time, update_time) VALUES (4, 'Golang开发工程师', 1, '2019-07-18 06:54:55', '2019-07-18 06:54:56');
-- emp_addr
INSERT INTO dolphin.emp_addr (id, street, number, province, city, create_time, update_time) VALUES (1, '西乡街道', 1002, '广东', '深圳', '2019-07-18 06:56:47', '2019-07-18 06:56:49');
INSERT INTO dolphin.emp_addr (id, street, number, province, city, create_time, update_time) VALUES (2, '宝安大道', 2004, '广东', '深圳', '2019-07-18 06:57:36', '2019-07-18 06:57:37');
INSERT INTO dolphin.emp_addr (id, street, number, province, city, create_time, update_time) VALUES (3, '南山大道', 2012, '广东', '深圳', '2019-07-18 06:59:38', '2019-07-18 06:59:40');
在application
目录下新建一个employee
目录,并在employee
目录下新建一个info.php
文件:
/**
* 员工表模块信息
*/
return [
// 模块名[必填]
'name' => 'employee',
// 模块标题[必填]
'title' => '员工',
// 模块唯一标识[必填],格式:模块名.开发者标识.module
'identifier' => 'emp.xx.module',
// 开发者[必填]
'author' => 'xxx',
// 版本[必填],格式采用三段式:主版本号.次版本号.修订版本号
'version' => '1.0.0',
// 模块描述[必填]
'description' => '员工模块',
];
我们进入系统
->扩展中心
->模块管理
中可以查看到当前的模块信息:
我样可以通过点击安装来安装当前模块.
安装完模块后,我们要让模块展示出来,类似其他模块一样:
我们要通过系统
->系统功能
->节点管理
->新增
来添加节点:
然后在新增界面添加如下信息,并提交:
待页面刷新后我们就可以看到刚才添加的节点信息了:
如果此时点击它会提示无任何节权限.
接下来我们要做的就是为当前节点添加子节点,以同样的方式来到新增节点的页面,并填写这样如下的节点信息,并提交:
添加完成后我们再点击员工
,会看到如下信息:
员工
添加控制器在employee
目录下新建一个admin
目录,并在admin
目录下新建一个Index.php
,注意这里I是大写的.并在Index.php
下面输入以下内容:
namespace app\employee\admin;
use app\admin\controller\Admin;
class Index extends Admin {
public function index() {
dump('员工列表');
}
}
我们根据需要,修改员工界面的展示信息,首先我们要知道框架用的是use app\common\builder\ZBuilder;
来构建页面信息的.所以我们在构建页面的时候要使用它.
namespace app\employee\admin;
use app\admin\controller\Admin;
use app\common\builder\ZBuilder; // 引入ZBuilder
class Index extends Admin {
public function index() {
dump('员工列表');
}
}
由于当前页面要展示员工信息,所示我们要构建一个表格:
namespace app\employee\admin;
use app\admin\controller\Admin;
use app\common\builder\ZBuilder; // 引入ZBuilder
class Index extends Admin {
public function index() {
// 构建表格展示
return ZBuilder::make('table')->fetch();
}
}
我们再次访问可以看到当前页面类似如下(由于没有配置表格信息,所以没有展示出表格来):
现在为我们的表格添加表头,我们要展示内容有"数字编号/员工名字/年龄/电话/职位/工资/状态",由于这里只是修改index()
方法中的内容,这里只展示index()
中的代码:
public function index() {
return ZBuilder::make('table')
->addColumns([
['__INDEX__', '#'],
['name', '姓名'],
['age', '年龄'],
['phone', '电话'],
['position', '职位'],
['salary', '工资'],
['status', '状态']
])
->fetch();
}
['name', '姓名'],
其中name
就是要传入数据(数组)的key
,我们看一下现在的页面:
查询数据并展示到表格中,注意这里引用了use think\Db
命名空间用于查询数据:
public function index() {
$join = [
[['emp_position' => 'p'],'e.position_id = p.id', 'LEFT'],
[['emp_status_info' => 's'], 's.id = e.status_id', 'LEFT'],
];
$dataList = Db::field('e.name, e.age, e.phone, p.name position, e.salary, s.status status')
-> table('emp_employee')->alias('e')
-> join($join)
->select();
for ($i = 0 ; $i < count($dataList); $i++) {
foreach($dataList[$i] as $k => $v) {
if ($k == 'status' && $v== NULL) {
$dataList[$i][$k] = '在职';
}
}
}
return ZBuilder::make('table')
->addColumns([
['__INDEX__', '#'],
['name', '姓名'],
['age', '年龄'],
['phone', '电话'],
['position', '职位'],
['salary', '工资'],
['status', '状态']
])
-> setRowList($dataList)
->fetch();
}
修改后的效果:
我们看到每一列前都有一个多选框,现在我们将它隐藏:
public function index() {
$join = [
[['emp_position' => 'p'],'e.position_id = p.id', 'LEFT'],
[['emp_status_info' => 's'], 's.id = e.status_id', 'LEFT'],
];
$dataList = Db::field('e.name, e.age, e.phone, p.name position, e.salary, s.status status')
-> table('emp_employee')->alias('e')
-> join($join)
->select();
for ($i = 0 ; $i < count($dataList); $i++) {
foreach($dataList[$i] as $k => $v) {
if ($k == 'status' && $v== NULL) {
$dataList[$i][$k] = '在职';
}
}
}
return ZBuilder::make('table')
->addColumns([
['__INDEX__', '#'],
['name', '姓名'],
['age', '年龄'],
['phone', '电话'],
['position', '职位'],
['salary', '工资'],
['status', '状态']
])
-> setRowList($dataList)
// 隐藏多选框
->hideCheckbox()
->fetch();
}
为表头添加排序:
public function index() {
// 获取排序方式
$order = $this->getOrder();
$join = [
[['emp_position' => 'p'],'e.position_id = p.id', 'LEFT'],
[['emp_status_info' => 's'], 's.id = e.status_id', 'LEFT'],
];
$dataList = Db::field('e.name, e.age, e.phone, p.name position, e.salary, s.status status')
-> table('emp_employee')->alias('e')
-> join($join)
// 查询时,设置排序方式
->order($order)
->select();
for ($i = 0 ; $i < count($dataList); $i++) {
foreach($dataList[$i] as $k => $v) {
if ($k == 'status' && $v== NULL) {
$dataList[$i][$k] = '在职';
}
}
}
return ZBuilder::make('table')
->addColumns([
['__INDEX__', '#'],
['name', '姓名'],
['age', '年龄'],
['phone', '电话'],
['position', '职位'],
['salary', '工资'],
['status', '状态']
])
// 设置要排序的字段
->addOrder('name,salary')
-> setRowList($dataList)
// 隐藏多选框
->hideCheckbox()
->fetch();
}
记录:关于添加筛选,表名始终会被加上前缀,未解决!
public function index() {
$order = $this->getOrder();
$join = [
[['emp_position' => 'p'],'e.position_id = p.id', 'LEFT'],
[['emp_status_info' => 's'], 's.id = e.status_id', 'LEFT'],
];
$dataList = Db::field('e.name, e.age, e.phone, p.name position, e.salary, s.status status')
-> table('emp_employee')->alias('e')
-> join($join)
->order($order)
->select();
for ($i = 0 ; $i < count($dataList); $i++) {
foreach($dataList[$i] as $k => $v) {
if ($k == 'status' && $v== NULL) {
$dataList[$i][$k] = '在职';
}
}
}
return ZBuilder::make('table')
->addColumns([
['__INDEX__', '#'],
['name', '姓名'],
['age', '年龄'],
['phone', '电话'],
['position', '职位'],
['salary', '工资'],
['status', '状态']
])
->addOrder('name,salary')
-> setRowList($dataList)
// 隐藏多选框
->hideCheckbox()
// 添加新增按钮,并以弹窗形式打开(第三个参数存在),且设定title
->addTopButton('add', [],['title'=>'添加员工'])
->fetch();
}
public function add() {
return ZBuilder::make('form')
->fetch();
}
public function add() {
$dept = Db::table('emp_dept')->field('id,name')->select();
$list = [];
for ($i = 0; $i < count($dept); $i++) {
$list[$dept[$i]['id']] = $dept[$i]['name'];
}
return ZBuilder::make('form')
// 添加单行文本框,输入姓名,并设置 placeHolder 请输入员工的姓名
->addText('name', '姓名[:请输入员工的姓名]', '', '', [''])
->addText('age', '年龄[:请输入员工的年龄]', '', '', [''])
->addText('phone', '电话[:请输入员工的电话]', '', '', [''])
->addLinkage('dept ', '选择部门', '请选择部门', $list, '', url('getPosition'), 'position', 'dept')
->addSelect('position', '选择职位')
->addText('salary', '工资[:请输入员工的工资]', '', '', [''])
->addDatetime('join_in_time', '入职时间','', '', 'YYYY-MM-DD')
->fetch();
}
public function getPosition($dept = '') {
$res = Db::query('select p.id, p.name from emp_position p left join emp_dept d on p.dept_id = d.id where d.name = ? ', [$dept]);
$list = [];
for ($i = 0; $i < count($res); $i++) {
array_push($list, ['key' => $res[$i]['id'], 'value' => $res[$i]['name']]);
}
$arr['code'] = '1'; //判断状态
$arr['msg'] = '请求成功'; //回传信息
$arr['list'] = $list;
return json($arr);
}
页面效果:
为新增员工添加url请求链接,并创建save
方法:
public function add() {
$dept = Db::table('emp_dept')->field('id,name')->select();
$list = [];
for ($i = 0; $i < count($dept); $i++) {
$list[$dept[$i]['id']] = $dept[$i]['name'];
}
return ZBuilder::make('form')
// 添加单行文本框,输入姓名,并设置 placeHolder 请输入员工的姓名
->addText('name', '姓名[:请输入员工的姓名]', '', '', [''])
->addText('age', '年龄[:请输入员工的年龄]', '', '', [''])
->addText('phone', '电话[:请输入员工的电话]', '', '', [''])
->addLinkage('dept ', '选择部门', '请选择部门', $list, '', url('getPosition'), 'position', 'dept')
->addSelect('position', '选择职位')
->addText('salary', '工资[:请输入员工的工资]', '', '', [''])
->addDatetime('join_in_time', '入职时间','', '', 'YYYY-MM-DD')
// 设置提交地址
->setUrl(url('save'))
->submitConfirm()
->fetch();
}
public function save() {
// 获取请求参数
$arr['code'] = '1'; //判断状态
$arr['msg'] = '添加成功'; //回传信息
$arr['list'] = [];
return json($arr);
}
在save()
方法中获取请求数据并入库:
public function save() {
$post = request()->post();
$data = [
'name' => $post['name'],
'age' => $post['age'],
'phone' => $post['phone'],
'position_id' => $post['position'],
'salary' => $post['salary'],
'join_in_time' => $post['join_in_time'],
// 为not null字段添加默认值
'status_id' => 0,
'addr_id' => 0,
'p_id' => 0
];
$id = Db::table('emp_employee')->insert($data);
$id = Db::table('emp_employee')->getLastInsID();
// 获取请求参数
$arr['code'] = '1'; //判断状态
$arr['msg'] = '添加成功'; //回传信息
$arr['data'] = $id;
return json($arr);
}
现在我们要为员工数据每一栏添加操作按钮,先看看没添加时的样子:
添加操作代码(由于代码较长,只在新加代码处加了注释),请注意注释处代码:
public function index() {
$order = $this->getOrder();
$join = [
[['emp_position' => 'p'],'e.position_id = p.id', 'LEFT'],
[['emp_status_info' => 's'], 's.id = e.status_id', 'LEFT'],
];
// 添加 e.id 为数据指定id,否则报错
$dataList = Db::field('e.id, e.name, e.age, e.phone, p.name position, e.salary, s.status status')
-> table('emp_employee')->alias('e')
-> join($join)
->order($order)
->select();
for ($i = 0 ; $i < count($dataList); $i++) {
foreach($dataList[$i] as $k => $v) {
if ($k == 'status' && $v== NULL) {
$dataList[$i][$k] = '在职';
}
}
}
return ZBuilder::make('table')
->addColumns([
['__INDEX__', '#'],
['name', '姓名'],
['age', '年龄'],
['phone', '电话'],
['position', '职位'],
['salary', '工资'],
['status', '状态']
])
->addOrder('name,salary')
-> setRowList($dataList)
// 添加操作 表头
->addColumn('right_button', '操作', 'btn')
// 添加edit操作按钮
->addRightButton('edit', ['href' => url('edit', ['id' => '__id__', 'group' => 'normal'])])
// 隐藏多选框
->hideCheckbox()
->addTopButton('add', [],['title'=>'添加员工'])
->fetch();
}
添加操作按钮后,我们的页面长这样子:
注意->addRightButton('edit', ['href' => url('edit', ['id' => '__id__', 'group' => 'normal'])])
我们在指定编辑按钮时已经设置了跳转的url:**/模块名/edit/id/1/group/normal.html.所以,我们应该添加一个edit方法和配置一个修改员工的节点!
配置节点:
添加edit方法:
public function edit($id = '') {
dump('edit');
}
上诉操作完成后,点击编辑按钮就可以跳到如下页面:
此时,我们应该为编辑页面创建布局,编辑页面主要是用来更改员工状态的,比如请假/调休/高职等操作,所以我们在edit中添加如下代码:
public function edit($id = '', $group = 'normal') {
// tab 信息
$tabInfo = [
// edit 表示页面跳转的方法, group 是参数 normal是参数值 ,也就是每次点击都会跳到edit方法,并且传递group参数
'normal' => ['title' => '正常工作', 'url' => url('edit', ['group' => 'normal'])],
'qj' => ['title' => '请假', 'url' => url('edit', ['group' => 'qj'])],
'tx' => ['title' => '调休', 'url' => url('edit', ['group' => 'tx'])],
'lz' => ['title' => '离职', 'url' => url('edit', ['group' => 'lz'])],
];
// 状态单选按钮信息
$radioInfo = [
0 => '事假',
1 => '病假',
2 => '其它'
];
// 是否开启开关
$isOpen = 1;
$canOpt = '';
// 如果
if ($isOpen == 1) {
$canOpt = 'disabled';
}
// 根据不同的group参数 构建不同的form表单
switch ($group) {
case 'normal' :
return ZBuilder::make('form')
// 构建tab
->setTabNav($tabInfo, $group)
// 添加单选按钮, 最后一个参数是默认选中值
->addSwitch('status', '修改员工状态为正常', '', $isOpen, '', $canOpt)
->fetch();
// 请假表单样式
case 'qj' :
return ZBuilder::make('form')
->setTabNav($tabInfo, $group)
->addRadio('type', '请假类型', '', $radioInfo, '0')
->addDaterange('begin,end', '请假时间', '', date("Y-m-d",time()))
->fetch();
// 调休表单样式
case 'tx' :
return ZBuilder::make('form')
->setTabNav($tabInfo, $group)
->addDaterange('begin,end', '调休时间', '', date("Y-m-d",time()))
->fetch();
// 离职表单样式
case 'lz' :
return ZBuilder::make('form')
->setTabNav($tabInfo, $group)
->addDatetime('leave_time', '离职时间', '', date("Y-m-d H:i",time()))
->addTextarea('reason', '离职原因')
->fetch();
}
}