DingTalkFromToVue.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <template>
  2. <div class="">
  3. <el-form ref="dingtalkForm" label-position="top" :model="dingtalkForm">
  4. <el-row :gutter="20">
  5. <div v-for="(item, index) in dingtalkForm.items" :key="index">
  6. <el-col v-if="item.componentName !== 'TableField'" :span="colSpan">
  7. <el-form-item
  8. :label="item.props.label"
  9. :prop="'items.' + index + '.props.value'"
  10. :rules="{
  11. required: item.props.required,
  12. message: '不能为空',
  13. trigger: ['blur', 'change'],
  14. }">
  15. <!--文本框-->
  16. <el-input
  17. v-if="item.componentName === 'TextField'"
  18. v-model="item.props.value"
  19. :disabled="item.props.disabled"
  20. :placeholder="item.props.placeholder" />
  21. <!--文本域-->
  22. <el-input
  23. v-else-if="item.componentName === 'TextareaField'"
  24. v-model="item.props.value"
  25. :disabled="item.props.disabled"
  26. :placeholder="item.props.placeholder"
  27. :rows="5"
  28. show-word-limit
  29. type="textarea" />
  30. <!--下拉选-->
  31. <el-select
  32. v-else-if="item.componentName === 'DDSelectField'"
  33. v-model="item.props.value"
  34. clearable
  35. :disabled="item.props.disabled"
  36. :placeholder="item.props.placeholder"
  37. style="width: 100%">
  38. <el-option
  39. v-for="option in selectDataToJson(item.props.options)"
  40. :key="option.key"
  41. :label="option.value"
  42. :value="option.value" />
  43. </el-select>
  44. <!--下拉多选-->
  45. <el-select
  46. v-else-if="item.componentName === 'DDMultiSelectField'"
  47. v-model="item.props.value"
  48. clearable
  49. :disabled="item.props.disabled"
  50. multiple
  51. :placeholder="item.props.placeholder"
  52. style="width: 100%">
  53. <el-option
  54. v-for="option in selectDataToJson(item.props.options)"
  55. :key="option.key"
  56. :label="option.value"
  57. :value="option.value" />
  58. </el-select>
  59. <!--时间选择器-->
  60. <el-date-picker
  61. v-else-if="item.componentName === 'DDDateField'"
  62. v-model="item.props.value"
  63. :disabled="item.props.disabled"
  64. :placeholder="item.props.placeholder"
  65. type="daterange"
  66. :value-format="item.props.format" />
  67. <!--时间范围选择器-->
  68. <el-date-picker
  69. v-else-if="item.componentName === 'DDDateRangeField'"
  70. v-model="item.props.value"
  71. :disabled="item.props.disabled"
  72. :end-placeholder="item.props.placeholder[1]"
  73. :start-placeholder="item.props.placeholder[0]"
  74. style="width: 100%"
  75. type="daterange"
  76. :value-format="item.props.format" />
  77. <!--文件-->
  78. <el-upload
  79. v-else-if="item.componentName === 'DDAttachment'"
  80. :ref="item.props.id"
  81. action="#"
  82. :auto-upload="false"
  83. :file-list="item.props.value"
  84. :limit="1"
  85. :on-change="
  86. (file) => {
  87. return setFile(index, file)
  88. }
  89. ">
  90. <el-button size="mini" type="primary">点击上传</el-button>
  91. </el-upload>
  92. <!--选择用户-->
  93. <el-input
  94. v-else-if="item.componentName === 'InnerContactField'"
  95. v-model="item.props.value"
  96. :disabled="item.props.disabled"
  97. :placeholder="item.props.placeholder"
  98. readonly
  99. suffix-icon="el-icon-search"
  100. @focus="handleSelectUser(index)" />
  101. </el-form-item>
  102. </el-col>
  103. <el-col v-if="item.componentName === 'TableField'" :span="24">
  104. <el-form-item :label="item.props.label" :prop="item.props.id" :required="item.props.required">
  105. <el-button
  106. v-show="item.props.actionName"
  107. style="float: right; margin-top: -20px"
  108. @click="addTableData(index)">
  109. {{ item.props.actionName }}
  110. </el-button>
  111. <!--表格-->
  112. <el-table :key="dingTableFlag" :ref="'dingTable' + index" border :data="item.tableData" height="250px">
  113. <el-table-column
  114. v-for="(child, idx) in item.children"
  115. :key="idx"
  116. align="center"
  117. :label="child.props.label"
  118. :prop="child.props.id"
  119. show-overflow-tooltip>
  120. <template #default="{ row }">
  121. <!--文本框-->
  122. <el-select
  123. v-if="child.props.label === '产品型号'"
  124. v-model="row[child.props.id]"
  125. filterable
  126. :placeholder="item.props.placeholder"
  127. value-key="prodCode"
  128. @change="(val) => selectLabel(val, item.children, row)">
  129. <el-option v-for="prod in productList" :key="prod.id" :label="prod.prodCode" :value="prod" />
  130. </el-select>
  131. <el-select
  132. v-if="child.props.label === '产品名称'"
  133. v-model="row[child.props.id]"
  134. filterable
  135. :placeholder="item.props.placeholder"
  136. value-key="prodName"
  137. @change="(val) => selectLabel(val, item.children, row)">
  138. <el-option v-for="prod in productList" :key="prod.id" :label="prod.prodName" :value="prod" />
  139. </el-select>
  140. <!--数字文本框-->
  141. <el-input
  142. v-if="child.componentName === 'NumberField'"
  143. v-model="row[child.props.id]"
  144. :min="1"
  145. onkeyup="value=value.replace(/[^\d]/g,'')" />
  146. </template>
  147. </el-table-column>
  148. </el-table>
  149. </el-form-item>
  150. </el-col>
  151. </div>
  152. </el-row>
  153. </el-form>
  154. <!-- 选择人员弹窗 -->
  155. <select-user ref="selectUser" @save="selectUser" />
  156. </div>
  157. </template>
  158. <script>
  159. import productApi from '@/api/base/product'
  160. import SelectUser from '@/components/select/SelectUser'
  161. export default {
  162. name: 'DingTalkFromToVue',
  163. components: {
  164. SelectUser,
  165. },
  166. props: {
  167. colSpan: {
  168. type: Number,
  169. default: 24,
  170. },
  171. },
  172. data() {
  173. return {
  174. dingtalkForm: {},
  175. fileList: [],
  176. productList: [],
  177. dingRules: {},
  178. userItemIndex: {},
  179. dingTableFlag: true,
  180. }
  181. },
  182. mounted() {
  183. this.getProduct()
  184. },
  185. // 方法集合
  186. methods: {
  187. selectLabel(val, children, row) {
  188. const codeId = children.find((item) => item.props.label == '产品型号').props.id
  189. const nameId = children.find((item) => item.props.label == '产品名称').props.id
  190. row[codeId] = val.prodCode
  191. row[nameId] = val.prodName
  192. },
  193. getProduct() {
  194. let params = {
  195. pageNum: 1,
  196. pageSize: 999,
  197. }
  198. Promise.all([productApi.getList({ ...params })])
  199. .then(([product]) => {
  200. this.productList = product.data.list || []
  201. })
  202. .catch((err) => console.log(err))
  203. },
  204. addTableData(index) {
  205. let newObj = {}
  206. let tableData = this.dingtalkForm.items[index].tableData
  207. if (!tableData) {
  208. this.dingtalkForm.items[index].tableData = []
  209. }
  210. for (let child of this.dingtalkForm.items[index].children) {
  211. newObj[child.props.id] = ''
  212. }
  213. this.dingtalkForm.items[index].tableData.push(newObj)
  214. this.dingTableFlag = !this.dingTableFlag
  215. },
  216. handleSelectUser(index) {
  217. this.userItemIndex = index
  218. this.$refs.selectUser.open()
  219. },
  220. selectUser(val) {
  221. let nickName = val.map((item) => item.nickName).join()
  222. this.dingtalkForm.items[this.userItemIndex].props.value = nickName
  223. this.$forceUpdate()
  224. },
  225. // 文件
  226. setFile(index, file) {
  227. this.$emit('upload', file.raw)
  228. this.dingtalkForm.items[index].props.value = file.name
  229. // 上传文件一直校验不过问题方案
  230. let temp = JSON.parse(JSON.stringify(this.dingtalkForm))
  231. this.$refs.dingtalkForm.clearValidate('items.' + index + '.props.value')
  232. this.dingtalkForm = temp
  233. return true
  234. },
  235. selectDataToJson(data) {
  236. return data.map((item) => {
  237. return JSON.parse(item)
  238. })
  239. },
  240. setFormAndRules(dingtalkForm) {
  241. for (let index in dingtalkForm.items) {
  242. if (dingtalkForm.items[index].componentName === 'DDDateRangeField') {
  243. dingtalkForm.items[index].props.placeholder = JSON.parse(dingtalkForm.items[index].props.label)
  244. dingtalkForm.items[index].props.label = dingtalkForm.items[index].props.placeholder.join(' - ')
  245. }
  246. }
  247. this.dingtalkForm = dingtalkForm
  248. },
  249. getFormData() {
  250. for (let index in this.dingtalkForm.items) {
  251. // 表格数据需要特殊处理
  252. if (this.dingtalkForm.items[index].componentName === 'TableField') {
  253. this.dingtalkForm.items[index].props.value = []
  254. let tableData = this.dingtalkForm.items[index].tableData
  255. for (let row of tableData) {
  256. // 循环数据,组装信息
  257. let newData = []
  258. for (let colKey in row) {
  259. let child = this.dingtalkForm.items[index].children.find((val) => {
  260. return val.props.id === colKey //筛选出匹配数据
  261. })
  262. newData.push({
  263. value: row[colKey],
  264. id: child.props.id,
  265. name: child.props.label,
  266. required: child.props.required,
  267. componentName: child.componentName,
  268. })
  269. }
  270. this.dingtalkForm.items[index].props.value.push(newData)
  271. }
  272. }
  273. }
  274. return this.dingtalkForm
  275. },
  276. validateForm() {
  277. let result = false
  278. this.$refs['dingtalkForm'].validate((valid) => {
  279. result = valid
  280. })
  281. return result
  282. },
  283. resetForm() {
  284. this.$refs['dingtalkForm'].resetFields()
  285. },
  286. },
  287. }
  288. </script>
  289. <style lang="scss" scoped></style>