设备总包项目管理剩余页面
This commit is contained in:
162
ruoyi-ui/src/views/rm/installPrep/tools.vue
Normal file
162
ruoyi-ui/src/views/rm/installPrep/tools.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Stats -->
|
||||
<div class="dashboard-grid">
|
||||
<div class="stat-card"><div class="label">工具总项数</div><div class="value">{{ tools.length }}</div><div class="sub">{{ groupKeys.length }} 个分类</div></div>
|
||||
<div class="stat-card green"><div class="label">工具总金额</div><div class="value">¥{{ totalAmount }}</div><div class="sub">预估采购总价</div></div>
|
||||
<div class="stat-card orange"><div class="label">关键工具(★★)</div><div class="value">{{ criticalCount }}</div><div class="sub">必须到位</div></div>
|
||||
<div class="stat-card"><div class="label">已到位</div><div class="value">{{ arrivedCount }}/{{ tools.length }}</div><div class="sub">项</div></div>
|
||||
</div>
|
||||
<div style="margin-bottom:12px;">
|
||||
<el-button size="mini" type="primary" @click="handleAdd">+ 添加工具</el-button>
|
||||
</div>
|
||||
|
||||
<!-- Grouped sections -->
|
||||
<div v-if="tools.length === 0" style="text-align:center;color:#aaa;padding:40px;">暂无工具数据</div>
|
||||
<div v-for="(grp, cat) in grouped" :key="cat" class="cat-section">
|
||||
<div class="cat-header">
|
||||
<span>{{ catIcon(cat) }} {{ cat }}</span>
|
||||
<span class="cat-count">{{ grp.length }}项 · ¥{{ groupTotal(grp).toLocaleString() }}</span>
|
||||
</div>
|
||||
<el-table :data="grp" stripe border size="small" style="width:100%;">
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column prop="name" label="工具名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="spec" label="规格型号" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="qty" label="数量" width="50" />
|
||||
<el-table-column prop="unit" label="单位" width="50" />
|
||||
<el-table-column prop="unitPrice" label="单价" width="80" align="right" />
|
||||
<el-table-column prop="totalPrice" label="总价" width="90" align="right" />
|
||||
<el-table-column label="重要" width="65" align="center">
|
||||
<template slot-scope="s">
|
||||
<el-tag v-if="s.row.priority==='★★'" size="mini" type="danger">关键</el-tag>
|
||||
<el-tag v-else-if="s.row.priority==='★'" size="mini" type="warning">重要</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="purpose" label="用途" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="responsible" label="责任人" width="70" />
|
||||
<el-table-column label="状态" width="70" align="center">
|
||||
<template slot-scope="s">
|
||||
<el-tag :type="s.row.status==='已到位'?'success':s.row.status==='已确认'?'':'info'" size="mini">{{ s.row.status||'待确认' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" fixed="right">
|
||||
<template slot-scope="s">
|
||||
<el-button type="text" size="mini" @click="handleEdit(s.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click="handleDelete(s.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- Dialog -->
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px" append-to-body @closed="onClosed">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="0" size="small">
|
||||
<div class="form-row">
|
||||
<div class="form-group" style="flex:1;"><label>工具名称</label><el-input v-model="form.name" /></div>
|
||||
<div class="form-group" style="flex:0 0 140px;"><label>分类</label><el-select v-model="form.category" style="width:100%;"><el-option v-for="c in categories" :key="c" :label="c" :value="c" /></el-select></div>
|
||||
</div>
|
||||
<div class="form-group"><label>英文名称</label><el-input v-model="form.nameEn" /></div>
|
||||
<div class="form-row">
|
||||
<div class="form-group" style="flex:1;"><label>规格型号</label><el-input v-model="form.spec" /></div>
|
||||
<div class="form-group" style="flex:0 0 70px;"><label>数量</label><el-input v-model="form.qty" /></div>
|
||||
<div class="form-group" style="flex:0 0 70px;"><label>单位</label><el-input v-model="form.unit" /></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>单价(元)</label><el-input v-model="form.unitPrice" @input="autoCalcTotal" /></div>
|
||||
<div class="form-group"><label>总价(元)</label><el-input v-model="form.totalPrice" /></div>
|
||||
<div class="form-group"><label>重要程度</label><el-select v-model="form.priority" style="width:100%;" clearable><el-option label="普通" value="" /><el-option label="★ 重要" value="★" /><el-option label="★★ 关键" value="★★" /></el-select></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>到位日期</label><el-date-picker v-model="form.arrivalDate" type="date" value-format="yyyy-MM-dd" style="width:100%;" /></div>
|
||||
<div class="form-group"><label>责任人</label><el-input v-model="form.responsible" /></div>
|
||||
</div>
|
||||
<div class="form-group"><label>主要用途</label><el-input v-model="form.purpose" /></div>
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>状态</label><el-select v-model="form.status" style="width:100%;"><el-option label="待确认" value="待确认" /><el-option label="已确认" value="已确认" /><el-option label="已到位" value="已到位" /><el-option label="已取消" value="已取消" /></el-select></div>
|
||||
<div class="form-group"><label>备注</label><el-input v-model="form.remark" /></div>
|
||||
</div>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button size="small" @click="dialogVisible=false">取消</el-button>
|
||||
<el-button size="small" type="primary" @click="save">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listInstallToolAll, addInstallTool, updateInstallTool, delInstallTool } from '@/api/rm/installTool'
|
||||
|
||||
export default {
|
||||
name: 'InstallTools',
|
||||
props: { projectId: { type: [Number, String], default: null } },
|
||||
watch: { projectId: { immediate: true, handler(v) { if (v) this.loadData() } } },
|
||||
data() {
|
||||
return {
|
||||
tools: [],
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
form: this.cleanForm(),
|
||||
rules: { name: [{ required: true, message: '请填写工具名称', trigger: 'blur' }] },
|
||||
categories: ['起重吊装','测量仪器','机械安装','液压专用','电气安装','其他']
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
grouped() {
|
||||
const map = {}
|
||||
this.tools.forEach(t => { const c = t.category||'其他'; if (!map[c]) map[c]=[]; map[c].push(t) })
|
||||
return map
|
||||
},
|
||||
groupKeys() { return Object.keys(this.grouped) },
|
||||
totalAmount() { return this.tools.reduce((s,t) => s+(parseFloat(t.totalPrice)||0), 0).toLocaleString() },
|
||||
criticalCount() { return this.tools.filter(t => t.priority==='★★').length },
|
||||
arrivedCount() { return this.tools.filter(t => t.status==='已到位').length }
|
||||
},
|
||||
methods: {
|
||||
catIcon(cat) { return { '起重吊装':'🏗️','测量仪器':'📐','机械安装':'🔩','液压专用':'💧','电气安装':'⚡' }[cat]||'📌' },
|
||||
groupTotal(arr) { return arr.reduce((s,t) => s+(parseFloat(t.totalPrice)||0), 0) },
|
||||
cleanForm() { return { name:'', nameEn:'', spec:'', qty:'', unit:'台', unitPrice:'', totalPrice:'', priority:'', arrivalDate:'', purpose:'', responsible:'', status:'待确认', category:'起重吊装', remark:'' } },
|
||||
loadData() {
|
||||
if (!this.projectId) return
|
||||
listInstallToolAll({ projectId: this.projectId }).then(res => { this.tools = res.data || [] })
|
||||
},
|
||||
handleAdd() { this.dialogTitle='添加工具'; this.form=this.cleanForm(); this.dialogVisible=true },
|
||||
handleEdit(row) { this.dialogTitle='编辑工具'; this.form={...row, arrivalDate: row.arrivalDate||''}; this.dialogVisible=true },
|
||||
handleDelete(row) {
|
||||
this.$confirm('确认删除?','提示',{type:'warning'}).then(() => {
|
||||
delInstallTool(row.toolId).then(() => { this.loadData() })
|
||||
}).catch(() => {})
|
||||
},
|
||||
autoCalcTotal() {
|
||||
const qty = parseFloat(this.form.qty)||0
|
||||
const price = parseFloat(this.form.unitPrice)||0
|
||||
if (qty && price) this.form.totalPrice = (qty * price).toString()
|
||||
},
|
||||
save() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (!valid) return
|
||||
const data = { ...this.form, projectId: this.projectId }
|
||||
const act = data.toolId ? updateInstallTool(data) : addInstallTool(data)
|
||||
act.then(() => { this.dialogVisible=false; this.loadData() })
|
||||
})
|
||||
},
|
||||
onClosed() { this.$refs.form?.clearValidate() }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dashboard-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 8px; margin-bottom: 12px; }
|
||||
.stat-card { background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; padding: 10px; text-align: center; }
|
||||
.stat-card .label { font-size: 11px; color: #6c757d; }
|
||||
.stat-card .value { font-size: 20px; font-weight: 700; color: #1a5a9e; }
|
||||
.stat-card.green .value { color: #28a745; }
|
||||
.stat-card.orange .value { color: #e67e22; }
|
||||
.cat-section { margin-bottom: 12px; border: 1px solid #e9ecef; border-radius: 6px; overflow: hidden; }
|
||||
.cat-header { padding: 6px 10px; background: #f8f9fa; font-size: 13px; font-weight: 600; display: flex; justify-content: space-between; border-bottom: 1px solid #e9ecef; }
|
||||
.cat-count { font-size: 11px; color: #6c757d; font-weight: 400; }
|
||||
.form-group { margin-bottom: 6px; }
|
||||
.form-group label { display: block; font-size: 12px; color: #555; margin-bottom: 3px; font-weight: 500; }
|
||||
.form-row { display: flex; gap: 10px; }
|
||||
.form-row .form-group { flex: 1; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user