统一仓库纸质单据体验
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<span ref="anchorRef" class="document-action-anchor" aria-hidden="true"></span>
|
||||
|
||||
<Teleport :to="actionHost" :disabled="!actionHost">
|
||||
<div
|
||||
class="document-action-bar"
|
||||
:class="[
|
||||
$attrs.class,
|
||||
{ 'document-action-bar--with-state': $slots.state }
|
||||
]"
|
||||
@click.capture="handleActionClick"
|
||||
>
|
||||
<div v-if="$slots.state" class="document-action-state">
|
||||
<slot name="state" />
|
||||
</div>
|
||||
|
||||
<div class="document-action-buttons">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { nextTick, onMounted, ref } from "vue";
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false
|
||||
});
|
||||
|
||||
const anchorRef = ref(null);
|
||||
const actionHost = ref(null);
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
const form = anchorRef.value?.closest?.("form");
|
||||
actionHost.value = form?.querySelector?.("[data-document-action-host]") || form?.querySelector?.("[data-warehouse-document-action-host]") || null;
|
||||
});
|
||||
|
||||
function handleActionClick(event) {
|
||||
const target = event.target;
|
||||
const submitter = target?.closest?.("button[type='submit'], input[type='submit']");
|
||||
if (!submitter || submitter.disabled) {
|
||||
return;
|
||||
}
|
||||
const form = anchorRef.value?.closest?.("form");
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
form.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true }));
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<component
|
||||
:is="as"
|
||||
class="document-paper-field"
|
||||
:class="[
|
||||
spanClass,
|
||||
{
|
||||
'document-paper-field-readonly': readonly,
|
||||
'document-paper-field-upload': upload
|
||||
}
|
||||
]"
|
||||
>
|
||||
<span>{{ label }}</span>
|
||||
<slot>
|
||||
<p class="document-paper-readonly-value">{{ value || "-" }}</p>
|
||||
</slot>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: ""
|
||||
},
|
||||
span: {
|
||||
type: [Number, String],
|
||||
default: 1
|
||||
},
|
||||
as: {
|
||||
type: String,
|
||||
default: "label"
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
upload: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
const spanClass = computed(() => {
|
||||
if (String(props.span) === "full") return "document-paper-field-full";
|
||||
if (Number(props.span) === 2) return "document-paper-field-wide";
|
||||
return "";
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<form class="document-form-shell" @submit.prevent="emit('submit')">
|
||||
<DocumentPaper
|
||||
:title="title"
|
||||
:document-no="documentNo"
|
||||
:company-name="companyName"
|
||||
:tone="tone"
|
||||
:signature-labels="signatureLabels"
|
||||
>
|
||||
<div class="document-form-meta" :aria-label="metaAriaLabel">
|
||||
<span>{{ metaLabel }}</span>
|
||||
<strong>{{ companyName }}</strong>
|
||||
<span>{{ dateLabel }}</span>
|
||||
<strong>{{ displayBusinessDate }}</strong>
|
||||
</div>
|
||||
|
||||
<main class="document-form-body">
|
||||
<slot />
|
||||
</main>
|
||||
</DocumentPaper>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
import DocumentPaper from "./DocumentPaper.vue";
|
||||
import { formatChineseDate } from "../../utils/formatters";
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
documentNo: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
businessDate: {
|
||||
type: [String, Date],
|
||||
default: ""
|
||||
},
|
||||
tone: {
|
||||
type: String,
|
||||
default: "green"
|
||||
},
|
||||
companyName: {
|
||||
type: String,
|
||||
default: "宁波嘉恒智能科技有限公司"
|
||||
},
|
||||
metaLabel: {
|
||||
type: String,
|
||||
default: "业务联单"
|
||||
},
|
||||
dateLabel: {
|
||||
type: String,
|
||||
default: "业务日期"
|
||||
},
|
||||
signatureLabels: {
|
||||
type: Array,
|
||||
default: () => ["制单", "经办", "审核", "财务"]
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(["submit"]);
|
||||
|
||||
const displayBusinessDate = computed(() => formatChineseDate(props.businessDate));
|
||||
const metaAriaLabel = computed(() => `${props.metaLabel}基础信息`);
|
||||
</script>
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="document-inline-summary" :class="toneClass">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
tone: {
|
||||
type: String,
|
||||
default: "green"
|
||||
}
|
||||
});
|
||||
|
||||
const toneClass = computed(() => `document-inline-summary-${props.tone}`);
|
||||
</script>
|
||||
@@ -43,7 +43,11 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<div class="document-paper-action-host" data-warehouse-document-action-host></div>
|
||||
<div
|
||||
class="document-paper-action-host"
|
||||
data-document-action-host
|
||||
data-warehouse-document-action-host
|
||||
></div>
|
||||
</article>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<section class="document-section">
|
||||
<header class="document-section-head">
|
||||
<span class="document-section-index">{{ index }}</span>
|
||||
<strong>{{ title }}</strong>
|
||||
</header>
|
||||
|
||||
<div class="document-section-grid">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
index: {
|
||||
type: [Number, String],
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<section class="document-selector-panel">
|
||||
<div class="document-selector-heading">
|
||||
<span>{{ label }}</span>
|
||||
<strong>{{ hint }}</strong>
|
||||
</div>
|
||||
<div class="document-selector-body">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
hint: {
|
||||
type: String,
|
||||
default: "请选择"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<section class="document-settle-panel">
|
||||
<slot />
|
||||
</section>
|
||||
</template>
|
||||
@@ -1,47 +1,12 @@
|
||||
<template>
|
||||
<span ref="anchorRef" class="warehouse-document-action-anchor" aria-hidden="true"></span>
|
||||
|
||||
<Teleport :to="actionHost" :disabled="!actionHost">
|
||||
<div
|
||||
class="warehouse-document-action-bar warehouse-document-action-bar--shared"
|
||||
:class="{ 'warehouse-document-action-bar--with-state': $slots.state }"
|
||||
@click.capture="handleActionClick"
|
||||
>
|
||||
<div v-if="$slots.state" class="warehouse-document-action-state">
|
||||
<slot name="state" />
|
||||
</div>
|
||||
|
||||
<div class="warehouse-document-action-buttons">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
<DocumentActionBar class="warehouse-document-action-bar warehouse-document-action-bar--shared">
|
||||
<template v-if="$slots.state" #state>
|
||||
<slot name="state" />
|
||||
</template>
|
||||
<slot />
|
||||
</DocumentActionBar>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { nextTick, onMounted, ref } from "vue";
|
||||
|
||||
const anchorRef = ref(null);
|
||||
const actionHost = ref(null);
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
actionHost.value = anchorRef.value
|
||||
?.closest?.("form")
|
||||
?.querySelector?.("[data-warehouse-document-action-host]") || null;
|
||||
});
|
||||
|
||||
function handleActionClick(event) {
|
||||
const target = event.target;
|
||||
const submitter = target?.closest?.("button[type='submit'], input[type='submit']");
|
||||
if (!submitter || submitter.disabled) {
|
||||
return;
|
||||
}
|
||||
const form = anchorRef.value?.closest?.("form");
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
form.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true }));
|
||||
}
|
||||
import DocumentActionBar from "./DocumentActionBar.vue";
|
||||
</script>
|
||||
|
||||
@@ -1,32 +1,23 @@
|
||||
<template>
|
||||
<form class="warehouse-document-form" @submit.prevent="emit('submit')">
|
||||
<DocumentPaper
|
||||
:title="title"
|
||||
:document-no="documentNo"
|
||||
:company-name="companyName"
|
||||
:tone="tone"
|
||||
>
|
||||
<div class="warehouse-document-form-meta" aria-label="仓库单据基础信息">
|
||||
<span>仓库联单</span>
|
||||
<strong>{{ companyName }}</strong>
|
||||
<span>业务日期</span>
|
||||
<strong>{{ displayBusinessDate }}</strong>
|
||||
</div>
|
||||
|
||||
<main class="warehouse-document-body">
|
||||
<slot />
|
||||
</main>
|
||||
</DocumentPaper>
|
||||
</form>
|
||||
<DocumentFormShell
|
||||
class="warehouse-document-form"
|
||||
:title="title"
|
||||
:document-no="documentNo"
|
||||
:business-date="businessDate"
|
||||
:tone="tone"
|
||||
:company-name="companyName"
|
||||
meta-label="仓库联单"
|
||||
:signature-labels="signatureLabels"
|
||||
@submit="emit('submit')"
|
||||
>
|
||||
<slot />
|
||||
</DocumentFormShell>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import DocumentFormShell from "./DocumentFormShell.vue";
|
||||
|
||||
import DocumentPaper from "./DocumentPaper.vue";
|
||||
import { formatChineseDate } from "../../utils/formatters";
|
||||
|
||||
const props = defineProps({
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
@@ -46,9 +37,12 @@ const props = defineProps({
|
||||
companyName: {
|
||||
type: String,
|
||||
default: "嘉恒仓库"
|
||||
},
|
||||
signatureLabels: {
|
||||
type: Array,
|
||||
default: () => ["制单", "审核", "仓库", "财务"]
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(["submit"]);
|
||||
const displayBusinessDate = computed(() => formatChineseDate(props.businessDate));
|
||||
</script>
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
<template>
|
||||
<section class="warehouse-document-section">
|
||||
<header class="warehouse-document-section-head">
|
||||
<span class="warehouse-document-section-index">{{ index }}</span>
|
||||
<strong>{{ title }}</strong>
|
||||
</header>
|
||||
|
||||
<div class="warehouse-document-section-grid">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
<DocumentSection
|
||||
class="warehouse-document-section"
|
||||
:index="index"
|
||||
:title="title"
|
||||
>
|
||||
<slot />
|
||||
</DocumentSection>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DocumentSection from "./DocumentSection.vue";
|
||||
|
||||
defineProps({
|
||||
index: {
|
||||
type: [Number, String],
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
function readComponent(name) {
|
||||
return readFileSync(join(__dirname, name), "utf8");
|
||||
}
|
||||
|
||||
const mainCss = readFileSync(resolve(__dirname, "../../styles/main.css"), "utf8");
|
||||
|
||||
describe("document form foundation", () => {
|
||||
it("provides generic system-wide paper form components", () => {
|
||||
[
|
||||
"DocumentFormShell.vue",
|
||||
"DocumentSection.vue",
|
||||
"DocumentActionBar.vue",
|
||||
"DocumentField.vue",
|
||||
"DocumentSelectorPanel.vue",
|
||||
"DocumentInlineSummary.vue",
|
||||
"DocumentSettlePanel.vue"
|
||||
].forEach((name) => {
|
||||
const source = readComponent(name);
|
||||
assert.match(source, /document-/);
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps warehouse wrappers as compatibility adapters over generic document components", () => {
|
||||
assert.match(readComponent("WarehouseDocumentFormShell.vue"), /import DocumentFormShell/);
|
||||
assert.match(readComponent("WarehouseDocumentSection.vue"), /import DocumentSection/);
|
||||
assert.match(readComponent("WarehouseDocumentActionBar.vue"), /import DocumentActionBar/);
|
||||
});
|
||||
|
||||
it("exposes a generic action host without removing the existing warehouse host", () => {
|
||||
const paper = readComponent("DocumentPaper.vue");
|
||||
assert.match(paper, /data-document-action-host/);
|
||||
assert.match(paper, /data-warehouse-document-action-host/);
|
||||
});
|
||||
|
||||
it("defines generic document paper controls and keeps warehouse aliases compatible", () => {
|
||||
assert.match(mainCss, /\.document-form-shell/);
|
||||
assert.match(mainCss, /\.document-section-grid/);
|
||||
assert.match(mainCss, /\.document-paper-field/);
|
||||
assert.match(mainCss, /\.document-selector-panel/);
|
||||
assert.match(mainCss, /\.document-inline-summary/);
|
||||
assert.match(mainCss, /\.document-settle-panel/);
|
||||
assert.match(mainCss, /\.warehouse-paper-control-grid/);
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,14 @@ function functionBody(name) {
|
||||
return match[0];
|
||||
}
|
||||
|
||||
function drawerBlock(openBinding, nextMarker) {
|
||||
const start = source.indexOf(`:open="${openBinding}"`);
|
||||
assert.ok(start >= 0, `expected drawer ${openBinding} to exist`);
|
||||
const end = source.indexOf(nextMarker, start + openBinding.length);
|
||||
assert.ok(end > start, `expected drawer ${openBinding} to end before ${nextMarker}`);
|
||||
return source.slice(start, end);
|
||||
}
|
||||
|
||||
describe("InventoryLedgerView warehouse action layout", () => {
|
||||
it("keeps stocktake inside the tool action group instead of a standalone rack", () => {
|
||||
assert.equal(source.includes("warehouse-stocktake-rack"), false);
|
||||
@@ -77,6 +85,134 @@ describe("InventoryLedgerView warehouse action layout", () => {
|
||||
assert.match(mainCss, /\.warehouse-paper-summary-grid\s*\{[\s\S]*grid-template-columns: repeat\(4, minmax\(0, 1fr\)\);/);
|
||||
});
|
||||
|
||||
it("keeps customer supplied inbound paper fields full width instead of squeezed into a side column", () => {
|
||||
assert.match(source, /title="客料入库单"/);
|
||||
assert.match(source, /class="warehouse-document-meta-strip"/);
|
||||
assert.match(source, /class="warehouse-paper-grid"/);
|
||||
assert.match(mainCss, /\.warehouse-document-operation-form\s*\{[\s\S]*width: 100%;/);
|
||||
assert.match(mainCss, /\.warehouse-document-section-grid > \.warehouse-document-meta-strip\s*\{[\s\S]*grid-column: 1 \/ -1;/);
|
||||
assert.match(mainCss, /\.warehouse-document-section-grid > \.warehouse-paper-grid\s*\{[\s\S]*grid-column: 1 \/ -1;/);
|
||||
assert.match(mainCss, /\.warehouse-paper-field > span\s*\{[\s\S]*font-size: 13px;/);
|
||||
assert.match(mainCss, /\.warehouse-paper-field input,[\s\S]*?\.warehouse-paper-field textarea\s*\{[\s\S]*font-size: 15px;/);
|
||||
assert.match(mainCss, /@media \(max-width: 520px\)[\s\S]*\.document-paper-binder,[\s\S]*\.document-retained-mark\s*\{[\s\S]*display: none;/);
|
||||
assert.match(mainCss, /@media \(max-width: 520px\)[\s\S]*\.document-paper-sheet\s*\{[\s\S]*padding: 18px 10px 22px;/);
|
||||
assert.match(mainCss, /body \.workflow-drawer\.form-drawer:has\(\.warehouse-document-operation-form\)\s*\{[\s\S]*width: min\(1280px, calc\(100vw - 24px\)\) !important;/);
|
||||
assert.match(mainCss, /body \.workflow-drawer\.form-drawer:has\(\.warehouse-document-operation-form\) \.form-drawer-body\s*\{[\s\S]*overflow-x: hidden !important;/);
|
||||
assert.match(mainCss, /body \.workflow-drawer\.form-drawer:has\(\.warehouse-document-operation-form\) \.document-paper-title\s*\{[\s\S]*font-size: clamp\(22px, 7\.2vw, 28px\) !important;/);
|
||||
assert.match(mainCss, /body \.workflow-drawer\.form-drawer:has\(\.warehouse-document-operation-form\) \.document-paper-title\s*\{[\s\S]*white-space: normal !important;/);
|
||||
assert.match(mainCss, /body \.workflow-drawer\.form-drawer:has\(\.warehouse-document-operation-form\) \.document-paper-title\s*\{[\s\S]*overflow-wrap: anywhere !important;/);
|
||||
assert.match(mainCss, /body \.workflow-drawer\.form-drawer:has\(\.warehouse-document-operation-form\) \.document-number-stamp\s*\{[\s\S]*width: min\(176px, 100%\) !important;/);
|
||||
assert.match(mainCss, /body \.workflow-drawer\.form-drawer:has\(\.warehouse-document-operation-form\) \.form-drawer-body\s*\{[\s\S]*padding: 10px !important;/);
|
||||
});
|
||||
|
||||
it("wraps production-ledger controlled inbound forms in the shared paper control language", () => {
|
||||
assert.match(source, /warehouse-paper-control-grid/);
|
||||
assert.match(source, /warehouse-paper-source-lot-panel/);
|
||||
assert.match(source, /warehouse-paper-source-lot-table/);
|
||||
assert.match(source, /warehouse-paper-inline-summary/);
|
||||
assert.match(source, /warehouse-paper-settle-panel/);
|
||||
assert.match(source, /warehouse-paper-settle-toggle/);
|
||||
assert.match(source, /warehouse-paper-settle-grid/);
|
||||
assert.match(source, /warehouse-paper-settle-remark/);
|
||||
assert.match(mainCss, /\.warehouse-document-section-grid > \.warehouse-paper-control-grid\s*\{[\s\S]*grid-column: 1 \/ -1;/);
|
||||
assert.match(mainCss, /\.warehouse-paper-control-grid\s*\{[\s\S]*grid-template-columns: repeat\(4, minmax\(0, 1fr\)\);/);
|
||||
assert.match(mainCss, /\.warehouse-paper-source-lot-table/);
|
||||
assert.match(mainCss, /\.warehouse-paper-settle-toggle/);
|
||||
});
|
||||
|
||||
it("keeps special adjustment documents inside the paper document language", () => {
|
||||
const specialAdjustmentBlock = source.slice(
|
||||
source.indexOf(':open="specialAdjustmentDrawerOpen"'),
|
||||
source.indexOf(':open="productionDrawerOpen"')
|
||||
);
|
||||
assert.match(source, /special-adjustment-paper-grid/);
|
||||
assert.match(source, /special-adjustment-paper-warning/);
|
||||
assert.match(source, /special-adjustment-paper-lines/);
|
||||
assert.match(source, /special-adjustment-paper-line-card/);
|
||||
assert.doesNotMatch(specialAdjustmentBlock, /<div class="double-field">[\s\S]*?specialAdjustmentForm\.reason/);
|
||||
assert.match(mainCss, /\.special-adjustment-paper-grid/);
|
||||
assert.match(mainCss, /\.special-adjustment-paper-line-card/);
|
||||
});
|
||||
|
||||
it("keeps production outbound document controls paper-native", () => {
|
||||
assert.match(source, /production-out-paper-grid/);
|
||||
assert.match(source, /production-out-source-lot-panel/);
|
||||
assert.match(source, /production-out-source-lot-table/);
|
||||
assert.doesNotMatch(source, /<div class="workflow-tip">选择原材料库存批次出库/);
|
||||
assert.match(mainCss, /\.production-out-source-lot-panel/);
|
||||
});
|
||||
|
||||
it("keeps production ledger inbound settlement controls paper-native", () => {
|
||||
const productionLedgerInboundBlock = source.slice(
|
||||
source.indexOf(':open="productionWorkOrderInboundDrawerOpen"'),
|
||||
source.indexOf("<StocktakeDialog")
|
||||
);
|
||||
assert.match(source, /production-ledger-inbound-paper-grid/);
|
||||
assert.match(source, /production-ledger-inbound-summary/);
|
||||
assert.match(source, /production-ledger-inbound-metrics/);
|
||||
assert.doesNotMatch(productionLedgerInboundBlock, /<div class="triple-field">[\s\S]*?productionWorkOrderInboundForm\.finished_qty/);
|
||||
assert.match(mainCss, /\.production-ledger-inbound-metrics/);
|
||||
});
|
||||
|
||||
it("keeps raw material return outbound documents paper-native", () => {
|
||||
const block = drawerBlock("rawReturnDrawerOpen", ':open="returnInboundDrawerOpen"');
|
||||
assert.match(block, /raw-return-paper-grid/);
|
||||
assert.match(block, /raw-return-logistics-grid/);
|
||||
assert.doesNotMatch(block, /class="double-field"/);
|
||||
assert.doesNotMatch(block, /class="triple-field"/);
|
||||
assert.doesNotMatch(block, /class="form-field/);
|
||||
assert.doesNotMatch(block, /modern-upload/);
|
||||
assert.match(mainCss, /\.raw-return-paper-grid/);
|
||||
});
|
||||
|
||||
it("keeps return inbound and return scrap inbound documents paper-native", () => {
|
||||
const returnBlock = drawerBlock("returnInboundDrawerOpen", ':open="returnScrapInboundDrawerOpen"');
|
||||
const scrapBlock = drawerBlock("returnScrapInboundDrawerOpen", ':open="openingImportDrawerOpen"');
|
||||
[returnBlock, scrapBlock].forEach((block) => {
|
||||
assert.match(block, /return-paper-grid/);
|
||||
assert.match(block, /return-trace-summary/);
|
||||
assert.doesNotMatch(block, /class="double-field"/);
|
||||
assert.doesNotMatch(block, /class="triple-field"/);
|
||||
assert.doesNotMatch(block, /class="form-field/);
|
||||
});
|
||||
assert.match(mainCss, /\.return-paper-grid/);
|
||||
});
|
||||
|
||||
it("keeps finished inbound and sales outbound documents paper-native", () => {
|
||||
const completionBlock = drawerBlock("completionDrawerOpen", ':open="deliveryDrawerOpen"');
|
||||
const deliveryBlock = drawerBlock("deliveryDrawerOpen", ':open="returnReworkDrawerOpen"');
|
||||
assert.match(completionBlock, /completion-paper-grid/);
|
||||
assert.match(completionBlock, /completion-settle-panel/);
|
||||
assert.match(deliveryBlock, /sales-delivery-paper-grid/);
|
||||
assert.match(deliveryBlock, /sales-delivery-allocation-table/);
|
||||
[completionBlock, deliveryBlock].forEach((block) => {
|
||||
assert.doesNotMatch(block, /class="double-field"/);
|
||||
assert.doesNotMatch(block, /class="triple-field"/);
|
||||
assert.doesNotMatch(block, /class="form-field/);
|
||||
assert.doesNotMatch(block, /modern-upload/);
|
||||
});
|
||||
assert.match(mainCss, /\.completion-paper-grid/);
|
||||
assert.match(mainCss, /\.sales-delivery-paper-grid/);
|
||||
});
|
||||
|
||||
it("keeps return rework and production ledger closeout tails paper-native", () => {
|
||||
const reworkBlock = drawerBlock("returnReworkDrawerOpen", ':open="warehouseLedgerDrawerOpen"');
|
||||
const productionBlock = drawerBlock("productionDrawerOpen", ':open="completionDrawerOpen"');
|
||||
const ledgerInboundBlock = drawerBlock("productionWorkOrderInboundDrawerOpen", "<StocktakeDialog");
|
||||
assert.match(reworkBlock, /return-rework-paper-grid/);
|
||||
assert.match(reworkBlock, /return-rework-trace-summary/);
|
||||
assert.match(productionBlock, /production-out-paper-remark/);
|
||||
assert.match(ledgerInboundBlock, /production-ledger-inbound-settle-panel/);
|
||||
assert.match(ledgerInboundBlock, /production-ledger-inbound-remark/);
|
||||
[reworkBlock, productionBlock, ledgerInboundBlock].forEach((block) => {
|
||||
assert.doesNotMatch(block, /class="double-field"/);
|
||||
assert.doesNotMatch(block, /class="triple-field"/);
|
||||
assert.doesNotMatch(block, /class="form-field/);
|
||||
});
|
||||
assert.match(mainCss, /\.return-rework-paper-grid/);
|
||||
assert.match(mainCss, /\.production-ledger-inbound-settle-panel/);
|
||||
});
|
||||
|
||||
it("surfaces generated PDF archive feedback after independent warehouse saves", () => {
|
||||
[
|
||||
["submitRawReturnOutbound", "退货出库"],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user