Commit 213060b8 by linjinhong

物流报价和运费计算页面添加完成

parent 5003fd35
...@@ -50,6 +50,7 @@ declare module 'vue' { ...@@ -50,6 +50,7 @@ declare module 'vue' {
ElTag: typeof import('element-plus/es')['ElTag'] ElTag: typeof import('element-plus/es')['ElTag']
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']
Icon: typeof import('./src/components/Icon.vue')['default'] Icon: typeof import('./src/components/Icon.vue')['default']
ImageView: typeof import('./src/components/ImageView.vue')['default'] ImageView: typeof import('./src/components/ImageView.vue')['default']
LogList: typeof import('./src/components/LogList.vue')['default'] LogList: typeof import('./src/components/LogList.vue')['default']
......
...@@ -114,15 +114,15 @@ export function getlogisticsWayAllList() { ...@@ -114,15 +114,15 @@ export function getlogisticsWayAllList() {
return axios.get<never, BaseRespData<never>>('/logisticsWay/all_list', {}) return axios.get<never, BaseRespData<never>>('/logisticsWay/all_list', {})
} }
//物流报价列表 //物流报价列表
export function getlogisticsQuotationList() { export function getlogisticsQuotationList(params: any) {
return axios.get<never, BaseRespData<never>>( return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsQuotation/list_page', '/logistics/logisticsQuotation/list_page',
{}, params,
) )
} }
//新增 //新增
export function addLogisticsQuotation(params: any) { export function addLogisticsQuotation(params: any) {
return axios.get<never, BaseRespData<never>>( return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsQuotation/add', '/logistics/logisticsQuotation/add',
params, params,
) )
...@@ -142,24 +142,31 @@ export function deleteLogisticsQuotation(params: any) { ...@@ -142,24 +142,31 @@ export function deleteLogisticsQuotation(params: any) {
) )
} }
//导入 //导入
export function importLogisticsQuotation(params: any) { export function importLogisticsQuotation(formData: any) {
return axios.get<never, BaseRespData<never>>( return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsQuotation/import', '/logistics/logisticsQuotation/import',
{ params }, formData,
{
headers: {
'Content-Type': 'multipart/form-data',
},
},
) )
} }
//下载模版 //下载模版
export function exportLogisticsQuotationTemplate(params: any) { export function downloadLogisticsQuotationTemplate() {
return axios.get<never, BaseRespData<never>>( return axios.get<never, BaseRespData<never>>(
'/logistics/logisticsQuotation/exportExcel', '/logistics/logisticsQuotation/exportExcel',
{ params }, {
responseType: 'blob',
},
) )
} }
//根据ID查对象 //根据ID查对象
export function getLogisticsQuotationByID(params: any) { export function getLogisticsQuotationByID(params: any) {
return axios.get<never, BaseRespData<never>>( return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsQuotation/get', '/logistics/logisticsQuotation/get',
{ params }, params,
) )
} }
...@@ -193,3 +200,68 @@ export function deleteLogisticsCustomsRule(params: any) { ...@@ -193,3 +200,68 @@ export function deleteLogisticsCustomsRule(params: any) {
params, params,
}) })
} }
/**
* @description 物流分区
*/
//列表
export function getLogisticsZoneList(params: any) {
return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsZone/list',
params,
)
}
//新增
export function addLogisticsZone(params: any) {
return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsZone/add',
params,
)
}
//修改
export function updateLogisticsZone(params: any) {
return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsZone/update',
params,
)
}
//删除
export function deleteLogisticsZone(params: any) {
return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsZone/delete',
params,
)
}
//物流分区导入
export function importLogisticsZone(formData: any) {
return axios.post<never, BaseRespData<never>>(
'/logistics/logisticsZone/import',
formData,
{
headers: {
'Content-Type': 'multipart/form-data',
},
},
)
}
//物流分区导入模板
export function exportExcelLogisticsZone() {
return axios.get<never, BaseRespData<never>>(
'/logistics/logisticsZone/exportExcel',
{
responseType: 'blob',
},
)
}
/**
* @description 运费试算
*/
export function getLogisticsTrialCalculation(params: any) {
return axios.get<never, BaseRespData<never>>(
'/logistics/logisticsQuotation/logisticsTrialCalculation',
{
params,
},
)
}
...@@ -130,8 +130,8 @@ export default defineComponent({ ...@@ -130,8 +130,8 @@ export default defineComponent({
await formRef.value?.resetFields() await formRef.value?.resetFields()
} }
function refashConfig(showFields: string[]) { function refashConfig(showFields?: string[]) {
if (showFields.length) { if (showFields?.length) {
const filterArr = props.config.filter((item) => const filterArr = props.config.filter((item) =>
showFields.includes(item.prop as string), showFields.includes(item.prop as string),
) )
...@@ -142,6 +142,8 @@ export default defineComponent({ ...@@ -142,6 +142,8 @@ export default defineComponent({
] ]
.filter((item) => !item.fixed) .filter((item) => !item.fixed)
.concat(tableConfig.value.filter((item) => item.fixed)) .concat(tableConfig.value.filter((item) => item.fixed))
} else {
tableConfig.value = props.config
} }
console.log('tableConfig', tableConfig.value) console.log('tableConfig', tableConfig.value)
} }
......
...@@ -9,9 +9,12 @@ ...@@ -9,9 +9,12 @@
@input="iptFn" @input="iptFn"
> >
<template v-if="hasSuffix" #suffix>{{ suffix }}</template> <template v-if="hasSuffix" #suffix>{{ suffix }}</template>
<template v-if="hasAppend" #append>
<component :is="appendRender" />
</template>
</el-input> </el-input>
</template> </template>
<script lang="ts" setup> <script lang="tsx" setup>
import { isNumFloat } from '@/utils/validate' import { isNumFloat } from '@/utils/validate'
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
...@@ -20,6 +23,8 @@ const props = withDefaults( ...@@ -20,6 +23,8 @@ const props = withDefaults(
placeholder?: string placeholder?: string
size?: '' | 'default' | 'small' | 'large' size?: '' | 'default' | 'small' | 'large'
hasSuffix?: boolean hasSuffix?: boolean
hasAppend?: boolean
appendRender?: () => JSX.Element
isDisabled?: boolean isDisabled?: boolean
}>(), }>(),
{ {
...@@ -29,6 +34,8 @@ const props = withDefaults( ...@@ -29,6 +34,8 @@ const props = withDefaults(
size: 'default', size: 'default',
hasSuffix: true, hasSuffix: true,
isDisabled: false, isDisabled: false,
hasAppend: false,
appendRender: null,
}, },
) )
const emits = defineEmits<{ const emits = defineEmits<{
......
...@@ -34,9 +34,10 @@ const props = withDefaults( ...@@ -34,9 +34,10 @@ const props = withDefaults(
hasAllOptions?: boolean hasAllOptions?: boolean
labelIsValue?: boolean // value 使用label字段 labelIsValue?: boolean // value 使用label字段
initChange?: boolean // 首次是否触发change事件 initChange?: boolean // 首次是否触发change事件
modelValue?: string | number modelValue?: string | number | string[] | number[]
isRefresh?: boolean isRefresh?: boolean
isValueKey?: boolean isValueKey?: boolean
load?: (arg: (val: boolean) => void) => void // focus后再加载数据的 load?: (arg: (val: boolean) => void) => void // focus后再加载数据的
}>(), }>(),
{ {
......
...@@ -104,12 +104,23 @@ export default defineComponent({ ...@@ -104,12 +104,23 @@ export default defineComponent({
setup(props, { emit, slots, attrs }) { setup(props, { emit, slots, attrs }) {
const formRef = ref() const formRef = ref()
const formWrapperRef = ref() const formWrapperRef = ref()
const searchForm = ref<ISearchForm>(props.modelValue || {}) const searchForm = ref<ISearchForm>({})
const selectResult = ref<ISeachFormConfig[]>([]) const selectResult = ref<ISeachFormConfig[]>([])
const componentWidth = computed(() => const componentWidth = computed(() =>
props.size === 'default' ? 200 : 220, props.size === 'default' ? 200 : 220,
) )
watch(
() => props.modelValue,
(val) => {
searchForm.value = val
},
{
immediate: true,
deep: true,
},
)
function initSeachForm() { function initSeachForm() {
props.config.forEach((item, index) => { props.config.forEach((item, index) => {
if (componentDataTypeMap.has(item.type as EComponenetType)) { if (componentDataTypeMap.has(item.type as EComponenetType)) {
...@@ -157,7 +168,7 @@ export default defineComponent({ ...@@ -157,7 +168,7 @@ export default defineComponent({
<div style={styles.wrapper} class="mt-15"> <div style={styles.wrapper} class="mt-15">
<ElForm <ElForm
{...getFormAttrs.value} {...getFormAttrs.value}
ref={el=>formRef.value=el} ref={(el) => (formRef.value = el)}
class="w-full" class="w-full"
inline inline
model={searchForm.value} model={searchForm.value}
......
import { VNode } from 'vue' import { VNode } from 'vue'
interface ColumnAttrs { interface ColumnAttrs {
field?: string field?: string
title?: string title?: string
...@@ -52,7 +51,7 @@ export default defineComponent({ ...@@ -52,7 +51,7 @@ export default defineComponent({
}, },
}, },
emits: ['update:modelValue', 'checkbox-change', 'getCheckboxRecords'], emits: ['update:modelValue', 'checkbox-change', 'getCheckboxRecords'],
setup(props, { emit ,attrs}) { setup(props, { emit, attrs }) {
const tableRef = ref(null) const tableRef = ref(null)
const tableData = ref<Record<string, unknown>[]>([]) const tableData = ref<Record<string, unknown>[]>([])
const tableColumns = ref<TableColumn[]>([]) const tableColumns = ref<TableColumn[]>([])
...@@ -79,9 +78,7 @@ export default defineComponent({ ...@@ -79,9 +78,7 @@ export default defineComponent({
watch( watch(
() => props.modelValue, () => props.modelValue,
(val) => { (val) => {
tableData.value = Array.isArray(val) ? val : []
tableData.value = Array.isArray(val) ? val : []
}, },
{ {
immediate: true, immediate: true,
...@@ -98,7 +95,7 @@ export default defineComponent({ ...@@ -98,7 +95,7 @@ export default defineComponent({
} }
} }
} }
//获取选中数据
const getSelectEvent = () => { const getSelectEvent = () => {
const $table = tableRef.value const $table = tableRef.value
if ($table) { if ($table) {
...@@ -106,6 +103,14 @@ export default defineComponent({ ...@@ -106,6 +103,14 @@ export default defineComponent({
emit('getCheckboxRecords', selectRecords) emit('getCheckboxRecords', selectRecords)
} }
} }
//设置高亮行
const selectRowEvent = (row: TableRowData) => {
const $table = tableRef.value
if ($table) {
console.log(110, row)
$table.setCurrentRow(row)
}
}
onMounted(() => { onMounted(() => {
getList() getList()
...@@ -116,62 +121,61 @@ export default defineComponent({ ...@@ -116,62 +121,61 @@ export default defineComponent({
tableData, tableData,
tableColumns, tableColumns,
editConfig, editConfig,
getSelectEvent,attrs getSelectEvent,
selectRowEvent,
attrs,
} }
}, },
render() { render() {
return ( return (
<vxe-table
<vxe-table ref={(el) => (this.tableRef = el)}
ref={(el) => this.tableRef = el} data={this.tableData}
data={this.tableData} height="100%"
height='100%' edit-config={this.editConfig}
onCheckboxChange={this.getSelectEvent}
edit-config={this.editConfig} onCheckboxAll={this.getSelectEvent}
onCheckboxChange={this.getSelectEvent} {...this.attrs}
onCheckboxAll={this.getSelectEvent} >
{...this.attrs} {this.isShowCheckBox && (
> <vxe-column type="checkbox" width="50" align="center"></vxe-column>
{this.isShowCheckBox && ( )}
<vxe-column type="checkbox" width="50" align="center"></vxe-column>
)}
<vxe-column align="center" type="seq" width="50" title="序号" /> <vxe-column align="center" type="seq" width="50" title="序号" />
{this.tableColumns.map((item: TableColumn, index: number) => ( {this.tableColumns.map((item: TableColumn, index: number) => (
<vxe-column <vxe-column
key={index} key={index}
field={item.prop} field={item.prop}
title={item.label} title={item.label}
{...item.attrs} {...item.attrs}
edit-render={{}} edit-render={{}}
> >
{{ {{
...(() => { ...(() => {
// 创建基础插槽配置 // 创建基础插槽配置
const slots: Record<string, SlotFunction> = { const slots: Record<string, SlotFunction> = {
// 默认的 default 插槽实现 // 默认的 default 插槽实现
default: ({ row }) => <span>{row[item.prop]}</span>, default: ({ row }) => <span>{row[item.prop]}</span>,
} }
if (item.render) { if (item.render) {
// 添加所有自定义插槽 // 添加所有自定义插槽
Object.entries(item.render).forEach( Object.entries(item.render).forEach(
([slotName, renderFn]) => { ([slotName, renderFn]) => {
if (renderFn) { if (renderFn) {
slots[slotName] = (scope: { row: TableRowData }) => slots[slotName] = (scope: { row: TableRowData }) =>
renderFn(scope) renderFn(scope)
} }
}, },
) )
} }
return slots return slots
})(), })(),
}} }}
</vxe-column> </vxe-column>
))} ))}
</vxe-table> </vxe-table>
) )
}, },
}) })
...@@ -148,7 +148,20 @@ const router = createRouter({ ...@@ -148,7 +148,20 @@ const router = createRouter({
}, },
component: () => import('@/views/logistics/declarationRule.vue'), component: () => import('@/views/logistics/declarationRule.vue'),
}, },
{
path: '/logistics/logisticsPartition',
meta: {
title: '物流分区',
},
component: () => import('@/views/logistics/logisticsPartition.vue'),
},
{
path: '/logistics/logisticsCalculate',
meta: {
title: '运费试算',
},
component: () => import('@/views/logistics/logisticsCalculate.vue'),
},
{ {
path: '/warehouse/manage', path: '/warehouse/manage',
meta: { meta: {
......
...@@ -136,19 +136,29 @@ const menu: MenuItem[] = [ ...@@ -136,19 +136,29 @@ const menu: MenuItem[] = [
}, },
{ {
index: '/logistics/shippingAddress', index: '/logistics/shippingAddress',
id: 1, id: 2,
label: '发货地址', label: '发货地址',
}, },
{ {
index: '/logistics/logisticsQuotation', index: '/logistics/logisticsQuotation',
id: 1, id: 3,
label: '物流报价', label: '物流报价',
}, },
{ {
index: '/logistics/declarationRule', index: '/logistics/declarationRule',
id: 1, id: 4,
label: '申报规则', label: '申报规则',
}, },
{
index: '/logistics/logisticsPartition',
id: 5,
label: '物流分区',
},
{
index: '/logistics/logisticsCalculate',
id: 6,
label: '运费试算',
},
], ],
}, },
// { // {
......
...@@ -12,6 +12,7 @@ export interface PaginationData<D> { ...@@ -12,6 +12,7 @@ export interface PaginationData<D> {
size: number size: number
current: number current: number
records: D[] records: D[]
data?: D[]
} }
export interface Statistics<D> { export interface Statistics<D> {
sumNotPassNum: number sumNotPassNum: number
......
...@@ -44,7 +44,6 @@ export default function usePageList<T>(options: UsePageListOptions<T>) { ...@@ -44,7 +44,6 @@ export default function usePageList<T>(options: UsePageListOptions<T>) {
pageSize.value = res.size pageSize.value = res.size
data.value = res.records data.value = res.records
} }
console.log(7, data.value)
} catch (error) { } catch (error) {
console.error(error) console.error(error)
// showError(error) // showError(error)
......
<template>
<div class="user-page flex-column card h-100 overflow-hidden">
<div class="header-filter-form">
<SearchForm
:config="searchConfig"
:isSearchBtn="false"
:isAddBtn="false"
:isDeleteBtn="false"
v-model="searchForm"
>
<template #ontherBtn>
<div style="margin-left: 10px; display: flex; gap: 10px">
<ElButton @click="search" type="primary">计算</ElButton>
</div>
</template>
</SearchForm>
</div>
<div
v-loading="loading"
class="user-content flex-1 flex-column overflow-hidden"
>
<div class="user-list flex-1 overflow-hidden">
<CustomizeTable
ref="tableRef"
v-model="tableData"
:config="tableConfig"
:merge-cells="mergeCells"
highlight-current-row
:isShowCheckBox="false"
border="full"
@getCheckboxRecords="handleCheckboxRecords"
></CustomizeTable>
</div>
</div>
</div>
</template>
<script setup lang="tsx">
import { getLogisticsTrialCalculation } from '@/api/logistics'
import type { LogisticsMethod } from '@/types/api/logistics'
import SearchForm from '@/components/SearchForm.tsx'
import LogDialog from './components/LogDialog.tsx'
import CustomizeForm from '@/components/CustomizeForm.tsx'
import CustomizeTable from '@/components/VxeTable.tsx'
import type { VxeTablePropTypes } from 'vxe-table'
import usePageList from '@/utils/hooks/usePageList'
import { useValue } from './hooks/useValue'
import { showConfirm } from '@/utils/ui'
import { Edit } from '@element-plus/icons-vue'
const [searchForm] = useValue({ code: '', weight: '' })
const tableRef = ref(null)
const selection = ref([])
const mergeCells = ref<VxeTablePropTypes.MergeCells>([])
const tableData = ref([])
const searchConfig = ref([
{
prop: 'code',
type: 'input',
label: '邮编',
attrs: {
placeholder: '请输入邮编',
},
},
{
prop: 'weight',
type: 'amountInput',
label: '重量',
attrs: {
placeholder: '请输入重量',
hasUnit: true,
suffix: 'g',
},
},
])
const tableConfig = ref([
{
prop: 'logisticsWayName',
label: '物流名称',
attrs: {
align: 'center',
width: 100,
},
},
{
prop: 'warehouseName',
label: '发货仓库',
},
{
prop: 'logisticsWayCode',
label: '物流编码',
},
{
prop: 'partition',
label: '所在分区',
},
{
prop: 'status',
label: '状态',
render: {
default: ({ row }) => {
return (
<div style={{ color: row.status ? '#67c23a' : '#f56c6c' }}>
{row.status ? '成功' : '失败'}
</div>
)
},
},
},
{
prop: 'payFreight',
label: '预计运费($)',
},
])
async function search() {
if (!searchForm.value.code) {
ElMessage.warning('请输入邮编')
return
}
if (!searchForm.value.weight) {
ElMessage.warning('请输入重量')
return
}
await getList(searchForm.value)
const itemIndex = tableData.value.findIndex((item) => item.status)
console.log(123, itemIndex)
if (itemIndex !== -1) {
nextTick(() => {
tableRef.value?.selectRowEvent(tableData.value[itemIndex])
})
}
}
const loading = ref(false)
async function getList(data?) {
loading.value = true
try {
const res = await getLogisticsTrialCalculation({
...data,
})
tableData.value = [...res.data]
} catch (error) {
console.log(error)
} finally {
loading.value = false
}
}
function handleCheckboxRecords(value: never[]) {
console.log(351, value)
selection.value = value
}
</script>
<style lang="scss" scoped>
.header-filter-form {
margin-bottom: 20px;
:deep(.el-form-item) {
margin-right: 14px;
margin-bottom: 10px;
}
}
.user-operate-btn {
margin-bottom: 10px;
}
.dialog-footer {
text-align: center;
}
</style>
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