新增员工批量导入功能,注意:升级该功能需要composer install新增phpoffice/phpspreadsheet依赖包,安装该依赖包需要服务器环境安装php扩展:fileinfo和zip
This commit is contained in:
parent
ccdd2d236b
commit
6387b28251
180
app/api/controller/Import.php
Normal file
180
app/api/controller/Import.php
Normal file
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
declare (strict_types = 1);
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\api\BaseController;
|
||||
use think\facade\Db;
|
||||
use app\user\model\Admin;
|
||||
use avatars\MDAvatars;
|
||||
use Overtrue\Pinyin\Pinyin;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date as Shared;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
|
||||
|
||||
class Import extends BaseController
|
||||
{
|
||||
//生成头像
|
||||
public function to_avatars($char)
|
||||
{
|
||||
$defaultData = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'S', 'Y', 'Z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖', '拾',
|
||||
'一', '二', '三', '四', '五', '六', '七', '八', '九', '十');
|
||||
if (isset($char)) {
|
||||
$Char = $char;
|
||||
} else {
|
||||
$Char = $defaultData[mt_rand(0, count($defaultData) - 1)];
|
||||
}
|
||||
$OutputSize = min(512, empty($_GET['size']) ? 36 : intval($_GET['size']));
|
||||
|
||||
$Avatar = new MDAvatars($Char, 256, 1);
|
||||
$avatar_name = '/avatars/avatar_256_' . set_salt(10) . time() . '.png';
|
||||
$path = get_config('filesystem.disks.public.url') . $avatar_name;
|
||||
$res = $Avatar->Save('.' . $path, 256);
|
||||
$Avatar->Free();
|
||||
return $path;
|
||||
}
|
||||
//导入员工
|
||||
public function import_admin(){
|
||||
// 获取表单上传文件
|
||||
$file[]= request()->file('file');
|
||||
if($this->uid>1){
|
||||
return to_assign(1,'该操作只能是超级管理员有权限操作');
|
||||
}
|
||||
try {
|
||||
// 验证文件大小,名称等是否正确
|
||||
validate(['file' => 'filesize:51200|fileExt:xls,xlsx'])->check($file);
|
||||
// 日期前綴
|
||||
$dataPath = date('Ym');
|
||||
$md5 = $file[0]->hash('md5');
|
||||
$savename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file[0], function () use ($md5) {
|
||||
return $md5;
|
||||
});
|
||||
$fileExtendName = substr(strrchr($savename, '.'), 1);
|
||||
// 有Xls和Xlsx格式两种
|
||||
if ($fileExtendName == 'xlsx') {
|
||||
$objReader = IOFactory::createReader('Xlsx');
|
||||
} else {
|
||||
$objReader = IOFactory::createReader('Xls');
|
||||
}
|
||||
$objReader->setReadDataOnly(TRUE);
|
||||
$path = get_config('filesystem.disks.public.url');
|
||||
// 读取文件,tp6默认上传的文件,在runtime的相应目录下,可根据实际情况自己更改
|
||||
$objPHPExcel = $objReader->load('.'.$path . '/' .$savename);
|
||||
//$objPHPExcel = $objReader->load('./storage/202209/d11544d20b3ca1c1a5f8ce799c3b2433.xlsx');
|
||||
$sheet = $objPHPExcel->getSheet(0); //excel中的第一张sheet
|
||||
$highestRow = $sheet->getHighestRow(); // 取得总行数
|
||||
$highestColumn = $sheet->getHighestColumn(); // 取得总列数
|
||||
Coordinate::columnIndexFromString($highestColumn);
|
||||
$lines = $highestRow - 1;
|
||||
if ($lines <= 0) {
|
||||
return to_assign(1, '数据不能为空');
|
||||
exit();
|
||||
}
|
||||
$sex_array=['未知','男','女'];
|
||||
$type_array=['未知','正式','试用','实习'];
|
||||
$mobile_array = Db::name('Admin')->where([['status','>=',0]])->column('mobile');
|
||||
$email_array = Db::name('Admin')->where([['status','>=',0]])->column('email');
|
||||
$department_array = Db::name('Department')->where(['status' => 1])->column('title', 'id');
|
||||
$position_array = Db::name('Position')->where(['status' => 1])->column('title', 'id');
|
||||
//循环读取excel表格,整合成数组。如果是不指定key的二维,就用$data[i][j]表示。
|
||||
$pinyin = new Pinyin();
|
||||
for ($j = 3; $j <= $highestRow; $j++) {
|
||||
$salt = set_salt(20);
|
||||
$reg_pwd = '123456';
|
||||
$name = $objPHPExcel->getActiveSheet()->getCell("A" . $j)->getValue();
|
||||
if(empty($name)){
|
||||
continue;
|
||||
}
|
||||
$char = mb_substr($name, 0, 1, 'utf-8');
|
||||
$sex = arraySearch($sex_array,$objPHPExcel->getActiveSheet()->getCell("D" . $j)->getValue());
|
||||
$department = arraySearch($department_array,$objPHPExcel->getActiveSheet()->getCell("E" . $j)->getValue());
|
||||
$position = arraySearch($position_array,$objPHPExcel->getActiveSheet()->getCell("f" . $j)->getValue());
|
||||
$type = arraySearch($type_array,$objPHPExcel->getActiveSheet()->getCell("G" . $j)->getValue());
|
||||
$username = $pinyin->name($name,PINYIN_UMLAUT_V);
|
||||
|
||||
$mobile = $objPHPExcel->getActiveSheet()->getCell("B" . $j)->getValue();
|
||||
$email = $objPHPExcel->getActiveSheet()->getCell("C" . $j)->getValue();
|
||||
$file_check['mobile'] = $mobile;
|
||||
$file_check['email'] = $email;
|
||||
$validate_mobile = \think\facade\Validate::rule([
|
||||
'mobile' => 'require|mobile',
|
||||
]);
|
||||
$validate_email = \think\facade\Validate::rule([
|
||||
'email' => 'email',
|
||||
]);
|
||||
if (!$validate_mobile->check($file_check)) {
|
||||
return to_assign(1, '第'.($j - 2).'行的手机号码'.$validate->getError());
|
||||
}
|
||||
else{
|
||||
if(in_array($mobile,$mobile_array)){
|
||||
return to_assign(1, '第'.($j - 2).'行的手机号码已存在或者重复');
|
||||
}
|
||||
else{
|
||||
array_push($mobile_array,$mobile);
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($email)){
|
||||
if (!$validate_email->check($file_check)) {
|
||||
return to_assign(1, '第'.($j - 2).'行的电子邮箱'.$validate->getError());
|
||||
}
|
||||
else{
|
||||
if(in_array($email,$email_array)){
|
||||
return to_assign(1, '第'.($j - 2).'行的电子邮箱已存在或者重复');
|
||||
}
|
||||
else{
|
||||
array_push($email_array,$email);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
$email='';
|
||||
}
|
||||
|
||||
if(empty($department)){
|
||||
return to_assign(1, '第'.($j - 2).'行的所在部门错误');
|
||||
}
|
||||
if(empty($department)){
|
||||
return to_assign(1, '第'.($j - 2).'行的所在部门错误');
|
||||
}
|
||||
if(empty($position)){
|
||||
return to_assign(1, '第'.($j - 2).'行的所属职位错误');
|
||||
}
|
||||
$data[$j - 3] = [
|
||||
'name' => $name,
|
||||
'nickname' => $name,
|
||||
'mobile' => $mobile,
|
||||
'email' => $email,
|
||||
'sex' => $sex,
|
||||
'did' => $department,
|
||||
'position_id' => $position,
|
||||
'type' => $type,
|
||||
'entry_time' => Shared::excelToTimestamp($objPHPExcel->getActiveSheet()->getCell("H" . $j)->getValue(),'Asia/Shanghai'),
|
||||
'username' => implode('', $username),
|
||||
'salt' => $salt,
|
||||
'pwd' => set_password($reg_pwd, $salt),
|
||||
'reg_pwd' => $reg_pwd,
|
||||
'thumb' => $this->to_avatars($char)
|
||||
];
|
||||
}
|
||||
//dd($data);exit;
|
||||
// 批量添加数据
|
||||
if ((new Admin())->saveAll($data)) {
|
||||
return to_assign(0, '导入成功');
|
||||
}
|
||||
else{
|
||||
return to_assign(1, '导入失败,请检查excel文件再试');
|
||||
}
|
||||
} catch (\think\exception\ValidateException $e) {
|
||||
return to_assign(1, $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -661,6 +661,25 @@ function get_desc_content($content, $count)
|
||||
return $res;
|
||||
}
|
||||
|
||||
//查找数组索引
|
||||
function arraySearch($array, $searchFor) {
|
||||
foreach($array as $key => $value) {
|
||||
if(is_array($value)){
|
||||
foreach($value as $key1 => $value1) {
|
||||
if($value1 == $searchFor) {
|
||||
return array("index" => $key, "key" => $key1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if($value == $searchFor) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP去除空格
|
||||
* @param string $str 字符串
|
||||
|
@ -9,6 +9,11 @@
|
||||
.layui-tree-line .layui-tree-set .layui-tree-set:after{top:18px;}
|
||||
.tree-left{width:200px; float:left; height:calc(100% - 30px); overflow: scroll; border:1px solid #eeeeee; background-color:#FAFAFA; padding:12px 12px 12px 5px;}
|
||||
.tree-left h3{font-size:16px; height:30px; padding-left:10px; font-weight:800}
|
||||
|
||||
.gougu-upload-files{background-color: #ffffff; border:1px solid #e4e7ed;color: #c0c4cc;cursor: not-allowed; padding:0 12px; width:180px; box-sizing: border-box; display: inline-block; font-size: inherit; height: 38px; line-height: 35px; margin-right:8px; border-radius:2px;}
|
||||
.gougu-upload-tips{color:#969696}
|
||||
.layui-form-item{margin-bottom:8px;}
|
||||
.layui-input-block{min-height:24px;}
|
||||
</style>
|
||||
{/block}
|
||||
<!-- 主体 -->
|
||||
@ -52,6 +57,7 @@
|
||||
<button class="layui-btn layui-btn-normal layui-btn-sm" lay-event="add"><i class="layui-icon"></i>添加员工</button>
|
||||
<button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="disable"><i class="layui-icon">ဆ</i>禁止登录</button>
|
||||
<button class="layui-btn layui-btn-sm" lay-event="recovery"><i class="layui-icon"></i>恢复正常</button>
|
||||
<button class="layui-btn layui-btn-normal layui-btn-sm" lay-event="import"><i class="layui-icon"></i>批量导入</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@ -63,30 +69,117 @@
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var table = layui.table, tool = layui.tool,tree = layui.tree,form = layui.form;
|
||||
$.ajax({
|
||||
url: "/api/index/get_department_tree",
|
||||
type:'get',
|
||||
success:function(res){
|
||||
//仅节点左侧图标控制收缩
|
||||
tree.render({
|
||||
elem: '#depament',
|
||||
data: res.trees,
|
||||
onlyIconControl: true, //是否仅允许节点左侧图标控制展开收缩
|
||||
click: function(obj){
|
||||
//layer.msg(JSON.stringify(obj.data));
|
||||
layui.pageTable.reload({
|
||||
where: {did: obj.data.id}
|
||||
,page:{curr:1}
|
||||
var table = layui.table, tool = layui.tool,tree = layui.tree,form = layui.form,upload = layui.upload;
|
||||
$.ajax({
|
||||
url: "/api/index/get_department_tree",
|
||||
type:'get',
|
||||
success:function(res){
|
||||
//仅节点左侧图标控制收缩
|
||||
tree.render({
|
||||
elem: '#depament',
|
||||
data: res.trees,
|
||||
onlyIconControl: true, //是否仅允许节点左侧图标控制展开收缩
|
||||
click: function(obj){
|
||||
//layer.msg(JSON.stringify(obj.data));
|
||||
layui.pageTable.reload({
|
||||
where: {did: obj.data.id}
|
||||
,page:{curr:1}
|
||||
});
|
||||
$('[name="keywords"]').val('');
|
||||
$('[name="status"]').val('');
|
||||
$('[name="type"]').val('');
|
||||
layui.form.render('select');
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
let uploadFiles;
|
||||
function clearFile() {
|
||||
for (let x in uploadFiles) {
|
||||
delete uploadFiles[x];
|
||||
}
|
||||
$('#gougu-upload-choosed').html('');
|
||||
}
|
||||
function uploadImport(){
|
||||
layer.open({
|
||||
'title':'批量导入员工',
|
||||
'type':1,
|
||||
'area': ['640px', '320px'],
|
||||
'content':'<div class="layui-form p-3">\
|
||||
<div id="uploadType1">\
|
||||
<div class="layui-form-item">\
|
||||
<label class="layui-form-label">文件:</label>\
|
||||
<div class="layui-input-block">\
|
||||
<span class="gougu-upload-files">.xls,.xlsx</span><button type="button" class="layui-btn layui-btn-normal" id="uploadSelect">选择文件</button><a href="/static/home/file/勾股OA员工导入模板.xlsx" class="layui-btn ml-4">Execl表格模板下载</a>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="layui-form-item">\
|
||||
<label class="layui-form-label"></label>\
|
||||
<div class="layui-input-block">\
|
||||
<span class="gougu-upload-tips">1、只有超级管理员才能进行批量导入操作;<br>2、只能上传 .xls、.xlsx文件;<br>3、数据请勿放在合并的单元格中;<br>4、文件大小请勿超过2MB,导入数据不能超过3000条</span>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="layui-form-item">\
|
||||
<label class="layui-form-label"></label>\
|
||||
<div class="layui-input-block green" id="gougu-upload-choosed"></div>\
|
||||
</div>\
|
||||
<div class="layui-form-item">\
|
||||
<label class="layui-form-label"></label>\
|
||||
<div class="layui-input-block red" id="gougu-upload-note"></div>\
|
||||
</div>\
|
||||
<div class="layui-form-item layui-form-item-sm">\
|
||||
<label class="layui-form-label"></label>\
|
||||
<div class="layui-input-block">\
|
||||
<button type="button" class="layui-btn" id="uploadAjax">上传并导入</button>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div> \
|
||||
</div>',
|
||||
success: function(layero, idx){
|
||||
form.render();
|
||||
//选文件
|
||||
let uploadImport = upload.render({
|
||||
elem: '#uploadSelect'
|
||||
,url: '/api/import/import_admin'
|
||||
,auto: false
|
||||
,accept: 'file' //普通文件
|
||||
,exts: 'xls|xlsx' //只允许上传文件格式
|
||||
,bindAction: '#uploadAjax'
|
||||
,choose: function(obj){
|
||||
uploadFiles = obj.pushFile();
|
||||
// 清空,防止多次上传
|
||||
clearFile();
|
||||
obj.preview(function(index, file, result){
|
||||
obj.pushFile();// 再添加
|
||||
$('#gougu-upload-choosed').html('已选择:'+file.name);
|
||||
});
|
||||
$('[name="keywords"]').val('');
|
||||
$('[name="status"]').val('');
|
||||
$('[name="type"]').val('');
|
||||
layui.form.render('select');
|
||||
}
|
||||
});
|
||||
,before: function(obj){
|
||||
}
|
||||
,progress: function(n, elem, e){
|
||||
$('#gougu-upload-note').html('文件上转中...');
|
||||
if(n==100){
|
||||
$('#gougu-upload-note').html('数据导入中...');
|
||||
}
|
||||
}
|
||||
,error: function(index, upload){
|
||||
clearFile();
|
||||
$('#gougu-upload-note').html('数据导入失败,请关闭重试');
|
||||
}
|
||||
,done: function(res, index, upload){
|
||||
clearFile();
|
||||
layer.msg(res.msg);
|
||||
$('#gougu-upload-note').html(res.msg);
|
||||
if(res.code==0){
|
||||
layer.close(idx);
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test',
|
||||
@ -230,6 +323,10 @@
|
||||
tool.side("/user/user/add");
|
||||
return;
|
||||
}
|
||||
if (obj.event === 'import') {
|
||||
uploadImport();
|
||||
return;
|
||||
}
|
||||
if(data.length==0){
|
||||
layer.msg('请选择要操作的员工');
|
||||
return false;
|
||||
|
@ -28,6 +28,7 @@
|
||||
"topthink/think-captcha": "^3.0",
|
||||
"phpmailer/phpmailer": "^6.6",
|
||||
"firebase/php-jwt": "6.1.2",
|
||||
"phpoffice/phpspreadsheet": "1.19",
|
||||
"overtrue/pinyin": "^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -15,7 +15,7 @@ if (empty(file_exists(__DIR__ . '/../vendor/autoload.php'))) {
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
// 定义当前版本号
|
||||
define('CMS_VERSION','4.0.83');
|
||||
define('CMS_VERSION','4.9.22');
|
||||
|
||||
// 定义Layui版本号
|
||||
define('LAYUI_VERSION','2.7.6');
|
||||
|
BIN
public/static/home/file/勾股OA员工导入模板.xlsx
Normal file
BIN
public/static/home/file/勾股OA员工导入模板.xlsx
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user