@
feat(overview): Temperprozess rename, order-count badge, amber transit flow, brighter labels - Rename line "Temper-Linie" → "Temperprozess" (tab title + i18n de/en) - Per-press order display: chip row → single colored order-count badge (.ocount) - New 5th flow colour --transit (amber) for "Auf dem Weg"; --way (cyan) reserved for cart/verladen; per-press amber arrows drop to the oven; header "Maschinenhalle" - Brighter --ink-faint labels to match temper_rejects (dark #7f8b9a, light #4b586b) - Grid width tweaks (col floor 96px, wrap max-width 1300px) + hide matrix scrollbar - Rebuilt dist Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
This commit is contained in:
parent
a24f7d2c1e
commit
84253f7dcc
1
dist/assets/index-B4JBFZH3.css
vendored
Normal file
1
dist/assets/index-B4JBFZH3.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/index-BxZ3b12T.css
vendored
1
dist/assets/index-BxZ3b12T.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
36
dist/index.html
vendored
36
dist/index.html
vendored
@ -1,18 +1,18 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<!--
|
<!--
|
||||||
Dark-first board (class="dark" → @sp-ui-kit token dark values + PrimeVue dark
|
Dark-first board (class="dark" → @sp-ui-kit token dark values + PrimeVue dark
|
||||||
mode, whose darkModeSelector is ".dark"). data-density="comfortable": this is a
|
mode, whose darkModeSelector is ".dark"). data-density="comfortable": this is a
|
||||||
view-only wall board, not a finger-touch panel (the reject STATION uses "touch").
|
view-only wall board, not a finger-touch panel (the reject STATION uses "touch").
|
||||||
-->
|
-->
|
||||||
<html lang="de" class="dark" data-density="comfortable">
|
<html lang="de" class="dark" data-density="comfortable">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Temper-Linie · Live-Übersicht</title>
|
<title>Temperprozess · Live-Übersicht</title>
|
||||||
<script type="module" crossorigin src="/module/temper_overview/assets/index-C3BK_Qev.js"></script>
|
<script type="module" crossorigin src="/module/temper_overview/assets/index-Vt9ocbug.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/module/temper_overview/assets/index-BxZ3b12T.css">
|
<link rel="stylesheet" crossorigin href="/module/temper_overview/assets/index-B4JBFZH3.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Temper-Linie · Live-Übersicht</title>
|
<title>Temperprozess · Live-Übersicht</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@ -11,7 +11,8 @@ const { t } = useI18n()
|
|||||||
<span class="sw" :style="{ background: 'var(--press)' }"></span>
|
<span class="sw" :style="{ background: 'var(--press)' }"></span>
|
||||||
<span><span class="nm">{{ t('flow.presses') }}</span> <span class="sub">{{ t('flow.pressesSub') }}</span></span>
|
<span><span class="nm">{{ t('flow.presses') }}</span> <span class="sub">{{ t('flow.pressesSub') }}</span></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="node"><span class="sw" :style="{ background: 'var(--way)' }"></span><span class="nm">{{ t('flow.onWay') }}</span></div>
|
<div class="node"><span class="sw" :style="{ background: 'var(--way)' }"></span><span class="nm">{{ t('flow.loaded') }}</span></div>
|
||||||
|
<div class="node"><span class="sw" :style="{ background: 'var(--transit)' }"></span><span class="nm">{{ t('flow.onWay') }}</span></div>
|
||||||
<div class="node"><span class="sw" :style="{ background: 'var(--oven)' }"></span><span class="nm">{{ t('flow.oven') }}</span></div>
|
<div class="node"><span class="sw" :style="{ background: 'var(--oven)' }"></span><span class="nm">{{ t('flow.oven') }}</span></div>
|
||||||
<div class="node"><span class="sw" :style="{ background: 'var(--done)' }"></span><span class="nm">{{ t('flow.finished') }}</span></div>
|
<div class="node"><span class="sw" :style="{ background: 'var(--done)' }"></span><span class="nm">{{ t('flow.finished') }}</span></div>
|
||||||
<span class="orders">
|
<span class="orders">
|
||||||
|
|||||||
@ -70,7 +70,7 @@ const scrapRate = computed(() => {
|
|||||||
border-left-color: var(--press);
|
border-left-color: var(--press);
|
||||||
}
|
}
|
||||||
.kpi.way {
|
.kpi.way {
|
||||||
border-left-color: var(--way);
|
border-left-color: var(--transit);
|
||||||
}
|
}
|
||||||
.kpi.oven {
|
.kpi.oven {
|
||||||
border-left-color: var(--oven);
|
border-left-color: var(--oven);
|
||||||
@ -95,7 +95,7 @@ const scrapRate = computed(() => {
|
|||||||
color: var(--press);
|
color: var(--press);
|
||||||
}
|
}
|
||||||
.kpi.way .kv {
|
.kpi.way .kv {
|
||||||
color: var(--way);
|
color: var(--transit);
|
||||||
}
|
}
|
||||||
.kpi.oven .kv {
|
.kpi.oven .kv {
|
||||||
color: var(--oven);
|
color: var(--oven);
|
||||||
|
|||||||
@ -24,11 +24,15 @@ const statusText = computed(() =>
|
|||||||
<div v-else class="press" :class="press.status">
|
<div v-else class="press" :class="press.status">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
<span class="pn">{{ press.name }}</span>
|
<span class="pn">{{ press.name }}</span>
|
||||||
|
<span
|
||||||
|
v-if="press.orders.length"
|
||||||
|
class="ocount"
|
||||||
|
:style="{ background: orderColor(press.orders.length - 1) }"
|
||||||
|
:title="t('press.orderCount', { n: press.orders.length })"
|
||||||
|
>{{ press.orders.length }}</span
|
||||||
|
>
|
||||||
<span class="stled" :style="{ background: ledColor }"></span>
|
<span class="stled" :style="{ background: ledColor }"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="chips">
|
|
||||||
<span v-for="(o, i) in press.orders" :key="i" class="chip" :style="{ background: orderColor(o.colorIndex) }"></span>
|
|
||||||
</div>
|
|
||||||
<template v-if="press.status === 'run'">
|
<template v-if="press.status === 'run'">
|
||||||
<div class="good num">{{ de(press.good) }}</div>
|
<div class="good num">{{ de(press.good) }}</div>
|
||||||
<div class="sub">{{ t('press.good') }} · {{ press.cycleTime }}s</div>
|
<div class="sub">{{ t('press.good') }} · {{ press.cycleTime }}s</div>
|
||||||
@ -91,15 +95,19 @@ const statusText = computed(() =>
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
.chips {
|
.ocount {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
gap: 3px;
|
align-items: center;
|
||||||
min-height: 12px;
|
justify-content: center;
|
||||||
}
|
min-width: 17px;
|
||||||
.chip {
|
height: 17px;
|
||||||
width: 12px;
|
padding: 0 4px;
|
||||||
height: 12px;
|
border-radius: 4px;
|
||||||
border-radius: 3px;
|
font-family: var(--mono);
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--ground);
|
||||||
}
|
}
|
||||||
.good {
|
.good {
|
||||||
font-family: var(--mono);
|
font-family: var(--mono);
|
||||||
|
|||||||
@ -12,34 +12,50 @@ const partsOf = (c: CartOnWay) => c.orders.reduce((s, o) => s + o.qty, 0)
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="lane" :class="{ active }">
|
<div class="lane-wrap">
|
||||||
<span class="conn"></span>
|
<div class="lane" :class="{ active }">
|
||||||
<span class="lc" :class="active ? 'on' : 'off'">
|
<span class="conn"></span>
|
||||||
{{ active ? t('lane.wagen', { n: carts.length }) : t('lane.none') }}
|
<span class="lc" :class="active ? 'on' : 'off'">
|
||||||
</span>
|
{{ active ? t('lane.wagen', { n: carts.length }) : t('lane.none') }}
|
||||||
<div v-for="cart in carts" :key="cart.cartId" class="cart">
|
</span>
|
||||||
<div class="chd">
|
<div v-for="cart in carts" :key="cart.cartId" class="cart">
|
||||||
<span class="cid">{{ cart.cartId }}</span>
|
<div class="chd">
|
||||||
<span class="cp">{{ t('lane.parts', { n: partsOf(cart) }) }}</span>
|
<span class="cid">{{ cart.cartId }}</span>
|
||||||
|
<span class="cp">{{ t('lane.parts', { n: partsOf(cart) }) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="cbody">
|
||||||
|
<OrderLine v-for="(o, i) in cart.orders" :key="i" :order-no="o.orderNo" :qty="o.qty" :color-index="o.colorIndex" />
|
||||||
|
</div>
|
||||||
|
<div class="cfoot">{{ t('lane.ovenIn', { n: cart.etaMin }) }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cbody">
|
</div>
|
||||||
<OrderLine v-for="(o, i) in cart.orders" :key="i" :order-no="o.orderNo" :qty="o.qty" :color-index="o.colorIndex" />
|
<!-- Connector: bridges the on-the-way lane down to the oven. `.drop` grows to
|
||||||
</div>
|
fill the space below the cart list, so every active column's arrow lands on
|
||||||
<div class="cfoot">{{ t('lane.ovenIn', { n: cart.etaMin }) }}</div>
|
the same line and touches the oven box (like the oven→Fertig connector). -->
|
||||||
|
<div v-if="active" class="drop" :title="t('flow.onWay')">
|
||||||
|
<span class="dropline"></span>
|
||||||
|
<span class="arrow">▼</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.lane-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
.lane {
|
.lane {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 100%;
|
||||||
min-height: 132px;
|
min-height: 132px;
|
||||||
max-height: 236px;
|
max-height: 236px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-top: 22px;
|
padding-top: 22px;
|
||||||
|
padding-bottom: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 12px;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
}
|
}
|
||||||
.conn {
|
.conn {
|
||||||
@ -50,7 +66,7 @@ const partsOf = (c: CartOnWay) => c.orders.reduce((s, o) => s + o.qty, 0)
|
|||||||
width: 2px;
|
width: 2px;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
background: repeating-linear-gradient(180deg, var(--way) 0 3px, transparent 3px 11px);
|
background: repeating-linear-gradient(180deg, var(--transit) 0 3px, transparent 3px 11px);
|
||||||
background-size: 2px 11px;
|
background-size: 2px 11px;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
@ -73,11 +89,42 @@ const partsOf = (c: CartOnWay) => c.orders.reduce((s, o) => s + o.qty, 0)
|
|||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
.lc.on {
|
.lc.on {
|
||||||
color: var(--way);
|
color: var(--transit);
|
||||||
}
|
}
|
||||||
.lc.off {
|
.lc.off {
|
||||||
color: var(--ink-faint);
|
color: var(--ink-faint);
|
||||||
}
|
}
|
||||||
|
/* Bridge from the cart lane down to the oven — mirrors the oven→Fertig `.link`. */
|
||||||
|
.drop {
|
||||||
|
position: relative;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 26px;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
.dropline {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 0;
|
||||||
|
bottom: 7px;
|
||||||
|
width: 2px;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: repeating-linear-gradient(180deg, var(--transit) 0 3px, transparent 3px 11px);
|
||||||
|
background-size: 2px 11px;
|
||||||
|
opacity: 0.95;
|
||||||
|
animation: flowdown 1.05s linear infinite;
|
||||||
|
box-shadow: 0 0 6px var(--transit);
|
||||||
|
}
|
||||||
|
.arrow {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 0;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
color: var(--transit);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
line-height: 1;
|
||||||
|
text-shadow: 0 0 6px var(--transit);
|
||||||
|
animation: blink 1.1s ease-in-out infinite;
|
||||||
|
}
|
||||||
.cart {
|
.cart {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|||||||
@ -25,6 +25,10 @@ function cartsFor(pressName: string): CartOnWay[] {
|
|||||||
<div class="stagehd">
|
<div class="stagehd">
|
||||||
<span class="sw" :style="{ background: 'var(--press)' }"></span>
|
<span class="sw" :style="{ background: 'var(--press)' }"></span>
|
||||||
{{ t('line.header') }}
|
{{ t('line.header') }}
|
||||||
|
<span v-if="wayCarts > 0" class="way-badge">
|
||||||
|
<span class="dot"></span>
|
||||||
|
{{ t('kpi.onWaySub', { n: wayCarts }) }}
|
||||||
|
</span>
|
||||||
<span class="c">{{ t('line.active', { running, total }) }}</span>
|
<span class="c">{{ t('line.active', { running, total }) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -35,10 +39,6 @@ function cartsFor(pressName: string): CartOnWay[] {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="link" :style="{ '--lc': 'var(--way)' }">
|
|
||||||
<span class="lbl"><b>{{ t('line.toOven') }}</b> → {{ t('line.toOvenTail') }} · {{ t('line.wagen', { n: wayCarts }) }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<OvenBand :batches="payload.oven" :temp-c="payload.ovenTempC ?? null" :avg-min="payload.ovenAvgMin" />
|
<OvenBand :batches="payload.oven" :temp-c="payload.ovenTempC ?? null" :avg-min="payload.ovenAvgMin" />
|
||||||
|
|
||||||
<div class="link" :style="{ '--lc': 'var(--done)' }">
|
<div class="link" :style="{ '--lc': 'var(--done)' }">
|
||||||
@ -78,18 +78,45 @@ html:not(.dark) .production {
|
|||||||
height: 9px;
|
height: 9px;
|
||||||
border-radius: var(--r);
|
border-radius: var(--r);
|
||||||
}
|
}
|
||||||
|
.way-badge {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
color: var(--transit);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
.dot {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--transit);
|
||||||
|
box-shadow: 0 0 6px var(--transit);
|
||||||
|
animation: blink 1.2s ease-in-out infinite;
|
||||||
|
}
|
||||||
.c {
|
.c {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
color: var(--ink-dim);
|
color: var(--ink-dim);
|
||||||
}
|
}
|
||||||
.matrix {
|
.matrix {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
/* No gap: the per-press amber connectors (PressLane `.drop`) grow to the bottom of
|
||||||
|
this grid, so their arrows land flush on the oven band's top edge. Hide the
|
||||||
|
horizontal scrollbar — with the gap gone, a stray/near-miss scrollbar otherwise
|
||||||
|
rendered as a gray line sitting on the oven's top edge. Hiding it also reclaims
|
||||||
|
the scrollbar's ~15px, which clears the near-miss overflow so the grid just fits. */
|
||||||
|
margin-bottom: 0;
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
-ms-overflow-style: none; /* legacy Edge */
|
||||||
|
}
|
||||||
|
.matrix::-webkit-scrollbar {
|
||||||
|
display: none; /* Chromium / WebKit (the Grafana embed) */
|
||||||
}
|
}
|
||||||
.grid {
|
.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(10, minmax(102px, 1fr));
|
grid-template-columns: repeat(10, minmax(96px, 1fr));
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
min-width: 1080px;
|
min-width: 1032px;
|
||||||
}
|
}
|
||||||
.link {
|
.link {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ export default {
|
|||||||
app: {
|
app: {
|
||||||
brand: 'PressV',
|
brand: 'PressV',
|
||||||
plant: 'Werk',
|
plant: 'Werk',
|
||||||
line: 'Temper-Linie',
|
line: 'Temperprozess',
|
||||||
subtitle: 'Live-Übersicht',
|
subtitle: 'Live-Übersicht',
|
||||||
live: 'Live',
|
live: 'Live',
|
||||||
demo: 'Demo-Daten',
|
demo: 'Demo-Daten',
|
||||||
@ -10,6 +10,7 @@ export default {
|
|||||||
flow: {
|
flow: {
|
||||||
presses: 'Pressen',
|
presses: 'Pressen',
|
||||||
pressesSub: 'inkl. nicht verladen',
|
pressesSub: 'inkl. nicht verladen',
|
||||||
|
loaded: 'Auf Wagen verladen',
|
||||||
onWay: 'Auf dem Weg',
|
onWay: 'Auf dem Weg',
|
||||||
oven: 'Ofen',
|
oven: 'Ofen',
|
||||||
finished: 'Fertig',
|
finished: 'Fertig',
|
||||||
@ -29,13 +30,10 @@ export default {
|
|||||||
scrapRateSub: 'Ausschuss / Gesamt',
|
scrapRateSub: 'Ausschuss / Gesamt',
|
||||||
},
|
},
|
||||||
line: {
|
line: {
|
||||||
header: 'Pressenhalle → auf dem Weg',
|
header: 'Maschinenhalle',
|
||||||
active: '{running}/{total} aktiv · Wagen hängen unter ihrer Presse',
|
active: '{running}/{total} aktiv · Wagen hängen unter ihrer Presse',
|
||||||
toOven: 'Auf dem Weg',
|
|
||||||
toOvenTail: 'in den Ofen',
|
|
||||||
toStorage: 'Aus dem Ofen',
|
toStorage: 'Aus dem Ofen',
|
||||||
toStorageTail: 'Fertig / Lager',
|
toStorageTail: 'Fertig / Lager',
|
||||||
wagen: '{n} Wagen',
|
|
||||||
},
|
},
|
||||||
press: {
|
press: {
|
||||||
good: 'Gut',
|
good: 'Gut',
|
||||||
@ -44,6 +42,7 @@ export default {
|
|||||||
statusRun: 'Läuft',
|
statusRun: 'Läuft',
|
||||||
statusStop: 'Störung',
|
statusStop: 'Störung',
|
||||||
statusIdle: 'Leerlauf',
|
statusIdle: 'Leerlauf',
|
||||||
|
orderCount: '{n} aktive Aufträge',
|
||||||
},
|
},
|
||||||
lane: {
|
lane: {
|
||||||
wagen: '{n} Wagen ↓',
|
wagen: '{n} Wagen ↓',
|
||||||
|
|||||||
@ -3,7 +3,7 @@ export default {
|
|||||||
app: {
|
app: {
|
||||||
brand: 'PressV',
|
brand: 'PressV',
|
||||||
plant: 'Plant',
|
plant: 'Plant',
|
||||||
line: 'Temper Line',
|
line: 'Temperprozess',
|
||||||
subtitle: 'Live Overview',
|
subtitle: 'Live Overview',
|
||||||
live: 'Live',
|
live: 'Live',
|
||||||
demo: 'Sample data',
|
demo: 'Sample data',
|
||||||
@ -11,6 +11,7 @@ export default {
|
|||||||
flow: {
|
flow: {
|
||||||
presses: 'Presses',
|
presses: 'Presses',
|
||||||
pressesSub: 'incl. not yet loaded',
|
pressesSub: 'incl. not yet loaded',
|
||||||
|
loaded: 'Loaded onto cart',
|
||||||
onWay: 'On the way',
|
onWay: 'On the way',
|
||||||
oven: 'Oven',
|
oven: 'Oven',
|
||||||
finished: 'Finished',
|
finished: 'Finished',
|
||||||
@ -30,13 +31,10 @@ export default {
|
|||||||
scrapRateSub: 'Scrap / total',
|
scrapRateSub: 'Scrap / total',
|
||||||
},
|
},
|
||||||
line: {
|
line: {
|
||||||
header: 'Press hall → on the way',
|
header: 'Machine hall',
|
||||||
active: '{running}/{total} active · carts hang under their press',
|
active: '{running}/{total} active · carts hang under their press',
|
||||||
toOven: 'On the way',
|
|
||||||
toOvenTail: 'into the oven',
|
|
||||||
toStorage: 'Out of the oven',
|
toStorage: 'Out of the oven',
|
||||||
toStorageTail: 'finished / storage',
|
toStorageTail: 'finished / storage',
|
||||||
wagen: '{n} carts',
|
|
||||||
},
|
},
|
||||||
press: {
|
press: {
|
||||||
good: 'Good',
|
good: 'Good',
|
||||||
@ -45,6 +43,7 @@ export default {
|
|||||||
statusRun: 'Running',
|
statusRun: 'Running',
|
||||||
statusStop: 'Fault',
|
statusStop: 'Fault',
|
||||||
statusIdle: 'Idle',
|
statusIdle: 'Idle',
|
||||||
|
orderCount: '{n} active orders',
|
||||||
},
|
},
|
||||||
lane: {
|
lane: {
|
||||||
wagen: '{n} carts ↓',
|
wagen: '{n} carts ↓',
|
||||||
|
|||||||
@ -16,7 +16,8 @@
|
|||||||
Neutral surfaces are the locked prototype's board palette (dark, layered,
|
Neutral surfaces are the locked prototype's board palette (dark, layered,
|
||||||
with a radial glow). The FLOW ACCENTS match PressV's --c-* process colours
|
with a radial glow). The FLOW ACCENTS match PressV's --c-* process colours
|
||||||
verbatim so the temper process reads the same across every SPRO app
|
verbatim so the temper process reads the same across every SPRO app
|
||||||
(press=violet, on-the-way/cart=cyan, oven=orange, hot=red, finished=emerald).
|
(press=violet, cart/verladen=cyan, in-transit=amber, oven=orange, hot=red,
|
||||||
|
finished=emerald — same 5-station palette as the Ausschuss-Station board).
|
||||||
Font families come from @sp-ui-kit/tokens (Inter Variable + mono).
|
Font families come from @sp-ui-kit/tokens (Inter Variable + mono).
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
:root {
|
:root {
|
||||||
@ -29,10 +30,11 @@
|
|||||||
|
|
||||||
--ink: #e8edf2;
|
--ink: #e8edf2;
|
||||||
--ink-dim: #97a3b1;
|
--ink-dim: #97a3b1;
|
||||||
--ink-faint: #5a6573;
|
--ink-faint: #7f8b9a;
|
||||||
|
|
||||||
--press: #a78bfa; /* violet — Pressen / not yet loaded */
|
--press: #a78bfa; /* violet — Pressen / not yet loaded */
|
||||||
--way: #22d3ee; /* cyan — Auf dem Weg / cart */
|
--way: #22d3ee; /* cyan — Auf Wagen verladen / cart */
|
||||||
|
--transit: #fbbf24; /* amber — Auf dem Weg (unterwegs) */
|
||||||
--oven: #f97316; /* orange — Ofen */
|
--oven: #f97316; /* orange — Ofen */
|
||||||
--hot: #ef4444; /* red — Ofen, kurz vor raus */
|
--hot: #ef4444; /* red — Ofen, kurz vor raus */
|
||||||
--done: #34d399; /* emerald — Fertig / Lager */
|
--done: #34d399; /* emerald — Fertig / Lager */
|
||||||
@ -63,10 +65,11 @@ html:not(.dark) {
|
|||||||
|
|
||||||
--ink: #0f172a;
|
--ink: #0f172a;
|
||||||
--ink-dim: #475569;
|
--ink-dim: #475569;
|
||||||
--ink-faint: #64748b;
|
--ink-faint: #4b586b;
|
||||||
|
|
||||||
--press: #6d28d9;
|
--press: #6d28d9;
|
||||||
--way: #0e7490;
|
--way: #0e7490;
|
||||||
|
--transit: #a16207;
|
||||||
--oven: #c2410c;
|
--oven: #c2410c;
|
||||||
--hot: #dc2626;
|
--hot: #dc2626;
|
||||||
--done: #15803d;
|
--done: #15803d;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
<!--
|
<!--
|
||||||
TemperOverviewPage.vue — the whole-line temper board (design #4 "Shop-floor
|
TemperOverviewPage.vue — the whole-line temper board (design #4 "Shop-floor
|
||||||
Schematic", locked). One connected line: Pressen → (cyan ↓) → Ofen → (green ↓)
|
Schematic", locked). One connected line: Pressen → (per-press amber ↓ arrows,
|
||||||
→ Fertig. Carts hang under their origin press; the oven & finished bands scroll
|
only under presses with a cart on the way) → Ofen → (green ↓) → Fertig. Carts
|
||||||
horizontally. The time-range picker scopes ONLY the Fertig figures.
|
hang under their origin press; the oven & finished bands scroll horizontally.
|
||||||
|
The time-range picker scopes ONLY the Fertig figures.
|
||||||
|
|
||||||
Data comes from the store (GET …/api/overview, polled). With no backend the
|
Data comes from the store (GET …/api/overview, polled). With no backend the
|
||||||
store falls back to bundled sample data, so `npm run dev` renders the design.
|
store falls back to bundled sample data, so `npm run dev` renders the design.
|
||||||
@ -48,7 +49,7 @@ onUnmounted(() => store.stopPolling())
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.wrap {
|
.wrap {
|
||||||
max-width: 1240px;
|
max-width: 1300px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px 22px 80px;
|
padding: 20px 22px 80px;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user