现在要加个出库按钮,打开出库页模态框
<template>
<div class="query-view-detail">
<DetailHeader
@saveModalHandleOpen="saveModalHandleOpen"
@powerModalHandleOpen="powerModalHandleOpen"
@deleteModalHandleOpen="deleteModalHandleOpen"
@handleSelectWarnTypes="handleSelectWarnTypes"
@exportExcel="exportExcel"
/>
<main>
<SearchBar
ref="searchBarRef"
@handleSearch="handleSearch"
@updateFilter="updateFilter"
:filter="filter"
:frameFilters="frameFilters"
:currentTab="currentTab"
/>
<!-- <ResidualQuantityWarn @handleClickWatchQuantityWarn="handleClickWatchQuantityWarn" /> -->
<TableList
ref="tableListRef"
:loading="refreshTable.loading"
@changeTab="changeTab"
@changePagination="changePagination"
:currentTab="currentTab"
:tableListData="tableListData"
@openStockInModal="openStockInModal"
@openStockOutModal="openStockOutModal"
/>
</main>
<!-- Modals -->
<SaveModal
ref="saveModalRef"
:filter="filter"
@saveModalMakeViewHandleOk="saveModalMakeViewHandleOk"
@saveModalUpdateViewHandleOk="saveModalUpdateViewHandleOk"
/>
<PowerModal ref="powerModalRef" @powerModalHandleOk="powerModalHandleOk" />
<DeleteModal ref="deleteModalRef" @deleteModalHandleOk="deleteModalHandleOk" />
<StockInModal v-model:visible="stockInModalVisible" @refreshCurrentTabTable="refreshCurrentTabTable" />
<!-- 出库组件,通过v-model控制显隐-->
<StockOutModal v-model:visible="stockOutModalVisible" @refreshCurrentTabTable="refreshCurrentTabTable" />
</div>
</template>
<script lang="ts">
export type FrameFilter = {
fieldId: string | null
fieldKey?: string
fieldName: string
fieldType: FilterOriginType
filterType: TableColsTypeEnum
preDefinedValues: string[]
}
</script>
<script setup lang="ts">
//components
import TableList, { MaterialData } from './components/TableList.vue'
import DetailHeader from './components/DetailHeader.vue'
import SaveModal from './components/SaveModal.vue'
import PowerModal from './components/PowerModal.vue'
import DeleteModal from './components/DeleteModal.vue'
import SearchBar from './components/SearchBar.vue'
import { Message } from '@arco-design/web-vue'
// import ResidualQuantityWarn from './components/ResidualQuantityWarn.vue'
import StockInModal from './components/stockInModal/index.vue'
import StockOutModal from './components/stockOutModal/index.vue'
//utils
import { ref, reactive, computed, inject, toRaw, shallowRef, provide } from 'vue'
import {
initSearchInfo,
TabsEnum,
buildColumns,
TreeNodeTypeEnum,
deBuildColumns,
SaveViewModeEnmu
} from '@/views/register/registration-and-batch-info-query/utils'
import { useFetch } from '@/hooks'
//api
import {
searchBatchInfoList,
searchProductInfoList,
updateSearchView,
saveSearchView,
deleteSearchView,
getProductFrameFilters,
getExportColumnsData,
getExportProd
} from '@/api/material'
//types
import { Filter, FilterOriginType, SearchInfo, TableColsTypeEnum } from '../types'
import { exportExcelModeEnum } from '@/views/register/registration-and-batch-info-query/types'
import { SearchTypeEnmu } from '@/common/enum'
//plugin
import { useI18n } from 'vue-i18n'
import _, { cloneDeep } from 'lodash'
const { t } = useI18n()
const RootData = inject('rootData')
const { treeNodeData } = RootData as any
const Emiter = defineEmits(['saveView', 'updateView', 'deleteView', 'powerModalHandleOk'])
const globalSearchInfo = ref(initSearchInfo())
const setGlobalSearchInfo = (searchInfo) => (globalSearchInfo.value = searchInfo)
const tableListRef = ref()
const stockInModalVisible = ref<boolean>(false)
const stockOutModalVisible = ref<boolean>(false)
const materialDataList = shallowRef<MaterialData[] | undefined>(void 0)
provide('materialDataList', materialDataList)
const openStockInModal = (data: MaterialData[]) => {
stockInModalVisible.value = true
materialDataList.value = data
}
const openStockOutModal = (data: MaterialData[]) => {
stockOutModalVisible.value = true
materialDataList.value = data
}
const searchBarRef = ref()
/**
* DetailHeader 相关业务
*/
const saveModalRef = ref()
const powerModalRef = ref()
const deleteModalRef = ref()
const saveModalHandleOpen = () => {
saveModalRef.value.saveModalHandleOpen(SaveViewModeEnmu.CREATE_VIEW, {})
}
const powerModalHandleOpen = () => {
powerModalRef.value.powerModalHandleOpen()
}
const deleteModalHandleOpen = () => {
deleteModalRef.value.deleteModalHandleOpen()
}
const handleSelectWarnTypes = async (selectWarnTypes) => {
const newFilter = Object.assign(globalSearchInfo.value.filter, { alarmTypes: selectWarnTypes })
const searchInfo = globalSearchInfo.value
await refreshAllTabTable({ searchInfo })
}
/**
* 根据不同的tab,映射不同的接口
*/
const refreshTabTableMaps = {
[TabsEnum.REGISTER]: async ({ searchInfo, allColumns }: { searchInfo: SearchInfo; allColumns?: any[] }) => {
let ProductTableInfo = await searchProductInfoList(searchInfo)
//拼接展示列的信息
// if (!isEmpty(allColumns)) {
// ProductTableInfo.allColumns = buildColumns(TabsEnum.REGISTER, allColumns as any[])
// ProductTableInfo.showColumns = buildColumns(TabsEnum.REGISTER, searchInfo.productShowCols)
// } else {
// ProductTableInfo.allColumns = buildColumns(TabsEnum.REGISTER, searchInfo.productShowCols)
// ProductTableInfo.showColumns = buildColumns(TabsEnum.REGISTER, searchInfo.productShowCols)
// }
ProductTableInfo.allColumns = buildColumns(TabsEnum.REGISTER, searchInfo.productShowCols)
ProductTableInfo.data = parseCustomParams(ProductTableInfo.data)
tableListData[TabsEnum.REGISTER] = ProductTableInfo
setGlobalSearchInfo(cloneDeep(toRaw(searchInfo)))
filter.value = cloneDeep(toRaw(searchInfo.filter))
},
[TabsEnum.BATCH]: async ({ searchInfo, allColumns }: { searchInfo: SearchInfo; allColumns?: any[] }) => {
let BatchTableInfo = await searchBatchInfoList(searchInfo)
//拼接展示列的信息
BatchTableInfo.allColumns = buildColumns(TabsEnum.BATCH, searchInfo.batchShowCols)
BatchTableInfo.data = parseCustomParams(BatchTableInfo.data)
tableListData[TabsEnum.BATCH] = BatchTableInfo
setGlobalSearchInfo(cloneDeep(toRaw(searchInfo)))
filter.value = cloneDeep(toRaw(searchInfo.filter))
}
}
//将一些自定义字段解析到每个 dataItem 的外部
function parseCustomParams(data) {
return data.map((row, index) => {
let batchParams = row?.batchParams || []
let productParams = row?.productParams || []
const params = [...batchParams, ...productParams]
params.map((v) => {
row[v.fieldId] = v
})
//标记序号
row.index = index + 1
return row
})
}
/**
* 刷新所有tab数据
*/
const refreshAllTabTable = async ({ searchInfo, allColumns }: { searchInfo: SearchInfo; allColumns?: any[] }) => {
refreshTable.value.loading.value = true
tableListRef.value.clearCacheData() //清除之前表单的缓存数据
await Promise.all(
Object.values(refreshTabTableMaps).map((refreshFunc) => refreshFunc({ searchInfo, allColumns }))
).finally(() => {
refreshTable.value.loading.value = false
})
//回显对应的 keyword
searchBarRef.value.setKeywrod(searchInfo.keyword)
}
/**
* 刷新当前tab数据
*/
const refreshCurrentTabTable = () => {
refreshTabTableMaps[currentTab.value]({ searchInfo: globalSearchInfo.value })
tableListRef.value.initialSelectedRowKeys()
}
/**
* tab 相关
*/
const currentTab = reactive<{ value: TabsEnum }>({ value: TabsEnum.REGISTER })
// computed返回的是ref,之后访问时需要通过value
const refreshTable = computed(() => {
return useFetch(refreshTabTableMaps[currentTab.value], {
isLazy: true
})
})
// 切换tab事件
const changeTab = async ({ type, paginationInfo }) => {
currentTab.value = Number(type)
const { pageNum, pageSize } = paginationInfo
await refreshTable.value.fetchResource({ searchInfo: Object.assign(globalSearchInfo.value, { pageNum, pageSize }) })
}
//表单总数
const tableListData = reactive({
[TabsEnum.REGISTER]: {},
[TabsEnum.BATCH]: {}
})
const filter = ref<Filter>({})
/**
* 搜索按钮事件
* TODO
* 根据筛选条件进行搜索
*/
const handleSearch = ({ keyword = '' }: { keyword: string }) => {
// console.log('搜索', keyWord, tableListRef.value.selectedKeys)
//根据不同的节点类型,拿到正确的frameId
let frameId
switch (treeNodeData.value.nodeType) {
case TreeNodeTypeEnum.PRODUCT_FRAM: {
frameId = treeNodeData.value.id
}
case TreeNodeTypeEnum.VIEW: {
frameId = treeNodeData.value.parentId
}
default: {
frameId = treeNodeData.value.id
}
}
//初始化分页数据
tableListRef.value.initialPresetPagination()
const pageNum = tableListRef.value.paginationInfo.pageNum
//刷新列表
const targetParams = { ...globalSearchInfo.value, keyword, pageNum }
refreshTable.value.fetchResource({ searchInfo: targetParams })
//清空选择列
tableListRef.value.initialSelectedRowKeys()
}
/**
* 筛选条件更新到globalSearchInfo
*/
const updateFilter = (filter: Filter) => {
Object.assign(globalSearchInfo.value.filter, filter)
}
/**
* 导出接口
*/
const exportInfo = {
[TabsEnum.REGISTER]: {
method: getExportProd,
prefixName: t('register.registrationAndBatchInfoQuery.queryViewDetail.product')
},
[TabsEnum.BATCH]: {
method: getExportColumnsData,
prefixName: t('register.registrationAndBatchInfoQuery.queryViewDetail.batch')
}
}
/**
* 导出
*/
const exportExcel = async (mode, callback: Function) => {
let condition = {}
let seletCols: {
productShowCols: any[]
batchShowCols: any[]
} = {
productShowCols: [],
batchShowCols: []
}
switch (mode) {
case exportExcelModeEnum.CURRENT_SHOW: {
const { productShowCols, batchShowCols } = tableListRef.value.showCols
seletCols.productShowCols = deBuildColumns(productShowCols)
seletCols.batchShowCols = deBuildColumns(batchShowCols)
condition = Object.assign({}, globalSearchInfo.value, seletCols)
break
}
default: {
condition = Object.assign({}, globalSearchInfo.value, tableListRef.value.currentAllCols)
break
}
}
const { data } = await exportInfo[currentTab.value].method(condition)
callback(data, { fileName: `${exportInfo[currentTab.value].prefixName}_${treeNodeData.value.name}` })
}
/**
* 改变分页
*/
const changePagination = async ({ paginationInfo }) => {
const { pageNum, pageSize } = paginationInfo
// const { productShowCols, batchShowCols } = tableListRef.value.showCols
await refreshTable.value.fetchResource({
searchInfo: Object.assign(globalSearchInfo.value, {
pageNum,
pageSize
})
})
// const targetColsPropName = currentTab.value === TabsEnum.REGISTER ? 'productShowCols' : 'batchShowCols'
// const allColumns = cloneDeep(globalSearchInfo.value[targetColsPropName])
// await refreshTable.value.fetchResource({
// searchInfo: Object.assign(globalSearchInfo.value, {
// pageNum,
// pageSize,
// productShowCols: deBuildColumns(productShowCols),
// batchShowCols: deBuildColumns(batchShowCols)
// }),
// allColumns
// })
}
/**
* Modal相关
*/
//打包主要的视图信息
const buildViewMainInfo = ({ viewInfo }) => {
//保存的视图信息
const { viewName, viewDesc } = viewInfo
//筛选条件
const { productShowCols, batchShowCols } = tableListRef.value.showCols
globalSearchInfo.value.productShowCols = deBuildColumns(productShowCols)
globalSearchInfo.value.batchShowCols = deBuildColumns(batchShowCols)
const condition = globalSearchInfo.value
return { viewName, viewDesc, condition }
}
//保存视图
const saveModalMakeViewHandleOk = async (info, closeSaveModal, extraData) => {
const { viewName, viewDesc, condition } = buildViewMainInfo({ viewInfo: info })
//其他信息
const searchType = SearchTypeEnmu.PRODUCT_INFO
const frameId = extraData?.frameId
let referenceId
if (treeNodeData.value.nodeType === TreeNodeTypeEnum.PRODUCT_FRAM) {
referenceId = frameId || treeNodeData.value.key
}
if (treeNodeData.value.nodeType === TreeNodeTypeEnum.VIEW) {
referenceId = frameId || treeNodeData.value.parentId
}
//传递的总数居
const data = { viewName, viewDesc, condition, searchType, referenceId }
// console.log('保存时,传递的总数居', data)
await saveSearchView(data)
//告知外部,让其刷新树列表
Emiter('saveView', referenceId)
closeSaveModal()
}
//更新视图
const saveModalUpdateViewHandleOk = async (info, closeSaveModal) => {
const { viewName, viewDesc, condition } = buildViewMainInfo({ viewInfo: info })
//其他信息
const searchType = SearchTypeEnmu.PRODUCT_INFO
const frameId = treeNodeData.value.parentId
const id = treeNodeData.value.key
//传递的总数居
const data = { viewName, viewDesc, condition, searchType, id }
// console.log('更新时,传递的总数居', data)
try {
await updateSearchView(data)
} catch (error) {
/**
* 若保存失败,则要回溯对 globalSearchInfo 的更改
* (buildViewMainInfo中,操作了globalSearchInfo)
* */
const { productShowCols, batchShowCols } = tableListRef.value.allCols
globalSearchInfo.value.productShowCols = deBuildColumns(productShowCols)
globalSearchInfo.value.batchShowCols = deBuildColumns(batchShowCols)
}
//告知外部,让其刷新树列表
Emiter('updateView', { frameId, viewName, viewDesc, condition })
closeSaveModal()
}
//删除视图
const deleteModalHandleOk = async (closeDeleteModal) => {
await deleteSearchView(treeNodeData.value.id)
Message.success('删除成功!')
closeDeleteModal()
const frameId = treeNodeData.value.parentId
Emiter('deleteView', frameId)
}
//保存视图权限
const powerModalHandleOk = () => {
//权限相关信息
Emiter('powerModalHandleOk')
}
const frameFilters = ref<FrameFilter[]>([])
const getFrameFilters = async (frameId: string) => {
const res = await getProductFrameFilters(frameId)
frameFilters.value = res.data
}
/**
* 查看余量告警信息
*/
// async function handleClickWatchQuantityWarn() {
// const newFilter = Object.assign(globalSearchInfo.value.filter, { alarmOn: SystemYesNoEnum.YES })
// const searchInfo = globalSearchInfo.value
// await refreshAllTabTable(searchInfo)
// }
/**
* 暴露给外部的state
* */
const exposeSaveHandleOpen = computed(() => saveModalRef.value?.saveModalHandleOpen)
const initialTablePresetPagination = computed(() => tableListRef.value?.initialPresetPagination)
const initialTableSelectedRowKeys = computed(() => tableListRef.value?.initialSelectedRowKeys)
defineExpose({
refreshAllTabTable,
getFrameFilters,
saveModalHandleOpen: exposeSaveHandleOpen,
initialTablePresetPagination,
initialTableSelectedRowKeys
})
</script>
<style scoped lang="scss">
.query-view-detail {
background-color: #fff;
main {
padding: 0px 20px 24px;
}
}
.pointer {
cursor: pointer;
}
</style>
<template>
<div class="table-list-wrapper">
<div class="tabs-bar">
<div
class="tab-btn pointer"
:class="currentTab.value === Number(type) ? 'tab-active' : ''"
v-for="(item, type) in TabOptions"
:key="type"
@click="changeTab(item, type)"
>
{{ item.title }}({{ item.totalSum }})
</div>
</div>
<div class="table-wrapper">
<BasicTable
ref="tableRef"
rowKey="id"
v-model:columns="TabMapDataSource[currentTab.value].showColumns"
:data="showData"
:isShowFliter="true"
:columnsAll="currentAllCols"
:row-selection="rowSelection"
v-model:selectedRowKeys="selectedRowKeys"
:pagination="pagination"
:scroll="{ y: 600 }"
@select="handleSelected"
@selectAll="handleSelectAll"
column-resizable
:bordered="{ headerCell: true }"
:loading="loading"
>
<template #customTitle>
<a-space>
<span>已选定 {{ selectedRowKeys.length }} 个</span>
<a-button @click="openStockInModal" size="mini">入库</a-button>
<a-button @click="openStockOutModal" size="mini">出库</a-button>
<!-- <a-button size="mini">出库</a-button> -->
</a-space>
</template>
<!-- 序号列 -->
<template #cell-serialNumber="{ item }">
<a-tooltip :mini="true" :position="toolTipPosition" content-class="tool-tip-content">
<template #content>
<span v-for="msg in item.record.alarmMsgs" :key="msg">{{ msg }}</span>
</template>
<icon-exclamation-circle-fill v-if="item.record.alarmOn === 1" :style="{ color: '#ff7d00' }" />
{{ computedShowSerialNumber(item.record.index) }}
</a-tooltip>
</template>
<!-- 产品/批次附加字段 -->
<template #cell-customParams="{ item }">
<a-tooltip :mini="true" :position="toolTipPosition" content-class="tool-tip-content">
<template #content>
<p
v-for="(filed, filedKey) in showAdditionalFields(item.record[item.column.dataIndex], 'array')"
:key="filedKey"
class="tool-tip-content-item"
>
{{ filed }}
</p>
</template>
<a-tag v-if="!isShowEmpty(showAdditionalFields(item.record[item.column.dataIndex], 'string'))">
<span class="pointer">{{ showAdditionalFields(item.record[item.column.dataIndex], 'string') }}</span>
</a-tag>
</a-tooltip>
</template>
<!-- 以 link 形式展示的字段 -->
<template #cell-link="{ item }">
<a-link v-if="item.column.dataIndex === 'batchNum'">
批次数:
{{ customShowByColType(item.column.type, item.column.paramType, item.record[item.column.dataIndex]) }}
</a-link>
<a-link v-else>
{{ customShowByColType(item.column.type, item.column.paramType, item.record[item.column.dataIndex]) }}
</a-link>
</template>
<!-- 以 tag 形式展示的字段 -->
<template #cell-inStockNum="{ item }">
<a-tooltip
:position="toolTipPosition"
:popup-visible="!stockDetialLoading && item.record.id === mouseenterStockInfoCellId"
>
<template #content>
<a-spin :loading="stockDetialLoading" @mouseenter="showStock" @mouseleave="hideStock">
<span class="col-stock-detial-title">库存信息</span>
<p v-for="(str, key) in stockDetialInfoArr" :key="key" class="col-stock-detial-item">{{ str }}</p>
<a-link class="col-stock-detial-item">跳转至库存</a-link>
</a-spin>
</template>
<a-tag class="pointer" @mouseenter="getStockInfo(item.record)" @mouseout="initMouseenterStockInfoCellId">
在库数量:
{{ customShowByColType(item.column.type, item.column.paramType, item.record[item.column.dataIndex]) }}
</a-tag>
</a-tooltip>
</template>
<template #cell-default="{ item }">
{{ customShowByColType(item.column.type, item.column.paramType, item.record[item.column.dataIndex]) }}
</template>
</BasicTable>
</div>
</div>
</template>
<script lang="ts">
type TabMapDataSource = {
[key in TabsEnum]: {
//展示的cols
showColumns: any[]
//编辑的cols信息 (dataIndexArr)
selectShowColumns: string[]
}
}
interface StockDetialInfo {
inStockNum: string | number
inStockAmount: string | number
totalNum: string | number
totalAmount: string | number
}
</script>
<script setup lang="ts">
//api
import { getStockDetialInfo } from '@/api/material'
//components
import BasicTable from '@/components/BasicTable/index.vue'
//utils
import { ref, computed, Ref, watch, toRaw, reactive, nextTick, ShallowRef, shallowRef } from 'vue'
import _, { isEmpty } from 'lodash'
import moment from 'moment'
import { SERIAL_NUMBER } from '@/common/constant'
import { useFetch, useSelectedRows } from '@/hooks'
import { debounce } from '@/util/tools/index'
//types
import { TableRowSelection } from '@arco-design/web-vue'
import { TabsEnum } from '@/views/register/registration-and-batch-info-query/utils'
import { TableColsTypeEnum } from '@/views/register/registration-and-batch-info-query/types'
import { ParameterType } from '@/common/enum'
export type MaterialData = {
id: string
frameId: string
frameName: string
batchName?: string
productName: string
productId: string
batchNum: number
[key: string]: any
}
// const RootData = inject('rootData')
// const { productFrameInfo } = RootData as any
// const getProductFrameName = computed(() => productFrameInfo.value?.name)
const { currentTab, tableListData, loading } = defineProps<{
currentTab: { value: number }
tableListData: any
loading: Ref<boolean>
}>()
const Emiter = defineEmits(['changeTab', 'changePagination', 'openStockInModal', 'openStockOutModal'])
const tableRef = ref()
const rowSelection: TableRowSelection = reactive({
type: 'checkbox',
showCheckedAll: true
})
// tab信息
const TabOptions = computed(() => {
return {
[TabsEnum.REGISTER]: {
title: '注册信息',
totalSum: tableListData[TabsEnum.REGISTER].totalRecords || 0
},
[TabsEnum.BATCH]: {
title: '批次信息',
totalSum: tableListData[TabsEnum.BATCH].totalRecords || 0
}
}
})
//组件内部维护的不同 tab 对应的信息
let TabMapDataSource = reactive<TabMapDataSource>({
[TabsEnum.REGISTER]: {
//展示的cols
showColumns: [],
//编辑的cols信息 (dataIndexArr)
selectShowColumns: []
},
[TabsEnum.BATCH]: {
showColumns: [],
selectShowColumns: []
}
})
const isChangeTabMapDataSource = ref(true)
watch(
TabMapDataSource,
() => {
if (isChangeTabMapDataSource.value) {
if (TabMapDataSource[TabsEnum.REGISTER].showColumns[0]) {
;(TabMapDataSource[TabsEnum.REGISTER].showColumns[0] as any).customTitle = true
}
isChangeTabMapDataSource.value = false
}
nextTick(() => {
isChangeTabMapDataSource.value = true
})
},
{
immediate: false
}
)
const showData = computed(() => {
return _.isEmpty(TabMapDataSource[currentTab.value].selectShowColumns) ? ([] as []) : (data.value as [])
})
/**
* 索引当前的列表信息
* */
const data = computed<MaterialData[]>(() => {
refreshTableScroll()
return tableListData[currentTab.value].data
})
//当前总的cols
const currentAllCols = computed(() => tableListData[currentTab.value].allColumns)
//map形式的缓存
const currentAllColsToMap = ref({})
//初始化缓存
watch(currentAllCols, (newCurrentCols) => {
currentAllColsToMap.value = {}
newCurrentCols.map((v) => {
currentAllColsToMap.value[v.dataIndex] = v
})
})
//初始化展示的 cols
watch(currentAllCols, () => {
// 所有tab一起初始化,因为如果没有进入某个tab(未编辑),外面在保存时也能拿到该tab所有的列
for (const type in TabMapDataSource) {
if (_.isEmpty(TabMapDataSource[type].showColumns)) {
TabMapDataSource[type].showColumns = tableListData[type].allColumns
}
}
})
/**
* 设置展示列相关
*/
//初始化选项(选中全部)
watch(currentAllCols, (newCurrentCols) => {
if (_.isEmpty(TabMapDataSource[currentTab.value].selectShowColumns)) {
TabMapDataSource[currentTab.value].selectShowColumns = newCurrentCols.map((v) => v.dataIndex)
}
})
//(编辑展示列) newSelectShowColumns 就是一个 dataIndexArray
watch(
() => TabMapDataSource[currentTab.value].selectShowColumns,
(newSelectShowColumns) => {
TabMapDataSource[currentTab.value].showColumns = newSelectShowColumns.map((v) => currentAllColsToMap.value[v])
addFixedCol()
}
)
//追加固定列
const addFixedCol = () => {
TabMapDataSource[currentTab.value].showColumns.unshift({
title: '序号',
dataIndex: SERIAL_NUMBER,
customTitle: true,
isShowFliter: false
})
}
/**
* 选择表格数据相关
*/
const selectedRowKeys: ShallowRef<string[]> = shallowRef([])
const { selectedRaws: selectedMaterial, handleSelected, handleSelectAll } = useSelectedRows<MaterialData>(data)
const initialSelectedRowKeys = () => {
selectedRowKeys.value = []
selectedMaterial.value = []
tableRef.value.clearSelectedKeysCache()
}
const openStockInModal = () => {
Emiter('openStockInModal', selectedMaterial.value)
}
const openStockOutModal = () => {
Emiter('openStockOutModal', selectedMaterial.value)
}
/**
*
* 切换tab
*/
const changeTab = (item, type) => {
initialPresetPagination()
initialSelectedRowKeys()
Emiter('changeTab', { type, paginationInfo })
/**
* TODO
* 发送网络请求、刷新列表(可以在外部做)
*/
}
/**
* 分页相关
*/
let paginationInfo = reactive({
pageNum: 1,
pageSize: 10
})
const pagination = computed(() => {
const { pageNum, pageSize } = paginationInfo
return {
total: tableListData[currentTab.value].totalRecords,
showPageSize: true,
current: pageNum,
pageSize,
//页码改变时触发
onChange: (current) => {
paginationInfo.pageNum = current
Emiter('changePagination', { paginationInfo })
},
//数据条数改变时触发
onPageSizeChange: (pageSize) => {
paginationInfo.pageNum = 1
paginationInfo.pageSize = pageSize
Emiter('changePagination', { paginationInfo })
}
}
})
const initialPresetPagination = () => {
paginationInfo.pageNum = 1
paginationInfo.pageSize = 10
}
/**
* 附加信息的合理展示
*/
function showAdditionalFields(fieldArray, type) {
fieldArray = fieldArray || []
const array = fieldArray.map((field) => {
const name = field.fieldName
const values = customShowByColType(666, field.fieldType, field)
return `${name}:${values}`
})
return type === 'string' ? array.join('、') : array
}
/**
* 根据当前列的字段种类合理展示字段
*/
function customShowByColType(type: TableColsTypeEnum, paramType, data) {
//基础列,直接展示
if (type === TableColsTypeEnum.BASIC_BATCH || type === TableColsTypeEnum.BASIC_Product) {
return data
}
/**
* 自定义字段
*/
let paramValues = data?.paramValues
paramValues = _.isEmpty(paramValues) ? [] : paramValues
const filterValues = paramValues.map((v) => v.showName)
switch (paramType) {
//时间类型
case ParameterType.MOMENT: {
const showValues = filterValues.map((v) => moment(v).format('YYYY-MM-DD')).join('、')
return showValues
}
default: {
const showValues = filterValues.join('、')
return showValues
}
}
}
const isShowEmpty = (content) => {
return isEmpty(content)
}
/**
* 合理展示序号列
*/
function computedShowSerialNumber(num) {
const { pageNum, pageSize } = paginationInfo
const showNum = (pageNum - 1) * pageSize + num
return showNum
}
/**
* 切换 tab 后,更新滚动条位置
*/
watch(
() => currentTab.value,
() => {
refreshTableScroll()
}
)
function refreshTableScroll() {
nextTick(() => {
const tableBody = document.querySelector('.arco-table-body')
tableBody?.scroll({ left: 1, behavior: 'smooth' })
})
}
/**
* 判断是否展示 table 自带的 tooltip
*/
type Postion = 'left' | 'top' | 'tl' | 'tr' | 'bottom' | 'bl' | 'br' | 'right' | 'lt' | 'lb' | 'rt' | 'rb' | undefined
const toolTipPosition: Postion = 'left'
// const isShowTableToolTip = (col) => {
// // col.dataIndex !== 'productCustomParams' ? { position: 'bottom' } :false
// return col.dataIndex !== 'productCustomParams' && col.dataIndex !== 'batchCustomParams'
// ? { position: toolTipPosition, mini: true }
// : false
// }
/**
* 鼠标 hover 到库存信息列时 getStockInfo
*/
const {
loading: stockDetialLoading,
fetchResource: getStockDetialInfoFetchHook,
result: stockDetialRes
} = useFetch(getStockDetialInfo, {
isLazy: true
})
const stockDetialInfoArr = ref<string[]>()
//记录当前 hover 的库存信息 cell
const mouseenterStockInfoCellId = ref<string>()
const initMouseenterStockInfoCellId = debounce(() => {
if (showFlag == false) {
mouseenterStockInfoCellId.value = ''
}
}, 600)
//获取库位详情信息
const getStockInfo = debounce(async (record) => {
await getStockDetialInfoFetchHook(record.id)
updateStockDetialInfoArr(stockDetialRes.value.data)
mouseenterStockInfoCellId.value = record.id
}, 500)
// 停留展示Stock信息
let showFlag: boolean
const showStock = () => {
showFlag = true
}
const hideStock = () => {
showFlag = false
initMouseenterStockInfoCellId()
}
//构建展示库位详情信息的array
const updateStockDetialInfoArr = (data: StockDetialInfo) => {
const propNameMapPrefix = {
inStockNum: '在库数量:',
inStockAmount: '在库总量:',
totalNum: '入库数量:',
totalAmount: '入库总量:'
}
const detialItems = Object.entries(propNameMapPrefix).map(([key, prefix]) => `${prefix}${data[key] || 0}`)
stockDetialInfoArr.value = detialItems
}
/**
* 暴露给外部的state
*/
const initTabMapDataSource = () => {
for (const key in TabMapDataSource) {
TabMapDataSource[key].showColumns = []
TabMapDataSource[key].selectShowColumns = []
}
}
const clearCacheData = () => {
initTabMapDataSource()
}
const showCols = computed(() => {
return {
productShowCols: toRaw(TabMapDataSource[TabsEnum.REGISTER].showColumns),
batchShowCols: toRaw(TabMapDataSource[TabsEnum.BATCH].showColumns)
}
})
const allCols = computed(() => {
return {
productShowCols: toRaw(tableListData[TabsEnum.REGISTER].allColumns),
batchShowCols: toRaw(tableListData[TabsEnum.BATCH].allColumns)
}
})
defineExpose({
selectedRowKeys,
showCols,
allCols,
clearCacheData,
currentAllCols,
//分页相关
paginationInfo,
initialPresetPagination,
//初始化选择项
initialSelectedRowKeys
})
</script>
<style scoped lang="scss">
.table-list-wrapper {
margin-top: 25px;
background-color: #fff;
.tabs-bar {
margin: 16px 0px 8px 0px;
display: flex;
.tab-btn {
width: 142px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
border-radius: 32px;
}
.tab-active {
color: #3358ff;
background-color: #f2f3f5;
}
}
.table-wrapper {
position: relative;
.editor-show-columns-btn {
position: absolute;
top: 0px;
right: 0px;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
width: 40px;
height: 40px;
font-size: 15px;
border: 1px solid #e5e6eb;
background-color: #f2f3f5;
}
}
}
.tool-tip-content-item {
margin: 2px 0px;
}
.col-stock-detial-title {
font-size: 15px;
}
.col-stock-detial-item {
font-size: 13px;
}
.pointer {
cursor: pointer;
}
.arco-tag.arco-tag-size-medium.arco-tag-checked {
display: inline-block;
max-width: 100%;
span {
width: 100%;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>
<style lang="scss">
.tool-tip-content {
display: flex;
flex-direction: column;
}
</style>