mat/frontend/src/views/MaterialDetail.vue

325 lines
10 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.

<template>
<div class="material-detail">
<el-card v-loading="loading">
<template #header>
<div class="card-header">
<el-button link @click="handleBack">
<el-icon><ArrowLeft /></el-icon>
返回
</el-button>
<div class="header-actions">
<el-button v-if="canEdit" type="primary" @click="handleEdit">编辑</el-button>
<el-button v-if="canSubmit" type="warning" @click="handleSubmit">提交审核</el-button>
<el-button v-if="canApprove" type="success" @click="handleApprove">审核通过</el-button>
<el-button v-if="canReject" type="danger" @click="handleReject">审核拒绝</el-button>
<el-button v-if="canDelete" type="danger" @click="handleDelete">删除</el-button>
</div>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="材料名称">{{ material.name }}</el-descriptions-item>
<el-descriptions-item label="专业类别">{{ material.major_category_display }}</el-descriptions-item>
<el-descriptions-item label="材料分类">{{ material.material_category }}</el-descriptions-item>
<el-descriptions-item label="材料子类">{{ material.material_subcategory }}</el-descriptions-item>
<el-descriptions-item label="规格型号">{{ material.spec || '-' }}</el-descriptions-item>
<el-descriptions-item label="符合标准">{{ material.standard || '-' }}</el-descriptions-item>
<el-descriptions-item label="应用场景">{{ material.application_scene_display || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属品牌">{{ material.factory_name }}</el-descriptions-item>
<el-descriptions-item label="状态">
<el-tag :type="getStatusType(material.status)">
{{ material.status_display }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
<el-divider>应用场景说明</el-divider>
<div class="content-text">{{ material.application_desc || '暂无' }}</div>
<el-divider>替代材料信息</el-divider>
<el-descriptions :column="2" border>
<el-descriptions-item label="替代材料类型">{{ material.replace_type_display || '-' }}</el-descriptions-item>
<el-descriptions-item label="竞争优势">{{ material.advantage_display || '-' }}</el-descriptions-item>
</el-descriptions>
<div class="content-text">{{ material.advantage_desc || '暂无' }}</div>
<el-divider>成本信息</el-divider>
<el-descriptions :column="2" border>
<el-descriptions-item label="成本对比百分数">
{{ material.cost_compare ? `${material.cost_compare}%` : '-' }}
</el-descriptions-item>
</el-descriptions>
<div class="content-text">{{ material.cost_desc || '暂无' }}</div>
<el-divider>案例</el-divider>
<div class="content-text">{{ material.cases || '暂无' }}</div>
<el-divider>宣传页图片</el-divider>
<div v-if="material.brochure_url" class="brochure-container">
<el-image
:src="material.brochure_url"
fit="contain"
:preview-src-list="[material.brochure_url]"
style="max-width: 100%; max-height: 500px;"
/>
</div>
<div v-else class="content-text">暂无</div>
<el-divider>星级评价</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<div class="star-item">
<span class="star-label">质量提升等级:</span>
<el-rate v-model="material.quality_level" disabled :max="3" />
</div>
</el-col>
<el-col :span="8">
<div class="star-item">
<span class="star-label">耐久可靠等级:</span>
<el-rate v-model="material.durability_level" disabled :max="3" />
</div>
</el-col>
<el-col :span="8">
<div class="star-item">
<span class="star-label">环保健康等级:</span>
<el-rate v-model="material.eco_level" disabled :max="3" />
</div>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 20px;">
<el-col :span="8">
<div class="star-item">
<span class="star-label">循环低碳等级:</span>
<el-rate v-model="material.carbon_level" disabled :max="3" />
</div>
</el-col>
<el-col :span="8">
<div class="star-item">
<span class="star-label">总评分等级</span>
<el-rate v-model="material.score_level" disabled :max="3" />
</div>
</el-col>
</el-row>
<el-divider>施工与限制</el-divider>
<el-descriptions :column="2" border>
<el-descriptions-item label="连接方式">{{ material.connection_method || '-' }}</el-descriptions-item>
<el-descriptions-item label="施工工艺">{{ material.construction_method || '-' }}</el-descriptions-item>
</el-descriptions>
<div class="content-text">{{ material.limit_condition || '暂无' }}</div>
<el-divider>其他信息</el-divider>
<el-descriptions :column="2" border>
<el-descriptions-item label="创建时间">{{ formatDate(material.created_at) }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ formatDate(material.updated_at) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useUserStore } from '@/stores/user'
import { getMaterialDetail, deleteMaterial, submitMaterial, approveMaterial, rejectMaterial } from '@/api/material'
import { ElMessage, ElMessageBox } from 'element-plus'
const route = useRoute()
const router = useRouter()
const userStore = useUserStore()
const material = ref({})
const loading = ref(false)
const isAdmin = computed(() => userStore.isAdmin)
// 判断是否可以编辑
const canEdit = computed(() => {
if (isAdmin.value) return true
return material.value.status === 'draft' && userStore.factoryId === material.value.factory
})
// 判断是否可以提交
const canSubmit = computed(() => {
return material.value.status === 'draft' && (isAdmin.value || userStore.factoryId === material.value.factory)
})
// 判断是否可以审核
const canApprove = computed(() => {
return isAdmin.value && material.value.status === 'pending'
})
// 判断是否可以拒绝
const canReject = computed(() => {
return isAdmin.value && material.value.status === 'pending'
})
// 判断是否可以删除
const canDelete = computed(() => {
if (isAdmin.value) return true
return material.value.status === 'draft' && userStore.factoryId === material.value.factory
})
// 获取状态类型
const getStatusType = (status) => {
const statusMap = {
draft: 'info',
pending: 'warning',
approved: 'success'
}
return statusMap[status] || 'info'
}
// 格式化日期
const formatDate = (dateStr) => {
if (!dateStr) return '-'
const date = new Date(dateStr)
return date.toLocaleString('zh-CN')
}
// 加载数据
const loadData = async () => {
loading.value = true
try {
const id = route.params.id
material.value = await getMaterialDetail(id)
} catch (error) {
console.error('加载数据失败:', error)
ElMessage.error('加载数据失败')
} finally {
loading.value = false
}
}
// 返回
const handleBack = () => {
router.back()
}
// 编辑
const handleEdit = () => {
router.push(`/materials/${material.value.id}/edit`)
}
// 提交
const handleSubmit = async () => {
try {
await ElMessageBox.confirm('确认提交该材料进行审核吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
await submitMaterial(material.value.id)
ElMessage.success('提交成功')
loadData()
} catch (error) {
if (error !== 'cancel') {
console.error('提交失败:', error)
ElMessage.error('提交失败')
}
}
}
// 审核通过
const handleApprove = async () => {
try {
await ElMessageBox.confirm('确认审核通过该材料吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
await approveMaterial(material.value.id)
ElMessage.success('审核通过')
loadData()
} catch (error) {
if (error !== 'cancel') {
console.error('审核失败:', error)
ElMessage.error('审核失败')
}
}
}
// 审核拒绝
const handleReject = async () => {
try {
await ElMessageBox.confirm('确认拒绝该材料吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
await rejectMaterial(material.value.id)
ElMessage.success('已拒绝')
loadData()
} catch (error) {
if (error !== 'cancel') {
console.error('操作失败:', error)
ElMessage.error('操作失败')
}
}
}
// 删除
const handleDelete = async () => {
try {
await ElMessageBox.confirm('确认删除该材料吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
await deleteMaterial(material.value.id)
ElMessage.success('删除成功')
router.push('/materials')
} catch (error) {
if (error !== 'cancel') {
console.error('删除失败:', error)
ElMessage.error('删除失败')
}
}
}
onMounted(() => {
loadData()
})
</script>
<style lang="scss" scoped>
.material-detail {
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
.header-actions {
display: flex;
gap: 10px;
}
}
.content-text {
padding: 10px 0;
line-height: 1.8;
white-space: pre-wrap;
}
.brochure-container {
display: flex;
justify-content: center;
padding: 20px 0;
}
.star-item {
display: flex;
align-items: center;
.star-label {
margin-right: 10px;
color: #606266;
}
}
}
</style>