You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

317 lines
11 KiB

  1. <template>
  2. <view>
  3. <view
  4. :key="item.id"
  5. v-for="(item, index) of scheme"
  6. :style="{ marginTop: index !== 0 && item.type === 'label' ? '15px' : '0' }"
  7. >
  8. <!-- 标题文字 label -->
  9. <l-title v-if="item.type === 'label'" border>{{ item.title }}</l-title>
  10. <!-- 文字输入框 text -->
  11. <l-input
  12. v-else-if="item.type === 'text'"
  13. @input="setValue(item.__valuePath__, $event)"
  14. :value="getValue(item.__valuePath__)"
  15. :disabled="!isEdit(item)"
  16. :required="Boolean(item.verify)"
  17. :title="item.title"
  18. />
  19. <!-- 单选和选择 radio和select -->
  20. <l-select
  21. v-else-if="item.type === 'radio' || item.type === 'select'"
  22. @input="setValue(item.__valuePath__, $event)"
  23. :value="getValue(item.__valuePath__)"
  24. :disabled="!isEdit(item)"
  25. :required="Boolean(item.verify)"
  26. :range="item.__sourceData__"
  27. :title="item.title"
  28. />
  29. <!-- 多选 checkbox -->
  30. <l-checkbox-picker
  31. v-else-if="item.type === 'checkbox'"
  32. @input="setValue(item.__valuePath__, $event)"
  33. :value="getValue(item.__valuePath__)"
  34. :readonly="!isEdit(item)"
  35. :required="Boolean(item.verify)"
  36. :range="item.__sourceData__"
  37. :title="item.title"
  38. />
  39. <!-- 多行文本 textarea -->
  40. <l-textarea
  41. v-else-if="item.type === 'textarea' || item.type === 'texteditor'"
  42. @input="setValue(item.__valuePath__, $event)"
  43. :value="getValue(item.__valuePath__)"
  44. :readonly="!isEdit(item)"
  45. :required="Boolean(item.verify)"
  46. :title="item.title"
  47. />
  48. <!-- 时间日期 datetime -->
  49. <l-datetime-picker
  50. v-else-if="item.type === 'datetime' && Number(item.dateformat) === 1"
  51. @input="setValue(item.__valuePath__, $event)"
  52. @change="relChange(item.id, $event)"
  53. :value="getValue(item.__valuePath__)"
  54. :disabled="!isEdit(item)"
  55. :required="Boolean(item.verify)"
  56. :title="item.title"
  57. />
  58. <!-- 日期 date -->
  59. <l-date-picker
  60. v-else-if="item.type === 'datetime' && Number(item.dateformat) !== 1"
  61. @input="setValue(item.__valuePath__, $event)"
  62. @change="relChange(item.id, $event)"
  63. :value="getValue(item.__valuePath__)"
  64. :required="Boolean(item.verify)"
  65. :disabled="!isEdit(item)"
  66. :title="item.title"
  67. />
  68. <!-- 日期区间 datetimerange -->
  69. <l-input
  70. v-else-if="item.type === 'datetimerange'"
  71. @input="setValue(item.__valuePath__, $event)"
  72. :value="getValue(item.__valuePath__)"
  73. :disabled="!isEdit(item)"
  74. :required="Boolean(item.verify)"
  75. :title="item.title"
  76. placeholder=""
  77. />
  78. <!-- 当前状态 currentInfo:组织结构 organize -->
  79. <l-organize-picker
  80. v-else-if="item.type === 'currentInfo' && item.dataType !== 'time'"
  81. :value="getValue(item.__valuePath__)"
  82. :type="item.dataType"
  83. :required="Boolean(item.verify)"
  84. :title="item.title"
  85. readonly
  86. />
  87. <!-- 当前状态 currentInfo:时间 time -->
  88. <l-input
  89. v-else-if="item.type === 'currentInfo' && item.dataType === 'time'"
  90. :value="getValue(item.__valuePath__)"
  91. :disabled="!isEdit(item)"
  92. :required="Boolean(item.verify)"
  93. :title="item.title"
  94. disabled
  95. />
  96. <!-- 编码 encode -->
  97. <l-input
  98. v-else-if="item.type === 'encode'"
  99. :value="getValue(item.__valuePath__)"
  100. :required="Boolean(item.verify)"
  101. :title="item.title"
  102. disabled
  103. />
  104. <!-- 公司人员结构选单 organize -->
  105. <l-organize-picker
  106. v-else-if="item.type === 'organize'"
  107. @input="setValue(item.__valuePath__, $event)"
  108. @change="relChange(item.id, $event)"
  109. :value="getValue(item.__valuePath__)"
  110. :rootId="getValue(item.__relationPath__)"
  111. :type="item.dataType"
  112. :required="Boolean(item.verify)"
  113. :readonly="item.__relationPath__ ? !isEdit(item) || !getValue(item.__relationPath__) : !isEdit(item)"
  114. :title="item.title"
  115. :placeholder="displayPlaceHolder(item)"
  116. />
  117. <!-- 文件上传 upload -->
  118. <l-upload-file
  119. v-else-if="item.type === 'upload'"
  120. @input="setValue(item.__valuePath__, $event)"
  121. :value="getValue(item.__valuePath__)"
  122. :labelId="item.id"
  123. :required="Boolean(item.verify)"
  124. :readonly="!isEdit(item)"
  125. :title="item.title"
  126. :number="9"
  127. />
  128. <!-- HTML内容 html -->
  129. <view v-else-if="item.type === 'html'" class="cu-form-group">
  130. <view class="bg-white">
  131. <u-parse :imageProp="{ domain: apiRoot }" :content="CONVERT_HTML(item.title)"></u-parse>
  132. </view>
  133. </view>
  134. <!-- 表格 girdtable -->
  135. <l-customform-table
  136. v-else-if="item.type === 'girdtable'"
  137. @input="setValue(item.__valuePath__, $event)"
  138. :value="getValue(item.__valuePath__)"
  139. :item="item"
  140. :edit="isEdit(item)"
  141. />
  142. </view>
  143. </view>
  144. </template>
  145. <script>
  146. import get from 'lodash/get'
  147. import set from 'lodash/set'
  148. import moment from 'moment'
  149. export default {
  150. name: 'l-customform',
  151. props: {
  152. scheme: { default: () => [] },
  153. editMode: { default: true },
  154. initFormValue: { default: () => ({}) },
  155. rel: { default: () => ({}) }
  156. },
  157. data() {
  158. return {
  159. formValue: this.initFormValue
  160. }
  161. },
  162. methods: {
  163. // 本方法由调用方使用 $refs 的方式调用
  164. // 给表单设置值
  165. setFormValue(formValue) {
  166. this.formValue = formValue
  167. },
  168. // 本方法由调用方使用 $refs 的方式调用
  169. // 获取表单值
  170. getFormValue() {
  171. return this.formValue
  172. },
  173. // 本方法由调用方使用 $refs 的方式调用
  174. // 依次验证表单项,返回一个所有错误提示的数组,如果为空数组则表示无错误
  175. verifyValue() {
  176. const errorList = []
  177. console.log(this.scheme)
  178. this.scheme
  179. .filter(t => t.verify)
  180. .forEach(schemeItem => {
  181. if (schemeItem.table && schemeItem.field) {
  182. console.log(schemeItem.verify,'hemeItem.verify')
  183. const verifyFunc = this.verify[schemeItem.verify]
  184. console.log(schemeItem.verify)
  185. const verifyResult = verifyFunc(this.getValue(schemeItem.__valuePath__))
  186. if (verifyResult !== true) {
  187. errorList.push(`[${schemeItem.title}]: ${verifyResult}`)
  188. }
  189. } else if (schemeItem.fieldsData) {
  190. this.getValue(schemeItem.__valuePath__).forEach((valueItem, valueIndex) => {
  191. schemeItem.fieldsData.forEach(fieldItem => {
  192. const verifyFunc = this.verify[fieldItem.verify]
  193. const verifyResult = verifyFunc(
  194. this.getValue(`${schemeItem.__valuePath__}.${valueIndex}.${fieldItem.field}`)
  195. )
  196. if (verifyResult !== true) {
  197. errorList.push(`[表格${schemeItem.title}第${tableIndex}行${fieldItem.name}列]: ${verifyResult}`)
  198. }
  199. })
  200. })
  201. }
  202. })
  203. return errorList
  204. },
  205. // 设置表单数据的方法
  206. setValue(path, value) {
  207. set(this.formValue, path, value)
  208. },
  209. // 获取表单数据的方法
  210. getValue(path) {
  211. return get(this.formValue, path)
  212. },
  213. // 处理互相关联的表单项(organize 级联,datetimerange 日期区间)
  214. relChange(id, val) {
  215. const relList = this.rel[id] || []
  216. relList.forEach(relItem => {
  217. if (relItem.type === 'organize') {
  218. // 组织结构,重设级联过来的组件
  219. this.setValue(relItem.path, '')
  220. // 向下递归
  221. if (this.rel[relItem.id]) {
  222. this.relChange(relItem.id)
  223. }
  224. } else if (relItem.type === 'datetimerange') {
  225. // 时间日期区间,重新计算
  226. const startTime = this.getValue(relItem.startPath)
  227. const endTime = this.getValue(relItem.endPath)
  228. if (!startTime || !endTime || moment(endTime).isBefore(startTime)) {
  229. return
  230. }
  231. const newVal = moment
  232. .duration(moment(endTime).diff(moment(startTime)))
  233. .asDays()
  234. .toFixed(0)
  235. this.setValue(relItem.path, newVal)
  236. }
  237. })
  238. },
  239. // 获取表单项的 placeholder ,在无法编辑时隐藏
  240. displayPlaceHolder(item) {
  241. if (!this.editMode || item.type !== 'organize') {
  242. return ' '
  243. }
  244. if (!item.relation) {
  245. return `请选择${item.title || item.name}`
  246. }
  247. const parentType = { user: '部门', department: '公司' }[item.dataType]
  248. const parentValue = this.getValue(item.__relationPath__)
  249. return parentValue ? `请选择${item.title || item.name}` : `请先选择上级${parentType}`
  250. },
  251. // 获取表单项可否编辑
  252. isEdit(item) {
  253. return this.editMode && item.edit !== 0
  254. }
  255. },
  256. computed: {
  257. verify() {
  258. return {
  259. NotNull: t => (t !== null && t !== undefined && t !== '' && (!Array.isArray(t) || t.length > 0)) || '不能为空',
  260. Num: t => !isNaN(t) || '须输入数值',
  261. NumOrNull: t => t.length <= 0 || !isNaN(t) || '须留空或输入数值',
  262. Email: t => /^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_]+.[a-zA-Z0-9]+$/.test(t) || '须符合Email格式',
  263. EmailOrNull: t =>
  264. t.length <= 0 || /^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_]+.[a-zA-Z0-9]+$/.test(t) || '须留空或符合Email格式',
  265. EnglishStr: t => /^[a-zA-Z]*$/.test(t) || '须由英文字母组成',
  266. EnglishStrOrNull: t => t.length <= 0 || /^[a-zA-Z]*$/.test(t) || '须留空或由英文字母组成',
  267. Phone: t => /^[+0-9- ]*$/.test(t) || '须符合电话号码格式',
  268. PhoneOrNull: t => t.length <= 0 || /^[+0-9- ]*$/.test(t) || '须留空或符合电话号码格式',
  269. Fax: t => /^[+0-9- ]*$/.test(t) || '须符合传真号码格式',
  270. Mobile: t => /^1[0-9]{10}$/.test(t) || '须符合手机号码格式',
  271. MobileOrPhone: t => /^[+0-9- ]*$/.test(t) || /^1[0-9]{10}$/.test(t) || '须符合电话或手机号码格式',
  272. MobileOrNull: t => t.length <= 0 || /^1[0-9]{10}$/.test(t) || '须留空或符合手机号码格式',
  273. MobileOrPhoneOrNull: t =>
  274. t.length <= 0 || /^1[0-9]{10}$/.test(t) || /^[+0-9- ]*$/.test(t) || '须留空或符合手机/电话号码格式',
  275. Uri: t => /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须符合网址Url格式',
  276. UriOrNull: t => t.length <= 0 || /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须留空或符合网址Url格式',
  277. PositiveFloatint:t=> /^([1-9]\d*|(0|[1-9]\d*)\.\d*[1-9])$/.test(t) || '请输入正确的整数或小数(不能为零和负数)'
  278. }
  279. }
  280. }
  281. }
  282. </script>