263 lines
8.2 KiB
Vue
263 lines
8.2 KiB
Vue
<script setup>
|
||
import { ref, computed, onMounted } from "vue"
|
||
import { getCurrentInstance } from "vue"
|
||
import { ElMessage, ElMessageBox } from "element-plus"
|
||
|
||
const { $http } = getCurrentInstance().appContext.config.globalProperties
|
||
|
||
const isAdmin = localStorage.getItem('role') === 'admin'
|
||
|
||
function formatDate(date) {
|
||
if (!date) return "-"
|
||
const d = new Date(date)
|
||
const y = d.getFullYear()
|
||
const m = String(d.getMonth() + 1).padStart(2, "0")
|
||
const day = String(d.getDate()).padStart(2, "0")
|
||
return `${y}-${m}-${day}`
|
||
}
|
||
|
||
const data = ref([])
|
||
const dialogVisible = ref(false)
|
||
const editing = ref(false)
|
||
const form = ref({
|
||
batch: "",
|
||
im: "",
|
||
ass: "",
|
||
calibration_date: "",
|
||
expire_date: "",
|
||
location: "",
|
||
})
|
||
|
||
// 有效期筛查(天数,0=全部)
|
||
const filterDays = ref(0)
|
||
const filteredData = computed(() => {
|
||
if (!filterDays.value || filterDays.value <= 0) return data.value
|
||
const now = new Date()
|
||
const limit = new Date(now.getTime() + filterDays.value * 86400000)
|
||
return data.value.filter((item) => {
|
||
if (!item.expire_date) return false
|
||
const expire = new Date(item.expire_date)
|
||
return expire >= now && expire <= limit
|
||
})
|
||
})
|
||
|
||
function rowClass({ row }) {
|
||
if (!row.expire_date) return ""
|
||
const today = new Date()
|
||
today.setHours(0, 0, 0, 0)
|
||
const expire = new Date(row.expire_date)
|
||
expire.setHours(0, 0, 0, 0)
|
||
return expire < today ? "row-expired" : ""
|
||
}
|
||
|
||
function rowStyle({ row }) {
|
||
if (!row.expire_date) return {}
|
||
const today = new Date()
|
||
today.setHours(0, 0, 0, 0)
|
||
const expire = new Date(row.expire_date)
|
||
expire.setHours(0, 0, 0, 0)
|
||
if (expire < today) {
|
||
return { color: "#dc2626" }
|
||
}
|
||
return {}
|
||
}
|
||
|
||
async function refresh() {
|
||
try {
|
||
const res = await $http.get("/standard")
|
||
data.value = res.data || []
|
||
} catch {
|
||
data.value = []
|
||
}
|
||
}
|
||
|
||
function openCreate() {
|
||
editing.value = false
|
||
form.value = { batch: "", im: "", ass: "", calibration_date: "", expire_date: "", location: "" }
|
||
dialogVisible.value = true
|
||
}
|
||
|
||
function openEdit(row) {
|
||
editing.value = true
|
||
form.value = { ...row }
|
||
dialogVisible.value = true
|
||
}
|
||
|
||
async function save() {
|
||
if (!form.value.batch) {
|
||
ElMessage.error("批号不能为空")
|
||
return
|
||
}
|
||
try {
|
||
if (editing.value) {
|
||
await $http.patch(`/standard/${form.value._id}`, form.value)
|
||
ElMessage.success("更新成功")
|
||
} else {
|
||
await $http.post("/standard", form.value)
|
||
ElMessage.success("创建成功")
|
||
}
|
||
dialogVisible.value = false
|
||
await refresh()
|
||
} catch (error) {
|
||
ElMessage.error(error.response?.data?.message || "操作失败")
|
||
}
|
||
}
|
||
|
||
async function remove(row) {
|
||
try {
|
||
await ElMessageBox.confirm(`确定要删除批号为"${row.batch}"的对照品吗?`, "确认删除", {
|
||
confirmButtonText: "确定",
|
||
cancelButtonText: "取消",
|
||
type: "warning",
|
||
})
|
||
await $http.delete(`/standard/${row._id}`)
|
||
ElMessage.success("删除成功")
|
||
await refresh()
|
||
} catch {
|
||
// cancelled
|
||
}
|
||
}
|
||
|
||
onMounted(refresh)
|
||
</script>
|
||
|
||
<template>
|
||
<div class="page-container">
|
||
<div class="actions-bar">
|
||
<div class="actions-left">
|
||
<el-button @click="refresh">刷新</el-button>
|
||
<el-button type="primary" @click="openCreate">新增对照品</el-button>
|
||
</div>
|
||
<div class="actions-right">
|
||
<span class="filter-label">有效期</span>
|
||
<el-input-number v-model="filterDays" :min="0" :max="365" :step="7" size="small"
|
||
controls-position="right" style="width: 100px" />
|
||
<span class="filter-unit">天内到期</span>
|
||
<el-tag v-if="filterDays > 0" type="warning" size="small" effect="plain">
|
||
显示 {{ filteredData.length }} 条
|
||
</el-tag>
|
||
<el-button v-if="filterDays > 0" size="small" text type="info" @click="filterDays = 0">
|
||
清除
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<el-table :data="filteredData" stripe border style="width: 100%" :row-class-name="rowClass"
|
||
:row-style="rowStyle">
|
||
<el-table-column prop="batch" label="批号" min-width="180" />
|
||
<el-table-column prop="im" label="含量(%)" width="100" />
|
||
<el-table-column prop="ass" label="纯度(%)" width="100" />
|
||
<el-table-column prop="calibration_date" label="标定日期" width="120">
|
||
<template #default="{ row }">
|
||
{{ formatDate(row.calibration_date) }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="expire_date" label="有效期" width="120">
|
||
<template #default="{ row }">
|
||
{{ formatDate(row.expire_date) }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="location" label="存放位置" min-width="140" />
|
||
<el-table-column label="操作" width="180" fixed="right">
|
||
<template #default="{ row }">
|
||
<el-button size="small" @click="openEdit(row)">编辑</el-button>
|
||
<el-button size="small" type="danger" :disabled="!isAdmin" @click="remove(row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<el-dialog v-model="dialogVisible" :title="editing ? '编辑对照品' : '新增对照品'" width="520px" align-center>
|
||
<el-form :model="form" label-position="top">
|
||
<el-form-item label="批号" required>
|
||
<el-input v-model="form.batch" />
|
||
</el-form-item>
|
||
<el-row :gutter="16">
|
||
<el-col :span="12">
|
||
<el-form-item label="含量(%)">
|
||
<el-input v-model="form.im" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="纯度(%)">
|
||
<el-input v-model="form.ass" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="16">
|
||
<el-col :span="12">
|
||
<el-form-item label="标定日期">
|
||
<el-date-picker v-model="form.calibration_date" type="date" style="width: 100%"
|
||
value-format="YYYY-MM-DD" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="有效期">
|
||
<el-date-picker v-model="form.expire_date" type="date" style="width: 100%"
|
||
value-format="YYYY-MM-DD" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-form-item label="存放位置">
|
||
<el-input v-model="form.location" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="dialogVisible = false">取消</el-button>
|
||
<el-button type="primary" @click="save">保存</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.page-container {
|
||
padding: 24px;
|
||
}
|
||
|
||
.actions-bar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 16px;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
}
|
||
|
||
.actions-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.actions-right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
|
||
.filter-label {
|
||
font-size: 13px;
|
||
color: #8896a8;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.filter-unit {
|
||
font-size: 13px;
|
||
color: #3d4a5c;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* 过期行文字红色 */
|
||
:deep(.el-table .row-expired) {
|
||
color: #dc2626 !important;
|
||
font-weight: 500;
|
||
}
|
||
|
||
:deep(.row-expired:hover) {
|
||
background-color: #fee2e2 !important;
|
||
}
|
||
|
||
:deep(.row-expired .el-table__cell) {
|
||
color: #dc2626;
|
||
}
|
||
</style> |