diff --git a/application/admin/controller/user/User.php b/application/admin/controller/user/User.php index 814ecd0..55f8a54 100644 --- a/application/admin/controller/user/User.php +++ b/application/admin/controller/user/User.php @@ -2,7 +2,13 @@ namespace app\admin\controller\user; +use app\admin\library\Auth; use app\common\controller\Backend; +use PhpOffice\PhpSpreadsheet\Cell\Coordinate; +use PhpOffice\PhpSpreadsheet\Reader\Csv; +use PhpOffice\PhpSpreadsheet\Reader\Xls; +use PhpOffice\PhpSpreadsheet\Reader\Xlsx; +use think\exception\PDOException; /** * 会员管理 @@ -26,6 +32,133 @@ class User extends Backend $this->model = model('User'); } + public function import() + { + $file = $this->request->request('file'); + if (!$file) { + $this->error(__('Parameter %s can not be empty', 'file')); + } + $filePath = ROOT_PATH . DS . 'public' . DS . $file; + if (!is_file($filePath)) { + $this->error(__('No results were found')); + } + //实例化reader + $ext = pathinfo($filePath, PATHINFO_EXTENSION); + if (!in_array($ext, ['csv', 'xls', 'xlsx'])) { + $this->error(__('Unknown data format')); + } + if ($ext === 'csv') { + $file = fopen($filePath, 'r'); + $filePath = tempnam(sys_get_temp_dir(), 'import_csv'); + $fp = fopen($filePath, "w"); + $n = 0; + while ($line = fgets($file)) { + $line = rtrim($line, "\n\r\0"); + $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']); + if ($encoding != 'utf-8') { + $line = mb_convert_encoding($line, 'utf-8', $encoding); + } + if ($n == 0 || preg_match('/^".*"$/', $line)) { + fwrite($fp, $line . "\n"); + } else { + fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n"); + } + $n++; + } + fclose($file) || fclose($fp); + + $reader = new Csv(); + } elseif ($ext === 'xls') { + $reader = new Xls(); + } else { + $reader = new Xlsx(); + } + + //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name + $fieldArr = [ 'nickname', + 'username', + 'password', + 'email',]; + + + //加载文件 + $insert = []; + try { + if (!$PHPExcel = $reader->load($filePath)) { + $this->error(__('Unknown data format')); + } + $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表 + $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号 + $allRow = $currentSheet->getHighestRow(); //取得一共有多少行 +// $maxColumnNumber = Coordinate::columnIndexFromString($allColumn); + $fields = [ + 'nickname', + 'username', + 'password', + 'email', + ]; + $salt = \fast\Random::alnum(); + for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) { + $values = []; + for ($currentColumn = 1; $currentColumn <= 4; $currentColumn++) { + $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue(); + if ($currentColumn==3){ + //修改的是密码 + $val= \app\common\library\Auth::instance()->getEncryptPassword($val, $salt); + } + $values[] = is_null($val) ? '' : $val; + } +// $row = []; + $temp = array_combine($fields, $values); +// foreach ($temp as $k => $v) { +// if (isset($fieldArr[$k]) && $k !== '') { +// $row[$fieldArr[$k]] = $v; +// } +// } +// print_r($temp); +// print_r($row); +// if ($row) { + $insert[] = $temp; +// } + } + } catch (Exception $exception) { + $this->error($exception->getMessage()); + } + if (!$insert) { + $this->error(__('No rows were updated')); + } + + try { + //是否包含admin_id字段 + $has_admin_id = false; + foreach ($fieldArr as $name => $key) { + if ($key == 'admin_id') { + $has_admin_id = true; + break; + } + } + if ($has_admin_id) { + $auth = Auth::instance(); + foreach ($insert as &$val) { + if (!isset($val['admin_id']) || empty($val['admin_id'])) { + $val['admin_id'] = $auth->isLogin() ? $auth->id : 0; + } + } + } + $this->model->saveAll($insert); + } catch (PDOException $exception) { + $msg = $exception->getMessage(); + if (preg_match("/.+Integrity constraint violation: 1062 Duplicate entry '(.+)' for key '(.+)'/is", $msg, $matches)) { + $msg = "导入失败,包含【{$matches[1]}】的记录已存在"; + }; + $this->error($msg); + } catch (Exception $e) { + $this->error($e->getMessage()); + } + + $this->success(); + } + /** * 查看 */ diff --git a/application/extra/upload.php b/application/extra/upload.php index 5bfa25d..2848944 100644 --- a/application/extra/upload.php +++ b/application/extra/upload.php @@ -21,7 +21,7 @@ return [ /** * 可上传的文件类型 */ - 'mimetype' => 'jpg,png,bmp,jpeg,gif,zip,rar,xls,xlsx', + 'mimetype' => 'jpg,png,bmp,jpeg,gif,zip,rar,xls,xlsx,csv', /** * 是否支持批量上传 */ diff --git a/public/assets/js/backend/user/user.js b/public/assets/js/backend/user/user.js index 6889f75..fae1c32 100644 --- a/public/assets/js/backend/user/user.js +++ b/public/assets/js/backend/user/user.js @@ -10,7 +10,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin edit_url: 'user/user/edit', del_url: 'user/user/del', multi_url: 'user/user/multi', - import_url: 'example/import', + import_url: 'user/user/import', table: 'user', } }); @@ -26,22 +26,22 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin [ {checkbox: true}, {field: 'id', title: __('Id'), sortable: true}, - {field: 'group.name', title: __('Group')}, + // {field: 'group.name', title: __('Group')}, {field: 'username', title: __('Username'), operate: 'LIKE'}, {field: 'nickname', title: __('Nickname'), operate: 'LIKE'}, {field: 'email', title: __('Email'), operate: 'LIKE'}, - {field: 'mobile', title: __('Mobile'), operate: 'LIKE'}, - {field: 'avatar', title: __('Avatar'), events: Table.api.events.image, formatter: Table.api.formatter.image, operate: false}, - {field: 'level', title: __('Level'), operate: 'BETWEEN', sortable: true}, - {field: 'gender', title: __('Gender'), visible: false, searchList: {1: __('Male'), 0: __('Female')}}, - {field: 'score', title: __('Score'), operate: 'BETWEEN', sortable: true}, - {field: 'successions', title: __('Successions'), visible: false, operate: 'BETWEEN', sortable: true}, - {field: 'maxsuccessions', title: __('Maxsuccessions'), visible: false, operate: 'BETWEEN', sortable: true}, - {field: 'logintime', title: __('Logintime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true}, - {field: 'loginip', title: __('Loginip'), formatter: Table.api.formatter.search}, - {field: 'jointime', title: __('Jointime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true}, - {field: 'joinip', title: __('Joinip'), formatter: Table.api.formatter.search}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status, searchList: {normal: __('Normal'), hidden: __('Hidden')}}, + // {field: 'mobile', title: __('Mobile'), operate: 'LIKE'}, + // {field: 'avatar', title: __('Avatar'), events: Table.api.events.image, formatter: Table.api.formatter.image, operate: false}, + // {field: 'level', title: __('Level'), operate: 'BETWEEN', sortable: true}, + // {field: 'gender', title: __('Gender'), visible: false, searchList: {1: __('Male'), 0: __('Female')}}, + // {field: 'score', title: __('Score'), operate: 'BETWEEN', sortable: true}, + // {field: 'successions', title: __('Successions'), visible: false, operate: 'BETWEEN', sortable: true}, + // {field: 'maxsuccessions', title: __('Maxsuccessions'), visible: false, operate: 'BETWEEN', sortable: true}, + // {field: 'logintime', title: __('Logintime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true}, + // {field: 'loginip', title: __('Loginip'), formatter: Table.api.formatter.search}, + // {field: 'jointime', title: __('Jointime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true}, + // {field: 'joinip', title: __('Joinip'), formatter: Table.api.formatter.search}, + // {field: 'status', title: __('Status'), formatter: Table.api.formatter.status, searchList: {normal: __('Normal'), hidden: __('Hidden')}}, {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} ] ]