装备类型管理

This commit is contained in:
jiang 2025-08-12 18:52:05 +08:00
parent 4dccab085b
commit 0ecafb4654
9 changed files with 2407 additions and 1338 deletions

View File

@ -16,6 +16,14 @@ export function getMaTypeList(query) {
params: query,
});
}
export function getList(query) {
return request({
url: "/material-mall/type/getList",
method: "get",
params: query,
});
}
//机具类型-详情
export function getMaType(typeId) {
@ -33,6 +41,21 @@ export function addMaType(data) {
data: data,
});
}
export function addProperties(data) {
return request({
url: "/material-mall/type/addProperties",
method: "post",
data: data,
});
}
export function updateProperties(data) {
return request({
url: "/material-mall/type/updateProperties",
method: "post",
data: data,
});
}
// 机具类型--修改
export function updateMaType(data) {
return request({

View File

@ -0,0 +1,218 @@
<template>
<el-dialog :modal-append-to-body="false" :visible.sync="dialogVisible" title="新增" width="70%" @close="handleClose"
:close-on-click-modal="false"
>
<!-- 基础信息 -->
<el-divider content-position="left">基础信息</el-divider>
<el-form :model="form" :rules="rules" ref="form" label-width="120px">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="所属专业" prop="major">
<el-input v-model="form.major" disabled/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="主工序" prop="mainProcedure">
<el-input v-model="form.mainProcedure" disabled/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="子工序" prop="subProcedure">
<el-input v-model="form.subProcedure" disabled/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="form.deviceName"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="计量单位" prop="unit">
<el-input v-model="form.unit"/>
</el-form-item>
</el-col>
</el-row>
<!-- 特征值信息 -->
<el-row type="flex" align="middle">
<el-col :span="22">
<el-divider content-position="left">特征值信息</el-divider>
</el-col>
<el-col :span="2" style="text-align: right;">
<el-button type="primary" size="mini" @click="addFeature">新增特征项</el-button>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-bottom: 10px">
<el-col
v-for="(item, index) in form.features"
:key="index"
:span="8"
>
<el-form-item
style="margin: unset"
:label="item.featureName"
:prop="`features.${index}.value`"
required
:rules="[{ required: true, message: `请输入${item.featureName}`, trigger: ['blur', 'change'] }]"
>
<!-- 普通输入框 -->
<el-input
v-if="item.inputType === 'input'"
v-model="item.value"
>
<template #suffix>
<i
class="el-icon-delete"
@click="removeFeature(index)"
style="font-size: 16px; color: red;"
></i>
</template>
</el-input>
<!-- 可输入下拉 -->
<InputSelect
:label="item.featureName"
v-else-if="item.inputType === 'select'"
v-model="item.value"
@update:modelValue="item.value = $event"
:optionsList="item.options"
@update:optionsList="item.options = $event"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 底部按钮 -->
<template #footer>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="submit">确定</el-button>
</template>
<Feature :visible.sync="featureOpen" @submit-success="handleSubmitSuccess"/>
</el-dialog>
</template>
<script>
import InputSelect from '@/views/lessor/equipment/equipType/child/inputSelect.vue'
import Feature from '@/views/lessor/equipment/equipType/child/feature.vue'
import { addProperties } from '@/api/lessor/equipType'
export default {
name: 'AddDeviceDialog',
components: { Feature, InputSelect },
props: {
visible: {
type: Boolean,
default: false
},
parentNode: {
type: Object,
default: () => ({})
}
},
data() {
return {
featureOpen: false,
form: {
major: '',
mainProcedure: '',
subProcedure: '',
deviceName: '',
unit: '',
powerType: '',
ratedForce: '',
maxForce: '',
smartControl: '',
features: []
},
rules: {
deviceName: [{ required: true, message: '请输入设备名称', trigger: 'blur' }],
unit: [{ required: true, message: '请输入计量单位', trigger: 'blur' }],
powerType: [{ required: true, message: '请输入动力方式', trigger: 'blur' }],
ratedForce: [{ required: true, message: '请输入额定牵引力', trigger: 'blur' }],
maxForce: [{ required: true, message: '请输入最大牵引力', trigger: 'blur' }],
smartControl: [{ required: true, message: '请输入智能集控能力', trigger: 'blur' }]
}
}
},
computed: {
dialogVisible: {
get() {
return this.visible
},
set(val) {
this.$emit('update:visible', val)
}
}
},
watch: {
parentNode: {
immediate: true,
handler(newVal) {
this.form.subProcedure = newVal?.label || null
this.form.major = newVal?.major || null
this.form.mainProcedure = newVal?.mainProcedure || null
}
}
},
methods: {
handleSubmitSuccess(data) {
const formData = JSON.parse(data) //
const isDuplicate = this.form.features.some(
(item) => item.featureName === formData.featureName
)
if (!isDuplicate) {
if (formData.inputType === 'input') {
formData.value = ''
} else {
formData.value = ''
formData.options = []
}
this.form.features.push(formData) //
this.featureOpen = false
} else {
this.$message.warning(`特征项 "${formData.featureName}" 已存在!`)
}
},
addFeature() {
this.featureOpen = true
},
removeFeature(index) {
this.form.features.splice(index, 1)
},
handleClose() {
this.$emit('update:visible', false)
this.$emit('refresh', false)
this.resetForm()
},
submit() {
this.$refs.form.validate(valid => {
if (valid) {
const formData = {
typeName: this.form.deviceName || null,
parentId: this.parentNode?.id || null,
companyId: this.parentNode?.companyId || null,
unitName: this.form.unit || null,
formFeature: this.form.features || null
}
addProperties(formData).then((response) => {
this.$modal.msgSuccess('新增成功')
})
this.handleClose()
}
})
},
resetForm() {
this.form.features = []
this.$refs.form?.resetFields()
}
}
}
</script>

View File

@ -0,0 +1,122 @@
<template>
<el-dialog
title="新增"
:visible.sync="dialogVisible"
width="50%"
append-to-body
:close-on-click-modal="false"
@close="handleClose"
>
<el-form
label-width="80px"
:model="form"
:rules="rules"
ref="formRef"
>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="所属上级">
<el-input
style="width: 100%"
disabled
v-model="form.parentName"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="名称" prop="name">
<el-input
style="width: 100%"
v-model="form.name"
placeholder="请输入名称"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row style="text-align: right; margin-top: 20px">
<el-form-item>
<el-button size="small" @click="handleClose"> </el-button>
<el-button size="small" type="primary" @click="onSubmit"> </el-button>
</el-form-item>
</el-row>
</el-form>
</el-dialog>
</template>
<script>
import { addMaType } from '@/api/lessor/equipType'
export default {
name: 'AddNodeDialog',
props: {
visible: {
type: Boolean,
default: false
},
parentNode: {
type: Object,
default: () => ({})
}
},
data() {
return {
form: {
parentName: '',
name: ''
},
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在2到20个字符', trigger: 'blur' }
]
}
}
},
computed: {
dialogVisible: {
get() {
return this.visible
},
set(val) {
this.$emit('update:visible', val)
}
}
},
watch: {
parentNode: {
immediate: true,
handler(newVal) {
this.form.parentName = newVal?.label || newVal?.name || ''
}
}
},
methods: {
onSubmit() {
this.$refs.formRef.validate(valid => {
if (valid) {
const formData = {
typeName: this.form.name || null,
parentId: this.parentNode?.id || null,
companyId: this.parentNode?.companyId || null
}
addMaType(formData).then((response) => {
this.$modal.msgSuccess('新增成功')
})
this.handleClose()
}
})
},
handleClose() {
this.resetForm()
this.$emit('update:visible', false)
this.$emit('refresh', false)
},
resetForm() {
this.$refs.formRef?.resetFields()
}
}
}
</script>

View File

@ -0,0 +1,265 @@
<template>
<el-dialog :modal-append-to-body="false" :visible.sync="dialogVisible" title="修改" width="70%" @close="handleClose"
:close-on-click-modal="false"
>
<!-- 基础信息 -->
<el-divider content-position="left">基础信息</el-divider>
<el-form :model="form" :rules="rules" ref="form" label-width="120px">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="所属专业" prop="major">
<el-input v-model="form.major" disabled/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="主工序" prop="mainProcedure">
<el-input v-model="form.mainProcedure" disabled/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="子工序" prop="subProcedure">
<el-input v-model="form.subProcedure" disabled/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="form.deviceName"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="计量单位" prop="unit">
<el-input v-model="form.unit"/>
</el-form-item>
</el-col>
</el-row>
<!-- 特征值信息 -->
<el-row type="flex" align="middle">
<el-col :span="22">
<el-divider content-position="left">特征值信息</el-divider>
</el-col>
<el-col :span="2" style="text-align: right;">
<el-button type="primary" size="mini" @click="addFeature">新增特征项</el-button>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-bottom: 10px">
<el-col
v-for="(item, index) in form.features"
:key="index"
:span="8"
>
<el-form-item
style="margin: unset"
:label="item.featureName"
:prop="`features[${index}].value`"
required
:rules="[{ required: true, message: `请输入${item.featureName}`, trigger: ['blur', 'change'] }]"
>
<!-- 普通输入框 -->
<el-input
v-if="item.inputType === 'input'"
v-model="item.value"
>
<template #suffix>
<i
class="el-icon-delete"
@click="removeFeature(index)"
style="font-size: 16px; color: red;"
></i>
</template>
</el-input>
<!-- 可输入下拉 -->
<InputSelect
:label="item.featureName"
v-else-if="item.inputType === 'select'"
v-model="item.value"
@update:modelValue="item.value = $event"
:optionsList="item.options"
@update:optionsList="item.options = $event"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 底部按钮 -->
<template #footer>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="submit">确定</el-button>
</template>
<Feature :visible.sync="featureOpen" @submit-success="handleSubmitSuccess"/>
</el-dialog>
</template>
<script>
import InputSelect from '@/views/lessor/equipment/equipType/child/inputSelect.vue'
import Feature from '@/views/lessor/equipment/equipType/child/feature.vue'
import { updateProperties } from '@/api/lessor/equipType'
export default {
name: 'AddDeviceDialog',
components: { Feature, InputSelect },
props: {
visible: {
type: Boolean,
default: false
},
parentNode: {
type: Object,
default: () => ({})
}
},
data() {
return {
featureOpen: false,
form: {
major: '',
mainProcedure: '',
subProcedure: '',
deviceName: '',
unit: '',
powerType: '',
ratedForce: '',
maxForce: '',
smartControl: '',
features: [] //
},
rules: {
deviceName: [{ required: true, message: '请输入设备名称', trigger: 'blur' }],
unit: [{ required: true, message: '请输入计量单位', trigger: 'blur' }],
powerType: [{ required: true, message: '请输入动力方式', trigger: 'blur' }],
ratedForce: [{ required: true, message: '请输入额定牵引力', trigger: 'blur' }],
maxForce: [{ required: true, message: '请输入最大牵引力', trigger: 'blur' }],
smartControl: [{ required: true, message: '请输入智能集控能力', trigger: 'blur' }]
}
}
},
computed: {
dialogVisible: {
get() {
return this.visible
},
set(val) {
this.$emit('update:visible', val)
}
}
},
watch: {
parentNode: {
immediate: true,
handler(newVal) {
this.form.subProcedure = newVal?.label || null
this.form.major = newVal?.major || null
this.form.mainProcedure = newVal?.mainProcedure || null
this.form.deviceName = newVal?.label || newVal?.typeName
this.form.unit = newVal?.unitName || null
//
this.analyzeData(newVal?.maTypeProperties || [])
}
}
},
methods: {
/**
* 分析特征值数据统计重复的propertyName并设置输入类型
* @param {Array} data - 特征值数据数组
*/
analyzeData(data) {
//
this.form.features = []
if (!data || !data.length) return
// propertyName
const result = {}
data.forEach(item => {
if (!result[item.propertyName]) {
result[item.propertyName] = {
count: 0,
options: []
}
}
//
result[item.propertyName].count++
//
if (item.propertyValue && !result[item.propertyName].options.includes(item.propertyValue)) {
result[item.propertyName].options.push(item.propertyValue)
}
})
//
Object.entries(result).forEach(([name, info]) => {
this.form.features.push({
featureName: name,
// >1
inputType: info.count > 1 ? 'select' : 'input',
options: info.options, //
value: info.options[0] //
})
})
},
handleSubmitSuccess(data) {
const formData = JSON.parse(data)
const isDuplicate = this.form.features.some(
(item) => item.featureName === formData.featureName
)
if (!isDuplicate) {
if (formData.inputType === 'input') {
formData.value = ''
} else {
formData.value = ''
formData.options = []
}
this.form.features.push(formData)
this.featureOpen = false
} else {
this.$message.warning(`特征项 "${formData.featureName}" 已存在!`)
}
},
addFeature() {
this.featureOpen = true
},
removeFeature(index) {
this.form.features.splice(index, 1)
},
handleClose() {
//this.resetForm()
this.$emit('update:visible', false)
this.$emit('refresh', false)
},
submit() {
this.$refs.form.validate(valid => {
if (valid) {
const formData = {
typeName: this.form.deviceName || null,
typeId: this.parentNode?.id || null,
parentId: this.parentNode?.parentId || null,
companyId: this.parentNode?.companyId || null,
unitName: this.form.unit || null,
formFeature: this.form.features || null
}
updateProperties(formData).then((response) => {
this.$modal.msgSuccess('修改成功')
this.handleClose()
})
}
})
},
resetForm() {
this.form.features = []
this.$refs.form?.resetFields()
}
}
}
</script>

View File

@ -0,0 +1,112 @@
<template>
<el-dialog
title="修改"
:visible.sync="dialogVisible"
width="50%"
append-to-body
:close-on-click-modal="false"
@close="handleClose"
>
<el-form
label-width="80px"
:model="form"
:rules="rules"
ref="formRef"
>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="名称" prop="name">
<el-input
style="width: 100%"
v-model="form.name"
placeholder="请输入名称"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row style="text-align: right; margin-top: 20px">
<el-form-item>
<el-button size="small" @click="handleClose"> </el-button>
<el-button size="small" type="primary" @click="onSubmit"> </el-button>
</el-form-item>
</el-row>
</el-form>
</el-dialog>
</template>
<script>
import { updateMaType } from '@/api/lessor/equipType'
export default {
name: 'EditNodeDialog',
props: {
visible: {
type: Boolean,
default: false
},
parentNode: {
type: Object,
default: () => ({})
}
},
data() {
return {
form: {
name: ''
},
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在2到20个字符', trigger: 'blur' }
]
}
}
},
computed: {
dialogVisible: {
get() {
return this.visible
},
set(val) {
this.$emit('update:visible', val)
}
}
},
watch: {
parentNode: {
immediate: true,
handler(newVal) {
console.log(newVal)
this.form.name = newVal?.label || newVal?.name || ''
}
}
},
methods: {
onSubmit() {
this.$refs.formRef.validate(valid => {
if (valid) {
const formData = {
typeName: this.form.name || null,
typeId: this.parentNode?.id || null
}
updateMaType(formData).then((response) => {
this.$modal.msgSuccess('修改成功')
})
this.handleClose()
}
})
},
handleClose() {
this.resetForm()
this.$emit('update:visible', false)
this.$emit('refresh', false)
},
resetForm() {
this.$refs.formRef?.resetFields()
this.form.name = this.parentNode?.label || this.parentNode?.name || ''
}
}
}
</script>

