wk-form.vue 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  1. <template>
  2. <view v-if="showForm" class="wk-form">
  3. <template
  4. v-for="(field, index) in fieldArr">
  5. <template v-if="field.show">
  6. <!-- 单行文本、邮箱 -->
  7. <wk-field-input
  8. v-if="['text', 'email', 'website'].includes(field.formType)"
  9. :key="index"
  10. v-model="field.value"
  11. :index="index"
  12. :field="field"
  13. :disabled="field.disabled || false"
  14. :config="getConfig(field)"
  15. @change="valueChange" />
  16. <!-- 数字、小数 -->
  17. <wk-field-input-number
  18. v-else-if="['floatnumber', 'number', 'percent'].includes(field.formType)"
  19. :key="index"
  20. v-model="field.value"
  21. :index="index"
  22. :field="field"
  23. :disabled="field.disabled || false"
  24. :config="getConfig(field)"
  25. @change="valueChange" />
  26. <!-- 手机号 -->
  27. <wk-field-mobile
  28. v-else-if="field.formType === 'mobile'"
  29. :key="index"
  30. v-model="field.value"
  31. :index="index"
  32. :field="field"
  33. :disabled="field.disabled || false"
  34. :config="getConfig(field)"
  35. @change="valueChange" />
  36. <!-- 多行文本 -->
  37. <wk-field-textarea
  38. v-if="field.formType === 'textarea'"
  39. :key="index"
  40. v-model="field.value"
  41. :index="index"
  42. :field="field"
  43. :disabled="field.disabled || false"
  44. :config="getConfig(field)"
  45. @change="valueChange" />
  46. <!-- 选项、商机状态组、商机阶段 -->
  47. <wk-field-select
  48. v-else-if="[
  49. 'select',
  50. 'checkbox',
  51. 'business_type',
  52. 'business_status',
  53. 'category',
  54. 'receivables_plan'
  55. ].includes(field.formType)"
  56. :key="index"
  57. v-model="field.value"
  58. :index="index"
  59. :field="field"
  60. :disabled="field.disabled || false"
  61. :config="getConfig(field)"
  62. @change="valueChange" />
  63. <!-- 员工 -->
  64. <wk-field-user
  65. v-else-if="['single_user', 'user'].includes(field.formType)"
  66. :key="index"
  67. v-model="field.value"
  68. :index="index"
  69. :field="field"
  70. :disabled="field.disabled || false"
  71. :config="getConfig(field)"
  72. @change="valueChange" />
  73. <!-- 部门 -->
  74. <wk-field-dept
  75. v-else-if="field.formType === 'structure'"
  76. :key="index"
  77. v-model="field.value"
  78. :index="index"
  79. :field="field"
  80. :disabled="field.disabled || false"
  81. :config="getConfig(field)"
  82. @change="valueChange" />
  83. <!-- 时间日期 -->
  84. <wk-field-datetime
  85. v-else-if="['datetime', 'date'].includes(field.formType)"
  86. :key="index"
  87. v-model="field.value"
  88. :index="index"
  89. :field="field"
  90. :disabled="field.disabled || false"
  91. :config="getConfig(field)"
  92. @change="valueChange" />
  93. <!-- label -->
  94. <wk-field-label
  95. v-else-if="field.formType === 'label'"
  96. :key="index"
  97. v-model="field.value"
  98. :index="index"
  99. :field="field"
  100. :disabled="field.disabled || false"
  101. :config="getConfig(field)"
  102. @change="valueChange" />
  103. <!-- 关联项 -->
  104. <wk-field-revelance
  105. v-else-if="['customer', 'contacts', 'contract', 'business'].includes(field.formType)"
  106. :key="index"
  107. v-model="field.value"
  108. :index="index"
  109. :field="field"
  110. :disabled="field.disabled || false"
  111. :config="getConfig(field)"
  112. :is-detail-table="isDetailTable"
  113. @change="valueChange" />
  114. <!-- map_address -->
  115. <wk-field-address
  116. v-else-if="field.formType === 'map_address'"
  117. :key="index"
  118. v-model="field.value"
  119. :index="index"
  120. :field="field"
  121. :disabled="field.disabled || false"
  122. :config="getConfig(field)"
  123. @change="valueChange" />
  124. <wk-field-file
  125. v-else-if="field.formType === 'file'"
  126. :key="index"
  127. v-model="field.value"
  128. :index="index"
  129. :field="field"
  130. :disabled="field.disabled || false"
  131. :config="getConfig(field)"
  132. @change="valueChange" />
  133. <!-- 布尔值 -->
  134. <wk-field-bool
  135. v-else-if="field.formType === 'boolean_value'"
  136. :key="index"
  137. v-model="field.value"
  138. :index="index"
  139. :field="field"
  140. :disabled="field.disabled || false"
  141. :config="getConfig(field)"
  142. @change="valueChange" />
  143. <!-- 定位 -->
  144. <wk-field-location
  145. v-else-if="field.formType === 'location'"
  146. :key="index"
  147. v-model="field.value"
  148. :index="index"
  149. :field="field"
  150. :disabled="field.disabled || false"
  151. :config="getConfig(field)"
  152. @change="valueChange" />
  153. <!-- 日期范围 -->
  154. <wk-field-date-range
  155. v-else-if="field.formType === 'date_interval'"
  156. :key="index"
  157. v-model="field.value"
  158. :index="index"
  159. :field="field"
  160. :disabled="field.disabled || false"
  161. :config="getConfig(field)"
  162. @change="valueChange" />
  163. <!-- 地址 -->
  164. <wk-field-position
  165. v-else-if="field.formType === 'position'"
  166. :key="index"
  167. v-model="field.value"
  168. :index="index"
  169. :field="field"
  170. :disabled="field.disabled || false"
  171. :config="getConfig(field)"
  172. @change="valueChange" />
  173. <!-- 签名 -->
  174. <wk-field-write-sign
  175. v-else-if="field.formType === 'handwriting_sign'"
  176. :key="index"
  177. v-model="field.value"
  178. :index="index"
  179. :field="field"
  180. :disabled="field.disabled || false"
  181. :config="getConfig(field)"
  182. @change="valueChange" />
  183. <!-- 明细表格 -->
  184. <wk-field-table
  185. v-else-if="field.formType === 'detail_table'"
  186. :key="index"
  187. v-model="field.value"
  188. :index="index"
  189. :field="field"
  190. :disabled="field.disabled || false"
  191. :config="getConfig(field)"
  192. @change="valueChange" />
  193. <!-- 自定义编号 -->
  194. <wk-field-serial-number
  195. v-else-if="field.formType === 'serial_number'"
  196. :key="index"
  197. :index="index"
  198. :field="field" />
  199. <!-- 自定义标签 -->
  200. <wk-field-tag
  201. v-else-if="field.formType === 'field_tag'"
  202. :key="index"
  203. v-model="field.value"
  204. :index="index"
  205. :field="field"
  206. :disabled="field.disabled || false"
  207. @change="valueChange" />
  208. <!-- 关注度 -->
  209. <wk-field-attention
  210. v-else-if="field.formType === 'field_attention'"
  211. :key="index"
  212. v-model="field.value"
  213. :index="index"
  214. :field="field"
  215. :disabled="field.disabled || false"
  216. @change="valueChange" />
  217. <!-- 自定义分组 -->
  218. <view
  219. v-else-if="field.formType === 'field_group'"
  220. :key="index"
  221. class="wk-field-group">
  222. <text class="prev-badge" />
  223. <text>{{ field.name }}</text>
  224. </view>
  225. <view v-else-if="field.formType === 'desc_text'" :key="index" class="desc_text">
  226. <rich-text :nodes="field.value" />
  227. </view>
  228. </template>
  229. </template>
  230. </view>
  231. </template>
  232. <script>
  233. import { CheckOnlyField } from 'API/base'
  234. import WkFieldInput from './wk-field-input.vue'
  235. import WkFieldInputNumber from './wk-field-input-number.vue'
  236. import WkFieldMobile from './wk-field-mobile.vue'
  237. import WkFieldTextarea from './wk-field-textarea.vue'
  238. import WkFieldUser from './wk-field-user.vue'
  239. import WkFieldDept from './wk-field-dept.vue'
  240. import WkFieldSelect from './wk-field-select.vue'
  241. import WkFieldDatetime from './wk-field-datetime.vue'
  242. import WkFieldLabel from './wk-field-label.vue'
  243. import WkFieldRevelance from './wk-field-revelance.vue'
  244. import WkFieldAddress from './wk-field-address.vue'
  245. import WkFieldFile from './wk-field-file.vue'
  246. import WkFieldBool from './wk-field-bool.vue'
  247. import WkFieldLocation from './wk-field-location.vue'
  248. import WkFieldDateRange from './wk-field-date-range.vue'
  249. import WkFieldPosition from './wk-field-position.vue'
  250. import WkFieldWriteSign from './wk-field-write-sign.vue'
  251. import WkFieldTable from './wk-field-table.vue'
  252. import WkFieldTag from './wk-field-tag.vue'
  253. import WkFieldAttention from './wk-field-attention.vue'
  254. import WkFieldSerialNumber from './wk-field-serial-number.vue'
  255. import formMixins from '@/mixins/formMixins.js'
  256. import { deepCopy, isEmail, isMobile } from '@/utils/lib.js'
  257. import { isArray, isObject } from '@/utils/types.js'
  258. import moment from 'moment'
  259. export default {
  260. name: 'WkForm',
  261. components: {
  262. WkFieldInput,
  263. WkFieldInputNumber,
  264. WkFieldMobile,
  265. WkFieldTextarea,
  266. WkFieldUser,
  267. WkFieldDept,
  268. WkFieldSelect,
  269. WkFieldDatetime,
  270. WkFieldLabel,
  271. WkFieldRevelance,
  272. WkFieldAddress,
  273. WkFieldFile,
  274. WkFieldBool,
  275. WkFieldLocation,
  276. WkFieldDateRange,
  277. WkFieldPosition,
  278. WkFieldWriteSign,
  279. WkFieldTable,
  280. WkFieldTag,
  281. WkFieldAttention,
  282. WkFieldSerialNumber
  283. },
  284. mixins: [formMixins],
  285. inheritAttrs: false,
  286. props: {
  287. fields: { // 字段列表
  288. type: Array,
  289. default: () => []
  290. },
  291. batchId: { // 详情的batchId用于字段验重和文件上传
  292. type: String,
  293. default: ''
  294. },
  295. isDetailTable: {
  296. type: Boolean,
  297. default: false
  298. }
  299. },
  300. data() {
  301. return {
  302. showForm: true,
  303. fieldArr: [],
  304. form: {},
  305. fileBatchId: null,
  306. allAssistIds: []
  307. }
  308. },
  309. watch: {
  310. fields: {
  311. handler() {
  312. this.allAssistIds = this.getAllFormAssistId(this.fields)
  313. this.fieldArr = deepCopy(this.fields)
  314. let assistHideIds = []
  315. this.fieldArr.forEach(field => {
  316. field.show = true
  317. // 自动编号类型不做必填验证
  318. if (field.formType === 'serial_number') {
  319. field.isNull = 0
  320. }
  321. if (this.allAssistIds.includes(field.formAssistId)) {
  322. const res = this.getIdsStatus(field, field.value)
  323. assistHideIds = Array.from(new Set(assistHideIds.concat(res.hideIds)))
  324. }
  325. })
  326. this.fieldArr.forEach(field => {
  327. if (assistHideIds.includes(field.formAssistId)) {
  328. field.show = false
  329. } else {
  330. field.show = true
  331. }
  332. })
  333. this.$nextTick(() => {
  334. if (this.isDetailTable) {
  335. getApp().globalData.formBridge.detailTableFields = this.fieldArr
  336. } else {
  337. getApp().globalData.formBridge.fields = this.fieldArr
  338. }
  339. // getApp().globalData.formBridge.fields = this.fieldArr
  340. })
  341. },
  342. deep: true,
  343. immediate: true
  344. }
  345. },
  346. methods: {
  347. /**
  348. * 字段值发生变化派发 change 事件
  349. * @param {Object} data
  350. */
  351. valueChange(data) {
  352. this.checkAssistField(data.field, data.value)
  353. this.$nextTick(() => {
  354. this.$emit('change', data)
  355. })
  356. },
  357. /**
  358. * 切换逻辑表单展示状态
  359. * @param {Object} field 字段对象
  360. * @param value 字段值,不传时取 field.value
  361. */
  362. checkAssistField(field, value = null) {
  363. // 非逻辑表单直接返回
  364. if (![
  365. 'checkbox',
  366. 'select',
  367. ].includes(field.formType)) return
  368. if (field.remark !== 'options_type') return
  369. if (value === null) {
  370. value = field.value
  371. }
  372. const res = this.getIdsStatus(field, value)
  373. const assistShowIds = res.showIds
  374. const assistHideIds = res.hideIds
  375. this.fieldArr.forEach(o => {
  376. if (!o.hasOwnProperty('show')) {
  377. this.$set(o, 'show', true)
  378. }
  379. if (assistShowIds.includes(o.formAssistId)) {
  380. // 显示字段
  381. this.$set(o, 'show', true)
  382. } else if (assistHideIds.includes(o.formAssistId)) {
  383. // 隐藏字段
  384. this.$set(o, 'show', false)
  385. this.$set(o, 'value', null)
  386. this.$set(o, 'value', this.mixinsFormatFieldValue(o))
  387. }
  388. })
  389. },
  390. getIdsStatus(field, value) {
  391. if (
  392. !['checkbox', 'select'].includes(field.formType) ||
  393. field.remark !== 'options_type'
  394. ) {
  395. return {
  396. showIds: [],
  397. hideIds: []
  398. }
  399. }
  400. let assistShowIds = [] // 展示的字段关联id
  401. let assistHideIds = [] // 隐藏的字段关联id
  402. // 获取被选中的选项值
  403. let selectedOpt = (this.$isEmpty(value) ? [] : value).map(o => o.value)
  404. Object.keys(field.optionsData).forEach(key => {
  405. if (selectedOpt.includes(key)) {
  406. // 被选中的项下关联字段显示
  407. assistShowIds = assistShowIds.concat(field.optionsData[key])
  408. } else {
  409. // 没有选中的项隐藏
  410. assistHideIds = assistHideIds.concat(field.optionsData[key])
  411. }
  412. })
  413. /**
  414. * 递归获取显示字段的关联显示字段
  415. */
  416. let _showIds = []
  417. function getShowIds(fieldArr, ids = []) {
  418. let res = []
  419. ids.forEach(id => {
  420. // 查找显示的字段下是否还有关联
  421. const findRes = fieldArr.find(o => o.formAssistId === id)
  422. if (
  423. findRes &&
  424. ['checkbox', 'select'].includes(findRes.formType) &&
  425. findRes.remark === 'options_type'
  426. ) {
  427. let opt = findRes.value.map(o => o.value)
  428. Object.keys(findRes.optionsData).forEach(key => {
  429. if (
  430. findRes.optionsData[key] &&
  431. opt.includes(key)
  432. ) {
  433. res = res.concat(findRes.optionsData[key])
  434. }
  435. })
  436. }
  437. })
  438. // 记录所有id
  439. _showIds = _showIds.concat(ids)
  440. res = Array.from(new Set(res)).filter(o => o)
  441. if (res.length > 0) {
  442. // 判断查询的结果是否已经被记录,防止无限递归
  443. let count = 0
  444. res.forEach(id => {
  445. if (_showIds.includes(id)) {
  446. count++
  447. }
  448. })
  449. if (res.length === count) {
  450. res = []
  451. }
  452. }
  453. const arr = res.length === 0 ? res : getShowIds(fieldArr, res)
  454. return Array.from(new Set(ids.concat(arr)))
  455. }
  456. /**
  457. * 递归获取隐藏字段的关联隐藏字段
  458. */
  459. let _hideIds = []
  460. function getHidenIds(fieldArr, ids = []) {
  461. let res = []
  462. ids.forEach(id => {
  463. const findRes = fieldArr.find(o => o.formAssistId === id)
  464. if (
  465. findRes &&
  466. ['checkbox', 'select'].includes(findRes.formType) &&
  467. findRes.remark === 'options_type'
  468. ) {
  469. Object.keys(findRes.optionsData).forEach(key => {
  470. res = res.concat(findRes.optionsData[key])
  471. })
  472. }
  473. })
  474. _hideIds = _hideIds.concat(ids)
  475. res = Array.from(new Set(res)).filter(o => o)
  476. if (res.length > 0) {
  477. // 判断查询的结果是否已经被记录,防止无限递归
  478. let count = 0
  479. res.forEach(id => {
  480. if (_hideIds.includes(id)) {
  481. count++
  482. }
  483. })
  484. if (res.length === count) {
  485. res = []
  486. }
  487. }
  488. const arr = res.length === 0 ? res : getHidenIds(fieldArr, res)
  489. return Array.from(new Set(ids.concat(arr)))
  490. }
  491. _showIds = []
  492. _hideIds = []
  493. const arr = this.fieldArr.filter(o => this.allAssistIds.includes(o.formAssistId))
  494. assistShowIds = getShowIds(arr, assistShowIds)
  495. assistHideIds = getHidenIds(arr, assistHideIds)
  496. return {
  497. showIds: assistShowIds.filter(o => o),
  498. hideIds: assistHideIds.filter(o => o)
  499. }
  500. },
  501. getConfig(field) {
  502. const config = { batchId: this.batchId }
  503. return field.sys_config ? {
  504. ...field.sys_config,
  505. ...config
  506. } : config
  507. },
  508. /**
  509. * 修改配置项钩子
  510. * @param {String} key 字段名
  511. * @param {Object} config
  512. */
  513. setConfig(key, config = {}) {
  514. // config
  515. // config.disabledMsg {String} 禁用时click toast 提示信息
  516. // config.otherParams {Object} 选项ajax请求附加参数
  517. // config.request {Function} 选项ajax
  518. // config.optionsConfig {Object} 选项配置
  519. // config.optionsConfig.labelField {String} 选项配置
  520. // config.optionsConfig.valueField {String} 选项配置
  521. if (!key) return
  522. this.$nextTick(() => {
  523. const findRes = this.fieldArr.find(o => o.fieldName === key)
  524. if (!findRes) return
  525. const oldConfig = findRes.sys_config || {}
  526. findRes.sys_config = {
  527. ...oldConfig,
  528. ...config
  529. }
  530. // console.log('set sys_config: ', findRes.name, findRes.sys_config)
  531. const formType = findRes.formType
  532. this.$set(findRes, 'formType', null)
  533. this.$nextTick(function() {
  534. this.$set(findRes, 'sys_config', config)
  535. this.$set(findRes, 'formType', formType)
  536. })
  537. })
  538. },
  539. /**
  540. * 设置禁用状态钩子
  541. * @param {String} key 字段名
  542. * @param {Boolean} flag 是否禁用
  543. */
  544. setDisabled(key, flag = false) {
  545. if (!key) return
  546. this.$nextTick(() => {
  547. const findRes = this.fieldArr.find(o => o.fieldName === key)
  548. // console.log('finddd', key, findRes)
  549. // console.log('set disabled: ', this.fieldArr)
  550. if (!findRes) return
  551. findRes.disabled = flag
  552. this.$set(findRes, 'disabled', flag)
  553. })
  554. },
  555. /**
  556. * 修改单个字段的值钩子
  557. * @param {String} key
  558. * @param {Any} value
  559. */
  560. setFormVal(key, value = null) {
  561. if (!key) return
  562. this.$nextTick(() => {
  563. const findIndex = this.fieldArr.findIndex(o => o.fieldName === key)
  564. if (findIndex !== -1) {
  565. let findRes = this.fieldArr[findIndex]
  566. findRes.value = value
  567. // this.fieldArr[findIndex].value = value
  568. // this.$set(findRes, 'value', value)
  569. this.$set(this.fieldArr, findIndex, findRes)
  570. // console.log('emit change findRes: ----', findRes)
  571. this.$nextTick(() => {
  572. this.$emit('change', {
  573. index: findIndex,
  574. field: findRes,
  575. value: value
  576. })
  577. })
  578. }
  579. })
  580. },
  581. setForm(form = {}) {
  582. this.$nextTick(function() {
  583. Object.keys(form).forEach(key => {
  584. this.setFormVal(key, form[key])
  585. })
  586. })
  587. },
  588. /**
  589. * 强制刷新视图
  590. */
  591. updateView() {
  592. this.$nextTick(() => {
  593. this.showForm = false
  594. this.$nextTick(() => {
  595. this.showForm = true
  596. this.$set(this, 'fieldArr', this.fieldArr)
  597. })
  598. })
  599. },
  600. /**
  601. * 通过字段名修改字段的可见状态
  602. * @param {Object} fieldName 字段名
  603. * @param {Object} status 状态 默认 true 可见
  604. */
  605. updateVisibleStatus(fieldName, status = true) {
  606. const findRes = this.fieldArr.find(o => o.fieldName === fieldName)
  607. if (!findRes) return
  608. this.$set(findRes, 'show', status)
  609. this.$forceUpdate()
  610. },
  611. /**
  612. * 通过字段名获取单个字段的值
  613. * @param {String} fieldName
  614. */
  615. getValueByFieldName(fieldName) {
  616. const findRes = this.fieldArr.find(o => o.fieldName === fieldName)
  617. if (!findRes) return undefined
  618. return this.getFieldValue(findRes)
  619. },
  620. /**
  621. * 修改字段配置
  622. * @param {Object} index
  623. * @param {Object} data
  624. */
  625. updateFields(index, data) {
  626. this.$set(this.fieldArr, index, {
  627. ...this.fieldArr[index],
  628. ...data
  629. })
  630. },
  631. /**
  632. * 获取表单数据
  633. * @param {Boolean} check 是否进行表单验证 默认true
  634. * @param {Boolean} format 是否格式化值 默认true
  635. */
  636. getForm(check = true, format = true) {
  637. // eslint-disable-next-line no-async-promise-executor
  638. return new Promise(async(resolve, reject) => {
  639. // 拆分自定义字段和固定字段
  640. let form = {
  641. field: [],
  642. entity: {}
  643. }
  644. for (let i = 0; i < this.fieldArr.length; i++) {
  645. const field = this.fieldArr[i]
  646. let value = null
  647. if (format) {
  648. value = this.getFieldValue(field)
  649. } else {
  650. value = this.$isEmpty(field.value) ? null : field.value
  651. }
  652. // 如果字段没有展示则把值设置为空
  653. if (field.show === false) {
  654. value = null
  655. }
  656. if (check && field.show) {
  657. if (field.formType === 'detail_table') {
  658. if (field.isNull === 1 && this.$isEmpty(value)) {
  659. this.$toast(`请完善${field.name}数据`)
  660. reject('请检查数据格式!')
  661. return
  662. }
  663. const len = field.fieldExtendList.filter(o => o.isNull === 1).length
  664. // console.log('len, ', len, field)
  665. if (len > 0 && this.$isEmpty(value)) {
  666. this.$toast(`请完善${field.name}数据`)
  667. reject('请检查数据格式!')
  668. return
  669. }
  670. if (!this.$isEmpty(value)) {
  671. for (let j = 0; j < value.length; j++) {
  672. const child = value[j]
  673. for (let k = 0; k < child.length; k++) {
  674. try {
  675. await this.validateFieldValue(child[k], child[k].value)
  676. } catch {
  677. reject('请检查数据格式!')
  678. return
  679. }
  680. }
  681. }
  682. }
  683. } else {
  684. try {
  685. await this.validateFieldValue(field, value)
  686. } catch {
  687. reject('请检查数据格式!')
  688. return
  689. }
  690. }
  691. }
  692. if (field.formType === 'map_address') {
  693. form.entity = {
  694. ...form.entity,
  695. ...value,
  696. }
  697. } else if (field.fieldType === 1) {
  698. form.entity[field.fieldName] = value
  699. } else {
  700. form.field.push({
  701. // ...field,
  702. ...this.fields[i],
  703. value
  704. })
  705. }
  706. }
  707. resolve(form)
  708. })
  709. },
  710. /**
  711. * 字段校验
  712. * @param {Object} field
  713. * @param {Object} value
  714. */
  715. validateFieldValue(field, value) {
  716. return new Promise((resolve, reject) => {
  717. if (field.isNull === 1 && this.$isEmpty(value)) {
  718. this.$toast(`${field.name}不能为空`)
  719. reject(false)
  720. return
  721. }
  722. if (!this.$isEmpty(value)) {
  723. if (field.formType === 'mobile' && !isMobile(value)) {
  724. this.$toast(`${field.name}格式错误`)
  725. reject(false)
  726. return
  727. }
  728. if (field.formType === 'email' && !isEmail(value)) {
  729. this.$toast(`${field.name}格式错误`)
  730. reject(false)
  731. return
  732. }
  733. if (field.formType === 'date_interval') {
  734. let start = field.value[0] || null
  735. let end = field.value[1] || null
  736. if (!start || !end) {
  737. this.$toast(`${field.name}格式错误`)
  738. reject(false)
  739. return
  740. }
  741. if (moment(start).isAfter(end)) {
  742. this.$toast('开始时间不能大于结束时间')
  743. reject(false)
  744. return
  745. }
  746. }
  747. if (field.isUnique === 1) {
  748. const params = {
  749. fieldId: field.fieldId,
  750. value: value
  751. }
  752. if (this.batchId) {
  753. params.batchId = this.batchId
  754. }
  755. CheckOnlyField(params).then(res => {
  756. if (res.status === 0) {
  757. this.$toast(field.name + '不能重复')
  758. reject(false)
  759. } else {
  760. resolve(true)
  761. }
  762. }).catch(() => {
  763. reject(false)
  764. })
  765. return
  766. }
  767. }
  768. resolve(true)
  769. })
  770. },
  771. /**
  772. * 获取单个字段保存值
  773. * @param {Object} field
  774. */
  775. getFieldValue(field) {
  776. if (this.$isEmpty(field.value)) return ''
  777. const value = field.value
  778. console.log('get field value: ', field.name, value)
  779. switch (field.formType) {
  780. case 'user':
  781. if (!isArray(value)) return value
  782. return value.map(o => o.id || o.userId).join(',')
  783. case 'single_user':
  784. if (!isArray(value)) return value
  785. return value.map(o => o.id || o.userId).join(',')
  786. case 'structure':
  787. if (!isArray(value)) return value
  788. return value.map(o => o.id || o.deptId).join(',')
  789. case 'select':
  790. if (this.$isEmpty(value)) return ''
  791. if (!isArray(value)) return value
  792. if (value[0].hasOwnProperty('otherVal')) {
  793. return value[0].otherVal || ''
  794. }
  795. return value[0].value
  796. case 'checkbox':
  797. if (this.$isEmpty(value)) return ''
  798. if (!isArray(value)) return value
  799. return value
  800. .map(o => {
  801. if (o.hasOwnProperty('otherVal')) {
  802. return o.otherVal
  803. } else {
  804. return o.value
  805. }
  806. })
  807. .filter(o => !this.$isEmpty(o))
  808. .join(',')
  809. case 'business_type':
  810. if (this.$isEmpty(value)) return ''
  811. if (!isArray(value)) return value
  812. return value[0].flowId
  813. case 'receivables_plan':
  814. if (this.$isEmpty(value)) return ''
  815. if (isObject(value)) return value.receivablesPlanId
  816. if (!isArray(value)) return value
  817. return value[0].receivablesPlanId
  818. case 'category':
  819. if (this.$isEmpty(value)) return ''
  820. if (isObject(value)) return value.categoryId
  821. if (!isArray(value)) return value
  822. return value[0].categoryId
  823. case 'file':
  824. console.log('file value: ', value)
  825. if (this.$isEmpty(value)) return ''
  826. if (isArray(value)) return value[0].batchId
  827. if (typeof value === 'string') return value
  828. return ''
  829. case 'detail_table':
  830. if (this.$isEmpty(value)) return []
  831. if (!isArray(value)) return value
  832. deepCopy(value)
  833. .forEach(child => {
  834. child.forEach(item => {
  835. delete item.companyId
  836. item.value = this.getFieldValue(item)
  837. })
  838. })
  839. .filter(child => {
  840. const len = child.length
  841. const emptyLen = child.filter(item => this.$isEmpty(item.value)).length
  842. return len !== emptyLen
  843. })
  844. }
  845. if (['customer', 'business', 'contacts', 'contract'].includes(field.formType)) {
  846. if (this.$isEmpty(value)) return ''
  847. if (isObject(value)) return value[`${field.formType}Id`] || value.id
  848. if (!isArray(value)) return value
  849. // return value.map(o => o[`${field.formType}Id`] || o.id).join(',')
  850. return value.map(o => o[`${field.formType}Id`] || o.id)[0]
  851. }
  852. return field.value
  853. }
  854. }
  855. }
  856. </script>
  857. <style scoped lang="scss">
  858. .wk-form {
  859. padding: 0 30rpx;
  860. background-color: white;
  861. overflow: hidden;
  862. .wk-field-group {
  863. font-size: $wk-font-base;
  864. background-color: #F3F5FA;
  865. padding: 18rpx 30rpx;
  866. margin: 0 -32rpx;
  867. @include left;
  868. .prev-badge {
  869. width: 10rpx;
  870. height: 30rpx;
  871. border-radius: 10rpx;
  872. background-color: $theme-color;
  873. margin-right: 15rpx;
  874. }
  875. }
  876. .desc_text {
  877. font-size: $wk-font-base;
  878. margin: 10rpx 0;
  879. }
  880. }
  881. </style>