| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- <template>
- <el-drawer
- :append-to-body="true"
- :model-value="modelValue"
- :show-close="false"
- direction="rtl"
- :size="computedSize"
- class="selected-material-drawer"
- @update:model-value="emit('update:modelValue', $event)">
- <template #header>
- <div class="drawer-header">
- <div class="drawer-header__main">
- <div class="drawer-header__icon">
- <Icon icon="ep:goods" :size="22" />
- </div>
- <div>
- <div class="drawer-title">{{ t('bomList.materialDetail') }}</div>
- <div class="drawer-subtitle">查看当前维修项目关联的物料明细</div>
- </div>
- </div>
- <el-button circle @click="handleClose">
- <Icon icon="ep:close" />
- </el-button>
- </div>
- </template>
- <div class="drawer-body">
- <section class="material-section">
- <div class="section-header">
- <div class="section-title">
- <span class="section-marker"></span>
- <span>关联物料</span>
- </div>
- <span class="material-total">共 {{ filteredMaterials.length }} 条</span>
- </div>
- <div class="table-container">
- <ZmTable
- :data="filteredMaterials"
- :loading="loading"
- :show-border="true"
- settings-cache-key="pms-maintain-selected-material">
- <ZmTableColumn
- v-if="!hideExtraColumns"
- prop="factory"
- :label="t('workOrderMaterial.factory')"
- min-width="140" />
- <ZmTableColumn
- v-if="!hideExtraColumns"
- prop="costCenter"
- :label="t('workOrderMaterial.costCenter')"
- min-width="150" />
- <ZmTableColumn
- v-if="!hideExtraColumns"
- prop="projectDepartment"
- :label="t('workOrderMaterial.storageLocation')"
- min-width="150" />
- <ZmTableColumn
- prop="materialName"
- :label="t('workOrderMaterial.materialName')"
- min-width="180" />
- <ZmTableColumn
- prop="materialCode"
- :label="t('workOrderMaterial.materialCode')"
- min-width="150" />
- <ZmTableColumn prop="unit" :label="t('workOrderMaterial.unit')" width="100" />
- <ZmTableColumn
- prop="unitPrice"
- :label="t('workOrderMaterial.unitPrice')"
- min-width="120" />
- <ZmTableColumn
- prop="quantity"
- :label="t('workOrderMaterial.ConsumptionQuantity')"
- min-width="130" />
- <ZmTableColumn prop="materialSource" :label="t('bomList.type')" min-width="120" />
- <ZmTableColumn
- v-if="!detail"
- :label="t('workplace.operation')"
- width="100"
- fixed="right"
- action>
- <template #default="{ row }">
- <el-button link type="danger" @click="handleDelete(row)">
- <Icon icon="ep:delete" class="mr-4px" />{{ t('form.delete') }}
- </el-button>
- </template>
- </ZmTableColumn>
- </ZmTable>
- </div>
- </section>
- </div>
- <template #footer>
- <div class="drawer-footer">
- <el-button @click="handleClose">关闭</el-button>
- </div>
- </template>
- </el-drawer>
- </template>
- <script setup lang="ts">
- import { useTableComponents } from '@/components/ZmTable/useTableComponents'
- interface MaterialRow {
- id?: number
- bomNodeId?: number | string
- factory?: string
- costCenter?: string
- projectDepartment?: string
- materialName?: string
- materialCode?: string
- unit?: string
- unitPrice?: number
- quantity?: number
- materialSource?: string
- }
- defineOptions({ name: 'SelectedMaterialDrawer' })
- const props = withDefaults(
- defineProps<{
- modelValue: boolean
- nodeId?: number | string
- detail?: boolean
- materials?: MaterialRow[]
- hideExtraColumns?: boolean
- }>(),
- {
- detail: false,
- materials: () => [],
- hideExtraColumns: false
- }
- )
- const emit = defineEmits<{
- (e: 'update:modelValue', value: boolean): void
- (e: 'add', row: MaterialRow): void
- (e: 'delete', row: MaterialRow): void
- }>()
- const { t } = useI18n()
- const message = useMessage()
- const { ZmTable, ZmTableColumn } = useTableComponents<MaterialRow>()
- const loading = ref(false)
- const windowWidth = ref(window.innerWidth)
- const computedSize = computed(() => {
- if (windowWidth.value <= 768) return '100%'
- return windowWidth.value > 1440 ? '68%' : '82%'
- })
- const filteredMaterials = computed(() => {
- if (!props.nodeId) return []
- return props.materials.filter((item) => item.bomNodeId === props.nodeId)
- })
- const handleDelete = async (row: MaterialRow) => {
- try {
- await message.delConfirm()
- emit('delete', row)
- } catch {}
- }
- const handleClose = () => {
- emit('update:modelValue', false)
- }
- const openDrawer = () => {
- emit('update:modelValue', true)
- }
- const closeDrawer = () => {
- handleClose()
- }
- const updateWindowWidth = () => {
- windowWidth.value = window.innerWidth
- }
- onMounted(() => window.addEventListener('resize', updateWindowWidth))
- onUnmounted(() => window.removeEventListener('resize', updateWindowWidth))
- defineExpose({ openDrawer, closeDrawer })
- </script>
- <style scoped>
- .drawer-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 16px;
- width: 100%;
- }
- .drawer-header__main {
- display: flex;
- align-items: center;
- min-width: 0;
- }
- .drawer-header__icon {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 44px;
- height: 44px;
- margin-right: 12px;
- color: var(--el-color-primary);
- background: var(--el-color-primary-light-9);
- border: 1px solid var(--el-color-primary-light-7);
- border-radius: 8px;
- }
- .drawer-title {
- font-size: 18px;
- font-weight: 600;
- color: var(--el-text-color-primary);
- }
- .drawer-subtitle {
- margin-top: 4px;
- font-size: 13px;
- color: var(--el-text-color-secondary);
- }
- .drawer-body {
- height: 100%;
- padding: 4px;
- }
- .material-section {
- height: 100%;
- overflow: hidden;
- background: var(--el-bg-color);
- border: 1px solid var(--el-border-color-lighter);
- border-radius: 8px;
- }
- .section-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- min-height: 54px;
- padding: 0 18px;
- background: var(--el-fill-color-extra-light);
- border-bottom: 1px solid var(--el-border-color-lighter);
- }
- .section-title {
- display: flex;
- align-items: center;
- font-size: 16px;
- font-weight: 600;
- color: var(--el-text-color-primary);
- }
- .section-marker {
- width: 4px;
- height: 18px;
- margin-right: 10px;
- background: var(--el-color-primary);
- border-radius: 2px;
- }
- .material-total {
- padding: 4px 10px;
- font-size: 12px;
- color: var(--el-color-primary);
- background: var(--el-color-primary-light-9);
- border-radius: 4px;
- }
- .table-container {
- padding: 16px;
- }
- .drawer-footer {
- display: flex;
- justify-content: flex-end;
- }
- @media (width <= 768px) {
- .drawer-subtitle {
- display: none;
- }
- .table-container {
- padding: 12px;
- }
- }
- </style>
|