123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- <?php
- // +----------------------------------------------------------------------
- // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- // +----------------------------------------------------------------------
- // | Author: CRMEB Team <admin@crmeb.com>
- // +----------------------------------------------------------------------
- namespace qiniu\basic;
- //use crmeb\utils\JwtAuth;
- use app\jobs\system\ExportExcelJob;
- use qiniu\exceptions\AdminException;
- use qiniu\services\SpreadsheetExcelService;
- use qiniu\utils\JwtAuth;
- use think\facade\Db;
- use think\facade\Config;
- use think\facade\Route as Url;
- use think\Model;
- /**
- * Class BaseServices
- * @package app\services
- */
- abstract class BaseServices
- {
- /**
- * 模型注入
- * @var object
- */
- protected $model;
- protected $exportHeader = [];
- public function getHeader()
- {
- return $this->exportHeader;
- }
- /**
- * 获取分页配置
- * @param bool $isPage
- * @param bool $isRelieve
- * @return int[]
- */
- public function getPageValue(bool $isPage = true, bool $isRelieve = true)
- {
- $page = $limit = 0;
- if ($isPage) {
- $page = app()->request->param(Config::get('database.page.pageKey', 'page') . '/d', 0);
- $limit = app()->request->param(Config::get('database.page.limitKey', 'limit') . '/d', 0);
- }
- $limitMax = Config::get('database.page.limitMax', 100);
- $defaultLimit = Config::get('database.page.defaultLimit', 10);
- if ($limit > $limitMax && $isRelieve) {
- $limit = $limitMax;
- }
- return [(int)$page, (int)$limit, (int)$defaultLimit];
- }
- /**
- * 数据库事务操作
- * @param callable $closure
- * @return mixed
- */
- public function transaction(callable $closure, bool $isTran = true)
- {
- return $isTran ? Db::transaction($closure) : $closure();
- }
- // /**
- // * 创建token
- // * @param int $id
- // * @param $type
- // * @return array
- // */
- // public function createToken(int $id, $type, string $pwd = '')
- // {
- // /** @var JwtAuth $jwtAuth */
- // $jwtAuth = app()->make(JwtAuth::class);
- // return $jwtAuth->createToken($id, $type, ['auth' => md5($pwd)]);
- // }
- /**
- * 获取路由地址
- * @param string $path
- * @param array $params
- * @param bool $suffix
- * @param bool $isDomain
- * @return string
- */
- public function url(string $path, array $params = [], bool $suffix = false, bool $isDomain = false)
- {
- return Url::buildUrl($path, $params)->suffix($suffix)->domain($isDomain)->build();
- }
- /**
- * 密码hash加密
- * @param string $password
- * @return false|string|null
- */
- public function passwordHash(string $password)
- {
- return password_hash($password, PASSWORD_BCRYPT);
- }
- /**
- * 创建token
- * @param int $id
- * @param $type
- * @param string $pwd
- * @return array
- */
- public function createToken(int $id, $type, string $pwd = '')
- {
- /** @var JwtAuth $jwtAuth */
- $jwtAuth = app()->make(JwtAuth::class);
- return $jwtAuth->createToken($id, $type, ['auth' => md5($pwd)]);
- }
- /**
- * 格式化时间
- * @param $time
- * @param bool $is_time_key
- * @return array
- */
- public function timeHandle($time, bool $is_time_key = false)
- {
- switch ($time) {
- case 'today':
- $start = date('Y-m-d 00:00:00');
- $end = date('Y-m-d 23:59:59');
- break;
- case 'yesterday':
- $start = date('Y-m-d 00:00:00', strtotime("-1 day"));
- $end = date('Y-m-d 23:59:59', strtotime("-1 day"));
- break;
- case 'sevenday':
- $start = date('Y-m-d 00:00:00', strtotime('-6 day'));
- $end = date('Y-m-d 23:59:59');
- break;
- case 'thirtyday':
- $start = date('Y-m-d 00:00:00', strtotime('-29 day'));
- $end = date('Y-m-d 23:59:59');
- break;
- case 'last month':
- $start = date('Y-m-01 00:00:00', strtotime('first Day of last month 00:00:00'));
- $end = date("Y-m-d 23:59:59", strtotime('first Day of this month 00:00:00 -1second'));
- break;
- case 'month':
- $start = date('Y-m-01 00:00:00');
- $end = date('Y-m-d 23:59:59', mktime(23, 59, 59, date('m'), date('t'), date('Y')));
- break;
- case 'year':
- $start = date('Y-01-01 00:00:00');
- $end = date('Y-12-31 23:59:59');
- break;
- default:
- $start = date("Y/m/d", strtotime("-30 days", time()));
- $end = date("Y/m/d", time());
- if (strstr($time, '-') !== false) {
- [$start_r, $end_r] = explode('-', $time);
- if ($start_r || $end_r) {
- $start = $start_r;
- $end = $end_r;
- $end_time = strtotime($end_r);
- //没选具体时分秒 加上86400
- if ($end_time == strtotime(date('Y/m/d', $end_time))) {
- $end = date('Y/m/d H:i:s', $end_time + 86399);
- }
- }
- }
- break;
- }
- $start = $start ? strtotime($start) : 0;
- $end = $end ? strtotime($end) : 0;
- if ($is_time_key) {
- $dayCount = ceil(($end - $start) / 86400);
- $s_start = $start;
- $timeKey = [];
- if ($dayCount == 1) {
- $timeType = 'hour';
- $timeKey = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
- } elseif ($dayCount <= 31) {
- $timeType = 'day';
- for ($i = 0; $i < $dayCount; $i++) {
- $timeKey[] = date('Y-m-d', $s_start);
- $s_start = strtotime("+1 day", $s_start);
- }
- } elseif ($dayCount <= 92) {
- $timeType = 'weekly';
- for ($i = 0; $i < $dayCount; $i = $i + 7) {
- $timeKey[] = '第' . date('W', $s_start) . '周';
- $s_start = strtotime("+1 week", $s_start);
- }
- } else {
- $timeType = 'year';
- while ($s_start <= $end) {
- $timeKey[] = date('Y-m', $s_start);
- $s_start = strtotime("+1 month", $s_start);
- }
- }
- return [$start, $end, $timeType, $timeKey];
- }
- return [$start, $end];
- }
- /**
- * 计算环比增长率
- * @param $nowValue
- * @param $lastValue
- * @return float|int|string
- */
- public function countRate($nowValue, $lastValue)
- {
- if ($lastValue == 0 && $nowValue == 0) return 0;
- if ($lastValue == 0) return round(bcmul(bcdiv($nowValue, 1, 4), 100, 2), 2);
- if ($nowValue == 0) return -round(bcmul(bcdiv($lastValue, 1, 4), 100, 2), 2);
- return bcmul(bcdiv((bcsub($nowValue, $lastValue, 2)), $lastValue, 4), 100, 2);
- }
- /**
- * tree处理 分类、标签数据(这一类数据)
- * @param array $cate
- * @param array $label
- * @return array
- */
- public function get_tree_children(array $cate, array $label)
- {
- if ($cate) {
- foreach ($cate as $key => $value) {
- if ($label) {
- foreach ($label as $k => $item) {
- if ($value['id'] == $item['label_cate']) {
- $cate[$key]['children'][] = $item;
- unset($label[$k]);
- }
- }
- } else {
- $cate[$key]['children'] = [];
- }
- }
- }
- return $cate;
- }
- /**
- * ip转城市
- * @param $ip
- * @return array|string|string[]|null
- */
- public function convertIp($ip)
- {
- try {
- $ip1num = 0;
- $ip2num = 0;
- $ipAddr1 = "";
- $ipAddr2 = "";
- $dat_path = public_path() . 'statics/ip.dat';
- if (!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
- return '';
- }
- if (!$fd = @fopen($dat_path, 'rb')) {
- return '';
- }
- $ip = explode('.', $ip);
- $ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
- $DataBegin = fread($fd, 4);
- $DataEnd = fread($fd, 4);
- $ipbegin = implode('', unpack('L', $DataBegin));
- if ($ipbegin < 0) $ipbegin += pow(2, 32);
- $ipend = implode('', unpack('L', $DataEnd));
- if ($ipend < 0) $ipend += pow(2, 32);
- $ipAllNum = ($ipend - $ipbegin) / 7 + 1;
- $BeginNum = 0;
- $EndNum = $ipAllNum;
- while ($ip1num > $ipNum || $ip2num < $ipNum) {
- $Middle = intval(($EndNum + $BeginNum) / 2);
- fseek($fd, $ipbegin + 7 * $Middle);
- $ipData1 = fread($fd, 4);
- if (strlen($ipData1) < 4) {
- fclose($fd);
- return '';
- }
- $ip1num = implode('', unpack('L', $ipData1));
- if ($ip1num < 0) $ip1num += pow(2, 32);
- if ($ip1num > $ipNum) {
- $EndNum = $Middle;
- continue;
- }
- $DataSeek = fread($fd, 3);
- if (strlen($DataSeek) < 3) {
- fclose($fd);
- return '';
- }
- $DataSeek = implode('', unpack('L', $DataSeek . chr(0)));
- fseek($fd, $DataSeek);
- $ipData2 = fread($fd, 4);
- if (strlen($ipData2) < 4) {
- fclose($fd);
- return '';
- }
- $ip2num = implode('', unpack('L', $ipData2));
- if ($ip2num < 0) $ip2num += pow(2, 32);
- if ($ip2num < $ipNum) {
- if ($Middle == $BeginNum) {
- fclose($fd);
- return '';
- }
- $BeginNum = $Middle;
- }
- }
- $ipFlag = fread($fd, 1);
- if ($ipFlag == chr(1)) {
- $ipSeek = fread($fd, 3);
- if (strlen($ipSeek) < 3) {
- fclose($fd);
- return '';
- }
- $ipSeek = implode('', unpack('L', $ipSeek . chr(0)));
- fseek($fd, $ipSeek);
- $ipFlag = fread($fd, 1);
- }
- if ($ipFlag == chr(2)) {
- $AddrSeek = fread($fd, 3);
- if (strlen($AddrSeek) < 3) {
- fclose($fd);
- return '';
- }
- $ipFlag = fread($fd, 1);
- if ($ipFlag == chr(2)) {
- $AddrSeek2 = fread($fd, 3);
- if (strlen($AddrSeek2) < 3) {
- fclose($fd);
- return '';
- }
- $AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
- fseek($fd, $AddrSeek2);
- } else {
- fseek($fd, -1, SEEK_CUR);
- }
- while (($char = fread($fd, 1)) != chr(0))
- $ipAddr2 .= $char;
- $AddrSeek = implode('', unpack('L', $AddrSeek . chr(0)));
- fseek($fd, $AddrSeek);
- while (($char = fread($fd, 1)) != chr(0))
- $ipAddr1 .= $char;
- } else {
- fseek($fd, -1, SEEK_CUR);
- while (($char = fread($fd, 1)) != chr(0))
- $ipAddr1 .= $char;
- $ipFlag = fread($fd, 1);
- if ($ipFlag == chr(2)) {
- $AddrSeek2 = fread($fd, 3);
- if (strlen($AddrSeek2) < 3) {
- fclose($fd);
- return '';
- }
- $AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
- fseek($fd, $AddrSeek2);
- } else {
- fseek($fd, -1, SEEK_CUR);
- }
- while (($char = fread($fd, 1)) != chr(0)) {
- $ipAddr2 .= $char;
- }
- }
- fclose($fd);
- if (preg_match('/http/i', $ipAddr2)) {
- $ipAddr2 = '';
- }
- $ipaddr = $ipAddr1;
- $ipaddr = preg_replace('/CZ88.NET/is', '', $ipaddr);
- $ipaddr = preg_replace('/^s*/is', '', $ipaddr);
- $ipaddr = preg_replace('/s*$/is', '', $ipaddr);
- if (preg_match('/http/i', $ipaddr) || $ipaddr == '') {
- $ipaddr = '';
- }
- return $this->strToUtf8($ipaddr);
- } catch (\Throwable $e) {
- return '';
- }
- }
- /**
- * 文字格式转utf8
- * @param $str
- * @return array|false|string|string[]|null
- */
- public function strToUtf8($str)
- {
- $encode = mb_detect_encoding($str, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
- if ($encode == 'UTF-8') {
- return $str;
- } else {
- return mb_convert_encoding($str, 'UTF-8', $encode);
- }
- }
- /**
- * 处理城市数据
- * @param $address
- * @return array
- */
- public function addressHandle($address)
- {
- if ($address) {
- try {
- preg_match('/(.*?(省|自治区|北京市|天津市|上海市|重庆市|澳门特别行政区|香港特别行政区))/', $address, $matches);
- if (count($matches) > 1) {
- $province = $matches[count($matches) - 2];
- $address = preg_replace('/(.*?(省|自治区|北京市|天津市|上海市|重庆市|澳门特别行政区|香港特别行政区))/', '', $address, 1);
- }
- preg_match('/(.*?(市|自治州|地区|区划|县))/', $address, $matches);
- if (count($matches) > 1) {
- $city = $matches[count($matches) - 2];
- $address = str_replace($city, '', $address);
- }
- preg_match('/(.*?(区|县|镇|乡|街道))/', $address, $matches);
- if (count($matches) > 1) {
- $area = $matches[count($matches) - 2];
- $address = str_replace($area, '', $address);
- }
- } catch (\Throwable $e) {
- }
- }
- return [
- 'province' => $province ?? '',
- 'city' => $city ?? '',
- 'district' => $area ?? '',
- "address" => $address
- ];
- }
- /**
- * 插入数据
- * @param array $data
- * @return BaseModel|Model
- */
- public function create(array $data)
- {
- if (method_exists($this->model, 'setAddTimeAttr') && !isset($data['add_time'])) {
- $data['add_time'] = time();
- }
- return $this->model->create($data);
- }
- /**
- * 更新数据
- * @param int|string|array $id
- * @param array $data
- * @param string|null $key
- * @return mixed
- */
- public function update($id, array $data, ?string $key = null)
- {
- if (is_array($id)) {
- $where = $id;
- } else {
- $where = [is_null($key) ? $this->model->getPk() : $key => $id];
- }
- return $this->model->update($data, $where);
- }
- /**
- * 删除
- * @param int|string|array $id
- * @return mixed
- */
- public function delete($id, ?string $key = null)
- {
- if (is_array($id)) {
- $where = $id;
- } else {
- $where = [is_null($key) ? $this->model->getPk() : $key => $id];
- }
- $info = $this->model->where($where)->find();
- if (!$info) return false;
- return $info->delete();
- }
- /**
- * 高精度加法
- * @param int|string $key
- * @param string $incField
- * @param string $inc
- * @param string|null $keyField
- * @param int $acc
- * @return bool
- */
- public function bcInc($key, string $incField, string $inc, string $keyField = null, int $acc = 2)
- {
- return $this->bc($key, $incField, $inc, $keyField, 1);
- }
- /**
- * 高精度 减法
- * @param $key
- * @param string $decField 相减的字段
- * @param string $dec 减的值
- * @param string|null $keyField id的字段
- * @param int $acc 精度
- * @param bool $dec_return_false 减法 不够减是否返回false || 减为0
- * @return bool
- */
- public function bcDec($key, string $decField, string $dec, string $keyField = null, int $acc = 2, bool $dec_return_false = true)
- {
- return $this->bc($key, $decField, $dec, $keyField, 2, $acc, $dec_return_false);
- }
- /**
- * 高精度计算并保存
- * @param $key
- * @param string $incField
- * @param string $inc
- * @param string|null $keyField
- * @param int $type
- * @param int $acc
- * @param bool $dec_return_false 减法 不够减是否返回false || 减为0
- * @return bool
- */
- public function bc($key, string $incField, string $inc, string $keyField = null, int $type = 1, int $acc = 2, bool $dec_return_false = true)
- {
- if ($keyField === null) {
- $result = $this->model->get($key);
- } else {
- $result = $this->model->getOne([$keyField => $key]);
- }
- if (!$result) return false;
- if ($type === 1) {
- $new = bcadd($result[$incField], $inc, $acc);
- } else if ($type === 2) {
- if ($result[$incField] < $inc) {
- if ($dec_return_false) return false;
- $new = 0;
- } else {
- $new = bcsub($result[$incField], $inc, $acc);
- }
- }
- $result->{$incField} = $new;
- return false !== $result->save();
- }
- /**
- * @param $where
- * @return array|array[]
- */
- public function export($where = [], $export_type = 1)
- {
- $list = $this->getExportList($where, '*');
- if (empty($list)) {
- throw new AdminException('暂无数据');
- }
- $export = [];
- $modelName = $this->model->modelName();
- $headers = $this->getHeader();
- if (!count($headers)) throw new AdminException('请设置导出字段');
- $header = array_values($headers);
- $keys = array_keys($headers);
- $title = [$modelName . '导出', $modelName . '信息' . time(), ' 生成时间:' . date('Y-m-d H:i:s', time())];
- $filename = $modelName . '导出_' . date('YmdHis', time());
- $i = 0;
- foreach ($list as $v) {
- $one_data = [];
- foreach ($headers as $k => $vv) {
- if (isset($v[$k]) && is_array($v[$k])) {
- $one_data[$k] = implode("\n", $v[$k]);
- } else {
- $one_data[$k] = $v[$k] ?? '';
- }
- }
- if ($export_type == 1) {
- $export[] = $one_data;
- } else {
- $export[] = array_values($one_data);
- }
- $i++;
- }
- if ($export_type == 1) {
- return compact('header', 'keys', 'export', 'filename');
- } else {
- return ['path' => $this->excel($header, $title, $export, $filename)];
- }
- }
- /**
- * 真实请求导出
- * @param array $header excel表头
- * @param array $title_arr
- * @param array $export 填充数据
- * @param string $filename 保存文件名称
- * @param string $suffix 保存文件后缀
- * @param bool $is_save true|false 是否保存到本地
- * @return mixed
- */
- private function excel(array $header, array $title_arr, array $export = [], string $filename = '', string $suffix = 'xlsx', bool $is_save = true)
- {
- $path = [];
- $exportNum = count($export);
- $limit = $this->model->limit;
- if ($exportNum < $limit) {
- $title = isset($title_arr[0]) && !empty($title_arr[0]) ? $title_arr[0] : '导出数据';
- $name = isset($title_arr[1]) && !empty($title_arr[1]) ? $title_arr[1] : '导出数据';
- $info = isset($title_arr[2]) && !empty($title_arr[2]) ? $title_arr[2] : date('Y-m-d H:i:s', time());
- $filePath = SpreadsheetExcelService::instance()->setExcelHeader($header)
- ->setExcelTile($title, $name, $info)
- ->setExcelContent($export)
- ->excelSave($filename, $suffix, $is_save);
- $path[] = sys_config('site_url') . $filePath;
- } else {
- $data = [];
- $i = $j = 0;
- $basePath = sys_config('site_url') . '/phpExcel/';
- foreach ($export as $item) {
- $data[] = $item;
- $i++;
- if ($limit <= 1 || $i == $exportNum) {
- if ($j > 0) {
- $filename .= '_' . $j;
- $header = [];
- $title_arr = [];
- }
- //加入队列
- ExportExcelJob::dispatch([$data, $filename, $header, $title_arr, $suffix, $is_save]);
- $path[] = $basePath . $filename . '.' . $suffix;
- $data = [];
- $limit = $this->model->limit + 1;
- $j++;
- }
- $limit--;
- }
- }
- return $path;
- }
- /**
- * @param $name
- * @param $arguments
- * @return mixed
- */
- public function __call($name, $arguments)
- {
- return call_user_func_array([$this->model, $name], $arguments);
- }
- }
|