1. <template>
    2. <a-modal
    3. v-if="visible"
    4. :title="title" // 标题
    5. :visible="visible" // 对话框是否可见
    6. @ok="handleOk" //点击确定回调
    7. @cancel="handleCancel" //点击遮罩层或右上角叉或取消按钮的回调
    8. :width="800"
    9. :height="900"
    10. :destoryOnClose="true" //关闭时销毁 Modal 里的子元素
    11. :bodyStyle="{ padding: '0px 10px', minHeight: '500px' }" //Modal body 样式
    12. >
    13. <a-tabs default-active-key="1">
    14. <a-tab-pane key="1" tab="基本信息" style="padding-left: 10px"> //基本信息tab
    15. <a-row>
    16. <a-form-model
    17. ref="createBatchInfoRef" //表单DOM实例
    18. :model="form" //表单数据对象
    19. :labelCol="{ span: 10 }" //label 标签布局
    20. :wrapperCol="{ span: 14 }"
    21. :rules="rules" // 表单验证规则
    22. > // Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 FormItem 的 prop 属性设置为需校验的字段名即可。
    23. <a-row :gutter="16">
    24. <a-col :span="12">
    25. <a-form-model-item label="种类" prop="frameName">
    26. <a-input disabled v-model="form.frameName"></a-input>
    27. </a-form-model-item>
    28. </a-col>
    29. <a-col :span="12">
    30. <a-form-model-item label="图标" prop="icon">
    31. <a-select v-model="form.icon">
    32. <a-select-option
    33. :value="item"
    34. :key="index"
    35. v-for="(item, index) in schemaIcons"
    36. >
    37. <a-icon :type="item" style="font-size: 16px" />
    38. </a-select-option>
    39. </a-select>
    40. </a-form-model-item>
    41. </a-col>
    42. <a-col :span="12">
    43. <a-form-model-item label="编码" prop="prefix">
    44. <a-input v-model="form.prefix"></a-input>
    45. </a-form-model-item>
    46. </a-col>
    47. <a-col :span="12">
    48. <a-form-model-item label="元件名称" prop="name">
    49. <a-input v-model="form.name"></a-input>
    50. </a-form-model-item>
    51. </a-col>
    52. <!--如果stockFrameInfo.id===3,也就是容器才触发-->
    53. <a-col :span="12" v-if="CONTAINER_TYPE === stockFrameInfo.id">
    54. <a-form-model-item label="单位" prop="unitId">
    55. <a-select
    56. @dropdownVisibleChange="dropdownVisibleChange" //展开下拉菜单的回调
    57. v-model="form.unitId"
    58. placeholder="请选择"
    59. >
    60. <a-select-option
    61. :key="item.id"
    62. :value="item.id"
    63. v-for="item in unitOptions" //拿到数据库中的预选单位
    64. >
    65. {{ item.unitName }}
    66. </a-select-option>
    67. <template v-slot:notFoundContent v-if="spinning">
    68. <a-spin :spinning="spinning"></a-spin>
    69. </template>
    70. </a-select>
    71. </a-form-model-item>
    72. </a-col>
    73. <a-col :span="12" v-if="CONTAINER_TYPE === stockFrameInfo.id">
    74. <a-form-model-item label="容量" prop="capacity">
    75. <a-input v-model="form.capacity"></a-input>
    76. </a-form-model-item>
    77. </a-col>
    78. <a-col
    79. :key="item.id"
    80. :span="12"
    81. v-for="item in stockFrameAttribute" //根据库位种类id获取的库位种类动态字段信息
    82. >
    83. <a-form-model-item :label="item.paramName" :prop="item.id">
    84. // 根据数据类型进行不同的操作
    85. <template
    86. v-if="
    87. paramTypeColumn.text === item.paramType || // 10
    88. paramTypeColumn.integer === item.paramType || // 30
    89. paramTypeColumn.float === item.paramType // 31
    90. "
    91. >
    92. <a-input
    93. v-if="item.isMultipleValue === 2"
    94. v-model="form[item.id][0]"
    95. ></a-input>
    96. <a-select
    97. v-else
    98. v-model="form[item.id]"
    99. :dropdownStyle="{ display: 'none' }"
    100. :dropdownMenuStyle="{ display: 'none' }"
    101. mode="tags"
    102. ></a-select>
    103. </template>
    104. <template
    105. v-else-if="paramTypeColumn.textArea === item.paramType"
    106. >
    107. <a-input
    108. :auto-size="{ minRows: 3, maxRows: 5 }"
    109. class="default-input"
    110. v-model="form[item.id][0]"
    111. type="textarea"
    112. ></a-input>
    113. </template>
    114. <template
    115. v-else-if="paramTypeColumn.radioSelect === item.paramType"
    116. >
    117. <a-select v-model="form[item.id][0]">
    118. <a-select-option
    119. :key="element"
    120. v-for="element in item.preDefinedValues"
    121. >
    122. {{ element }}
    123. </a-select-option>
    124. </a-select>
    125. </template>
    126. <template
    127. v-else-if="paramTypeColumn.multiSelect === item.paramType"
    128. >
    129. <a-select mode="multiple" v-model="form[item.id]">
    130. <a-select-option
    131. :key="element"
    132. v-for="element in item.preDefinedValues"
    133. >
    134. {{ element }}
    135. </a-select-option>
    136. </a-select>
    137. </template>
    138. <template v-else-if="paramTypeColumn.time === item.paramType">
    139. <a-date-picker
    140. v-model="item.paramValues[0]"
    141. :showTime="true"
    142. ></a-date-picker>
    143. </template>
    144. <template v-else-if="paramTypeColumn.link === item.paramType">
    145. <span
    146. class="link-type"
    147. :key="ele.referenceId"
    148. v-for="ele in item.paramValues"
    149. @click="showProductLinkDetail(ele)"
    150. ><a-icon type="link" /> {{ ele.referenceName }}</span
    151. >
    152. </template>
    153. <template
    154. v-else-if="
    155. paramTypeColumn.container === item.paramType &&
    156. (CONTAINER_TYPE_HE | CONTAINER_TYPE_BAN) ===
    157. stockFrameInfo.id
    158. "
    159. >
    160. <a-select
    161. @dropdownVisibleChange="dropdownVisibleChange2"
    162. v-model="form[item.id][0]"
    163. >
    164. // 要加key、value才行
    165. <a-select-option
    166. :key="element.id"
    167. v-for="element in ContainerOptions"
    168. :value="element.id"
    169. >
    170. {{ element.name }}
    171. </a-select-option>
    172. </a-select>
    173. </template>
    174. </a-form-model-item>
    175. </a-col>
    176. </a-row>
    177. </a-form-model>
    178. </a-row>
    179. <span>元件字段:</span>
    180. <custom-fields
    181. @getData="getCustomFieldsData"
    182. ref="customFieldsRef"
    183. ></custom-fields>
    184. <span>库位字段:</span>
    185. <storage-fields
    186. ref="storageFieldsRef"
    187. @getData="getStorageLocationFieldsData"
    188. :showMode="showMode.productKey"
    189. >
    190. </storage-fields>
    191. </a-tab-pane>
    192. <a-tab-pane
    193. key="2"
    194. tab="规则设置"
    195. style="padding-left: 10px"
    196. ></a-tab-pane> //规则设置tab
    197. </a-tabs>
    198. </a-modal>
    199. </template>
    200. <script>
    201. import {
    202. queryStockFrameFields,
    203. saveStockSchema,
    204. queryStockSchemasDetail
    205. } from '@/api/material/locationSetting' // 引入API接口
    206. import { getFullUnitInfo } from '@/api/system/unit'
    207. import {
    208. handleValidateCodePlus,
    209. validateInteger,
    210. validateFloat,
    211. validateFloatNumber,
    212. validateArrRequired
    213. } from '@/common/inspectFunction' // 引入规则校验函数
    214. import { paramTypeColumn, schemaIcons, VOLUME_TYPE_UNIT } from '@/common/global'
    215. import CustomFields from '@/views/materialcenter/productManagement/components/ProductCustomFields'
    216. import { CUSTOM_FIELD_SHOW_MODE } from '@/views/materialcenter/productManagement/components/comm/constValues'
    217. const CONTAINER_TYPE = '3'
    218. const CONTAINER_TYPE_HE = '2'
    219. const CONTAINER_TYPE_BAN = '4'
    220. export default {
    221. components: {
    222. CustomFields,
    223. StorageFields: CustomFields,
    224. },
    225. props: {
    226. leftSuccess: Function,
    227. schemaRightSuccess: Function,
    228. },
    229. data() {
    230. return {
    231. schemaIcons: Object.freeze(schemaIcons),
    232. source: '',
    233. stockFrameInfo: {},
    234. visible: false,
    235. title: '新建元件',
    236. paramTypeColumn: Object.freeze(paramTypeColumn), //参数类型
    237. baseInfo: {
    238. frameName: '',
    239. icon: '',
    240. prefix: '',
    241. name: '',
    242. unitId: undefined,
    243. capacity: undefined,
    244. },
    245. form: {
    246. frameName: '',
    247. icon: '',
    248. prefix: '',
    249. name: '',
    250. unitId: undefined,
    251. capacity: undefined,
    252. },
    253. rules: {
    254. prefix: [
    255. {
    256. min: 1,
    257. max: 64,
    258. required: true,
    259. message: '编码的长度在1~64位之间',
    260. trigger: 'change',
    261. },
    262. {
    263. validator: this.handleValidateCodePlus,
    264. message: '编号格式不正确',
    265. trigger: 'change',
    266. },
    267. ],
    268. name: [
    269. {
    270. min: 1,
    271. max: 32,
    272. required: true,
    273. message: '元件名称的长度在1~32位之间',
    274. trigger: 'change',
    275. },
    276. ],
    277. capacity: [
    278. {
    279. validator: this.validateFloatNumber,
    280. },
    281. {
    282. required: true,
    283. message: '容量为必填',
    284. trigger: 'blur',
    285. },
    286. ],
    287. unitId: [
    288. {
    289. required: true,
    290. message: '请填写单位',
    291. trigger: 'blur',
    292. },
    293. ],
    294. },
    295. stockFrameAttribute: [], //库位种类属性
    296. // 后端需要的paramType
    297. paramTypeObj: {},
    298. showMode: Object.freeze(CUSTOM_FIELD_SHOW_MODE),
    299. customFieldsData: [],
    300. storageFieldData: [],
    301. unitOptions: [], // 单位选项
    302. CONTAINER_TYPE,
    303. spinning: true,
    304. CONTAINER_TYPE_HE,
    305. CONTAINER_TYPE_BAN,
    306. ContainerOptions: [] //容器选项
    307. }
    308. },
    309. methods: {
    310. dropdownVisibleChange(open) {
    311. // this.spinning = true
    312. open && _.isEmpty(this.unitOptions) && this.getFullUnitInfo()
    313. },
    314. /**
    315. * 获取数据库预选单位
    316. */
    317. async getFullUnitInfo() {
    318. this.spinning = true
    319. const res = await getFullUnitInfo({
    320. artifacts: [VOLUME_TYPE_UNIT],
    321. pageSize: -1,
    322. }).finally(() => {
    323. this.spinning = false
    324. })
    325. if (res.code === '200') {
    326. this.unitOptions = res.data
    327. }
    328. },
    329. dropdownVisibleChange2(open) {
    330. open && _.isEmpty(this.ContainerOptions) && this.getFullContainerInfo()
    331. },
    332. /**
    333. * 获取数据库容器
    334. */
    335. async getFullContainerInfo() {
    336. this.spinning = true
    337. const res = await queryStockSchemasDetail({
    338. stockFrameId: '3',
    339. pageSize: -1
    340. }).finally(() => {
    341. this.spinning = false
    342. })
    343. if (res.code === '200') {
    344. this.ContainerOptions = res.data.result
    345. this.ContainerOptions.forEach(item => {
    346. this.$set(this.form, item.id, item.name)
    347. })
    348. }
    349. },
    350. /**
    351. * 自定义编码规则
    352. */
    353. handleValidateCodePlus,
    354. /**
    355. * 整数自定义验证
    356. */
    357. validateInteger,
    358. /**
    359. * 浮点数自定义验证
    360. */
    361. validateFloat,
    362. validateFloatNumber,
    363. /**
    364. * 后端给的值是数组
    365. * 自定义必填
    366. */
    367. validateArrRequired,
    368. /**
    369. * 动态表单校验
    370. */
    371. dynamicValidate(element) {
    372. // 必填项
    373. if (element.isRequired === 1) {
    374. const requiredInfo = [
    375. { validator: this.validateArrRequired, trigger: 'change' },
    376. { required: true, message: '必填', trigger: 'change' }
    377. ]
    378. !this.rules[element.id] && this.$set(this.rules, element.id, requiredInfo)
    379. if (this.rules[element.id] && this.rules[element.id].findIndex(item => item.required) < 0) {
    380. this.rules[element.id].push(...requiredInfo)
    381. }
    382. // this.rules[element.id] = [{ required: true, message: '必填', trigger: 'change' }]
    383. }
    384. // 整数
    385. if (element.paramType === this.paramTypeColumn.integer) {
    386. !this.rules[element.id] &&
    387. this.$set(this.rules, element.id, [
    388. { validator: this.validateInteger },
    389. ])
    390. this.rules[element.id] &&
    391. this.rules[element.id].push({
    392. validator: this.validateInteger,
    393. })
    394. }
    395. // 浮点数
    396. if (element.paramType === this.paramTypeColumn.float) {
    397. !this.rules[element.id] &&
    398. this.$set(this.rules, element.id, [{ validator: this.validateFloat }])
    399. this.rules[element.id] &&
    400. this.rules[element.id].push({
    401. validator: this.validateFloat,
    402. })
    403. }
    404. },
    405. /**
    406. * 获取自定义字段数据
    407. */
    408. getCustomFieldsData(data) {
    409. this.customFieldsData = data
    410. },
    411. /**
    412. * 获取元件为库位设置的字段信息
    413. */
    414. getStorageLocationFieldsData(data) {
    415. this.storageFieldData = data
    416. },
    417. /**
    418. * 保存库位元件
    419. */
    420. async saveStockSchema(data) {
    421. const res = await saveStockSchema(data)
    422. if (res.code === '200') {
    423. this.judgeCallback()
    424. this.handleCancel()
    425. }
    426. },
    427. /**
    428. * 判断需要执行的回调
    429. */
    430. judgeCallback() {
    431. switch (this.source) {
    432. case 'storageComponentLeft':
    433. this.leftSuccess(this.stockFrameInfo)
    434. break
    435. case 'storageSchemaListRight':
    436. this.schemaRightSuccess()
    437. break
    438. default:
    439. break
    440. }
    441. },
    442. /**
    443. * 获取自定义字段和设置字段的数据
    444. */
    445. getCustomFieldsDataAndSettingData() {
    446. this.$refs.customFieldsRef.getData()
    447. this.$refs.storageFieldsRef.getData()
    448. },
    449. /**
    450. * 获取种类字段数据
    451. */
    452. getFrameParams() {
    453. let targetArr = []
    454. const target = _.cloneDeep(this.form)
    455. Object.keys(this.baseInfo).forEach((key) => {
    456. this.baseInfo[key] = target[key]
    457. delete target[key]
    458. })
    459. Object.keys(target).forEach((key) => {
    460. targetArr.push({
    461. id: key,
    462. paramValues: target[key],
    463. paramType: this.paramTypeObj[key],
    464. })
    465. })
    466. return targetArr
    467. },
    468. /**
    469. * TODO
    470. * 模态框确定
    471. */
    472. handleOk() {
    473. this.$refs.createBatchInfoRef.validate((valid) => {
    474. if (valid) {
    475. this.getCustomFieldsDataAndSettingData()
    476. const frameParams = this.getFrameParams()
    477. this.saveStockSchema({
    478. ...this.baseInfo,
    479. frameParams: frameParams,
    480. customParams: {
    481. params: this.customFieldsData,
    482. },
    483. stockParams: {
    484. params: this.storageFieldData,
    485. },
    486. stockFrameId: this.stockFrameInfo.id,
    487. })
    488. }
    489. })
    490. },
    491. /**
    492. * 模态框取消
    493. */
    494. handleCancel() {
    495. this.visible = false
    496. this.$refs.createBatchInfoRef.resetFields()
    497. this.form = {
    498. frameName: '',
    499. icon: '',
    500. prefix: '',
    501. name: '',
    502. unitId: undefined,
    503. capacity: undefined,
    504. }
    505. this.stockFrameAttribute = []
    506. },
    507. /**
    508. * 根据库位种类id获取库位种类属性信息
    509. */
    510. async queryStockFrameFields(data) {
    511. const res = await queryStockFrameFields(data) //根据库位种类id获取库位种类动态字段信息
    512. if (res.code === '200') {
    513. this.stockFrameAttribute = res.data //存到这里
    514. this.stockFrameAttribute.forEach((element) => {
    515. this.paramTypeObj[element.id] = element.paramType //取出paramType存到paramTypeObj对象;
    516. this.$set(this.form, element.id, element.paramValues || []) //向form中添加表单动态字段以便在template中显示
    517. // 校验规则
    518. this.dynamicValidate(element)
    519. })
    520. }
    521. },
    522. /**
    523. * 打开模态框
    524. */
    525. openCreateStockShemaModal(data, source) {
    526. this.source = source || ''
    527. this.visible = true
    528. this.stockFrameInfo = data
    529. this.form.frameName = this.stockFrameInfo.name // 位置、盒、容器、板
    530. this.queryStockFrameFields({ id: this.stockFrameInfo.id }) //id 对应1、2、3、4
    531. },
    532. },
    533. watch: {},
    534. }
    535. </script>
    536. <style lang="scss" scoped>
    537. </style>
    1. const paramTypeColumn = {
    2. text: 10,
    3. textArea: 11,
    4. radioSelect: 20,
    5. multiSelect: 21,
    6. integer: 30,
    7. float: 31,
    8. time: 40,
    9. link: 50,
    10. frame: 51,
    11. entity: 55,
    12. }

    image.png
    image.png
    添加一个动态表单container:

    1. <template v-else-if="paramTypeColumn.container === item.paramType">
    2. <a-select v-model="form[item.id][0]">
    3. <a-select-option :key="element" v-for="element in item.preDefinedValues">
    4. {{ element }}
    5. </a-select-option>
    6. </a-select>
    7. </template>