feat: 净菜加工秤新增采样模块与加工记录优化,配比秤新增配比记录页
- 净菜加工秤:新增净菜采样(04)与采样历史(05)页面 - 净菜加工秤:菜单页(01-menu)增加采样、采样历史、加工记录入口 - 净菜加工秤:加工记录(02)规格改为净菜类型,去掉操作员与验收结果列,去掉订单维度与订单数统计 - 净菜加工秤:采样与历史页筛选改为食材类别(叶菜类/根茎类等),净菜名称改为食材名称 - 配比秤:新增配比记录页(03),卡片式布局对齐配比任务页字段结构 - 配比秤:配比任务页"任务截止时间"改为"任务完成时间" - 配比秤:称重打包页增加当前规格标识 - 统一各页面规格格式为"尺寸 · 形状 · 刀法" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
06587d20a3
commit
d13843d3e6
@@ -88,6 +88,30 @@
|
||||
</div>
|
||||
<div class="menu-btn__arrow">›</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">🔍</div>
|
||||
<div class="menu-btn__info">
|
||||
<div class="menu-btn__title">净菜采样</div>
|
||||
<div class="menu-btn__desc">采样操作、外观等级判定、保存采样</div>
|
||||
</div>
|
||||
<div class="menu-btn__arrow">›</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">📋</div>
|
||||
<div class="menu-btn__info">
|
||||
<div class="menu-btn__title">采样历史</div>
|
||||
<div class="menu-btn__desc">采样记录查看与筛选</div>
|
||||
</div>
|
||||
<div class="menu-btn__arrow">›</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">📝</div>
|
||||
<div class="menu-btn__info">
|
||||
<div class="menu-btn__title">加工记录</div>
|
||||
<div class="menu-btn__desc">历史加工验收记录查看与筛选</div>
|
||||
</div>
|
||||
<div class="menu-btn__arrow">›</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)">◀ 返回</a> <span class="top-bar__title">验收记录</span>
|
||||
<div class="top-bar">
|
||||
<a class="back-btn" id="backBtn" href="javascript:void(0)">◀ 返回</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">🥔</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">🥒</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">🥬</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">🥕</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">🍅</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">🥔</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">🥔</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">🥕</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>‹</button>
|
||||
<button class="pagination__btn active">1</button>
|
||||
<button class="pagination__btn" disabled>›</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">🔍</span>
|
||||
<input class="search-box__input" id="searchInput" type="text" placeholder="搜索加工号 / 净菜" oninput="onSearchInput()">
|
||||
<button class="search-box__clear" id="searchClear" onclick="clearSearch()">×</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 统计行 -->
|
||||
<div class="stats-row">
|
||||
<div class="stat-chip">
|
||||
<div class="stat-chip__icon stat-chip__icon--blue">📋</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">⚖️</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">🥬</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">📭</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)">◀ 返回</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">🥬 净菜选择</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">📷</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">📸<br>拍照采集</button>
|
||||
</div>
|
||||
|
||||
<!-- 采集结果 -->
|
||||
<div class="result-section">
|
||||
<div class="result-section__title">
|
||||
<span>📋 采集结果</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">↻ 重新采样</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: '🥬', cat: '叶菜类', spec: '35mm*1mm*1mm · 长条 · 平刀' },
|
||||
{ id: 2, name: '大白菜', icon: '🥬', cat: '叶菜类', spec: '50mm*30mm*30mm · 宽段 · 平刀' },
|
||||
{ id: 3, name: '圆白菜', icon: '🥬', cat: '叶菜类', spec: '30mm*2mm*2mm · 细丝 · 平刀' },
|
||||
{ id: 4, name: '油菜', icon: '🥬', cat: '叶菜类', spec: '40mm*10mm*10mm · 宽段 · 平刀' },
|
||||
{ id: 5, name: '生菜', icon: '🥬', cat: '叶菜类', spec: '30mm*2mm*2mm · 细丝 · 平刀' },
|
||||
{ id: 6, name: '芹菜', icon: '🥬', cat: '叶菜类', spec: '40mm*10mm*10mm · 宽段 · 平刀' },
|
||||
{ id: 7, name: '小白菜', icon: '🥬', cat: '叶菜类', spec: '30mm*10mm*10mm · 宽段 · 平刀' },
|
||||
{ id: 8, name: '西兰花', icon: '🥦', cat: '花菜类', spec: '30mm*30mm*30mm · 方丁 · 平刀' },
|
||||
{ id: 9, name: '花菜', icon: '🥦', cat: '花菜类', spec: '30mm*30mm*30mm · 方丁 · 平刀' },
|
||||
{ id: 10, name: '黄瓜', icon: '🥒', cat: '瓜果类', spec: '30mm*30mm*3mm · 圆片 · 平刀' },
|
||||
{ id: 11, name: '西红柿', icon: '🍅', cat: '瓜果类', spec: '25mm*25mm*20mm · 楔形块 · 平刀' },
|
||||
{ id: 12, name: '茄子', icon: '🍆', cat: '瓜果类', spec: '25mm*25mm*25mm · 方丁 · 平刀' },
|
||||
{ id: 13, name: '青椒', icon: '🫑', cat: '瓜果类', spec: '30mm*3mm*3mm · 长条 · 平刀' },
|
||||
{ id: 14, name: '豆角', icon: '🫘', cat: '瓜果类', spec: '40mm*10mm*10mm · 宽段 · 平刀' },
|
||||
{ id: 15, name: '胡萝卜', icon: '🥕', cat: '根茎类', spec: '20mm*1mm*1mm · 细丝 · 平刀' },
|
||||
{ id: 16, name: '莴笋', icon: '🥬', cat: '根茎类', spec: '30mm*2mm*2mm · 细丝 · 平刀' },
|
||||
{ id: 17, name: '莲藕', icon: '🫑', cat: '根茎类', spec: '35mm*35mm*3mm · 圆片 · 平刀' },
|
||||
{ id: 18, name: '洋葱', icon: '🧅', cat: '根茎类', spec: '30mm*2mm*2mm · 细丝 · 平刀' },
|
||||
{ id: 19, name: '土豆', icon: '🥔', cat: '薯类', spec: '35mm*1mm*1mm · 长条 · 平刀' },
|
||||
{ id: 20, name: '红薯', icon: '🍠', cat: '薯类', spec: '20mm*20mm*20mm · 方丁 · 平刀' },
|
||||
{ id: 21, name: '紫薯', icon: '🍠', cat: '薯类', spec: '20mm*20mm*20mm · 方丁 · 平刀' },
|
||||
{ id: 22, name: '猪里脊', icon: '🥩', cat: '肉禽类', spec: '40mm*3mm*3mm · 长条 · 平刀' },
|
||||
{ id: 23, name: '五花肉', icon: '🥩', cat: '肉禽类', spec: '50mm*30mm*3mm · 圆片 · 平刀' },
|
||||
{ id: 24, name: '鸡胸肉', icon: '🦦', cat: '肉禽类', spec: '40mm*3mm*3mm · 长条 · 平刀' },
|
||||
{ id: 25, name: '草鱼', icon: '🐟', cat: '水产类', spec: '30mm*30mm*3mm · 圆片 · 平刀' },
|
||||
{ id: 26, name: '虾仁', icon: '🦐', 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">🔍</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">✔</span>'
|
||||
+ '</div>'
|
||||
+ '<button class="remove-btn" data-index="' + i + '">✖</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 = '📷';
|
||||
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)">◀ 返回</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">🔍 快捷查找</div>
|
||||
|
||||
<input type="text" class="search-panel__input" id="searchInput" placeholder="输入食材名称...">
|
||||
|
||||
<div>
|
||||
<div class="search-panel__title" style="margin-bottom:8px;">📁 按类目筛选</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()">✖ 关闭</button>
|
||||
<button class="btn-resample" id="btnResample" onclick="resampleFood()">📸 补充采集</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: '🥔', 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: '🥒', catLabel: '瓜果类', spec: '30mm*30mm*3mm · 圆片 · 平刀', count: 3, time: '2026-06-17 09:15', images: [10,10,10] },
|
||||
{ id: 3, foodId: 2, name: '大白菜', icon: '🥬', catLabel: '叶菜类', spec: '50mm*30mm*30mm · 宽段 · 平刀', count: 4, time: '2026-06-17 08:45', images: [2,2,2,2] },
|
||||
{ id: 4, foodId: 15, name: '胡萝卜', icon: '🥕', 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: '🍅', catLabel: '瓜果类', spec: '25mm*25mm*20mm · 楔形块 · 平刀', count: 2, time: '2026-06-16 11:30', images: [11,11] },
|
||||
{ id: 6, foodId: 18, name: '洋葱', icon: '🧅', catLabel: '根茎类', spec: '30mm*2mm*2mm · 细丝 · 平刀', count: 4, time: '2026-06-16 10:00', images: [18,18,18,18] },
|
||||
{ id: 7, foodId: 17, name: '莲藕', icon: '🫑', catLabel: '根茎类', spec: '35mm*35mm*3mm · 圆片 · 平刀', count: 3, time: '2026-06-15 15:10', images: [17,17,17] },
|
||||
{ id: 8, foodId: 13, name: '青椒', icon: '🫑', 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: '🥬', 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: '🫘', catLabel: '瓜果类', spec: '40mm*10mm*10mm · 宽段 · 平刀', count: 3, time: '2026-06-14 14:00', images: [14,14,14] },
|
||||
{ id: 11, foodId: 20, name: '红薯', icon: '🍠', catLabel: '薯类', spec: '20mm*20mm*20mm · 方丁 · 平刀', count: 4, time: '2026-06-14 10:20', images: [20,20,20,20] },
|
||||
{ id: 12, foodId: 3, name: '圆白菜', icon: '🥬', 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 + '">✖</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">›</span>
|
||||
</a>
|
||||
<a class="card" href="04-sampling.html">
|
||||
<span class="card__icon">🔍</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">净菜采样</div>
|
||||
<div class="card__desc">采样操作、外观等级判定、保存采样</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<a class="card" href="05-sampling-history.html">
|
||||
<span class="card__icon">📋</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">采样历史</div>
|
||||
<div class="card__desc">采样记录查看与筛选</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<a class="card" href="02-history.html">
|
||||
<span class="card__icon">📝</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">验收记录</div>
|
||||
<div class="card__desc">历史验收记录查看与筛选</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</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">⏰ 任务截止时间:<span class="task-card__arrival__time">' + order.expectedArrival + '</span></span>' +
|
||||
'<span class="task-card__arrival">⏰ 任务完成时间:<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)">◀ 返回</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">🔍</span>
|
||||
<input class="search-box__input" id="searchInput" type="text" placeholder="搜索订单号 / 名称" oninput="onSearchInput()">
|
||||
<button class="search-box__clear" id="searchClear" onclick="clearSearch()">×</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 统计行 -->
|
||||
<div class="stats-row">
|
||||
<div class="stat-chip">
|
||||
<div class="stat-chip__icon stat-chip__icon--blue">📋</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">⚖️</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">🥬</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">📦</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">📭</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: '🥔', iconClass: 'child-icon--potato', weightPerPack: 500, weighed: 1500 }
|
||||
]},
|
||||
{ type: '净菜包', packName: '胡萝卜丝', packSize: 3, packSpec: '500g', ingredients: [
|
||||
{ name: '胡萝卜丝', icon: '🥕', iconClass: 'child-icon--carrot', weightPerPack: 500, weighed: 1500 }
|
||||
]},
|
||||
{ type: '净菜包', packName: '黄瓜片', packSize: 3, packSpec: '500g', ingredients: [
|
||||
{ name: '黄瓜片', icon: '🥒', iconClass: 'child-icon--cucumber', weightPerPack: 500, weighed: 1500 }
|
||||
]},
|
||||
{ type: '餐品净菜包', packName: '宫保鸡丁套餐', packSize: 2, packSpec: '大份800g', ingredients: [
|
||||
{ name: '宫保鸡丁', icon: '🥘', 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: '🥬', iconClass: 'child-icon--cabbage', weightPerPack: 1000, weighed: 2000 }
|
||||
]},
|
||||
{ type: '餐品净菜包', packName: '鱼香肉丝套餐', packSize: 2, packSpec: '大份800g', ingredients: [
|
||||
{ name: '鱼香肉丝', icon: '🥘', 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: '🥺', iconClass: 'child-icon--green-onion', weightPerPack: 400, weighed: 1200 }
|
||||
]},
|
||||
{ type: '净菜包', packName: '洋葱丝', packSize: 3, packSpec: '300g', ingredients: [
|
||||
{ name: '洋葱丝', icon: '🧅', 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: '🥬', 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">⏰ 任务完成时间:<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">📦</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">›</span>
|
||||
</a>
|
||||
<a class="card" href="03-verify-history.html">
|
||||
<span class="card__icon">📝</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">验收记录</div>
|
||||
<div class="card__desc">历史配比验收记录查看与筛选</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user