Files
zkxw/web-admin/src/views/system/unit/index.vue
T
2026-05-26 19:04:27 +08:00

374 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 物品单位管理 -->
<!-- eslint-disable vue/no-v-model-argument -->
<template>
<div class="page-container">
<header class="page-head">
<h1>单位管理</h1>
<p class="page-desc">统一维护物品计量单位与排序规则。</p>
</header>
<section class="panel">
<div class="panel-top">
<h2>单位列表</h2>
</div>
<div class="filter-block">
<el-form :model="searchForm" class="filter-form" @submit.prevent>
<div class="filter-grid">
<el-form-item label="关键词">
<el-input v-model="searchForm.keyword" placeholder="单位名称/编码" clearable />
</el-form-item>
</div>
<div class="filter-actions-row">
<span class="filter-hint">按名称、编码模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
</div>
<div class="list-toolbar">
<div class="list-toolbar-row">
<div class="list-toolbar-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-button class="btn-main" type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增单位
</el-button>
<el-button
class="btn-ghost"
type="danger"
:disabled="selectedRows.length === 0"
@click="handleBatchDelete"
>
批量删除
</el-button>
</div>
</div>
<div class="list-body list-wrap">
<el-table
class="list-table"
:data="tableData"
v-loading="loading"
stripe
row-key="id"
@selection-change="handleSelectionChange"
@row-dblclick="handleView"
>
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
<el-table-column
type="index"
label="序号"
min-width="68"
align="center"
header-align="center"
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
/>
<el-table-column
prop="unitName"
label="单位名称"
min-width="150"
align="center"
header-align="center"
/>
<el-table-column
prop="unitCode"
label="单位编码"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="createTime"
label="创建时间"
min-width="180"
align="center"
header-align="center"
/>
<el-table-column
label="操作"
min-width="320"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"
><el-icon><View /></el-icon>查看</el-button
>
<el-button class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination list-pager-bar">
<el-pagination
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
/>
</div>
</div>
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="560px"
class="dialog-form-layout"
align-center
destroy-on-close
:close-on-click-modal="false"
>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
class="unit-dialog-form"
scroll-to-error
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
>
<div class="form-grid-2">
<el-form-item label="单位名称" prop="unitName">
<el-input v-model="formData.unitName" placeholder="如:斤、kg、个" />
</el-form-item>
<el-form-item label="单位编码" prop="unitCode">
<el-input v-model="formData.unitCode" placeholder="如:jin、kg、ge" />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="formData.remark" placeholder="可选" />
</el-form-item>
</div>
</el-form>
<template #footer>
<el-button class="btn-ghost" @click="dialogVisible = false">
<el-icon><Close /></el-icon>
取消
</el-button>
<el-button class="btn-main" type="primary" @click="handleSubmit" :loading="submitLoading">
<el-icon><Check /></el-icon>
确定
</el-button>
</template>
</el-dialog>
<SystemViewDialog
v-model:visible="viewVisible"
:title="viewRow?.unitName || '单位详情'"
:icon="ScaleToOriginal"
:meta="viewRow?.createTime || ''"
:sections="viewSections"
/>
</section>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
Plus,
Close,
Check,
View,
ScaleToOriginal,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
import {
fetchItemUnitList,
fetchCreateItemUnit,
fetchUpdateItemUnit,
fetchDeleteItemUnit
} from '@/api/admin'
defineOptions({ name: 'SystemItemUnit' })
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
const tableData = ref<Api.ItemUnit.ItemUnitItem[]>([])
const selectedRows = ref<Api.ItemUnit.ItemUnitItem[]>([])
const loading = ref(false)
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
const dialogVisible = ref(false)
const dialogTitle = ref('新增单位')
const isEdit = ref(false)
const submitLoading = ref(false)
const formRef = ref()
const editingId = ref<string | null>(null)
const viewVisible = ref(false)
const viewRow = ref<Api.ItemUnit.ItemUnitItem | null>(null)
const formData = reactive({
unitName: '',
unitCode: '',
orderNum: 0,
remark: ''
})
const formRules = {
unitName: [{ required: true, message: '请输入单位名称', trigger: 'blur' }],
unitCode: [{ required: true, message: '请输入单位编码', trigger: 'blur' }]
}
const handleSelectionChange = (rows: Api.ItemUnit.ItemUnitItem[]) => {
selectedRows.value = rows
}
const viewSections = computed(() => {
if (!viewRow.value) return []
const row = viewRow.value
return [
{
title: '基本信息',
fields: [
{ label: '单位名称', value: row.unitName },
{ label: '单位编码', value: row.unitCode },
{ label: '备注', value: row.remark, span: true }
]
}
]
})
async function loadData() {
loading.value = true
try {
const res = await fetchItemUnitList({
page: pagination.page,
pageSize: pagination.pageSize,
keyword: searchForm.keyword || undefined
})
tableData.value = res.list || []
pagination.total = res.total ?? 0
} finally {
loading.value = false
}
}
function handleSearch() {
pagination.page = 1
loadData()
}
function handleReset() {
searchForm.keyword = ''
pagination.page = 1
loadData()
}
function resetForm() {
formData.unitName = ''
formData.unitCode = ''
formData.orderNum = 0
formData.remark = ''
editingId.value = null
}
function handleAdd() {
isEdit.value = false
dialogTitle.value = '新增单位'
resetForm()
dialogVisible.value = true
formRef.value?.clearValidate?.()
}
function handleEdit(row: Api.ItemUnit.ItemUnitItem) {
isEdit.value = true
dialogTitle.value = '编辑单位'
editingId.value = row.id
formData.unitName = row.unitName || ''
formData.unitCode = row.unitCode || ''
formData.orderNum = row.orderNum ?? 0
formData.remark = row.remark || ''
dialogVisible.value = true
formRef.value?.clearValidate?.()
}
async function handleSubmit() {
await formRef.value?.validate?.()
submitLoading.value = true
try {
const payload = {
unitName: formData.unitName.trim(),
unitCode: formData.unitCode.trim(),
orderNum: formData.orderNum,
remark: formData.remark?.trim() || undefined
}
if (isEdit.value && editingId.value) {
await fetchUpdateItemUnit(editingId.value, payload)
} else {
await fetchCreateItemUnit(payload)
}
ElMessage.success(isEdit.value ? '更新成功' : '创建成功')
dialogVisible.value = false
await loadData()
} catch {
/* 校验或接口错误已由全局处理 */
} finally {
submitLoading.value = false
}
}
function handleView(row: Api.ItemUnit.ItemUnitItem) {
viewRow.value = row
viewVisible.value = true
}
async function handleDelete(row: Api.ItemUnit.ItemUnitItem) {
await ElMessageBox.confirm('确定要删除该单位吗?', '提示', { type: 'warning' })
await fetchDeleteItemUnit(row.id)
ElMessage.success('删除成功')
await loadData()
}
async function handleBatchDelete() {
const ids = selectedRows.value.map((r) => r.id)
if (!ids.length) return
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个单位吗?`, '提示', {
type: 'warning'
})
await withFullscreenLoading(async () => {
for (const id of ids) {
await fetchDeleteItemUnit(id)
}
ElMessage.success('批量删除成功')
selectedRows.value = []
await loadData()
}, fullscreenLoadingText.batchDelete)
}
// 输入检索条件时自动搜索(防抖 300ms)
watchDebounced(
searchForm,
() => {
pagination.page = 1
loadData()
},
{ debounce: 300, deep: true }
)
onMounted(() => {
loadData()
})
</script>
<style scoped lang="scss">
.unit-dialog-form {
:deep(.el-form-item) {
margin-bottom: 0;
}
}
</style>