feat(backend): implement task creation and admin web
This commit is contained in:
@@ -210,6 +210,12 @@
|
||||
<input id="title" name="title" maxlength="120" placeholder="例如:演示用桌面收纳盒">
|
||||
<p id="title-error" class="error"></p>
|
||||
</div>
|
||||
<div class="span-2">
|
||||
<label class="required" for="sku">SKU</label>
|
||||
<input id="sku" name="sku" maxlength="120" placeholder="例如:浅灰色 · 中号">
|
||||
<p id="sku-error" class="error"></p>
|
||||
<p class="help">SKU 是不可覆盖的原始采购要求。</p>
|
||||
</div>
|
||||
<div class="span-2">
|
||||
<label for="description">商品描述</label>
|
||||
<textarea id="description" name="description" placeholder="填写规格、颜色、材质等判断条件"></textarea>
|
||||
@@ -221,7 +227,7 @@
|
||||
<p id="quantity-error" class="error"></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="budget">最高总预算(元)</label>
|
||||
<label for="budget">最高商品总预算(元)</label>
|
||||
<input id="budget" name="budget" type="number" min="0.01" step="0.01" inputmode="decimal" placeholder="不填写则不设上限">
|
||||
<p id="budget-error" class="error"></p>
|
||||
</div>
|
||||
@@ -284,7 +290,7 @@
|
||||
});
|
||||
|
||||
function clearFeedback() {
|
||||
['title', 'quantity', 'budget', 'image'].forEach((name) => {
|
||||
['title', 'sku', 'quantity', 'budget', 'image'].forEach((name) => {
|
||||
document.querySelector(`#${name}-error`).textContent = '';
|
||||
});
|
||||
notice.style.display = 'none';
|
||||
@@ -303,18 +309,23 @@
|
||||
clearFeedback();
|
||||
let firstInvalid = null;
|
||||
const title = document.querySelector('#title');
|
||||
const sku = document.querySelector('#sku');
|
||||
const quantity = document.querySelector('#quantity');
|
||||
const budget = document.querySelector('#budget');
|
||||
if (!title.value.trim()) {
|
||||
document.querySelector('#title-error').textContent = '请输入商品标题。';
|
||||
firstInvalid ||= title;
|
||||
}
|
||||
if (!sku.value.trim()) {
|
||||
document.querySelector('#sku-error').textContent = '请输入 SKU。';
|
||||
firstInvalid ||= sku;
|
||||
}
|
||||
if (!Number.isInteger(Number(quantity.value)) || Number(quantity.value) < 1) {
|
||||
document.querySelector('#quantity-error').textContent = '数量必须是大于 0 的整数。';
|
||||
firstInvalid ||= quantity;
|
||||
}
|
||||
if (budget.value && Number(budget.value) <= 0) {
|
||||
document.querySelector('#budget-error').textContent = '预算必须大于 0,或留空。';
|
||||
document.querySelector('#budget-error').textContent = '商品总预算必须大于 0,或留空。';
|
||||
firstInvalid ||= budget;
|
||||
}
|
||||
if (!image.files.length) {
|
||||
|
||||
@@ -289,8 +289,9 @@
|
||||
<p class="description">桌面用分格收纳盒,浅灰色,塑料材质。
|
||||
需要带可拆分隔板,外观接近参考图。</p>
|
||||
<div class="constraints">
|
||||
<span class="constraint">SKU:浅灰色 · 中号</span>
|
||||
<span class="constraint">数量:2</span>
|
||||
<span class="constraint">最高总预算:60.00 元</span>
|
||||
<span class="constraint">最高商品总预算:60.00 元</span>
|
||||
<span class="constraint">关键属性:浅灰 / 分隔板</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -38,14 +38,14 @@
|
||||
</section>
|
||||
<section class="panel" id="requirement" aria-labelledby="requirementTitle">
|
||||
<h2 id="requirementTitle">管理员原始要求</h2>
|
||||
<dl class="facts"><dt>商品</dt><dd>透明抽屉式收纳盒</dd><dt>SKU</dt><dd>白色 · 中号</dd><dt>数量</dt><dd>2 件</dd><dt>最高预算</dt><dd>¥ 48.00 / 件</dd></dl>
|
||||
<dl class="facts"><dt>商品</dt><dd>透明抽屉式收纳盒</dd><dt>SKU</dt><dd>白色 · 中号</dd><dt>数量</dt><dd>2 件</dd><dt>最高商品总预算</dt><dd>¥ 96.00</dd></dl>
|
||||
</section>
|
||||
<section class="panel" id="candidate" aria-labelledby="candidateTitle">
|
||||
<h2 id="candidateTitle">候选 1 / 3</h2>
|
||||
<div class="evidence" role="img" aria-label="脱敏的候选商品截图占位">脱敏候选截图<br>证据占位</div>
|
||||
<dl class="facts"><dt>候选标题</dt><dd>透明可叠放抽屉收纳盒</dd><dt>单价</dt><dd class="price" id="price">¥ 39.90</dd></dl>
|
||||
<h3>匹配与风险</h3>
|
||||
<ul class="checks" id="checks"><li><span class="ok">符合</span> 颜色:白色</li><li><span class="ok">符合</span> 规格:中号</li><li><span class="ok">符合</span> 单价未超过预算</li></ul>
|
||||
<ul class="checks" id="checks"><li><span class="ok">符合</span> 颜色:白色</li><li><span class="ok">符合</span> 规格:中号</li><li><span class="ok">符合</span> 商品总价 ¥ 79.80 未超过预算</li></ul>
|
||||
</section>
|
||||
<section class="panel">
|
||||
<h2>人员结论</h2>
|
||||
@@ -65,7 +65,7 @@
|
||||
</dialog>
|
||||
<script>
|
||||
const scenario=document.querySelector("#scenario"),candidate=document.querySelector("#candidate"),accept=document.querySelector("#accept"),reject=document.querySelector("#reject"),noneAction=document.querySelector("#noneAction"),price=document.querySelector("#price"),checks=document.querySelector("#checks"),dialog=document.querySelector("#confirmDialog"),cancel=document.querySelector("#cancel"),completion=document.querySelector("#completion");let pending="";
|
||||
function render(){const v=scenario.value,missing=v==="none";candidate.hidden=missing;noneAction.disabled=!missing;accept.disabled=v!=="valid";reject.disabled=missing;if(v==="over"){price.textContent="¥ 56.00";checks.innerHTML='<li><span class="ok">符合</span> 颜色:白色</li><li><span class="ok">符合</span> 规格:中号</li><li><span class="risk">不符合</span> 单价超过最高预算,不能接受</li>'}else if(v==="unknown"){price.textContent="¥ 41.00";checks.innerHTML='<li><span class="ok">符合</span> 颜色:白色</li><li><span class="risk">未知</span> 规格无法确认,不能接受</li><li><span class="ok">符合</span> 单价未超过预算</li>'}else{price.textContent="¥ 39.90";checks.innerHTML='<li><span class="ok">符合</span> 颜色:白色</li><li><span class="ok">符合</span> 规格:中号</li><li><span class="ok">符合</span> 单价未超过预算</li>'}}
|
||||
function render(){const v=scenario.value,missing=v==="none";candidate.hidden=missing;noneAction.disabled=!missing;accept.disabled=v!=="valid";reject.disabled=missing;if(v==="over"){price.textContent="¥ 56.00";checks.innerHTML='<li><span class="ok">符合</span> 颜色:白色</li><li><span class="ok">符合</span> 规格:中号</li><li><span class="risk">不符合</span> 商品总价 ¥ 112.00 超过总预算,不能接受</li>'}else if(v==="unknown"){price.textContent="¥ 41.00";checks.innerHTML='<li><span class="ok">符合</span> 颜色:白色</li><li><span class="risk">未知</span> 规格无法确认,不能接受</li><li><span class="ok">符合</span> 商品总价 ¥ 82.00 未超过总预算</li>'}else{price.textContent="¥ 39.90";checks.innerHTML='<li><span class="ok">符合</span> 颜色:白色</li><li><span class="ok">符合</span> 规格:中号</li><li><span class="ok">符合</span> 商品总价 ¥ 79.80 未超过总预算</li>'}}
|
||||
document.querySelectorAll("[data-action]").forEach(button=>button.addEventListener("click",()=>{pending=button.dataset.action;document.querySelector("#dialogText").textContent="选择:"+pending;dialog.showModal();setTimeout(()=>cancel.focus(),0)}));
|
||||
scenario.addEventListener("change",render);cancel.addEventListener("click",()=>dialog.close());dialog.addEventListener("cancel",e=>{e.preventDefault();dialog.close()});document.querySelector("#confirm").addEventListener("click",()=>{dialog.close();completion.classList.add("show");document.querySelector("#completionText").textContent="“"+pending+"”已记录,结果正在同步。";completion.scrollIntoView({behavior:"smooth",block:"start"})});render();
|
||||
</script>
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
<dt>商品标题</dt><dd>透明抽屉式桌面收纳盒</dd>
|
||||
<dt>SKU</dt><dd>白色 · 中号</dd>
|
||||
<dt>数量</dt><dd class="constraint">2 件</dd>
|
||||
<dt>最高预算</dt><dd class="constraint">¥ 48.00 / 件</dd>
|
||||
<dt>最高商品总预算</dt><dd class="constraint">¥ 96.00</dd>
|
||||
<dt>描述</dt><dd>带把手,可叠放,优先选择相同外观。</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section class="panel derived" aria-labelledby="derivedTitle">
|
||||
<h2 id="derivedTitle">AI 辅助理解 · 待验证</h2>
|
||||
<p>可能关键词:透明、抽屉式、中号、可叠放。最终数量和预算始终以原始要求为准。</p>
|
||||
<p>可能关键词:透明、抽屉式、中号、可叠放。最终 SKU、数量和商品总预算始终以原始要求为准。</p>
|
||||
</section>
|
||||
<section class="panel">
|
||||
<label for="scenario">原型状态</label>
|
||||
|
||||
Reference in New Issue
Block a user