Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

316 linhas
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. :required="Boolean(item.verify)"
  123. :readonly="!isEdit(item)"
  124. :title="item.title"
  125. :number="9"
  126. />
  127. <!-- HTML内容 html -->
  128. <view v-else-if="item.type === 'html'" class="cu-form-group">
  129. <view class="bg-white">
  130. <u-parse :imageProp="{ domain: apiRoot }" :content="CONVERT_HTML(item.title)"></u-parse>
  131. </view>
  132. </view>
  133. <!-- 表格 girdtable -->
  134. <l-customform-table
  135. v-else-if="item.type === 'girdtable'"
  136. @input="setValue(item.__valuePath__, $event)"
  137. :value="getValue(item.__valuePath__)"
  138. :item="item"
  139. :edit="isEdit(item)"
  140. />
  141. </view>
  142. </view>
  143. </template>
  144. <script>
  145. import get from 'lodash/get'
  146. import set from 'lodash/set'
  147. import moment from 'moment'
  148. export default {
  149. name: 'l-customform',
  150. props: {
  151. scheme: { default: () => [] },
  152. editMode: { default: true },
  153. initFormValue: { default: () => ({}) },
  154. rel: { default: () => ({}) }
  155. },
  156. data() {
  157. return {
  158. formValue: this.initFormValue
  159. }
  160. },
  161. methods: {
  162. // 本方法由调用方使用 $refs 的方式调用
  163. // 给表单设置值
  164. setFormValue(formValue) {
  165. this.formValue = formValue
  166. },
  167. // 本方法由调用方使用 $refs 的方式调用
  168. // 获取表单值
  169. getFormValue() {
  170. return this.formValue
  171. },
  172. // 本方法由调用方使用 $refs 的方式调用
  173. // 依次验证表单项,返回一个所有错误提示的数组,如果为空数组则表示无错误
  174. verifyValue() {
  175. const errorList = []
  176. console.log(this.scheme)
  177. this.scheme
  178. .filter(t => t.verify)
  179. .forEach(schemeItem => {
  180. if (schemeItem.table && schemeItem.field) {
  181. console.log(schemeItem.verify,'hemeItem.verify')
  182. const verifyFunc = this.verify[schemeItem.verify]
  183. console.log(schemeItem.verify)
  184. const verifyResult = verifyFunc(this.getValue(schemeItem.__valuePath__))
  185. if (verifyResult !== true) {
  186. errorList.push(`[${schemeItem.title}]: ${verifyResult}`)
  187. }
  188. } else if (schemeItem.fieldsData) {
  189. this.getValue(schemeItem.__valuePath__).forEach((valueItem, valueIndex) => {
  190. schemeItem.fieldsData.forEach(fieldItem => {
  191. const verifyFunc = this.verify[fieldItem.verify]
  192. const verifyResult = verifyFunc(
  193. this.getValue(`${schemeItem.__valuePath__}.${valueIndex}.${fieldItem.field}`)
  194. )
  195. if (verifyResult !== true) {
  196. errorList.push(`[表格${schemeItem.title}第${tableIndex}行${fieldItem.name}列]: ${verifyResult}`)
  197. }
  198. })
  199. })
  200. }
  201. })
  202. return errorList
  203. },
  204. // 设置表单数据的方法
  205. setValue(path, value) {
  206. set(this.formValue, path, value)
  207. },
  208. // 获取表单数据的方法
  209. getValue(path) {
  210. return get(this.formValue, path)
  211. },
  212. // 处理互相关联的表单项(organize 级联,datetimerange 日期区间)
  213. relChange(id, val) {
  214. const relList = this.rel[id] || []
  215. relList.forEach(relItem => {
  216. if (relItem.type === 'organize') {
  217. // 组织结构,重设级联过来的组件
  218. this.setValue(relItem.path, '')
  219. // 向下递归
  220. if (this.rel[relItem.id]) {
  221. this.relChange(relItem.id)
  222. }
  223. } else if (relItem.type === 'datetimerange') {
  224. // 时间日期区间,重新计算
  225. const startTime = this.getValue(relItem.startPath)
  226. const endTime = this.getValue(relItem.endPath)
  227. if (!startTime || !endTime || moment(endTime).isBefore(startTime)) {
  228. return
  229. }
  230. const newVal = moment
  231. .duration(moment(endTime).diff(moment(startTime)))
  232. .asDays()
  233. .toFixed(0)
  234. this.setValue(relItem.path, newVal)
  235. }
  236. })
  237. },
  238. // 获取表单项的 placeholder ,在无法编辑时隐藏
  239. displayPlaceHolder(item) {
  240. if (!this.editMode || item.type !== 'organize') {
  241. return ' '
  242. }
  243. if (!item.relation) {
  244. return `请选择${item.title || item.name}`
  245. }
  246. const parentType = { user: '部门', department: '公司' }[item.dataType]
  247. const parentValue = this.getValue(item.__relationPath__)
  248. return parentValue ? `请选择${item.title || item.name}` : `请先选择上级${parentType}`
  249. },
  250. // 获取表单项可否编辑
  251. isEdit(item) {
  252. return this.editMode && item.edit !== 0
  253. }
  254. },
  255. computed: {
  256. verify() {
  257. return {
  258. NotNull: t => (t !== null && t !== undefined && t !== '' && (!Array.isArray(t) || t.length > 0)) || '不能为空',
  259. Num: t => !isNaN(t) || '须输入数值',
  260. NumOrNull: t => t.length <= 0 || !isNaN(t) || '须留空或输入数值',
  261. Email: t => /^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_]+.[a-zA-Z0-9]+$/.test(t) || '须符合Email格式',
  262. EmailOrNull: t =>
  263. t.length <= 0 || /^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_]+.[a-zA-Z0-9]+$/.test(t) || '须留空或符合Email格式',
  264. EnglishStr: t => /^[a-zA-Z]*$/.test(t) || '须由英文字母组成',
  265. EnglishStrOrNull: t => t.length <= 0 || /^[a-zA-Z]*$/.test(t) || '须留空或由英文字母组成',
  266. Phone: t => /^[+0-9- ]*$/.test(t) || '须符合电话号码格式',
  267. PhoneOrNull: t => t.length <= 0 || /^[+0-9- ]*$/.test(t) || '须留空或符合电话号码格式',
  268. Fax: t => /^[+0-9- ]*$/.test(t) || '须符合传真号码格式',
  269. Mobile: t => /^1[0-9]{10}$/.test(t) || '须符合手机号码格式',
  270. MobileOrPhone: t => /^[+0-9- ]*$/.test(t) || /^1[0-9]{10}$/.test(t) || '须符合电话或手机号码格式',
  271. MobileOrNull: t => t.length <= 0 || /^1[0-9]{10}$/.test(t) || '须留空或符合手机号码格式',
  272. MobileOrPhoneOrNull: t =>
  273. t.length <= 0 || /^1[0-9]{10}$/.test(t) || /^[+0-9- ]*$/.test(t) || '须留空或符合手机/电话号码格式',
  274. Uri: t => /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须符合网址Url格式',
  275. UriOrNull: t => t.length <= 0 || /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须留空或符合网址Url格式',
  276. PositiveFloatint:t=> /^([1-9]\d*|(0|[1-9]\d*)\.\d*[1-9])$/.test(t) || '请输入正确的整数或小数(不能为零和负数)'
  277. }
  278. }
  279. }
  280. }
  281. </script>