Commit cc6f038d by wuqian

Merge branch 'dev' of 47.122.114.111:qinjianhui/factory_front into new-pod-cn

parents 852ad049 f08a0ccd
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"luxon": "^3.7.1", "luxon": "^3.7.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"qrcode": "^1.5.4",
"splitpanes": "^3.1.5", "splitpanes": "^3.1.5",
"vue": "^3.4.19", "vue": "^3.4.19",
"vue-dompurify-html": "^5.1.0", "vue-dompurify-html": "^5.1.0",
...@@ -30,6 +31,7 @@ ...@@ -30,6 +31,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/luxon": "^3.7.1", "@types/luxon": "^3.7.1",
"@types/qrcode": "^1.5.5",
"@types/splitpanes": "^2.2.6", "@types/splitpanes": "^2.2.6",
"@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1", "@typescript-eslint/parser": "^7.1.1",
......
...@@ -60,6 +60,12 @@ export function getFilePath() { ...@@ -60,6 +60,12 @@ export function getFilePath() {
import.meta.env.VITE_API_BASE_URL + import.meta.env.VITE_API_BASE_UPLOAD_URL import.meta.env.VITE_API_BASE_URL + import.meta.env.VITE_API_BASE_UPLOAD_URL
) )
} }
export function getFileCnPath() {
if (!/(http|https):\/\/([^/]+)/i.test(import.meta.env.BASE_URL)) {
return location.origin
}
return import.meta.env.VITE_API_BASE_URL
}
export function getWsUrl() { export function getWsUrl() {
if (location.protocol === 'https:') { if (location.protocol === 'https:') {
return 'wss://' + location.host return 'wss://' + location.host
...@@ -68,5 +74,6 @@ export function getWsUrl() { ...@@ -68,5 +74,6 @@ export function getWsUrl() {
} }
} }
export const filePath = getFilePath() export const filePath = getFilePath()
export const FileCnPath = getFileCnPath()
export default axios export default axios
...@@ -34,14 +34,14 @@ export function uploadFileApi(data: FormData) { ...@@ -34,14 +34,14 @@ export function uploadFileApi(data: FormData) {
) )
} }
// 获取物流面单 US // 打印物流面单 US
export function getLogisticUSApi(content: string) { export function getLogisticUSApi(content: string) {
return axios.get<never, BaseRespData<{ documentUrl: string }>>( return axios.get<never, BaseRespData<{ documentUrl: string }>>(
`factory/podJomallOrderUs/getDocument?content=${content}`, `factory/podJomallOrderUs/getDocument?content=${content}`,
) )
} }
// 获取物流面单 CN // 打印物流面单 CN
export function getLogisticCNApi(content: string) { export function getLogisticCNApi(content: string) {
return axios.get<never, BaseRespData<{ documentUrl: string }>>( return axios.get<never, BaseRespData<{ documentUrl: string }>>(
`factory/podJomallOrder/getDocument?content=${content}`, `factory/podJomallOrder/getDocument?content=${content}`,
......
...@@ -117,11 +117,11 @@ ...@@ -117,11 +117,11 @@
<img src="../assets/images/brush-no.png" width="24" height="24" /> <img src="../assets/images/brush-no.png" width="24" height="24" />
</div> </div>
<div <div
title="获取物流面单" title="打印物流面单"
class="tool-item" class="tool-item"
@click="getLogisticDrawer = true" @click="getLogisticDrawer = true"
> >
<img src="../assets/images/package.png" width="24" height="24" /> <img src="../assets/images/printer.png" width="24" height="24" />
</div> </div>
</div> </div>
</div> </div>
...@@ -206,17 +206,31 @@ ...@@ -206,17 +206,31 @@
</el-drawer> </el-drawer>
<el-drawer <el-drawer
v-model="getLogisticDrawer" v-model="getLogisticDrawer"
direction="btt"
class="get-logistic-drawer" class="get-logistic-drawer"
title="获取物流面单" title="打印物流面单"
@close="content = ''" @close="content = ''"
> >
<el-input v-model="content" placeholder="请输入单号" clearable /> <ElSelect
<template #footer> v-model="sheetPrinter"
<span style="display: flex; justify-content: center"> placeholder="请选择打印机"
<el-button @click="getLogisticDrawer = false"> 取 消 </el-button> @change="handlePrinterChange"
<el-button type="primary" @click="getLogistic">查 询</el-button> style="width: 200px; margin-right: 10px"
</span> >
</template> <ElOption
v-for="item in printDeviceList"
:key="item"
:label="item"
:value="item"
/>
</ElSelect>
<el-input
v-model="content"
placeholder="请输入单号"
style="width: 300px; margin-right: 10px"
clearable
/>
<el-button type="primary" @click="getLogistic">查 询</el-button>
</el-drawer> </el-drawer>
</span> </span>
</template> </template>
...@@ -240,11 +254,14 @@ import { ...@@ -240,11 +254,14 @@ import {
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import Menu from '@/router/menu' import Menu from '@/router/menu'
import userUserStore from '@/store/user' import userUserStore from '@/store/user'
import type { FormRules } from 'element-plus' import type { FormRules } from 'element-plus'
import { useValue } from '@/utils/hooks/useValue' import { useValue } from '@/utils/hooks/useValue'
import useLodop from '@/utils/hooks/useLodop'
import { changePasswordApi } from '@/api/auth' import { changePasswordApi } from '@/api/auth'
import { getLogisticUSApi, getLogisticCNApi } from '@/api/common' import { getLogisticUSApi, getLogisticCNApi } from '@/api/common'
import { filePath } from '@/api/axios' import { filePath, FileCnPath } from '@/api/axios'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
interface MenuItem { interface MenuItem {
index: string index: string
...@@ -272,6 +289,9 @@ const userInfo = userStore.user ...@@ -272,6 +289,9 @@ const userInfo = userStore.user
const dialogVisible = ref(false) const dialogVisible = ref(false)
const formatDrawer = ref(false) const formatDrawer = ref(false)
const getLogisticDrawer = ref(false) const getLogisticDrawer = ref(false)
const printDeviceList = ref<string[]>([])
const sheetPrinter = ref('')
const textareaT = ref('') const textareaT = ref('')
const newTextareaT = ref('') const newTextareaT = ref('')
const content = ref('') const content = ref('')
...@@ -504,7 +524,31 @@ const copy = () => { ...@@ -504,7 +524,31 @@ const copy = () => {
}) })
} }
// 获取物流面单 const { getCLodop } = useLodop()
const initPrintDevice = () => {
const lodop = getCLodop(null, null)
if (!lodop) return
const arr = []
// 获取打印机数量
const length = lodop.GET_PRINTER_COUNT()
for (let i = 0; i < length; i++) {
// 根据设备序号获取设备名
const name = lodop.GET_PRINTER_NAME(i)
arr.push(name)
}
// 获取默认打印机
sheetPrinter.value = lodop.GET_PRINTER_NAME(0)
printDeviceList.value = arr
}
// 处理打印机选择变化,保存到 localStorage
const handlePrinterChange = (value: string) => {
sheetPrinter.value = value
localStorage.setItem('sheetPrinter', JSON.stringify(value))
}
// 打印物流面单
const getLogistic = () => { const getLogistic = () => {
if (!content.value) { if (!content.value) {
ElMessage.warning('请输入单号') ElMessage.warning('请输入单号')
...@@ -530,7 +574,7 @@ const getLogistic = () => { ...@@ -530,7 +574,7 @@ const getLogistic = () => {
// 中国物流 // 中国物流
getLogisticCNApi(content.value).then((res) => { getLogisticCNApi(content.value).then((res) => {
if (res.code === 200) { if (res.code === 200) {
window.open(filePath + res.data.documentUrl, '_blank') window.open(FileCnPath + res.data.documentUrl, '_blank')
} }
}) })
} else { } else {
...@@ -547,6 +591,24 @@ watch( ...@@ -547,6 +591,24 @@ watch(
{ immediate: true }, { immediate: true },
) )
watch(getLogisticDrawer, async (value: boolean) => {
if (value) {
initPrintDevice()
const locaclPrinter = localStorage.getItem('sheetPrinter')
if (locaclPrinter) {
const savedPrinter = JSON.parse(locaclPrinter)
// 检查保存的打印机是否在当前打印机列表中
if (printDeviceList.value.includes(savedPrinter)) {
sheetPrinter.value = savedPrinter
} else {
// 如果保存的打印机不在当前列表中,清空 localStorage 并设置为空
localStorage.removeItem('sheetPrinter')
sheetPrinter.value = ''
}
}
}
})
// 点击标签时切换路由 // 点击标签时切换路由
watch(activeTab, (newTab) => { watch(activeTab, (newTab) => {
if (newTab) { if (newTab) {
...@@ -700,9 +762,11 @@ onUnmounted(() => { ...@@ -700,9 +762,11 @@ onUnmounted(() => {
top: calc(50% - 325px) !important; top: calc(50% - 325px) !important;
} }
::v-deep(.get-logistic-drawer.el-drawer.rtl) { ::v-deep(.get-logistic-drawer.el-drawer.btt) {
height: 200px !important; height: 120px !important;
top: calc(50% - 100px) !important; width: 700px !important;
top: calc(50% - 60px) !important;
left: calc(50% - 350px) !important;
} }
.tool-item { .tool-item {
......
...@@ -27,7 +27,7 @@ export interface OrderData { ...@@ -27,7 +27,7 @@ export interface OrderData {
printResult?: string printResult?: string
remark?: string remark?: string
version?: number version?: number
factoryOrderNumber?: number factoryOrderNumber?: number | string
} }
export interface ProductList { export interface ProductList {
......
...@@ -90,12 +90,26 @@ ...@@ -90,12 +90,26 @@
<p> <p>
{{ detail?.factorySubOrderNumber }} {{ detail?.factorySubOrderNumber }}
</p> </p>
<el-icon
v-if="detail?.factorySubOrderNumber"
class="icon"
@click="copy(detail?.factorySubOrderNumber || '')"
>
<DocumentCopy />
</el-icon>
</div> </div>
<div :title="detail?.thirdSubOrderNumber || ''" class="div-item"> <div :title="detail?.thirdSubOrderNumber || ''" class="div-item">
<span>第三方生产单号</span> <span>第三方生产单号</span>
<p> <p>
{{ detail?.thirdSubOrderNumber }} {{ detail?.thirdSubOrderNumber }}
</p> </p>
<el-icon
v-if="detail?.thirdSubOrderNumber"
class="icon"
@click="copy(detail?.thirdSubOrderNumber || '')"
>
<DocumentCopy />
</el-icon>
</div> </div>
<div :title="String(detail?.craftName)" class="div-item"> <div :title="String(detail?.craftName)" class="div-item">
<span>生产工艺</span> <span>生产工艺</span>
...@@ -125,6 +139,13 @@ ...@@ -125,6 +139,13 @@
<div :title="detail?.shopNumber ?? ''" class="div-item"> <div :title="detail?.shopNumber ?? ''" class="div-item">
<span>店铺单号</span> <span>店铺单号</span>
<p>{{ detail?.shopNumber ?? '' }}</p> <p>{{ detail?.shopNumber ?? '' }}</p>
<el-icon
v-if="detail?.shopNumber"
class="icon"
@click="copy(detail?.shopNumber || '')"
>
<DocumentCopy />
</el-icon>
</div> </div>
<div :title="detail?.createTime" class="div-item"> <div :title="detail?.createTime" class="div-item">
...@@ -203,6 +224,8 @@ import { ...@@ -203,6 +224,8 @@ import {
getSubOrderBySubOrderNumber, getSubOrderBySubOrderNumber,
downloadMaterialApi, downloadMaterialApi,
} from '@/api/podUsOrder' } from '@/api/podUsOrder'
import { DocumentCopy } from '@element-plus/icons-vue'
import { cardImages, PodOrderRes } from '@/types/api/podUsOrder' import { cardImages, PodOrderRes } from '@/types/api/podUsOrder'
import { showConfirm } from '@/utils/ui' import { showConfirm } from '@/utils/ui'
import { filePath } from '@/api/axios' import { filePath } from '@/api/axios'
...@@ -529,6 +552,28 @@ const trackCodeInput = async () => { ...@@ -529,6 +552,28 @@ const trackCodeInput = async () => {
removeFromHistory() removeFromHistory()
return ElMessage.error('生产单不存在') return ElMessage.error('生产单不存在')
} }
if (res.data.interceptStatus == 0 || res.data.interceptStatus == 2) {
try {
await ElMessageBox.confirm(
'该生产单已提交至拦截申请,请确认是否继续生产',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
},
)
} catch (error) {
TrackingNumber.value = ''
detail.value = {
id: -1,
podJomallOrderUsId: -1,
imgList: [],
}
trackingNumberRef.value && trackingNumberRef.value.focus()
return
}
}
const d = JSON.parse(JSON.stringify(res.data)) const d = JSON.parse(JSON.stringify(res.data))
if (d.note) { if (d.note) {
...@@ -559,6 +604,15 @@ const trackCodeInput = async () => { ...@@ -559,6 +604,15 @@ const trackCodeInput = async () => {
const onOpened = () => { const onOpened = () => {
trackingNumberRef.value && trackingNumberRef.value.focus() trackingNumberRef.value && trackingNumberRef.value.focus()
} }
const copy = (text: string) => {
try {
navigator.clipboard.writeText(text)
ElMessage.success('复制成功')
} catch (err) {
console.error('复制失败:', err)
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.sure-btn { .sure-btn {
......
<template>
<div>
<ElDialog
v-model="visible"
title="质检包装"
fullscreen
:close-on-click-modal="false"
:close-on-press-escape="false"
style="top: 60px"
center
modal-class="pod-make-order-dialog"
>
<div class="detail-div">
<div class="left">
<div class="left-images">
<div
class="imagBox"
v-for="(item, index) in detail?.imgList"
:key="index"
>
<div
v-show="item?.title && item?.url"
style="font-size: 30px; font-weight: 700; text-align: center"
>
{{ item?.title }}
</div>
<img :src="item.url" alt="" />
</div>
</div>
<div class="tips">
<div>第一次扫码:就绪</div>
<div>第二次扫码:完成</div>
<div>
单子为就绪状态,如果下一个单子状态为完成,则从就绪变为错误
</div>
</div>
</div>
<div class="right">
<div class="input">
<el-input
ref="trackingNumberRef"
v-model="TrackingNumber"
:placeholder="placeholderText"
style="margin-right: 10px"
clearable
@keydown.enter="trackCodeInput()"
></el-input>
<el-button type="primary" @click="trackCodeInput()">
查询
</el-button>
</div>
<div class="printerContent">
<div class="qr">
二维码:<span style="color: #ff0000">{{ 111 }}</span>
</div>
<el-form style="display: flex; gap: 10px">
<el-form-item label="打印机:" style="flex: 1">
<ElSelect
v-model="sheetPrinter"
placeholder="请选择打印机"
@change="handlePrinterChange"
>
<ElOption
v-for="item in printDeviceList"
:key="item"
:label="item"
:value="item"
/>
</ElSelect>
</el-form-item>
<el-form-item label="标签尺寸:" style="flex: 1">
<ElSelect
v-model="sheetPrinter"
placeholder="请选择标签尺寸"
@change="handlePrinterChange"
>
<ElOption
v-for="item in printDeviceList"
:key="item"
:label="item"
:value="item"
/>
</ElSelect>
</el-form-item>
</el-form>
<div class="canvas-container">
<canvas id="canvas" ref="canvas"></canvas>
</div>
</div>
<div class="printQueue">
<div style="font-size: 18px; font-weight: 700; margin-bottom: 10px">
打印队列
</div>
<ul>
<li
v-for="value in 10"
:key="value"
:style="{
color:
value == 1 ? `#006000` : value == 2 ? `#ff0000` : '#000',
}"
>
value
</li>
</ul>
</div>
</div>
</div></ElDialog
>
</div>
</template>
<script setup lang="ts">
import QRCode from 'qrcode'
const visible = ref(false)
const TrackingNumber = ref('')
const placeholderText = ref('扫描枪输入生产单号')
const sheetPrinter = ref('')
const printDeviceList = ref([])
const trackingNumberRef = ref()
const detail = ref({
imgList: [
{
title: 'A',
id: '',
url: 'https://pic3.zhimg.com/v2-e52354ffdbd94a8e0a7649eacd34a788_r.jpg?source=1940ef5c',
},
{
title: 'b',
id: '',
url: 'https://bpic.588ku.com/element_origin_min_pic/23/07/11/d32dabe266d10da8b21bd640a2e9b611.jpg!r650',
},
],
})
function trackCodeInput() {
QRCode.toCanvas(document.getElementById('canvas'), '11', function (error) {
if (error) console.error(error)
console.log('QR code generated!')
})
}
function handlePrinterChange() {}
function open() {
visible.value = true
}
defineExpose({ open })
</script>
<style scoped lang="scss">
.detail-div {
display: flex;
height: 100%;
gap: 20px;
justify-content: space-between;
.left {
flex: 5;
display: flex;
flex-direction: column;
align-items: center;
.left-images {
flex: 1;
display: flex;
height: 100%;
gap: 10px;
.imagBox {
width: 50%;
}
}
.tips {
font-size: 25px;
color: #afafaf;
}
}
.right {
flex: 3;
gap: 20px;
flex-direction: column;
display: flex;
.input {
display: flex;
}
.printerContent {
flex: 6;
border: 1px solid #dcdfe6;
padding: 10px;
padding-bottom: 0;
.qr {
margin-bottom: 10px;
}
}
.printQueue {
flex: 5;
border: 1px solid #dcdfe6;
padding: 10px;
}
}
}
:deep() {
.el-dialog {
.el-dialog__header {
.el-dialog__title {
font-size: 30px !important;
font-weight: 700 !important;
}
}
}
}
.el-form-item {
margin-bottom: 0;
}
.canvas-container {
position: relative;
width: 100%;
height: calc(100% - 61px); /* 1:1 宽高比 */
}
#canvas {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: auto !important;
height: 100% !important;
}
</style>
...@@ -72,10 +72,24 @@ ...@@ -72,10 +72,24 @@
<div class="basic-info-item"> <div class="basic-info-item">
<span>物流跟踪号:</span> <span>物流跟踪号:</span>
<span>{{ podOrderDetailsData?.trackingNumber }}</span> <span>{{ podOrderDetailsData?.trackingNumber }}</span>
<el-icon
v-if="podOrderDetailsData?.trackingNumber"
class="icon"
@click="copy(podOrderDetailsData?.trackingNumber || '')"
>
<DocumentCopy />
</el-icon>
</div> </div>
<div class="basic-info-item"> <div class="basic-info-item">
<span>店铺单号:</span> <span>店铺单号:</span>
<span>{{ podOrderDetailsData?.shopNumber }}</span> <span>{{ podOrderDetailsData?.shopNumber }}</span>
<el-icon
v-if="podOrderDetailsData?.shopNumber"
class="icon"
@click="copy(podOrderDetailsData?.shopNumber || '')"
>
<DocumentCopy />
</el-icon>
</div> </div>
<div class="basic-info-item"> <div class="basic-info-item">
<span>商品总数量:</span> <span>商品总数量:</span>
...@@ -100,6 +114,15 @@ ...@@ -100,6 +114,15 @@
<div class="basic-info-item"> <div class="basic-info-item">
<span>订单号:</span> <span>订单号:</span>
<span>{{ podOrderDetailsData?.factoryOrderNumber }}</span> <span>{{ podOrderDetailsData?.factoryOrderNumber }}</span>
<el-icon
v-if="podOrderDetailsData?.factoryOrderNumber"
class="icon"
@click="
copy((podOrderDetailsData.factoryOrderNumber as string) || '')
"
>
<DocumentCopy />
</el-icon>
</div> </div>
</div> </div>
...@@ -219,6 +242,8 @@ ...@@ -219,6 +242,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue' import { computed, nextTick, ref, watch } from 'vue'
import { DocumentCopy } from '@element-plus/icons-vue'
import useLodop from '@/utils/hooks/useLodop' import useLodop from '@/utils/hooks/useLodop'
import TableView from '@/components/TableView.vue' import TableView from '@/components/TableView.vue'
import type { WebSocketMessage } from '@/utils/websocket' import type { WebSocketMessage } from '@/utils/websocket'
...@@ -945,6 +970,15 @@ const handleWarehouseChange = (value: string | number) => { ...@@ -945,6 +970,15 @@ const handleWarehouseChange = (value: string | number) => {
_warehouseId.value = value _warehouseId.value = value
initOrderDetailBox() initOrderDetailBox()
} }
const copy = (text: string) => {
try {
navigator.clipboard.writeText(text)
ElMessage.success('复制成功')
} catch (err) {
console.error('复制失败:', err)
}
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment