1f5db7473c
- 新增order.php工厂下单表页面 - 实现数据自动保存到localStorage功能 - 添加导出CSV功能 - 防止页面意外刷新丢失数据
546 lines
18 KiB
PHP
546 lines
18 KiB
PHP
|
|
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
|
|
<script>
|
|
// 自动保存功能
|
|
$(document).ready(function() {
|
|
// 确保按钮不存在时再添加
|
|
if ($('#saveData').length === 0) {
|
|
$('body').append('<button id="saveData" style="position:fixed;bottom:80px;right:120px;z-index:9999;padding:8px 16px;background-color:#4CAF50;color:white;border:none;border-radius:4px;font-size:14px;">保存数据</button>');
|
|
}
|
|
if ($('#clearSavedData').length === 0) {
|
|
$('body').append('<button id="clearSavedData" style="position:fixed;bottom:20px;right:120px;z-index:9999;padding:8px 16px;background-color:#f44336;color:white;border:none;border-radius:4px;font-size:14px;">清除保存的数据</button>');
|
|
}
|
|
// 确保导出CSV按钮不存在时再添加
|
|
if ($('#exportCSVButton').length === 0) {
|
|
$('body').append('<button id="exportCSVButton" style="position:fixed;bottom:140px;right:120px;z-index:9999;padding:8px 16px;background-color:#467FE6;color:white;border:none;border-radius:4px;font-size:14px;">导出CSV</button>');
|
|
}
|
|
// 导出CSV按钮点击事件
|
|
$('#exportCSVButton').click(function() {
|
|
exportToCSV();
|
|
downloadCSV(csv);
|
|
}
|
|
);
|
|
|
|
|
|
// 防重复点击标志
|
|
let isSaving = false;
|
|
let isClearing = false;
|
|
|
|
// 封装获取所有需要保存数据的函数
|
|
function getAllDataToSave() {
|
|
const itemNo = '<?php echo htmlspecialchars($item["no"]); ?>';
|
|
const counter = '<?php echo $counter; ?>';
|
|
const allData = {};
|
|
|
|
// 获取 r2 和 r9 行以及其他输入框
|
|
const r2Rows = document.querySelectorAll('tr[id^="r2_"]');
|
|
const r9Rows = document.querySelectorAll('tr[id^="r9_"]');
|
|
const otherInputs = document.querySelectorAll('tr:not([id^="r2_"]):not([id^="r9_"]) input[type="number"]');
|
|
|
|
// 保存 r2 行数据
|
|
r2Rows.forEach(row => {
|
|
const rowId = row.id.split('_')[1];
|
|
const inputs = row.querySelectorAll('input[type="number"]');
|
|
const rowData = {};
|
|
|
|
inputs.forEach(input => {
|
|
rowData[input.name] = input.value;
|
|
});
|
|
|
|
allData[`r2_row_${rowId}`] = rowData;
|
|
});
|
|
|
|
// 保存 r9 行数据
|
|
r9Rows.forEach(row => {
|
|
const rowId = row.id.split('_')[1];
|
|
const inputs = row.querySelectorAll('input[type="number"]');
|
|
const rowData = {};
|
|
|
|
inputs.forEach(input => {
|
|
rowData[input.name] = input.value;
|
|
});
|
|
|
|
allData[`r9_row_${rowId}`] = rowData;
|
|
});
|
|
|
|
// 保存其他独立输入框数据
|
|
const otherData = {};
|
|
otherInputs.forEach(input => {
|
|
otherData[input.name] = input.value;
|
|
});
|
|
allData['other_inputs'] = otherData;
|
|
|
|
// 保存货号作为数据标识
|
|
allData['item_no'] = itemNo;
|
|
|
|
return { allData, storageKey: `order_data_${itemNo}_${counter}` };
|
|
}
|
|
|
|
// 修改后的保存数据按钮点击事件
|
|
$('#saveData').click(function() {
|
|
if (isSaving) return;
|
|
isSaving = true;
|
|
|
|
const { allData, storageKey } = getAllDataToSave();
|
|
|
|
try {
|
|
localStorage.setItem(storageKey, JSON.stringify(allData));
|
|
alert('数据已保存!');
|
|
} catch (e) {
|
|
alert('保存数据时出错: ' + e.message);
|
|
} finally {
|
|
isSaving = false;
|
|
}
|
|
});
|
|
|
|
// 封装恢复数据的函数
|
|
function restoreData() {
|
|
const itemNo = '<?php echo htmlspecialchars($item["no"]); ?>';
|
|
const counter = '<?php echo $counter; ?>';
|
|
const storageKey = `order_data_${itemNo}_${counter}`;
|
|
|
|
const savedData = localStorage.getItem(storageKey);
|
|
if (savedData) {
|
|
try {
|
|
const allData = JSON.parse(savedData);
|
|
|
|
// 检查是否是当前货号的数据
|
|
if (allData.item_no === itemNo) {
|
|
// 恢复 r2 行数据
|
|
Object.keys(allData).forEach(key => {
|
|
if (key.startsWith('r2_row_')) {
|
|
const rowId = key.split('_')[2];
|
|
const rowData = allData[key];
|
|
|
|
Object.keys(rowData).forEach(inputName => {
|
|
const input = document.querySelector(`#r2_${rowId} input[name="${inputName}"]`);
|
|
if (input) {
|
|
input.value = rowData[inputName];
|
|
const event = new Event('change');
|
|
input.dispatchEvent(event);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// 恢复 r9 行数据
|
|
Object.keys(allData).forEach(key => {
|
|
if (key.startsWith('r9_row_')) {
|
|
const rowId = key.split('_')[2];
|
|
const rowData = allData[key];
|
|
|
|
Object.keys(rowData).forEach(inputName => {
|
|
const input = document.querySelector(`#r9_${rowId} input[name="${inputName}"]`);
|
|
if (input) {
|
|
input.value = rowData[inputName];
|
|
const event = new Event('change');
|
|
input.dispatchEvent(event);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// 恢复其他独立输入框数据
|
|
if (allData.other_inputs) {
|
|
Object.keys(allData.other_inputs).forEach(inputName => {
|
|
const input = document.querySelector(`input[name="${inputName}"]`);
|
|
if (input) {
|
|
input.value = allData.other_inputs[inputName];
|
|
const event = new Event('change');
|
|
input.dispatchEvent(event);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
} catch (e) {
|
|
alert('恢复数据时出错: ' + e.message);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 页面加载时恢复数据
|
|
restoreData();
|
|
|
|
// 清除保存的数据按钮
|
|
$('#clearSavedData').click(function() {
|
|
if (isClearing) return;
|
|
isClearing = true;
|
|
|
|
try {
|
|
const { storageKey } = getAllDataToSave();
|
|
localStorage.removeItem(storageKey);
|
|
// 清除输入框独立保存的数据
|
|
const inputs = document.querySelectorAll('input[type="number"]');
|
|
inputs.forEach(input => {
|
|
const key = 'order_data_' + '<?php echo htmlspecialchars($item["no"]); ?>_' + input.name + '_' + '<?php echo $counter; ?>';
|
|
localStorage.removeItem(key);
|
|
});
|
|
alert('已清除所有保存的数据!');
|
|
location.reload();
|
|
} catch (e) {
|
|
alert('清除数据时出错: ' + e.message);
|
|
} finally {
|
|
isClearing = false;
|
|
}
|
|
});
|
|
|
|
// 输入框独立保存功能
|
|
$('input[type="number"]').on('input', function() {
|
|
const key = 'order_data_' + '<?php echo htmlspecialchars($item["no"]); ?>_' + $(this).attr('name') + '_' + '<?php echo $counter; ?>';
|
|
try {
|
|
localStorage.setItem(key, $(this).val());
|
|
} catch (e) {
|
|
alert('保存输入框数据时出错: ' + e.message);
|
|
}
|
|
});
|
|
|
|
// 立即执行函数确保最早恢复数据(复用恢复数据函数)
|
|
restoreData();
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 禁止F5刷新
|
|
$(document).ready(function() {
|
|
$(document).keydown(function(e) {
|
|
if (e.keyCode === 116) { // F5键的keyCode是116
|
|
e.preventDefault();
|
|
alert('当前页面禁止刷新,请使用保存按钮保存数据');
|
|
return false;
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
|
|
function exportToCSV() {
|
|
// 获取所有以 tb_ 开头的表格元素,这样就能处理多个货号对应的表格
|
|
const tables = document.querySelectorAll('[id^="tb_"]');
|
|
let allCSV = [];
|
|
|
|
// 遍历每个表格
|
|
tables.forEach((table) => {
|
|
let csv = [];
|
|
const rows = table.rows;
|
|
// 用于跟踪已经处理过的合并单元格
|
|
const mergedCells = new Array(rows.length).fill(null).map(() => []);
|
|
|
|
// 计算表格的最大列数
|
|
let maxColumns = 0;
|
|
for (let i = 0; i < rows.length; i++) {
|
|
let currentColumns = 0;
|
|
const row = rows[i];
|
|
for (let j = 0; j < row.cells.length; j++) {
|
|
const cell = row.cells[j];
|
|
currentColumns += cell.colSpan || 1;
|
|
}
|
|
if (currentColumns > maxColumns) {
|
|
maxColumns = currentColumns;
|
|
}
|
|
}
|
|
|
|
// 遍历所有行
|
|
for (let i = 0; i < rows.length; i++) {
|
|
const row = rows[i];
|
|
let rowData = new Array(maxColumns).fill('""'); // 初始化行数据数组,填充空值
|
|
let colIndex = 0; // 当前处理的列索引
|
|
|
|
// 遍历当前行的所有单元格
|
|
for (let j = 0; j < row.cells.length; j++) {
|
|
const col = row.cells[j];
|
|
const colSpan = col.colSpan || 1;
|
|
const rowSpan = col.rowSpan || 1;
|
|
|
|
// 找到第一个未处理的列索引
|
|
while (colIndex < maxColumns && mergedCells[i][colIndex]) {
|
|
colIndex++;
|
|
}
|
|
|
|
// 处理单元格内容
|
|
let content = "";
|
|
const input = col.querySelector('input[type="number"]');
|
|
if (input) {
|
|
// 如果单元格中有输入框,获取输入框的值
|
|
content = input.value;
|
|
} else {
|
|
// 尝试获取图片信息
|
|
const img = col.querySelector('img');
|
|
if (img) {
|
|
// 检测是否为 WPS 环境,这里简单假设无法准确检测,所以同时提供两种格式
|
|
// Office 不支持函数插入图片,只能导出图片路径文本;WPS 支持 IMAGE 函数
|
|
// 为了兼容两种情况,导出时将图片路径和 WPS 函数格式都写入单元格
|
|
content = `${img.src}`;
|
|
} else {
|
|
// 否则获取单元格的文本内容
|
|
content = col.innerText;
|
|
}
|
|
}
|
|
|
|
// 清理数据中的逗号、换行符和双引号
|
|
content = '"' + content.replace(/"/g, '""') + '"';
|
|
|
|
// 填充合并单元格的数据
|
|
for (let k = 0; k < colSpan; k++) {
|
|
if (colIndex + k < maxColumns) {
|
|
if (k === 0) {
|
|
rowData[colIndex + k] = content;
|
|
} else {
|
|
rowData[colIndex + k] = '""';
|
|
}
|
|
}
|
|
}
|
|
|
|
// 标记合并单元格的范围为已处理
|
|
for (let r = 0; r < rowSpan; r++) {
|
|
for (let c = 0; c < colSpan; c++) {
|
|
if (i + r < rows.length && colIndex + c < maxColumns) {
|
|
mergedCells[i + r][colIndex + c] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
colIndex += colSpan; // 跳过合并的列
|
|
}
|
|
|
|
csv.push(rowData.join(","));
|
|
}
|
|
|
|
// 将当前表格的 CSV 数据添加到总的 CSV 数据中,用空行分隔不同表格的数据
|
|
allCSV = allCSV.concat(csv, [""]);
|
|
});
|
|
|
|
// 把 allCSV 赋值给原来的 csv 变量,以便后续下载逻辑不需要修改
|
|
csv = allCSV;
|
|
|
|
|
|
|
|
}
|
|
|
|
// 此函数用于下载 CSV 文件,接收 CSV 数据数组作为参数
|
|
function downloadCSV(csv) {
|
|
// 为避免多次触发下载,添加一个标志位
|
|
let isDownloading = false;
|
|
// 确保不在循环内触发多次下载,增强标志位的控制逻辑
|
|
if (!isDownloading) {
|
|
isDownloading = true;
|
|
const csvContent = "data:text/csv;charset=utf-8," + csv.join("\n");
|
|
const encodedUri = encodeURI(csvContent);
|
|
const link = document.createElement("a");
|
|
link.setAttribute("href", encodedUri);
|
|
// 获取当前日期时间
|
|
const now = new Date();
|
|
const year = now.getFullYear();
|
|
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
const day = String(now.getDate()).padStart(2, '0');
|
|
const hours = String(now.getHours()).padStart(2, '0');
|
|
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
const seconds = String(now.getSeconds()).padStart(2, '0');
|
|
const dateTimeString = `${year}${month}${day}${hours}${minutes}${seconds}`;
|
|
// 设置下载文件名为下单表加当前日期时间.csv
|
|
link.setAttribute("download", `下单表${dateTimeString}.csv`);
|
|
document.body.appendChild(link);
|
|
|
|
// 封装模拟点击事件为一个函数,使用 promise 确保下载完成后再重置标志位
|
|
function simulateClick() {
|
|
return new Promise((resolve) => {
|
|
// 为避免重复触发点击事件,在点击前移除之前可能存在的点击事件监听器
|
|
link.removeEventListener('click', link.clickHandler);
|
|
link.clickHandler = () => {
|
|
// 等待 1 秒确保下载触发
|
|
setTimeout(() => {
|
|
resolve();
|
|
}, 1000);
|
|
};
|
|
link.addEventListener('click', link.clickHandler);
|
|
link.click();
|
|
});
|
|
}
|
|
|
|
// 执行模拟点击并处理后续操作
|
|
simulateClick().then(() => {
|
|
document.body.removeChild(link);
|
|
// 下载完成后重置标志位
|
|
isDownloading = false;
|
|
}).catch((error) => {
|
|
console.error('下载CSV文件时出错:', error);
|
|
// 出错时也重置标志位,避免后续无法下载
|
|
isDownloading = false;
|
|
});
|
|
}
|
|
};
|
|
|
|
</script>
|
|
<script language="javascript" type="text/javascript"></script>
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<style>
|
|
.x69
|
|
{
|
|
text-align:center;
|
|
vertical-align:middle;
|
|
white-space:nowrap;
|
|
background:auto;
|
|
font-size:11pt;
|
|
font-weight:700;
|
|
font-style:normal;
|
|
font-family:"宋体","sans-serif";
|
|
border-top:1px solid windowtext;
|
|
border-right:1px solid windowtext;
|
|
border-bottom:1px solid windowtext;
|
|
border-left:1px solid windowtext;
|
|
}
|
|
.x70
|
|
{
|
|
text-align:center;
|
|
vertical-align:middle;
|
|
white-space:nowrap;
|
|
background:auto;
|
|
font-size:11pt;
|
|
font-weight:700;
|
|
font-style:normal;
|
|
font-family:"宋体","sans-serif";
|
|
border-top:1px solid windowtext;
|
|
border-right:1px solid windowtext;
|
|
border-bottom:1px solid windowtext;
|
|
border-left:1px solid windowtext;
|
|
}
|
|
.x71
|
|
{
|
|
text-align:center;
|
|
vertical-align:middle;
|
|
white-space:nowrap;
|
|
background:auto;
|
|
color:#000000;
|
|
font-size:11pt;
|
|
font-weight:400;
|
|
font-style:normal;
|
|
font-family:"宋体","sans-serif";
|
|
border-top:1px solid windowtext;
|
|
border-right:1px solid windowtext;
|
|
border-bottom:1px solid windowtext;
|
|
border-left:1px solid windowtext;
|
|
}
|
|
.x72
|
|
{
|
|
text-align:general;
|
|
vertical-align:middle;
|
|
white-space:nowrap;
|
|
background:auto;
|
|
font-size:12pt;
|
|
font-weight:400;
|
|
font-style:normal;
|
|
font-family:"宋体","sans-serif";
|
|
}
|
|
-->
|
|
</style> <?php
|
|
|
|
function get_kh_picture_dhd($no,$main_pic,$color){
|
|
$pic="";
|
|
if(trim($main_pic)){
|
|
$pic="../../attachments/design/mini/".$no."_".$main_pic.".jpg";
|
|
}
|
|
if(!is_file($pic)){
|
|
$pic="../../attachments/design/mini/".$no.".jpg";
|
|
}
|
|
if(!is_file($pic)){
|
|
$tmp=explode(",",$color);
|
|
for($j=0;$j<count($tmp);$j++){
|
|
$pic="../../attachments/design/mini/".$no."_".$tmp[$j].".jpg";
|
|
if(is_file($pic))
|
|
break;
|
|
}
|
|
}
|
|
if(!is_file($pic)){
|
|
$pic="../images/no_pic_80.gif";
|
|
}
|
|
return $pic;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 数据库连接配置
|
|
require "../config.php";
|
|
include "../../tmpl/config.php";
|
|
require THIS_FILE_ROOT."/include/function.php";
|
|
require THIS_FILE_ROOT."/include/db_mysql.php";
|
|
error_reporting(E_ERROR | E_WARNING | E_PARSE);
|
|
$msg="";
|
|
$db=new DB_Sql;
|
|
$db->connect($dbhost,$dbuser,$dbpw,$dbname,"p");
|
|
$sys_size_num=get_max_size_num();
|
|
|
|
error_reporting(E_ERROR | E_WARNING | E_PARSE);
|
|
|
|
|
|
// 查询web_order表中的订单款号和颜色
|
|
$sql = "SELECT DISTINCT no, color FROM web_order ORDER BY no";
|
|
$result = $db->query($sql);
|
|
$order_items = array();
|
|
while($row = $db->fetch_array($result)) {
|
|
$order_items[] = $row;
|
|
}
|
|
|
|
|
|
// 在表格中显示查询结果
|
|
$counter = 1;
|
|
foreach($order_items as $item) {
|
|
// 查询当前货号的店铺定量
|
|
$shop_order_row = array();
|
|
$shop_order_query = "SELECT no,
|
|
SUM(num_1) as c32,
|
|
SUM(num_2) as c33,
|
|
SUM(num_3) as c34,
|
|
SUM(num_4) as c35,
|
|
SUM(num_5) as c36,
|
|
SUM(num_6) as c37,
|
|
SUM(num_7) as c38,
|
|
SUM(num_8) as c39,
|
|
SUM(num_9) as c40,
|
|
SUM(num_10) as c41,
|
|
SUM(num) as num
|
|
FROM web_order
|
|
WHERE uid IN (SELECT id FROM web_client WHERE dpsx='店铺')
|
|
AND no = '{$item['no']}'
|
|
GROUP BY no";
|
|
|
|
$shop_result = $db->query($shop_order_query);
|
|
if($db->num_rows($shop_result) > 0) {
|
|
$shop_order_row = $db->fetch_array($shop_result);
|
|
}
|
|
// 查询当前货号的批发定量
|
|
$pf_order_row = array();
|
|
$pf_order_query = "SELECT no,
|
|
SUM(num_1) as c32,
|
|
SUM(num_2) as c33,
|
|
SUM(num_3) as c34,
|
|
SUM(num_4) as c35,
|
|
SUM(num_5) as c36,
|
|
SUM(num_6) as c37,
|
|
SUM(num_7) as c38,
|
|
SUM(num_8) as c39,
|
|
SUM(num_9) as c40,
|
|
SUM(num_10) as c41,
|
|
SUM(num) as num
|
|
FROM web_order
|
|
WHERE uid IN (SELECT id FROM web_client WHERE dpsx='批发')
|
|
AND no = '{$item['no']}'
|
|
GROUP BY no";
|
|
|
|
$pf_result = $db->query($pf_order_query);
|
|
if($db->num_rows($pf_result) > 0) {
|
|
$pf_order_row = $db->fetch_array($pf_result);
|
|
}
|
|
|
|
// 包含orderlist.php文件并传递当前item数据
|
|
include 'orderlist.php';
|
|
$counter++;
|
|
}
|
|
|
|
|
|
|