更新部分的内容,同步数据
This commit is contained in:
@@ -146,6 +146,73 @@ class PdmPartitemIndex extends AdminController
|
||||
}
|
||||
return [$count, $list];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取资源列表
|
||||
* @param array $params
|
||||
* @return array
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public static function dataListAll(array $params): array
|
||||
{
|
||||
$controller = new PdmPartitemIndex();
|
||||
|
||||
$where = $controller->buildSelectParams();
|
||||
$count = $controller->model->where($where)->count();
|
||||
$fieldList = $controller->model->getFields();
|
||||
$order = !array_key_exists('sort', $fieldList) ? 'id' : 'sort';
|
||||
$subQuery = $controller->model->field('id')->where($where)->order($order, 'desc')->buildSql();
|
||||
$subQuery = '( SELECT object.id FROM ' . $subQuery . ' AS object )';
|
||||
// $list = $this->model->with($this->relationModel)->where('id in' . $subQuery)->order($order, 'asc')->select()->toArray(); // 如果是'desc' list_to_tree 函数返回为空!
|
||||
$list = $controller->model->with($controller->relationModel)->where('id in' . $subQuery)->order($order, 'asc')->select(); // 如果是'desc' list_to_tree 函数返回为空!
|
||||
|
||||
foreach($list as $key => $value){
|
||||
// throw new \Exception(json_encode($value));
|
||||
// throw new \Exception(json_encode($list[$key]->admin['nickname']));
|
||||
$list[$key]['creator'] =__($list[$key]->admin == null?'': $list[$key]->admin['nickname']);
|
||||
$list[$key]['parttype'] =__($list[$key]->pdmParttype ==null?'': $list[$key]->pdmParttype['name']);
|
||||
$list[$key]['mfg_name'] =__($list[$key]->pdmMfgName == null ?'': $list[$key]->pdmMfgName['mfgname']);
|
||||
$list[$key]['mpn'] =__($list[$key]->pdmPurchasecode == null ?'': $list[$key]->pdmPurchasecode['mpn']);
|
||||
|
||||
// if($list[$key]->mfgname == null){
|
||||
// $list[$key]['mfg_name'] ='';
|
||||
// }else{
|
||||
// $list[$key]['mfg_name'] =$list[$key]->mfgname['mfgname'];
|
||||
// }
|
||||
}
|
||||
|
||||
$list = $list->toArray();
|
||||
if(!empty($list) && is_array($list)){
|
||||
$nodeid = array();
|
||||
foreach($list as $key => $value){
|
||||
if($value['pid'] == 0 ){
|
||||
$nodeid[] = $value['id'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach($list as $key => $value){
|
||||
if(!in_array($value['pid'],$nodeid) && $value['pid'] > 0){
|
||||
$nodeid[] = $value['pid'];
|
||||
$nodevalue = $controller->model->find($value['pid']);
|
||||
$nodevalue = $controller->model->find($value['pid'])->toArray();
|
||||
|
||||
if(!empty($nodevalue)){
|
||||
$list[] = &$nodevalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
$list = list_sort_by($list,'id','asc');
|
||||
// usort($list, function($a, $b) {
|
||||
// return $a['id'] <=> $b['id']; // 对 'id' 进行升序排序
|
||||
// });
|
||||
// throw new \Exception(json_encode($list));
|
||||
}
|
||||
return [$count, $list];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -212,7 +212,7 @@ class PdmPartitemRelation extends AdminController
|
||||
$where = ['partnumber' => $partnumbertemp];
|
||||
// $partnumbertemp1 = PdmPartitemIndexModel::find($partnumbertemp)->toArray();
|
||||
$partnumbertemp1 = PdmPartitemIndexModel::where($where)->select()->toArray();
|
||||
list($countpartnumberIndex, $partitemIndex) = \app\admin\controller\PdmPartitemIndex::dataList($partnumbertemp1);
|
||||
list($countpartnumberIndex, $partitemIndex) = \app\admin\controller\PdmPartitemIndex::dataListAll($partnumbertemp1);
|
||||
|
||||
|
||||
if (request()->isPost()) {
|
||||
|
||||
@@ -63,7 +63,8 @@ class PdmPartlist extends AdminController
|
||||
$limit = (int)input('limit', 10);
|
||||
$where = $this->buildSelectParams();
|
||||
$fieldList = $this->model->getFields();
|
||||
$order = !array_key_exists('sort', $fieldList) ? 'id' : 'sort';
|
||||
// $order = !array_key_exists('sort', $fieldList) ? 'id' : 'sort';
|
||||
$order = 'id' ;
|
||||
|
||||
$where[] = ['pid','in',$pid];
|
||||
if (!empty($post['keyword'])) {
|
||||
@@ -77,7 +78,13 @@ class PdmPartlist extends AdminController
|
||||
}
|
||||
// throw new \Exception(json_encode($where));
|
||||
$count = $this->model->where($where)->count();
|
||||
$subQuery = $this->model->field('id')->where($where)->order($order, 'desc')->limit($limit)->page($page)->buildSql();
|
||||
$export = input('export',0);
|
||||
if($export>0){
|
||||
$subQuery = $this->model->field('id')->where($where)->order($order, 'asc')->buildSql(); // asc or desc
|
||||
}else{
|
||||
$subQuery = $this->model->field('id')->where($where)->order($order, 'asc')->limit($limit)->page($page)->buildSql();
|
||||
}
|
||||
|
||||
$subQuery = '( SELECT object.id FROM ' . $subQuery . ' AS object )';
|
||||
$list = $this->model->with($this->relationModel)->where('id in' . $subQuery)->order($order, 'asc')->select() // 如果是'desc' list_to_tree 函数返回为空!
|
||||
// $list = $this->model->where($where)->limit((int)$limit)->page((int)$page)->select()
|
||||
@@ -99,4 +106,59 @@ class PdmPartlist extends AdminController
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新数据到CIS数据表
|
||||
* @return Response
|
||||
* @throws DbException
|
||||
*/
|
||||
public function sync(): Response
|
||||
{
|
||||
//$lists = json_decode( input('data'));
|
||||
$lists = input('data');
|
||||
$bomid = input('bomid') ;
|
||||
// throw new \Exception(json_encode($lists));
|
||||
|
||||
if(!empty($bomid)){
|
||||
$status = $this->model->destroy(['pid' => $bomid]);
|
||||
if($status){
|
||||
|
||||
} else{
|
||||
return $this->error('BOM ID:'.$bomid.',删除数据失败!');
|
||||
}
|
||||
}
|
||||
|
||||
foreach( $lists as &$item){
|
||||
// 添加或修改 'pid' 键
|
||||
$item['pid'] = $bomid;
|
||||
// 检查 '备注' 键是否存在
|
||||
// if (isset($item['备注'])) {
|
||||
// // 将 '备注' 的值赋给 'content'
|
||||
// $item['content'] = $item['备注'];
|
||||
// // 移除 '备注' 键
|
||||
// unset($item['备注']);
|
||||
// } else {
|
||||
// // 可选:如果 '备注' 键不存在,可以设置一个默认值或记录日志
|
||||
// $item['content'] = ''; // 或其他默认值
|
||||
// // error_log("缺少 '备注' 字段,键值: " . $key);
|
||||
// }
|
||||
// 可选:处理 'id' 键
|
||||
if (!empty($item['id'])) {
|
||||
unset($item['id']);
|
||||
}
|
||||
}
|
||||
// throw new \Exception(json_encode($lists));
|
||||
|
||||
$status = $this->model->saveAll($lists);
|
||||
if($status){
|
||||
return $this->success('BOM ID:'.$bomid.'更新数据成功。');
|
||||
// return $this->success();
|
||||
} else{
|
||||
return $this->error('BOM ID:'.$bomid.',更新数据失败!');
|
||||
}
|
||||
|
||||
return $this->error('更新失败,请检查您的参数!');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -77,4 +77,33 @@ class PdmPurchasecode extends AdminController
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改资源状态 -EOL
|
||||
* @return Response|void
|
||||
*/
|
||||
public function statusEol()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
|
||||
$where[] = ['id', '=', input('id')];
|
||||
if (!$this->authService->SuperAdmin() && $this->dataLimit
|
||||
&& in_array($this->dataLimitField, $this->model->getFields())) {
|
||||
$where[] = [$this->dataLimitField, '=', get_admin_id()];
|
||||
}
|
||||
|
||||
try {
|
||||
$this->status = $this->model->where($where)->update(['eol' => input('eol')]);
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage());
|
||||
}
|
||||
|
||||
if ($this->status) {
|
||||
return $this->success();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->error();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class PdmPartlist extends Model
|
||||
*/
|
||||
public function partitemview()
|
||||
{
|
||||
return $this->hasOne(\app\admin\model\PdmPartitemView::Class,'partnumber','partnumber')->bind(['purchasecode','parttype','value','description','mpn','mfgname','footprint','manufacture']);
|
||||
return $this->hasOne(\app\admin\model\PdmPartitemView::Class,'partnumber','partnumber')->bind(['purchasecode','parttype','value','description','mpn','mfg','footprint','manufacture']);
|
||||
}
|
||||
|
||||
// 字段修改器
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</div> -->
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Symbol</label>
|
||||
<label class="layui-form-label">Partnumber</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="partnumberNode" name="partnumber" lay-filter="partnumberNode" data-pid="{$data.partnumber|default=''}"></div>
|
||||
</div>
|
||||
|
||||
@@ -312,12 +312,12 @@
|
||||
// 确认用户希望导出全部数据
|
||||
layer.confirm('确定更新所有数据到 CIS数据表 吗?', { icon: 3, title: '更新确认' }, function(index){
|
||||
layer.close(index);
|
||||
exportAllDataToExcel();
|
||||
updataAllCis();
|
||||
});
|
||||
});
|
||||
|
||||
// 自定义导出功能
|
||||
function exportAllDataToExcel(){
|
||||
function updataAllCis(){
|
||||
// 获取当前的过滤条件(例如,pid)
|
||||
// let selectedData = table.checkStatus('lay-tableGroup').data;
|
||||
// let pid = selectedData.length ? selectedData[0].id : 0;
|
||||
|
||||
@@ -143,7 +143,17 @@
|
||||
|
||||
<!-- 自定义导出按钮 -->
|
||||
<button id="exportExcel" class="layui-btn layui-btn-primary">
|
||||
<i class="layui-icon layui-icon-export"></i> 导出 Excel
|
||||
<i class="layui-icon layui-icon-export"></i> {:__('导出 Excel')}
|
||||
</button>
|
||||
|
||||
<button type="button" class="layui-btn" id="uploadExcelBtn">
|
||||
<i class="layui-icon"></i> {:__('导入Excel')}
|
||||
</button>
|
||||
|
||||
<input type="file" id="excelFileInput" accept=".xls,.xlsx" style="display: none;" />
|
||||
|
||||
<button id="syncButton" class="layui-btn" style="display: none;">
|
||||
<i class="layui-icon"></i>{:__('同步到数据库')}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
@@ -153,11 +163,19 @@
|
||||
|
||||
<!-- // 创建数据实例 -->
|
||||
<table id="lay-tableList" lay-filter="lay-tableList"></table>
|
||||
<table class="layui-hide" id="dataTable" lay-filter="dataTableFilter"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm" lay-event="export" lay-filter="dataTableFilter" >导出数据</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<!-- // 添加编辑数据 -->
|
||||
<section id="editforms_bom" class="layui-hide">
|
||||
<div class="layui-fluid layui-bg-white">
|
||||
@@ -313,7 +331,10 @@
|
||||
let $ = layui.jquery;
|
||||
let table = layui.table;
|
||||
let form = layui.form;
|
||||
let count = {$count|default=300};
|
||||
// let count = {$count|default=300};
|
||||
|
||||
let bomname ="";
|
||||
let bomid = "";
|
||||
|
||||
// 定义表格URL
|
||||
let tableURL = "{:url('/PdmPartlist/index')}";
|
||||
@@ -327,11 +348,55 @@
|
||||
, page: true
|
||||
, limit: 18
|
||||
, cols: [[
|
||||
{ type: 'radio', align: 'left', title: '{:__("ID")}' },
|
||||
{ type: 'radio', align: 'left' },
|
||||
{ field: 'id', title: '{:__("ID")}' },
|
||||
{ field: 'partnumber', align: 'center', title: '{:__("BOM编码")}' },
|
||||
// { field: 'reference', align: 'center', title: '{:__("位号")}' },
|
||||
{ field: 'content', align: 'center', title: '{:__("备注")}' },
|
||||
]]
|
||||
,done: function(res, curr, count) {
|
||||
if (res.data.length > 0) {
|
||||
// 获取第一行数据
|
||||
// let firstRow = res.data[0];
|
||||
let data = table.checkStatus('lay-tableGroup').data;
|
||||
let ids = [];
|
||||
|
||||
// console.log('data:'+ JSON.stringify(data));
|
||||
|
||||
// 处理选中行的数据
|
||||
handleSelectedRow(data);
|
||||
|
||||
for (const key in data) {
|
||||
ids.push(data[key].id);
|
||||
bomid = data[key].id;
|
||||
bomname = data[key].partnumber;
|
||||
}
|
||||
|
||||
let url = tableURL + '?pid=' + ids.join(',');
|
||||
table.reloadData('lay-tableList', {
|
||||
url: url
|
||||
});
|
||||
|
||||
|
||||
// // 重新加载关联表格数据
|
||||
// let ids = res.data.map(item => item.id);
|
||||
// let url = tableURL + '?pid=' + ids.join(',');
|
||||
|
||||
// table.reload('lay-tableList', {
|
||||
// url: url,
|
||||
// where: { pid: ids.join(',') } // 传递必要的参数
|
||||
// });
|
||||
|
||||
// 模拟点击第一行的 radio
|
||||
setTimeout(function(){
|
||||
let firstRadio = $('tr.layui-table-body tbody tr').first().find('.layui-form-radio');
|
||||
firstRadio.addClass('layui-form-radioed');
|
||||
firstRadio.find('input[type="radio"]').prop('checked', true).trigger('change');
|
||||
}, 100); // 延迟以确保 DOM 渲染完成
|
||||
|
||||
console.log('bomid:'+bomid+',bomname:'+bomname);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 基础表格
|
||||
@@ -341,6 +406,7 @@
|
||||
,toolbar: '#tableButton'
|
||||
// ,defaultToolbar: ['filter', 'exports', 'print', 'search']
|
||||
,defaultToolbar: ['filter', 'print', 'search']
|
||||
, cellMinWidth: 80
|
||||
, page: true
|
||||
//, page: false
|
||||
, limit: 18
|
||||
@@ -355,7 +421,7 @@
|
||||
{ field: 'value', align: 'left', width: 100,title: '{:__("Value")}' },
|
||||
{ field: 'description', align: 'left', width: 200,title: '{:__("Description")}' },
|
||||
{ field: 'mpn', align: 'left', width: 150,title: '{:__("MPN")}' },
|
||||
{ field: 'mfgname', align: 'left', width: 150,title: '{:__("MFG")}' },
|
||||
{ field: 'mfg', align: 'left', width: 150,title: '{:__("MFG")}' },
|
||||
{ field: 'footprint', align: 'left', width: 150,title: '{:__("Footprint")}' },
|
||||
{ field: 'manufacture', align: 'left', width: 120,title: '{:__("Manufacture")}' },
|
||||
|
||||
@@ -364,11 +430,19 @@
|
||||
// {field: 'sort', align: 'center', width: 135, title: '{:__("排序号")}'},
|
||||
{ field: 'quantity', align: 'center', width: 100, title: '{:__("Quantity")}' },
|
||||
{ field: 'unit', align: 'center', width: 80, title: '{:__("Unit")}' },
|
||||
{ field: 'content', align: 'left', title: '{:__("备注")}' },
|
||||
{ field: 'content', align: 'left', title: '{:__("Remark")}' },
|
||||
// {field: 'create_time', align: 'center', width: 180,title: '{:__("创建时间")}'},
|
||||
{ align: 'center', toolbar: '#tableBar', width: 135, fixed:'right', title: '{:__("操作")}' },
|
||||
]]
|
||||
})
|
||||
|
||||
|
||||
// 定义处理选中行数据的函数
|
||||
function handleSelectedRow(row) {
|
||||
$('#editforms').find('.pid').attr('value', row.id);
|
||||
$('#editforms_bom').find('.pid').attr('value', row.id);
|
||||
}
|
||||
|
||||
// 表格选择行事件
|
||||
table.on('radio(lay-tableGroup)', function (obj) {
|
||||
let data = table.checkStatus('lay-tableGroup').data;
|
||||
@@ -385,8 +459,10 @@
|
||||
|
||||
// 获取最后点击
|
||||
if (obj.checked === true) {
|
||||
$('#editforms').find('.pid').attr('value', obj.data.id);
|
||||
$('#editforms_bom').find('.pid').attr('value', obj.data.id);
|
||||
handleSelectedRow(obj.data);
|
||||
bomname = obj.data.partnumber;
|
||||
bomid = obj.data.id;
|
||||
console.log('bomid:'+bomid+',bomname:'+bomname);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -400,30 +476,41 @@
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function isValidFilename(name) {
|
||||
// 正则匹配非法字符
|
||||
const invalidChars = /[\\/:*?"<>|]/;
|
||||
return !invalidChars.test(name);
|
||||
}
|
||||
|
||||
// 自定义导出功能
|
||||
function exportAllDataToExcel(){
|
||||
|
||||
// 获取当前的过滤条件(例如,pid)
|
||||
let selectedData = table.checkStatus('lay-tableGroup').data;
|
||||
let pid = selectedData.length ? selectedData[0].id : 0;
|
||||
// 异步获取所有数据(不分页)
|
||||
layer.msg('异步获取所有数据(不分页),超时限制:30s');
|
||||
// 显示加载层
|
||||
const loadingIndex = layer.load(1, { shade: [0.3, '#fff'] });
|
||||
|
||||
$.ajax({
|
||||
url: tableURL + "?pid=" + pid + "&export=1&limit=" +count ,// 后端需要根据 'export=1' 返回所有数据
|
||||
// method: 'GET',
|
||||
url: tableURL + "?pid=" + pid + "&export=1", // 后端需要根据 'export=1' 返回所有数据
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
timeout: 30000,
|
||||
success: function(res){
|
||||
if(res.code === 200){
|
||||
layer.msg('获取数据总数:'+ res.data.length);
|
||||
// layer.msg('获取数据总数: ' + res.data.length);
|
||||
let data = res.data;
|
||||
if(data.length === 0){
|
||||
layer.msg('没有数据可导出');
|
||||
layer.msg('没有数据可导出,BOM ID:'+bomid+'BOMname:'+bomname);
|
||||
// 解析完成后关闭加载层
|
||||
layer.close(loadingIndex);
|
||||
return;
|
||||
}
|
||||
// 转换数据为 SheetJS 格式
|
||||
layer.msg('转换数据为 SheetJS 格式');
|
||||
// let worksheetData = data.map(row => {
|
||||
// layer.msg('转换数据为 SheetJS 格式');
|
||||
let worksheetData = data.map(row => {
|
||||
return {
|
||||
'Item': row.item,
|
||||
@@ -433,34 +520,66 @@
|
||||
'Value': row.value,
|
||||
'Description': row.description,
|
||||
'MPN': row.mpn,
|
||||
'MFG': row.mfgname,
|
||||
'MFG': row.mfg,
|
||||
'Footprint': row.footprint,
|
||||
'Manufacture': row.manufacture,
|
||||
'Reference': row.reference,
|
||||
'Quantity': row.quantity,
|
||||
'Unit': row.unit,
|
||||
'备注': row.content,
|
||||
'Remark': row.content,
|
||||
// 添加其他需要导出的字段
|
||||
};
|
||||
});
|
||||
// 创建工作簿和工作表
|
||||
layer.msg('创建工作簿和工作表');
|
||||
// layer.msg('创建工作簿和工作表');
|
||||
let worksheet = XLSX.utils.json_to_sheet(worksheetData);
|
||||
let workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "BOM数据");
|
||||
// 生成 Excel 文件并下载,设置自定义文件名
|
||||
|
||||
const filename = "BOM_Export_" + new Date().toISOString().slice(0,10) + ".xlsx"; // 自定义文件名
|
||||
layer.msg('生成 Excel 文件并下载,设置自定义文件名:'+filename);
|
||||
XLSX.writeFile(workbook, filename);
|
||||
// 解析完成后关闭加载层
|
||||
layer.close(loadingIndex);
|
||||
|
||||
// 默认文件名
|
||||
const defaultFilename = bomname+" BOM_Export_" + new Date().toISOString().slice(0,10);
|
||||
|
||||
// 弹出提示框让用户输入文件名
|
||||
layer.prompt({
|
||||
title: '请输入导出文件名',
|
||||
formType: 0, // 0 = 输入框, 1 = 密码框, 2 = 多行文本
|
||||
value: defaultFilename,
|
||||
area: ['800px', '200px'] // 设置提示框的宽度和高度
|
||||
// area: ['50%', '30%'] // 宽度为50%,高度为30%
|
||||
}, function(value, index, elem){
|
||||
// 确保文件名不为空
|
||||
if(!value.trim()){
|
||||
layer.msg('文件名不能为空');
|
||||
return;
|
||||
}
|
||||
if(!isValidFilename(value.trim())){
|
||||
layer.msg('文件名包含非法字符');
|
||||
return;
|
||||
}
|
||||
// 确定文件名,添加 .xlsx 后缀
|
||||
const filename = value.trim() + ".xlsx";
|
||||
layer.msg('生成 Excel 文件并下载,文件名:' + filename);
|
||||
// 生成并下载 Excel 文件
|
||||
XLSX.writeFile(workbook, filename);
|
||||
layer.close(index); // 关闭提示框
|
||||
});
|
||||
} else {
|
||||
layer.msg('获取数据失败,状态码:' + res.code);
|
||||
// 解析完成后关闭加载层
|
||||
layer.close(loadingIndex);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
layer.msg('数据获取失败,请稍后重试: ' + error);
|
||||
// 解析完成后关闭加载层
|
||||
layer.close(loadingIndex);
|
||||
}
|
||||
|
||||
},
|
||||
error: function(res){
|
||||
layer.msg('数据获取失败,请稍后重试:'+res.msg);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 全局回调函数
|
||||
@@ -499,5 +618,295 @@
|
||||
return false;
|
||||
})
|
||||
}
|
||||
|
||||
let jsonData = [];
|
||||
|
||||
|
||||
// 定义字段映射对象
|
||||
const fieldMapping = {
|
||||
'Item': 'item',
|
||||
'Partnumber': 'partnumber',
|
||||
'Parttype': 'parttype',
|
||||
'Purchasecode': 'purchasecode',
|
||||
'Value': 'value',
|
||||
'Description': 'description',
|
||||
'MPN': 'mpn',
|
||||
'MFG': 'mfg',
|
||||
'Footprint': 'footprint',
|
||||
'Manufacture': 'manufacture',
|
||||
'Reference': 'reference',
|
||||
'Quantity': 'quantity',
|
||||
'Unit': 'unit',
|
||||
'Remark': 'content'
|
||||
// 添加其他需要映射的字段
|
||||
};
|
||||
|
||||
// 逆向转换函数
|
||||
function reverseTransform(data, mapping) {
|
||||
return data.map(row => {
|
||||
const originalRow = {};
|
||||
for (const [exportKey, originalKey] of Object.entries(mapping)) {
|
||||
originalRow[originalKey] = row[exportKey];
|
||||
}
|
||||
return originalRow;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//当用户点击上传按钮时,触发隐藏的文件输入:
|
||||
document.getElementById('uploadExcelBtn').addEventListener('click', function(){
|
||||
document.getElementById('excelFileInput').click();
|
||||
|
||||
});
|
||||
|
||||
document.getElementById('excelFileInput').addEventListener('change', function(event){
|
||||
|
||||
// 显示加载层
|
||||
const loadingIndex = layer.load(1, { shade: [0.3, '#fff'] });
|
||||
|
||||
const file = event.target.files[0];
|
||||
if(!file){
|
||||
layer.close(loadingIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e){
|
||||
try {
|
||||
const data = e.target.result;
|
||||
let workbook;
|
||||
try {
|
||||
workbook = XLSX.read(data, { type: 'binary' });
|
||||
} catch (error) {
|
||||
layer.msg('读取 Excel 文件失败,请检查文件格式。');
|
||||
return;
|
||||
}
|
||||
|
||||
// 假设导入第一个工作表
|
||||
const firstSheetName = workbook.SheetNames[0];
|
||||
const worksheet = workbook.Sheets[firstSheetName];
|
||||
|
||||
// 将工作表转换为 JSON
|
||||
jsonData = XLSX.utils.sheet_to_json(worksheet, { defval: '' });
|
||||
|
||||
if(jsonData.length === 0){
|
||||
layer.msg('Excel 文件中没有数据。');
|
||||
layer.close(loadingIndex);
|
||||
return;
|
||||
}
|
||||
// 在渲染之前进行验证
|
||||
if(!validateData(jsonData)){
|
||||
layer.close(loadingIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
layer.msg('Excel 文件数据读取成功,渲染数据表。');
|
||||
|
||||
// 渲染数据到表格
|
||||
renderDataTable(jsonData);
|
||||
|
||||
// 显示同步按钮
|
||||
document.getElementById('syncButton').style.display = 'inline-block';
|
||||
|
||||
} catch (error) {
|
||||
layer.msg('读取 Excel 文件失败,请检查文件格式。');
|
||||
} finally {
|
||||
// 解析完成后关闭加载层
|
||||
layer.close(loadingIndex);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
reader.onerror = function(){
|
||||
layer.msg('文件读取出现错误。');
|
||||
layer.close(loadingIndex);
|
||||
};
|
||||
|
||||
// 读取文件为二进制字符串
|
||||
reader.readAsBinaryString(file);
|
||||
|
||||
});
|
||||
|
||||
// 同步数据到数据库
|
||||
document.getElementById('syncButton').addEventListener('click', function(){
|
||||
if(jsonData.length === 0){
|
||||
layer.msg('没有可同步的数据。');
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示加载层
|
||||
const loadingIndex = layer.load(1, { shade: [0.3, '#fff'] });
|
||||
|
||||
let syncurl = "{:url('/PdmPartlist/sync')}?bomid="+bomid;
|
||||
|
||||
// fetch(syncurl
|
||||
// , {
|
||||
// method: 'POST'
|
||||
// ,headers: { 'Content-Type': 'application/json' }
|
||||
// ,body: JSON.stringify({ data: jsonData })
|
||||
// })
|
||||
// .then(response => response.json())
|
||||
// .then(data => {
|
||||
// layer.msg('dddd'.data);
|
||||
// if(data.success){
|
||||
// layer.msg('数据同步成功!');
|
||||
// } else {
|
||||
// layer.msg('同步失败: ' + data.message);
|
||||
// }
|
||||
// })
|
||||
// .catch(error => {
|
||||
// console.error('错误:', error);
|
||||
// layer.msg('同步过程中发生错误');
|
||||
// })
|
||||
// .finally(() => {
|
||||
// layer.close(loadingIndex);
|
||||
// });
|
||||
|
||||
// 应用逆向转换
|
||||
const originalData = reverseTransform(jsonData, fieldMapping);
|
||||
// console.log(originalData);
|
||||
console.log(JSON.stringify({ data: originalData }));
|
||||
|
||||
syncData(syncurl, originalData);
|
||||
|
||||
});
|
||||
|
||||
function syncData(url, jsonData, retries = 3, retryDelay = 1000) {
|
||||
let attempt = 0;
|
||||
let loadingIndex;
|
||||
|
||||
attempt++;
|
||||
// 显示加载指示器
|
||||
loadingIndex = layer.load(1, { shade: [0.1, '#fff'] });
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
// method: 'POST', // 使用 method 替代 type
|
||||
type: 'POST',
|
||||
dataType: 'json', // 预期服务器返回 JSON
|
||||
contentType: 'application/json', // 发送的数据为 JSON
|
||||
data: JSON.stringify({ data: jsonData }), // 序列化数据
|
||||
timeout: 30000, // 设置超时时间30秒
|
||||
})
|
||||
.done(function(res) {
|
||||
if (res.code === 200) {
|
||||
layer.msg('更新数据成功: ' + res.msg);
|
||||
} else {
|
||||
layer.msg('更新失败: ' + res.msg);
|
||||
}
|
||||
})
|
||||
.fail(function(jqXHR, textStatus, errorThrown) {
|
||||
if (textStatus === 'timeout') {
|
||||
if (attempt < retries) {
|
||||
layer.msg(`请求超时,正在进行第 ${attempt} 次重试...`);
|
||||
setTimeout(makeRequest, retryDelay);
|
||||
} else {
|
||||
layer.msg('请求超时,请稍后重试。');
|
||||
}
|
||||
} else if (jqXHR.status === 0) {
|
||||
layer.msg('网络错误,请检查您的网络连接。');
|
||||
} else if (jqXHR.status >= 500) {
|
||||
layer.msg('服务器错误,请稍后再试。');
|
||||
} else if (jqXHR.status === 404) {
|
||||
layer.msg('请求的资源未找到 (404)。');
|
||||
} else if (jqXHR.status === 401) {
|
||||
layer.msg('未授权,请登录。');
|
||||
// 可选:重定向到登录页
|
||||
window.location.href = '/login';
|
||||
} else {
|
||||
layer.msg('数据获取失败,请稍后重试: ' + errorThrown);
|
||||
}
|
||||
|
||||
// 可选:在控制台打印错误详情以便调试
|
||||
console.error('AJAX 错误:', jqXHR.responseText);
|
||||
})
|
||||
.always(function() {
|
||||
// 关闭加载指示器
|
||||
layer.close(loadingIndex);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function renderDataTable(data){
|
||||
// 提取表头(即对象的键)
|
||||
const tableHeaders = Object.keys(data[0]).map(key => ({
|
||||
field: key,
|
||||
title: key,
|
||||
sort: true, // 可根据需要设置是否可排序
|
||||
// 可以根据需要添加其他属性,如宽度、对齐方式等
|
||||
}));
|
||||
|
||||
// 渲染 LayUI 表格
|
||||
|
||||
// table.reloadData('lay-tableList', {
|
||||
// data: data
|
||||
// });
|
||||
|
||||
// 表格基本配置
|
||||
table.render({
|
||||
elem: '#dataTable',
|
||||
data: data,
|
||||
// cols: [tableHeaders],
|
||||
cols: [tableHeaders.map(header => ({
|
||||
field: header.field,
|
||||
title: header.title,
|
||||
width: 150, // 设置指定宽度,如150px
|
||||
// cellMinWidth:150,
|
||||
sort: header.sort
|
||||
}))],
|
||||
toolbar: '#toolbarDemo', // 绑定工具栏模板
|
||||
page: true, // 是否显示分页
|
||||
limit: 20, // 默认每页显示数量
|
||||
height: 'full-200', // 设置表格高度,根据需要调整
|
||||
id: 'dataTableReload'
|
||||
});
|
||||
|
||||
// 监听工具栏
|
||||
table.on('toolbar(dataTableFilter)', function(obj){
|
||||
|
||||
if(obj.event === 'export'){
|
||||
layer.msg('Excel dataTableFilter export');
|
||||
exportTableData(data); // 定义导出函数
|
||||
layer.msg('Excel dataTableFilter export end');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function validateData(data){
|
||||
// 示例:确保每行都有 "Item" 和 "Quantity" 字段
|
||||
for(let i = 0; i < data.length; i++){
|
||||
const row = data[i];
|
||||
if(!row.hasOwnProperty('Item') || !row.hasOwnProperty('Quantity')){
|
||||
layer.msg(`第 ${i+1} 行缺少必填字段。`);
|
||||
return false;
|
||||
}
|
||||
// 可以添加更多的验证逻辑,如数据类型、值范围等
|
||||
}
|
||||
layer.msg(`数据校验成功。`);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// (可选)导出表格数据为 Excel
|
||||
function exportTableData(data){
|
||||
layer.msg('Excel dataTableFilter --');
|
||||
// 使用 SheetJS 将数据转换为工作表
|
||||
const worksheet = XLSX.utils.json_to_sheet(data);
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "导出数据");
|
||||
|
||||
// 生成 Excel 文件并下载
|
||||
const filename = "导出数据_" + new Date().toISOString().slice(0,10) + ".xlsx";
|
||||
XLSX.writeFile(workbook, filename);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
@@ -50,20 +50,20 @@
|
||||
<div class="layui-col-md6 layui-grid-1" data-index="1">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">交期</label>
|
||||
<div class="layui-input-block"><input class="layui-input" name="ltime" placeholder="请输入"
|
||||
<div class="layui-input-block"><input class="layui-input" name="ltime" placeholder="请输入,留空默认置0."
|
||||
lay-verify="number" value="{$data.ltime}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">MOQ</label>
|
||||
<div class="layui-input-block"><input class="layui-input" name="moq" placeholder="请输入" lay-verify=""
|
||||
<div class="layui-input-block"><input class="layui-input" name="moq" placeholder="请输入,留空默认置0." lay-verify=""
|
||||
value="{$data.moq}"></div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">MPQ</label>
|
||||
<div class="layui-input-block"><input class="layui-input" name="mpq" placeholder="请输入" lay-verify=""
|
||||
<div class="layui-input-block"><input class="layui-input" name="mpq" placeholder="请输入,留空默认置0." lay-verify=""
|
||||
value="{$data.mpq}"></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -183,6 +183,16 @@
|
||||
<input type="checkbox" lay-filter="switchStatus" data-url="{:url('/PdmPurchasecode/status')}" value="{{d.id}}" lay-skin="switch" {{d.status==1?'checked':''}} />
|
||||
</script>
|
||||
|
||||
<!-- // 列表状态栏 -->
|
||||
<script type="text/html" id="columnEOL">
|
||||
<input type="checkbox" lay-filter="switchEOL" data-url="{:url('/PdmPurchasecode/statusEol')}" value="{{d.id}}" lay-skin="switch" {{d.eol==1?'checked':''}} />
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- // 列表工具栏 -->
|
||||
<script type="text/html" id="tableBar">
|
||||
<!--formBegin-->
|
||||
@@ -199,10 +209,15 @@
|
||||
|
||||
<include file="/public/footer" />
|
||||
<script>
|
||||
layui.use(['admin', 'table'], function () {
|
||||
layui.use(['jquery','admin','form', 'table','show'], function () {
|
||||
|
||||
var admin = layui.admin;
|
||||
var table = layui.table;
|
||||
var form = layui.form;
|
||||
let $ = layui.jquery;
|
||||
|
||||
// 自定义消息通知
|
||||
let show = layui.show;
|
||||
|
||||
/*
|
||||
* 初始化表格
|
||||
@@ -220,15 +235,43 @@
|
||||
{ field: 'id', align: 'center', sort: true, width: 80, title: 'ID' },
|
||||
{ field: 'purchasecode', width: 200,title: '{:__("采购编码")}' },
|
||||
{ field: 'mpn',width: 250, title: '{:__("物料描述")}' },
|
||||
{ field: 'preferencelevel', title: '{:__("优选等级")}' },
|
||||
{ field: 'eol', title: '{:__("是否EOL")}' },
|
||||
{ field: 'preferredlevel', title: '{:__("优选等级")}' },
|
||||
|
||||
{ field: 'moq', title: '{:__("MOQ")}' },
|
||||
{ field: 'mpq', title: '{:__("MPQ")}' },
|
||||
{ field: 'ltime', title: '{:__("交期")}' },
|
||||
{ field: 'eol', templet: '#columnEOL', title: '{:__("是否EOL")}' },
|
||||
{ field: 'status', templet: '#columnStatus', title: '{:__("状态")}' },
|
||||
{ align: 'center', toolbar: '#tableBar', width: 160, fixed: 'right', title: '{:__("操作")}' },
|
||||
]]
|
||||
})
|
||||
|
||||
|
||||
|
||||
form.on('switch(switchEOL)',function(obj) {
|
||||
// admin.setStorage('refreshClearTab',obj.elem.checked);
|
||||
|
||||
let that = $(this)
|
||||
, callback = {
|
||||
error: function (res) {
|
||||
$(obj.elem).prop('checked', !obj.elem.checked);
|
||||
show.error(res.msg);
|
||||
form.render('checkbox');
|
||||
}
|
||||
}
|
||||
, data = {
|
||||
id: $(this).attr('value'),
|
||||
eol: obj.elem.checked ? 1 : 0
|
||||
};
|
||||
|
||||
if ($('.bubble').length) {
|
||||
$('.bubble').removeClass('bubble');
|
||||
return false;
|
||||
}
|
||||
|
||||
admin.event.request(that, data, callback);
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user