This commit is contained in:
zlwu committed 2026-07-26 21:06:09 +08:00
1 parent 70bdd820ce
commit bede140d12
988 files changed
+692310 -775910

No files matched your search

@@ -33,6 +33,12 @@
<el-button class="btn-ghost" :loading="saveLoading" @click="handleSaveTemplate">
<el-icon><DocumentChecked /></el-icon>保存模板
</el-button>
<el-button class="btn-ghost" @click="toggleRedSeal">
<el-icon>
<component :is="showRedSeal ? Hide : Stamp" />
</el-icon>
{{ showRedSeal ? '隐藏红章' : '显示红章' }}
</el-button>
<el-button class="btn-ghost" @click="handlePrint">
<el-icon><Printer /></el-icon>打印
</el-button>
@@ -45,7 +51,7 @@
</template>
<script setup lang="ts">
import { Close, DocumentChecked, Download, Printer, View } from '@element-plus/icons-vue'
import { Close, DocumentChecked, Download, Hide, Printer, Stamp, View } from '@element-plus/icons-vue'
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
import { fetchProductDetail } from '@/api/crm/product'
@@ -53,6 +59,7 @@ import { planApi, type Plan } from '@/api/pl'
import TinyMceEditor from '@/components/TinyMceEditor/index.vue'
import { useDictStore } from '@/store/modules/dict'
import {
buildDeliverySlipCompanySealHtml,
generateDeliverySlipTemplate,
DELIVERY_SLIP_DOC_MAX_WIDTH,
DELIVERY_SLIP_PRINT_CSS,
@@ -62,11 +69,14 @@ import {
setupDeliverySlipEditorTypeCheckboxes,
type DeliverySlipRenderContext
} from '@/utils/pl-delivery-slip-template'
import { injectSlipSealImages, stripSlipSealImages } from '@/utils/pl-slip-red-seal'
import { getPlSlipPdfCanvasScale } from '@/utils/pl-slip-pdf-render'
const visible = ref(false)
const slipContent = ref('')
const isPreviewMode = ref(false)
/** 打印弹窗内红章显隐(仅本次弹窗有效,打开时默认显示) */
const showRedSeal = ref(true)
const saveLoading = ref(false)
const pdfGenerating = ref(false)
const currentPlanId = ref('')
@@ -129,6 +139,7 @@ async function buildSlipRenderContext(plan: Plan): Promise<DeliverySlipRenderCon
async function open(planId: string) {
currentPlanId.value = planId
isPreviewMode.value = false
showRedSeal.value = true
try {
ElMessage.info({ message: '正在生成送(提)货单...', duration: 800 })
const res = await planApi.get(planId)
@@ -162,6 +173,22 @@ function handleClosed() {
currentPlanId.value = ''
currentPlan.value = null
isPreviewMode.value = false
showRedSeal.value = true
}
/** 切换红章显示/隐藏(同步影响编辑器、打印、PDF) */
function toggleRedSeal() {
if (showRedSeal.value) {
slipContent.value = stripSlipSealImages(slipContent.value)
showRedSeal.value = false
return
}
slipContent.value = injectSlipSealImages(
slipContent.value,
buildDeliverySlipCompanySealHtml(),
'delivery-slip-seal-block'
)
showRedSeal.value = true
}
async function refreshPlan() {
@@ -32,6 +32,12 @@
<el-button class="btn-ghost" :loading="saveLoading" @click="handleSaveTemplate">
<el-icon><DocumentChecked /></el-icon>保存模板
</el-button>
<el-button class="btn-ghost" @click="toggleRedSeal">
<el-icon>
<component :is="showRedSeal ? Hide : Stamp" />
</el-icon>
{{ showRedSeal ? '隐藏红章' : '显示红章' }}
</el-button>
<el-button class="btn-ghost" @click="handlePrint">
<el-icon><Printer /></el-icon>打印
</el-button>
@@ -44,7 +50,7 @@
</template>
<script setup lang="ts">
import { Close, DocumentChecked, Download, Printer, View } from '@element-plus/icons-vue'
import { Close, DocumentChecked, Download, Hide, Printer, Stamp, View } from '@element-plus/icons-vue'
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
import { fetchProductDetail } from '@/api/crm/product'
@@ -52,6 +58,7 @@ import { planApi, type Plan } from '@/api/pl'
import TinyMceEditor from '@/components/TinyMceEditor/index.vue'
import { useDictStore } from '@/store/modules/dict'
import {
buildInboundSlipCompanySealHtml,
generateInboundSlipTemplate,
INBOUND_SLIP_DOC_MAX_WIDTH,
INBOUND_SLIP_PRINT_CSS,
@@ -60,11 +67,14 @@ import {
restoreInboundSlipPlaceholders,
type InboundSlipRenderContext
} from '@/utils/pl-inbound-slip-template'
import { injectSlipSealImages, stripSlipSealImages } from '@/utils/pl-slip-red-seal'
import { getPlSlipPdfCanvasScale } from '@/utils/pl-slip-pdf-render'
const visible = ref(false)
const slipContent = ref('')
const isPreviewMode = ref(false)
/** 打印弹窗内红章显隐(仅本次弹窗有效,打开时默认显示) */
const showRedSeal = ref(true)
const saveLoading = ref(false)
const pdfGenerating = ref(false)
const currentPlanId = ref('')
@@ -127,6 +137,7 @@ async function buildSlipRenderContext(plan: Plan): Promise<InboundSlipRenderCont
async function open(planId: string) {
currentPlanId.value = planId
isPreviewMode.value = false
showRedSeal.value = true
try {
ElMessage.info({ message: '正在生成入库单...', duration: 800 })
const res = await planApi.get(planId)
@@ -160,6 +171,22 @@ function handleClosed() {
currentPlanId.value = ''
currentPlan.value = null
isPreviewMode.value = false
showRedSeal.value = true
}
/** 切换红章显示/隐藏(同步影响编辑器、打印、PDF) */
function toggleRedSeal() {
if (showRedSeal.value) {
slipContent.value = stripSlipSealImages(slipContent.value)
showRedSeal.value = false
return
}
slipContent.value = injectSlipSealImages(
slipContent.value,
buildInboundSlipCompanySealHtml(),
'inbound-slip-seal-block'
)
showRedSeal.value = true
}
async function refreshPlan() {
@@ -68,7 +68,7 @@
</el-select>
</el-form-item>
<el-form-item label="单据类型" prop="planType">
<el-select v-model="formData.planType" placeholder="请选择单据类型" style="width: 100%">
<el-select v-model="formData.planType" placeholder="请选择单据类型" clearable style="width: 100%">
<el-option label="直销单" value="direct" />
<el-option label="入库单" value="inbound" />
<el-option label="出库单" value="outbound" />
@@ -398,8 +398,7 @@ const formData = reactive({
const basicRules = {
planDate: [{ required: true, message: '请选择计划日期', trigger: 'change' }],
belongsCompany: [{ required: true, message: '请选择归属公司', trigger: 'change' }],
planType: [{ required: true, message: '请选择单据类型', trigger: 'change' }]
belongsCompany: [{ required: true, message: '请选择归属公司', trigger: 'change' }]
}
const productsRef = computed(() => formData.products)
@@ -561,7 +560,7 @@ function buildPlanCommonPayload(options?: { allowClearTransport?: boolean }): Pl
return {
planDate: formData.planDate,
belongsCompany: formData.belongsCompany,
planType: formData.planType,
planType: formData.planType || '',
contractNo: formData.contractNo,
supplierId: formData.supplierId || undefined,
supplierName: formData.supplierName || undefined,
@@ -33,6 +33,12 @@
<el-button class="btn-ghost" :loading="saveLoading" @click="handleSaveTemplate">
<el-icon><DocumentChecked /></el-icon>保存模板
</el-button>
<el-button class="btn-ghost" @click="toggleRedSeal">
<el-icon>
<component :is="showRedSeal ? Hide : Stamp" />
</el-icon>
{{ showRedSeal ? '隐藏红章' : '显示红章' }}
</el-button>
<el-button class="btn-ghost" @click="handlePrint">
<el-icon><Printer /></el-icon>打印
</el-button>
@@ -45,7 +51,7 @@
</template>
<script setup lang="ts">
import { Close, DocumentChecked, Download, Printer, View } from '@element-plus/icons-vue'
import { Close, DocumentChecked, Download, Hide, Printer, Stamp, View } from '@element-plus/icons-vue'
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
import { planApi, type Plan } from '@/api/pl'
@@ -53,6 +59,7 @@ import TinyMceEditor from '@/components/TinyMceEditor/index.vue'
import { useDictStore } from '@/store/modules/dict'
import { useUserStore } from '@/store/modules/user'
import {
buildSubpackSlipCompanySealHtml,
formatSubpackSlipDateIso,
generateSubpackSlipTemplate,
SUBPACK_SLIP_DOC_MAX_WIDTH,
@@ -63,11 +70,14 @@ import {
setupSubpackSlipEditorCheckboxes,
type SubpackSlipRenderContext
} from '@/utils/pl-subpack-slip-template'
import { injectSlipSealImages, stripSlipSealImages } from '@/utils/pl-slip-red-seal'
import { getPlSlipPdfCanvasScale } from '@/utils/pl-slip-pdf-render'
const visible = ref(false)
const slipContent = ref('')
const isPreviewMode = ref(false)
/** 打印弹窗内红章显隐(仅本次弹窗有效,打开时默认显示) */
const showRedSeal = ref(true)
const saveLoading = ref(false)
const pdfGenerating = ref(false)
const currentPlanId = ref('')
@@ -120,6 +130,7 @@ async function buildSlipRenderContext(plan: Plan): Promise<SubpackSlipRenderCont
async function open(planId: string) {
currentPlanId.value = planId
isPreviewMode.value = false
showRedSeal.value = true
try {
ElMessage.info({ message: '正在生成分装单...', duration: 800 })
const res = await planApi.get(planId)
@@ -144,6 +155,8 @@ async function open(planId: string) {
const renderCtx = await buildSlipRenderContext(plan)
slipContent.value = replaceSubpackSlipPlaceholders(htmlContent, plan, renderCtx)
// 新模板默认已去掉印章区;若历史模板仍含章,按内容同步按钮态
showRedSeal.value = /<img[^>]*alt=["']印章["'][^>]*>/i.test(slipContent.value)
visible.value = true
} catch (error) {
console.error('打开分装单打印失败', error)
@@ -157,6 +170,24 @@ function handleClosed() {
currentPlan.value = null
currentSubpackSlipNo.value = ''
isPreviewMode.value = false
showRedSeal.value = true
}
/** 切换红章显示/隐藏(同步影响编辑器、打印、PDF) */
function toggleRedSeal() {
if (showRedSeal.value) {
slipContent.value = stripSlipSealImages(slipContent.value)
showRedSeal.value = false
return
}
const sealHtml = buildSubpackSlipCompanySealHtml()
let next = injectSlipSealImages(slipContent.value, sealHtml, 'subpack-slip-seal-block')
// 新模板已去掉印章区时,回退到标题区(position:relative)右上角
if (!/<img[^>]*alt=["']印章["'][^>]*>/i.test(next) && next.includes('subpack-slip-title-section')) {
next = next.replace(/(<div class="subpack-slip-title-section"[^>]*>)/, `$1\n ${sealHtml}\n `)
}
slipContent.value = next
showRedSeal.value = /<img[^>]*alt=["']印章["'][^>]*>/i.test(next)
}
async function refreshPlan() {