front/index.html
zzh f1d219ae48 feat: ship billing UI for additional services, conditions, and fee insights
Add product/channel billing condition editors, place-order additional services, billing simulator, forecast-to-inbound fee delta and margin warnings, insurance-aware claim tips, OMS preset dict seeds, and related AI skills/system pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-01 18:09:22 +08:00

365 lines
12 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 lang="zh-CN" class="app-booting">
<head>
<meta charset="UTF-8" />
<script>
/* 首屏前判定 H5/语言,避免 body 绘出后再改「IDE」→「IDE客户中心」造成字号/布局抖 */
(function () {
var path = location.pathname || '';
var isH5 =
path === '/h5' ||
path.indexOf('/h5/') === 0 ||
path.indexOf('/wechat/') === 0 ||
path === '/track/query' ||
path.indexOf('/track/query/') === 0;
var isEn = false;
try {
var locale =
localStorage.getItem('arco-locale') || localStorage.getItem('locale') || '';
isEn = /^en/i.test(locale);
} catch (e) {}
var root = document.documentElement;
if (isH5) root.classList.add('app-boot-h5');
if (isEn) root.classList.add('app-boot-en');
try {
document.title = isH5
? isEn
? 'IDE Customer Center'
: 'IDE客户中心'
: 'IDE I Faster & Simpler';
} catch (e2) {}
})();
</script>
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="preload" href="/boot-logo.png" as="image" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
/>
<title>IDE I Faster &amp; Simpler</title>
<link rel="stylesheet" type="text/css" media="print" href="/print-lock.css" />
<!-- DNS 预解析,加速资源加载 -->
<link rel="dns-prefetch" href="//43.139.210.35" />
<!-- 预连接,提前建立连接 -->
<link rel="preconnect" href="//43.139.210.35" crossorigin />
<style>
/*
* 右→左偏移根因:Vue 挂载后页面出现纵向滚动条,视口变窄,
* fixed 居中点左移约半个滚动条宽度。boot 期间锁滚动 + 常驻 gutter。
*/
html {
scrollbar-gutter: stable;
background: #f0f3f4;
}
html.app-booting,
html.app-booting body {
overflow: hidden !important;
overscroll-behavior: none;
}
html,
body,
#app {
margin: 0;
min-height: 100%;
background: #f0f3f4;
}
#app-boot {
position: fixed;
inset: 0;
z-index: 99999;
margin: 0;
padding: 0;
box-sizing: border-box;
/* 用 100% 相对自身,避免 100vw 把滚动条宽度算进去 */
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #f0f3f4;
/*
* 必须与 global.less 首屏后状态一致:
* Vue 加载后 html 会带上 antialiased,若 boot 首帧没有,中文会突然变细像「字号缩小」。
*/
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC',
'Microsoft YaHei', Inter, Roboto, 'Helvetica Neue', Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-size: 16px;
color: #4e5969;
text-align: center;
opacity: 1;
transition: opacity 0.28s ease;
pointer-events: auto;
}
#app-boot.is-leaving {
opacity: 0;
pointer-events: none;
}
#app-boot .boot-panel {
width: 300px;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
/* 不用 left:50% + translate,避免视口宽度变化时二次偏移 */
flex-shrink: 0;
}
#app-boot .boot-brand {
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
}
#app-boot .boot-logo-wrap {
width: 72px;
height: 72px;
border-radius: 16px;
background: #fff;
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04), 0 8px 24px rgba(15, 23, 42, 0.06);
box-sizing: border-box;
padding: 10px;
overflow: hidden;
}
#app-boot .boot-logo {
display: block;
width: 52px;
height: 52px;
object-fit: contain;
}
#app-boot .boot-status {
margin-top: 20px;
width: 100%;
height: 96px;
display: flex;
flex-direction: column;
align-items: center;
}
#app-boot .boot-spinner-slot {
position: relative;
width: 120px;
height: 32px;
flex-shrink: 0;
}
#app-boot .boot-spinner {
position: absolute;
left: 50%;
top: 50%;
width: 22px;
height: 22px;
margin: 0;
border: 2px solid #e5e6eb;
border-top-color: var(--app-primary-color, #007979);
border-radius: 50%;
box-sizing: border-box;
transform: translate(-50%, -50%);
transform-origin: center center;
animation: app-boot-spin 0.8s linear infinite;
will-change: transform;
backface-visibility: hidden;
}
#app-boot .boot-retry {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
height: 32px;
padding: 0 16px;
border: 1px solid #e5e6eb;
border-radius: 4px;
background: #fff;
color: #1d2129;
font-size: 14px;
font-weight: 500;
cursor: pointer;
opacity: 0;
visibility: hidden;
pointer-events: none;
white-space: nowrap;
}
#app-boot .boot-retry:hover {
border-color: var(--app-primary-color, #007979);
color: var(--app-primary-color, #007979);
}
#app-boot.is-timeout .boot-spinner {
opacity: 0;
visibility: hidden;
animation: none;
}
#app-boot.is-timeout .boot-retry {
opacity: 1;
visibility: visible;
pointer-events: auto;
}
#app-boot .boot-title {
margin: 10px 0 0;
height: 20px;
font-size: 14px;
font-weight: 500;
color: #86909c;
line-height: 20px;
}
#app-boot .boot-sub {
margin: 6px 0 0;
height: 36px;
font-size: 12px;
line-height: 18px;
color: #c9cdd4;
width: 100%;
overflow: hidden;
}
#app-boot.is-timeout .boot-title {
color: #1d2129;
font-weight: 600;
}
#app-boot.is-timeout .boot-sub {
color: #86909c;
}
/* H5:样式挂在 html.app-boot-h5 上,首屏即正确,不再二次改字号/Logo */
html.app-boot-h5 {
scrollbar-gutter: stable;
background: #f5f6f8;
}
html.app-boot-h5,
html.app-boot-h5 body,
html.app-boot-h5 #app {
background: #f5f6f8;
}
html.app-boot-h5 #app-boot {
background: #f5f6f8;
padding: env(safe-area-inset-top, 0) 24px env(safe-area-inset-bottom, 0);
}
html.app-boot-h5 #app-boot .boot-panel {
width: min(300px, 100%);
}
html.app-boot-h5 #app-boot .boot-status {
height: 104px;
}
/* boot 盖住期间禁止登录页入场动画,避免淡出瞬间叠 rise 抖动 */
html.app-booting .h5-login-main,
html.app-booting .h5-login-error {
animation: none !important;
}
@keyframes app-boot-spin {
from {
transform: translate(-50%, -50%) rotate(0deg);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
</style>
</head>
<body>
<div id="app-boot" role="status" aria-live="polite">
<div class="boot-panel">
<div class="boot-brand">
<div class="boot-logo-wrap">
<img
class="boot-logo"
src="/boot-logo.png"
width="52"
height="52"
alt=""
decoding="sync"
fetchpriority="high"
/>
</div>
</div>
<div class="boot-status">
<div class="boot-spinner-slot">
<div class="boot-spinner" aria-hidden="true"></div>
<button type="button" class="boot-retry" id="app-boot-retry" onclick="location.reload()">
重新加载
</button>
</div>
<p class="boot-title" id="app-boot-title">正在加载系统…</p>
<p class="boot-sub" id="app-boot-sub">首次打开或网络较慢时可能稍等片刻</p>
</div>
</div>
</div>
<div id="app"></div>
<script>
(function () {
var boot = document.getElementById('app-boot');
var title = document.getElementById('app-boot-title');
var sub = document.getElementById('app-boot-sub');
var retry = document.getElementById('app-boot-retry');
if (!boot) return;
var root = document.documentElement;
var isH5 = root.classList.contains('app-boot-h5');
var isEn = root.classList.contains('app-boot-en');
var copy = isH5
? isEn
? {
title: 'Loading…',
sub: 'Please wait a moment',
slow: 'Still loading, please wait…',
timeoutTitle: 'Taking too long',
timeoutSub: 'Check your network and try again',
retry: 'Reload',
}
: {
title: '正在加载…',
sub: '请稍候',
slow: '仍在加载,请稍候…',
timeoutTitle: '加载时间过长',
timeoutSub: '请检查网络后重试',
retry: '重新加载',
}
: isEn
? {
title: 'Loading…',
sub: 'First open or slow network may take a moment',
slow: 'Still loading resources…',
timeoutTitle: 'Taking too long',
timeoutSub: 'Check your network and try again',
retry: 'Reload',
}
: {
title: '正在加载系统…',
sub: '首次打开或网络较慢时可能稍等片刻',
slow: '仍在加载资源,请稍候…',
timeoutTitle: '加载时间过长',
timeoutSub: '请检查网络后重试;若持续失败,可刷新页面或稍后再试',
retry: '重新加载',
};
if (title) title.textContent = copy.title;
if (sub) sub.textContent = copy.sub;
if (retry) retry.textContent = copy.retry;
window.__dismissAppBoot = function () {
if (!boot || boot.classList.contains('is-leaving')) return;
boot.classList.add('is-leaving');
var done = false;
function removeBoot() {
if (done) return;
done = true;
document.documentElement.classList.remove('app-booting');
document.documentElement.classList.remove('app-boot-h5');
document.documentElement.classList.remove('app-boot-en');
if (boot && boot.parentNode) boot.parentNode.removeChild(boot);
}
boot.addEventListener('transitionend', removeBoot, { once: true });
window.setTimeout(removeBoot, 360);
};
window.setTimeout(function () {
if (window.__APP_MOUNTED__ || !document.getElementById('app-boot')) return;
if (sub) sub.textContent = copy.slow;
}, 4000);
window.setTimeout(function () {
if (window.__APP_MOUNTED__ || !document.getElementById('app-boot')) return;
boot.classList.add('is-timeout');
if (title) title.textContent = copy.timeoutTitle;
if (sub) sub.textContent = copy.timeoutSub;
}, 20000);
})();
</script>
<script type="module" src="/src/main.ts"></script>
</body>
</html>