BomForm.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <template>
  2. <Dialog v-model="dialogVisible" :title="dialogTitle">
  3. <el-form
  4. ref="formRef"
  5. v-loading="formLoading"
  6. :model="formData"
  7. :rules="formRules"
  8. label-width="120px"
  9. >
  10. <el-form-item label="设备分类" prop="deviceCategoryId">
  11. <el-tree-select
  12. v-model="formData.deviceCategoryId"
  13. :data="deviceCategoryTree"
  14. :props="defaultProps"
  15. check-strictly
  16. :default-expanded-keys="firstLevelKeys"
  17. placeholder="请选择设备分类"
  18. value-key="id"
  19. @node-click="handleDeviceCategoryTreeNodeClick"
  20. />
  21. </el-form-item>
  22. <el-form-item label="上级BOM" prop="parentId">
  23. <el-tree-select
  24. v-model="formData.parentId"
  25. :data="bomTree"
  26. :props="defaultProps"
  27. check-strictly
  28. default-expand-all
  29. placeholder="请选择上级BOM"
  30. value-key="bomId"
  31. />
  32. </el-form-item>
  33. <el-form-item label="BOM节点名称" prop="name">
  34. <el-input v-model="formData.name" placeholder="请输入BOM节点名称" />
  35. </el-form-item>
  36. <el-form-item label="BOM节点属性" prop="type">
  37. <el-checkbox-group v-model="formData.type" class="w-80">
  38. <el-checkbox
  39. v-for="dict in getIntDictOptions(DICT_TYPE.PMS_BOM_NODE_EXT_ATTR)"
  40. :key="dict.value"
  41. :value="dict.value"
  42. >
  43. {{ dict.label }}
  44. </el-checkbox>
  45. </el-checkbox-group>
  46. </el-form-item>
  47. <el-form-item label="显示排序" prop="sort">
  48. <el-input-number v-model="formData.sort" :min="0" controls-position="right" />
  49. </el-form-item>
  50. <el-form-item label="状态" prop="status">
  51. <el-select v-model="formData.status" clearable placeholder="请选择状态">
  52. <el-option
  53. v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
  54. :key="dict.value"
  55. :label="dict.label"
  56. :value="dict.value"
  57. />
  58. </el-select>
  59. </el-form-item>
  60. </el-form>
  61. <template #footer>
  62. <el-button type="primary" @click="submitForm">确 定</el-button>
  63. <el-button @click="dialogVisible = false">取 消</el-button>
  64. </template>
  65. </Dialog>
  66. </template>
  67. <script lang="ts" setup>
  68. import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
  69. import { defaultProps, handleTree } from '@/utils/tree'
  70. import * as BomApi from '@/api/pms/bom'
  71. import { CommonStatusEnum } from '@/utils/constants'
  72. import { useTreeStore } from '@/store/modules/treeStore';
  73. import * as DeviceCategoryApi from '@/api/pms/productclassify'
  74. import { FormRules } from 'element-plus'
  75. import { defineEmits, ref } from 'vue';
  76. defineOptions({ name: 'BomForm' })
  77. // 从store中共享设备分类id
  78. const treeStore = useTreeStore();
  79. const { t } = useI18n() // 国际化
  80. const message = useMessage() // 消息弹窗
  81. const localCategoryId = ref(null); // 通过store存储的设备分类id 由父组件传递过来
  82. const selfDeviceCategoryId = ref(null); // 当前页面定义的 设备分类id
  83. const dialogVisible = ref(false) // 弹窗的是否展示
  84. const dialogTitle = ref('') // 弹窗的标题
  85. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  86. const formType = ref('') // 表单的类型:create - 新增;update - 修改
  87. const formData = ref({
  88. id: undefined,
  89. deviceCategoryId: localCategoryId.value,
  90. title: '',
  91. parentId: undefined,
  92. name: undefined,
  93. sort: 0,
  94. type: undefined,
  95. status: CommonStatusEnum.ENABLE
  96. })
  97. const formRules = reactive<FormRules>({
  98. deviceCategoryId: [{ required: true, message: '设备分类不能为空', trigger: 'blur' }],
  99. parentId: [{ required: true, message: '上级Bom不能为空', trigger: 'blur' }],
  100. name: [{ required: true, message: 'Bom节点名称不能为空', trigger: 'blur' }],
  101. sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
  102. status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
  103. })
  104. const formRef = ref() // 表单 Ref
  105. const bomTree = ref() // BOM 树形结构
  106. const deviceCategoryTree = ref() // 设备分类树
  107. const firstLevelKeys = ref([])
  108. const queryParams = reactive({
  109. pageNo: 1,
  110. pageSize: 10,
  111. name: undefined,
  112. status: undefined,
  113. deviceCategoryId: localCategoryId.value,
  114. })
  115. /** 打开弹窗 */
  116. const open = async (type: string, id?: number) => {
  117. dialogVisible.value = true
  118. // 获取store中的设备分类id
  119. localCategoryId.value = treeStore.selectedId;
  120. selfDeviceCategoryId.value = treeStore.selectedId;
  121. dialogTitle.value = t('action.' + type)
  122. formType.value = type
  123. resetForm()
  124. // 修改时,设置数据
  125. if (id) {
  126. formLoading.value = true
  127. try {
  128. formData.value = await BomApi.getBom(id)
  129. } finally {
  130. formLoading.value = false
  131. }
  132. }
  133. // 获得 设备分类树
  134. await getDeviceCategoryTree()
  135. // 获得 bom 树
  136. await getTree()
  137. }
  138. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  139. const emit = defineEmits(['success', 'node-click']) // 定义 success 树点击 事件,用于操作成功后的回调
  140. /** 处理 设备分类 树 被点击 */
  141. const handleDeviceCategoryTreeNodeClick = async (row: { [key: string]: any }) => {
  142. emit('node-click', row)
  143. // treeStore.setSelectedId(row.id);
  144. // 清空设备分类bom树的选择,重新查询筛选bom树
  145. selfDeviceCategoryId.value = row.id
  146. await getTree()
  147. }
  148. /** 提交表单 */
  149. const submitForm = async () => {
  150. // 校验表单
  151. if (!formRef.value) return
  152. const valid = await formRef.value.validate()
  153. if (!valid) return
  154. // 提交请求
  155. formLoading.value = true
  156. try {
  157. // 赋值设备分类id
  158. formData.value.deviceCategoryId = selfDeviceCategoryId.value
  159. const data = formData.value as unknown as BomApi.BomVO
  160. if (formType.value === 'create') {
  161. await BomApi.createBomNode(data)
  162. message.success(t('common.createSuccess'))
  163. } else {
  164. await BomApi.updateBomNode(data)
  165. message.success(t('common.updateSuccess'))
  166. }
  167. dialogVisible.value = false
  168. // 发送操作成功的事件
  169. emit('success')
  170. } finally {
  171. formLoading.value = false
  172. }
  173. }
  174. /** 重置表单 */
  175. const resetForm = () => {
  176. formData.value = {
  177. id: undefined,
  178. deviceCategoryId: localCategoryId.value,
  179. title: '',
  180. parentId: undefined,
  181. name: undefined,
  182. sort: 0,
  183. type: undefined,
  184. status: CommonStatusEnum.ENABLE
  185. }
  186. formRef.value?.resetFields()
  187. }
  188. /** 获得 设备分类 树 **/
  189. const getDeviceCategoryTree = async () => {
  190. deviceCategoryTree.value = []
  191. const res = await DeviceCategoryApi.IotProductClassifyApi.getSimpleProductClassifyList()
  192. let bom: Tree = { id: 0, name: '顶级Bom', children: [] }
  193. bom.children = handleTree(res)
  194. deviceCategoryTree.value.push(bom)
  195. }
  196. /** 获得 Bom 树 */
  197. const getTree = async () => {
  198. bomTree.value = []
  199. queryParams.deviceCategoryId = selfDeviceCategoryId.value;
  200. const data = await BomApi.getSimpleBomList(queryParams)
  201. let bom: Tree = { id: 0, name: '顶级Bom', children: [] }
  202. bom.children = handleTree(data)
  203. bomTree.value.push(bom)
  204. firstLevelKeys.value = bomTree.value.map(node => node.id);
  205. }
  206. /** 初始化 **/
  207. onMounted(() => {
  208. formData.value.sort = 0
  209. })
  210. </script>