初始上传

This commit is contained in:
2026-04-04 17:27:12 +08:00
parent 4d80d28eb4
commit b7e11774ee
11191 changed files with 1588469 additions and 0 deletions

340
app/model/system/Export.php Executable file
View File

@@ -0,0 +1,340 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\system;
use app\model\BaseModel;
use think\facade\Db;
class Export extends BaseModel
{
const STATUS_IN_PROCESS = 0;
const STATUS_SUCCESS = 1;
const STATUS_FAIL = 2;
static public function getStatus($key = null)
{
$arr = [
[
'id' => self::STATUS_IN_PROCESS,
'name' => '导出中',
],
[
'id' => self::STATUS_SUCCESS,
'name' => '导出成功',
],
[
'id' => self::STATUS_FAIL,
'name' => '导出失败',
],
];
if(isset($arr[0][$key])){
$arr = array_column($arr, null, $key);
}
return $arr;
}
protected $data_num = 0;
/**
* 导出
* @param $param
* @return array
*/
public function export($param)
{
//传参说明
/*$param = [
'site_id' => $site_id,
'store_id' => $export_store_id,
'from_type' => 'store_account',
'from_type_name' => '门店账户',
'condition_desc' => $condition_desc,
'export_field' => [
['field' => 'store_name', 'name' => '门店名称'],
['field' => 'type_name', 'name' => '来源方式'],
['field' => 'account_data', 'name' => '记录金额'],
['field' => 'create_time', 'name' => '发生时间'],
['field' => 'remark', 'name' => '备注'],
['field' => 'related_no', 'name' => '关联编号'],
],
//数据库查询相关参数
'query' => [
'table' => 'store_account',
'alias' => 'sa',
'join' => [
['store s', 'sa.store_id = s.store_id', 'inner'],
],
'condition' => $condition,
'field' => 'sa.*,s.store_name',
'chunk_field' => 'sa.id',
'chunk_order' => 'asc',
],
//数据库查询结果处理 这个其实应该放在query中
'handle' => function($item_list){
return $item_list;
},
//直接传递导出的数据
'data' => [],
];*/
set_time_limit(0);
$site_id = $param['site_id'];
$store_id = $param['store_id'] ?? 0;
$from_type = $param['from_type'];
$from_type_name = $param['from_type_name'];
$condition_desc= $param['condition_desc'];
$export_field = $param['export_field'];
$query = $param['query'] ?? null;//table alias join condition field order
$handle = $param['handle'] ?? null;//数据处理
try {
//预先创建导出的记录
$data = array(
'condition' => json_encode($condition_desc, JSON_UNESCAPED_UNICODE),
'create_time' => time(),
'from_type' => $from_type,
'from_type_name' => $from_type_name,
'status' => self::STATUS_IN_PROCESS,
'site_id' => $site_id,
'store_id' => $store_id,
);
$records_result = $this->addExport($data);
$export_id = $records_result['data'];
if (empty($export_id)) return $this->error(null, '创建导出记录失败');
$this->data_num = 0;
//创建目录
$file_path = 'upload/export/'.$from_type.'/';
if (!dir_mkdir($file_path)) return $this->error(null, '导出目录创建失败');
//创建并打开文件
$file_name = $from_type_name.date('YmdHis');//csv文件名
$file_path = $file_path . $file_name . '.csv';
$fp = fopen($file_path, 'w');
fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
//写入第一行表头
fwrite($fp, join(',', array_column($export_field, 'name'))."\n");
//导出数据
if(isset($param['query'])){
$export_table = Db::name($query['table'])->where($query['condition']);
if(!empty($query['alias'])) $export_table = $export_table->alias($query['alias']);
if(!empty($query['join'])) $export_table = $this->parseJoin($export_table, $query['join']);
if(!empty($query['group'])) $export_table = $export_table->group($query['group']);
$export_table->field($query['field'])->chunk(1000, function ($item_list) use ($fp, $export_field, $handle) {
$item_list = $item_list->toArray();
if(!empty($handle)){
$item_list = $handle($item_list);
}
$this->data_num += count($item_list);
$this->itemExport($item_list, $export_field, $fp);
unset($item_list);
}, $query['chunk_field'], $query['chunk_order']);
$export_table->removeOption();
}else if(isset($param['data'])){
$this->itemExport($param['data'], $export_field, $fp);
}else{
throw new \Exception('query参数和data参数至少要传一个');
}
fclose($fp); //每生成一个文件关闭
unset($export_table);
//更新导出记录
$this->editExport([
'path' => $file_path,
'status' => self::STATUS_SUCCESS,
'data_num' => $this->data_num,
], [['export_id', '=', $export_id]]);
//返回导出信息
$export_info = $this->getExportInfo([['export_id', '=', $export_id]])['data'];
return $this->success($export_info);
} catch (\Exception $e ) {
$error = [
'file' => $e->getFile(),
'line' => $e->getLine(),
'message' => $e->getMessage(),
];
if(isset($export_id)){
//更新导出记录
$this->editExport([
'status' => self::STATUS_FAIL,
'fail_log' => json_encode($error, JSON_UNESCAPED_UNICODE),
], [['export_id', '=', $export_id]]);
}
return $this->error($error, '导出失败');
}
}
/**
* 给csv写入新的数据
* @param $item_list
* @param $field_key
* @param $temp_line
* @param $fp
*/
protected function itemExport($item_list, $export_field, $fp)
{
if(method_exists($item_list, 'toArray')){
$item_list = $item_list->toArray();
}
foreach ($item_list as $item_info) {
$values = [];
foreach($export_field as $field_info){
if(isset($item_info[$field_info['field']])){
$value = $item_info[$field_info['field']];
$value = trim($value);
$value = str_replace(',', '', $value . "\t");
$value = str_replace("\n", '', $value);
$value = str_replace("\r", '', $value);
$values[] = $value;
}
}
//写入数据
fwrite($fp, join(',', $values)."\n");
//销毁变量, 防止内存溢出
unset($new_line_value);
}
}
/**
* 解析关联
* @param $db_obj
* @param $join
* @return mixed
*/
protected function parseJoin($db_obj, $join)
{
foreach ($join as $item) {
list($table, $on, $type) = $item;
$type = strtolower($type);
switch ($type) {
case 'left':
$db_obj = $db_obj->leftJoin($table, $on);
break;
case 'inner':
$db_obj = $db_obj->join($table, $on);
break;
case 'right':
$db_obj = $db_obj->rightjoin($table, $on);
break;
case 'full':
$db_obj = $db_obj->fulljoin($table, $on);
break;
default:
break;
}
}
return $db_obj;
}
/**
* 添加导出记录
* @param $data
* @return array
*/
public function addExport($data)
{
$res = model('export')->add($data);
return $this->success($res);
}
/**
* 更新导出记录
* @param $data
* @param $condition
* @return array
*/
public function editExport($data, $condition)
{
$res = model('export')->update($data, $condition);
return $this->success($res);
}
/**
* 删除导出记录
* @param $condition
* @return array
*/
public function deleteExport($condition)
{
//先查询数据
$list = model('export')->getList($condition, '*');
if (!empty($list)) {
foreach ($list as $k => $v) {
if (file_exists($v['path'])) {
//删除物理文件路径
if (!unlink($v['path'])) {
//失败
} else {
//成功
}
}
}
$res = model('export')->delete($condition);
}
return $this->success($res ?? '');
}
public function getExportInfo($condition, $field = '*')
{
$info = model('export')->getInfo($condition, $field);
$info = $this->handleData($info);
return $this->success($info);
}
/**
* 获取导出记录
* @param $condition
* @param string $field
* @param string $order
* @return array
*/
public function getExportList($condition, $field = '*', $order = '')
{
$list = model('export')->getList($condition, $field, $order);
foreach($list as &$val){
$val = $this->handleData($val);
}
return $this->success($list);
}
/**
* 导出记录
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getExportPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
{
$list = model('export')->pageList($condition, $field, $order, $page, $page_size);
foreach($list['list'] as &$val){
$val = $this->handleData($val);
}
return $this->success($list);
}
protected function handleData($data)
{
if(isset($data['status'])){
$status_list = self::getStatus('id');
$data['status_name'] = $status_list[$data['status']]['name'] ?? '';
}
return $data;
}
}