Commit 6e1adba3 by qinjianhui

feat: 降低 index.vue 复杂度,抽取hooks

parent 5a438c3f
import { ElMessage } from 'element-plus' import useLodop from '@/utils/hooks/useLodop.ts'
import useLodop, { LODOPObject } from '@/utils/hooks/useLodop.ts' import { printWithLodop } from '@/utils/lodopPrinter'
const { getCLodop } = useLodop() const { getCLodop } = useLodop()
const lodopCall = async (fn: (lodop: LODOPObject) => string) => {
if (!window._lodop) {
window._lodop = getCLodop(null, null)
if (window._lodop) {
window._lodop.On_Return_Remain = true
window._lodop.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
window._lodopCallback = {}
window._lodop.On_Return = function (id, value) {
const cb = window._lodopCallback[id]
if (!cb) return
delete window._lodopCallback[id]
cb(value)
}
}
}
return new Promise((resolve) => {
let id
if (window._lodop) {
id = fn(window._lodop)
}
window._lodopCallback[id || 0] = resolve
})
}
function downloadPDF(url: string) {
if (!/^https?:/i.test(url)) return url
let xhr,
arrybuffer = false,
dataArray = null
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest()
} else {
xhr = new window.ActiveXObject('MSXML2.XMLHTTP')
}
xhr.open('GET', url, false) //同步方式
if (xhr.overrideMimeType)
try {
xhr.responseType = 'arraybuffer'
arrybuffer = true
} catch (err) {
xhr.overrideMimeType('text/plain; charset=x-user-defined')
}
xhr.send(null)
const data = xhr.response || xhr.responseBody
if (typeof Uint8Array !== 'undefined') {
if (arrybuffer) {
dataArray = new Uint8Array(data)
} else {
dataArray = new Uint8Array(data.length)
for (let i = 0; i < dataArray.length; i++) {
dataArray[i] = data.charCodeAt(i)
}
}
} else {
dataArray = window.VBS_BinaryToArray(data).toArray() //兼容IE低版本
}
const digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
let strData = ''
for (let i = 0, ii = dataArray.length; i < ii; i += 3) {
if (isNaN(dataArray[i])) break
const b1 = dataArray[i] & 0xff,
b2 = dataArray[i + 1] & 0xff,
b3 = dataArray[i + 2] & 0xff
const d1 = b1 >> 2,
d2 = ((b1 & 3) << 4) | (b2 >> 4)
const d3 = i + 1 < ii ? ((b2 & 0xf) << 2) | (b3 >> 6) : 64
const d4 = i + 2 < ii ? b3 & 0x3f : 64
strData +=
digits.substring(d1, d1 + 1) +
digits.substring(d2, d2 + 1) +
digits.substring(d3, d3 + 1) +
digits.substring(d4, d4 + 1)
}
return strData
}
export const print = async (url: string,printDevice:string) => { export const print = async (url: string,printDevice:string) => {
const lodop = getCLodop(null, null) //调用getLodop获取LODOP对象 await printWithLodop({
if (!lodop) return getCLodop: () => getCLodop(null, null),
lodop.PRINT_INIT('打印内容') printer: printDevice,
// SET_PRINTER_INDEX 指定打印设备 data: { filePath: url },
const setPrintRes = lodop.SET_PRINTER_INDEX(printDevice) callback: (_status: boolean) => {},
if (!setPrintRes) { baseUrl: '',
ElMessage.warning('设置面单打印机出错') })
return
}
lodop.ADD_PRINT_PDF(0, 0, '100%', '100%', downloadPDF(url))
console.log(lodop)
if (lodop.CVERSION) {
const startTime = Date.now()
const jobCode = await lodopCall((lodop: LODOPObject) => {
lodop.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
return lodop.PRINT()
})
console.log('[LODOP] job ' + jobCode)
// eslint-disable-next-line no-constant-condition
while (true) {
const ok = await lodopCall((lodop: LODOPObject) =>
lodop.GET_VALUE('PRINT_STATUS_OK', jobCode),
)
if (ok == 1) {
// 打印状态:成功
return
}
// 如果打印状态表示未成功或者返回了空,继续获取任务是否存在
const exist = await lodopCall((lodop: LODOPObject) =>
lodop.GET_VALUE('PRINT_STATUS_EXIST', jobCode),
)
console.log(
'[LODOP] PRINT_STATUS OK,EXIST',
jobCode,
ok,
exist,
`(${Date.now() - startTime}ms)`,
)
if (exist == 0) {
// 任务不存在了
return
}
await new Promise((r) => setTimeout(r, 500))
if (Date.now() - startTime >= 30000) {
ElMessage.error('打印超时(30秒)')
return
}
}
} else {
lodop.PRINT()
}
} }
import { ElMessage } from 'element-plus'
import type { LODOPObject } from '@/utils/hooks/useLodop'
type LodopGetter = () => LODOPObject | null
export function downloadPDF(url: string): string {
if (!/^https?:/i.test(url)) return url
const xhr = new XMLHttpRequest()
let arrayBuffer = false
xhr.open('GET', url, false)
if (xhr.overrideMimeType) {
try {
xhr.responseType = 'arraybuffer'
arrayBuffer = true
} catch {
xhr.overrideMimeType('text/plain; charset=x-user-defined')
}
}
xhr.send(null)
const data = (xhr.response ||
(xhr as unknown as { responseBody?: unknown }).responseBody) as
| ArrayBuffer
| string
let dataArray: Uint8Array
if (arrayBuffer) {
dataArray = new Uint8Array(data as ArrayBuffer)
} else {
const text = data as string
dataArray = new Uint8Array(text.length)
for (let i = 0; i < dataArray.length; i++) dataArray[i] = text.charCodeAt(i)
}
const digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
let strData = ''
for (let i = 0, ii = dataArray.length; i < ii; i += 3) {
const b1 = dataArray[i] & 0xff
const b2 = dataArray[i + 1] & 0xff
const b3 = dataArray[i + 2] & 0xff
const d1 = b1 >> 2
const d2 = ((b1 & 3) << 4) | (b2 >> 4)
const d3 = i + 1 < ii ? ((b2 & 0xf) << 2) | (b3 >> 6) : 64
const d4 = i + 2 < ii ? b3 & 0x3f : 64
strData +=
digits.charAt(d1) +
digits.charAt(d2) +
digits.charAt(d3) +
digits.charAt(d4)
}
return 'data:application/pdf;base64,' + strData
}
export function createLodopCaller(getCLodop: LodopGetter) {
let lodop: LODOPObject | null = null
let lodopCallback: { [key: string]: (value: string) => void } = {}
return (fn: (lodop: LODOPObject) => string) => {
if (!lodop) {
lodop = getCLodop()
if (!lodop) return Promise.resolve('')
lodop.On_Return_Remain = true
lodop.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
lodopCallback = {}
lodop.On_Return = (id, value) => {
const cb = lodopCallback[id]
if (!cb) return
delete lodopCallback[id]
cb(value)
}
}
return new Promise<string>((resolve) => {
if (!lodop) {
resolve('')
return
}
const id = fn(lodop)
lodopCallback[id] = resolve
})
}
}
interface PrintData {
filePath?: string
fileData?: string
}
interface PrintWithLodopOptions {
getCLodop: LodopGetter
printer: string
data: PrintData
callback?: (success: boolean) => void
timeout?: number
baseUrl?: string
}
export async function printWithLodop(options: PrintWithLodopOptions) {
const {
getCLodop,
printer,
data,
callback,
timeout = 30000,
baseUrl = '',
} = options
const lodop = getCLodop()
if (!lodop) return
const lodopCall = createLodopCaller(getCLodop)
lodop.PRINT_INIT('打印内容')
const printerIndex = lodop.SET_PRINTER_INDEX(printer)
if (!printerIndex) {
ElMessage.error('打印机设置失败')
callback?.(false)
return
}
if (data.filePath) {
const strURL = /^https?:/i.test(data.filePath)
? data.filePath
: baseUrl + data.filePath
lodop.ADD_PRINT_PDF(
0,
0,
'100%',
'100%',
/^https?:/i.test(strURL) ? downloadPDF(strURL) : strURL,
)
} else {
lodop.SEND_PRINT_RAWDATA(data.fileData || '')
}
if (lodop.CVERSION) {
const startTime = Date.now()
const jobCode = await lodopCall((instance) => {
instance.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
return instance.PRINT()
})
let pending = true
while (pending) {
const ok = await lodopCall((instance) =>
instance.GET_VALUE('PRINT_STATUS_OK', jobCode),
)
if (ok == '1' || ok == '1.0') {
callback?.(true)
return
}
const exist = await lodopCall((instance) =>
instance.GET_VALUE('PRINT_STATUS_EXIST', jobCode),
)
if (exist == '0' || exist == '0.0') {
callback?.(true)
return
}
await new Promise((r) => setTimeout(r, 500))
if (Date.now() - startTime >= timeout) {
ElMessage.error(`打印超时(${Math.floor(timeout / 1000)}秒)`)
callback?.(false)
pending = false
}
}
return
}
lodop.PRINT()
callback?.(false)
}
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import type { BaseRespData } from '@/types/api'
interface BatchActionOptions<T = unknown> {
getIds: () => (number | string)[]
api: (ids: (number | string)[]) => Promise<BaseRespData<T>>
confirmText?: string
successText?: string
refreshTree?: boolean
onSuccess?: (res: BaseRespData<T>) => void | Promise<void>
onAfter?: () => void | Promise<void>
}
interface UseOrderBatchActionsOptions {
getIds: () => (number | string)[]
refreshCurrentView: (options?: { isRefreshTree?: boolean }) => void | Promise<void>
}
export function useOrderBatchActions(options: UseOrderBatchActionsOptions) {
const { getIds, refreshCurrentView } = options
const ensureSelection = (msg = '请先选择订单'): boolean => {
const ids = getIds()
if (!ids.length) {
ElMessage.warning(msg)
return false
}
return true
}
const executeBatchAction = async <T = unknown>(action: BatchActionOptions<T>) => {
const ids = action.getIds()
if (!ids.length) {
ElMessage.warning('请先选择订单')
return
}
if (action.confirmText) {
try {
await ElMessageBox.confirm(action.confirmText, '提示', { type: 'warning' })
} catch {
return
}
}
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try {
const res = await action.api(ids)
if (res.code !== 200) return
if (action.successText) ElMessage.success(action.successText)
if (action.onSuccess) await action.onSuccess(res)
await refreshCurrentView({ isRefreshTree: !!action.refreshTree })
if (action.onAfter) await action.onAfter()
} catch (e) {
console.error(e)
} finally {
loading.close()
}
}
return {
ensureSelection,
executeBatchAction,
}
}
import { ref } from 'vue'
import { getListCraftApi, getCustomTagListCnApi, allErpCodeListApi } from '@/api/podCnOrder'
import { getUserMarkList, loadWarehouseListApi } from '@/api/common'
import { getAllCountryApi } from '@/api/logistics'
import type { ProductTypeGroup } from '../component/productTypeFilterTypes'
import type { IAllList } from '@/types/api/podUsOrder'
import type { CraftListData } from '@/types/api/podCnOrder'
import type { WarehouseListData } from '@/types'
interface LogisticsCodeItem {
code: string
basicsName: string
apiData: unknown
}
const processTypeMap: Record<string, string> = {
TH: '烫画',
ZP: '直喷',
CX: '刺绣',
DK: '雕刻',
BP: '白胚',
QT: '其他',
}
export function useOrderDictionaries() {
const userMarkList = ref<string[]>([])
const receiverCountryList = ref<{ countryCode: string; nameCn: string }[]>([])
const customTagList = ref<{ id: string; name: string }[]>([])
const allCodelist = ref<LogisticsCodeItem[]>([])
const craftList = ref<IAllList[]>([])
const warehouseList = ref<WarehouseListData[]>([])
const sourceList = [
{ name: 'erp推送', id: 'jomall-erp' },
{ name: '第三方推送', id: 'third-party' },
]
const sizes = ['FS', 'XS', 'S', 'M', 'L', 'XL', 'XXL', '3XL', '4XL', '5XL']
const productTypeGroups = ref<ProductTypeGroup[]>([
{
label: '普品',
value: 'NORMAL_ALL',
children: [{ label: '普品', value: 'NORMAL' }],
},
{
label: '胚衣',
value: 'GREIGE_ALL',
children: [{ label: '胚衣', value: 'GREIGE' }],
},
{
label: 'POD商品',
value: 'POD_ALL',
children: [
{ label: '单面', value: 'POD_SINGLE' },
{ label: '多面', value: 'POD_MULTI' },
],
},
{
label: '一件定制局部印',
value: 'CUSTOM_PART_ALL',
children: [
{ label: '单面', value: 'CUSTOM_PART_SINGLE' },
{ label: '多面', value: 'CUSTOM_PART_MULTI' },
],
},
])
const getUserMark = async () => {
try {
const res = await getUserMarkList()
userMarkList.value = res.data
} catch (_e) {
/* empty */
}
}
const getReceiverCountryList = async () => {
try {
const res = await getAllCountryApi()
if (res.code !== 200) return
receiverCountryList.value = res.data
} catch (_e) {
/* empty */
}
}
const getCustomTagList = async () => {
try {
const res = await getCustomTagListCnApi()
if (res.code !== 200) return
customTagList.value = res.data
} catch (_e) {
/* empty */
}
}
const getLogisticsCompanyAllCodelist = async () => {
try {
const res = await allErpCodeListApi()
if (res.code !== 200) return
allCodelist.value = res.data
} catch (_e) {
/* empty */
}
}
const loadCraftList = async () => {
try {
const res = await getListCraftApi()
if (res.code !== 200) return
const data: CraftListData[] = res.data
craftList.value = data.map((item) => ({
id: item.craftCode,
name: item.craftName,
warehouseName: processTypeMap[item.craftType] ?? '其他',
}))
} catch (_e) {
/* empty */
}
}
const loadWarehouseList = async () => {
try {
const res = await loadWarehouseListApi()
if (res.code !== 200) return
warehouseList.value = res.data
} catch (e) {
console.error(e)
}
}
const loadAllDictionaries = async () => {
await Promise.all([
loadCraftList(),
getUserMark(),
getCustomTagList(),
getLogisticsCompanyAllCodelist(),
getReceiverCountryList(),
loadWarehouseList(),
])
}
return {
userMarkList,
receiverCountryList,
customTagList,
allCodelist,
craftList,
warehouseList,
sourceList,
sizes,
productTypeGroups,
loadCraftList,
getUserMark,
getCustomTagList,
getLogisticsCompanyAllCodelist,
getReceiverCountryList,
loadWarehouseList,
loadAllDictionaries,
}
}
import { nextTick, ref, watch, type Ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
import usePageList from '@/utils/hooks/usePageList'
import {
getFactoryOrderNewDetailApi,
getFactoryOrderNewListApi,
getFactoryOrderNewLogApi,
getSuspendDetailApi,
getSuspendListApi,
getSuspendLogApi,
} from '@/api/factoryOrderNew'
import type {
FactoryOrderNewListData,
LogListData,
ProductListData,
operateOrderListData,
} from '@/types/api/order/factoryOrderNew'
interface UseOrderListAndDetailOptions {
status: Ref<string>
isCardLayout: Ref<boolean>
isTableLayout: Ref<boolean>
getQueryPayload: () => Record<string, unknown>
getListPageAcceptedSubStatus: () => number | undefined
}
export function useOrderListAndDetail(options: UseOrderListAndDetailOptions) {
const {
status,
isCardLayout,
isTableLayout,
getQueryPayload,
getListPageAcceptedSubStatus,
} = options
const subLoading = ref(false)
const activeTab = ref<'product' | 'log'>('product')
const productList = ref<ProductListData[]>([])
const logList = ref<LogListData[]>([])
const tableRef = ref()
const currentRow = ref<FactoryOrderNewListData | null>(null)
const selectedRowIds = ref<(number | string)[]>([])
const selectedRows = ref<FactoryOrderNewListData[]>([])
const cardSelectList = ref<operateOrderListData[]>([])
const {
loading,
currentPage,
pageSize,
total,
data: tableData,
onCurrentPageChange,
onPageSizeChange,
refresh: refreshTableList,
} = usePageList<FactoryOrderNewListData>({
query: (page, size) => {
if (status.value === 'SUSPEND') {
return getSuspendListApi(
getQueryPayload(),
page,
size,
status.value,
).then(async (res) => {
const records = Array.isArray(res.data?.records) ? res.data.records : []
await nextTick(() => {
tableRef.value.setCurrentRow(records[0])
currentRow.value = records[0] as never
})
return res.data
})
}
return getFactoryOrderNewListApi(
getQueryPayload(),
page,
size,
status.value === 'ALL' ? undefined : status.value,
getListPageAcceptedSubStatus(),
).then(async (res) => {
const records = res.data.records
await nextTick(() => {
tableRef.value.setCurrentRow(records[0])
currentRow.value = (records[0] as never) || null
})
return res.data
})
},
})
const getSelectedIds = (): (number | string)[] => {
if (isCardLayout.value) return cardSelectList.value.map((item) => item.id)
return selectedRowIds.value
}
const clearTableState = () => {
selectedRowIds.value = []
selectedRows.value = []
cardSelectList.value = []
productList.value = []
logList.value = []
currentRow.value = null
}
const handleMainSelectionChange = (rows: FactoryOrderNewListData[]) => {
selectedRowIds.value = rows.map((row) => row.id)
selectedRows.value = rows
}
const handleCardSelectionChange = (items: operateOrderListData[]) => {
cardSelectList.value = items
}
const getOrderDetailsById = async (tabName?: 'product' | 'log') => {
if (!currentRow.value) {
productList.value = []
logList.value = []
return
}
const id = currentRow.value.id
const isSuspend = status.value === 'SUSPEND'
const effectiveTab = tabName ?? activeTab.value
subLoading.value = true
try {
if (effectiveTab === 'product') {
productList.value = []
const productRes = isSuspend
? await getSuspendDetailApi(id)
: await getFactoryOrderNewDetailApi(id)
productList.value = Array.isArray(productRes.data) ? productRes.data : []
} else {
logList.value = []
const logRes = isSuspend
? await getSuspendLogApi(id)
: await getFactoryOrderNewLogApi(id)
logList.value = Array.isArray(logRes.data) ? logRes.data : []
}
} catch (e) {
console.error(e)
} finally {
subLoading.value = false
}
}
watch(currentRow, (row) => {
if (!row) {
productList.value = []
logList.value = []
return
}
if (!isTableLayout.value) return
void getOrderDetailsById()
})
const handleRowClick = (row: FactoryOrderNewListData) => {
const isSameRow = currentRow.value?.id === row.id
currentRow.value = row
if (isSameRow) {
getOrderDetailsById()
}
}
const handleTabClick = (tab: TabsPaneContext) => {
if (!currentRow.value) return
const name = tab?.props?.name as 'product' | 'log' | undefined
void getOrderDetailsById(name)
}
return {
subLoading,
activeTab,
productList,
logList,
tableRef,
currentRow,
selectedRowIds,
selectedRows,
cardSelectList,
loading,
currentPage,
pageSize,
total,
tableData,
onCurrentPageChange,
onPageSizeChange,
refreshTableList,
getSelectedIds,
clearTableState,
handleMainSelectionChange,
handleCardSelectionChange,
getOrderDetailsById,
handleRowClick,
handleTabClick,
}
}
import { ref } from 'vue'
import type { SearchForm } from '@/types/api/order/factoryOrderNew'
export function useOrderSearchForm(refreshCurrentView: () => void) {
const searchForm = ref<SearchForm>({})
const dateRange = ref<string[]>([])
const searchVisible = ref(false)
const pickerOptions = {
shortcuts: [
{
text: '今日',
value: () => {
const start = new Date()
start.setHours(0, 0, 0, 0)
const end = new Date()
end.setHours(23, 59, 59, 999)
return [start, end]
},
},
{
text: '最近7天',
value: () => {
const end = new Date()
end.setHours(23, 59, 59, 999)
const start = new Date()
start.setDate(start.getDate() - 6)
start.setHours(0, 0, 0, 0)
return [start, end]
},
},
{
text: '最近30天',
value: () => {
const end = new Date()
end.setHours(23, 59, 59, 999)
const start = new Date()
start.setDate(start.getDate() - 29)
start.setHours(0, 0, 0, 0)
return [start, end]
},
},
],
}
const toggleMulti = (val: boolean) => {
if (searchForm.value.multi === val) {
setTimeout(() => {
if (searchForm.value.multi === val) {
searchForm.value.multi = undefined
}
}, 0)
}
}
const changeReplaceShipment = () => {
searchForm.value.shipmentType = ''
}
const getQueryPayload = () => ({
...searchForm.value,
startTime: dateRange.value?.[0] || null,
endTime: dateRange.value?.[1] || null,
})
const reset = () => {
searchForm.value = {}
dateRange.value = []
refreshCurrentView()
}
return {
searchForm,
dateRange,
searchVisible,
pickerOptions,
toggleMulti,
changeReplaceShipment,
getQueryPayload,
reset,
}
}
import { computed, ref, nextTick } from 'vue'
import { getPodOrderAcceptedStatisticsApi, getPodOrderStateGroupListApi } from '@/api/factoryOrderNew'
import type { StatusTreeNode } from '@/types/api/order/factoryOrderNew'
interface UseOrderStatusTreeOptions {
getQueryPayload: () => Record<string, unknown>
currentPage: { value: number }
pageSize: { value: number }
onClearTableState: () => void
onRefreshCurrentView: () => void
}
export function useOrderStatusTree(options: UseOrderStatusTreeOptions) {
const { getQueryPayload, currentPage, pageSize, onClearTableState, onRefreshCurrentView } =
options
const cardLayoutStatuses = [
'PENDING_SCHEDULE',
'PENDING_PICK',
'PENDING_REPLENISH',
'IN_PRODUCTION',
'PENDING_PACKING',
]
const specialLayoutStatuses = ['BATCH_MANAGE', 'AWAITING_RESTOCK']
const statusTree = ref<StatusTreeNode[]>()
const status = ref<string>('PENDING_RECEIVE')
const pendingAcceptSubTab = ref<'PENDING_RECEIVE' | 'ACCEPT_FAIL_OUT_OF_STOCK'>(
'PENDING_RECEIVE',
)
const pendingAcceptCounts = ref<{
acceptedOutOfStockCount?: number
pendingCount?: number
totalCount?: number
}>({
pendingCount: 0,
acceptedOutOfStockCount: 0,
})
const suspendedTabs = [
{ label: '客户拦截', value: 'CUSTOMER_INTERCEPT', count: 0 },
{ label: '地址异常', value: 'ADDRESS_EXCEPTION', count: 0 },
{ label: '其他', value: 'OTHER', count: 0 },
]
const suspendedSubTab = ref('CUSTOMER_INTERCEPT')
const treeRef = ref()
const isCardLayout = computed(() => cardLayoutStatuses.includes(status.value))
const isSpecialLayout = computed(() => specialLayoutStatuses.includes(status.value))
const isTableLayout = computed(
() => !isCardLayout.value && !isSpecialLayout.value,
)
const getListPageAcceptedSubStatus = () =>
status.value === 'PENDING_RECEIVE'
? pendingAcceptSubTab.value === 'PENDING_RECEIVE'
? 0
: 2
: undefined
const getPendingReceiveCounts = async () => {
try {
const res = await getPodOrderAcceptedStatisticsApi(
getQueryPayload(),
currentPage.value,
pageSize.value,
status.value,
getListPageAcceptedSubStatus(),
)
if (res.code !== 200) return
pendingAcceptCounts.value = res.data || {
pendingCount: 0,
acceptedOutOfStockCount: 0,
}
} catch (e) {
console.error(e)
}
}
const loadStatusTreeCounts = async () => {
try {
const res = await getPodOrderStateGroupListApi()
statusTree.value = [
{ status: 'ALL', statusName: '全部', quantity: 0, children: res.data },
]
nextTick(() => {
treeRef.value?.setCurrentKey(status.value, true)
})
} catch (e) {
console.error(e)
}
}
const handleStatusNodeClick = (node: StatusTreeNode) => {
status.value = node.status
if (node.status !== 'PENDING_RECEIVE') {
pendingAcceptSubTab.value = 'PENDING_RECEIVE'
}
if (node.status !== 'SUSPEND') {
suspendedSubTab.value = 'CUSTOMER_INTERCEPT'
}
onClearTableState()
if (!isSpecialLayout.value) {
onRefreshCurrentView()
}
}
const handlePendingAcceptTabClick = (
tab: 'PENDING_RECEIVE' | 'ACCEPT_FAIL_OUT_OF_STOCK',
refreshTableList: () => void,
) => {
if (pendingAcceptSubTab.value === tab) return
pendingAcceptSubTab.value = tab
refreshTableList()
}
const toggleExpand = (node: { expanded?: boolean }) => {
node.expanded = !node.expanded
}
return {
cardLayoutStatuses,
specialLayoutStatuses,
statusTree,
status,
pendingAcceptSubTab,
pendingAcceptCounts,
suspendedTabs,
suspendedSubTab,
treeRef,
isCardLayout,
isSpecialLayout,
isTableLayout,
getListPageAcceptedSubStatus,
getPendingReceiveCounts,
loadStatusTreeCounts,
handleStatusNodeClick,
handlePendingAcceptTabClick,
toggleExpand,
}
}
...@@ -870,31 +870,17 @@ import { ...@@ -870,31 +870,17 @@ import {
CaretBottom, CaretBottom,
Edit, Edit,
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import { computed, onMounted, ref, watch } from 'vue' import { computed, onMounted, ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
import splitDiv from '@/components/splitDiv/splitDiv.vue' import splitDiv from '@/components/splitDiv/splitDiv.vue'
import TableView from '@/components/TableView.vue' import TableView from '@/components/TableView.vue'
import usePageList from '@/utils/hooks/usePageList'
import ResultInfo from '@/views/order/components/ResultInfo.vue' import ResultInfo from '@/views/order/components/ResultInfo.vue'
import type { BaseRespData } from '@/types/api' import type { BaseRespData } from '@/types/api'
import type { import type {
FactoryOrderNewListData, FactoryOrderNewListData,
LogListData,
operateOrderListData,
ProductListData, ProductListData,
SearchForm,
StatusTreeNode,
} from '@/types/api/order/factoryOrderNew' } from '@/types/api/order/factoryOrderNew'
import platformJson from '../../../json/platform.json' import platformJson from '../../../json/platform.json'
import { import {
getFactoryOrderNewDetailApi,
getFactoryOrderNewListApi,
getPodOrderAcceptedStatisticsApi,
getFactoryOrderNewLogApi,
getSuspendListApi,
getSuspendDetailApi,
getSuspendLogApi,
getPodOrderStateGroupListApi,
refreshProductInfoApi, refreshProductInfoApi,
transferOldFlowApi, transferOldFlowApi,
cancelSuspendApi, cancelSuspendApi,
...@@ -913,22 +899,12 @@ import { ...@@ -913,22 +899,12 @@ import {
completeDeliveryApi, completeDeliveryApi,
getByOperationNoLogApi, getByOperationNoLogApi,
} from '@/api/factoryOrderNew' } from '@/api/factoryOrderNew'
import {
getListCraftApi,
getCustomTagListCnApi,
allErpCodeListApi,
} from '@/api/podCnOrder'
import { getUserMarkList, loadWarehouseListApi } from '@/api/common'
import { getAllCountryApi } from '@/api/logistics'
import { filePath } from '@/api/axios' import { filePath } from '@/api/axios'
import { OrderData } from '@/types/api/podMakeOrder' import { OrderData } from '@/types/api/podMakeOrder'
import type { WarehouseListData } from '@/types' import useLodop from '@/utils/hooks/useLodop'
import useLodop, { LODOPObject } from '@/utils/hooks/useLodop' import { printWithLodop } from '@/utils/lodopPrinter'
import LogisticsWaySelect from '@/views/logistics/components/LogisticsWaySelect' import LogisticsWaySelect from '@/views/logistics/components/LogisticsWaySelect'
import { IAllList } from '@/types/api/podUsOrder'
import { CraftListData } from '@/types/api/podCnOrder'
import ProductTypeFilter from './component/ProductTypeFilter.vue' import ProductTypeFilter from './component/ProductTypeFilter.vue'
import type { ProductTypeGroup } from './component/productTypeFilterTypes'
import ConfirmOrderDialog from './component/ConfirmOrderDialog.vue' import ConfirmOrderDialog from './component/ConfirmOrderDialog.vue'
import CancelOrderDialog from './component/CancelOrderDialog.vue' import CancelOrderDialog from './component/CancelOrderDialog.vue'
import SuspendDialog from './component/SuspendDialog.vue' import SuspendDialog from './component/SuspendDialog.vue'
...@@ -945,218 +921,141 @@ import WeightDialog from '@/views/order/components/WeightDialog.vue' ...@@ -945,218 +921,141 @@ import WeightDialog from '@/views/order/components/WeightDialog.vue'
import FastProduction from '@/views/order/components/FastProduction.vue' import FastProduction from '@/views/order/components/FastProduction.vue'
import PodMakeOrder from '@/views/order/podUs/PodMakeOrder.vue' import PodMakeOrder from '@/views/order/podUs/PodMakeOrder.vue'
import { ResultInfoDataItem } from '@/types/api/order/common' import { ResultInfoDataItem } from '@/types/api/order/common'
import { useOrderDictionaries } from './hooks/useOrderDictionaries'
import { useOrderSearchForm } from './hooks/useOrderSearchForm'
import { useOrderStatusTree } from './hooks/useOrderStatusTree'
import { useOrderListAndDetail } from './hooks/useOrderListAndDetail'
import { useOrderBatchActions } from './hooks/useOrderBatchActions'
const cardLayoutStatuses = [
'PENDING_SCHEDULE',
'PENDING_PICK',
'PENDING_REPLENISH',
'IN_PRODUCTION',
'PENDING_PACKING',
]
const specialLayoutStatuses = ['BATCH_MANAGE', 'AWAITING_RESTOCK']
const subLoading = ref(false)
const isCardLayout = computed(() => cardLayoutStatuses.includes(status.value))
const isSpecialLayout = computed(() =>
specialLayoutStatuses.includes(status.value),
)
const isTableLayout = computed(
() => !isCardLayout.value && !isSpecialLayout.value,
)
const statusTree = ref<StatusTreeNode[]>()
const status = ref<string>('PENDING_RECEIVE')
const pendingAcceptSubTab = ref<'PENDING_RECEIVE' | 'ACCEPT_FAIL_OUT_OF_STOCK'>(
'PENDING_RECEIVE',
)
const pendingAcceptCounts = ref<{
acceptedOutOfStockCount?: number
pendingCount?: number
totalCount?: number
}>({
pendingCount: 0,
acceptedOutOfStockCount: 0,
})
const suspendedTabs = [
{ label: '客户拦截', value: 'CUSTOMER_INTERCEPT', count: 0 },
{ label: '地址异常', value: 'ADDRESS_EXCEPTION', count: 0 },
{ label: '其他', value: 'OTHER', count: 0 },
]
const suspendedSubTab = ref('CUSTOMER_INTERCEPT')
const resultInfo = ref<ResultInfoDataItem[]>([]) const resultInfo = ref<ResultInfoDataItem[]>([])
const resultRefs = ref() const resultRefs = ref()
const treeRef = ref()
const searchForm = ref<SearchForm>({})
const dateRange = ref<string[]>([])
const searchVisible = ref(false)
const userMarkList = ref<string[]>([]) const batchManageRef = ref<InstanceType<typeof BatchManageTable>>()
const receiverCountryList = ref<{ countryCode: string; nameCn: string }[]>([]) const waitingRestockRef = ref<InstanceType<typeof WaitingRestockTable>>()
const customTagList = ref<{ id: string; name: string }[]>([]) const cardLayoutRef = ref<InstanceType<typeof CardLayout>>()
interface LogisticsCodeItem {
code: string
basicsName: string
apiData: unknown
}
const allCodelist = ref<LogisticsCodeItem[]>([])
const sourceList = [ const {
{ name: 'erp推送', id: 'jomall-erp' }, userMarkList,
{ name: '第三方推送', id: 'third-party' }, receiverCountryList,
] customTagList,
const sizes = ['FS', 'XS', 'S', 'M', 'L', 'XL', 'XXL', '3XL', '4XL', '5XL'] allCodelist,
craftList,
warehouseList,
sourceList,
sizes,
productTypeGroups,
loadAllDictionaries,
} = useOrderDictionaries()
const refreshCurrentViewProxy = ref<() => void>(() => {})
const {
searchForm,
dateRange,
searchVisible,
pickerOptions,
toggleMulti,
changeReplaceShipment,
getQueryPayload,
reset,
} = useOrderSearchForm(() => refreshCurrentViewProxy.value())
const statusCurrentPageRef = ref(1)
const statusPageSizeRef = ref(50)
const {
cardLayoutStatuses,
statusTree,
status,
pendingAcceptSubTab,
pendingAcceptCounts,
suspendedTabs,
suspendedSubTab,
treeRef,
isCardLayout,
isSpecialLayout,
isTableLayout,
getListPageAcceptedSubStatus,
getPendingReceiveCounts,
loadStatusTreeCounts,
handlePendingAcceptTabClick: handlePendingAcceptTabClickRaw,
toggleExpand,
} = useOrderStatusTree({
getQueryPayload,
currentPage: statusCurrentPageRef,
pageSize: statusPageSizeRef,
onClearTableState: () => {},
onRefreshCurrentView: () => {},
})
const productTypeGroups = ref<ProductTypeGroup[]>([ const {
{ subLoading,
label: '普品', activeTab,
value: 'NORMAL_ALL', productList,
children: [{ label: '普品', value: 'NORMAL' }], logList,
}, tableRef,
{ selectedRows,
label: '胚衣', cardSelectList,
value: 'GREIGE_ALL', loading,
children: [{ label: '胚衣', value: 'GREIGE' }], currentPage,
}, pageSize,
{ total,
label: 'POD商品', tableData,
value: 'POD_ALL', onCurrentPageChange,
children: [ onPageSizeChange,
{ label: '单面', value: 'POD_SINGLE' }, refreshTableList,
{ label: '多面', value: 'POD_MULTI' }, getSelectedIds,
], clearTableState,
}, handleMainSelectionChange,
{ handleCardSelectionChange,
label: '一件定制局部印', getOrderDetailsById,
value: 'CUSTOM_PART_ALL', handleRowClick,
children: [ handleTabClick,
{ label: '单面', value: 'CUSTOM_PART_SINGLE' }, } = useOrderListAndDetail({
{ label: '多面', value: 'CUSTOM_PART_MULTI' }, status,
], isCardLayout,
}, isTableLayout,
]) getQueryPayload,
getListPageAcceptedSubStatus,
})
statusCurrentPageRef.value = currentPage.value
statusPageSizeRef.value = pageSize.value
const toggleMulti = (val: boolean) => { const refreshCurrentView = (options?: { isRefreshTree?: boolean }) => {
if (searchForm.value.multi === val) { if (options?.isRefreshTree) void loadStatusTreeCounts()
setTimeout(() => { if (isSpecialLayout.value) {
if (searchForm.value.multi === val) { if (status.value === 'BATCH_MANAGE') batchManageRef.value?.refresh()
searchForm.value.multi = undefined if (status.value === 'AWAITING_RESTOCK') waitingRestockRef.value?.refresh()
} return
}, 0)
} }
} if (isCardLayout.value) {
const changeReplaceShipment = () => { cardLayoutRef.value?.clearSelection()
searchForm.value.shipmentType = '' cardLayoutRef.value?.refresh(true)
} return
const getUserMark = async () => {
try {
const res = await getUserMarkList()
userMarkList.value = res.data
} catch (_e) {
/* empty */
} }
} if (status.value === 'PENDING_RECEIVE') {
statusCurrentPageRef.value = currentPage.value
const getReceiverCountryList = async () => { statusPageSizeRef.value = pageSize.value
try { void getPendingReceiveCounts()
const res = await getAllCountryApi()
if (res.code !== 200) return
receiverCountryList.value = res.data
} catch (_e) {
/* empty */
} }
refreshTableList()
} }
refreshCurrentViewProxy.value = () => refreshCurrentView()
const getCustomTagList = async () => { const handleStatusNodeClick = (node: { status: string }) => {
try { status.value = node.status
const res = await getCustomTagListCnApi() if (node.status !== 'PENDING_RECEIVE') {
if (res.code !== 200) return pendingAcceptSubTab.value = 'PENDING_RECEIVE'
customTagList.value = res.data
} catch (_e) {
/* empty */
} }
} if (node.status !== 'SUSPEND') {
suspendedSubTab.value = 'CUSTOMER_INTERCEPT'
const getLogisticsCompanyAllCodelist = async () => {
try {
const res = await allErpCodeListApi()
if (res.code !== 200) return
allCodelist.value = res.data
} catch (_e) {
/* empty */
} }
} clearTableState()
if (!isSpecialLayout.value) {
const processTypeMap: Record<string, string> = { refreshCurrentView()
TH: '烫画',
ZP: '直喷',
CX: '刺绣',
DK: '雕刻',
BP: '白胚',
QT: '其他',
}
const craftList = ref<IAllList[]>([])
const loadCraftList = async () => {
try {
const res = await getListCraftApi()
if (res.code !== 200) return
const data: CraftListData[] = res.data
craftList.value = data.map((item) => ({
id: item.craftCode,
name: item.craftName,
warehouseName: processTypeMap[item.craftType] ?? '其他',
}))
} catch (_e) {
/* empty */
} }
} }
const handlePendingAcceptTabClick = (
const pickerOptions = { tab: 'PENDING_RECEIVE' | 'ACCEPT_FAIL_OUT_OF_STOCK',
shortcuts: [ ) => handlePendingAcceptTabClickRaw(tab, refreshTableList)
{
text: '今日',
value: () => {
const start = new Date()
start.setHours(0, 0, 0, 0)
const end = new Date()
end.setHours(23, 59, 59, 999)
return [start, end]
},
},
{
text: '最近7天',
value: () => {
const end = new Date()
end.setHours(23, 59, 59, 999)
const start = new Date()
start.setDate(start.getDate() - 6)
start.setHours(0, 0, 0, 0)
return [start, end]
},
},
{
text: '最近30天',
value: () => {
const end = new Date()
end.setHours(23, 59, 59, 999)
const start = new Date()
start.setDate(start.getDate() - 29)
start.setHours(0, 0, 0, 0)
return [start, end]
},
},
],
}
const activeTab = ref<'product' | 'log'>('product')
const productList = ref<ProductListData[]>([])
const currentRow = ref<FactoryOrderNewListData | null>(null)
const selectedRowIds = ref<(number | string)[]>([])
// 主表格选中数据
const selectedRows = ref<FactoryOrderNewListData[]>([])
// 卡片布局选中数据
const cardSelectList = ref<operateOrderListData[]>([])
const logList = ref<LogListData[]>([])
const tableRef = ref()
const mainColumns = [ const mainColumns = [
{ {
prop: 'factoryOrderNumber', prop: 'factoryOrderNumber',
...@@ -1430,77 +1329,12 @@ const productColumns = computed(() => { ...@@ -1430,77 +1329,12 @@ const productColumns = computed(() => {
return baseProductColumns return baseProductColumns
}) })
const getQueryPayload = () => ({
...searchForm.value,
startTime: dateRange.value?.[0] || null,
endTime: dateRange.value?.[1] || null,
})
const getListPageAcceptedSubStatus = () =>
status.value === 'PENDING_RECEIVE'
? pendingAcceptSubTab.value === 'PENDING_RECEIVE'
? 0
: 2
: undefined
const {
loading,
currentPage,
pageSize,
total,
data: tableData,
onCurrentPageChange,
onPageSizeChange,
refresh: refreshTableList,
} = usePageList<FactoryOrderNewListData>({
query: (page, size) => {
if (status.value === 'SUSPEND') {
return getSuspendListApi(
getQueryPayload(),
page,
size,
status.value,
).then(async (res) => {
const records = Array.isArray(res.data?.records) ? res.data.records : []
await nextTick(() => {
tableRef.value.setCurrentRow(records[0])
currentRow.value = records[0] as never
})
return res.data
})
}
return getFactoryOrderNewListApi(
getQueryPayload(),
page,
size,
status.value === 'ALL' ? undefined : status.value,
getListPageAcceptedSubStatus(),
).then(async (res) => {
const records = res.data.records
await nextTick(() => {
tableRef.value.setCurrentRow(records[0])
currentRow.value = (records[0] as never) || null
})
return res.data
})
},
})
const reset = () => {
searchForm.value = {}
dateRange.value = []
refreshCurrentView()
}
const confirmOrderDialogRef = ref<InstanceType<typeof ConfirmOrderDialog>>() const confirmOrderDialogRef = ref<InstanceType<typeof ConfirmOrderDialog>>()
const cancelOrderDialogRef = ref<InstanceType<typeof CancelOrderDialog>>() const cancelOrderDialogRef = ref<InstanceType<typeof CancelOrderDialog>>()
const suspendDialogRef = ref<InstanceType<typeof SuspendDialog>>() const suspendDialogRef = ref<InstanceType<typeof SuspendDialog>>()
const pickCompleteDialogRef = ref<InstanceType<typeof PickCompleteDialog>>() const pickCompleteDialogRef = ref<InstanceType<typeof PickCompleteDialog>>()
const pickFailDialogRef = ref<InstanceType<typeof PickFailDialog>>() const pickFailDialogRef = ref<InstanceType<typeof PickFailDialog>>()
const operateDetailsDialogRef = ref() const operateDetailsDialogRef = ref()
const cardLayoutRef = ref<InstanceType<typeof CardLayout>>()
const batchManageRef = ref<InstanceType<typeof BatchManageTable>>()
const waitingRestockRef = ref<InstanceType<typeof WaitingRestockTable>>()
const arrangeDialogRef = ref<InstanceType<typeof ArrangeDialog>>() const arrangeDialogRef = ref<InstanceType<typeof ArrangeDialog>>()
const createLogisticDialogRef = ref() const createLogisticDialogRef = ref()
const updateCustomsDialogVisible = ref(false) const updateCustomsDialogVisible = ref(false)
...@@ -1508,136 +1342,10 @@ const weightDialogRef = ref() ...@@ -1508,136 +1342,10 @@ const weightDialogRef = ref()
const detailVisible = ref(false) const detailVisible = ref(false)
const fastKey = ref('') const fastKey = ref('')
const detailData = ref<Record<string, unknown>>({}) const detailData = ref<Record<string, unknown>>({})
const getSelectedIds = (): (number | string)[] => { const { ensureSelection, executeBatchAction } = useOrderBatchActions({
if (isCardLayout.value) return cardSelectList.value.map((item) => item.id) getIds: getSelectedIds,
return selectedRowIds.value refreshCurrentView,
}
const ensureSelection = (msg = '请先选择订单'): boolean => {
const ids = getSelectedIds()
if (!ids.length) {
ElMessage.warning(msg)
return false
}
return true
}
const refreshCurrentView = (options?: { isRefreshTree?: boolean }) => {
if (options?.isRefreshTree) void loadStatusTreeCounts()
if (isSpecialLayout.value) {
if (status.value === 'BATCH_MANAGE') batchManageRef.value?.refresh()
if (status.value === 'AWAITING_RESTOCK') waitingRestockRef.value?.refresh()
return
}
if (isCardLayout.value) {
cardLayoutRef.value?.clearSelection()
cardLayoutRef.value?.refresh(true)
return
}
if (status.value === 'PENDING_RECEIVE') {
getPendingReceiveCounts()
}
refreshTableList()
}
const handleStatusNodeClick = (node: StatusTreeNode) => {
status.value = node.status
if (node.status !== 'PENDING_RECEIVE') {
pendingAcceptSubTab.value = 'PENDING_RECEIVE'
}
if (node.status !== 'SUSPEND') {
suspendedSubTab.value = 'CUSTOMER_INTERCEPT'
}
selectedRowIds.value = []
selectedRows.value = []
cardSelectList.value = []
productList.value = []
logList.value = []
currentRow.value = null
if (!isSpecialLayout.value) {
refreshCurrentView()
}
}
const handlePendingAcceptTabClick = (
tab: 'PENDING_RECEIVE' | 'ACCEPT_FAIL_OUT_OF_STOCK',
) => {
if (pendingAcceptSubTab.value === tab) return
pendingAcceptSubTab.value = tab
refreshTableList()
}
const toggleExpand = (node: { expanded?: boolean }) => {
node.expanded = !node.expanded
}
const loadStatusTreeCounts = async () => {
try {
const res = await getPodOrderStateGroupListApi()
statusTree.value = [
{ status: 'ALL', statusName: '全部', quantity: 0, children: res.data },
]
nextTick(() => {
treeRef.value?.setCurrentKey(status.value, true)
})
} catch (e) {
console.error(e)
}
}
const handleMainSelectionChange = (rows: FactoryOrderNewListData[]) => {
selectedRowIds.value = rows.map((row) => row.id)
selectedRows.value = rows
}
const handleCardSelectionChange = (items: operateOrderListData[]) => {
cardSelectList.value = items
}
const getOrderDetailsById = async (tabName?: 'product' | 'log') => {
if (!currentRow.value) {
productList.value = []
logList.value = []
return
}
const id = currentRow.value.id
const isSuspend = status.value === 'SUSPEND'
const effectiveTab = tabName ?? activeTab.value
subLoading.value = true
try {
if (effectiveTab === 'product') {
productList.value = []
const productRes = isSuspend
? await getSuspendDetailApi(id)
: await getFactoryOrderNewDetailApi(id)
productList.value = Array.isArray(productRes.data) ? productRes.data : []
} else {
logList.value = []
const logRes = isSuspend
? await getSuspendLogApi(id)
: await getFactoryOrderNewLogApi(id)
logList.value = Array.isArray(logRes.data) ? logRes.data : []
}
} catch (e) {
console.error(e)
} finally {
subLoading.value = false
}
}
watch(currentRow, (row) => {
if (!row) {
productList.value = []
logList.value = []
return
}
if (!isTableLayout.value) return
void getOrderDetailsById()
}) })
const handleRowClick = (row: FactoryOrderNewListData) => {
const isSameRow = currentRow.value?.id === row.id
currentRow.value = row
if (isSameRow) {
getOrderDetailsById()
return
}
}
const handleTabClick = (tab: TabsPaneContext) => {
if (!currentRow.value) return
const name = tab?.props?.name as 'product' | 'log' | undefined
void getOrderDetailsById(name)
}
const handleEditRemark = async (row: ProductListData) => { const handleEditRemark = async (row: ProductListData) => {
try { try {
...@@ -1684,38 +1392,22 @@ const handleCancelOrder = () => { ...@@ -1684,38 +1392,22 @@ const handleCancelOrder = () => {
if (!ensureSelection()) return if (!ensureSelection()) return
cancelOrderDialogRef.value?.open(getSelectedIds()) cancelOrderDialogRef.value?.open(getSelectedIds())
} }
const handleRefreshProductInfo = async () => { const handleRefreshProductInfo = async () =>
if (!ensureSelection()) return executeBatchAction({
try { getIds: getSelectedIds,
await ElMessageBox.confirm('确定刷新商品信息吗?', '提示', { api: refreshProductInfoApi,
type: 'warning', confirmText: '确定刷新商品信息吗?',
}) successText: '刷新商品信息成功',
} catch {
return
}
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
}) })
try {
const res = await refreshProductInfoApi(getSelectedIds())
if (res.code !== 200) return
ElMessage.success('刷新商品信息成功')
refreshCurrentView()
} catch (e) {
console.error(e)
} finally {
loading.close()
}
}
const handleTransferOldFlow = async () => { const handleTransferOldFlow = async () => {
if (!ensureSelection()) return
await ElMessageBox.confirm('确定转旧流程吗?', '提示', { type: 'warning' })
try { try {
await transferOldFlowApi(getSelectedIds()) await executeBatchAction({
ElMessage.success('转旧流程成功') getIds: getSelectedIds,
refreshCurrentView({ isRefreshTree: true }) api: transferOldFlowApi,
confirmText: '确定转旧流程吗?',
successText: '转旧流程成功',
refreshTree: true,
})
} catch (e: unknown) { } catch (e: unknown) {
ElMessage.error((e as Error)?.message || '转旧流程失败') ElMessage.error((e as Error)?.message || '转旧流程失败')
} }
...@@ -1800,16 +1492,6 @@ const handleSingleConfirmOrder = (row: FactoryOrderNewListData) => { ...@@ -1800,16 +1492,6 @@ const handleSingleConfirmOrder = (row: FactoryOrderNewListData) => {
confirmOrderDialogRef.value?.open([row.id]) confirmOrderDialogRef.value?.open([row.id])
} }
const podOrderVisible = ref(false) const podOrderVisible = ref(false)
const warehouseList = ref<WarehouseListData[]>([])
const loadWarehouseList = async () => {
try {
const res = await loadWarehouseListApi()
if (res.code !== 200) return
warehouseList.value = res.data
} catch (e) {
console.error(e)
}
}
const sheetPrinter = ref('') const sheetPrinter = ref('')
const handlePrinterChange = (value: string) => { const handlePrinterChange = (value: string) => {
sheetPrinter.value = value sheetPrinter.value = value
...@@ -1830,129 +1512,14 @@ const printOrder = async ( ...@@ -1830,129 +1512,14 @@ const printOrder = async (
data: OrderData, data: OrderData,
callback: (status: boolean) => void, callback: (status: boolean) => void,
) => { ) => {
const lodop = getCLodop(null, null) await printWithLodop({
if (!lodop) return getCLodop: () => getCLodop(null, null),
lodop.PRINT_INIT('打印内容') printer: sheetPrinter.value,
const printerIndex = lodop.SET_PRINTER_INDEX(sheetPrinter.value) data,
if (!printerIndex) { callback,
ElMessage.error('打印机设置失败') baseUrl: filePath,
callback(false)
return
}
if (data.filePath) {
const strURL = filePath + data.filePath
lodop.ADD_PRINT_PDF(
0,
0,
'100%',
'100%',
/(https):\/\/([^/]+)/i.test(strURL) ? downloadPDF(strURL) : strURL,
)
} else {
lodop.SEND_PRINT_RAWDATA(data.fileData || '')
}
if (lodop.CVERSION) {
const startTime = Date.now()
const jobCode = await lodopCall((lodop) => {
lodop.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
return lodop.PRINT()
})
// eslint-disable-next-line no-constant-condition
while (true) {
const ok = await lodopCall((lodop) =>
lodop.GET_VALUE('PRINT_STATUS_OK', jobCode),
)
if (ok == '1') {
callback(true)
return
}
const exist = await lodopCall((lodop) =>
lodop.GET_VALUE('PRINT_STATUS_EXIST', jobCode),
)
if (exist == '0') {
callback(true)
return
}
await new Promise((r) => setTimeout(r, 500))
if (Date.now() - startTime >= 30000) {
ElMessage.error('打印超时(30秒)')
callback(false)
return
}
}
} else {
lodop.PRINT()
callback(false)
}
}
let _lodop: LODOPObject | null = null
let _lodopCallback: { [key: string]: (value: string) => void } = {}
const lodopCall = (fn: (lodop: LODOPObject) => string) => {
if (!_lodop) {
_lodop = getCLodop(null, null)
if (!_lodop) return
_lodop.On_Return_Remain = true
_lodop.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
_lodopCallback = {}
_lodop.On_Return = (id, value) => {
const cb = _lodopCallback[id]
if (!cb) return
delete _lodopCallback[id]
cb(value)
}
}
return new Promise((resolve) => {
if (!_lodop) return
const id = fn(_lodop)
_lodopCallback[id] = resolve
}) })
} }
const downloadPDF = (url: string) => {
if (!/^https?:/i.test(url)) return url
const xhr = new XMLHttpRequest()
let arrybuffer = false
xhr.open('GET', url, false)
if (xhr.overrideMimeType) {
try {
xhr.responseType = 'arraybuffer'
arrybuffer = true
} catch {
xhr.overrideMimeType('text/plain; charset=x-user-defined')
}
}
xhr.send(null)
const data = (xhr.response ||
(xhr as unknown as { responseBody?: unknown }).responseBody) as
| ArrayBuffer
| string
let dataArray: Uint8Array
if (arrybuffer) {
dataArray = new Uint8Array(data as ArrayBuffer)
} else {
const text = data as string
dataArray = new Uint8Array(text.length)
for (let i = 0; i < dataArray.length; i++) dataArray[i] = text.charCodeAt(i)
}
const digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
let strData = ''
for (let i = 0, ii = dataArray.length; i < ii; i += 3) {
const b1 = dataArray[i] & 0xff
const b2 = dataArray[i + 1] & 0xff
const b3 = dataArray[i + 2] & 0xff
const d1 = b1 >> 2
const d2 = ((b1 & 3) << 4) | (b2 >> 4)
const d3 = i + 1 < ii ? ((b2 & 0xf) << 2) | (b3 >> 6) : 64
const d4 = i + 2 < ii ? b3 & 0x3f : 64
strData +=
digits.charAt(d1) +
digits.charAt(d2) +
digits.charAt(d3) +
digits.charAt(d4)
}
return 'data:application/pdf;base64,' + strData
}
const handleDownloadMaterial = async () => { const handleDownloadMaterial = async () => {
if (!ensureSelection()) return if (!ensureSelection()) return
const usePodOrderDownloadStatuses = ['PENDING_DELIVERY', 'SUSPEND'] const usePodOrderDownloadStatuses = ['PENDING_DELIVERY', 'SUSPEND']
...@@ -2034,22 +1601,11 @@ const handlePrintProductionOrder = async () => { ...@@ -2034,22 +1601,11 @@ const handlePrintProductionOrder = async () => {
} }
} }
const handlePrintPickOrder = async () => { const handlePrintPickOrder = async () => {
if (!ensureSelection()) return await executeBatchAction({
const ids = getSelectedIds() getIds: getSelectedIds,
const loading = ElLoading.service({ api: printPickOrderApi,
fullscreen: true, successText: '打印拣胚单成功',
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
}) })
try {
await printPickOrderApi(ids)
ElMessage.success('打印拣胚单成功')
refreshCurrentView()
} catch (e: unknown) {
console.error(e)
} finally {
loading.close()
}
} }
const handlePickComplete = () => { const handlePickComplete = () => {
if (!ensureSelection()) return if (!ensureSelection()) return
...@@ -2060,108 +1616,59 @@ const handlePickFail = () => { ...@@ -2060,108 +1616,59 @@ const handlePickFail = () => {
pickFailDialogRef.value?.open(getSelectedIds()) pickFailDialogRef.value?.open(getSelectedIds())
} }
const handleApplyReplenish = async () => { const handleApplyReplenish = async () => {
if (!ensureSelection()) return await executeBatchAction({
await ElMessageBox.confirm('确定申请补胚吗?', '提示', { type: 'warning' }) getIds: getSelectedIds,
const loading = ElLoading.service({ api: applyReplenishApi,
fullscreen: true, confirmText: '确定申请补胚吗?',
text: '操作中...', successText: '申请补胚成功',
background: 'rgba(0, 0, 0, 0.3)', refreshTree: true,
}) })
try {
const res = await applyReplenishApi(getSelectedIds())
if (res.code !== 200) return
ElMessage.success('申请补胚成功')
refreshCurrentView({ isRefreshTree: true })
} catch (e) {
console.error(e)
} finally {
loading.close()
}
} }
const handleProductionComplete = async () => { const handleProductionComplete = async () => {
if (!ensureSelection()) return await executeBatchAction({
await ElMessageBox.confirm('确定生产完成吗?', '提示', { type: 'warning' }) getIds: getSelectedIds,
const loading = ElLoading.service({ api: completeDeliveryApi,
fullscreen: true, confirmText: '确定生产完成吗?',
text: '操作中...', refreshTree: true,
background: 'rgba(0, 0, 0, 0.3)', onSuccess: (res) => {
const data = Array.isArray(res.data) ? (res.data as ResultInfoDataItem[]) : []
const hasFailed = data.some((item) => !item.status)
if (hasFailed) {
resultInfo.value = data.filter((item) => !item.status)
resultRefs.value?.showDialog()
}
},
}) })
try {
const res = await completeDeliveryApi(getSelectedIds())
if (res.code !== 200) return
const status = res.data.some((item) => !item.status)
if (status) {
resultInfo.value = res.data.filter((item) => !item.status)
resultRefs.value?.showDialog()
} else {
refreshCurrentView({ isRefreshTree: true })
}
} catch (e) {
console.error(e)
} finally {
loading.close()
}
} }
const handleWeightSort = () => { const handleWeightSort = () => {
weightDialogRef.value?.open() weightDialogRef.value?.open()
} }
const handleArchiveOrder = async () => { const handleArchiveOrder = async () => {
if (!ensureSelection()) return await executeBatchAction({
await ElMessageBox.confirm('确定订单归档吗?', '提示', { type: 'warning' }) getIds: getSelectedIds,
const loading = ElLoading.service({ api: archiveOrderApi,
fullscreen: true, confirmText: '确定订单归档吗?',
text: '操作中...', successText: '订单归档成功',
background: 'rgba(0, 0, 0, 0.3)', refreshTree: true,
}) })
try {
await archiveOrderApi(getSelectedIds())
ElMessage.success('订单归档成功')
refreshCurrentView({ isRefreshTree: true })
} catch (e) {
console.error(e)
} finally {
loading.close()
}
} }
const handleCancelSuspend = async () => { const handleCancelSuspend = async () => {
if (!ensureSelection()) return await executeBatchAction({
try { getIds: getSelectedIds,
await ElMessageBox.confirm('确定取消挂起吗?', '提示', { type: 'warning' }) api: cancelSuspendApi,
} catch { confirmText: '确定取消挂起吗?',
return successText: '取消挂起成功',
} refreshTree: true,
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
}) })
try {
await cancelSuspendApi(getSelectedIds())
ElMessage.success('取消挂起成功')
refreshCurrentView({ isRefreshTree: true })
} catch (e) {
console.error(e)
} finally {
loading.close()
}
} }
const handleSyncAddress = async () => { const handleSyncAddress = async () => {
if (!ensureSelection()) return await executeBatchAction({
await ElMessageBox.confirm('确定同步收货地址吗?', '提示', { type: 'warning' }) getIds: getSelectedIds,
const loading = ElLoading.service({ api: (ids) => syncReceiverAddress(ids as number[]),
fullscreen: true, confirmText: '确定同步收货地址吗?',
text: '操作中...', successText: '同步收货地址成功',
background: 'rgba(0, 0, 0, 0.3)', refreshTree: true,
}) })
try {
await syncReceiverAddress(getSelectedIds() as number[])
ElMessage.success('同步收货地址成功')
refreshCurrentView({ isRefreshTree: true })
} catch (e) {
console.error(e)
} finally {
loading.close()
}
} }
const handleReplenishComplete = () => { const handleReplenishComplete = () => {
if (!ensureSelection()) return if (!ensureSelection()) return
...@@ -2200,53 +1707,20 @@ const handleSinglePrint = () => { ...@@ -2200,53 +1707,20 @@ const handleSinglePrint = () => {
ElMessage.info('单件打单功能待集成') ElMessage.info('单件打单功能待集成')
} }
const handleGetTrackingNumber = async () => { const handleGetTrackingNumber = async () => {
if (!ensureSelection()) return await executeBatchAction({
await ElMessageBox.confirm('确定获取跟踪号吗?', '提示', { type: 'warning' }) getIds: getSelectedIds,
const loading = ElLoading.service({ api: (ids) => getTrackingNumberApi(ids as number[]),
fullscreen: true, confirmText: '确定获取跟踪号吗?',
text: '操作中...', successText: '获取跟踪号成功',
background: 'rgba(0, 0, 0, 0.3)',
}) })
try {
await getTrackingNumberApi(getSelectedIds() as number[])
ElMessage.success('获取跟踪号成功')
refreshCurrentView()
} catch (e) {
console.error(e)
} finally {
loading.close()
}
} }
const handleStatusPush = () => { const handleStatusPush = () => {
if (!ensureSelection()) return if (!ensureSelection()) return
ElMessage.info('状态推送功能待集成') ElMessage.info('状态推送功能待集成')
} }
const getPendingReceiveCounts = async () => {
try {
const res = await getPodOrderAcceptedStatisticsApi(
getQueryPayload(),
currentPage.value,
pageSize.value,
status.value,
getListPageAcceptedSubStatus(),
)
if (res.code !== 200) return
pendingAcceptCounts.value = res.data || {
pendingCount: 0,
acceptedOutOfStockCount: 0,
}
} catch (e) {
console.error(e)
}
}
onMounted(() => { onMounted(() => {
loadStatusTreeCounts() loadStatusTreeCounts()
loadCraftList() loadAllDictionaries()
getUserMark()
getCustomTagList()
getLogisticsCompanyAllCodelist()
getReceiverCountryList()
loadWarehouseList()
if (status.value === 'PENDING_RECEIVE') { if (status.value === 'PENDING_RECEIVE') {
getPendingReceiveCounts() getPendingReceiveCounts()
} }
......
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