feat: 净菜加工秤新增采样模块与加工记录优化,配比秤新增配比记录页

- 净菜加工秤:新增净菜采样(04)与采样历史(05)页面
- 净菜加工秤:菜单页(01-menu)增加采样、采样历史、加工记录入口
- 净菜加工秤:加工记录(02)规格改为净菜类型,去掉操作员与验收结果列,去掉订单维度与订单数统计
- 净菜加工秤:采样与历史页筛选改为食材类别(叶菜类/根茎类等),净菜名称改为食材名称
- 配比秤:新增配比记录页(03),卡片式布局对齐配比任务页字段结构
- 配比秤:配比任务页"任务截止时间"改为"任务完成时间"
- 配比秤:称重打包页增加当前规格标识
- 统一各页面规格格式为"尺寸 · 形状 · 刀法"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
zhangyan
2026-06-22 14:25:03 +08:00
co-authored by Claude Opus 4.6
parent 06587d20a3
commit d13843d3e6
9 changed files with 2557 additions and 223 deletions
@@ -88,6 +88,30 @@
</div>
<div class="menu-btn__arrow">&#x203A;</div>
</a>
<a class="menu-btn" id="btnSampling" href="javascript:void(0)" onclick="handleMenu('04-sampling.html')">
<div class="menu-btn__icon menu-btn__icon--orange">&#x1F50D;</div>
<div class="menu-btn__info">
<div class="menu-btn__title">净菜采样</div>
<div class="menu-btn__desc">采样操作、外观等级判定、保存采样</div>
</div>
<div class="menu-btn__arrow">&#x203A;</div>
</a>
<a class="menu-btn" id="btnSamplingHistory" href="javascript:void(0)" onclick="handleMenu('05-sampling-history.html')">
<div class="menu-btn__icon menu-btn__icon--gray">&#x1F4CB;</div>
<div class="menu-btn__info">
<div class="menu-btn__title">采样历史</div>
<div class="menu-btn__desc">采样记录查看与筛选</div>
</div>
<div class="menu-btn__arrow">&#x203A;</div>
</a>
<a class="menu-btn" id="btnHistory" href="javascript:void(0)" onclick="handleMenu('02-history.html')">
<div class="menu-btn__icon menu-btn__icon--gray">&#x1F4DD;</div>
<div class="menu-btn__info">
<div class="menu-btn__title">加工记录</div>
<div class="menu-btn__desc">历史加工验收记录查看与筛选</div>
</div>
<div class="menu-btn__arrow">&#x203A;</div>
</a>
</div>
</div>
<script>
@@ -3,241 +3,312 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1280, initial-scale=1.0">
<title>净菜加工秤 - 验收记录 | 蚁熊智能餐养平台</title>
<title>净菜加工秤 - 加工记录 | 蚁熊智能餐养平台</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif; background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden; }
.top-bar { display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px; }
.back-btn { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s; }
body {
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden;
display: flex; flex-direction: column;
}
/* 顶部导航栏 */
.top-bar {
display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px;
flex-shrink: 0;
}
.back-btn {
font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s;
}
.back-btn:hover { color: #fff; }
.top-bar__title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
.page-title {
flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85);
}
.top-bar__user { font-size: 12px; color: rgba(255,255,255,0.5); }
.main-content { height: calc(100% - 44px); padding: 20px 28px; display: flex; flex-direction: column; gap: 16px; }
.filter-bar { display: flex; align-items: center; gap: 12px; }
.filter-group { display: flex; align-items: center; gap: 8px; }
.filter-label { font-size: 12px; color: rgba(255,255,255,0.5); }
.filter-select { background: #1a2b4a; border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; padding: 8px 12px; font-size: 12px; color: #fff; outline: none; cursor: pointer; }
.filter-select:focus { border-color: #4a90d9; }
.filter-input { background: #1a2b4a; border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; padding: 8px 12px; font-size: 12px; color: #fff; outline: none; width: 140px; }
.filter-input:focus { border-color: #4a90d9; }
.filter-input::placeholder { color: rgba(255,255,255,0.3); }
.filter-btn { padding: 8px 16px; border-radius: 6px; font-size: 12px; background: #4a90d9; color: #fff; border: none; cursor: pointer; }
.filter-btn:hover { background: #5ba0e9; }
.filter-btn--secondary { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.8); }
.filter-btn--secondary:hover { background: rgba(255,255,255,0.12); }
.stats-row { display: flex; gap: 14px; }
.stat-card { flex: 1; background: #1a2b4a; border-radius: 12px; padding: 16px 20px; border: 1px solid rgba(255,255,255,0.06); }
.stat-card__label { font-size: 12px; color: rgba(255,255,255,0.5); margin-bottom: 6px; }
.stat-card__value { font-size: 24px; font-weight: 700; color: #fff; }
.stat-card__value--green { color: #52c41a; }
.stat-card__value--blue { color: #4a90d9; }
.stat-card__value--purple { color: #722ed1; }
.records-section { flex: 1; background: #1a2b4a; border-radius: 12px; padding: 16px 20px; display: flex; flex-direction: column; overflow: hidden; }
.records-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.records-title { font-size: 14px; font-weight: 600; color: rgba(255,255,255,0.8); }
.records-count { font-size: 12px; color: rgba(255,255,255,0.4); }
.table-header { display: flex; align-items: center; padding: 10px 16px; background: rgba(0,0,0,0.2); border-radius: 8px; margin-bottom: 8px; }
.table-header__cell { font-size: 12px; color: rgba(255,255,255,0.5); font-weight: 500; }
.col-batch { flex: 0 0 140px; }
.col-name { flex: 0 0 100px; }
.col-cutting { flex: 0 0 80px; }
.col-weight { flex: 0 0 80px; }
.col-time { flex: 0 0 100px; }
.col-duration { flex: 0 0 80px; }
.col-operator { flex: 0 0 80px; }
.col-status { flex: 0 0 80px; }
.col-action { flex: 1; text-align: right; }
.records-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.1) transparent; }
.records-list::-webkit-scrollbar { width: 4px; }
.records-list::-webkit-scrollbar-track { background: transparent; }
.records-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 2px; }
.record-row { display: flex; align-items: center; padding: 12px 16px; background: rgba(0,0,0,0.15); border-radius: 8px; transition: background 0.2s; }
.record-row:hover { background: rgba(74,144,217,0.08); }
.record-row__cell { font-size: 13px; color: rgba(255,255,255,0.8); }
.record-row__cell--icon { font-size: 18px; }
.spec-badge { display: inline-block; padding: 2px 6px; border-radius: 3px; font-size: 11px; background: rgba(24,144,255,0.15); color: #40a9ff; }
.status-badge { display: inline-block; padding: 3px 8px; border-radius: 4px; font-size: 11px; font-weight: 500; }
.status-badge--done { background: rgba(82,196,26,0.15); color: #52c41a; }
.action-link { font-size: 12px; color: #4a90d9; cursor: pointer; text-decoration: none; }
.action-link:hover { text-decoration: underline; }
.pagination { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding-top: 14px; border-top: 1px solid rgba(255,255,255,0.06); }
.pagination__info { font-size: 12px; color: rgba(255,255,255,0.4); margin-right: auto; }
.pagination__btn { width: 32px; height: 32px; border-radius: 6px; display: flex; align-items: center; justify-content: center; background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.6); font-size: 12px; border: none; cursor: pointer; transition: all 0.2s; }
.pagination__btn:hover { background: rgba(255,255,255,0.1); color: #fff; }
.pagination__btn.active { background: #4a90d9; color: #fff; }
.pagination__btn:disabled { opacity: 0.4; cursor: not-allowed; }
.logout-btn {
padding: 4px 10px; font-size: 11px;
background: rgba(255,77,79,0.08); border: 1px solid rgba(255,77,79,0.2);
border-radius: 5px; color: rgba(255,77,79,0.7); cursor: pointer;
transition: all 0.2s; font-family: inherit; margin-left: 10px;
}
.logout-btn:hover { background: rgba(255,77,79,0.18); color: #ff6b6d; border-color: rgba(255,77,79,0.4); }
/* 触控筛选栏 */
.touch-filter {
display: flex; align-items: center; gap: 12px;
padding: 10px 20px; background: #1a2b4a; margin: 12px 20px 0; border-radius: 10px;
flex-shrink: 0;
}
/* 模式切换(日视图 / 本周) */
.mode-seg {
flex-shrink: 0; display: flex; height: 52px; border-radius: 10px;
overflow: hidden; border: 1px solid rgba(255,255,255,0.1);
}
.mode-btn {
min-width: 72px; padding: 0 16px; border: none;
background: rgba(255,255,255,0.04); color: rgba(255,255,255,0.5);
font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s;
}
.mode-btn:hover { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.8); }
.mode-btn.active { background: #4a90d9; color: #fff; }
.filter-divider {
width: 1px; height: 36px; background: rgba(255,255,255,0.1); flex-shrink: 0;
}
/* 横向日期滚动条 */
.date-strip {
flex: 1; display: flex; align-items: stretch; gap: 6px;
overflow-x: auto; overflow-y: hidden;
padding: 4px 0;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
transition: opacity 0.2s;
}
.date-strip::-webkit-scrollbar { display: none; }
.date-strip.disabled { opacity: 0.25; pointer-events: none; }
/* 日期单元格 */
.date-cell {
flex-shrink: 0; width: 80px; height: 68px; border-radius: 10px;
border: 2px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 3px; transition: all 0.2s;
}
.date-cell:hover { background: rgba(74,144,217,0.1); border-color: rgba(74,144,217,0.3); }
.date-cell.active { background: rgba(74,144,217,0.25); border-color: #4a90d9; }
.date-cell__weekday { font-size: 12px; color: rgba(255,255,255,0.45); }
.date-cell__day { font-size: 20px; font-weight: 700; color: rgba(255,255,255,0.9); }
.date-cell.active .date-cell__weekday { color: #7ab8f5; }
.date-cell.active .date-cell__day { color: #fff; }
/* 今天快速按钮 */
.today-btn {
flex-shrink: 0; height: 68px; padding: 0 16px; border-radius: 10px;
border: 2px solid rgba(74,144,217,0.4); background: rgba(74,144,217,0.1);
color: #7ab8f5; font-size: 15px; font-weight: 600; cursor: pointer; transition: all 0.2s;
white-space: nowrap;
}
.today-btn:hover { background: rgba(74,144,217,0.2); border-color: #4a90d9; }
.today-btn.active { background: #4a90d9; color: #fff; border-color: #4a90d9; }
.today-btn.disabled { opacity: 0.25; pointer-events: none; }
/* 日历按钮 */
.calendar-btn {
flex-shrink: 0; width: 68px; height: 68px; border-radius: 10px;
border: 2px solid rgba(255,255,255,0.12); background: rgba(255,255,255,0.04);
cursor: pointer; display: flex; align-items: center; justify-content: center;
transition: all 0.2s;
}
.calendar-btn:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.25); }
.calendar-btn svg { width: 28px; height: 28px; }
.calendar-btn.disabled { opacity: 0.25; pointer-events: none; }
/* 状态分段控件 */
.status-seg { flex-shrink: 0; display: flex; height: 52px; border-radius: 10px; overflow: hidden; border: 1px solid rgba(255,255,255,0.1); }
.status-btn {
min-width: 80px; padding: 0 18px; border: none; background: rgba(255,255,255,0.04);
color: rgba(255,255,255,0.5); font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s;
}
.status-btn:hover { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.8); }
.status-btn.active { background: #4a90d9; color: #fff; }
.status-btn.active--green { background: #389e0d; color: #fff; }
.status-btn.active--red { background: #cf1322; color: #fff; }
/* 搜索框 */
.search-box {
flex-shrink: 0; display: flex; align-items: center; gap: 6px;
height: 40px; padding: 0 12px; border-radius: 10px;
background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.1);
transition: border-color 0.2s;
}
.search-box:focus-within { border-color: #4a90d9; }
.search-box__icon { font-size: 14px; color: rgba(255,255,255,0.35); flex-shrink: 0; }
.search-box__input {
width: 160px; border: none; outline: none; background: transparent;
font-size: 13px; color: rgba(255,255,255,0.85);
}
.search-box__input::placeholder { color: rgba(255,255,255,0.25); }
.search-box__clear {
flex-shrink: 0; width: 20px; height: 20px; border-radius: 50%;
background: rgba(255,255,255,0.1); color: rgba(255,255,255,0.5);
font-size: 12px; cursor: pointer; display: none;
align-items: center; justify-content: center; border: none;
}
.search-box__clear.show { display: flex; }
.search-box__clear:hover { background: rgba(255,255,255,0.18); color: #fff; }
/* 维度切换 */
.view-toggle {
flex-shrink: 0; display: flex; height: 34px; border-radius: 8px; overflow: hidden;
border: 1px solid rgba(255,255,255,0.1);
}
.view-toggle__btn {
padding: 0 14px; font-size: 12px; border: none; cursor: pointer;
background: transparent; color: rgba(255,255,255,0.45); transition: all 0.2s;
white-space: nowrap;
}
.view-toggle__btn.active {
background: rgba(74,144,217,0.2); color: #4a90d9; font-weight: 600;
}
.view-toggle__btn:hover:not(.active) { color: rgba(255,255,255,0.7); }
/* 统计行 */
.stats-row { display: flex; gap: 12px; padding: 12px 20px; flex-shrink: 0; }
.stat-chip {
flex: 1; background: #1a2b4a; border-radius: 8px; padding: 12px 16px;
display: flex; align-items: center; gap: 12px;
}
.stat-chip__icon {
width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center;
justify-content: center; font-size: 18px;
}
.stat-chip__icon--blue { background: rgba(74,144,217,0.2); }
.stat-chip__icon--green { background: rgba(82,196,26,0.2); }
.stat-chip__icon--red { background: rgba(255,77,79,0.2); }
.stat-chip__icon--orange { background: rgba(250,173,22,0.2); }
.stat-chip__value { font-size: 20px; font-weight: 700; }
.stat-chip__label { font-size: 11px; color: rgba(255,255,255,0.4); }
/* 表格 */
.table-wrap {
margin: 12px 20px; background: #1a2b4a; border-radius: 10px; overflow: hidden;
flex: 1; min-height: 0; display: flex; flex-direction: column;
}
.table-scroll { flex: 1; overflow-y: auto; }
.table-scroll::-webkit-scrollbar { width: 6px; }
.table-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 3px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th {
background: rgba(255,255,255,0.04); padding: 12px 10px; text-align: left;
color: rgba(255,255,255,0.5); font-weight: 500; border-bottom: 1px solid rgba(255,255,255,0.06);
white-space: nowrap; position: sticky; top: 0; background: #1a2b4a; z-index: 1;
}
tbody td {
padding: 12px 10px; border-bottom: 1px solid rgba(255,255,255,0.04);
color: rgba(255,255,255,0.8);
}
tbody tr:hover { background: rgba(74,144,217,0.08); }
tbody tr:last-child td { border-bottom: none; }
/* 日期列标签(本周模式) */
.date-tag {
display: inline-flex; align-items: center; gap: 4px;
padding: 3px 8px; border-radius: 8px; font-size: 11px;
background: rgba(74,144,217,0.12); color: #7ab8f5; white-space: nowrap;
}
/* 规格标签 */
.spec-badge {
display: inline-block; padding: 2px 6px; border-radius: 3px; font-size: 11px;
background: rgba(24,144,255,0.15); color: #40a9ff; white-space: nowrap;
}
.tag {
display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 10px; font-size: 12px;
}
.tag--green { background: rgba(82,196,26,0.15); color: #52c41a; }
.tag--red { background: rgba(255,77,79,0.15); color: #ff4d4f; }
.tag--blue { background: rgba(74,144,217,0.15); color: #4a90d9; }
.tag--orange { background: rgba(250,173,22,0.15); color: #faad14; }
/* 底栏 */
.table-footer {
display: flex; align-items: center; justify-content: center;
padding: 10px 20px; font-size: 12px; color: rgba(255,255,255,0.35);
border-top: 1px solid rgba(255,255,255,0.04); flex-shrink: 0;
}
/* 空状态 */
.empty-state {
display: none; flex: 1; align-items: center; justify-content: center;
flex-direction: column; gap: 8px; color: rgba(255,255,255,0.3); font-size: 14px;
}
.empty-state.show { display: flex; }
.empty-state__icon { font-size: 40px; opacity: 0.4; }
</style>
</head>
<body>
<div class="top-bar">
<a class="back-btn" id="backBtn" href="javascript:void(0)">&#x25C0; 返回</a> <span class="top-bar__title">验收记录</span>
<div class="top-bar">
<a class="back-btn" id="backBtn" href="javascript:void(0)">&#x25C0; 返回</a>
<span class="page-title">加工记录</span>
<span class="top-bar__user" id="topUser">--</span>
<button class="logout-btn" onclick="handleLogout()">退出</button>
</div>
<div class="main-content">
<div class="filter-bar">
<div class="filter-group">
<span class="filter-label">日期</span>
<input type="date" class="filter-input" value="2026-06-13">
</div>
<div class="filter-group">
<span class="filter-label">食材</span>
<select class="filter-select">
<option value="">全部</option>
<option value="potato">土豆</option>
<option value="carrot">胡萝卜</option>
<option value="cucumber">黄瓜</option>
<option value="cabbage">大白菜</option>
<option value="tomato">西红柿</option>
</select>
</div>
<div class="filter-group">
<span class="filter-label">规格</span>
<select class="filter-select">
<option value="">全部</option>
<option value="slice">圆片</option>
<option value="shred">丝条</option>
<option value="chunk">滚刀块</option>
<option value="dice">方丁</option>
<option value="section">宽段</option>
</select>
</div>
<button class="filter-btn">查询</button>
<button class="filter-btn filter-btn--secondary">重置</button>
<!-- 触控筛选栏 -->
<div class="touch-filter">
<!-- 模式切换:日视图 / 本周 -->
<div class="mode-seg">
<button class="mode-btn active" id="modeDayBtn">日视图</button>
<button class="mode-btn" id="modeWeekBtn">本周</button>
</div>
<div class="stats-row">
<div class="stat-card">
<div class="stat-card__label">今日验收批次</div>
<div class="stat-card__value stat-card__value--purple">8</div>
</div>
<div class="stat-card">
<div class="stat-card__label">验收总量</div>
<div class="stat-card__value">32.5斤</div>
</div>
<div class="stat-card">
<div class="stat-card__label">平均验收时长</div>
<div class="stat-card__value">5.3分钟</div>
</div>
<div class="stat-card">
<div class="stat-card__label">合格率</div>
<div class="stat-card__value stat-card__value--green">100%</div>
</div>
</div>
<div class="records-section">
<div class="records-header">
<span class="records-title">验收记录列表</span>
<span class="records-count">共 8 条记录</span>
</div>
<div class="table-header">
<div class="table-header__cell col-batch">批次号</div>
<div class="table-header__cell col-name">食材</div>
<div class="table-header__cell col-cutting">规格</div>
<div class="table-header__cell col-weight">重量</div>
<div class="table-header__cell col-time">完成时间</div>
<div class="table-header__cell col-duration">时长</div>
<div class="table-header__cell col-operator">操作员</div>
<div class="table-header__cell col-status">状态</div>
<div class="table-header__cell col-action">操作</div>
</div>
<div class="records-list">
<div class="record-row">
<div class="record-row__cell col-batch">#20260613-C01</div>
<div class="record-row__cell col-name"><span class="record-row__cell--icon">&#x1F954;</span> 土豆</div>
<div class="record-row__cell col-cutting"><span class="spec-badge">丝条</span></div>
<div class="record-row__cell col-weight">5.2斤</div>
<div class="record-row__cell col-time">09:35</div>
<div class="record-row__cell col-duration">5分钟</div>
<div class="record-row__cell col-operator">赵六</div>
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
</div>
<div class="record-row">
<div class="record-row__cell col-batch">#20260613-C02</div>
<div class="record-row__cell col-name"><span class="record-row__cell--icon">&#x1F952;</span> 黄瓜</div>
<div class="record-row__cell col-cutting"><span class="spec-badge">圆片</span></div>
<div class="record-row__cell col-weight">4.2斤</div>
<div class="record-row__cell col-time">09:52</div>
<div class="record-row__cell col-duration">4分钟</div>
<div class="record-row__cell col-operator">赵六</div>
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
</div>
<div class="record-row">
<div class="record-row__cell col-batch">#20260613-C03</div>
<div class="record-row__cell col-name"><span class="record-row__cell--icon">&#x1F96C;</span> 大白菜</div>
<div class="record-row__cell col-cutting"><span class="spec-badge">宽段</span></div>
<div class="record-row__cell col-weight">8.5斤</div>
<div class="record-row__cell col-time">10:15</div>
<div class="record-row__cell col-duration">6分钟</div>
<div class="record-row__cell col-operator">赵六</div>
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
</div>
<div class="record-row">
<div class="record-row__cell col-batch">#20260613-C04</div>
<div class="record-row__cell col-name"><span class="record-row__cell--icon">&#x1F955;</span> 胡萝卜</div>
<div class="record-row__cell col-cutting"><span class="spec-badge">丝条</span></div>
<div class="record-row__cell col-weight">2.8斤</div>
<div class="record-row__cell col-time">10:32</div>
<div class="record-row__cell col-duration">5分钟</div>
<div class="record-row__cell col-operator">赵六</div>
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
</div>
<div class="record-row">
<div class="record-row__cell col-batch">#20260613-C05</div>
<div class="record-row__cell col-name"><span class="record-row__cell--icon">&#x1F345;</span> 西红柿</div>
<div class="record-row__cell col-cutting"><span class="spec-badge">滚刀块</span></div>
<div class="record-row__cell col-weight">3.5斤</div>
<div class="record-row__cell col-time">10:48</div>
<div class="record-row__cell col-duration">4分钟</div>
<div class="record-row__cell col-operator">赵六</div>
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
</div>
<div class="record-row">
<div class="record-row__cell col-batch">#20260613-C06</div>
<div class="record-row__cell col-name"><span class="record-row__cell--icon">&#x1F954;</span> 土豆</div>
<div class="record-row__cell col-cutting"><span class="spec-badge">滚刀块</span></div>
<div class="record-row__cell col-weight">3.2斤</div>
<div class="record-row__cell col-time">14:20</div>
<div class="record-row__cell col-duration">5分钟</div>
<div class="record-row__cell col-operator">赵六</div>
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
</div>
<div class="record-row">
<div class="record-row__cell col-batch">#20260613-C07</div>
<div class="record-row__cell col-name"><span class="record-row__cell--icon">&#x1F954;</span> 土豆</div>
<div class="record-row__cell col-cutting"><span class="spec-badge">细条</span></div>
<div class="record-row__cell col-weight">2.6斤</div>
<div class="record-row__cell col-time">14:38</div>
<div class="record-row__cell col-duration">5分钟</div>
<div class="record-row__cell col-operator">赵六</div>
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
</div>
<div class="record-row">
<div class="record-row__cell col-batch">#20260613-C08</div>
<div class="record-row__cell col-name"><span class="record-row__cell--icon">&#x1F955;</span> 胡萝卜</div>
<div class="record-row__cell col-cutting"><span class="spec-badge">方丁</span></div>
<div class="record-row__cell col-weight">2.5斤</div>
<div class="record-row__cell col-time">14:55</div>
<div class="record-row__cell col-duration">6分钟</div>
<div class="record-row__cell col-operator">赵六</div>
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
</div>
</div>
<div class="pagination">
<span class="pagination__info">共 8 条,第 1/1 页</span>
<button class="pagination__btn" disabled>&#x2039;</button>
<button class="pagination__btn active">1</button>
<button class="pagination__btn" disabled>&#x203A;</button>
</div>
<div class="filter-divider"></div>
<!-- 横向日期滚动条(日视图模式) -->
<div class="date-strip" id="dateStrip"></div>
<button class="today-btn active" id="todayBtn">今天</button>
<label class="calendar-btn" id="calendarBtn" title="选择任意日期">
<svg viewBox="0 0 24 24" fill="none" stroke="rgba(255,255,255,0.6)" stroke-width="1.8">
<rect x="3" y="4" width="18" height="18" rx="2"/>
<line x1="16" y1="2" x2="16" y2="6"/>
<line x1="8" y1="2" x2="8" y2="6"/>
<line x1="3" y1="10" x2="21" y2="10"/>
<rect x="7" y="14" width="3" height="3" rx="0.5" fill="rgba(255,255,255,0.6)" stroke="none"/>
</svg>
<input type="date" id="calendarInput" style="position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;">
</label>
<div class="filter-divider"></div>
<!-- 搜索框 -->
<div class="search-box">
<span class="search-box__icon">&#x1F50D;</span>
<input class="search-box__input" id="searchInput" type="text" placeholder="搜索加工号 / 净菜" oninput="onSearchInput()">
<button class="search-box__clear" id="searchClear" onclick="clearSearch()">&times;</button>
</div>
</div>
<!-- 统计行 -->
<div class="stats-row">
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--blue">&#x1F4CB;</div>
<div><div class="stat-chip__value" id="statTotal">6</div><div class="stat-chip__label" id="statTotalLabel">今日加工总数</div></div>
</div>
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--green">&#x2696;&#xFE0F;</div>
<div><div class="stat-chip__value" id="statWeight">0</div><div class="stat-chip__label">加工总重量(斤)</div></div>
</div>
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--orange">&#x1F96C;</div>
<div><div class="stat-chip__value" id="statFoods">0</div><div class="stat-chip__label">食材种类</div></div>
</div>
</div>
<!-- 表格 -->
<div class="table-wrap">
<div class="table-scroll">
<table>
<thead><tr id="tableHead">
<th>加工号</th><th>净菜</th><th>净菜类型</th>
<th>加工重量</th><th>完成时间</th><th>加工时长</th>
</tr></thead>
<tbody id="tableBody"></tbody>
</table>
<div class="empty-state" id="emptyState">
<div class="empty-state__icon">&#x1F4ED;</div>
<div>暂无加工记录</div>
</div>
</div>
<div class="table-footer" id="tableFooter">共 0 条记录</div>
</div>
<script>
/* 退出登录 */
function handleLogout() {
window.location.href = '00-welcome.html';
}
/* 获取 URL 参数 */
function getUrlParam(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
var r = window.location.search.substr(1).match(reg);
@@ -245,7 +316,272 @@
return null;
}
var userName = getUrlParam('user');
if (userName) document.getElementById('topUser').textContent = '操作员: ' + userName;
if (userName) {
document.getElementById('topUser').textContent = '操作员: ' + userName;
}
// 当天日期(原型基准日期)
var TODAY = '2026-06-17';
var WEEKDAYS = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
// 加工记录数据(净菜加工语义)
var RECORDS = [
{ batch:'JC-20260617-001', orderId:'PO-20260617-001', time:'2026-06-17 09:35', dish:'土豆', spec:'35mm*1mm*1mm · 长条 · 平刀', weight:5.2, duration:'5分钟' },
{ batch:'JC-20260617-002', orderId:'PO-20260617-001', time:'2026-06-17 09:52', dish:'黄瓜', spec:'30mm*30mm*3mm · 圆片 · 平刀', weight:4.2, duration:'4分钟' },
{ batch:'JC-20260617-003', orderId:'PO-20260617-001', time:'2026-06-17 10:15', dish:'大白菜', spec:'50mm*30mm*30mm · 宽段 · 平刀', weight:8.5, duration:'6分钟' },
{ batch:'JC-20260617-004', orderId:'PO-20260617-002', time:'2026-06-17 10:32', dish:'胡萝卜', spec:'20mm*1mm*1mm · 细丝 · 平刀', weight:2.8, duration:'5分钟' },
{ batch:'JC-20260617-005', orderId:'PO-20260617-002', time:'2026-06-17 10:48', dish:'西红柿', spec:'25mm*25mm*20mm · 楔形块 · 平刀', weight:3.5, duration:'4分钟' },
{ batch:'JC-20260617-006', orderId:'PO-20260617-003', time:'2026-06-17 14:20', dish:'青椒', spec:'30mm*3mm*3mm · 长条 · 平刀', weight:2.6, duration:'5分钟' },
{ batch:'JC-20260616-007', orderId:'PO-20260616-005', time:'2026-06-16 14:38', dish:'洋葱', spec:'30mm*2mm*2mm · 细丝 · 平刀', weight:3.2, duration:'5分钟' },
{ batch:'JC-20260616-008', orderId:'PO-20260616-005', time:'2026-06-16 14:55', dish:'芹菜', spec:'40mm*10mm*10mm · 宽段 · 平刀', weight:2.5, duration:'6分钟' },
{ batch:'JC-20260616-009', orderId:'PO-20260616-006', time:'2026-06-16 15:30', dish:'莲藕', spec:'35mm*35mm*3mm · 圆片 · 平刀', weight:4.0, duration:'5分钟' }
];
var selectedDate = TODAY;
var isWeeklyMode = false;
var searchKeyword = '';
// 获取本周一日期
function getMonday() {
var today = new Date(TODAY + 'T00:00:00');
var day = today.getDay();
var diff = today.getDate() - day + (day === 0 ? -6 : 1);
var monday = new Date(today);
monday.setDate(diff);
return monday;
}
// 生成日期字符串
function dateStr(d) {
return d.getFullYear() + '-' +
String(d.getMonth() + 1).padStart(2, '0') + '-' +
String(d.getDate()).padStart(2, '0');
}
// 生成日期条(最近7天)
function generateDateStrip() {
var strip = document.getElementById('dateStrip');
var today = new Date(TODAY + 'T00:00:00');
var html = '';
for (var i = 6; i >= 0; i--) {
var d = new Date(today);
d.setDate(d.getDate() - i);
var ds = dateStr(d);
var dayNum = d.getDate();
var weekday = WEEKDAYS[d.getDay()];
var label = (i === 0) ? '今天' : (i === 1 ? '昨天' : weekday);
var isActive = (ds === selectedDate) ? ' active' : '';
html += '<button class="date-cell' + isActive + '" data-date="' + ds + '">'
+ '<span class="date-cell__weekday">' + label + '</span>'
+ '<span class="date-cell__day">' + dayNum + '</span>'
+ '</button>';
}
strip.innerHTML = html;
strip.querySelectorAll('.date-cell').forEach(function(cell) {
cell.addEventListener('click', function() {
selectDate(cell.getAttribute('data-date'));
});
});
strip.scrollLeft = strip.scrollWidth;
}
// 选中日期
function selectDate(ds) {
if (isWeeklyMode) return;
selectedDate = ds;
document.querySelectorAll('.date-cell').forEach(function(c) {
c.classList.toggle('active', c.getAttribute('data-date') === ds);
});
document.getElementById('todayBtn').classList.toggle('active', ds === TODAY);
// 超出范围时扩展日期条
var inRange = Array.from(document.querySelectorAll('.date-cell'))
.some(function(c) { return c.getAttribute('data-date') === ds; });
if (!inRange) appendDateToStrip(ds);
var activeCell = document.querySelector('.date-cell[data-date="' + ds + '"]');
if (activeCell) activeCell.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' });
updateStats();
renderTable();
}
// 扩展日期条(左侧追加)
function appendDateToStrip(ds) {
var strip = document.getElementById('dateStrip');
var d = new Date(ds + 'T00:00:00');
var cell = document.createElement('button');
cell.className = 'date-cell active';
cell.setAttribute('data-date', ds);
cell.innerHTML = '<span class="date-cell__weekday">' + WEEKDAYS[d.getDay()] + '</span>'
+ '<span class="date-cell__day">' + d.getDate() + '</span>';
cell.addEventListener('click', function() { selectDate(ds); });
strip.insertBefore(cell, strip.firstChild);
}
// 切换模式:日视图 / 本周
function setMode(weekly) {
isWeeklyMode = weekly;
document.getElementById('modeDayBtn').classList.toggle('active', !weekly);
document.getElementById('modeWeekBtn').classList.toggle('active', weekly);
var disableClass = weekly ? 'add' : 'remove';
document.getElementById('dateStrip').classList[disableClass]('disabled');
document.getElementById('todayBtn').classList[disableClass]('disabled');
document.getElementById('calendarBtn').classList[disableClass]('disabled');
updateStats();
renderTable();
}
// 更新统计行
function updateStats() {
var records;
var totalLabel;
if (searchKeyword) {
records = RECORDS;
totalLabel = '搜索结果';
} else if (isWeeklyMode) {
var monday = getMonday();
var mondayStr = dateStr(monday);
records = RECORDS.filter(function(r) { return r.time.substring(0, 10) >= mondayStr; });
totalLabel = '本周加工总数';
} else {
records = RECORDS.filter(function(r) { return r.time.substring(0, 10) === selectedDate; });
totalLabel = (selectedDate === TODAY) ? '今日加工总数' : (selectedDate.substring(5).replace('-', '/') + ' 加工总数');
}
var total = records.length;
var totalWeight = records.reduce(function(sum, r) { return sum + r.weight; }, 0);
var foodSet = {};
records.forEach(function(r) { foodSet[r.dish] = true; });
var foodCount = Object.keys(foodSet).length;
document.getElementById('statTotal').textContent = total;
document.getElementById('statTotalLabel').textContent = totalLabel;
document.getElementById('statWeight').textContent = totalWeight.toFixed(1);
document.getElementById('statFoods').textContent = foodCount;
}
// 搜索输入处理
function onSearchInput() {
var val = document.getElementById('searchInput').value.trim();
searchKeyword = val;
document.getElementById('searchClear').classList.toggle('show', val.length > 0);
updateStats();
renderTable();
}
function clearSearch() {
document.getElementById('searchInput').value = '';
searchKeyword = '';
document.getElementById('searchClear').classList.remove('show');
updateStats();
renderTable();
}
// 过滤记录
function getFilteredRecords() {
var monday = getMonday();
var mondayStr = dateStr(monday);
return RECORDS.filter(function(r) {
if (!searchKeyword) {
if (isWeeklyMode) {
if (r.time.substring(0, 10) < mondayStr) return false;
} else {
if (r.time.substring(0, 10) !== selectedDate) return false;
}
}
if (searchKeyword) {
var kw = searchKeyword;
if (r.batch.indexOf(kw) === -1 && r.dish.indexOf(kw) === -1) return false;
}
return true;
}).sort(function(a, b) {
return b.time.localeCompare(a.time);
});
}
// 渲染表格
function renderTable() {
var records = getFilteredRecords();
var emptyEl = document.getElementById('emptyState');
var tbody = document.getElementById('tableBody');
var thead = document.getElementById('tableHead');
var dateCol = isWeeklyMode ? '<th>日期</th>' : '';
thead.innerHTML = dateCol + '<th>加工号</th><th>净菜</th><th>净菜类型</th>'
+ '<th>加工重量</th><th>完成时间</th><th>加工时长</th>';
if (records.length === 0) {
tbody.innerHTML = '';
emptyEl.classList.add('show');
document.getElementById('tableFooter').textContent = '共 0 条记录';
return;
}
emptyEl.classList.remove('show');
var html = records.map(function(r) {
var timeShort = r.time.substring(11);
var specFull = r.spec || '--';
var cols = '';
if (isWeeklyMode) {
var rd = new Date(r.time.substring(0, 10) + 'T00:00:00');
var weekday = WEEKDAYS[rd.getDay()];
var mmdd = r.time.substring(5, 10).replace('-', '/');
cols += '<td><span class="date-tag">' + weekday + ' ' + mmdd + '</span></td>';
}
cols += '<td>' + r.batch + '</td>'
+ '<td>' + r.dish + '</td>'
+ '<td><span class="spec-badge">' + specFull + '</span></td>'
+ '<td>' + r.weight.toFixed(1) + ' 斤</td>'
+ '<td>' + timeShort + '</td>'
+ '<td>' + r.duration + '</td>';
return '<tr>' + cols + '</tr>';
}).join('');
tbody.innerHTML = html;
var footerText;
if (isWeeklyMode) {
var monday = getMonday();
var mondayStr = dateStr(monday).substring(5).replace('-', '/');
var todayStr = TODAY.substring(5).replace('-', '/');
footerText = '本周 ' + mondayStr + ' - ' + todayStr + ' 共 ' + records.length + ' 条记录';
} else {
footerText = '共 ' + records.length + ' 条记录';
}
document.getElementById('tableFooter').textContent = footerText;
}
// 初始化
function init() {
generateDateStrip();
document.getElementById('modeDayBtn').addEventListener('click', function() { setMode(false); });
document.getElementById('modeWeekBtn').addEventListener('click', function() { setMode(true); });
document.getElementById('todayBtn').addEventListener('click', function() {
selectDate(TODAY);
});
document.getElementById('calendarInput').addEventListener('change', function(e) {
if (e.target.value) selectDate(e.target.value);
});
updateStats();
renderTable();
}
init();
</script>
<script>
@@ -0,0 +1,675 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1280, initial-scale=1.0">
<title>净菜加工秤 - 净菜采样 | 蚁熊智能餐养平台</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden;
}
/* ---- 顶部导航栏 ---- */
.top-bar { display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px; }
.top-bar__title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
.back-btn { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s; }
.back-btn:hover { color: #fff; }
.top-bar__user { font-size: 12px; color: rgba(255,255,255,0.5); }
.logout-btn {
padding: 4px 10px; font-size: 11px;
background: rgba(255,77,79,0.08); border: 1px solid rgba(255,77,79,0.2);
border-radius: 5px; color: rgba(255,77,79,0.7); cursor: pointer;
transition: all 0.2s; font-family: inherit; margin-left: 10px;
}
.logout-btn:hover { background: rgba(255,77,79,0.18); color: #ff6b6d; border-color: rgba(255,77,79,0.4); }
.main-content { display: flex; gap: 16px; padding: 16px 20px; height: calc(100% - 44px); }
/* ========== 左侧:净菜选择区 ========== */
.food-select-area {
width: 400px; flex-shrink: 0; background: #1a2b4a; border-radius: 12px;
padding: 20px; display: flex; flex-direction: column; overflow: hidden;
}
.area-title { font-size: 16px; font-weight: 600; margin-bottom: 16px; }
/* 搜索栏 */
.search-bar { margin-bottom: 10px; }
.search-input {
width: 100%; padding: 8px 12px; background: #121832;
border: 1px solid rgba(255,255,255,0.1); border-radius: 6px;
color: #fff; font-size: 13px; outline: none; transition: border-color 0.2s;
}
.search-input:focus { border-color: #4a90d9; }
.search-input::placeholder { color: rgba(255,255,255,0.3); }
/* 类目Tab */
.filter-tabs { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; }
.filter-tab {
padding: 5px 12px; font-size: 12px; border-radius: 4px;
background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.55);
cursor: pointer; transition: all 0.2s; border: 1px solid transparent;
}
.filter-tab.active { background: #4a90d9; color: #fff; }
.filter-tab:hover:not(.active) { border-color: rgba(255,255,255,0.15); color: rgba(255,255,255,0.75); }
/* 净菜列表 */
.food-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.food-list::-webkit-scrollbar { width: 4px; }
.food-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 2px; }
.food-item {
display: flex; align-items: center; padding: 12px;
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
border-radius: 10px; gap: 12px; cursor: pointer; transition: all 0.2s;
}
.food-item:hover { background: rgba(74,144,217,0.08); border-color: rgba(74,144,217,0.25); }
.food-item.selected { background: rgba(74,144,217,0.12); border-color: #4a90d9; }
.food-item__icon { font-size: 22px; width: 36px; text-align: center; flex-shrink: 0; }
.food-item__info { flex: 1; min-width: 0; }
.food-item__name { font-size: 14px; font-weight: 600; margin-bottom: 3px; }
.food-item__detail { font-size: 11px; color: rgba(255,255,255,0.45); }
.food-item__count {
font-size: 11px; color: #52c41a; background: rgba(82,196,26,0.1);
padding: 2px 8px; border-radius: 4px; flex-shrink: 0;
}
/* 空状态 */
.empty-state {
display: flex; flex-direction: column; align-items: center; justify-content: center;
padding: 40px 0; color: rgba(255,255,255,0.3);
}
.empty-state__icon { font-size: 40px; margin-bottom: 12px; }
.empty-state__text { font-size: 13px; }
/* ========== 右侧:拍照采集区 ========== */
.capture-area {
flex: 1; background: #1a2b4a; border-radius: 12px; padding: 20px;
display: flex; flex-direction: column; gap: 16px; overflow-y: auto;
}
.capture-area::-webkit-scrollbar { width: 4px; }
.capture-area::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 2px; }
/* 选中净菜信息 */
.selected-food-info {
display: flex; align-items: center; gap: 14px;
padding: 14px 16px; background: rgba(74,144,217,0.08);
border: 1px solid rgba(74,144,217,0.2); border-radius: 10px;
}
.selected-food-info__icon { font-size: 28px; flex-shrink: 0; }
.selected-food-info__name { font-size: 15px; font-weight: 600; }
.selected-food-info__desc { font-size: 12px; color: rgba(255,255,255,0.5); margin-top: 2px; }
/* 拍照区域 */
.camera-frame-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.camera-frame {
width: 100%; height: 280px; background: #0D1117; border-radius: 12px;
position: relative; border: 1px solid rgba(255,255,255,0.08);
display: flex; align-items: center; justify-content: center; overflow: hidden;
transition: border-color 0.3s;
}
.camera-frame.active { border-color: #4a90d9; }
.camera-frame__text { color: rgba(255,255,255,0.25); font-size: 14px; z-index: 1; }
.camera-frame::before, .camera-frame::after {
content: ""; position: absolute; pointer-events: none; z-index: 2;
}
.camera-frame::before {
top: 0; bottom: 0; left: 50%; width: 1px;
border-left: 1px dashed rgba(74,144,217,0.25);
}
.camera-frame::after {
left: 0; right: 0; top: 50%; height: 1px;
border-top: 1px dashed rgba(74,144,217,0.25);
}
.corner { position: absolute; width: 20px; height: 20px; z-index: 3; }
.corner--tl { top: 12px; left: 12px; border-top: 2px solid #4a90d9; border-left: 2px solid #4a90d9; }
.corner--tr { top: 12px; right: 12px; border-top: 2px solid #4a90d9; border-right: 2px solid #4a90d9; }
.corner--bl { bottom: 12px; left: 12px; border-bottom: 2px solid #4a90d9; border-left: 2px solid #4a90d9; }
.corner--br { bottom: 12px; right: 12px; border-bottom: 2px solid #4a90d9; border-right: 2px solid #4a90d9; }
/* 拍照闪烁效果 */
.flash-overlay {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
background: #fff; opacity: 0; pointer-events: none; border-radius: 12px; z-index: 10;
}
.flash-overlay.active { animation: flash 0.5s ease-out; }
@keyframes flash { 0% { opacity: 0; } 30% { opacity: 0.9; } 100% { opacity: 0; } }
.btn-photo {
width: 200px; padding: 14px 8px; border: none; border-radius: 10px;
background: #4a90d9; color: #fff; font-size: 14px; font-weight: 600;
cursor: pointer; display: flex; flex-direction: column; align-items: center;
justify-content: center; gap: 4px; transition: all 0.2s;
}
.btn-photo:hover { background: #3d7fc0; transform: scale(1.03); }
.btn-photo:active { transform: scale(0.97); background: #3570ad; }
.btn-photo.shooting { background: #ff4d4f; pointer-events: none; }
/* 采集结果 */
.result-section { flex: 1; display: flex; flex-direction: column; }
.result-section__title {
font-size: 14px; font-weight: 600; color: rgba(255,255,255,0.7);
margin-bottom: 10px; display: flex; align-items: center; justify-content: space-between;
}
.result-section__count { font-weight: 400; color: rgba(255,255,255,0.45); font-size: 12px; }
.result-grid { display: grid; grid-template-columns: repeat(9, 1fr); gap: 8px; }
.result-cell {
aspect-ratio: 1; background: #121832; border: 1px dashed rgba(255,255,255,0.1);
border-radius: 8px; display: flex; align-items: center; justify-content: center;
font-size: 11px; color: rgba(255,255,255,0.2); transition: all 0.2s;
overflow: hidden; cursor: pointer; position: relative;
}
.result-cell:hover:not(.disabled) { border-color: rgba(74,144,217,0.3); background: rgba(74,144,217,0.06); }
.result-cell.disabled { opacity: 0.3; cursor: not-allowed; }
.result-cell.has-img { border-style: solid; border-color: #52c41a; }
.result-cell .thumb-img-wrap {
width: 100%; height: 100%; border-radius: 7px; position: relative; overflow: hidden;
display: flex; align-items: center; justify-content: center;
}
.result-cell .thumb-icon { font-size: 28px; }
.result-cell .thumb-index {
position: absolute; top: 2px; left: 2px;
width: 16px; height: 16px; border-radius: 50%;
background: rgba(74,144,217,0.9); color: #fff;
font-size: 9px; font-weight: 700;
display: flex; align-items: center; justify-content: center; z-index: 3;
}
.result-cell .check-mark {
position: absolute; bottom: 2px; right: 2px;
width: 16px; height: 16px; border-radius: 50%;
background: rgba(82,196,26,0.9); color: #fff; font-size: 10px;
display: flex; align-items: center; justify-content: center; z-index: 3;
}
@keyframes imgAppear {
0% { transform: scale(0.5); opacity: 0; }
60% { transform: scale(1.1); }
100% { transform: scale(1); opacity: 1; }
}
.result-cell.just-added .thumb-img-wrap { animation: imgAppear 0.4s ease-out; }
.result-cell .remove-btn {
position: absolute; top: 2px; right: 2px;
width: 18px; height: 18px; border-radius: 50%;
background: rgba(255,77,79,0.85); color: #fff; font-size: 10px;
display: none; align-items: center; justify-content: center;
cursor: pointer; border: none; line-height: 1; z-index: 4;
}
.result-cell.has-img:hover .remove-btn { display: flex; }
/* 底部操作按钮 */
.action-bar { display: flex; gap: 12px; margin-top: auto; }
.action-bar .btn-cancel {
flex: 1; padding: 10px; border: 1px solid rgba(255,255,255,0.1); border-radius: 8px;
background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.7); font-size: 14px;
font-weight: 500; cursor: pointer; transition: all 0.2s;
}
.action-bar .btn-cancel:hover { background: rgba(255,255,255,0.1); color: #fff; }
.action-bar .btn-resample {
flex: 1; padding: 10px; border: 1px solid rgba(250,173,22,0.3); border-radius: 8px;
background: rgba(250,173,22,0.08); color: #faad14; font-size: 14px; font-weight: 500;
cursor: pointer; transition: all 0.2s;
}
.action-bar .btn-resample:hover { background: rgba(250,173,22,0.15); border-color: rgba(250,173,22,0.5); }
.action-bar .btn-save {
flex: 1; padding: 10px; border: none; border-radius: 8px;
background: #4a90d9; color: #fff; font-size: 14px; font-weight: 600;
cursor: pointer; transition: background 0.2s;
}
.action-bar .btn-save:hover { background: #3d7fc0; }
.action-bar .btn-save-continue {
flex: 1; padding: 10px; border: none; border-radius: 8px;
background: #52c41a; color: #fff; font-size: 14px; font-weight: 600;
cursor: pointer; transition: background 0.2s;
}
.action-bar .btn-save-continue:hover { background: #45a818; }
/* Toast */
.toast {
position: fixed; top: 60px; left: 50%; transform: translateX(-50%) translateY(-20px);
background: rgba(0,0,0,0.8); color: #fff; padding: 10px 24px; border-radius: 8px;
font-size: 13px; z-index: 1000; opacity: 0; visibility: hidden;
transition: opacity 0.3s, transform 0.3s, visibility 0.3s;
white-space: nowrap; pointer-events: none;
}
.toast.show { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
.toast--success { background: rgba(82,196,26,0.9); }
.toast--warn { background: rgba(250,173,22,0.9); }
.toast--error { background: rgba(255,77,79,0.9); }
</style>
</head>
<body>
<!-- 顶部导航 -->
<div class="top-bar">
<a class="back-btn" id="backBtn" href="javascript:void(0)">&#x25C0; 返回</a>
<span class="top-bar__title">净菜采样</span>
<span class="top-bar__user" id="topUser">--</span>
<button class="logout-btn" onclick="handleLogout()">退出</button>
</div>
<div class="main-content">
<!-- ========== 左侧:净菜选择区 ========== -->
<div class="food-select-area">
<div class="area-title">&#x1F96C; 净菜选择</div>
<!-- 搜索栏 -->
<div class="search-bar">
<input type="text" class="search-input" id="searchInput" placeholder="搜索食材名称...">
</div>
<!-- 类目Tab -->
<div class="filter-tabs" id="catTabs">
<span class="filter-tab active" data-cat="all">全部</span>
<span class="filter-tab" data-cat="叶菜类">叶菜类</span>
<span class="filter-tab" data-cat="根茎类">根茎类</span>
<span class="filter-tab" data-cat="瓜果类">瓜果类</span>
<span class="filter-tab" data-cat="花菜类">花菜类</span>
<span class="filter-tab" data-cat="薯类">薯类</span>
<span class="filter-tab" data-cat="肉禽类">肉禽类</span>
<span class="filter-tab" data-cat="水产类">水产类</span>
</div>
<!-- 净菜列表 -->
<div class="food-list" id="foodList"></div>
</div>
<!-- ========== 右侧:拍照采集区 ========== -->
<div class="capture-area">
<!-- 选中净菜信息 -->
<div class="selected-food-info" id="selectedFoodInfo">
<div class="selected-food-info__icon" id="selectedIcon">&#x1F4F7;</div>
<div>
<div class="selected-food-info__name" id="selectedName">请选择一个净菜</div>
<div class="selected-food-info__desc" id="selectedDesc">点击左侧列表中的净菜进行采样</div>
</div>
</div>
<!-- 摄像头区域 -->
<div class="camera-frame-wrap">
<div class="camera-frame" id="cameraFrame">
<span class="camera-frame__text">摄像头预览区域</span>
<div class="flash-overlay" id="flashOverlay"></div>
<div class="corner corner--tl"></div>
<div class="corner corner--tr"></div>
<div class="corner corner--bl"></div>
<div class="corner corner--br"></div>
</div>
<button class="btn-photo" id="btnPhoto">&#x1F4F8;<br>拍照采集</button>
</div>
<!-- 采集结果 -->
<div class="result-section">
<div class="result-section__title">
<span>&#x1F4CB; 采集结果</span>
<span class="result-section__count" id="resultCount">0/9</span>
</div>
<div class="result-grid" id="resultGrid"></div>
</div>
<!-- 底部操作按钮 -->
<div class="action-bar">
<button class="btn-cancel" id="btnCancel">取消</button>
<button class="btn-resample" id="btnResample">&#x21BB; 重新采样</button>
<button class="btn-save" id="btnSave">保存采集</button>
<button class="btn-save-continue" id="btnSaveContinue">保存并继续</button>
</div>
</div>
</div>
<!-- Toast -->
<div class="toast" id="toast"></div>
<script>
/* 退出登录 */
function handleLogout() {
window.location.href = '00-welcome.html';
}
/* 获取 URL 参数 */
function getUrlParam(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
var r = window.location.search.substr(1).match(reg);
if (r !== null) return decodeURIComponent(r[2]);
return null;
}
var userName = getUrlParam('user');
if (userName) {
document.getElementById('topUser').textContent = '操作员: ' + userName;
}
/* ===== 食材数据(带净菜类型标识) ===== */
var FOOD_DATA = [
{ id: 1, name: '菠菜', icon: '&#x1F96C;', cat: '叶菜类', spec: '35mm*1mm*1mm · 长条 · 平刀' },
{ id: 2, name: '大白菜', icon: '&#x1F96C;', cat: '叶菜类', spec: '50mm*30mm*30mm · 宽段 · 平刀' },
{ id: 3, name: '圆白菜', icon: '&#x1F96C;', cat: '叶菜类', spec: '30mm*2mm*2mm · 细丝 · 平刀' },
{ id: 4, name: '油菜', icon: '&#x1F96C;', cat: '叶菜类', spec: '40mm*10mm*10mm · 宽段 · 平刀' },
{ id: 5, name: '生菜', icon: '&#x1F96C;', cat: '叶菜类', spec: '30mm*2mm*2mm · 细丝 · 平刀' },
{ id: 6, name: '芹菜', icon: '&#x1F96C;', cat: '叶菜类', spec: '40mm*10mm*10mm · 宽段 · 平刀' },
{ id: 7, name: '小白菜', icon: '&#x1F96C;', cat: '叶菜类', spec: '30mm*10mm*10mm · 宽段 · 平刀' },
{ id: 8, name: '西兰花', icon: '&#x1F966;', cat: '花菜类', spec: '30mm*30mm*30mm · 方丁 · 平刀' },
{ id: 9, name: '花菜', icon: '&#x1F966;', cat: '花菜类', spec: '30mm*30mm*30mm · 方丁 · 平刀' },
{ id: 10, name: '黄瓜', icon: '&#x1F952;', cat: '瓜果类', spec: '30mm*30mm*3mm · 圆片 · 平刀' },
{ id: 11, name: '西红柿', icon: '&#x1F345;', cat: '瓜果类', spec: '25mm*25mm*20mm · 楔形块 · 平刀' },
{ id: 12, name: '茄子', icon: '&#x1F346;', cat: '瓜果类', spec: '25mm*25mm*25mm · 方丁 · 平刀' },
{ id: 13, name: '青椒', icon: '&#x1FAD1;', cat: '瓜果类', spec: '30mm*3mm*3mm · 长条 · 平刀' },
{ id: 14, name: '豆角', icon: '&#x1FAD8;', cat: '瓜果类', spec: '40mm*10mm*10mm · 宽段 · 平刀' },
{ id: 15, name: '胡萝卜', icon: '&#x1F955;', cat: '根茎类', spec: '20mm*1mm*1mm · 细丝 · 平刀' },
{ id: 16, name: '莴笋', icon: '&#x1F96C;', cat: '根茎类', spec: '30mm*2mm*2mm · 细丝 · 平刀' },
{ id: 17, name: '莲藕', icon: '&#x1FAD1;', cat: '根茎类', spec: '35mm*35mm*3mm · 圆片 · 平刀' },
{ id: 18, name: '洋葱', icon: '&#x1F9C5;', cat: '根茎类', spec: '30mm*2mm*2mm · 细丝 · 平刀' },
{ id: 19, name: '土豆', icon: '&#x1F954;', cat: '薯类', spec: '35mm*1mm*1mm · 长条 · 平刀' },
{ id: 20, name: '红薯', icon: '&#x1F360;', cat: '薯类', spec: '20mm*20mm*20mm · 方丁 · 平刀' },
{ id: 21, name: '紫薯', icon: '&#x1F360;', cat: '薯类', spec: '20mm*20mm*20mm · 方丁 · 平刀' },
{ id: 22, name: '猪里脊', icon: '&#x1F969;', cat: '肉禽类', spec: '40mm*3mm*3mm · 长条 · 平刀' },
{ id: 23, name: '五花肉', icon: '&#x1F969;', cat: '肉禽类', spec: '50mm*30mm*3mm · 圆片 · 平刀' },
{ id: 24, name: '鸡胸肉', icon: '&#x1F9A6;', cat: '肉禽类', spec: '40mm*3mm*3mm · 长条 · 平刀' },
{ id: 25, name: '草鱼', icon: '&#x1F41F;', cat: '水产类', spec: '30mm*30mm*3mm · 圆片 · 平刀' },
{ id: 26, name: '虾仁', icon: '&#x1F990;', cat: '水产类', spec: '原形态 · 整 · 去壳' }
];
/* ===== 状态变量 ===== */
var selectedFood = null;
var capturedImages = [];
var lastAddedIndex = -1;
var currentCat = 'all';
var searchKeyword = '';
var MAX_IMAGES = 9;
/* ===== DOM 引用 ===== */
var foodListEl = document.getElementById('foodList');
var searchInputEl = document.getElementById('searchInput');
var catTabsEl = document.getElementById('catTabs');
var selectedIconEl = document.getElementById('selectedIcon');
var selectedNameEl = document.getElementById('selectedName');
var selectedDescEl = document.getElementById('selectedDesc');
var cameraFrameEl = document.getElementById('cameraFrame');
var flashOverlayEl = document.getElementById('flashOverlay');
var btnPhotoEl = document.getElementById('btnPhoto');
var resultGridEl = document.getElementById('resultGrid');
var resultCountEl = document.getElementById('resultCount');
var toastEl = document.getElementById('toast');
/* ===== 解析 URL 参数 ===== */
function getQueryParam(key) {
var query = window.location.search.substring(1);
var pairs = query.split('&');
for (var i = 0; i < pairs.length; i++) {
var parts = pairs[i].split('=');
if (parts[0] === key) return decodeURIComponent(parts[1] || '');
}
return null;
}
/* ===== 初始化 ===== */
function init() {
renderFoodList();
renderResultGrid();
bindEvents();
/* 处理从采样历史进入的补充采集 */
var resampleFoodId = getQueryParam('resampleFoodId');
if (resampleFoodId) {
var fid = parseInt(resampleFoodId);
for (var i = 0; i < FOOD_DATA.length; i++) {
if (FOOD_DATA[i].id === fid) {
selectedFood = FOOD_DATA[i];
renderFoodList();
updateSelectedFoodInfo();
showToast('已自动选中:' + selectedFood.name + ',可直接追加采集', 2000, 'success');
break;
}
}
}
}
/* ===== 筛选 ===== */
function getFilteredFoods() {
return FOOD_DATA.filter(function(food) {
if (currentCat !== 'all' && food.cat !== currentCat) return false;
if (searchKeyword && food.name.indexOf(searchKeyword) === -1) return false;
return true;
});
}
/* ===== 渲染净菜列表 ===== */
function renderFoodList() {
var filtered = getFilteredFoods();
if (filtered.length === 0) {
foodListEl.innerHTML = '<div class="empty-state"><div class="empty-state__icon">&#x1F50D;</div><div class="empty-state__text">未找到匹配的净菜</div></div>';
return;
}
var html = '';
for (var i = 0; i < filtered.length; i++) {
var food = filtered[i];
var isSelected = selectedFood && selectedFood.id === food.id;
html += '<div class="food-item' + (isSelected ? ' selected' : '') + '" data-id="' + food.id + '">'
+ '<div class="food-item__icon">' + food.icon + '</div>'
+ '<div class="food-item__info">'
+ '<div class="food-item__name">' + food.name + '</div>'
+ '<div class="food-item__detail">' + food.cat + ' · ' + food.spec + '</div>'
+ '</div>'
+ '</div>';
}
foodListEl.innerHTML = html;
}
/* ===== 渲染采集结果网格 ===== */
function renderResultGrid() {
var html = '';
for (var i = 0; i < MAX_IMAGES; i++) {
if (i < capturedImages.length) {
var isJustAdded = (i === lastAddedIndex);
html += '<div class="result-cell has-img' + (isJustAdded ? ' just-added' : '') + '" data-index="' + i + '">'
+ '<div class="thumb-img-wrap">'
+ '<span class="thumb-index">' + (i + 1) + '</span>'
+ '<span class="thumb-icon">' + capturedImages[i].icon + '</span>'
+ '<span class="check-mark">&#x2714;</span>'
+ '</div>'
+ '<button class="remove-btn" data-index="' + i + '">&#x2716;</button>'
+ '</div>';
} else if (i === capturedImages.length) {
html += '<div class="result-cell" data-index="' + i + '">+添加</div>';
} else {
html += '<div class="result-cell disabled" data-index="' + i + '"></div>';
}
}
resultGridEl.innerHTML = html;
resultCountEl.textContent = capturedImages.length + '/' + MAX_IMAGES;
lastAddedIndex = -1;
}
/* ===== 更新选中净菜信息 ===== */
function updateSelectedFoodInfo() {
if (!selectedFood) {
selectedIconEl.innerHTML = '&#x1F4F7;';
selectedNameEl.textContent = '请选择一个净菜';
selectedDescEl.textContent = '点击左侧列表中的净菜进行采样';
return;
}
selectedIconEl.innerHTML = selectedFood.icon;
selectedNameEl.textContent = selectedFood.name;
selectedDescEl.textContent = selectedFood.cat + ' · ' + selectedFood.spec + ' · 样本采集';
}
/* ===== Toast ===== */
function showToast(msg, duration, type) {
toastEl.textContent = msg;
toastEl.className = 'toast';
if (type === 'success') toastEl.classList.add('toast--success');
else if (type === 'warn') toastEl.classList.add('toast--warn');
else if (type === 'error') toastEl.classList.add('toast--error');
toastEl.classList.add('show');
clearTimeout(toastEl._timer);
var t = duration || 2000;
toastEl._timer = setTimeout(function() { toastEl.classList.remove('show'); }, t);
}
/* ===== 事件绑定 ===== */
function bindEvents() {
/* 净菜列表点击 */
foodListEl.addEventListener('click', function(e) {
var item = e.target.closest('.food-item');
if (!item) return;
var id = parseInt(item.getAttribute('data-id'));
var food = null;
for (var i = 0; i < FOOD_DATA.length; i++) {
if (FOOD_DATA[i].id === id) { food = FOOD_DATA[i]; break; }
}
if (!food) return;
selectedFood = food;
renderFoodList();
updateSelectedFoodInfo();
showToast('已选中:' + food.name, 1200, 'success');
});
/* 类目Tab切换 */
catTabsEl.addEventListener('click', function(e) {
var tab = e.target.closest('.filter-tab');
if (!tab) return;
currentCat = tab.getAttribute('data-cat');
var tabs = catTabsEl.querySelectorAll('.filter-tab');
for (var i = 0; i < tabs.length; i++) tabs[i].classList.remove('active');
tab.classList.add('active');
renderFoodList();
});
/* 搜索 */
var searchTimer = null;
searchInputEl.addEventListener('input', function() {
clearTimeout(searchTimer);
searchTimer = setTimeout(function() {
searchKeyword = searchInputEl.value.replace(/^\s+|\s+$/g, '');
renderFoodList();
}, 300);
});
/* 拍照按钮 */
btnPhotoEl.addEventListener('click', function() {
if (!selectedFood) {
showToast('请先选择一个净菜', 1500, 'warn');
return;
}
if (capturedImages.length >= MAX_IMAGES) {
showToast('已达采集上限(9张)', 1500, 'warn');
return;
}
btnPhotoEl.classList.add('shooting');
cameraFrameEl.classList.add('active');
flashOverlayEl.classList.remove('active');
void flashOverlayEl.offsetWidth;
flashOverlayEl.classList.add('active');
setTimeout(function() {
btnPhotoEl.classList.remove('shooting');
cameraFrameEl.classList.remove('active');
capturedImages.push({ id: selectedFood.id, icon: selectedFood.icon });
lastAddedIndex = capturedImages.length - 1;
renderResultGrid();
showToast('采集成功!已采集 ' + capturedImages.length + '/' + MAX_IMAGES + ' 张', 1500, 'success');
}, 2000);
});
/* 结果网格交互 */
resultGridEl.addEventListener('click', function(e) {
var removeBtn = e.target.closest('.remove-btn');
if (removeBtn) {
e.stopPropagation();
var idx = parseInt(removeBtn.getAttribute('data-index'));
capturedImages.splice(idx, 1);
renderResultGrid();
showToast('已删除采集图片', 1200);
return;
}
var cell = e.target.closest('.result-cell');
if (!cell || cell.classList.contains('disabled')) return;
if (!selectedFood) {
showToast('请先选择一个净菜', 1500, 'warn');
return;
}
if (capturedImages.length >= MAX_IMAGES) {
showToast('已达采集上限', 1500, 'warn');
return;
}
btnPhotoEl.click();
});
/* 保存采集 → 返回欢迎页 */
document.getElementById('btnSave').addEventListener('click', function() {
if (!selectedFood) { showToast('请先选择一个净菜', 1500, 'warn'); return; }
if (capturedImages.length === 0) { showToast('请至少采集1张图片', 1500, 'warn'); return; }
showToast('采集数据已保存', 1500, 'success');
setTimeout(function() {
window.location.href = '00-welcome.html';
}, 1500);
});
/* 保存并继续 → 重置表单继续采集 */
document.getElementById('btnSaveContinue').addEventListener('click', function() {
if (!selectedFood) { showToast('请先选择一个净菜', 1500, 'warn'); return; }
if (capturedImages.length === 0) { showToast('请至少采集1张图片', 1500, 'warn'); return; }
showToast('采集数据已保存,请继续采集下一个净菜', 1500, 'success');
selectedFood = null;
capturedImages = [];
renderFoodList();
renderResultGrid();
updateSelectedFoodInfo();
});
/* 取消 */
document.getElementById('btnCancel').addEventListener('click', function() {
if (capturedImages.length === 0 && !selectedFood) {
window.location.href = '00-welcome.html';
return;
}
selectedFood = null;
capturedImages = [];
renderFoodList();
renderResultGrid();
updateSelectedFoodInfo();
showToast('已取消当前采集', 1000);
});
/* 重新采样 */
document.getElementById('btnResample').addEventListener('click', function() {
if (capturedImages.length === 0 && !selectedFood) {
showToast('当前无采样数据', 1500, 'warn');
return;
}
selectedFood = null;
capturedImages = [];
renderFoodList();
renderResultGrid();
updateSelectedFoodInfo();
showToast('已清空,请重新选择净菜开始采样', 1500);
});
}
/* 启动 */
init();
</script>
<script>
/* 返回按钮:从哪来回哪去 */
(function() {
var backBtn = document.getElementById('backBtn');
if (backBtn) {
var params = new URLSearchParams(window.location.search);
var referer = params.get('referer');
if (referer) {
backBtn.href = referer;
} else if (document.referrer && document.referrer.indexOf(window.location.hostname) !== -1) {
backBtn.href = document.referrer;
} else {
backBtn.href = '01-menu.html';
}
}
})();
</script>
</body>
</html>
@@ -0,0 +1,525 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1280, initial-scale=1.0">
<title>净菜加工秤 - 采样历史 | 蚁熊智能餐养平台</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden;
display: flex; flex-direction: column;
}
/* ---- 顶部导航栏 ---- */
.top-bar {
display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px;
flex-shrink: 0;
}
.back-btn { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s; }
.back-btn:hover { color: #fff; }
.top-bar__title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
.top-bar__user { font-size: 12px; color: rgba(255,255,255,0.5); }
.logout-btn {
padding: 4px 10px; font-size: 11px;
background: rgba(255,77,79,0.08); border: 1px solid rgba(255,77,79,0.2);
border-radius: 5px; color: rgba(255,77,79,0.7); cursor: pointer;
transition: all 0.2s; font-family: inherit; margin-left: 10px;
}
.logout-btn:hover { background: rgba(255,77,79,0.18); color: #ff6b6d; border-color: rgba(255,77,79,0.4); }
/* ---- 主内容区:左右两列 ---- */
.main-content { display: flex; gap: 16px; padding: 16px 20px; height: calc(100% - 44px); }
/* ===== 左侧:快捷查找面板 ===== */
.search-panel {
width: 260px; flex-shrink: 0; background: #1a2b4a; border-radius: 12px;
padding: 16px; display: flex; flex-direction: column; gap: 16px;
}
.search-panel__title { font-size: 14px; font-weight: 600; color: rgba(255,255,255,0.7); }
.search-panel__input {
width: 100%; padding: 10px 14px; background: #121832;
border: 1px solid rgba(255,255,255,0.1); border-radius: 8px;
color: #fff; font-size: 13px; outline: none; transition: border-color 0.2s;
}
.search-panel__input:focus { border-color: #4a90d9; }
.search-panel__input::placeholder { color: rgba(255,255,255,0.3); }
.cat-tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.cat-tab {
padding: 5px 10px; font-size: 12px; border-radius: 4px;
background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.55);
cursor: pointer; transition: all 0.2s; border: 1px solid transparent;
}
.cat-tab.active { background: #4a90d9; color: #fff; }
.cat-tab:hover:not(.active) { border-color: rgba(255,255,255,0.15); color: rgba(255,255,255,0.75); }
.search-panel__stats {
margin-top: auto; padding-top: 12px;
border-top: 1px solid rgba(255,255,255,0.06);
font-size: 12px; color: rgba(255,255,255,0.4);
}
.search-panel__stats em { font-style: normal; color: #4a90d9; font-weight: 600; }
/* ===== 右侧:瀑布流 ===== */
.waterfall-area { flex: 1; overflow-y: auto; }
.waterfall-area::-webkit-scrollbar { width: 6px; }
.waterfall-area::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 3px; }
.waterfall { column-count: 3; column-gap: 16px; }
.waterfall-card {
break-inside: avoid; background: #1a2b4a; border-radius: 12px;
padding: 16px; margin-bottom: 16px;
border: 1px solid rgba(255,255,255,0.06);
cursor: pointer; transition: all 0.2s;
}
.waterfall-card:hover {
border-color: rgba(74,144,217,0.3);
background: rgba(74,144,217,0.06);
transform: translateY(-2px);
}
/* 卡片头部 */
.card-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.card-icon { font-size: 32px; flex-shrink: 0; }
.card-name { font-size: 16px; font-weight: 600; margin-bottom: 4px; }
.card-spec { font-size: 11px; color: rgba(255,255,255,0.45); }
/* 卡片缩略图预览 */
.card-previews { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-bottom: 12px; }
.card-preview {
aspect-ratio: 1; border-radius: 6px; overflow: hidden;
background: rgba(255,255,255,0.04); display: flex; align-items: center; justify-content: center;
font-size: 24px;
}
.card-preview.hidden { visibility: hidden; }
/* 卡片底部信息 */
.card-footer { display: flex; align-items: center; justify-content: space-between; font-size: 12px; color: rgba(255,255,255,0.4); }
.card-count { color: #4a90d9; font-weight: 500; }
/* ---- 详情弹窗 ---- */
.modal-overlay {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.7);
display: flex; align-items: center; justify-content: center;
z-index: 999;
opacity: 0; visibility: hidden;
transition: opacity 0.3s, visibility 0.3s;
}
.modal-overlay.active { opacity: 1; visibility: visible; }
.modal-container {
background: #1a2b4a; border-radius: 16px; padding: 28px;
width: 700px; max-height: 80vh; overflow-y: auto;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
transform: translateY(-20px); transition: transform 0.3s;
}
.modal-overlay.active .modal-container { transform: translateY(0); }
.modal-header { display: flex; align-items: center; gap: 14px; margin-bottom: 24px; }
.modal-header__left { display: flex; align-items: center; gap: 14px; flex: 1; }
.modal-header__right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.modal-icon { font-size: 36px; flex-shrink: 0; }
.modal-title { font-size: 20px; font-weight: 600; }
.modal-subtitle { font-size: 13px; color: rgba(255,255,255,0.45); margin-top: 4px; }
.modal-time { font-size: 12px; color: rgba(255,255,255,0.35); text-align: right; line-height: 1.5; }
.modal-count {
display: flex; align-items: baseline; gap: 3px;
font-size: 14px; color: #52c41a; font-weight: 700;
background: rgba(82,196,26,0.1); border-radius: 6px;
padding: 4px 8px;
}
.modal-count .count-label { font-size: 10px; font-weight: 400; color: rgba(82,196,26,0.6); }
/* 图片网格 */
.image-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.image-cell {
aspect-ratio: 1; border-radius: 10px; overflow: hidden;
position: relative; border: 2px solid rgba(255,255,255,0.06);
display: flex; align-items: center; justify-content: center;
font-size: 48px; background: rgba(255,255,255,0.02);
}
.image-cell__time {
position: absolute; bottom: 0; left: 0; right: 0;
background: rgba(0,0,0,0.6); color: rgba(255,255,255,0.75);
font-size: 11px; text-align: center; padding: 3px 6px;
pointer-events: none;
}
.image-cell .remove-btn {
position: absolute; top: 4px; right: 4px;
width: 22px; height: 22px; border-radius: 50%;
background: rgba(255,77,79,0.9); color: #fff; font-size: 12px;
display: none; align-items: center; justify-content: center;
cursor: pointer; border: none; line-height: 1;
}
.image-cell:hover .remove-btn { display: flex; }
/* 弹窗信息行 */
.modal-info {
display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px;
margin-bottom: 20px; padding: 12px 16px;
background: rgba(255,255,255,0.03); border-radius: 8px;
}
.modal-info__label { font-size: 11px; color: rgba(255,255,255,0.4); margin-bottom: 2px; }
.modal-info__value { font-size: 14px; font-weight: 500; }
/* 底部操作 */
.modal-actions { display: flex; gap: 12px; margin-top: 24px; }
.modal-actions button {
flex: 1; padding: 10px; border-radius: 8px; font-size: 14px; font-weight: 500;
cursor: pointer; transition: all 0.2s;
}
.modal-actions .btn-close {
background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.7);
border: 1px solid rgba(255,255,255,0.08);
}
.modal-actions .btn-close:hover { background: rgba(255,255,255,0.1); color: #fff; }
.modal-actions .btn-resample {
background: rgba(255,193,7,0.1); color: #ffc107;
border: 1px solid rgba(255,193,7,0.3);
}
.modal-actions .btn-resample:hover { background: rgba(255,193,7,0.2); border-color: #ffc107; }
/* Toast */
.toast {
position: fixed; top: 60px; left: 50%; transform: translateX(-50%) translateY(-20px);
background: rgba(0,0,0,0.8); color: #fff; padding: 10px 24px; border-radius: 8px;
font-size: 13px; z-index: 1000; opacity: 0; visibility: hidden;
transition: opacity 0.3s, transform 0.3s, visibility 0.3s;
white-space: nowrap; pointer-events: none;
}
.toast.show { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
</style>
</head>
<body>
<!-- 顶部导航 -->
<div class="top-bar">
<a class="back-btn" id="backBtn" href="javascript:void(0)">&#x25C0; 返回</a>
<span class="top-bar__title">采样历史</span>
<span class="top-bar__user" id="topUser">--</span>
<button class="logout-btn" onclick="handleLogout()">退出</button>
</div>
<!-- 主内容 -->
<div class="main-content">
<!-- 左侧:快捷查找面板 -->
<div class="search-panel">
<div class="search-panel__title">&#x1F50D; 快捷查找</div>
<input type="text" class="search-panel__input" id="searchInput" placeholder="输入食材名称...">
<div>
<div class="search-panel__title" style="margin-bottom:8px;">&#x1F4C1; 按类目筛选</div>
<div class="cat-tabs" id="catTabs">
<span class="cat-tab active" data-cat="all">全部</span>
<span class="cat-tab" data-cat="叶菜类">叶菜类</span>
<span class="cat-tab" data-cat="根茎类">根茎类</span>
<span class="cat-tab" data-cat="瓜果类">瓜果类</span>
<span class="cat-tab" data-cat="花菜类">花菜类</span>
<span class="cat-tab" data-cat="薯类">薯类</span>
<span class="cat-tab" data-cat="肉禽类">肉禽类</span>
<span class="cat-tab" data-cat="水产类">水产类</span>
</div>
</div>
<div class="search-panel__stats">
<em id="totalCount">0</em> 条记录
</div>
</div>
<!-- 右侧:瀑布流 -->
<div class="waterfall-area">
<div class="waterfall" id="waterfall"></div>
</div>
</div>
<!-- 详情弹窗 -->
<div class="modal-overlay" id="detailModal">
<div class="modal-container">
<div class="modal-header">
<div class="modal-header__left">
<div class="modal-icon" id="modalIcon"></div>
<div>
<div class="modal-title" id="modalTitle"></div>
<div class="modal-subtitle" id="modalSubtitle"></div>
</div>
</div>
<div class="modal-header__right">
<div class="modal-count" id="modalCount"></div>
<div class="modal-time" id="modalTime"></div>
</div>
</div>
<!-- 采样信息 -->
<div class="modal-info" id="modalInfo"></div>
<!-- 图片网格 -->
<div class="image-grid" id="imageGrid"></div>
<div class="modal-actions">
<button class="btn-close" onclick="closeModal()">&#x2716; 关闭</button>
<button class="btn-resample" id="btnResample" onclick="resampleFood()">&#x1F4F8; 补充采集</button>
</div>
</div>
</div>
<!-- Toast -->
<div class="toast" id="toast"></div>
<script>
/* 退出登录 */
function handleLogout() {
window.location.href = '00-welcome.html';
}
/* 获取 URL 参数 */
function getUrlParam(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
var r = window.location.search.substr(1).match(reg);
if (r !== null) return decodeURIComponent(r[2]);
return null;
}
var userName = getUrlParam('user');
if (userName) {
document.getElementById('topUser').textContent = '操作员: ' + userName;
}
/* ===== 采样历史数据 ===== */
var SAMPLING_HISTORY = [
{ id: 1, foodId: 19, name: '土豆', icon: '&#x1F954;', catLabel: '薯类', spec: '35mm*1mm*1mm · 长条 · 平刀', count: 5, time: '2026-06-17 10:30', images: [19,19,19,19,19] },
{ id: 2, foodId: 10, name: '黄瓜', icon: '&#x1F952;', catLabel: '瓜果类', spec: '30mm*30mm*3mm · 圆片 · 平刀', count: 3, time: '2026-06-17 09:15', images: [10,10,10] },
{ id: 3, foodId: 2, name: '大白菜', icon: '&#x1F96C;', catLabel: '叶菜类', spec: '50mm*30mm*30mm · 宽段 · 平刀', count: 4, time: '2026-06-17 08:45', images: [2,2,2,2] },
{ id: 4, foodId: 15, name: '胡萝卜', icon: '&#x1F955;', catLabel: '根茎类', spec: '20mm*1mm*1mm · 细丝 · 平刀', count: 6, time: '2026-06-16 14:20', images: [15,15,15,15,15,15] },
{ id: 5, foodId: 11, name: '西红柿', icon: '&#x1F345;', catLabel: '瓜果类', spec: '25mm*25mm*20mm · 楔形块 · 平刀', count: 2, time: '2026-06-16 11:30', images: [11,11] },
{ id: 6, foodId: 18, name: '洋葱', icon: '&#x1F9C5;', catLabel: '根茎类', spec: '30mm*2mm*2mm · 细丝 · 平刀', count: 4, time: '2026-06-16 10:00', images: [18,18,18,18] },
{ id: 7, foodId: 17, name: '莲藕', icon: '&#x1FAD1;', catLabel: '根茎类', spec: '35mm*35mm*3mm · 圆片 · 平刀', count: 3, time: '2026-06-15 15:10', images: [17,17,17] },
{ id: 8, foodId: 13, name: '青椒', icon: '&#x1FAD1;', catLabel: '瓜果类', spec: '30mm*3mm*3mm · 长条 · 平刀', count: 7, time: '2026-06-15 09:30', images: [13,13,13,13,13,13,13] },
{ id: 9, foodId: 6, name: '芹菜', icon: '&#x1F96C;', catLabel: '叶菜类', spec: '40mm*10mm*10mm · 宽段 · 平刀', count: 5, time: '2026-06-15 08:20', images: [6,6,6,6,6] },
{ id: 10, foodId: 14, name: '豆角', icon: '&#x1FAD8;', catLabel: '瓜果类', spec: '40mm*10mm*10mm · 宽段 · 平刀', count: 3, time: '2026-06-14 14:00', images: [14,14,14] },
{ id: 11, foodId: 20, name: '红薯', icon: '&#x1F360;', catLabel: '薯类', spec: '20mm*20mm*20mm · 方丁 · 平刀', count: 4, time: '2026-06-14 10:20', images: [20,20,20,20] },
{ id: 12, foodId: 3, name: '圆白菜', icon: '&#x1F96C;', catLabel: '叶菜类', spec: '30mm*2mm*2mm · 细丝 · 平刀', count: 2, time: '2026-06-14 09:00', images: [3,3] }
];
var currentDetailId = null;
var currentCat = 'all';
var searchKeyword = '';
/* ===== DOM 引用 ===== */
var waterfallEl = document.getElementById('waterfall');
var modalEl = document.getElementById('detailModal');
var modalIconEl = document.getElementById('modalIcon');
var modalTitleEl = document.getElementById('modalTitle');
var modalSubtitleEl = document.getElementById('modalSubtitle');
var modalCountEl = document.getElementById('modalCount');
var modalTimeEl = document.getElementById('modalTime');
var modalInfoEl = document.getElementById('modalInfo');
var imageGridEl = document.getElementById('imageGrid');
var toastEl = document.getElementById('toast');
var searchInputEl = document.getElementById('searchInput');
var catTabsEl = document.getElementById('catTabs');
var totalCountEl = document.getElementById('totalCount');
/* ===== 筛选 ===== */
function getFilteredRecords() {
return SAMPLING_HISTORY.filter(function(record) {
if (currentCat !== 'all' && record.catLabel !== currentCat) return false;
if (searchKeyword && record.name.indexOf(searchKeyword) === -1) return false;
return true;
});
}
/* ===== 渲染瀑布流 ===== */
function renderWaterfall() {
var filtered = getFilteredRecords();
totalCountEl.textContent = filtered.length;
if (filtered.length === 0) {
waterfallEl.innerHTML = '<div style="text-align:center;padding:80px 0;color:rgba(255,255,255,0.3);">未找到匹配的采样记录</div>';
return;
}
var html = '';
for (var i = 0; i < filtered.length; i++) {
var record = filtered[i];
var previewCount = Math.min(record.count, 3);
var previews = '';
for (var j = 0; j < 3; j++) {
if (j < previewCount) {
previews += '<div class="card-preview">' + record.icon + '</div>';
} else {
previews += '<div class="card-preview hidden"></div>';
}
}
html += '<div class="waterfall-card" data-id="' + record.id + '" onclick="openDetail(' + record.id + ')">'
+ '<div class="card-header">'
+ '<div class="card-icon">' + record.icon + '</div>'
+ '<div>'
+ '<div class="card-name">' + record.name + '</div>'
+ '<div class="card-spec">' + record.spec + '</div>'
+ '</div>'
+ '</div>'
+ '<div class="card-previews">' + previews + '</div>'
+ '<div class="card-footer">'
+ '<span class="card-count">已采 ' + record.count + ' 张</span>'
+ '<span>' + record.time.substring(5) + '</span>'
+ '</div>'
+ '</div>';
}
waterfallEl.innerHTML = html;
}
/* ===== 打开详情弹窗 ===== */
function openDetail(id) {
var record = null;
for (var i = 0; i < SAMPLING_HISTORY.length; i++) {
if (SAMPLING_HISTORY[i].id === id) { record = SAMPLING_HISTORY[i]; break; }
}
if (!record) return;
currentDetailId = id;
modalIconEl.innerHTML = record.icon;
modalTitleEl.textContent = record.name;
modalSubtitleEl.textContent = record.catLabel + ' · ' + record.spec;
modalCountEl.innerHTML = record.count + '<span class="count-label">张</span>';
var parts = record.time.split(' ');
modalTimeEl.innerHTML = '<div>' + (parts[0] || '') + '</div><div>' + (parts[1] || '') + '</div>';
/* 采样信息 */
modalInfoEl.innerHTML =
'<div><div class="modal-info__label">食材名称</div><div class="modal-info__value">' + record.name + '</div></div>'
+ '<div><div class="modal-info__label">类目</div><div class="modal-info__value">' + record.catLabel + '</div></div>'
+ '<div><div class="modal-info__label">净菜类型</div><div class="modal-info__value">' + record.spec + '</div></div>'
+ '<div><div class="modal-info__label">采集时间</div><div class="modal-info__value">' + record.time + '</div></div>';
/* 已满9张时隐藏补充采集按钮 */
var btnResample = document.getElementById('btnResample');
btnResample.style.display = record.count >= 9 ? 'none' : '';
renderImageGrid(record);
modalEl.classList.add('active');
}
/* ===== 渲染图片网格 ===== */
function renderImageGrid(record) {
var MAX_IMAGES = 9;
var html = '';
for (var i = 0; i < record.images.length; i++) {
var canRemove = record.images.length > 1;
html += '<div class="image-cell">'
+ record.icon
+ '<span class="image-cell__time">' + record.time + '</span>'
+ (canRemove ? '<button class="remove-btn" data-idx="' + i + '">&#x2716;</button>' : '')
+ '</div>';
}
var remaining = MAX_IMAGES - record.images.length;
for (var j = 0; j < remaining; j++) {
html += '<div class="image-cell" style="opacity:0.3;"></div>';
}
imageGridEl.innerHTML = html;
}
/* ===== 删除图片 ===== */
function removeImage(idx) {
var record = null;
for (var i = 0; i < SAMPLING_HISTORY.length; i++) {
if (SAMPLING_HISTORY[i].id === currentDetailId) { record = SAMPLING_HISTORY[i]; break; }
}
if (!record || record.images.length <= 1) return;
record.images.splice(idx, 1);
record.count = record.images.length;
renderImageGrid(record);
renderWaterfall();
showToast('删除成功', 1200);
}
/* ===== 关闭弹窗 ===== */
function closeModal() {
modalEl.classList.remove('active');
currentDetailId = null;
}
/* ===== 补充采集 ===== */
function resampleFood() {
if (!currentDetailId) return;
var record = null;
for (var i = 0; i < SAMPLING_HISTORY.length; i++) {
if (SAMPLING_HISTORY[i].id === currentDetailId) { record = SAMPLING_HISTORY[i]; break; }
}
if (!record) return;
closeModal();
setTimeout(function() {
window.location.href = '04-sampling.html?resampleFoodId=' + record.foodId;
}, 300);
}
/* ===== Toast ===== */
function showToast(msg, duration) {
toastEl.textContent = msg;
toastEl.classList.add('show');
clearTimeout(toastEl._timer);
var t = duration || 2000;
toastEl._timer = setTimeout(function() { toastEl.classList.remove('show'); }, t);
}
/* ===== 事件绑定 ===== */
imageGridEl.addEventListener('click', function(e) {
var removeBtn = e.target.closest('.remove-btn');
if (removeBtn) {
e.stopPropagation();
var idx = parseInt(removeBtn.getAttribute('data-idx'));
removeImage(idx);
return;
}
});
modalEl.addEventListener('click', function(e) {
if (e.target === modalEl) closeModal();
});
catTabsEl.addEventListener('click', function(e) {
var tab = e.target.closest('.cat-tab');
if (!tab) return;
currentCat = tab.getAttribute('data-cat');
var tabs = catTabsEl.querySelectorAll('.cat-tab');
for (var i = 0; i < tabs.length; i++) tabs[i].classList.remove('active');
tab.classList.add('active');
renderWaterfall();
});
var searchTimer = null;
searchInputEl.addEventListener('input', function() {
clearTimeout(searchTimer);
searchTimer = setTimeout(function() {
searchKeyword = searchInputEl.value.replace(/^\s+|\s+$/g, '');
renderWaterfall();
}, 300);
});
/* ===== 初始化 ===== */
renderWaterfall();
</script>
<script>
/* 返回按钮:从哪来回哪去 */
(function() {
var backBtn = document.getElementById('backBtn');
if (backBtn) {
var params = new URLSearchParams(window.location.search);
var referer = params.get('referer');
if (referer) {
backBtn.href = referer;
} else if (document.referrer && document.referrer.indexOf(window.location.hostname) !== -1) {
backBtn.href = document.referrer;
} else {
backBtn.href = '01-menu.html';
}
}
})();
</script>
</body>
</html>
@@ -43,6 +43,30 @@
</div>
<span class="card__arrow">&#x203A;</span>
</a>
<a class="card" href="04-sampling.html">
<span class="card__icon">&#x1F50D;</span>
<div class="card__info">
<div class="card__title">净菜采样</div>
<div class="card__desc">采样操作、外观等级判定、保存采样</div>
</div>
<span class="card__arrow">&#x203A;</span>
</a>
<a class="card" href="05-sampling-history.html">
<span class="card__icon">&#x1F4CB;</span>
<div class="card__info">
<div class="card__title">采样历史</div>
<div class="card__desc">采样记录查看与筛选</div>
</div>
<span class="card__arrow">&#x203A;</span>
</a>
<a class="card" href="02-history.html">
<span class="card__icon">&#x1F4DD;</span>
<div class="card__info">
<div class="card__title">验收记录</div>
<div class="card__desc">历史验收记录查看与筛选</div>
</div>
<span class="card__arrow">&#x203A;</span>
</a>
</div>
</body>
</html>
@@ -267,7 +267,7 @@
header.innerHTML =
'<span class="task-card__order-info"><span class="task-card__order-info__label">订单号:</span><span class="task-card__order-info__value">' + order.orderNo + '</span></span>' +
'<span class="order-type-tag ' + orderTypeCls + '">' + orderTypeLabel + '</span>' +
'<span class="task-card__arrival">&#x23F0; 任务截止时间:<span class="task-card__arrival__time">' + order.expectedArrival + '</span></span>' +
'<span class="task-card__arrival">&#x23F0; 任务完成时间:<span class="task-card__arrival__time">' + order.expectedArrival + '</span></span>' +
'<span class="task-card__status"><span class="status-badge ' + (orderAllDone ? 'status-badge--done' : 'status-badge--pending') + '">' + (orderAllDone ? '已完成' : '待配比') + '</span></span>' +
(orderAllDone
? ''
@@ -193,6 +193,7 @@
.task-card__item-value--purple { color: #722ed1; }
.task-card__item-value--green { color: #52c41a; }
.task-card__item-value--yellow { color: #faad14; }
.task-card__spec-tag { font-size: 11px; padding: 3px 10px; border-radius: 4px; background: rgba(24,144,255,0.12); color: #40a9ff; display: inline-block; white-space: nowrap; }
.order-type-tag { font-size: 10px; padding: 2px 6px; border-radius: 3px; font-weight: 500; white-space: nowrap; flex-shrink: 0; }
.order-type-tag--internal { background: rgba(74,144,217,0.15); color: #4a90d9; }
.order-type-tag--external { background: rgba(250,140,22,0.15); color: #fa8c16; }
@@ -426,6 +427,10 @@
<div class="task-card__item-label">订单状态</div>
<div class="task-card__item-value" id="taskStatus">--</div>
</div>
<div class="task-card__item">
<div class="task-card__item-label">当前规格</div>
<div class="task-card__item-value"><span class="task-card__spec-tag">30mm*30mm*3mm · 圆片 · 平刀</span></div>
</div>
</div>
</div>
@@ -0,0 +1,737 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1280, initial-scale=1.0">
<title>净菜配比秤 - 配比记录 | 蚁熊智能餐养平台</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden;
display: flex; flex-direction: column;
}
/* 顶部导航栏 */
.top-bar {
display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px;
flex-shrink: 0;
}
.back-btn {
font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s;
}
.back-btn:hover { color: #fff; }
.page-title {
flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85);
}
.top-bar__user { font-size: 12px; color: rgba(255,255,255,0.5); }
.logout-btn {
padding: 4px 10px; font-size: 11px;
background: rgba(255,77,79,0.08); border: 1px solid rgba(255,77,79,0.2);
border-radius: 5px; color: rgba(255,77,79,0.7); cursor: pointer;
transition: all 0.2s; font-family: inherit; margin-left: 10px;
}
.logout-btn:hover { background: rgba(255,77,79,0.18); color: #ff6b6d; border-color: rgba(255,77,79,0.4); }
/* 触控筛选栏 */
.touch-filter {
display: flex; align-items: center; gap: 12px;
padding: 10px 20px; background: #1a2b4a; margin: 12px 20px 0; border-radius: 10px;
flex-shrink: 0;
}
/* 模式切换(日视图 / 本周) */
.mode-seg {
flex-shrink: 0; display: flex; height: 52px; border-radius: 10px;
overflow: hidden; border: 1px solid rgba(255,255,255,0.1);
}
.mode-btn {
min-width: 72px; padding: 0 16px; border: none;
background: rgba(255,255,255,0.04); color: rgba(255,255,255,0.5);
font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s;
}
.mode-btn:hover { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.8); }
.mode-btn.active { background: #4a90d9; color: #fff; }
.filter-divider {
width: 1px; height: 36px; background: rgba(255,255,255,0.1); flex-shrink: 0;
}
/* 横向日期滚动条 */
.date-strip {
flex: 1; display: flex; align-items: stretch; gap: 6px;
overflow-x: auto; overflow-y: hidden;
padding: 4px 0;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
transition: opacity 0.2s;
}
.date-strip::-webkit-scrollbar { display: none; }
.date-strip.disabled { opacity: 0.25; pointer-events: none; }
/* 日期单元格 */
.date-cell {
flex-shrink: 0; width: 80px; height: 68px; border-radius: 10px;
border: 2px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 3px; transition: all 0.2s;
}
.date-cell:hover { background: rgba(74,144,217,0.1); border-color: rgba(74,144,217,0.3); }
.date-cell.active { background: rgba(74,144,217,0.25); border-color: #4a90d9; }
.date-cell__weekday { font-size: 12px; color: rgba(255,255,255,0.45); }
.date-cell__day { font-size: 20px; font-weight: 700; color: rgba(255,255,255,0.9); }
.date-cell.active .date-cell__weekday { color: #7ab8f5; }
.date-cell.active .date-cell__day { color: #fff; }
/* 今天快速按钮 */
.today-btn {
flex-shrink: 0; height: 68px; padding: 0 16px; border-radius: 10px;
border: 2px solid rgba(74,144,217,0.4); background: rgba(74,144,217,0.1);
color: #7ab8f5; font-size: 15px; font-weight: 600; cursor: pointer; transition: all 0.2s;
white-space: nowrap;
}
.today-btn:hover { background: rgba(74,144,217,0.2); border-color: #4a90d9; }
.today-btn.active { background: #4a90d9; color: #fff; border-color: #4a90d9; }
.today-btn.disabled { opacity: 0.25; pointer-events: none; }
/* 日历按钮 */
.calendar-btn {
flex-shrink: 0; width: 68px; height: 68px; border-radius: 10px;
border: 2px solid rgba(255,255,255,0.12); background: rgba(255,255,255,0.04);
cursor: pointer; display: flex; align-items: center; justify-content: center;
transition: all 0.2s;
}
.calendar-btn:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.25); }
.calendar-btn svg { width: 28px; height: 28px; }
.calendar-btn.disabled { opacity: 0.25; pointer-events: none; }
/* 状态分段控件 */
.status-seg { flex-shrink: 0; display: flex; height: 52px; border-radius: 10px; overflow: hidden; border: 1px solid rgba(255,255,255,0.1); }
.status-btn {
min-width: 80px; padding: 0 18px; border: none; background: rgba(255,255,255,0.04);
color: rgba(255,255,255,0.5); font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s;
}
.status-btn:hover { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.8); }
.status-btn.active { background: #4a90d9; color: #fff; }
.status-btn.active--green { background: #389e0d; color: #fff; }
.status-btn.active--red { background: #cf1322; color: #fff; }
/* 搜索框 */
.search-box {
flex-shrink: 0; display: flex; align-items: center; gap: 6px;
height: 40px; padding: 0 12px; border-radius: 10px;
background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.1);
transition: border-color 0.2s;
}
.search-box:focus-within { border-color: #4a90d9; }
.search-box__icon { font-size: 14px; color: rgba(255,255,255,0.35); flex-shrink: 0; }
.search-box__input {
width: 160px; border: none; outline: none; background: transparent;
font-size: 13px; color: rgba(255,255,255,0.85);
}
.search-box__input::placeholder { color: rgba(255,255,255,0.25); }
.search-box__clear {
flex-shrink: 0; width: 20px; height: 20px; border-radius: 50%;
background: rgba(255,255,255,0.1); color: rgba(255,255,255,0.5);
font-size: 12px; cursor: pointer; display: none;
align-items: center; justify-content: center; border: none;
}
.search-box__clear.show { display: flex; }
.search-box__clear:hover { background: rgba(255,255,255,0.18); color: #fff; }
/* 维度切换 */
.view-toggle {
flex-shrink: 0; display: flex; height: 34px; border-radius: 8px; overflow: hidden;
border: 1px solid rgba(255,255,255,0.1);
}
.view-toggle__btn {
padding: 0 14px; font-size: 12px; border: none; cursor: pointer;
background: transparent; color: rgba(255,255,255,0.45); transition: all 0.2s;
white-space: nowrap;
}
.view-toggle__btn.active {
background: rgba(74,144,217,0.2); color: #4a90d9; font-weight: 600;
}
.view-toggle__btn:hover:not(.active) { color: rgba(255,255,255,0.7); }
/* 统计行 */
.stats-row { display: flex; gap: 12px; padding: 12px 20px; flex-shrink: 0; }
.stat-chip {
flex: 1; background: #1a2b4a; border-radius: 8px; padding: 12px 16px;
display: flex; align-items: center; gap: 12px;
}
.stat-chip__icon {
width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center;
justify-content: center; font-size: 18px;
}
.stat-chip__icon--blue { background: rgba(74,144,217,0.2); }
.stat-chip__icon--green { background: rgba(82,196,26,0.2); }
.stat-chip__icon--red { background: rgba(255,77,79,0.2); }
.stat-chip__icon--orange { background: rgba(250,173,22,0.2); }
.stat-chip__value { font-size: 20px; font-weight: 700; }
.stat-chip__label { font-size: 11px; color: rgba(255,255,255,0.4); }
/* 表格容器 */
.table-wrap {
margin: 12px 20px; background: #1a2b4a; border-radius: 10px; overflow: hidden;
flex: 1; min-height: 0; display: flex; flex-direction: column;
}
.table-scroll { flex: 1; overflow-y: auto; padding: 8px; scrollbar-width: none; }
.table-scroll::-webkit-scrollbar { display: none; }
/* 任务卡片 */
.task-card { background: #1a2b4a; border-radius: 10px; padding: 0; margin-bottom: 8px; border: 1px solid rgba(255,255,255,0.06); overflow: hidden; }
.task-card__header { display: flex; align-items: center; padding: 10px 16px; gap: 14px; background: rgba(26,43,74,0.6); border-bottom: 1px solid rgba(255,255,255,0.06); }
.task-card__order-info { font-size: 13px; color: rgba(255,255,255,0.7); display: flex; align-items: center; gap: 4px; }
.task-card__order-info__label { color: rgba(255,255,255,0.4); }
.task-card__order-info__value { color: #4a90d9; font-weight: 600; }
.task-card__arrival { font-size: 12px; color: rgba(255,255,255,0.5); display: flex; align-items: center; gap: 4px; }
.task-card__arrival__time { color: #faad16; font-weight: 500; }
.task-card__status { margin-left: auto; }
/* 表格头(7列) */
.item-table__head {
display: grid; grid-template-columns: 1fr 0.65fr 0.6fr 0.5fr 0.65fr 0.6fr 50px; gap: 8px;
padding: 6px 16px; background: rgba(0,0,0,0.2); font-size: 11px; color: rgba(255,255,255,0.4); font-weight: 500;
}
.item-table__body { display: flex; flex-direction: column; }
/* 餐品净菜包主行 */
.item-parent-row {
display: grid; grid-template-columns: 1fr 0.65fr 0.6fr 0.5fr 0.65fr 0.6fr 50px; gap: 8px;
padding: 10px 16px; border-top: 1px solid rgba(255,255,255,0.04); align-items: center;
background: rgba(74,144,217,0.06);
}
.parent-name { display: flex; align-items: center; gap: 8px; }
.parent-icon {
width: 32px; height: 32px; border-radius: 6px;
display: flex; align-items: center; justify-content: center;
font-size: 16px; background: rgba(114,46,209,0.15); flex-shrink: 0;
}
.parent-name__text { font-size: 13px; font-weight: 600; color: #fff; }
.pack-size-tag {
display: inline-block; font-size: 11px; padding: 2px 8px; border-radius: 4px;
background: rgba(74,144,217,0.15); color: #4a90d9; font-weight: 500;
}
.parent-weight { font-size: 12px; color: rgba(255,255,255,0.6); text-align: right; }
/* 食材子行 */
.item-child-row {
display: grid; grid-template-columns: 1fr 0.65fr 0.6fr 0.5fr 0.65fr 0.6fr 50px; gap: 8px;
padding: 8px 16px 8px 48px; border-top: 1px solid rgba(255,255,255,0.03);
align-items: center; transition: background 0.2s;
}
.item-child-row:hover { background: rgba(74,144,217,0.08); }
.child-name { display: flex; align-items: center; gap: 8px; }
.child-icon {
width: 26px; height: 26px; border-radius: 5px;
display: flex; align-items: center; justify-content: center;
font-size: 13px; flex-shrink: 0;
}
.child-icon--potato { background: rgba(250,173,22,0.15); }
.child-icon--carrot { background: rgba(250,140,22,0.15); }
.child-icon--cucumber { background: rgba(20,184,166,0.15); }
.child-icon--cabbage { background: rgba(82,196,26,0.15); }
.child-icon--tomato { background: rgba(255,77,79,0.15); }
.child-icon--egg { background: rgba(250,173,22,0.15); }
.child-icon--onion { background: rgba(114,46,209,0.15); }
.child-icon--green-onion { background: rgba(82,196,26,0.15); }
.child-name__text { font-size: 12px; color: rgba(255,255,255,0.85); }
.child-weight { font-size: 12px; color: rgba(255,255,255,0.55); text-align: right; }
/* 状态徽章 */
.status-badge { font-size: 11px; padding: 3px 8px; border-radius: 4px; font-weight: 500; display: inline-block; }
.status-badge--done { background: rgba(82,196,26,0.15); color: #52c41a; }
.status-badge--pending { background: rgba(250,173,22,0.15); color: #faad16; }
.status-tag {
display: inline-block; padding: 2px 6px; border-radius: 4px; font-size: 10px;
}
.status-tag--done { background: rgba(82,196,26,0.15); color: #52c41a; }
.status-tag--wait { background: rgba(250,173,22,0.15); color: #faad14; }
/* 订单类型标签 */
.order-type-tag { font-size: 10px; padding: 2px 6px; border-radius: 3px; font-weight: 500; white-space: nowrap; }
.order-type-tag--internal { background: rgba(74,144,217,0.15); color: #4a90d9; }
.order-type-tag--external { background: rgba(250,140,22,0.15); color: #fa8c16; }
/* 底栏 */
.table-footer {
display: flex; align-items: center; justify-content: center;
padding: 10px 20px; font-size: 12px; color: rgba(255,255,255,0.35);
border-top: 1px solid rgba(255,255,255,0.04); flex-shrink: 0;
}
/* 空状态 */
.empty-state {
display: none; flex: 1; align-items: center; justify-content: center;
flex-direction: column; gap: 8px; color: rgba(255,255,255,0.3); font-size: 14px;
}
.empty-state.show { display: flex; }
.empty-state__icon { font-size: 40px; opacity: 0.4; }
</style>
</head>
<body>
<div class="top-bar">
<a class="back-btn" id="backBtn" href="javascript:void(0)">&#x25C0; 返回</a>
<span class="page-title">配比记录</span>
<span class="top-bar__user" id="topUser">--</span>
<button class="logout-btn" onclick="handleLogout()">退出</button>
</div>
<!-- 触控筛选栏 -->
<div class="touch-filter">
<!-- 模式切换:日视图 / 本周 -->
<div class="mode-seg">
<button class="mode-btn active" id="modeDayBtn">日视图</button>
<button class="mode-btn" id="modeWeekBtn">本周</button>
</div>
<div class="filter-divider"></div>
<!-- 横向日期滚动条(日视图模式) -->
<div class="date-strip" id="dateStrip"></div>
<button class="today-btn active" id="todayBtn">今天</button>
<label class="calendar-btn" id="calendarBtn" title="选择任意日期">
<svg viewBox="0 0 24 24" fill="none" stroke="rgba(255,255,255,0.6)" stroke-width="1.8">
<rect x="3" y="4" width="18" height="18" rx="2"/>
<line x1="16" y1="2" x2="16" y2="6"/>
<line x1="8" y1="2" x2="8" y2="6"/>
<line x1="3" y1="10" x2="21" y2="10"/>
<rect x="7" y="14" width="3" height="3" rx="0.5" fill="rgba(255,255,255,0.6)" stroke="none"/>
</svg>
<input type="date" id="calendarInput" style="position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;">
</label>
<div class="filter-divider"></div>
<!-- 搜索框 -->
<div class="search-box">
<span class="search-box__icon">&#x1F50D;</span>
<input class="search-box__input" id="searchInput" type="text" placeholder="搜索订单号 / 名称" oninput="onSearchInput()">
<button class="search-box__clear" id="searchClear" onclick="clearSearch()">&times;</button>
</div>
</div>
<!-- 统计行 -->
<div class="stats-row">
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--blue">&#x1F4CB;</div>
<div><div class="stat-chip__value" id="statTotal">5</div><div class="stat-chip__label" id="statTotalLabel">今日配比订单数</div></div>
</div>
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--green">&#x2696;&#xFE0F;</div>
<div><div class="stat-chip__value" id="statWeight">0</div><div class="stat-chip__label">配比总重量(g)</div></div>
</div>
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--orange">&#x1F96C;</div>
<div><div class="stat-chip__value" id="statFoods">0</div><div class="stat-chip__label">净菜种类</div></div>
</div>
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--red">&#x1F4E6;</div>
<div><div class="stat-chip__value" id="statPacks">0</div><div class="stat-chip__label">总份数</div></div>
</div>
</div>
<!-- 任务列表 -->
<div class="table-wrap">
<div class="table-scroll" id="taskListContainer">
<!-- 动态渲染卡片 -->
</div>
<div class="empty-state" id="emptyState">
<div class="empty-state__icon">&#x1F4ED;</div>
<div>暂无配比记录</div>
</div>
<div class="table-footer" id="tableFooter">共 0 条记录</div>
</div>
<script>
/* 退出登录 */
function handleLogout() {
window.location.href = '00-welcome.html';
}
/* 获取 URL 参数 */
function getUrlParam(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
var r = window.location.search.substr(1).match(reg);
if (r !== null) return decodeURIComponent(r[2]);
return null;
}
var userName = getUrlParam('user');
if (userName) {
document.getElementById('topUser').textContent = '操作员: ' + userName;
}
// 当天日期(原型基准日期)
var TODAY = '2026-06-16';
var WEEKDAYS = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
// 配比记录数据(按订单组织,对齐配比任务页字段结构)
var RECORDS = [
{
orderNo: 'PO-20260616-001', orderType: 'internal', completeTime: '2026-06-16 10:20',
mealPacks: [
{ type: '净菜包', packName: '土豆丝', packSize: 3, packSpec: '500g', ingredients: [
{ name: '土豆丝', icon: '&#x1F954;', iconClass: 'child-icon--potato', weightPerPack: 500, weighed: 1500 }
]},
{ type: '净菜包', packName: '胡萝卜丝', packSize: 3, packSpec: '500g', ingredients: [
{ name: '胡萝卜丝', icon: '&#x1F955;', iconClass: 'child-icon--carrot', weightPerPack: 500, weighed: 1500 }
]},
{ type: '净菜包', packName: '黄瓜片', packSize: 3, packSpec: '500g', ingredients: [
{ name: '黄瓜片', icon: '&#x1F952;', iconClass: 'child-icon--cucumber', weightPerPack: 500, weighed: 1500 }
]},
{ type: '餐品净菜包', packName: '宫保鸡丁套餐', packSize: 2, packSpec: '大份800g', ingredients: [
{ name: '宫保鸡丁', icon: '&#x1F958;', iconClass: 'child-icon--tomato', weightPerPack: 800, weighed: 1600 }
]}
]
},
{
orderNo: 'PO-20260616-002', orderType: 'external', completeTime: '2026-06-16 11:00',
mealPacks: [
{ type: '净菜包', packName: '白菜丝', packSize: 2, packSpec: '1000g', ingredients: [
{ name: '白菜丝', icon: '&#x1F96C;', iconClass: 'child-icon--cabbage', weightPerPack: 1000, weighed: 2000 }
]},
{ type: '餐品净菜包', packName: '鱼香肉丝套餐', packSize: 2, packSpec: '大份800g', ingredients: [
{ name: '鱼香肉丝', icon: '&#x1F958;', iconClass: 'child-icon--tomato', weightPerPack: 800, weighed: 1600 }
]}
]
},
{
orderNo: 'PO-20260615-003', orderType: 'internal', completeTime: '2026-06-15 14:50',
mealPacks: [
{ type: '净菜包', packName: '青椒丝', packSize: 3, packSpec: '400g', ingredients: [
{ name: '青椒丝', icon: '&#x1F97A;', iconClass: 'child-icon--green-onion', weightPerPack: 400, weighed: 1200 }
]},
{ type: '净菜包', packName: '洋葱丝', packSize: 3, packSpec: '300g', ingredients: [
{ name: '洋葱丝', icon: '&#x1F9C5;', iconClass: 'child-icon--onion', weightPerPack: 300, weighed: 900 }
]}
]
},
{
orderNo: 'PO-20260615-004', orderType: 'external', completeTime: '2026-06-15 15:20',
mealPacks: [
{ type: '净菜包', packName: '芹菜段', packSize: 2, packSpec: '400g', ingredients: [
{ name: '芹菜段', icon: '&#x1F96C;', iconClass: 'child-icon--cabbage', weightPerPack: 400, weighed: 800 }
]}
]
}
];
var selectedDate = TODAY;
var isWeeklyMode = false;
var searchKeyword = '';
// 获取本周一日期
function getMonday() {
var today = new Date(TODAY + 'T00:00:00');
var day = today.getDay();
var diff = today.getDate() - day + (day === 0 ? -6 : 1);
var monday = new Date(today);
monday.setDate(diff);
return monday;
}
// 生成日期字符串
function dateStr(d) {
return d.getFullYear() + '-' +
String(d.getMonth() + 1).padStart(2, '0') + '-' +
String(d.getDate()).padStart(2, '0');
}
// 生成日期条(最近7天)
function generateDateStrip() {
var strip = document.getElementById('dateStrip');
var today = new Date(TODAY + 'T00:00:00');
var html = '';
for (var i = 6; i >= 0; i--) {
var d = new Date(today);
d.setDate(d.getDate() - i);
var ds = dateStr(d);
var dayNum = d.getDate();
var weekday = WEEKDAYS[d.getDay()];
var label = (i === 0) ? '今天' : (i === 1 ? '昨天' : weekday);
var isActive = (ds === selectedDate) ? ' active' : '';
html += '<button class="date-cell' + isActive + '" data-date="' + ds + '">'
+ '<span class="date-cell__weekday">' + label + '</span>'
+ '<span class="date-cell__day">' + dayNum + '</span>'
+ '</button>';
}
strip.innerHTML = html;
strip.querySelectorAll('.date-cell').forEach(function(cell) {
cell.addEventListener('click', function() {
selectDate(cell.getAttribute('data-date'));
});
});
strip.scrollLeft = strip.scrollWidth;
}
// 选中日期
function selectDate(ds) {
if (isWeeklyMode) return;
selectedDate = ds;
document.querySelectorAll('.date-cell').forEach(function(c) {
c.classList.toggle('active', c.getAttribute('data-date') === ds);
});
document.getElementById('todayBtn').classList.toggle('active', ds === TODAY);
var inRange = Array.from(document.querySelectorAll('.date-cell'))
.some(function(c) { return c.getAttribute('data-date') === ds; });
if (!inRange) appendDateToStrip(ds);
var activeCell = document.querySelector('.date-cell[data-date="' + ds + '"]');
if (activeCell) activeCell.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' });
updateStats();
renderTable();
}
// 扩展日期条(左侧追加)
function appendDateToStrip(ds) {
var strip = document.getElementById('dateStrip');
var d = new Date(ds + 'T00:00:00');
var cell = document.createElement('button');
cell.className = 'date-cell active';
cell.setAttribute('data-date', ds);
cell.innerHTML = '<span class="date-cell__weekday">' + WEEKDAYS[d.getDay()] + '</span>'
+ '<span class="date-cell__day">' + d.getDate() + '</span>';
cell.addEventListener('click', function() { selectDate(ds); });
strip.insertBefore(cell, strip.firstChild);
}
// 切换模式:日视图 / 本周
function setMode(weekly) {
isWeeklyMode = weekly;
document.getElementById('modeDayBtn').classList.toggle('active', !weekly);
document.getElementById('modeWeekBtn').classList.toggle('active', weekly);
var disableClass = weekly ? 'add' : 'remove';
document.getElementById('dateStrip').classList[disableClass]('disabled');
document.getElementById('todayBtn').classList[disableClass]('disabled');
document.getElementById('calendarBtn').classList[disableClass]('disabled');
updateStats();
renderTable();
}
// 更新统计行
function updateStats() {
var records;
var totalLabel;
if (searchKeyword) {
records = RECORDS;
totalLabel = '搜索结果';
} else if (isWeeklyMode) {
var monday = getMonday();
var mondayStr = dateStr(monday);
records = RECORDS.filter(function(r) { return r.completeTime.substring(0, 10) >= mondayStr; });
totalLabel = '本周配比订单数';
} else {
records = RECORDS.filter(function(r) { return r.completeTime.substring(0, 10) === selectedDate; });
totalLabel = (selectedDate === TODAY) ? '今日配比订单数' : (selectedDate.substring(5).replace('-', '/') + ' 配比订单数');
}
var total = records.length;
var totalWeight = 0;
var foodSet = {};
var totalPacks = 0;
records.forEach(function(order) {
order.mealPacks.forEach(function(pack) {
pack.ingredients.forEach(function(ing) {
totalWeight += ing.weighed;
foodSet[ing.name] = true;
});
totalPacks += pack.packSize;
});
});
document.getElementById('statTotal').textContent = total;
document.getElementById('statTotalLabel').textContent = totalLabel;
document.getElementById('statWeight').textContent = totalWeight;
document.getElementById('statFoods').textContent = Object.keys(foodSet).length;
document.getElementById('statPacks').textContent = totalPacks;
}
// 搜索输入处理
function onSearchInput() {
var val = document.getElementById('searchInput').value.trim();
searchKeyword = val;
document.getElementById('searchClear').classList.toggle('show', val.length > 0);
updateStats();
renderTable();
}
function clearSearch() {
document.getElementById('searchInput').value = '';
searchKeyword = '';
document.getElementById('searchClear').classList.remove('show');
updateStats();
renderTable();
}
// 过滤记录
function getFilteredRecords() {
var monday = getMonday();
var mondayStr = dateStr(monday);
return RECORDS.filter(function(r) {
if (!searchKeyword) {
if (isWeeklyMode) {
if (r.completeTime.substring(0, 10) < mondayStr) return false;
} else {
if (r.completeTime.substring(0, 10) !== selectedDate) return false;
}
}
if (searchKeyword) {
var kw = searchKeyword;
var matchOrder = (r.orderNo || '').indexOf(kw) !== -1;
var matchFood = r.mealPacks.some(function(pack) {
return pack.packName.indexOf(kw) !== -1 || pack.ingredients.some(function(ing) {
return ing.name.indexOf(kw) !== -1;
});
});
if (!matchOrder && !matchFood) return false;
}
return true;
}).sort(function(a, b) {
return b.completeTime.localeCompare(a.completeTime);
});
}
/* 获取净菜包状态 */
function getPackStatus(pack) {
var allDone = pack.ingredients.every(function(ing) {
return ing.weighed >= ing.weightPerPack * pack.packSize;
});
if (allDone) return { text: '已完成', cls: 'status-badge--done' };
return { text: '待配比', cls: 'status-badge--pending' };
}
// 渲染卡片列表
function renderTable() {
var records = getFilteredRecords();
var container = document.getElementById('taskListContainer');
var emptyEl = document.getElementById('emptyState');
if (records.length === 0) {
container.innerHTML = '';
emptyEl.classList.add('show');
document.getElementById('tableFooter').textContent = '共 0 条记录';
return;
}
emptyEl.classList.remove('show');
container.innerHTML = '';
records.forEach(function(order) {
var packs = order.mealPacks;
var orderAllDone = packs.every(function(p) { return !getPackStatus(p).text !== '待配比'; });
var taskCard = document.createElement('div');
taskCard.className = 'task-card';
var orderTypeLabel = order.orderType === 'internal' ? '内供订单' : '外售订单';
var orderTypeCls = order.orderType === 'internal' ? 'order-type-tag--internal' : 'order-type-tag--external';
/* 卡片头部:订单号 + 订单类型 + 完成时间 + 状态 */
var header = document.createElement('div');
header.className = 'task-card__header';
header.innerHTML =
'<span class="task-card__order-info"><span class="task-card__order-info__label">订单号:</span><span class="task-card__order-info__value">' + order.orderNo + '</span></span>' +
'<span class="order-type-tag ' + orderTypeCls + '">' + orderTypeLabel + '</span>' +
'<span class="task-card__arrival">&#x23F0; 任务完成时间:<span class="task-card__arrival__time">' + order.completeTime + '</span></span>' +
'<span class="task-card__status"><span class="status-badge status-badge--done">已完成</span></span>';
taskCard.appendChild(header);
/* 表格头(7列) */
var tableHead = document.createElement('div');
tableHead.className = 'item-table__head';
tableHead.innerHTML = '<div>名称</div><div style="text-align:center">净菜/餐品</div><div style="text-align:center">包装规格</div><div style="text-align:center">打包份数</div><div style="text-align:right">所需总重</div><div style="text-align:right">已称</div><div style="text-align:center">状态</div>';
taskCard.appendChild(tableHead);
/* 表格体 */
var tableBody = document.createElement('div');
tableBody.className = 'item-table__body';
packs.forEach(function(pack) {
var packStatus = getPackStatus(pack);
var totalNeed = 0;
var totalWeighed = 0;
pack.ingredients.forEach(function(ing) {
totalNeed += ing.weightPerPack * pack.packSize;
totalWeighed += ing.weighed;
});
totalNeed = Math.round(totalNeed * 100) / 100;
totalWeighed = Math.round(totalWeighed * 100) / 100;
/* 主行:净菜包/餐品净菜包 */
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + '</span></div>' +
'<div style="text-align:center;font-size:12px;color:' + (pack.type === '餐品净菜包' ? '#faad16' : '#4a90d9') + '">' + pack.type + '</div>' +
'<div style="text-align:center;font-size:12px;color:rgba(255,255,255,0.55)">' + (pack.packSpec || '—') + '</div>' +
'<div style="text-align:center"><span class="pack-size-tag">' + pack.packSize + '</span></div>' +
'<div class="parent-weight">需 ' + totalNeed + ' 克</div>' +
'<div class="parent-weight">已 ' + totalWeighed + ' 克</div>' +
'<div style="text-align:center"><span class="status-tag ' + (packStatus.text === '已完成' ? 'status-tag--done' : 'status-tag--wait') + '">' + packStatus.text + '</span></div>';
tableBody.appendChild(parentRow);
});
taskCard.appendChild(tableBody);
container.appendChild(taskCard);
});
var footerText;
if (isWeeklyMode) {
var monday = getMonday();
var mondayStr = dateStr(monday).substring(5).replace('-', '/');
var todayStr = TODAY.substring(5).replace('-', '/');
footerText = '本周 ' + mondayStr + ' - ' + todayStr + ' 共 ' + records.length + ' 条记录';
} else {
footerText = '共 ' + records.length + ' 条记录';
}
document.getElementById('tableFooter').textContent = footerText;
}
// 初始化
function init() {
generateDateStrip();
document.getElementById('modeDayBtn').addEventListener('click', function() { setMode(false); });
document.getElementById('modeWeekBtn').addEventListener('click', function() { setMode(true); });
document.getElementById('todayBtn').addEventListener('click', function() {
selectDate(TODAY);
});
document.getElementById('calendarInput').addEventListener('change', function(e) {
if (e.target.value) selectDate(e.target.value);
});
updateStats();
renderTable();
}
init();
</script>
<script>
/* 返回按钮:从哪来回哪去 */
(function() {
var backBtn = document.getElementById('backBtn');
if (backBtn) {
var params = new URLSearchParams(window.location.search);
var referer = params.get('referer');
if (referer) {
backBtn.href = referer;
} else if (document.referrer && document.referrer.indexOf(window.location.hostname) !== -1) {
backBtn.href = document.referrer;
} else {
backBtn.href = 'index.html';
}
}
})();
</script>
</body>
</html>
@@ -68,6 +68,14 @@
</div>
<span class="card__arrow">&#x203A;</span>
</a>
<a class="card" href="03-verify-history.html">
<span class="card__icon">&#x1F4DD;</span>
<div class="card__info">
<div class="card__title">验收记录</div>
<div class="card__desc">历史配比验收记录查看与筛选</div>
</div>
<span class="card__arrow">&#x203A;</span>
</a>
</div>
</div>
</body>