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.
 
 
 
 
 
 

334 lines
10 KiB

  1. <template>
  2. <view class="page">
  3. <!-- 顶部页签 -->
  4. <l-nav v-model="tab" :items="['表单信息', '流程信息']" type="flex" class="solid-bottom" />
  5. <!-- 表单区 -->
  6. <view v-if="ready && tab === 0" class="form">
  7. <!-- 表单内容 -->
  8. <l-datetime-picker
  9. @input="setValue('lr_demo_formleave.F_Begin', $event)"
  10. :value="getValue('lr_demo_formleave.F_Begin')"
  11. :disabled="!edit"
  12. title="开始日期"
  13. required
  14. />
  15. <l-datetime-picker
  16. @input="setValue('lr_demo_formleave.F_End', $event)"
  17. :value="getValue('lr_demo_formleave.F_End')"
  18. :disabled="!edit"
  19. title="结束日期"
  20. required
  21. />
  22. <l-input
  23. @input="setValue('lr_demo_formleave.F_Num', $event)"
  24. :value="getValue('lr_demo_formleave.F_Num')"
  25. :disabled="!edit"
  26. title="请假天数"
  27. required
  28. />
  29. <l-textarea
  30. @input="setValue('lr_demo_formleave.F_Reason', $event)"
  31. :value="getValue('lr_demo_formleave.F_Reason')"
  32. :readonly="!edit"
  33. title="请假理由"
  34. />
  35. <!-- 流程标题与优先级 -->
  36. <view v-if="['child', 'create', 'draft', 'again'].includes(type)" class="lr-hidden" style="margin-top: 15px;">
  37. <l-input v-if="needTitle" v-model="title" title="流程标题" placeholder="请为流程设置一个标题" required />
  38. <l-select v-model="level" :range="levelRange" title="流程优先级" placeholder="请选择一个优先级" required />
  39. </view>
  40. <!-- 表单操作区 -->
  41. <l-workflow-action
  42. @audit="audit"
  43. @action="action"
  44. :type="type"
  45. :currentNode="currentNode"
  46. :currentTask="currentTask"
  47. />
  48. </view>
  49. <!-- Tab #2:流程图页 -->
  50. <view v-if="ready && tab === 1" class="progress"><l-workflow-timeline :processList="processList" /></view>
  51. </view>
  52. </template>
  53. <script>
  54. /**
  55. * 系统表单示例
  56. *
  57. */
  58. import get from 'lodash/get'
  59. import set from 'lodash/set'
  60. import moment from 'moment'
  61. import customPageMixins from '@/common/custompage.js'
  62. export default {
  63. mixins: [customPageMixins],
  64. data() {
  65. return {
  66. // 页面参数
  67. tab: 0,
  68. edit: false,
  69. type: 'view',
  70. ready: false,
  71. level: '0',
  72. levelRange: [{ value: '0', text: '普通' }, { value: '1', text: '重要' }, { value: '2', text: '紧急' }],
  73. title: '',
  74. needTitle: false,
  75. code: null,
  76. currentTask: null,
  77. currentNode: null,
  78. processList: [],
  79. processId: null,
  80. parentProcessId: null,
  81. // 表单数据
  82. current: {},
  83. origin: {},
  84. // 表单项数据结构
  85. scheme: {
  86. lr_demo_formleave: {
  87. F_Begin: { type: 'datetime', title: '开始日期', verify: 'NotNull', dateformat: '1' },
  88. F_End: { type: 'datetime', title: '结束日期', verify: 'NotNull', dateformat: '1' },
  89. F_Num: {
  90. type: 'datetimerange',
  91. title: '请假天数',
  92. verify: 'NotNull',
  93. startTime: 'lr_demo_formleave.F_Begin',
  94. endTime: 'lr_demo_formleave.F_End'
  95. },
  96. F_Reason: { type: 'textarea', title: '请假理由' },
  97. F_Id: { type: 'keyValue' }
  98. }
  99. },
  100. // 数据源
  101. dataSource: {
  102. lr_demo_formleave: {}
  103. }
  104. }
  105. },
  106. async onLoad({ type }) {
  107. await this.init(type)
  108. },
  109. methods: {
  110. // 页面初始化
  111. async init(type = 'view') {
  112. this.type = type
  113. this.LOADING('加载表单中…')
  114. const pageParam = this.GET_PARAM()
  115. this.currentTask = pageParam.currentTask
  116. this.currentNode = pageParam.currentNode
  117. this.parentProcessId = pageParam.parentProcessId
  118. this.processList = pageParam.logList || []
  119. const title = this.currentTask.F_Name || this.currentTask.F_Title || this.currentTask.F_SchemeName
  120. this.SET_TITLE(title)
  121. this.edit = ['again', 'child', 'create', 'draft'].includes(this.type)
  122. this.code = this.currentTask.F_Code || this.currentTask.F_SchemeCode
  123. this.needTitle =
  124. ['again', 'child', 'create', 'draft'].includes(this.type) && Number(this.currentNode.isTitle) === 1
  125. this.processId = this.currentTask.F_SchemeCode ? this.currentTask.F_Id : this.GUID()
  126. // 拉取选单数据和表单数据
  127. await Promise.all([() => {}])
  128. await this.fetchForm()
  129. this.ready = true
  130. this.HIDE_LOADING()
  131. },
  132. // 加载表单数据
  133. async fetchForm() {
  134. // 此处处理旧版无外层表结构的表单格式
  135. const formData = {}
  136. formData.lr_demo_formleave = await this.HTTP_GET('learun/adms/demo/wfsys/form', this.processId)
  137. // 原版:
  138. // const formData = await this.HTTP_GET('learun/adms/demo/wfsys/form', this.processId)
  139. if (['again', 'child', 'create'].includes(this.type)) {
  140. this.origin = await this.getDefaultForm()
  141. } else {
  142. this.origin = await this.formatFormData(formData)
  143. }
  144. this.current = this.COPY(this.origin)
  145. },
  146. // 点击操作按钮(非审批类按钮)
  147. async action(actionType) {
  148. switch (actionType) {
  149. // 点击「催办」/「撤销流程」/「标记已阅」按钮
  150. case 'urge':
  151. case 'revoke':
  152. case 'refer':
  153. const actionText = { urge: '催办', revoke: '撤销', refer: '已阅' }[actionType]
  154. const actionUrl = { urge: '/urge', revoke: '/revoke', refer: '/refer' }[actionType]
  155. const actionData = this.processId
  156. if (actionType === 'refer') {
  157. actionData = { processId: this.processId, taskId: this.taskId }
  158. }
  159. if (!(await this.CONFIRM(`${actionText}确认`, `确定要提交${actionText}吗?`, true))) {
  160. return
  161. }
  162. this.LOADING(`提交${actionText}中…`)
  163. this.HTTP_POST(`learun/adms/newwf${actionUrl}`, actionData, `提交${actionText}失败`).then(success => {
  164. this.HIDE_LOADING()
  165. if (success) {
  166. this.EMIT('task-list-change')
  167. this.TOAST(`成功提交${actionText}`, 'success')
  168. }
  169. })
  170. break
  171. // 点击「提交草稿」按钮
  172. case 'draft':
  173. if (!(await this.CONFIRM('提交确认', '确定要提交草稿吗?', true))) {
  174. return
  175. }
  176. this.LOADING('正在提交草稿…')
  177. const draftPostData = await this.getPostData(this.processId)
  178. const pdSuccess = await this.HTTP_POST('learun/adms/demo/wfsys/save', draftPostData, '提交表单失败')
  179. if (!pdSuccess) {
  180. return
  181. }
  182. const draftWorkflowInfo = {
  183. code: this.code,
  184. processId: this.processId,
  185. formreq: JSON.stringify({})
  186. }
  187. const draftSuccess = await this.HTTP_POST('learun/adms/newwf/draft', draftWorkflowInfo, '提交草稿失败')
  188. if (!draftSuccess) {
  189. return
  190. }
  191. this.EMIT('task-list-change')
  192. this.NAV_BACK()
  193. this.TOAST('草稿已保存', 'success')
  194. break
  195. // 点击「发起流程」按钮
  196. case 'submit':
  197. const verifyResult = this.verifyForm(this.scheme)
  198. if (verifyResult.length > 0) {
  199. this.CONFIRM('表单验证失败', verifyResult.join('\n'))
  200. return
  201. }
  202. if (!(await this.CONFIRM('提交确认', '确定要发起流程吗?', true))) {
  203. return
  204. }
  205. this.LOADING('正在提交…')
  206. const postKv = ['create'].includes(this.type) ? '' : this.processId
  207. const postData = await this.getPostData(postKv)
  208. const pSuccess = await this.HTTP_POST('learun/adms/demo/wfsys/save', postData, '表单提交失败')
  209. if (!pSuccess) {
  210. return
  211. }
  212. const workflowInfo = {
  213. code: this.code,
  214. processId: this.processId,
  215. level: this.level,
  216. auditors: JSON.stringify({}),
  217. formreq: JSON.stringify([])
  218. }
  219. if (this.needTitle) {
  220. workflowInfo.title = this.title
  221. }
  222. if (this.type === 'child') {
  223. workflowInfo.parentProcessId = this.parentProcessId
  224. workflowInfo.parentTaskId = this.currentTask.F_TaskId
  225. }
  226. const postUrl = {
  227. create: 'learun/adms/newwf/create',
  228. draft: 'learun/adms/newwf/draft',
  229. again: 'learun/adms/newwf​/againcreate',
  230. child: 'learun/adms/newwf/createchildflow'
  231. }[this.type]
  232. const success = await this.HTTP_POST(postUrl, workflowInfo, '流程提交失败')
  233. if (!success) {
  234. return
  235. }
  236. this.EMIT('task-list-change')
  237. this.NAV_BACK()
  238. this.TOAST('操作成功', 'success')
  239. break
  240. default:
  241. break
  242. }
  243. },
  244. // 点击审批相关按钮
  245. audit(action) {
  246. const pageParam = {
  247. type: 'sign',
  248. processId: this.currentTask.F_Id,
  249. taskId: this.currentTask.F_TaskId,
  250. taskName: this.currentTask.F_Title,
  251. formreq: JSON.stringify([])
  252. }
  253. if (action.code !== '__sign__') {
  254. Object.assign(pageParam, action)
  255. pageParam.type = 'verify'
  256. pageParam.auditors = JSON.stringify({})
  257. }
  258. this.NAV_TO('/pages/nworkflow/myflow/sign', pageParam, true)
  259. },
  260. // 子表格删除一行
  261. tableDelete(tableName, index) {
  262. this.current[tableName].splice(index, 1)
  263. },
  264. // 子表格添加一行
  265. async tableAdd(tableName) {
  266. const newVal = {}
  267. for (const [fieldName, schemeItem] of Object.entries(this.scheme[tableName])) {
  268. if (fieldName !== '__GIRDTABLE__') {
  269. newVal[fieldName] = await this.getDefaultValue(`${tableName}.${fieldName}`, schemeItem)
  270. }
  271. }
  272. this.current[tableName].push(newVal)
  273. },
  274. // 从表弹层输入,可一次性设置多个字段
  275. layerSet(tableIndex, table, field, layerValue) {
  276. const layerData = get(this.scheme, `${table}.${field}.layerData`, [])
  277. layerData.forEach(({ name, value }) => {
  278. this.setValue(`${table}.${tableIndex}.${value}`, layerValue[name] || '')
  279. })
  280. },
  281. // 获取表单值
  282. getValue(path) {
  283. return get(this.current, path)
  284. },
  285. // 设置表单值
  286. setValue(path, val) {
  287. set(this.current, path, val)
  288. }
  289. }
  290. }
  291. </script>