ERPTurbo_Client/pc-wrapper.html
shenyifei fffb0c7269 feat(preview): 添加PC端预览页面和发货单预览功能
- 添加了PC端预览页面,支持多种设备模拟预览
- 在采购审核页面集成了发货单预览按钮
- 重构了发货表单组件,移除ref暴露机制
- 更新订单转换器以支持发货单数据转换
- 在发票上传页面添加供应商选择器组件
- 添加初始车次号相关字段到API类型定义
- 将发货表单中的Input组件替换为TextArea组件
- 修复了订单项ID匹配逻辑错误
2025-12-27 13:47:37 +08:00

752 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新发雷盛西瓜管理系统</title>
<style>
body {
margin: 0;
padding: 20px;
background: #f5f5f5;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.container {
max-width: 1600px;
margin: 0 auto;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px 30px;
}
.header h1 {
margin: 0 0 10px 0;
font-size: 24px;
}
.header p {
margin: 0;
opacity: 0.9;
}
.content-wrapper {
display: flex;
padding: 20px;
gap: 30px;
align-items: flex-start;
}
/* 左侧设备选择器 */
.device-selector {
display: flex;
flex-direction: column;
gap: 10px;
padding: 15px;
background: #f8f9fa;
border-radius: 12px;
flex-shrink: 0;
width: 140px;
height: fit-content;
position: sticky;
top: 20px;
}
.device-selector-label {
font-weight: 600;
color: #495057;
font-size: 13px;
text-align: center;
padding-bottom: 8px;
border-bottom: 2px solid #dee2e6;
margin-bottom: 5px;
}
.device-buttons {
display: flex;
flex-direction: column;
gap: 8px;
}
.device-btn {
padding: 10px 12px;
border: 2px solid #dee2e6;
background: white;
border-radius: 8px;
cursor: pointer;
font-size: 13px;
font-weight: 500;
color: #495057;
transition: all 0.2s;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
text-align: center;
}
.device-btn:hover {
border-color: #667eea;
color: #667eea;
transform: translateX(2px);
}
.device-btn.active {
background: #667eea;
border-color: #667eea;
color: white;
transform: translateX(4px);
}
.device-btn .device-icon {
font-size: 20px;
}
.device-btn span:last-child {
font-size: 12px;
}
/* 右侧内容区 */
.main-content {
flex: 1;
display: flex;
flex-wrap: wrap;
gap: 40px;
justify-content: center;
min-width: 0;
}
.frame-section {
flex: 1;
min-width: 400px;
max-width: 500px;
}
.qrcode-section {
flex: 1;
min-width: 300px;
max-width: 400px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
/* 通用设备框架样式 */
.frame-wrapper {
overflow: hidden;
position: relative;
background: white;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
margin: 0 auto;
transition: all 0.3s ease;
}
/* iPhone X */
.frame-wrapper.iphone-x {
width: 375px;
height: 812px;
border: 12px solid #333;
border-radius: 40px;
}
.frame-wrapper.iphone-x:before {
content: "";
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
height: 25px;
background: #333;
border-bottom-left-radius: 15px;
border-bottom-right-radius: 15px;
z-index: 10;
}
.frame-wrapper.iphone-x:after {
content: "";
position: absolute;
bottom: 8px;
left: 50%;
transform: translateX(-50%);
width: 134px;
height: 5px;
background: #333;
border-radius: 3px;
z-index: 10;
}
/* iPhone 14 Pro Max */
.frame-wrapper.iphone-14-pro {
width: 430px;
height: 932px;
border: 8px solid #1c1c1e;
border-radius: 55px;
}
.frame-wrapper.iphone-14-pro:before {
content: "";
position: absolute;
top: 12px;
left: 50%;
transform: translateX(-50%);
width: 140px;
height: 35px;
background: #1c1c1e;
border-radius: 20px;
z-index: 10;
}
.frame-wrapper.iphone-14-pro:after {
content: "";
position: absolute;
bottom: 8px;
left: 50%;
transform: translateX(-50%);
width: 134px;
height: 5px;
background: #333;
border-radius: 3px;
z-index: 10;
}
/* Samsung Galaxy S21 */
.frame-wrapper.galaxy-s21 {
width: 384px;
height: 854px;
border: 10px solid #1a1a1a;
border-radius: 32px;
}
.frame-wrapper.galaxy-s21:before {
content: "";
position: absolute;
top: 8px;
left: 50%;
transform: translateX(-50%);
width: 12px;
height: 12px;
background: #1a1a1a;
border-radius: 50%;
z-index: 10;
}
/* iPad */
.frame-wrapper.ipad {
width: 768px;
height: 1024px;
border: 18px solid #b4b4b4;
border-radius: 24px;
}
.frame-wrapper.ipad:before {
content: "";
position: absolute;
top: 18px;
left: 50%;
transform: translateX(-50%);
width: 12px;
height: 12px;
background: #333;
border-radius: 50%;
z-index: 10;
}
/* iPad Pro 11 */
.frame-wrapper.ipad-pro {
width: 834px;
height: 1194px;
border: 14px solid #b4b4b4;
border-radius: 18px;
}
/* Android 通用 */
.frame-wrapper.android {
width: 360px;
height: 760px;
border: 10px solid #2c2c2c;
border-radius: 24px;
}
.frame-wrapper.android:before {
content: "";
position: absolute;
top: 10px;
left: 50%;
transform: translateX(-50%);
width: 60px;
height: 8px;
background: #2c2c2c;
border-radius: 4px;
z-index: 10;
}
/* 屏幕容器 */
.frame-wrapper .screen-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
z-index: 1;
}
.frame-wrapper.iphone-x .screen-container,
.frame-wrapper.iphone-14-pro .screen-container,
.frame-wrapper.galaxy-s21 .screen-container,
.frame-wrapper.android .screen-container {
border-radius: 28px;
}
.frame-wrapper.ipad .screen-container,
.frame-wrapper.ipad-pro .screen-container {
border-radius: 12px;
}
iframe {
width: 100%;
height: calc(100% - 84px); /* 减去TabBar高度 */
border: none;
}
/* 顶部TabBar */
.tabbar {
height: 50px;
background: rgba(248, 248, 248, 0.95);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
padding: 0 16px;
z-index: 20;
}
.tabbar-time {
font-size: 15px;
font-weight: 600;
color: #000;
margin-right: auto;
}
.tabbar-icons {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
}
.tabbar-icon {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.tabbar-icon svg {
width: 100%;
height: 100%;
fill: #000;
}
/* 底部安全区域占位 */
.safe-area-bottom {
height: 34px;
background: transparent;
z-index: 5;
}
.qrcode-container {
background: white;
padding: 25px;
border-radius: 16px;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
text-align: center;
margin-bottom: 25px;
border: 1px solid #eee;
}
#qrcode {
width: 200px;
height: 200px;
margin: 15px auto;
padding: 10px;
background: white;
border-radius: 8px;
}
.qrcode-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 10px;
}
.qrcode-desc {
color: #666;
font-size: 14px;
line-height: 1.5;
margin-bottom: 20px;
max-width: 300px;
}
.url-display {
background: #f8f9fa;
padding: 12px 15px;
border-radius: 8px;
font-size: 13px;
color: #555;
word-break: break-all;
margin-top: 15px;
border: 1px solid #e9ecef;
max-width: 300px;
}
.mobile-tips {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
margin-top: 15px;
color: #666;
font-size: 14px;
}
.mobile-tips svg {
width: 20px;
height: 20px;
fill: #667eea;
}
.tips {
padding: 20px;
text-align: center;
color: #666;
font-size: 14px;
background: #f8f9fa;
border-top: 1px solid #eee;
}
@media (max-width: 1100px) {
.content-wrapper {
flex-direction: column;
}
.device-selector {
width: 100%;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
position: static;
}
.device-buttons {
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
.device-btn {
flex-direction: row;
padding: 8px 16px;
}
.device-btn:hover {
transform: translateY(-1px);
}
.device-btn.active {
transform: translateY(-1px);
}
.device-btn .device-icon {
font-size: 16px;
}
.device-btn span:last-child {
font-size: 14px;
}
.main-content {
flex-direction: column;
}
}
@media (max-width: 768px) {
.frame-section, .qrcode-section {
min-width: 100%;
max-width: 100%;
}
.qrcode-section {
order: -1;
}
}
/* 设备信息提示 */
.device-info {
text-align: center;
padding: 10px;
color: #666;
font-size: 13px;
background: #f8f9fa;
border-radius: 6px;
margin-top: 15px;
}
.device-info .device-size {
font-weight: 600;
color: #495057;
}
</style>
<script src="qrcode.min.js"></script>
</head>
<body>
<div class="container">
<div class="content-wrapper">
<!-- 左侧设备选择器 -->
<div class="device-selector">
<span class="device-selector-label">📱 设备</span>
<div class="device-buttons">
<button class="device-btn active" data-device="iphone-x">
<span class="device-icon">📱</span>
<span>iPhone X</span>
</button>
<button class="device-btn" data-device="iphone-14-pro">
<span class="device-icon">📲</span>
<span>iPhone 14 Pro</span>
</button>
<button class="device-btn" data-device="galaxy-s21">
<span class="device-icon">🤖</span>
<span>Galaxy S21</span>
</button>
<button class="device-btn" data-device="android">
<span class="device-icon">📱</span>
<span>Android</span>
</button>
</div>
</div>
<!-- 右侧内容区 -->
<div class="main-content">
<div class="frame-section">
<div class="frame-wrapper iphone-x" id="device-frame">
<div class="screen-container">
<!-- 顶部TabBar -->
<div class="tabbar">
<div class="tabbar-time" id="current-time">9:41</div>
</div>
<!-- iframe内容区域 -->
<iframe id="mobile-frame" src="/"
title="移动端页面"></iframe>
<!-- 底部安全区域占位 -->
<div class="safe-area-bottom"></div>
</div>
</div>
<div class="device-info">
当前设备: <span class="device-size" id="device-name">iPhone X (375×812)</span>
</div>
</div>
<div class="qrcode-section">
<div class="qrcode-container">
<div class="qrcode-title">手机扫码预览</div>
<div class="qrcode-desc">
使用手机扫描下方二维码,可直接在手机上访问此页面,获得真实的移动端体验
</div>
<div id="qrcode"></div>
<div class="url-display" id="current-url">
<!-- URL 将在这里显示 -->
</div>
<div class="mobile-tips">
<svg viewBox="0 0 24 24">
<path
d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/>
</svg>
<span>建议使用手机扫描体验最佳效果</span>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// 设备配置信息
const deviceConfigs = {
'iphone-x': {
name: 'iPhone X',
size: '375×812',
className: 'iphone-x'
},
'iphone-14-pro': {
name: 'iPhone 14 Pro Max',
size: '430×932',
className: 'iphone-14-pro'
},
'galaxy-s21': {
name: 'Samsung Galaxy S21',
size: '384×854',
className: 'galaxy-s21'
},
'android': {
name: 'Android (通用)',
size: '360×760',
className: 'android'
},
};
// 当前选择的设备
let currentDevice = 'iphone-x';
// 切换设备
function switchDevice(deviceId) {
const frame = document.getElementById('device-frame');
const deviceName = document.getElementById('device-name');
const config = deviceConfigs[deviceId];
// 移除所有设备类名
frame.className = 'frame-wrapper';
// 添加新设备类名
frame.classList.add(config.className);
// 更新设备信息显示
deviceName.textContent = `${config.name} (${config.size})`;
// 保存到localStorage
localStorage.setItem('previewDevice', deviceId);
// 更新按钮状态
document.querySelectorAll('.device-btn').forEach(btn => {
btn.classList.remove('active');
if (btn.dataset.device === deviceId) {
btn.classList.add('active');
}
});
currentDevice = deviceId;
}
// 初始化设备选择器
function initDeviceSelector() {
// 从localStorage读取上次选择的设备
const savedDevice = localStorage.getItem('previewDevice');
if (savedDevice && deviceConfigs[savedDevice]) {
switchDevice(savedDevice);
}
// 绑定按钮点击事件
document.querySelectorAll('.device-btn').forEach(btn => {
btn.addEventListener('click', function() {
const deviceId = this.dataset.device;
switchDevice(deviceId);
});
});
}
// 更新当前时间
function updateCurrentTime() {
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
document.getElementById('current-time').textContent = `${hours}:${minutes}`;
}
// 获取当前页面URL
function getCurrentUrl() {
// 如果 $request_uri 是占位符则使用实际URL
let iframeSrc = document.getElementById('mobile-frame').src;
if (iframeSrc.includes('$request_uri')) {
// 使用当前页面URL去掉预览页面的路径
let currentUrl = window.location.href;
// 移除预览页面的查询参数或路径
return currentUrl.split('?')[0].replace(/\/preview\/?$/, '');
}
return iframeSrc;
}
// 生成二维码
function generateQRCode() {
const url = getCurrentUrl();
const qrcodeElement = document.getElementById('qrcode');
const urlDisplay = document.getElementById('current-url');
// 显示URL
urlDisplay.textContent = url.length > 50 ? url.substring(0, 50) + '...' : url;
// 清空之前的二维码
qrcodeElement.innerHTML = '';
// 生成当前页面的二维码
new QRCode(document.getElementById('qrcode'), {
text: window.location.href,
width: 200,
height: 200,
margin: 1,
color: {
dark: '#333333',
light: '#ffffff'
}
});
}
// 处理iframe内部链接
var iframe = document.getElementById("mobile-frame");
iframe.onload = function () {
try {
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
var links = iframeDoc.querySelectorAll("a");
links.forEach(function (link) {
link.onclick = function (e) {
e.preventDefault();
var href = this.getAttribute("href");
if (href && !href.match(/^(http|https|#|javascript:)/)) {
iframe.src = href;
// 更新二维码
setTimeout(generateQRCode, 100);
}
};
});
} catch (e) {
// 跨域限制
}
// 每次iframe加载后更新二维码
generateQRCode();
};
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', function () {
// 初始化设备选择器
initDeviceSelector();
// 更新时间
updateCurrentTime();
setInterval(updateCurrentTime, 60000); // 每分钟更新一次
// 生成二维码
generateQRCode();
});
// 监听URL变化如果使用History API
window.addEventListener('popstate', generateQRCode);
</script>
</body>
</html>