1、新建元件 (盒、板、填了容器数的位置)、新建库位实例 (盒、板、填了容器数的位置) 时新增默认关联容器,固定字段
    2、新建元件 (盒、板、填了容器数的位置)时选了默认容器,在新建库位实例时需要带出来;直接创建实例时需带出来;
    image.png

    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"
    11. :bodyStyle="{ padding: '0px 10px', minHeight: '500px' }"
    12. >
    13. <a-tabs default-active-key="1">
    14. <a-tab-pane key="1" tab="基本信息" style="padding-left: 10px">
    15. <a-row>
    16. <a-form-model
    17. ref="createBatchInfoRef"
    18. :model="form"
    19. :labelCol="{ span: 10 }"
    20. :wrapperCol="{ span: 14 }"
    21. :rules="rules"
    22. >
    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. <svg-icon
    39. :icon-class="item"
    40. :style="{ fontSize: '16px' }"
    41. />
    42. </a-select-option>
    43. </a-select>
    44. </a-form-model-item>
    45. </a-col>
    46. <a-col :span="12">
    47. <a-form-model-item label="编码" prop="prefix">
    48. <a-input v-model="form.prefix"></a-input>
    49. </a-form-model-item>
    50. </a-col>
    51. <a-col :span="12">
    52. <a-form-model-item label="元件名称" prop="name">
    53. <a-input v-model="form.name"></a-input>
    54. </a-form-model-item>
    55. </a-col>
    56. <a-col :span="12" v-if="CONTAINER_TYPE === stockFrameInfo.id">
    57. <a-form-model-item label="单位" prop="unitId">
    58. <a-select
    59. @dropdownVisibleChange="dropdownVisibleChange"
    60. v-model="form.unitId"
    61. placeholder="请选择"
    62. >
    63. <a-select-option
    64. :key="item.id"
    65. :value="item.id"
    66. v-for="item in unitOptions"
    67. >
    68. {{ item.unitName }}
    69. </a-select-option>
    70. <template v-slot:notFoundContent v-if="spinning">
    71. <a-spin :spinning="spinning"></a-spin>
    72. </template>
    73. </a-select>
    74. </a-form-model-item>
    75. </a-col>
    76. <a-col :span="12" v-if="CONTAINER_TYPE === stockFrameInfo.id">
    77. <a-form-model-item label="容量" prop="capacity">
    78. <a-input v-model="form.capacity"></a-input>
    79. </a-form-model-item>
    80. </a-col>
    81. <a-col
    82. :key="item.id"
    83. :span="12"
    84. v-for="item in stockFrameAttribute"
    85. >
    86. <a-form-model-item :label="item.paramName" :prop="item.id">
    87. <template
    88. v-if="
    89. paramTypeColumn.text === item.paramType ||
    90. paramTypeColumn.integer === item.paramType ||
    91. paramTypeColumn.float === item.paramType
    92. "
    93. >
    94. <a-input
    95. v-if="item.isMultipleValue === 2"
    96. v-model="form[item.id][0]"
    97. ></a-input>
    98. <a-select
    99. v-else
    100. v-model="form[item.id]"
    101. :dropdownStyle="{ display: 'none' }"
    102. :dropdownMenuStyle="{ display: 'none' }"
    103. mode="tags"
    104. ></a-select>
    105. </template>
    106. <template
    107. v-else-if="paramTypeColumn.textArea === item.paramType"
    108. >
    109. <a-input
    110. :auto-size="{ minRows: 3, maxRows: 5 }"
    111. class="default-input"
    112. v-model="form[item.id][0]"
    113. type="textarea"
    114. ></a-input>
    115. </template>
    116. <template
    117. v-else-if="paramTypeColumn.radioSelect === item.paramType"
    118. >
    119. <a-select v-model="form[item.id][0]">
    120. <a-select-option
    121. :key="element"
    122. v-for="element in item.preDefinedValues"
    123. >
    124. {{ element }}
    125. </a-select-option>
    126. </a-select>
    127. </template>
    128. <template
    129. v-else-if="paramTypeColumn.multiSelect === item.paramType"
    130. >
    131. <a-select mode="multiple" v-model="form[item.id]">
    132. <a-select-option
    133. :key="element"
    134. v-for="element in item.preDefinedValues"
    135. >
    136. {{ element }}
    137. </a-select-option>
    138. </a-select>
    139. </template>
    140. <template v-else-if="paramTypeColumn.time === item.paramType">
    141. <a-date-picker
    142. v-model="item.paramValues[0]"
    143. :showTime="true"
    144. ></a-date-picker>
    145. </template>
    146. <template v-else-if="paramTypeColumn.link === item.paramType">
    147. <span
    148. class="link-type"
    149. :key="ele.referenceId"
    150. v-for="ele in item.paramValues"
    151. @click="showProductLinkDetail(ele)"
    152. ><a-icon type="link" /> {{ ele.referenceName }}</span
    153. >
    154. </template>
    155. <template
    156. v-else-if="paramTypeColumn.container === item.paramType"
    157. >
    158. <a-select
    159. @dropdownVisibleChange="dropdownVisibleChange2"
    160. v-model="form[item.id][0]"
    161. >
    162. <a-select-option
    163. :key="element.id"
    164. v-for="element in ContainerOptions"
    165. :value="element.id"
    166. >
    167. {{ element.name }}
    168. </a-select-option>
    169. </a-select>
    170. </template>
    171. </a-form-model-item>
    172. </a-col>
    173. </a-row>
    174. </a-form-model>
    175. </a-row>
    176. <span>元件字段:</span>
    177. <custom-fields
    178. @getData="getCustomFieldsData"
    179. ref="customFieldsRef"
    180. ></custom-fields>
    181. <span>库位字段:</span>
    182. <storage-fields
    183. ref="storageFieldsRef"
    184. @getData="getStorageLocationFieldsData"
    185. :showMode="showMode.productKey"
    186. >
    187. </storage-fields>
    188. </a-tab-pane>
    189. <a-tab-pane
    190. key="2"
    191. tab="规则设置"
    192. style="padding-left: 10px"
    193. ></a-tab-pane>
    194. </a-tabs>
    195. </a-modal>
    196. </template>
    197. <script>
    198. import {
    199. queryStockFrameFields,
    200. saveStockSchema,
    201. queryStockSchemasDetail
    202. } from '@/api/material/locationSetting'
    203. import { getFullUnitInfo } from '@/api/system/unit'
    204. import {
    205. handleValidateCodePlus,
    206. validateInteger,
    207. validateFloat,
    208. validateFloatNumber,
    209. validateArrRequired
    210. } from '@/common/inspectFunction'
    211. import { paramTypeColumn, schemaIcons, VOLUME_TYPE_UNIT } from '@/common/global'
    212. import CustomFields from '@/views/materialcenter/productManagement/components/ProductCustomFields'
    213. import { CUSTOM_FIELD_SHOW_MODE } from '@/views/materialcenter/productManagement/components/comm/constValues'
    214. const CONTAINER_TYPE = '3'
    215. // const CONTAINER_TYPE_HE = '2'
    216. // const CONTAINER_TYPE_BAN = '4'
    217. export default {
    218. components: {
    219. CustomFields,
    220. StorageFields: CustomFields
    221. },
    222. props: {
    223. leftSuccess: Function,
    224. schemaRightSuccess: Function
    225. },
    226. data() {
    227. return {
    228. schemaIcons: Object.freeze(schemaIcons),
    229. source: '',
    230. stockFrameInfo: {},
    231. visible: false,
    232. title: '新建元件',
    233. paramTypeColumn: Object.freeze(paramTypeColumn),
    234. baseInfo: {
    235. frameName: '',
    236. icon: '',
    237. prefix: '',
    238. name: '',
    239. unitId: undefined,
    240. capacity: undefined
    241. },
    242. form: {
    243. frameName: '',
    244. icon: '',
    245. prefix: '',
    246. name: '',
    247. unitId: undefined,
    248. capacity: undefined
    249. },
    250. rules: {
    251. prefix: [
    252. {
    253. min: 1,
    254. max: 64,
    255. required: true,
    256. message: '编码的长度在1~64位之间',
    257. trigger: 'change'
    258. },
    259. {
    260. validator: this.handleValidateCodePlus,
    261. message: '编号格式不正确',
    262. trigger: 'change'
    263. }
    264. ],
    265. name: [
    266. {
    267. min: 1,
    268. max: 32,
    269. required: true,
    270. message: '元件名称的长度在1~32位之间',
    271. trigger: 'change'
    272. }
    273. ],
    274. capacity: [
    275. {
    276. validator: this.validateFloatNumber
    277. },
    278. {
    279. required: true,
    280. message: '容量为必填',
    281. trigger: 'blur'
    282. }
    283. ],
    284. unitId: [
    285. {
    286. required: true,
    287. message: '请填写单位',
    288. trigger: 'blur'
    289. }
    290. ]
    291. },
    292. stockFrameAttribute: [],
    293. // 后端需要的paramType
    294. paramTypeObj: {},
    295. showMode: Object.freeze(CUSTOM_FIELD_SHOW_MODE),
    296. customFieldsData: [],
    297. storageFieldData: [],
    298. unitOptions: [], // 单位选项
    299. CONTAINER_TYPE,
    300. // CONTAINER_TYPE_HE,
    301. // CONTAINER_TYPE_BAN,
    302. spinning: true,
    303. ContainerOptions: [] //容器选项
    304. }
    305. },
    306. methods: {
    307. dropdownVisibleChange(open) {
    308. // this.spinning = true
    309. open && _.isEmpty(this.unitOptions) && this.getFullUnitInfo()
    310. },
    311. /**
    312. * 获取数据库预选单位
    313. */
    314. async getFullUnitInfo() {
    315. this.spinning = true
    316. const res = await getFullUnitInfo({
    317. artifacts: [VOLUME_TYPE_UNIT],
    318. pageSize: -1
    319. }).finally(() => {
    320. this.spinning = false
    321. })
    322. if (res.code === '200') {
    323. this.unitOptions = res.data
    324. }
    325. },
    326. dropdownVisibleChange2(open) {
    327. open && _.isEmpty(this.ContainerOptions) && this.getFullContainerInfo()
    328. },
    329. /**
    330. * 获取数据库容器
    331. */
    332. async getFullContainerInfo() {
    333. this.spinning = true
    334. const res = await queryStockSchemasDetail({
    335. stockFrameId: '3',
    336. pageSize: -1
    337. }).finally(() => {
    338. this.spinning = false
    339. })
    340. if (res.code === '200') {
    341. this.ContainerOptions = res.data.result
    342. }
    343. },
    344. /**
    345. * 自定义编码规则
    346. */
    347. handleValidateCodePlus,
    348. /**
    349. * 整数自定义验证
    350. */
    351. validateInteger,
    352. /**
    353. * 浮点数自定义验证
    354. */
    355. validateFloat,
    356. validateFloatNumber,
    357. /**
    358. * 后端给的值是数组
    359. * 自定义必填
    360. */
    361. validateArrRequired,
    362. /**
    363. * 动态表单校验
    364. */
    365. dynamicValidate(element) {
    366. // 必填项
    367. if (element.isRequired === 1) {
    368. const requiredInfo = [
    369. { validator: this.validateArrRequired, trigger: 'change' },
    370. { required: true, message: '必填', trigger: 'change' }
    371. ]
    372. !this.rules[element.id] &&
    373. this.$set(this.rules, element.id, requiredInfo)
    374. if (
    375. this.rules[element.id] &&
    376. this.rules[element.id].findIndex(item => item.required) < 0
    377. ) {
    378. this.rules[element.id].push(...requiredInfo)
    379. }
    380. // this.rules[element.id] = [{ required: true, message: '必填', trigger: 'change' }]
    381. }
    382. // 整数
    383. if (element.paramType === this.paramTypeColumn.integer) {
    384. !this.rules[element.id] &&
    385. this.$set(this.rules, element.id, [
    386. { validator: this.validateInteger }
    387. ])
    388. this.rules[element.id] &&
    389. this.rules[element.id].push({
    390. validator: this.validateInteger
    391. })
    392. }
    393. // 浮点数
    394. if (element.paramType === this.paramTypeColumn.float) {
    395. !this.rules[element.id] &&
    396. this.$set(this.rules, element.id, [{ validator: this.validateFloat }])
    397. this.rules[element.id] &&
    398. this.rules[element.id].push({
    399. validator: this.validateFloat
    400. })
    401. }
    402. },
    403. /**
    404. * 获取自定义字段数据
    405. */
    406. getCustomFieldsData(data) {
    407. this.customFieldsData = data
    408. },
    409. /**
    410. * 获取元件为库位设置的字段信息
    411. */
    412. getStorageLocationFieldsData(data) {
    413. this.storageFieldData = data
    414. },
    415. /**
    416. * 保存库位元件
    417. */
    418. async saveStockSchema(data) {
    419. const res = await saveStockSchema(data)
    420. if (res.code === '200') {
    421. this.judgeCallback()
    422. this.handleCancel()
    423. }
    424. },
    425. /**
    426. * 判断需要执行的回调
    427. */
    428. judgeCallback() {
    429. switch (this.source) {
    430. case 'storageComponentLeft':
    431. this.leftSuccess(this.stockFrameInfo)
    432. break
    433. case 'storageSchemaListRight':
    434. this.schemaRightSuccess()
    435. break
    436. default:
    437. break
    438. }
    439. },
    440. /**
    441. * 获取自定义字段和设置字段的数据
    442. */
    443. getCustomFieldsDataAndSettingData() {
    444. this.$refs.customFieldsRef.getData()
    445. this.$refs.storageFieldsRef.getData()
    446. },
    447. /**
    448. * 获取种类字段数据
    449. */
    450. getFrameParams() {
    451. let targetArr = []
    452. const target = _.cloneDeep(this.form)
    453. Object.keys(this.baseInfo).forEach(key => {
    454. this.baseInfo[key] = target[key]
    455. delete target[key]
    456. })
    457. Object.keys(target).forEach(key => {
    458. targetArr.push({
    459. id: key,
    460. paramValues: target[key],
    461. paramType: this.paramTypeObj[key]
    462. })
    463. })
    464. return targetArr
    465. },
    466. /**
    467. * TODO
    468. * 模态框确定
    469. */
    470. handleOk() {
    471. this.$refs.createBatchInfoRef.validate(valid => {
    472. if (valid) {
    473. this.getCustomFieldsDataAndSettingData()
    474. const frameParams = this.getFrameParams()
    475. this.saveStockSchema({
    476. ...this.baseInfo,
    477. frameParams: frameParams,
    478. customParams: {
    479. params: this.customFieldsData
    480. },
    481. stockParams: {
    482. params: this.storageFieldData
    483. },
    484. stockFrameId: this.stockFrameInfo.id
    485. })
    486. }
    487. })
    488. },
    489. /**
    490. * 模态框取消
    491. */
    492. handleCancel() {
    493. this.visible = false
    494. this.$refs.createBatchInfoRef.resetFields()
    495. this.form = {
    496. frameName: '',
    497. icon: '',
    498. prefix: '',
    499. name: '',
    500. unitId: undefined,
    501. capacity: undefined
    502. }
    503. this.stockFrameAttribute = []
    504. },
    505. /**
    506. * 根据库位种类id获取库位种类属性信息
    507. */
    508. async queryStockFrameFields(data) {
    509. const res = await queryStockFrameFields(data)
    510. if (res.code === '200') {
    511. this.stockFrameAttribute = res.data
    512. this.stockFrameAttribute.forEach(element => {
    513. this.paramTypeObj[element.id] = element.paramType
    514. this.$set(this.form, element.id, element.paramValues || [])
    515. // 校验规则
    516. this.dynamicValidate(element)
    517. })
    518. }
    519. },
    520. /**
    521. * 打开模态框
    522. */
    523. openCreateStockShemaModal(data, source) {
    524. this.source = source || ''
    525. this.visible = true
    526. this.stockFrameInfo = data
    527. this.form.frameName = this.stockFrameInfo.name
    528. this.queryStockFrameFields({ id: this.stockFrameInfo.id })
    529. }
    530. },
    531. watch: {}
    532. }
    533. </script>
    534. <style lang="scss" scoped></style>
    1. <template>
    2. <a-modal
    3. v-if="visible"
    4. @cancel="handleCancel"
    5. :title="title"
    6. :visible="visible"
    7. :width="800"
    8. :destoryOnClose="true"
    9. :bodyStyle="{ padding: '0px 10px', minHeight: '150px' }"
    10. >
    11. <a-form-model
    12. ref="stockInstanceFormRef"
    13. :labelCol="{ span: 10 }"
    14. :wrapperCol="{ span: 14 }"
    15. :model="form"
    16. :rules="rules"
    17. >
    18. <a-row :gutter="16" v-if="isShowCreateSelect">
    19. <a-col :span="12">
    20. <a-form-model-item label="创建方式" prop="createType">
    21. <a-radio-group v-model="form.createType" class="type-wrap">
    22. <a-radio :value="1">通过库位结构进行创建实例</a-radio>
    23. <a-radio :value="2">直接创建实例</a-radio>
    24. </a-radio-group>
    25. </a-form-model-item>
    26. </a-col>
    27. </a-row>
    28. <div v-if="form.createType === DIRECT_CREATE">
    29. <a-row :gutter="16" v-if="isShowCreateSelect">
    30. <a-col :span="12">
    31. <a-form-model-item label="库位元件" prop="schemaName">
    32. <a-button :disabled="disabled" @click="selectProduct()"
    33. ><a-icon type="fullscreen" :centered="true" />选择元件</a-button
    34. >
    35. <span class="link-type" @click="findStockSchemaInfo">{{
    36. selectSchemaInfo.referenceName
    37. }}</span>
    38. <a-input hidden v-model="form.schemaName"></a-input>
    39. </a-form-model-item>
    40. </a-col>
    41. </a-row>
    42. <a-row :gutter="16" v-if="isShowCreateSelect || title === '编辑名称'">
    43. <a-col :span="12">
    44. <a-form-model-item label="名称" prop="name">
    45. <a-input v-model="form.name"></a-input>
    46. </a-form-model-item>
    47. <a-form-model-item label="编号" prop="prefix">
    48. <a-input v-model="form.prefix"></a-input>
    49. </a-form-model-item>
    50. <!-- <a-spin :spinning="form.container"> -->
    51. <a-form-model-item
    52. label="关联容器"
    53. prop="container"
    54. v-if="form.container.length > 0"
    55. >
    56. <a-select v-model="containerName[0]">
    57. <a-select-option
    58. :key="element.id"
    59. v-for="element in form.container"
    60. :value="element.id"
    61. >
    62. {{ element.name }}
    63. </a-select-option>
    64. </a-select>
    65. </a-form-model-item>
    66. <!-- </a-spin> -->
    67. </a-col>
    68. <a-col
    69. :span="12"
    70. :key="item.id"
    71. v-for="item in schemaInfo.frameParams"
    72. >
    73. <a-form-model-item :label="item.paramName">
    74. <template
    75. v-if="
    76. paramTypeColumn.text === item.paramType ||
    77. paramTypeColumn.integer === item.paramType ||
    78. paramTypeColumn.float === item.paramType
    79. "
    80. >
    81. <a-input
    82. disabled
    83. v-if="item.isMultipleValue === 2"
    84. v-model="item.paramValues[0]"
    85. ></a-input>
    86. <a-select
    87. v-else
    88. disabled
    89. v-model="item.paramValues"
    90. :dropdownStyle="{ display: 'none' }"
    91. :dropdownMenuStyle="{ display: 'none' }"
    92. mode="tags"
    93. ></a-select>
    94. </template>
    95. <template v-else-if="paramTypeColumn.textArea === item.paramType">
    96. <a-input
    97. disabled
    98. :auto-size="{ minRows: 3, maxRows: 5 }"
    99. class="default-input"
    100. v-model="item.paramValues[0]"
    101. type="textarea"
    102. ></a-input>
    103. </template>
    104. <template
    105. v-else-if="paramTypeColumn.radioSelect === item.paramType"
    106. >
    107. <a-select v-model="item.paramValues[0]" disabled>
    108. <a-select-option
    109. :key="element"
    110. v-for="element in item.preDefinedValues"
    111. >
    112. {{ element }}
    113. </a-select-option>
    114. </a-select>
    115. </template>
    116. <template
    117. v-else-if="paramTypeColumn.multiSelect === item.paramType"
    118. >
    119. <a-select mode="multiple" v-model="item.paramValues" disabled>
    120. <a-select-option
    121. :key="element"
    122. v-for="element in item.preDefinedValues"
    123. >
    124. {{ element }}
    125. </a-select-option>
    126. </a-select>
    127. </template>
    128. <template v-else-if="paramTypeColumn.time === item.paramType">
    129. <a-date-picker
    130. disabled
    131. v-model="item.paramValues[0]"
    132. :showTime="true"
    133. ></a-date-picker>
    134. </template>
    135. <!-- <template v-else-if="paramTypeColumn.link === item.paramType">
    136. <span
    137. class="link-type"
    138. :key="ele.referenceId"
    139. v-for="ele in item.paramValues"
    140. @click="showProductLinkDetail(ele)"
    141. ><a-icon type="link" /> {{ ele.referenceName }}</span
    142. >
    143. </template> -->
    144. </a-form-model-item>
    145. </a-col>
    146. </a-row>
    147. </div>
    148. </a-form-model>
    149. <a-spin :spinning="loadingStockParams">
    150. <custom-fields
    151. v-show="
    152. (isShowCreateSelect &&
    153. form.createType === DIRECT_CREATE &&
    154. isShowExtraTable) ||
    155. (title === '编辑库位字段' && isShowExtraTable)
    156. "
    157. :customFields="params"
    158. ref="customFieldsRef"
    159. :showMode="showMode"
    160. @getData="getCustomFieldsData"
    161. ></custom-fields>
    162. <a-empty v-if="title === '编辑库位字段' && !isShowExtraTable"></a-empty>
    163. </a-spin>
    164. <select-stock-structure
    165. v-if="isShowCreateSelect && form.createType === STRUCTURE_CREATE"
    166. ref="selectStockStructureRef"
    167. ></select-stock-structure>
    168. <select-schema-modal ref="selectSchemaModalRef"></select-schema-modal>
    169. <stock-schema-info-modal
    170. ref="stockSchemaInfoModalRef"
    171. ></stock-schema-info-modal>
    172. <template slot="footer">
    173. <a-button key="back" @click="handleCancel">
    174. 取消
    175. </a-button>
    176. <a-button
    177. key="submit"
    178. type="primary"
    179. :loading="submitLoading"
    180. @click="handleOk"
    181. >
    182. 确定
    183. </a-button>
    184. </template>
    185. </a-modal>
    186. </template>
    187. <script>
    188. import {
    189. queryCurrentStockStructureDetail,
    190. getTextInfo,
    191. queryStockSchemasDetail,
    192. queryStockFramesDetailBySchemaId2
    193. } from '@/api/material/locationSetting'
    194. import {
    195. addStockStructure,
    196. editStockStructure,
    197. editStructureTextInfos,
    198. editStructureField
    199. } from '@/api/material/locationSetting'
    200. import {
    201. queryPublshedStockSolutions,
    202. initStockSolution
    203. } from '@/api/material/structure-set'
    204. import { CUSTOM_FIELD_SHOW_MODE } from '@/views/materialcenter/productManagement/components/comm/constValues'
    205. import CustomFields from '@/views/materialcenter/productManagement/components/ProductCustomFields'
    206. import SelectSchemaModal from './SelectSchemaModal'
    207. import StockSchemaInfoModal from './StockSchemaInfoModal'
    208. import SelectStockStructure from './SelectStockStructure'
    209. const STRUCTURE_CREATE = 1
    210. const DIRECT_CREATE = 2
    211. export default {
    212. props: {
    213. createdCallback: Function
    214. },
    215. components: {
    216. CustomFields,
    217. SelectSchemaModal,
    218. StockSchemaInfoModal,
    219. SelectStockStructure
    220. },
    221. data() {
    222. return {
    223. isEdit: false, // 是否编辑状态
    224. visible: false,
    225. editChannel: 'name',
    226. title: '新建库位实例',
    227. id: '',
    228. stockStructureVersion: undefined,
    229. form: {
    230. createType: DIRECT_CREATE, // 1.结构创建 2.直接创建
    231. name: '',
    232. schemaName: '',
    233. prefix: '',
    234. container: []
    235. },
    236. rules: {
    237. name: [
    238. {
    239. min: 1,
    240. max: 64,
    241. required: true,
    242. message: '库位实例名称的长度在1~64位之间',
    243. trigger: 'change'
    244. }
    245. ],
    246. prefix: [
    247. {
    248. required: true,
    249. message: '编号必填',
    250. trigger: 'change'
    251. }
    252. ],
    253. schemaName: [
    254. {
    255. required: true,
    256. message: '请选择库位元件',
    257. trigger: ['blur', 'change']
    258. }
    259. ],
    260. container: [
    261. {
    262. required: true,
    263. message: '关联容器必填',
    264. trigger: 'change'
    265. }
    266. ]
    267. },
    268. schemaInfo: {
    269. frameParams: []
    270. },
    271. params: [],
    272. selectSchemaInfo: {
    273. referenceName: '',
    274. referenceId: '',
    275. referenceType: ''
    276. },
    277. parentStructureId: '',
    278. disabled: false,
    279. showMode: CUSTOM_FIELD_SHOW_MODE.batchValue,
    280. DIRECT_CREATE,
    281. STRUCTURE_CREATE,
    282. loadingStockParams: false,
    283. submitLoading: false,
    284. containerName: []
    285. }
    286. },
    287. computed: {
    288. isShowCreateSelect() {
    289. return !this.id
    290. },
    291. isShowExtraTable() {
    292. if (this.loadingStockParams) {
    293. return true
    294. }
    295. return !_.isEmpty(this.params)
    296. }
    297. },
    298. methods: {
    299. /**
    300. * 模态框确定
    301. */
    302. handleOk() {
    303. if (this.isShowCreateSelect) {
    304. if (this.form.createType === DIRECT_CREATE) {
    305. this.directCreate()
    306. } else {
    307. this.structureCreate()
    308. }
    309. } else {
    310. if (this.editChannel === 'name') {
    311. this.editStockStructure({
    312. id: this.id,
    313. prefix: this.form.prefix,
    314. name: this.form.name
    315. })
    316. } else {
    317. this.directCreate()
    318. }
    319. }
    320. },
    321. /**
    322. * 直接创建
    323. */
    324. directCreate() {
    325. this.$refs.stockInstanceFormRef.validate(valid => {
    326. valid && this.$refs.customFieldsRef.getData()
    327. })
    328. },
    329. /**
    330. * 结构创建
    331. */
    332. structureCreate() {
    333. if (this.$refs.selectStockStructureRef.getSelectedId()) {
    334. this.initStockSolution({
    335. solutionId: this.$refs.selectStockStructureRef.getSelectedId(),
    336. parentStructureId: this.parentStructureId
    337. })
    338. } else {
    339. this.$message.error('请选择需要实例化的库位结构')
    340. }
    341. },
    342. /**
    343. * 库位结构实例化
    344. */
    345. async initStockSolution(data) {
    346. const res = await initStockSolution(data)
    347. if (res.code === '200') {
    348. this.handleCancel()
    349. this.createdCallback()
    350. }
    351. },
    352. /**
    353. * 模态框取消
    354. */
    355. handleCancel() {
    356. this.isEdit = false
    357. this.visible = false
    358. this.disabled = false
    359. this.selectSchemaInfo = {
    360. referenceName: '',
    361. referenceId: '',
    362. referenceType: ''
    363. }
    364. this.form = {
    365. createType: 2,
    366. name: '',
    367. schemaName: '',
    368. prefix: ''
    369. }
    370. this.params = []
    371. this.parentStructureId = ''
    372. this.id = ''
    373. this.title = '新建库位实例'
    374. this.$refs.stockInstanceFormRef.resetFields()
    375. },
    376. /**
    377. * 打开模态框
    378. */
    379. openModal(currentNodeInfo) {
    380. this.parentStructureId = currentNodeInfo.structureId
    381. this.visible = true
    382. },
    383. openModalEdit(currentNodeInfo, channel) {
    384. console.log('records', currentNodeInfo)
    385. this.editChannel = channel
    386. this.isEdit = true
    387. this.parentStructureId = currentNodeInfo.parentStructureId
    388. this.id = currentNodeInfo.id
    389. this.disabled = true
    390. this.visible = true
    391. switch (channel) {
    392. case 'name':
    393. this.title = '编辑名称'
    394. this.form.name = currentNodeInfo.name
    395. this.form.prefix = currentNodeInfo.prefix
    396. break
    397. case 'field':
    398. this.title = '编辑库位字段'
    399. this.queryCurrentStockStructureDetail(this.id)
    400. this.stockStructureVersion = currentNodeInfo.version
    401. break
    402. }
    403. },
    404. /**
    405. * 查询实例的详情信息
    406. */
    407. async queryCurrentStockStructureDetail(id) {
    408. this.loadingStockParams = true
    409. const res = await queryCurrentStockStructureDetail({ id }).finally(() => {
    410. this.loadingStockParams = false
    411. })
    412. if (res.code === '200') {
    413. this.form.schemaName = res.data.schemaName
    414. // 改变 selectSchemaInfo => 改变 params
    415. this.selectSchemaInfo = {
    416. stockParams: res.data.customParams || [],
    417. referenceName: res.data.schemaName,
    418. referenceId: res.data.schemaId
    419. }
    420. }
    421. },
    422. /**
    423. * 选择元件
    424. */
    425. selectProduct() {
    426. this.$refs.selectSchemaModalRef.openSelectProductInfoModal(
    427. this.selectSchemaInfo
    428. )
    429. },
    430. /**
    431. * 查看库位元件详情
    432. */
    433. findStockSchemaInfo() {
    434. this.$refs.stockSchemaInfoModalRef.openStockSchemaInfoModal({
    435. id: this.selectSchemaInfo.referenceId
    436. })
    437. },
    438. /**
    439. * 获取自定义字段的数据 确认模态框时调用
    440. */
    441. getCustomFieldsData(data) {
    442. if (this.id) {
    443. // 编辑
    444. this.editStockStructure({
    445. name: this.form.name,
    446. customParams: data,
    447. prefix: this.form.prefix,
    448. schemaId: this.selectSchemaInfo.referenceId,
    449. id: this.id,
    450. version: this.stockStructureVersion
    451. })
    452. } else {
    453. this.addStockStructure({
    454. name: this.form.name,
    455. customParams: data,
    456. prefix: this.form.prefix,
    457. schemaId: this.selectSchemaInfo.referenceId,
    458. parentStructureId: this.parentStructureId
    459. })
    460. }
    461. },
    462. /**
    463. * 保存库位实例
    464. */
    465. async addStockStructure(data) {
    466. const res = await addStockStructure(data)
    467. if (res.code === '200') {
    468. this.handleCancel()
    469. // 添加成功后需要执行的回调
    470. this.createdCallback()
    471. }
    472. },
    473. /**
    474. * 编辑库位实例
    475. */
    476. async editStockStructure(data) {
    477. console.log('editData', data)
    478. let res = []
    479. switch (this.editChannel) {
    480. case 'name':
    481. this.submitLoading = true
    482. res = await editStructureTextInfos({
    483. parentId: this.parentStructureId,
    484. textInfos: [{ id: data.id, prefix: data.prefix, name: data.name }]
    485. })
    486. this.submitLoading = false
    487. if (res.code === '200') {
    488. this.$message.success(res.msg)
    489. }
    490. break
    491. case 'field':
    492. res = await editStructureField({
    493. id: this.id,
    494. fields: data.customParams.map(item => {
    495. return {
    496. paramName: item.paramName,
    497. paramValue: item.paramValue,
    498. id: item.id
    499. }
    500. }),
    501. version: data.version
    502. })
    503. break
    504. }
    505. if (res.code === '200') {
    506. // this.stockStructureVersion = res.data.version
    507. this.handleCancel()
    508. this.createdCallback()
    509. }
    510. },
    511. /**
    512. * 根据元件 id 获取后端返回自动填充信息
    513. */
    514. async getTextInfo(id) {
    515. const { data } = await getTextInfo(id)
    516. this.form.name = data.name
    517. this.form.prefix = data.prefix
    518. },
    519. async getFullContainerInfo() {
    520. const res = await queryStockSchemasDetail({
    521. stockFrameId: '3',
    522. pageSize: -1
    523. })
    524. if (res.code === '200') {
    525. return res.data.result
    526. }
    527. },
    528. async getContainer(id) {
    529. const res = await queryStockFramesDetailBySchemaId2(id)
    530. if (res.code === '200') {
    531. console.log(res)
    532. if (
    533. res.data.frameId === '2' ||
    534. res.data.frameId === '4' ||
    535. (res.data.frameId === '1' &&
    536. res.data.frameParams[1]['paramValues'].length !== 0)
    537. ) {
    538. return res.data.frameParams[2].paramValues
    539. }
    540. }
    541. },
    542. async getSelected(id) {
    543. this.form.container = []
    544. this.containerName = []
    545. this.$nextTick(async () => {
    546. const [res1, res2] = await Promise.all([
    547. this.getContainer(id),
    548. this.getFullContainerInfo()
    549. ])
    550. this.containerName = res1
    551. if (res1) {
    552. this.form.container = res2
    553. }
    554. console.log(res1, res2)
    555. })
    556. }
    557. },
    558. watch: {
    559. selectSchemaInfo: {
    560. handler(newSelectSchemaInfo) {
    561. if (!this.isEdit) {
    562. const { referenceId } = newSelectSchemaInfo
    563. referenceId && this.getTextInfo(referenceId)
    564. this.getSelected(referenceId)
    565. }
    566. this.form.schemaName = newSelectSchemaInfo.referenceName
    567. this.params = newSelectSchemaInfo.stockParams
    568. // 手动校验 schemaName 字段
    569. this.$refs.stockInstanceFormRef &&
    570. this.$refs.stockInstanceFormRef.validateField &&
    571. this.$refs.stockInstanceFormRef.validateField('schemaName')
    572. },
    573. deep: true
    574. }
    575. }
    576. }
    577. </script>
    578. <style lang="scss" scoped>
    579. .type-wrap {
    580. display: flex;
    581. flex-direction: column;
    582. ::v-deep .ant-radio-wrapper {
    583. padding: 5px 10px;
    584. margin-bottom: 5px;
    585. border: 1px solid #e8e8e8;
    586. background-color: #fafafa;
    587. }
    588. }
    589. </style>
    <template>
      <div class="product-base-info-form">
        <a-form-model
          ref="productBaseInfoRef"
          :model="form"
          :rules="rules"
          labelAlign="left"
          :label-col="labelCol"
          :wrapper-col="wrapperCol"
          :colon="false"
        >
          <div v-if="frameId === STOCK_FRAME_TYPE.CONTAINER" :gutter="12">
            <div v-if="!disabled">
              <a-form-model-item
                prop="icon"
                :label-col="labelColItem"
                :wrapper-col="{ span: 4 }"
              >
                <a-select v-model="form.icon" placeholder="图标">
                  <a-select-option
                    :key="index"
                    :value="item"
                    v-for="(item, index) in productIcons"
                  >
                    <!-- <a-icon :type="item" style="font-size: 16px" /> -->
                    <svg-icon :icon-class="item" :style="{ fontSize: '16px' }" />
                  </a-select-option>
                </a-select>
              </a-form-model-item>
    
              <section class="column-item">
                <p class="lable">产品名称</p>
                <a-form-model-item
                  class="right"
                  prop="name"
                  :label-col="labelColItem"
                  :wrapper-col="{ span: 8 }"
                >
                  <a-input v-model="form.name" placeholder="名称"></a-input>
                </a-form-model-item>
              </section>
    
              <section class="column-item">
                <p class="lable">编码(Prefix)</p>
                <a-form-model-item
                  class="right"
                  prop="prefix"
                  :label-col="labelColItem"
                  :wrapper-col="{ span: 8 }"
                >
                  <a-input v-model="form.prefix" placeholder="prefix"></a-input>
                </a-form-model-item>
              </section>
            </div>
            <a-form-model-item label="容器单位" prop="unitId">
              <span v-if="disabled">
                {{ unitOptions.filter(item => item.id == form.unitId)[0].unitName }}
              </span>
              <a-select
                v-else
                @dropdownVisibleChange="dropdownVisibleChange"
                v-model="form.unitId"
                placeholder="请选择"
              >
                <a-select-option
                  :key="item.id"
                  :value="item.id"
                  v-for="item in unitOptions"
                >
                  {{ item.unitName }}
                </a-select-option>
                <template v-slot:notFoundContent v-if="spinning">
                  <a-spin :spinning="spinning"></a-spin>
                </template>
              </a-select>
            </a-form-model-item>
            <a-form-model-item label="上限容量" prop="capacity">
              <span v-if="disabled">{{ form.capacity }}</span>
              <a-input v-else v-model="form.capacity"></a-input>
            </a-form-model-item>
          </div>
          <!-- frameId !== STOCK_FRAME_TYPE.CONTAINER -->
          <!-- 可编辑状态 -->
          <div v-else>
            <div v-if="!disabled">
              <a-form-model-item
                prop="icon"
                :label-col="labelColItem"
                :wrapper-col="{ span: 6 }"
                label="图标"
              >
                <a-select v-model="form.icon" placeholder="图标">
                  <a-select-option
                    :key="index"
                    :value="item"
                    v-for="(item, index) in productIcons"
                  >
                    <!-- <a-icon :type="item" style="font-size: 16px" /> -->
                    <svg-icon :icon-class="item" :style="{ fontSize: '16px' }" />
                  </a-select-option>
                </a-select>
              </a-form-model-item>
              <a-form-model-item
                class="right"
                prop="name"
                :label-col="labelColItem"
                :wrapper-col="{ span: 8 }"
                label="产品名称"
              >
                <a-input v-model="form.name" placeholder="名称"></a-input>
              </a-form-model-item>
              <a-form-model-item
                class="right"
                prop="prefix"
                :label-col="labelColItem"
                :wrapper-col="{ span: 8 }"
                label="编码(Prefix)"
              >
                <a-input v-model="form.prefix" placeholder="prefix"></a-input>
              </a-form-model-item>
            </div>
          </div>
          <!-- <div class="custom-fields"> -->
          <a-form-model-item
            v-for="item in productValues"
            :label="item.paramName"
            :prop="item.id"
            :key="item.id"
            :label-col="labelColItem"
            :wrapper-col="wrapperColItem"
          >
            <div
              v-if="
                paramTypeColumn.text === item.paramType ||
                  paramTypeColumn.integer === item.paramType ||
                  paramTypeColumn.float === item.paramType
              "
            >
              <template v-if="disabled">
                <span v-if="item.isMultipleValue === 2">{{
                  form[item.id][0]
                }}</span>
                <a-tag v-else :key="index" v-for="(ele, index) in form[item.id]">
                  {{ ele }}
                </a-tag>
              </template>
              <template v-else>
                <a-input
                  v-if="item.isMultipleValue === 2"
                  v-model="form[item.id][0]"
                ></a-input>
                <a-select
                  v-else
                  v-model="form[item.id]"
                  :dropdownStyle="{ display: 'none' }"
                  :dropdownMenuStyle="{ display: 'none' }"
                  mode="tags"
                ></a-select>
              </template>
            </div>
            <div v-else-if="paramTypeColumn.textArea === item.paramType">
              <span v-if="disabled">{{ form[item.id][0] }}</span>
              <a-input
                v-else
                :auto-size="{ minRows: 3, maxRows: 5 }"
                v-model="form[item.id][0]"
                type="textarea"
              ></a-input>
            </div>
            <div v-else-if="paramTypeColumn.radioSelect === item.paramType">
              <span v-if="disabled">{{ form[item.id][0] }}</span>
              <a-select v-else v-model="form[item.id][0]">
                <a-select-option
                  :key="element"
                  v-for="element in item.preDefinedValues"
                >
                  {{ element }}
                </a-select-option>
              </a-select>
            </div>
            <div v-else-if="paramTypeColumn.multiSelect === item.paramType">
              <div v-if="disabled">
                <a-tag :key="index" v-for="(ele, index) in form[item.id]">
                  {{ ele }}
                </a-tag>
              </div>
              <a-select v-else mode="multiple" v-model="form[item.id]">
                <a-select-option
                  :key="element"
                  v-for="element in item.preDefinedValues"
                >
                  {{ element }}
                </a-select-option>
              </a-select>
            </div>
            <div v-else-if="paramTypeColumn.time === item.paramType">
              <span v-if="disabled">{{
                item.paramValues[0] &&
                  moment(item.paramValues[0]).format('YYYY-MM-DD HH:mm:ss')
              }}</span>
              <a-date-picker
                v-else
                v-model="item.paramValues[0]"
                :showTime="true"
              ></a-date-picker>
            </div>
            <div v-else-if="paramTypeColumn.link === item.paramType">
              <!-- <span>产品链接类型。。。</span> -->
              <!-- 展示产品链接 -->
              <div v-if="disabled">
                <div class="link-item-box">
                  <li
                    class="link-type"
                    :key="ele.referenceId"
                    v-for="ele in item.paramValues"
                    @click="showProductLinkDetail(ele)"
                  >
                    <a-icon type="link" />{{ ele.referenceName }}
                  </li>
                </div>
              </div>
              <div v-else>
                <a-button @click="selectProduct(item.paramValues)" size="small"
                  ><a-icon type="fullscreen" />选择产品</a-button
                >
                <div class="link-item-box">
                  <li
                    class="link-type"
                    :key="ele.referenceId"
                    v-for="ele in item.paramValues"
                    @click="showProductLinkDetail(ele)"
                  >
                    <a-icon type="link" /> {{ ele.referenceName }}
                  </li>
                </div>
              </div>
            </div>
            <div v-else-if="paramTypeColumn.cycle === item.paramType">
              <div v-if="disabled">
                <span
                  v-if="item.paramValues[0].value && item.paramValues[0].cycleType"
                  >{{
                    `${item.paramValues[0].value} ${
                      CycleTypeInfo[item.paramValues[0].cycleType]
                    }`
                  }}</span
                >
              </div>
              <!-- 周期 -->
              <CycleTypeCom
                v-else
                :info="item.paramValues[0]"
                style="width: 260px;"
              />
            </div>
            <div v-else-if="paramTypeColumn.container === item.paramType">
              <div>
                <a-select v-model="containerName[0]">
                  <a-select-option
                    :key="element.id"
                    v-for="element in form.container"
                    :value="element.id"
                  >
                    {{ element.name }}
                  </a-select-option>
                </a-select>
              </div>
            </div>
          </a-form-model-item>
          <!-- </div> -->
        </a-form-model>
        <product-link-modal ref="productLinkModalRef"></product-link-modal>
        <product-base-info-modal
          ref="productBaseInfoModalRef"
        ></product-base-info-modal>
      </div>
    </template>
    
    <script>
    import moment from 'moment'
    import {
      queryStockSchemasDetail,
      queryStockFramesDetailBySchemaId2
    } from '@/api/material/locationSetting'
    import {
      handleMaterialValidateCodePlus,
      validateInteger,
      validateFloat,
      validateFloatNumber,
      validateArrRequired
    } from '@/common/inspectFunction'
    import {
      paramTypeColumn,
      productIcons,
      STOCK_FRAME_TYPE,
      VOLUME_TYPE_UNIT,
      CycleTypeInfo
    } from '@/common/global'
    
    import { getFullUnitInfo } from '@/api/system/unit'
    
    import ProductBaseInfoModal from './ProductBaseInfoModal'
    import ProductLinkModal from './ProductLinkModal'
    import CycleTypeCom from './fieldRuleSetting/CycleTypeCom'
    
    export default {
      props: {
        productValues: {
          type: Array,
          default() {
            return []
          }
        },
        productSelfInfo: {
          type: Object,
          default() {
            return {}
          }
        },
        icons: {
          type: Array,
          default() {
            return []
          }
        },
        frameId: {
          type: String,
          default() {
            return ''
          }
        },
        referenceId: {
          type: String,
          default() {
            return ''
          }
        }
      },
      components: {
        ProductBaseInfoModal,
        ProductLinkModal,
        CycleTypeCom
      },
      data() {
        return {
          CycleTypeInfo,
          productIcons: this.icons,
          labelCol: { span: 8 },
          wrapperCol: { span: 12 },
          labelColItem: { span: 8 },
          wrapperColItem: { span: 12 },
          paramTypeColumn: Object.freeze(paramTypeColumn),
          baseInfo: {
            prefix: '',
            name: '',
            icon: '',
            unitId: undefined,
            capacity: undefined,
            version: undefined
          },
          form: {
            prefix: '',
            name: '',
            icon: '',
            unitId: undefined,
            capacity: '',
            version: undefined,
            container: []
          },
          rules: {
            prefix: [
              { required: true, message: '请填写编号', trigger: 'blur' },
              {
                min: 1,
                max: 32,
                message: '编号长度在1-32个字符之间',
                trigger: 'change'
              },
              {
                validator: this.handleMaterialValidateCodePlus,
                message: '编号格式不正确',
                trigger: 'change'
              }
            ],
            unitId: [{ required: true, message: '请填写单位', trigger: 'blur' }],
            capacity: [
              {
                validator: this.validateFloatNumber,
                message: '容量格式不正确',
                trigger: 'change'
              }
            ],
            name: [
              { required: true, message: '必填', trigger: 'change' },
              {
                min: 1,
                max: 32,
                message: '名称长度在1-32个字符之间',
                trigger: 'change'
              }
            ],
            container: [
              {
                required: true,
                message: '关联容器必填',
                trigger: 'change'
              }
            ]
          },
          disabled: true,
          // 后端需要的paramType
          paramTypeObj: {},
          STOCK_FRAME_TYPE: Object.freeze(STOCK_FRAME_TYPE),
          unitOptions: [],
          ContainerOptions: [],
          containerName: [],
          spinning: true
        }
      },
      methods: {
        moment,
        dropdownVisibleChange(open) {
          // this.spinning = true
          open && _.isEmpty(this.unitOptions) && this.getFullUnitInfo()
        },
    
        /**
         * 获取数据库预选单位
         */
        async getFullUnitInfo() {
          this.spinning = true
          const res = await getFullUnitInfo({
            artifacts: [VOLUME_TYPE_UNIT],
            pageSize: -1
          }).finally(() => {
            this.spinning = false
          })
          if (res.code === '200') {
            this.unitOptions = res.data
          }
        },
        // dropdownVisibleChange2(open) {
        //   open && _.isEmpty(this.ContainerOptions) && this.getFullContainerInfo()
        // },
        /**
         * 获取数据库容器
         */
        async getFullContainerInfo() {
          this.spinning = true
          const res = await queryStockSchemasDetail({
            stockFrameId: '3',
            pageSize: -1
          }).finally(() => {
            this.spinning = false
          })
          if (res.code === '200') {
            this.ContainerOptions = res.data.result
            return res.data.result
          }
        },
    
        async getContainer(id) {
          const res = await queryStockFramesDetailBySchemaId2(id)
          if (res.code === '200') {
            console.log(res)
            if (
              res.data.frameId === '2' ||
              res.data.frameId === '4' ||
              (res.data.frameId === '1' &&
                res.data.frameParams[1]['paramValues'].length !== 0)
            ) {
              return res.data.frameParams[2].paramValues
            }
          }
        },
        async getSelected(id) {
          this.form.container = []
          this.containerName = []
          this.$nextTick(async () => {
            const [res1, res2] = await Promise.all([
              this.getContainer(id),
              this.getFullContainerInfo()
            ])
            this.containerName = res1
            if (res1) {
              this.form.container = res2
            }
            console.log(res1, res2)
          })
        },
        /**
         * 自定义编码规则
         */
        handleMaterialValidateCodePlus,
        /**
         * 整数自定义验证
         */
        validateInteger,
        /**
         * 浮点数自定义验证
         */
        validateFloat,
        validateFloatNumber,
    
        validateArrRequired,
    
        /**
         * 验证表单数据规则是否匹配
         */
        validateFormData() {
          let flag = false
          this.$refs.productBaseInfoRef.validate(valid => {
            flag = valid
          })
          return flag
        },
        /**
         * 选择产品
         */
        selectProduct(paramValues) {
          this.$refs.productLinkModalRef.openSelectProductInfoModal(paramValues)
        },
        /**
         * 展示产品详情
         */
        showProductLinkDetail(item) {
          this.$refs.productBaseInfoModalRef.openProductInfoModal({
            id: item.referenceId
          })
        },
        /**
         * 传输产品基本信息和产品种类自定义字段
         */
        getFullData(callback) {
          if (!this.validateFormData()) {
            callback(false)
            return
          }
          const target = _.cloneDeep(this.form)
          let targetArr = []
          // {...this.baseInfo} = target
          Object.keys(this.baseInfo).forEach(key => {
            this.baseInfo[key] = target[key]
            delete target[key]
          })
          Object.keys(target).forEach(key => {
            targetArr.push({
              id: key,
              paramValues: target[key],
              paramType: this.paramTypeObj[key]
            })
          })
          callback({ ...this.baseInfo, productValues: targetArr })
        },
        /**
         * 改变为可以编辑的状态
         */
        changeIsShowStatus() {
          this.disabled = false
        },
        /**
         * 改变为不可编辑的状态
         */
        changeNoShowStatus() {
          this.disabled = true
        },
        /**
         * 清除 form 表单 多余信息
         */
        resetFormInfo() {
          this.$refs.productBaseInfoRef &&
            this.$refs.productBaseInfoRef.resetFields &&
            this.$refs.productBaseInfoRef.resetFields()
          const baseInfoKeys = Object.keys(this.baseInfo)
          Object.keys(this.form)
            .filter(item => {
              return !baseInfoKeys.includes(item)
            })
            .forEach(key => {
              delete this.form[key]
            })
        }
      },
      created() {
        this.frameId === STOCK_FRAME_TYPE.CONTAINER &&
          this.dropdownVisibleChange(true)
        this.getSelected(this.referenceId)
      },
      watch: {
        productValues: {
          handler(newProductValues) {
            // console.log(newProductValues)
            this.resetFormInfo()
            newProductValues.forEach(element => {
              this.paramTypeObj[element.id] = element.paramType
              this.$set(this.form, element.id, element.paramValues || [])
              // 必填项
              if (element.isRequired === 1) {
                const requiredInfo = [
                  { validator: this.validateArrRequired, trigger: 'change' },
                  { required: true, message: '必填', trigger: 'change' }
                ]
                !this.rules[element.id] &&
                  this.$set(this.rules, element.id, requiredInfo)
                if (
                  this.rules[element.id] &&
                  this.rules[element.id].findIndex(item => item.required) < 0
                ) {
                  this.rules[element.id].push(...requiredInfo)
                }
                // this.rules[element.id] = [{ required: true, message: '必填', trigger: 'change' }]
              }
              // 整数
              if (element.paramType === this.paramTypeColumn.integer) {
                !this.rules[element.id] &&
                  this.$set(this.rules, element.id, [
                    { validator: this.validateInteger }
                  ])
                this.rules[element.id] &&
                  this.rules[element.id].push({
                    validator: this.validateInteger
                  })
              }
              // 浮点数
              if (element.paramType === this.paramTypeColumn.float) {
                !this.rules[element.id] &&
                  this.$set(this.rules, element.id, [
                    { validator: this.validateFloat }
                  ])
                this.rules[element.id] &&
                  this.rules[element.id].push({
                    validator: this.validateFloat
                  })
              }
            })
          },
          immediate: true
        },
        productSelfInfo: {
          handler(newProductSelfInfo) {
            this.form.name = newProductSelfInfo.name
            this.form.prefix = newProductSelfInfo.prefix
            this.form.icon = newProductSelfInfo.icon
            this.form.unitId = newProductSelfInfo.unitId
            this.form.capacity = newProductSelfInfo.capacity
            this.form.version = newProductSelfInfo.version
            this.form.container = newProductSelfInfo.container
          },
          immediate: true,
          deep: true
        },
        frameId: {
          handler(newFramaId) {
            newFramaId === STOCK_FRAME_TYPE.CONTAINER &&
              this.dropdownVisibleChange(true)
          },
          immediate: true
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .product-base-info-form {
      .link-item-box {
        .link-type {
          margin: 0 2px;
          display: inline-block;
        }
      }
      & > .columns {
        display: flex;
        flex-flow: column;
        section.column-item {
          display: flex;
          flex-flow: row wrap;
          justify-content: space-between;
          align-items: center;
          p.lable {
            flex-grow: 1;
            color: #8c8c8c;
            font-size: 14px;
            user-select: none;
          }
          .right {
            width: 304px;
          }
        }
      }
    }
    .custom-fields,
    .columns {
      margin-right: 25px;
      ::v-deep div.ant-row.ant-form-item {
        display: flex !important;
        flex-flow: row wrap;
        justify-content: space-between;
        align-items: center;
      }
      ::v-deep div.ant-col.ant-col-8.ant-form-item-label.ant-form-item-label-left {
        background-color: red;
        flex-grow: 1;
        color: #8c8c8c;
        font-size: 14px;
        user-select: none;
      }
      ::v-deep .ant-col.ant-col-12.ant-form-item-control-wrapper {
        width: 304px;
        input.ant-input {
          width: 304px;
        }
      }
    }
    </style>
    
    <a-col>
      <div>
      <span>可用库位: </span>
    <span>{{ item.usedLocationAmount }}</span>
    </div>
    <div>
      <span>总库位: </span>
    <span>{{ item.totalLocationAmount }}</span>
    </div>
    </a-col>
    
    <!-- TODO -->
    <template>
      <div class="product-info-detail-right">
        <!-- 具体产品详细信息 -->
        <a-spin :spinning="isLoading">
          <a-col :span="10">
            <div class="product-info-content">
              <div class="product-info-content-head">
                <a-space>
                  <span
                    ><!-- <a-icon :type="productSelfInfo.icon" /> -->
                    <svg-icon :icon-class="productSelfInfo.icon" />
                    {{ productSelfInfo.name }}</span
                  >
                  <span
                    :style="{
                      fontWeight: 'normal',
                      fontSize: '12px',
                      color: '#bfbfbf'
                    }"
                    >PREFIX: {{ productSelfInfo.prefix }}</span
                  >
                </a-space>
                <div>
                  <a-button
                    v-if="operatorName[1] === 'edit'"
                    @click="e => changeCradStatus(1, e)"
                    size="small"
                    icon="edit"
                  />
                </div>
              </div>
              <div
                :class="
                  operatorName[1] === 'ok'
                    ? 'product-info-content-card'
                    : 'product-info-content-card rquired-no-star'
                "
              >
                <product-base-info-form
                  ref="productBaseInfoFormRef"
                  :productSelfInfo="productSelfInfo"
                  :productValues="frameParams"
                  :icons="schemaIcons"
                  :frameId="frameId"
                  :referenceId="referenceId"
                ></product-base-info-form>
                <div class="product-info-content-card-footer">
                  <a-space v-if="operatorName[1] === 'ok'">
                    <a-button size="small" @click="e => backCradEditStatus(1, e)"
                      >取消</a-button
                    >
                    <a-button
                      type="primary"
                      size="small"
                      @click="e => changeCradStatus(1, e)"
                      >提交</a-button
                    >
                  </a-space>
                </div>
              </div>
              <div class="product-info-content-card">
                <div class="product-info-content-card-header">
                  <span>附加信息</span>
                  <div>
                    <a-button
                      v-if="operatorName[2] === 'edit'"
                      @click="e => changeCradStatus(2, e)"
                      size="small"
                      icon="edit"
                    />
                  </div>
                </div>
                <a-descriptions
                  v-if="operatorName[2] === 'edit'"
                  :column="1"
                  size="small"
                  bordered
                >
                  <a-descriptions-item
                    :label="item.paramName"
                    :key="item.id"
                    v-for="item in customFields"
                  >
                    <span class="info-value">{{ item.paramValue }}</span>
                  </a-descriptions-item>
                </a-descriptions>
                <div v-show="operatorName[2] === 'ok'">
                  <a-alert message="进入编辑状态,暂未保存更新" banner />
                  <product-custom-fields
                    ref="productCustomFieldsRef"
                    @getData="getSchemaFieldsData"
                    :customFields="customFields"
                  ></product-custom-fields>
                  <div class="product-info-content-card-footer">
                    <a-space>
                      <a-button size="small" @click="e => backCradEditStatus(2, e)"
                        >取消</a-button
                      >
                      <a-button
                        type="primary"
                        size="small"
                        @click="e => changeCradStatus(2, e)"
                        >提交</a-button
                      >
                    </a-space>
                  </div>
                </div>
              </div>
            </div>
          </a-col>
          <a-col :span="14">
            <div>
              <a-tabs
                :default-active-key="titleKey"
                @change="key => onTabChange(key, 'titleKey')"
                size="small"
              >
                <a-tab-pane key="1" tab="相关库位">
                  <batch-info-table-list
                    :parentId="productInfoId"
                  ></batch-info-table-list>
                </a-tab-pane>
                <a-tab-pane key="2" tab="库位设置" force-render>
                  <div class="bmy-tab-pane-content">
                    <storage-location
                      ref="storageLocationRef"
                      @getData="getStorageLocationFieldsData"
                      :customFields="storageFields"
                      :showMode="showMode.productKey"
                    >
                    </storage-location>
                    <div class="product-info-content-card-footer">
                      <a-space>
                        <a-button
                          type="primary"
                          size="small"
                          @click="e => changeCradStatus(3, e)"
                          >提交</a-button
                        >
                      </a-space>
                    </div>
                  </div>
                </a-tab-pane>
              </a-tabs>
            </div>
          </a-col>
    
          <!-- <a-row :gutter="16">
            <a-col :span="12">
              <a-card
                class="card product-fields"
                title="基本信息"
                :class="{ 'product-forbidden': operatorName[1] === 'edit' }"
              >
                <a slot="extra" @click="(e) => changeCradStatus(1, e)">{{
                  operatorName[1] === "edit" ? "编辑" : "确认"
                }}</a>
                <product-base-info-form
                  ref="productBaseInfoFormRef"
                  :productSelfInfo="productSelfInfo"
                  :productValues="frameParams"
                  :icons="schemaIcons"
                  :frameId="frameId"
                  :class="{ forbidden: operatorName[1] === 'edit' }"
                ></product-base-info-form>
              </a-card>
            </a-col>
            <a-col :span="12">
              <a-card
                class="card product-fields"
                :class="{ 'product-forbidden': operatorName[2] === 'edit' }"
                :tab-list="tabListTitle"
                :active-tab-key="titleKey"
                @tabChange="(key) => onTabChange(key, 'titleKey')"
              >
                <a
                  class="link-button"
                  slot="tabBarExtraContent"
                  @click="(e) => changeCradStatus(2, e)"
                  >{{ operatorName[2] === "edit" ? "编辑" : "确认" }}</a
                >
                <a-alert
                  v-if="operatorName[2] === 'ok'"
                  message="进入编辑状态,暂未保存更新"
                  banner
                />
                <product-custom-fields
                  v-show="titleKey === '1'"
                  ref="productCustomFieldsRef"
                  @getData="getSchemaFieldsData"
                  :customFields="customFields"
                  :class="{ forbidden: operatorName[2] === 'edit' }"
                ></product-custom-fields>
    
                <storage-location
                  v-show="titleKey === '2'"
                  ref="storageLocationRef"
                  @getData="getStorageLocationFieldsData"
                  :class="{ forbidden: operatorName[2] === 'edit' }"
                  :customFields="storageFields"
                  :showMode="showMode.productKey"
                >
                </storage-location>
              </a-card>
            </a-col>
          </a-row>
          <a-row style="margin-top: 16px">
            <a-col :span="24">
              <a-card class="card batch-info" title="相关库位"> </a-card>
            </a-col>
          </a-row> -->
        </a-spin>
      </div>
    </template>
    
    <script>
    import { schemaIcons } from '@/common/global'
    import {
      queryStockFramesDetailBySchemaId,
      updateStockSchema,
      updateStockSchemaFields
    } from '@/api/material/locationSetting'
    import ProductCustomFields from '@/views/materialcenter/productManagement/components/ProductCustomFields'
    import ProductBaseInfoForm from '@/views/materialcenter/productManagement/components/ProductBaseInfoForm'
    import BatchInfoTableList from './StockInstanceTable'
    import { CUSTOM_FIELD_SHOW_MODE } from '@/views/materialcenter/productManagement/components/comm/constValues'
    
    export default {
      props: {
        productInfo: {
          type: Object,
          default() {
            return {}
          }
        },
        getLeftStockFrameOrSchema: Function
      },
      components: {
        ProductCustomFields,
        StorageLocation: ProductCustomFields,
        ProductBaseInfoForm,
        BatchInfoTableList
      },
      data() {
        return {
          schemaIcons: Object.freeze(schemaIcons), // icon 图标
          operatorName: {
            1: 'edit',
            2: 'edit'
          },
          isLoading: false,
          productInfoId: '',
          productSelfInfo: {
            name: '',
            prefix: '',
            icon: '',
            capacity: undefined,
            unitId: undefined,
            version: undefined
          },
          customFields: [],
          frameParams: [],
          tabListTitle: [
            {
              key: '1',
              tab: '元件字段'
            },
            {
              key: '2',
              tab: '库位字段'
            }
          ],
          titleKey: '1',
          showMode: Object.freeze(CUSTOM_FIELD_SHOW_MODE),
          schemaCustomFieldsData: {},
          storageFieldsData: {},
          storageFields: [],
          frameId: '',
          referenceId: ''
        }
      },
      methods: {
        /**
         * 切换 元件/库位字段卡片视图
         */
        onTabChange(key, type) {
          this[type] = key
        },
        /**
         * 改变卡片状态
         */
        changeCradStatus(key, e) {
          if (key === 3) {
            this.editBaseInfoOrFields(key)
            return
          }
          if (this.operatorName[key] === 'edit') {
            this.operatorName[key] = 'ok'
            key === 1 ? this.$refs.productBaseInfoFormRef.changeIsShowStatus() : ''
          } else {
            // this.operatorName[key] = 'edit'
            // 编辑基本信息/编辑产品字段
            this.editBaseInfoOrFields(key)
          }
        },
        /**
         * 调用编辑基本信息/产品字段
         * key 1.基本信息 2.产品字段 3.库位/批次字段
         */
        editBaseInfoOrFields(key) {
          switch (key) {
            case 1:
              this.editProductBaseInfo()
              break
            case 3:
            case 2:
              this.editProductFields()
              break
            default:
              break
          }
        },
        /**
         * 编辑产品字段 确认时
         */
        editProductFields() {
          this.$refs.productCustomFieldsRef.getData()
          this.$refs.storageLocationRef.getData()
          this.updateProductFields({
            id: this.productInfoId,
            customParams: this.schemaCustomFieldsData,
            stockParams: this.storageFieldsData
          })
        },
        /**
         * 编辑产品基本信息
         */
        editProductBaseInfo() {
          this.$refs.productBaseInfoFormRef.getFullData(data => {
            data.frameParams = data.productValues
            delete data.productValues
            data &&
              this.updateProductInfo({
                stockFrameId: this.frameId,
                id: this.productInfoId,
                ...data
              })
          })
        },
        /**
         * 更新产品基本信息 含产品种类字段的 values
         * fixme 这个函数到底是干嘛的。。。。
         */
        async updateProductInfo(data) {
          const res = await updateStockSchema(data)
          if (res.code === '200') {
            this.productSelfInfo.version = res.data.version
            this.productSelfInfo.name = this.$refs.productBaseInfoFormRef.form.name
            this.productSelfInfo.prefix = this.$refs.productBaseInfoFormRef.form.prefix
            this.productSelfInfo.icon = this.$refs.productBaseInfoFormRef.form.icon
            this.operatorName[1] = 'edit'
            this.$refs.productBaseInfoFormRef.changeNoShowStatus()
            // this.$emit('updateProductName')
            // 更新库位元件名称 => 手动调用接口
            this.getLeftStockFrameOrSchema()
          }
        },
        /**
         * 更新产品自定义字段
         */
        async updateProductFields(data) {
          const res = await updateStockSchemaFields(data)
          if (res.code === '200') {
            this.operatorName[2] = 'edit'
            // 发起请求
            this.getFullProductInfoDetail({ id: this.productInfoId })
          }
        },
        /**
         * 从编辑状态返回
         */
        backCradEditStatus(key, e) {
          if (this.operatorName[key] === 'ok') {
            this.operatorName[key] = 'edit'
            key === 1 ? this.$refs.productBaseInfoFormRef.changeNoShowStatus() : ''
          }
        },
        /**
         * 获取产品字段属性数据
         */
        getSchemaFieldsData(data, deletingFieldIds) {
          // 产品字段 修改是否编辑
          // this.updateProductFields({
          //   id: this.productInfoId,
          //   params: data,
          //   deletingFieldIds,
          // })
          this.schemaCustomFieldsData = {
            params: data,
            deletingFieldIds
          }
        },
        /**
         * 获取库位字段信息
         */
        getStorageLocationFieldsData(data, deletingFieldIds) {
          this.storageFieldsData = {
            params: data,
            deletingFieldIds
          }
        },
        /**
         * 获取产品信息详情
         */
        async getFullProductInfoDetail(data) {
          this.isLoading = true
          const res = await queryStockFramesDetailBySchemaId(data).finally(() => {
            this.isLoading = false
          })
          if (res.code === '200') {
            this.customFields = res.data.customParams
            this.frameId = res.data.frameId
            this.frameParams = res.data.frameParams
            this.storageFields = res.data.stockParams
            this.referenceId = res.data.id
            Object.keys(this.productSelfInfo).forEach(key => {
              this.productSelfInfo[key] = res.data[key]
            })
            // 深克隆 => productBaseInfoForm 组件监听
            this.productSelfInfo = _.cloneDeep(this.productSelfInfo)
          }
        },
        resetCartView() {
          this.operatorName = {
            1: 'edit',
            2: 'edit'
          }
          this.$refs.productBaseInfoFormRef &&
            this.$refs.productBaseInfoFormRef.changeNoShowStatus &&
            this.$refs.productBaseInfoFormRef.changeNoShowStatus()
        }
      },
      watch: {
        'productInfo.id': {
          handler(newVal) {
            this.productInfoId = newVal
            this.resetCartView()
            this.getFullProductInfoDetail({ id: newVal })
          },
          immediate: true
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .product-info-detail-right {
      height: 100%;
      // background-color: red;
      padding: 16px;
      .forbidden {
        pointer-events: none;
      }
      .product-fields {
        height: 350px;
        overflow-y: scroll;
      }
      .product-forbidden {
        cursor: not-allowed;
      }
      .batch-info {
        height: 500px;
        overflow-y: scroll;
      }
      .product-fields::-webkit-scrollbar {
        display: none;
      }
    }
    .product-info-detail-right {
      height: 100%;
      // background-color: red;
      padding: 16px;
      .forbidden {
        pointer-events: none;
      }
      .product-fields {
        height: 350px;
        overflow-y: scroll;
        ::v-deep.ant-card-head {
          border: none;
        }
      }
      .product-forbidden {
        cursor: not-allowed;
      }
      .batch-info {
        height: 500px;
        overflow-y: scroll;
      }
      .product-fields::-webkit-scrollbar {
        display: none;
      }
    }
    
    .product-info-content {
      height: calc(100vh - 48px);
      overflow-y: auto;
      margin-right: 8px;
      padding-right: 8px;
      border-right: 1px solid #f0f0f0;
      .product-info-content-head {
        display: flex;
        justify-content: space-between;
        padding: 0 8px 8px 0;
        span {
          font-size: 16px;
          font-weight: 700;
        }
      }
    
      .product-info-content-card {
        padding: 24px 8px 8px 24px;
        .product-info-content-card-header {
          display: flex;
          justify-content: space-between;
          margin-bottom: 8px;
          span {
            color: #8c8c8c;
            font-weight: 500;
          }
        }
      }
    
      .info-value {
        color: #262626;
      }
      ::v-deep.ant-form-item {
        margin-bottom: 8px;
        color: rgba(0, 0, 0, 0.85);
      }
    
      ::v-deep.ant-form-item-label-left {
        label {
          color: #8c8c8c;
          font-weight: 500;
        }
      }
      .rquired-no-star {
        ::v-deep.ant-form-item-required::before {
          content: none;
        }
      }
    }
    .product-info-content-card-footer {
      display: flex;
      justify-content: flex-end;
    }
    
    .bmy-tab-pane-content {
      padding: 8px 24px;
    }
    </style>