feat(debug): 添加工厂下单表功能并实现数据保存导出

- 新增order.php工厂下单表页面
- 实现数据自动保存到localStorage功能
- 添加导出CSV功能
- 防止页面意外刷新丢失数据
This commit is contained in:
2025-06-24 16:01:10 +08:00
parent b21769ed20
commit 1f5db7473c
3 changed files with 2445 additions and 1 deletions
+1 -1
View File
@@ -83,7 +83,7 @@ body,input,td,select,div,li,ul,textarea,form {
$tmp=get_db_msg("select count(*) 'num' from ".$table_pre."kh where ka='y' or color_ka<>''");
if($tmp["num"]>0)
echo "&nbsp;&nbsp;<a href=\"../kh_ka.htm\" target=\"blank\">删除款明细</a>";
?>&nbsp;&nbsp;<a href="../database_export.htm" target="blank">数据库源文件</a>&nbsp;&nbsp;<a href="export_order_by_client.php" target="blank">单客户明细表</a>&nbsp;&nbsp;<a href="export_order_total.php" target="blank">明细总表</a>&nbsp;&nbsp;<a href="export_order_total_xz.php" target="blank">明细总表(鞋子版本)</a>&nbsp;&nbsp;<a href="export_order_total_s.php" target="blank">明细总表(尺码竖排)</a>&nbsp;&nbsp;<a href="dhd.php" target="blank">大货单</a>&nbsp;&nbsp;<a href="danmu_export.php?_a=export_do" target="blank">弹幕导出</a>&nbsp;&nbsp;图片资料(请复制attachments文件夹)</td>
?>&nbsp;&nbsp;<a href="../database_export.htm" target="blank">数据库源文件</a>&nbsp;&nbsp;<a href="export_order_by_client.php" target="blank">单客户明细表</a>&nbsp;&nbsp;<a href="export_order_total.php" target="blank">明细总表</a>&nbsp;&nbsp;<a href="export_order_total_xz.php" target="blank">明细总表(鞋子版本)</a>&nbsp;&nbsp;<a href="export_order_total_s.php" target="blank">明细总表(尺码竖排)</a>&nbsp;&nbsp;<a href="dhd.php" target="blank">大货单</a>&nbsp;&nbsp;<a href="order.php" target="blank">工厂下单表</a>&nbsp;&nbsp;<a href="danmu_export.php?_a=export_do" target="blank">弹幕导出</a>&nbsp;&nbsp;图片资料(请复制attachments文件夹)</td>
</tr>
<tr>
<td height="30" align="left" bgcolor="#f0f0f0">订单处理</td>
+545
View File
@@ -0,0 +1,545 @@
<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++;
}
File diff suppressed because it is too large Load Diff