View File

@ -0,0 +1,95 @@
<template>
<el-dialog :visible.sync="dialogVisible" :append-to-body="true" title="新增" width="20%" @close="handleClose"
:close-on-click-modal="false"
>
<!-- 基础信息 -->
<el-form :model="form" :rules="rules" ref="form" label-width="120px">
<el-row :gutter="20">
<!-- 第1行特征项名称占满整行 -->
<el-col :span="24">
<el-form-item label="特征项名称" prop="featureName">
<el-input v-model="form.featureName"/>
</el-form-item>
</el-col>
<!-- 第2行类型 + 是否必填各占一半 -->
<el-col :span="24">
<el-form-item label="类型" prop="inputType">
<el-radio-group v-model="form.inputType">
<el-radio :label="'input'">输入框</el-radio>
<el-radio :label="'select'">下拉选</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="是否必填" prop="required">
<el-radio-group v-model="form.required">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 底部按钮 -->
<template #footer>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="submit">确定</el-button>
</template>
</el-dialog>
</template>
<script>
export default {
name: 'feature',
props: {
visible: {
type: Boolean,
default: false
}
},
data() {
return {
form: {
featureName: '',
inputType: 'input',
required: true
},
rules: {
featureName: [{ required: true, message: '请输入特征项名称', trigger: 'blur' }]
}
}
},
computed: {
dialogVisible: {
get() {
return this.visible
},
set(val) {
this.$emit('update:visible', val)
}
}
},
methods: {
handleClose() {
this.resetForm()
this.$emit('update:visible', false)
},
submit() {
this.$refs.form.validate(valid => {
if (valid) {
this.$emit('submit-success', JSON.stringify(this.form))
// ...
this.handleClose()
}
})
},
resetForm() {
this.$refs.form?.resetFields()
}
}
}
</script>

