作者 SHW\戥岁。。

加入购物车商品分类添加

... ... @@ -141,8 +141,8 @@ class Fastexport extends Backend
'status' => 0,// 0准备好,1进行中,2完成,3失败
'min' => $min,
'max' => $max,
'sql' => $ExportLib->buildSql('limit', [$min, $max])
]
'sql' => $ExportLib->buildSql('limit', [$min, $max]),
],
];
// 测试sql
... ... @@ -160,7 +160,7 @@ class Fastexport extends Backend
$this->success('导出任务测试准备好~', null, [
'direct_export' => true,
'subtask' => $subtask,
'id' => $ids
'id' => $ids,
]);
}
... ... @@ -200,7 +200,7 @@ class Fastexport extends Backend
'status' => 0,// 0准备好,1进行中,2完成,3失败
'min' => $min,
'max' => $xls_max_number,
'sql' => $ExportLib->buildSql('limit', [$min, $xls_max_number])
'sql' => $ExportLib->buildSql('limit', [$min, $xls_max_number]),
];
// 测试sql
... ... @@ -246,7 +246,7 @@ class Fastexport extends Backend
$this->success('导出任务初始化成功!', null, [
'direct_export' => ($subtask_count == 1) ? true : false,
'subtask' => $subtask,
'id' => $ids
'id' => $ids,
]);
}
... ... @@ -306,6 +306,227 @@ class Fastexport extends Backend
}
/**
* 执行自定义导出
* @param int $task_id 任务ID
* @param int $subtask_id 子任务ID
* @param boolean $direct_export 是否直接反回文件
*/
public function zdyTask()
{
$task_id = 1;
$subtask_id = 1;
$direct_export = true;
\think\Config::set('default_return_type', 'json');
$row = $this->model->get($task_id);
if (!$row) {
$this->error(__('No Results were found'));
}
if (isset($row['subtask'][$subtask_id]) && is_array($row['subtask'][$subtask_id])) {
$subtask = $row['subtask'][$subtask_id];
$task_name = $row['name'];
} else {
$this->result(['subtask_id' => $subtask_id], 0, '子任务找不到啦~', 'json');
}
set_time_limit(0);// 脚本执行时间限制
ini_set('memory_limit', $row['memory_limit'] . 'M');// 脚本内存限制
$ExportLib = new ExportLib($row);
unset($row);
// 检查任务状态
if (!$direct_export) {
if ($subtask['status'] == 1) {
$this->result(['subtask_id' => $subtask_id], 0, '此子任务正在执行中~', 'json');
} else if ($subtask['status'] == 2) {
if (file_exists($this->save_dir . $task_id . DS . $subtask_id . '.xlsx')) {
$this->result(['subtask_id' => $subtask_id], 1, '此子任务已经处理过啦~', 'json');
}
}
}
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->setTitle($task_name);
//设置表头
$head = $ExportLib->getXlsTitle();
$head_count = count($head);
for ($i = 0; $i < $head_count; $i++) {
$worksheet->setCellValueByColumnAndRow($i + 1, 1, $head[$i]);
}
// 写人数据
try {
$data = Db::query($subtask['sql']);
} catch (PDOException $e) {
$this->result([
'subtask_id' => $subtask_id,
'error_msg' => $e->getMessage(),
], 0, '任务失败!', 'json');
}
$y = 2;
foreach ($data as $row_key => $row) {
$i = 1;
foreach ($ExportLib->fields as $key => $value) {
$field = $value['field'];
if ($value['discerns'] == 0) {
// 文本
$worksheet->setCellValueByColumnAndRow($i, $y, $row[$field], DataType::TYPE_STRING);
} else if ($value['discerns'] == 1) {
// 数字
$worksheet->setCellValueByColumnAndRow($i, $y, $row[$field] . "\t");
} else if ($value['discerns'] == 2) {
// 日期时间
if ($row[$field]) {
$excelDateValue = date('Y-m-d H:i:s', $row[$field]);
$worksheet->setCellValueByColumnAndRow($i, $y, $excelDateValue, DataType::TYPE_STRING);
/*$excelDateValue = PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel( $row[$field] );
if ($excelDateValue) {
// 以日期日期格式写入,没区别,有需要的可以打开
$worksheet->setCellValueByColumnAndRow($i, $y, $excelDateValue);
$worksheet->getStyleByColumnAndRow($i,$y)
->getNumberFormat()
->setFormatCode('yyyy-mm-dd h:mm:ss');
$worksheet->getStyleByColumnAndRow($i,$y)->getFont()->setBold(true);
$worksheet->getStyleByColumnAndRow($i,$y)->getFont()->setBold(false);
}*/
} else {
$worksheet->setCellValueByColumnAndRow($i, $y, '-', DataType::TYPE_STRING);
}
} else if ($value['discerns'] == 3) {
// 图片-太慢,太耗资源,弃用
/*$file_info = pathinfo($row[$field]);
$coorrow = $worksheet->getCellByColumnAndRow($i, $y)->getRow();
$coorcolumn = $worksheet->getCellByColumnAndRow($i, $y)->getColumn();
if ($y == 2) {
$worksheet->getColumnDimension($coorcolumn)->setWidth(8);
}
$worksheet->getRowDimension($coorrow)->setRowHeight(40);
if (!empty($file_info['basename'])) {
$basename = $file_info['basename'];
$drawing = new Drawing();
$drawing->setName('图片');
$drawing->setPath($remote_save_dir . $row[$field]);
$drawing->setWidth(40);
$drawing->setHeight(40);
$drawing->setCoordinates($coorcolumn . $coorrow);
$drawing->setWorksheet($worksheet);
} else {
$worksheet->setCellValueByColumnAndRow($i, $y, $row[$field], DataType::TYPE_STRING);
}*/
// 以链接导出图片
$field_value = cdnurl($row[$field], true);
$worksheet->setCellValueByColumnAndRow($i, $y, $field_value, DataType::TYPE_STRING);
$worksheet->getCellByColumnAndRow($i, $y)->getHyperlink()->setUrl($field_value);
} else if ($value['discerns'] == 4) {
// 文件
$field_value = cdnurl($row[$field], true);
$worksheet->setCellValueByColumnAndRow($i, $y, $field_value, DataType::TYPE_STRING);
$worksheet->getCellByColumnAndRow($i, $y)->getHyperlink()->setUrl($field_value);
} else if ($value['discerns'] == 5) {
// 赋值
$field_value = $ExportLib->assignment($row[$field], $value['scheme']);
$worksheet->setCellValueByColumnAndRow($i, $y, $field_value, DataType::TYPE_STRING);
}
$i++;
}
$y++;
unset($data[$row_key]); // 能节约一点内存
}
// xls文件处理
if ($direct_export) {
// 直接下载
ob_end_clean();
header("Pragma: public");
header("Expires: 0");
header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
header("Content-Type:application/force-download");
header("Content-Type:application/vnd.ms-execl");
header("Content-Type:application/octet-stream");
header("Content-Type:application/download");
$task_name = $task_id . '.' . $task_name . '.xlsx';
$encoded_filename = urlencode($task_name);
$ua = $_SERVER["HTTP_USER_AGENT"];
if (preg_match("/MSIE/", $ua)) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else if (preg_match("/Firefox/", $ua)) {
header('Content-Disposition: attachment; filename*="utf8\'\'' . $task_name . '"');
} else {
header('Content-Disposition: attachment; filename="' . $task_name . '"');
}
header("Content-Transfer-Encoding:binary");
header('Cache-Control: max-age=0');// 禁止缓存
$writer = new Xlsx($spreadsheet);
$writer->save('php://output');
$spreadsheet->disconnectWorksheets();
unset($spreadsheet);
} else {
// 保存
$writer = new Xlsx($spreadsheet);
$writer->save($this->save_dir . $task_id . DS . $subtask_id . '.xlsx');
// 设置任务状态
$result = false;
Db::startTrans();
try {
// 读取最新的 subtask 数据
$row = $this->model->get($task_id);
$progress = $row->progress + round(92 / count($row['subtask']), 2);
$progress = ($progress > 100) ? 100 : $progress;
if (isset($row['subtask'][$subtask_id]) && is_array($row['subtask'][$subtask_id])) {
$subtask = $row['subtask'];
$subtask[$subtask_id]['status'] = 2;
$row->subtask = $subtask;
$row->progress = $progress;
$row->save();
$result = true;
}
Db::commit();
} catch (PDOException $e) {
Db::rollback();
$this->result([
'subtask_id' => $subtask_id,
'error_msg' => $e->getMessage(),
], 0, '任务失败!', 'json');
} catch (Exception $e) {
Db::rollback();
$this->result([
'subtask_id' => $subtask_id,
'error_msg' => $e->getMessage(),
], 0, '任务失败!', 'json');
}
$spreadsheet->disconnectWorksheets();
unset($spreadsheet);
if ($result) {
$this->result(['subtask_id' => $subtask_id], 1, '子任务处理成功!', 'json');
} else {
$this->result(['subtask_id' => $subtask_id], 0, '子任务找不到啦~', 'json');
}
}
}
/**
* 执行子任务
* @param int $task_id 任务ID
* @param int $subtask_id 子任务ID
... ... @@ -541,7 +762,7 @@ class Fastexport extends Backend
$this->result(['file_name' => $row['file']], 1, '此任务已经打过包了!', 'json');
}
is_dir($this->fastExportDir) OR mkdir($this->fastExportDir, 0755, true);
is_dir($this->fastExportDir) or mkdir($this->fastExportDir, 0755, true);
foreach ($row['subtask'] as $key => $subtask) {
if (!file_exists($this->save_dir . $task_id . DS . $subtask['id'] . '.xlsx')) {
... ... @@ -624,7 +845,7 @@ class Fastexport extends Backend
'smallint',
'mediumint',
'integer',
'bigint'
'bigint',
];
$discerns = 0;
... ... @@ -651,7 +872,7 @@ class Fastexport extends Backend
return [
'discerns' => $discerns,
'name' => $field,
'comment' => ''
'comment' => '',
];
}
... ... @@ -663,7 +884,7 @@ class Fastexport extends Backend
return [
'discerns' => 5,
'name' => $field_name ? $field_name : $field,
'comment' => $field_comment
'comment' => $field_comment,
];
} else {
... ... @@ -675,7 +896,7 @@ class Fastexport extends Backend
return [
'discerns' => $discerns,
'name' => $comment ? $comment : $field,
'comment' => isset($comment_temp) ? $comment_temp : ''
'comment' => isset($comment_temp) ? $comment_temp : '',
];
}
}
... ... @@ -898,7 +1119,7 @@ class Fastexport extends Backend
$row['where_field_arr_select'][] = $key;
$row['where_field_arr'][$key] = [
'op' => $value,
'condition' => $row['where_field']['condition'][$key]
'condition' => $row['where_field']['condition'][$key],
];
}
}
... ...
... ... @@ -6,19 +6,33 @@
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('litestore/litestoregoods/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('litestore/litestoregoods/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('litestore/litestoregoods/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
<a href="javascript:;" class="btn btn-danger btn-import {:$auth->check('litestore/litestoregoods/import')?'':'hide'}" title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__('Import')}</a>
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}"><i
class="fa fa-refresh"></i> </a>
<a href="javascript:;"
class="btn btn-success btn-add {:$auth->check('litestore/litestoregoods/add')?'':'hide'}"
title="{:__('Add')}"><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;"
class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('litestore/litestoregoods/edit')?'':'hide'}"
title="{:__('Edit')}"><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;"
class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('litestore/litestoregoods/del')?'':'hide'}"
title="{:__('Delete')}"><i class="fa fa-trash"></i> {:__('Delete')}</a>
<a href="javascript:;"
class="btn btn-danger btn-import {:$auth->check('litestore/litestoregoods/import')?'':'hide'}"
title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload"
data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i>
{:__('Import')}</a>
<a href="javascript:;"
class="btn btn-info btn-edit btn-sync"
title="{:__('批量导出')}"><i class="fa fa-download"></i>{:__('批量导出')}</a>
<!-- <div class="dropdown btn-group {:$auth->check('litestore/litestoregoods/multi')?'':'hide'}">-->
<!-- <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>-->
<!-- <ul class="dropdown-menu text-left" role="menu">-->
<!-- <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>-->
<!-- <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>-->
<!-- </ul>-->
<!-- </div>-->
<!-- <div class="dropdown btn-group {:$auth->check('litestore/litestoregoods/multi')?'':'hide'}">-->
<!-- <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>-->
<!-- <ul class="dropdown-menu text-left" role="menu">-->
<!-- <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>-->
<!-- <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>-->
<!-- </ul>-->
<!-- </div>-->
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('litestore/litestoregoods/edit')}"
... ...
... ... @@ -36,7 +36,7 @@ class Cart extends Api
$number = $this->request->post('number');
if (!is_numeric($sku_id) || !is_numeric($goods_id) || !is_numeric($number)) $this->error('参数不合法');
$category_id = (new \app\api\model\Goods())->where('id', $goods_id)->value('category_id');
$category_id = (new \app\api\model\Goods())->where('goods_id', $goods_id)->value('category_id');
$data = [
'user_id' => $this->auth->id,
... ...
define(['jquery', 'bootstrap', 'backend', 'table', 'form','template','litestoregoods'], function ($, undefined, Backend, Table, Form,Template,litestoregoods) {
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'litestoregoods'], function ($, undefined, Backend, Table, Form, Template, litestoregoods) {
var Controller = {
index: function () {
$(".btn-add").data("area", ["1000px","800px"]);
$(".btn-add").data("area", ["1000px", "800px"]);
// 初始化表格参数配置
Table.api.init({
extend: {
... ... @@ -22,51 +22,120 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','template','litestoreg
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'goods_id',
sortName: 'goods_sort',
search:false,
showExport:false,
search: false,
showExport: false,
columns: [
[
{checkbox: true},
{field: 'goods_id', title: __('Goods_id')},
{field: 'goods_name', title: __('Goods_name'),operate: 'LIKE'},
{field: 'keywords', title: __('Keywords'),operate: 'LIKE'},
{field: 'category.name', title: __('Category.name'),operate: false},
{field: 'activity.name', title: __('Activity.name'),operate: false},
{field: 'category_id', visible:false,title: __('Category_id')},
{field: 'goods_name', title: __('Goods_name'), operate: 'LIKE'},
{field: 'keywords', title: __('Keywords'), operate: 'LIKE'},
{field: 'category.name', title: __('Category.name'), operate: false},
{field: 'activity.name', title: __('Activity.name'), operate: false},
{field: 'category_id', visible: false, title: __('Category_id')},
{field: 'image', title: __('Image'), formatter: Table.api.formatter.image},
{field: 'images', title: __('Images'), formatter: Table.api.formatter.images},
{field: 'spec_type', title: __('Spec_type'), searchList: {"10":__('Spec_type 10'),"20":__('Spec_type 20')}, formatter: Table.api.formatter.normal},
{field: 'stock_num', title: __('库存'),operate: false},
{
field: 'spec_type',
title: __('Spec_type'),
searchList: {"10": __('Spec_type 10'), "20": __('Spec_type 20')},
formatter: Table.api.formatter.normal
},
{field: 'stock_num', title: __('库存'), operate: false},
// {field: 'deduct_stock_type', title: __('Deduct_stock_type'), searchList: {"10":__('Deduct_stock_type 10'),"20":__('Deduct_stock_type 20')}, formatter: Table.api.formatter.normal},
// {field: 'freight.name', title: __('Freight.name')},
// {field: 'sales_initial', title: __('Sales_initial')},
{field: 'sales_actual', title: __('Sales_actual')},
// {field: 'goods_sort', title: __('Goods_sort')},
// {field: 'delivery_id', title: __('Delivery_id')},
{field: 'goods_status', title: __('Goods_status'), searchList: {"10":__('Goods_status 10'),"20":__('Goods_status 20')}, formatter: Table.api.formatter.status},
{field: 'is_delete', title: __('Is_delete'), searchList: {"0":__('Is_delete 0'),"1":__('Is_delete 1')}, formatter: Table.api.formatter.normal},
{field: 'is_index', title: __('Is_index'), searchList: {"0":__('Is_index 0'),"1":__('Is_index 1')}, formatter: Table.api.formatter.normal},
{field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
{field: 'updatetime', title: __('Updatetime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
{
field: 'goods_status',
title: __('Goods_status'),
searchList: {"10": __('Goods_status 10'), "20": __('Goods_status 20')},
formatter: Table.api.formatter.status
},
{
field: 'is_delete',
title: __('Is_delete'),
searchList: {"0": __('Is_delete 0'), "1": __('Is_delete 1')},
formatter: Table.api.formatter.normal
},
{
field: 'is_index',
title: __('Is_index'),
searchList: {"0": __('Is_index 0'), "1": __('Is_index 1')},
formatter: Table.api.formatter.normal
},
{
field: 'createtime',
title: __('Createtime'),
operate: 'RANGE',
addclass: 'datetimerange',
formatter: Table.api.formatter.datetime
},
{
field: 'updatetime',
title: __('Updatetime'),
operate: 'RANGE',
addclass: 'datetimerange',
formatter: Table.api.formatter.datetime
},
{
field: 'operate',
title: __('Operate'),
table: table,
events: Table.api.events.operate,
formatter: Table.api.formatter.operate
}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
table.on('load-success.bs.table',function(data){
$(".btn-editone").data("area", ["1000px","800px"]);
$('.btn-sync').click(function () {
var index = Layer.load();
$.ajax({
// type: "POST",
url: $.fn.bootstrapTable.defaults.extend.performTask,
confirm: '确认开始执行任务吗?(数据导出属高IO操作,若本任务数据量超过2万,请择服务器相对闲时执行!)',
refresh: true,
// url: "fastexport/zdyTask",
datatype: "json",
success: function (data, ret) {
if (ret.code == 1) {
if (data.direct_export) {
Fast.api.msg('任务已开始,请稍等片刻...')
window.location = 'fastexport/zdyTask';
} else {
window.open("fastexport/taskControl/task_id/" + data.id, "_blank");
}
} else {
Layer.alert(ret.msg);
}
return false;
},
error: function (data, ret) {
Layer.alert(ret.msg);
return false;
}
});
});
table.on('load-success.bs.table', function (data) {
$(".btn-editone").data("area", ["1000px", "800px"]);
});
},
add: function () {
Form.api.bindevent($("form[role=form]"), function(data, ret){
Form.api.bindevent($("form[role=form]"), function (data, ret) {
Fast.api.close(data);
Toastr.success("商品提交成功");
}, function(data, ret){
}, function (data, ret) {
Toastr.success("商品提交失败");
}, function(success, error){
}, function (success, error) {
//注意如果我们需要阻止表单,可以在此使用return false;即可
//如果我们处理完成需要再次提交表单则可以使用submit提交,如下
console.log(this);
... ... @@ -104,7 +173,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','template','litestoreg
if (token) {
$("input[name='__token__']", form).val(token);
}
if(xhr.responseJSON.code == 1){
if (xhr.responseJSON.code == 1) {
//关闭弹窗
var index = parent.Layer.getFrameIndex(window.name);
var callback = parent.$("#layui-layer" + index).data("callback");
... ... @@ -134,7 +203,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','template','litestoreg
// 注册商品多规格组件
var specMany = new GoodsSpec({
container: '.goods-spec-many',
OutForm:Form
OutForm: Form
});
// 切换单/多规格
... ... @@ -153,12 +222,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','template','litestoreg
edit: function () {
//Controller.api.bindevent();
Form.api.bindevent($("form[role=form]"), function(data, ret){
Form.api.bindevent($("form[role=form]"), function (data, ret) {
//Fast.api.close(data);
Toastr.success("商品提交成功");
}, function(data, ret){
}, function (data, ret) {
Toastr.success("商品提交失败");
}, function(success, error){
}, function (success, error) {
//注意如果我们需要阻止表单,可以在此使用return false;即可
//如果我们处理完成需要再次提交表单则可以使用submit提交,如下
console.log(this);
... ... @@ -196,7 +265,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','template','litestoreg
if (token) {
$("input[name='__token__']", form).val(token);
}
if(xhr.responseJSON.code == 1){
if (xhr.responseJSON.code == 1) {
//关闭弹窗
var index = parent.Layer.getFrameIndex(window.name);
var callback = parent.$("#layui-layer" + index).data("callback");
... ... @@ -225,7 +294,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','template','litestoreg
// 注册商品多规格组件
var specMany = new GoodsSpec({
container: '.goods-spec-many',
OutForm:Form
OutForm: Form
}, from_specData);
// 切换单/多规格
... ...