|
|
@@ -8,9 +8,10 @@
|
|
|
<button class="mp-wv-header__back" type="button" @click="goBack">← 详情</button>
|
|
|
</div>
|
|
|
<h1>打印单据</h1>
|
|
|
+ <div class="mp-wv-header__sub">长按预览区可存图(WebView 不支持系统打印)</div>
|
|
|
</header>
|
|
|
|
|
|
- <p class="mp-print-hint">长按预览区可保存图片;WebView 不支持系统打印。</p>
|
|
|
+ <p class="mp-print-hint">WebView 不调用系统打印机,引导长按存图。</p>
|
|
|
|
|
|
<div class="mp-wv-chips">
|
|
|
<button
|
|
|
@@ -25,33 +26,50 @@
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
- <div v-if="kind === 'delivery' && customers.length > 1" class="mp-wv-toolbar">
|
|
|
- <el-select
|
|
|
- v-model="customerId"
|
|
|
- placeholder="选择送货客户"
|
|
|
- style="width: 100%"
|
|
|
- @change="reloadPreview"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="item in customers"
|
|
|
- :key="item.customerId"
|
|
|
- :label="item.customerName"
|
|
|
- :value="item.customerId"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
+ <div v-if="needCustomer" class="mp-wv-section" style="margin-top: 0">
|
|
|
+ <h3>送货客户</h3>
|
|
|
+ <button class="mp-wv-picker" type="button" @click="customerSheetOpen = true">
|
|
|
+ <span :class="{ 'is-ph': !customerLabel }">{{ customerLabel || '请选择送货客户' }}</span>
|
|
|
+ <span class="mp-wv-picker__chev">选择</span>
|
|
|
+ </button>
|
|
|
</div>
|
|
|
|
|
|
<div v-if="loading" class="mp-wv-empty">正在生成单据…</div>
|
|
|
<div v-else-if="blockReason" class="mp-wv-empty">{{ blockReason }}</div>
|
|
|
<div v-else class="mp-print-preview" v-html="html"></div>
|
|
|
+
|
|
|
+ <div class="mp-wv-fab-bar">
|
|
|
+ <button class="mp-wv-btn" type="button" @click="goBack">返回详情</button>
|
|
|
+ <button class="mp-wv-btn mp-wv-btn--primary" type="button" @click="hintSave">
|
|
|
+ 保存预览
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <MpBottomSheet v-model="customerSheetOpen" title="选择送货客户" searchable search-placeholder="搜索客户">
|
|
|
+ <template #default="{ keyword }">
|
|
|
+ <button
|
|
|
+ v-for="item in filteredCustomers(keyword)"
|
|
|
+ :key="item.customerId"
|
|
|
+ class="mp-wv-filter-opt"
|
|
|
+ type="button"
|
|
|
+ @click="pickCustomer(item)"
|
|
|
+ >
|
|
|
+ <span>{{ item.customerName }}</span>
|
|
|
+ <span v-if="item.customerId === customerId">✓</span>
|
|
|
+ </button>
|
|
|
+ <div v-if="!filteredCustomers(keyword).length" class="mp-wv-empty">无匹配客户</div>
|
|
|
+ </template>
|
|
|
+ </MpBottomSheet>
|
|
|
</template>
|
|
|
</MpWebviewShell>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { onMounted, ref } from 'vue'
|
|
|
+ import { computed, onMounted, ref } from 'vue'
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
+ import { ElMessage } from 'element-plus'
|
|
|
import MpWebviewShell from '@/layouts/MpWebviewShell.vue'
|
|
|
+ import MpBottomSheet from '@/components/mp/MpBottomSheet.vue'
|
|
|
import { planApi, type Plan } from '@/api/pl'
|
|
|
import { canBatchPrintSlip } from '@/utils/pl-batch-print'
|
|
|
import { listDeliveryPrintCustomers } from '@/utils/pl-delivery-slip-print'
|
|
|
@@ -80,6 +98,20 @@
|
|
|
const blockReason = ref('')
|
|
|
const customerId = ref('')
|
|
|
const customers = ref<{ customerId: string; customerName: string }[]>([])
|
|
|
+ const customerSheetOpen = ref(false)
|
|
|
+
|
|
|
+ const needCustomer = computed(
|
|
|
+ () => kind.value === 'delivery' || kind.value === 'blank-delivery'
|
|
|
+ )
|
|
|
+ const customerLabel = computed(
|
|
|
+ () => customers.value.find((c) => c.customerId === customerId.value)?.customerName || ''
|
|
|
+ )
|
|
|
+
|
|
|
+ function filteredCustomers(keyword: string) {
|
|
|
+ const kw = (keyword || '').trim().toLowerCase()
|
|
|
+ if (!kw) return customers.value
|
|
|
+ return customers.value.filter((c) => c.customerName.toLowerCase().includes(kw))
|
|
|
+ }
|
|
|
|
|
|
function goBack() {
|
|
|
if (window.history.length > 1) {
|
|
|
@@ -90,6 +122,10 @@
|
|
|
void router.replace(id ? `/m/pl/plan/${id}` : '/m/pl/plan')
|
|
|
}
|
|
|
|
|
|
+ function hintSave() {
|
|
|
+ ElMessage.info('请长按预览区保存图片')
|
|
|
+ }
|
|
|
+
|
|
|
function slipCommand(current: MpPlanPrintKind) {
|
|
|
if (current === 'inbound' || current === 'delivery' || current === 'subpack') return current
|
|
|
return null
|
|
|
@@ -97,6 +133,11 @@
|
|
|
|
|
|
async function reloadPreview() {
|
|
|
const current = kind.value
|
|
|
+ if (needCustomer.value && !customerId.value) {
|
|
|
+ html.value = ''
|
|
|
+ blockReason.value = '请先选择送货客户'
|
|
|
+ return
|
|
|
+ }
|
|
|
const command = slipCommand(current)
|
|
|
if (command && plan.value) {
|
|
|
const check = canBatchPrintSlip([plan.value], command)
|
|
|
@@ -125,6 +166,12 @@
|
|
|
void reloadPreview()
|
|
|
}
|
|
|
|
|
|
+ function pickCustomer(item: { customerId: string; customerName: string }) {
|
|
|
+ customerId.value = item.customerId
|
|
|
+ customerSheetOpen.value = false
|
|
|
+ void reloadPreview()
|
|
|
+ }
|
|
|
+
|
|
|
onMounted(async () => {
|
|
|
const id = String(route.params.id || '')
|
|
|
if (!id) {
|
|
|
@@ -146,3 +193,35 @@
|
|
|
}
|
|
|
})
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+ .mp-wv-header__sub {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: rgba(255, 255, 255, 0.9);
|
|
|
+ }
|
|
|
+
|
|
|
+ .mp-wv-picker {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ width: 100%;
|
|
|
+ height: 40px;
|
|
|
+ padding: 0 12px;
|
|
|
+ border: 1px solid #dcebe4;
|
|
|
+ border-radius: 8px;
|
|
|
+ background: #fff;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #1f2a26;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mp-wv-picker .is-ph {
|
|
|
+ color: #6b7b74;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mp-wv-picker__chev {
|
|
|
+ color: #0a9f6d;
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+</style>
|