admin-vue3/src/views/mes/wm/salesnotice/components/WmSalesNoticeSelectDialog.vue

327 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
MES 发货通知单弹窗选择器支持单选/多选
Props:
multiple true 多选checkboxfalse 单选radio默认 true
status 固定状态筛选传入后不展示状态下拉不传时展示状态搜索框
Events:
selected(rows: WmSalesNoticeVO[]) 确认选择后触发单选时数组长度为 1
Expose:
open(selectedIds?: number[]) 打开弹窗可传入已选 ID 用于预选高亮
-->
<template>
<Dialog title="发货通知单选择" v-model="dialogVisible" width="70%">
<ContentWrap>
<el-alert
v-if="status != null"
:title="`仅展示状态为【${getDictLabel(DICT_TYPE.MES_WM_SALES_NOTICE_STATUS, status)}】的发货通知单`"
type="info"
:closable="false"
show-icon
class="!mb-10px"
/>
<el-form :inline="true" :model="queryParams" label-width="100px">
<el-form-item label="通知单编号">
<el-input
v-model="queryParams.noticeCode"
placeholder="请输入通知单编号"
clearable
@keyup.enter="handleQuery"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="通知单名称">
<el-input
v-model="queryParams.noticeName"
placeholder="请输入通知单名称"
clearable
@keyup.enter="handleQuery"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="销售订单编号">
<el-input
v-model="queryParams.salesOrderCode"
placeholder="请输入销售订单编号"
clearable
@keyup.enter="handleQuery"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="客户">
<MdClientSelect v-model="queryParams.clientId" class="!w-220px" />
</el-form-item>
<el-form-item v-if="props.status == null" label="单据状态">
<el-select
v-model="queryParams.status"
placeholder="请选择单据状态"
clearable
class="!w-220px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_WM_SALES_NOTICE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 数据表格:单选 radio / 多选 checkbox 统一在一个 table 内 -->
<ContentWrap>
<el-table
ref="tableRef"
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
:highlight-current-row="!multiple"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
@row-dblclick="handleRowDblClick"
>
<!-- 多选checkboxreserve-selection 保证跨页勾选不丢失) -->
<el-table-column
v-if="multiple"
type="selection"
:reserve-selection="true"
width="50"
align="center"
/>
<!-- 单选radio -->
<el-table-column v-else width="50" align="center">
<template #default="{ row }">
<el-radio
v-model="selectedRadioId"
:value="row.id"
class="radio-no-label"
@change="handleRadioChange(row)"
/>
</template>
</el-table-column>
<el-table-column label="通知单编号" align="center" prop="noticeCode" width="180" />
<el-table-column label="通知单名称" align="left" prop="noticeName" min-width="150" />
<el-table-column label="销售订单编号" align="center" prop="salesOrderCode" width="160" />
<el-table-column label="客户名称" align="center" prop="clientName" width="120" />
<el-table-column label="发货日期" align="center" prop="salesDate" width="120">
<template #default="scope">
<span>{{ formatDate(scope.row.salesDate, 'YYYY-MM-DD') }}</span>
</template>
</el-table-column>
<el-table-column label="收货人" align="center" prop="recipientName" width="100" />
<el-table-column label="联系方式" align="center" prop="recipientTelephone" width="130" />
<el-table-column label="收货地址" align="center" prop="recipientAddress" min-width="200" />
<el-table-column label="单据状态" align="center" prop="status" width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_WM_SALES_NOTICE_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
</el-table>
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<template #footer>
<el-button type="primary" @click="confirmSelect">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions, getDictLabel } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { WmSalesNoticeApi, WmSalesNoticeVO } from '@/api/mes/wm/salesnotice'
import MdClientSelect from '@/views/mes/md/client/components/MdClientSelect.vue'
defineOptions({ name: 'WmSalesNoticeSelectDialog' })
const props = withDefaults(
defineProps<{
multiple?: boolean // true checkboxfalse radio
status?: number //
}>(),
{
multiple: true
}
)
const message = useMessage()
const emit = defineEmits<{
selected: [rows: WmSalesNoticeVO[]]
}>()
const dialogVisible = ref(false) // 弹窗是否展示
const loading = ref(false) // 列表加载中
const list = ref<WmSalesNoticeVO[]>([]) // 列表
const total = ref(0) // 总条数
// ==================== 选中状态 ====================
const tableRef = ref() // 表格 Ref
const selectedRows = ref<WmSalesNoticeVO[]>([]) // 多选模式:选中行
const selectedRadioId = ref<number>() // 单选模式:选中 ID
const currentRadioRow = ref<WmSalesNoticeVO>() // 单选模式:选中行对象
const preSelectedIds = ref<number[]>([]) // 打开弹窗时传入的已选 ID
/** 多选checkbox 变化 */
const handleSelectionChange = (rows: WmSalesNoticeVO[]) => {
if (props.multiple) {
selectedRows.value = rows
}
}
/** 单选radio 变化 */
const handleRadioChange = (row: WmSalesNoticeVO) => {
currentRadioRow.value = row
}
/** 单击行:单选模式下点击整行即选中(降低操作成本),多选不处理(避免和 dblclick 冲突) */
const handleRowClick = (row: WmSalesNoticeVO) => {
if (props.multiple) {
return
}
selectedRadioId.value = row.id
currentRadioRow.value = row
}
/** 双击行:多选模式切换勾选,单选模式直接确认 */
const handleRowDblClick = (row: WmSalesNoticeVO) => {
if (props.multiple) {
tableRef.value?.toggleRowSelection(row)
return
}
selectedRadioId.value = row.id
currentRadioRow.value = row
confirmSelect()
}
// ==================== 查询 ====================
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
noticeCode: undefined as string | undefined,
noticeName: undefined as string | undefined,
salesOrderCode: undefined as string | undefined,
clientId: undefined as number | undefined,
status: undefined as number | undefined
})
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await WmSalesNoticeApi.getSalesNoticePage(queryParams)
list.value = data.list
total.value = data.total
await nextTick()
applyPreSelection()
} finally {
loading.value = false
}
}
/** 恢复预选状态(当前页可见范围内) */
const applyPreSelection = () => {
if (preSelectedIds.value.length === 0) {
return
}
if (props.multiple) {
const table = tableRef.value
if (!table) {
return
}
list.value.forEach((row) => {
if (preSelectedIds.value.includes(row.id)) {
table.toggleRowSelection(row, true)
}
})
} else {
const match = list.value.find((row) => preSelectedIds.value.includes(row.id))
if (match) {
selectedRadioId.value = match.id
currentRadioRow.value = match
}
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置查询条件 */
const resetQuery = () => {
queryParams.noticeCode = undefined
queryParams.noticeName = undefined
queryParams.salesOrderCode = undefined
queryParams.clientId = undefined
queryParams.status = props.status
handleQuery()
}
/** 确认选择 */
const confirmSelect = () => {
if (props.multiple) {
if (selectedRows.value.length === 0) {
message.warning('请至少选择一条数据')
return
}
emit('selected', selectedRows.value)
} else {
if (!currentRadioRow.value) {
message.warning('请选择一条数据')
return
}
emit('selected', [currentRadioRow.value])
}
dialogVisible.value = false
}
// ==================== 打开弹窗 ====================
/** 打开弹窗,可传入已选 ID 用于预选高亮 */
const open = async (selectedIds?: number[]) => {
dialogVisible.value = true
// 重置查询条件 + 页码,避免二次打开继承上次过滤上下文
queryParams.noticeCode = undefined
queryParams.noticeName = undefined
queryParams.salesOrderCode = undefined
queryParams.clientId = undefined
queryParams.status = props.status != null ? props.status : undefined
queryParams.pageNo = 1
// 清空上一次的选中状态
selectedRows.value = []
selectedRadioId.value = undefined
currentRadioRow.value = undefined
preSelectedIds.value = selectedIds ?? []
// 多选模式清空跨页缓存的勾选
await nextTick()
tableRef.value?.clearSelection()
await getList()
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
/* 隐藏 radio 的 label 文字,只保留圆圈 */
.radio-no-label {
:deep(.el-radio__label) {
display: none;
}
}
</style>