View File

@ -0,0 +1,88 @@
<template>
<div>
<el-select
v-model="value"
filterable
allow-create
default-first-option
placeholder="请选择或输入"
@change="handleChange"
>
<el-option
v-for="item in options"
:key="item"
:label="renderLabel(item)"
:value="item"
>
<!-- 默认插槽允许父组件自定义内容 -->
<slot name="option" :item="item">
<!-- 默认内容 -->
<span style="float: left">{{ item }}</span>
<span
style="float: right; color: #8492a6; font-size: 13px; cursor: pointer"
@click.stop="deleteOption(item)"
>
<i class="el-icon-close"></i>
</span>
</slot>
</el-option>
</el-select>
</div>
</template>
<script>
export default {
props: {
modelValue: { type: String, default: '' },
optionsList: { type: Array, default: () => [] }
},
data() {
return {
options: [...this.optionsList],
value: this.modelValue
}
},
watch: {
modelValue(val) {
this.value = val
},
value(newVal) {
this.$emit('update:modelValue', newVal)
},
optionsList(newList) {
this.options = [...newList]
}
},
emits: ['update:modelValue', 'update:optionsList'],
methods: {
handleChange(val) {
if (val && !this.options.includes(val)) {
this.options.push(val)
this.$emit('update:optionsList', [...this.options])
}
},
deleteOption(item) {
const index = this.options.indexOf(item)
if (index !== -1) {
this.options.splice(index, 1)
this.$emit('update:optionsList', [...this.options])
if (this.value === item) {
this.value = ''
}
}
},
renderLabel(item) {
return item
}
}
}
</script>
<style scoped>
.el-select-dropdown__item {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff