Commit 95aa07a3 by qinjianhui

Merge branch 'dev' into 'master'

Dev

See merge request !96
parents 283e4e3c e8b276ce
...@@ -54,6 +54,7 @@ declare module 'vue' { ...@@ -54,6 +54,7 @@ declare module 'vue' {
ElTag: typeof import('element-plus/es')['ElTag'] ElTag: typeof import('element-plus/es')['ElTag']
ElTimeline: typeof import('element-plus/es')['ElTimeline'] ElTimeline: typeof import('element-plus/es')['ElTimeline']
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem'] ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTree: typeof import('element-plus/es')['ElTree'] ElTree: typeof import('element-plus/es')['ElTree']
ElUpload: typeof import('element-plus/es')['ElUpload'] ElUpload: typeof import('element-plus/es')['ElUpload']
......
...@@ -626,3 +626,11 @@ export function getCustomTagListApi() { ...@@ -626,3 +626,11 @@ export function getCustomTagListApi() {
`factory/podJomallOrderUs/getCustomTagList`, `factory/podJomallOrderUs/getCustomTagList`,
) )
} }
// 普货拣货
export function printNormalPickPdfApi(ids: string) {
return axios.get<never, BaseRespData<string>>(
'factory/podJomallOrderUs/printNormalPickPdf',
{ params: { ids } },
)
}
import axios from '@/api/axios.ts'
import { BasePaginationData, BaseRespData } from '@/types/api'
// 新增规则
interface BaseForm {
id?: number
}
type ParamKey = `param${number}`
type ParamValue = string | number | boolean | null | undefined
type PostData = BaseForm & Record<ParamKey, ParamValue>
export function usArrangeRuleApi(data: PostData) {
return axios.post<never, BasePaginationData<never>>(
'factory/podJomallOrderUs/usArrangeRule',
data,
)
}
// 编辑规则
export function updateRuleByIdApi(data: PostData) {
return axios.post<never, BasePaginationData<never>>(
'factory/podJomallOrderUsArrangeRule/updateRuleById',
data,
)
}
// us规则列表
export function getByFactoryNoApi(data: { factoryNo: number }) {
return axios.get<never, BaseRespData<never>>(
'/factory/podJomallOrderUsArrangeRule/getByFactoryNo',
{ params: data },
)
}
...@@ -88,7 +88,15 @@ const router = createRouter({ ...@@ -88,7 +88,15 @@ const router = createRouter({
}, },
component: () => import('@/views/order/orderTracking/index.vue'), component: () => import('@/views/order/orderTracking/index.vue'),
}, },
{ {
path: '/pod-us-order/podUsSchedulingRules',
meta: {
title: 'POD(US)排单规则',
},
component: () =>
import('@/views/order/podUsSchedulingRules/index.vue'),
},
{
path: '/pod-cn-order/orderTracking', path: '/pod-cn-order/orderTracking',
meta: { meta: {
title: 'POD(CN)订单跟踪', title: 'POD(CN)订单跟踪',
......
...@@ -137,6 +137,11 @@ const menu: MenuItem[] = [ ...@@ -137,6 +137,11 @@ const menu: MenuItem[] = [
id: 10, id: 10,
label: 'POD(US)订单跟踪', label: 'POD(US)订单跟踪',
}, },
{
index: '/pod-us-order/podUsSchedulingRules',
id: 11,
label: 'POD(US)排单规则',
},
], ],
}, },
......
...@@ -38,7 +38,7 @@ export interface SearchForm { ...@@ -38,7 +38,7 @@ export interface SearchForm {
thirdSkuCode?: string thirdSkuCode?: string
supplierProductNo?: string supplierProductNo?: string
batchArrangeNumber?: string batchArrangeNumber?: string
craftCode?: string craftCode?: string[] | string
thirdStockSku?: string thirdStockSku?: string
exceptionHandling?: number | undefined exceptionHandling?: number | undefined
interceptStatus?: number | string interceptStatus?: number | string
...@@ -221,6 +221,7 @@ export interface LogisticsFormData { ...@@ -221,6 +221,7 @@ export interface LogisticsFormData {
export interface CraftListData { export interface CraftListData {
craftName: string craftName: string
craftCode: string craftCode: string
craftType: string
} }
export interface PackingData { export interface PackingData {
podProductionNo?: string // 生产单号(PSCD 开头) podProductionNo?: string // 生产单号(PSCD 开头)
......
...@@ -34,7 +34,7 @@ export interface SearchForm { ...@@ -34,7 +34,7 @@ export interface SearchForm {
thirdSkuCode?: string thirdSkuCode?: string
supplierProductNo?: string supplierProductNo?: string
batchArrangeNumber?: string batchArrangeNumber?: string
craftCode?: string craftCode?: string | string[]
craftCodeArr?: string[] craftCodeArr?: string[]
thirdStockSku?: string thirdStockSku?: string
interceptStatus?: number | string interceptStatus?: number | string
...@@ -141,6 +141,7 @@ export interface ProductList { ...@@ -141,6 +141,7 @@ export interface ProductList {
batchArrangeNumber?: string | null batchArrangeNumber?: string | null
interceptStatus?: number | null interceptStatus?: number | null
sizeType?: number | null sizeType?: number | null
productMark?: string | null
customTagList?: { name: string }[] customTagList?: { name: string }[]
} }
export interface cardImages { export interface cardImages {
...@@ -216,6 +217,7 @@ export interface LogisticsFormData { ...@@ -216,6 +217,7 @@ export interface LogisticsFormData {
export interface CraftListData { export interface CraftListData {
craftName: string craftName: string
craftCode: string craftCode: string
craftType: string
} }
export interface InterceptStateGroupData { export interface InterceptStateGroupData {
...@@ -226,3 +228,8 @@ export interface InterceptStateGroupData { ...@@ -226,3 +228,8 @@ export interface InterceptStateGroupData {
[key: string]: number [key: string]: number
} }
} }
export interface IAllList {
id: string
name: string
warehouseName?: string
}
...@@ -43,7 +43,7 @@ interface IwayList { ...@@ -43,7 +43,7 @@ interface IwayList {
} }
interface IAllList { interface IAllList {
factoryId?: number factoryId?: number
id: number id: number | string
name: string name: string
serviceCode?: string serviceCode?: string
siteUrl?: string siteUrl?: string
...@@ -83,6 +83,18 @@ export default defineComponent({ ...@@ -83,6 +83,18 @@ export default defineComponent({
type: String, type: String,
default: 'id', default: 'id',
}, },
searchPlaceholder: {
type: String,
default: '请搜索承运商',
},
startPlaceholder: {
type: String,
default: '请选择物流方式',
},
startWidth: {
type: String,
default: '100%',
},
}, },
emits: ['update:modelValue'], emits: ['update:modelValue'],
setup(props, { emit }) { setup(props, { emit }) {
...@@ -161,7 +173,20 @@ export default defineComponent({ ...@@ -161,7 +173,20 @@ export default defineComponent({
}, },
{ deep: true, immediate: true }, { deep: true, immediate: true },
) )
const handleClearSelection = () => {
/* 1. 清空显示文本 */
waysName.value = ''
/* 2. 清空双向绑定结果 */
if (props.isRadio) {
selectedRadioList.value = '' // 单选
emit('update:modelValue', '')
} else {
selectedList.value = [] // 多选
emit('update:modelValue', [])
}
/* 3. 可选:把搜索框也重置 */
searchName.value = ''
}
function setCheckAll(company: ICompanyList, event: boolean) { function setCheckAll(company: ICompanyList, event: boolean) {
if (event) { if (event) {
selectedList.value = [ selectedList.value = [
...@@ -252,8 +277,10 @@ export default defineComponent({ ...@@ -252,8 +277,10 @@ export default defineComponent({
reference: () => ( reference: () => (
<ElInput <ElInput
modelValue={waysName.value} modelValue={waysName.value}
style={{ width: '100%' }} style={{ width: props.startWidth }}
placeholder="请选择物流方式" placeholder={props.startPlaceholder}
clearable
onClear={handleClearSelection}
/> />
), ),
}} }}
...@@ -271,7 +298,7 @@ export default defineComponent({ ...@@ -271,7 +298,7 @@ export default defineComponent({
}} }}
clearable clearable
style={{ width: '200px', padding: '10px' }} style={{ width: '200px', padding: '10px' }}
placeholder="请搜索承运商" placeholder={props.searchPlaceholder}
/> />
<ElScrollbar <ElScrollbar
class="scroll-container" class="scroll-container"
......
import { defineComponent, ref } from 'vue'
import { ElDialog } from 'element-plus'
export default defineComponent({
name: 'CustomizeForm',
props: {
modelValue: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
dialogWidth: {
type: String,
default: '600px',
},
},
emits: ['update:modelValue', 'close'],
setup(props, { emit, attrs, slots }) {
const formRef = ref<InstanceType<typeof ElDialog> | null>(null)
const isShow = ref(false)
watch(
() => props.modelValue,
(val) => {
isShow.value = val
},
{ immediate: true },
)
return () => {
return (
<ElDialog
ref={formRef}
v-model={isShow.value}
title={props.title}
width={props.dialogWidth}
onClose={() => {
emit('close')
}}
destroy-on-close={true}
close-on-click-modal={false}
{...attrs}
>
<div class="dialog-form">
{slots.default?.()}
{slots.footer?.()}
</div>
</ElDialog>
)
}
},
})
...@@ -52,20 +52,13 @@ ...@@ -52,20 +52,13 @@
</ElFormItem> </ElFormItem>
<ElFormItem label="工艺"> <ElFormItem label="工艺">
<ElSelect <LogisticsWaySelect
v-model="searchForm.craftCode" v-model="searchForm.craftCode"
clearable :company-list="craftList"
filterable :start-width="'150px'"
placeholder="请选择工艺" search-placeholder="搜索工艺名称"
style="width: 150px" start-placeholder="请选择工艺名称"
> ></LogisticsWaySelect>
<el-option
v-for="item in craftList"
:key="item.craftCode"
:label="item.craftName"
:value="item.craftCode"
></el-option>
</ElSelect>
</ElFormItem> </ElFormItem>
<ElFormItem label="库存SKU"> <ElFormItem label="库存SKU">
<ElInput <ElInput
...@@ -2476,6 +2469,7 @@ ...@@ -2476,6 +2469,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getUserMarkList } from '@/api/common' import { getUserMarkList } from '@/api/common'
import LogisticsWaySelect from '../../logistics/components/LogisticsWaySelect.tsx'
// import { AnyObject } from '@/types/api/warehouse' // import { AnyObject } from '@/types/api/warehouse'
import { import {
InfoFilled, InfoFilled,
...@@ -2544,7 +2538,7 @@ import { BaseRespData } from '@/types/api' ...@@ -2544,7 +2538,7 @@ import { BaseRespData } from '@/types/api'
import UpdateAddress from './components/updateAddress.vue' import UpdateAddress from './components/updateAddress.vue'
import { getAllCountryApi } from '@/api/logistics.ts' import { getAllCountryApi } from '@/api/logistics.ts'
import { InterceptStateGroupData } from '@/types/api/podUsOrder' import { InterceptStateGroupData, IAllList } from '@/types/api/podUsOrder'
import TableView from '@/components/TableView.vue' import TableView from '@/components/TableView.vue'
import { import {
LogListData, LogListData,
...@@ -2776,7 +2770,7 @@ const [searchForm, resetSearchForm] = useValue<SearchForm>({ ...@@ -2776,7 +2770,7 @@ const [searchForm, resetSearchForm] = useValue<SearchForm>({
thirdSkuCode: '', thirdSkuCode: '',
supplierProductNo: '', supplierProductNo: '',
batchArrangeNumber: '', batchArrangeNumber: '',
craftCode: '', craftCode: [],
thirdStockSku: '', thirdStockSku: '',
}) })
const shipmentArea = ref(0) const shipmentArea = ref(0)
...@@ -4982,14 +4976,48 @@ const loadWarehouseList = async () => { ...@@ -4982,14 +4976,48 @@ const loadWarehouseList = async () => {
console.error(e) console.error(e)
} }
} }
const processType = ref([
{
label: '烫画',
value: 'TH',
},
{
label: '直喷',
value: 'ZP',
},
{
label: '刺绣',
value: 'CX',
},
{
label: '雕刻',
value: 'DK',
},
{
label: '白胚',
value: 'BP',
},
{
label: '其他',
value: 'QT',
},
])
// 获取工艺列表 // 获取工艺列表
const craftList = ref<CraftListData[]>([]) const craftList = ref<IAllList[]>([])
const processTypeMap = processType.value.reduce((acc, cur) => {
acc[cur.value] = cur.label
return acc
}, {} as Record<string, string>)
const loadCraftList = async () => { const loadCraftList = async () => {
try { try {
const res = await getListCraftApi() const res = await getListCraftApi()
if (res.code !== 200) return if (res.code !== 200) return
craftList.value = res.data const data: CraftListData[] = res.data
craftList.value = data.map((item) => ({
id: item.craftCode,
name: item.craftName,
warehouseName: processTypeMap[item.craftType] ?? '其他', // craftType 对应中文
})) as IAllList[]
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} }
......
...@@ -172,6 +172,7 @@ ...@@ -172,6 +172,7 @@
@click="podOrderDetailsData && print(podOrderDetailsData, true)" @click="podOrderDetailsData && print(podOrderDetailsData, true)"
>手动打印</ElButton >手动打印</ElButton
> >
<ElButton type="primary" @click="printNormal">普货拣货 </ElButton>
<ElButton type="success" @click="handlePrintFinish" <ElButton type="success" @click="handlePrintFinish"
>打单完成</ElButton >打单完成</ElButton
> >
...@@ -210,6 +211,17 @@ ...@@ -210,6 +211,17 @@
<span v-if="item.data" class="number"> <span v-if="item.data" class="number">
{{ item.data.pickingNumber }}/{{ item.data.purchaseNumber }} {{ item.data.pickingNumber }}/{{ item.data.purchaseNumber }}
</span> </span>
<div
v-if="
item.data &&
item.data.productList?.some(
(e) => e.productMark === 'custom_normal',
)
"
class="cb-product-mark"
>
<div class="red-circle"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -234,11 +246,13 @@ import { ...@@ -234,11 +246,13 @@ import {
getPackingDataApi, getPackingDataApi,
getPodBoxListApi, getPodBoxListApi,
submitInspectionApi, submitInspectionApi,
printNormalPickPdfApi,
} from '@/api/podUsOrder' } from '@/api/podUsOrder'
import useUserStore from '@/store/user' import useUserStore from '@/store/user'
import { Check } from '@element-plus/icons-vue' import { Check } from '@element-plus/icons-vue'
import socket from '@/utils/websocket' import socket from '@/utils/websocket'
import { WarehouseListData } from '@/types/api/podUsOrder' import { WarehouseListData } from '@/types/api/podUsOrder'
import { filePath } from '@/api/axios.ts'
const { getCLodop } = useLodop() const { getCLodop } = useLodop()
...@@ -274,7 +288,6 @@ const podOrderDetailsColumns = computed(() => [ ...@@ -274,7 +288,6 @@ const podOrderDetailsColumns = computed(() => [
width: 250, width: 250,
slot: 'image', slot: 'image',
align: 'center', align: 'center',
fixed: 'left',
}, },
{ {
label: '生产单号', label: '生产单号',
...@@ -282,21 +295,23 @@ const podOrderDetailsColumns = computed(() => [ ...@@ -282,21 +295,23 @@ const podOrderDetailsColumns = computed(() => [
width: 150, width: 150,
align: 'center', align: 'center',
}, },
// { {
// label: 'base SKU', label: '库存 SKU',
// prop: 'baseSku', prop: 'thirdSkuCode',
// width: 140, width: 180,
// align: 'center', align: 'center',
// }, },
{ {
label: 'variant SKU', label: 'variant SKU',
prop: 'variantSku', prop: 'variantSku',
width: 140, width: 160,
align: 'center', align: 'center',
}, },
{ {
label: '商品名称', label: '商品名称',
prop: 'productName', prop: 'productName',
minWidth: 100,
}, },
{ {
...@@ -304,18 +319,21 @@ const podOrderDetailsColumns = computed(() => [ ...@@ -304,18 +319,21 @@ const podOrderDetailsColumns = computed(() => [
prop: 'purchaseNumber', prop: 'purchaseNumber',
width: 90, width: 90,
align: 'center', align: 'center',
fixed: 'right',
}, },
{ {
label: '拣货数量', label: '拣货数量',
prop: 'count', prop: 'count',
width: 90, width: 90,
align: 'center', align: 'center',
fixed: 'right',
}, },
{ {
label: '验证结果', label: '验证结果',
slot: 'verifyResult', slot: 'verifyResult',
width: 90, width: 90,
align: 'center', align: 'center',
fixed: 'right',
}, },
]) ])
const boxChange = ref<boolean>(false) const boxChange = ref<boolean>(false)
...@@ -401,7 +419,15 @@ watch( ...@@ -401,7 +419,15 @@ watch(
(val) => { (val) => {
if (val && val.productList?.length) if (val && val.productList?.length)
val.productList.forEach((el) => { val.productList.forEach((el) => {
if (!el.previewImgs) el.previewImgs = JSON.parse(el.imageAry) if (!el.previewImgs) {
if (el.productMark === 'custom_normal') {
el.previewImgs = [{ url: el.variantImage || '' }]
} else {
el.previewImgs = el.imageAry
? JSON.parse(el.imageAry)
: [{ url: el.variantImage }]
}
}
}) })
}, },
{ deep: true }, { deep: true },
...@@ -426,7 +452,13 @@ const renderItemBox = (bool: boolean) => { ...@@ -426,7 +452,13 @@ const renderItemBox = (bool: boolean) => {
if (!boxItem) boxItem = { data: { productList: [] } } if (!boxItem) boxItem = { data: { productList: [] } }
const { data } = boxItem const { data } = boxItem
data?.productList?.forEach((el) => { data?.productList?.forEach((el) => {
if (!el.previewImgs) el.previewImgs = JSON.parse(el.imageAry) if (!el.previewImgs) {
if (el.productMark === 'custom_normal') {
el.previewImgs = [{ url: el.variantImage || '' }]
} else {
el.previewImgs = JSON.parse(el.imageAry)
}
}
}) })
if (!data) { if (!data) {
renderLock = false renderLock = false
...@@ -690,7 +722,15 @@ const initOrderDetailBox = async () => { ...@@ -690,7 +722,15 @@ const initOrderDetailBox = async () => {
boxIndex.value = boxList.find((item) => item.data)?.box || null boxIndex.value = boxList.find((item) => item.data)?.box || null
podOrderDetailsData.value?.productList?.forEach((el) => { podOrderDetailsData.value?.productList?.forEach((el) => {
if (!el.previewImgs) el.previewImgs = JSON.parse(el.imageAry) if (!el.previewImgs) {
if (el.productMark === 'custom_normal') {
el.previewImgs = [{ url: el.variantImage || '' }]
} else {
el.previewImgs = el.imageAry
? JSON.parse(el.imageAry)
: [{ url: el.variantImage }]
}
}
}) })
coverImage.value = coverImage.value =
podOrderDetailsData.value?.productList?.[0]?.previewImgs?.[0].url || '' podOrderDetailsData.value?.productList?.[0]?.previewImgs?.[0].url || ''
...@@ -971,6 +1011,31 @@ const handleWarehouseChange = (value: string | number) => { ...@@ -971,6 +1011,31 @@ const handleWarehouseChange = (value: string | number) => {
_warehouseId.value = value _warehouseId.value = value
initOrderDetailBox() initOrderDetailBox()
} }
const printNormal = async () => {
const arr: (number | undefined)[] = []
;(podBoxList.value || []).forEach((item: PodMakeOrderData) => {
if (item.data) {
if (item.data.productList && item.data.productList.length > 0) {
item.data.productList.forEach((item1) => {
if (
item1.productMark == 'normal' ||
item1.productMark == 'custom_normal'
) {
arr?.push(item1?.id)
}
})
}
}
})
if (!arr.length) {
ElMessage.warning('暂无可打印的普货拣货单')
return
}
const res = await printNormalPickPdfApi(arr.join())
ElMessage.success('操作成功')
window.open(filePath + res.message)
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
...@@ -1149,6 +1214,17 @@ const handleWarehouseChange = (value: string | number) => { ...@@ -1149,6 +1214,17 @@ const handleWarehouseChange = (value: string | number) => {
color: #ddd; color: #ddd;
} }
} }
.cb-product-mark {
position: absolute;
top: 0;
right: 0;
.red-circle {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: red;
}
}
</style> </style>
<style lang="scss"> <style lang="scss">
.pod-make-order-dialog { .pod-make-order-dialog {
......
...@@ -8,6 +8,7 @@ import vueJsx from '@vitejs/plugin-vue-jsx' ...@@ -8,6 +8,7 @@ import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
base: '/', base: '/',
plugins: [ plugins: [
vue(), vue(),
vueJsx(), vueJsx(),
......
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