index.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <div class="white">
  3. <m-search :items="searchItems" v-model="searchValues" class="mb-3" @search="onSearch">
  4. <template #button>
  5. <m-button size="small" type="primary" plain icon="el-icon-finished" :loading="submitLoading" @click="onSave">提交待上传文件</m-button>
  6. <m-button size="small" type="warning" plain icon="el-icon-s-promotion" :loading="runLoading" @click="onRun">执行</m-button>
  7. </template>
  8. </m-search>
  9. <m-table
  10. :headers="headers"
  11. :items="items"
  12. v-loading="loading"
  13. >
  14. <!-- <template #header>
  15. <div class="header">
  16. <m-button size="small" type="primary" icon="el-icon-finished" :loading="submitLoading" @click="onSave">提交当前临时文件</m-button>
  17. </div>
  18. </template> -->
  19. <template #month>
  20. {{ queryValues.month }}
  21. </template>
  22. <template #file="{ row }">
  23. {{ filesValues[row.fileType]?.name }}
  24. </template>
  25. <template #actions="{ row }">
  26. <div class="d-flex">
  27. <el-upload
  28. class="mr-3"
  29. action="#"
  30. :limit="1"
  31. :show-file-list="false"
  32. :on-exceed="(files, fileList) => onExceed(files, fileList, row.fileType)"
  33. :http-request="e => onImport(e, row.fileType)"
  34. :on-remove="() => onRemove(row.fileType)"
  35. >
  36. <m-button slot="trigger" text type="primary">导入文件</m-button>
  37. </el-upload>
  38. <m-button text type="danger" v-show="filesValues[row.fileType]" @click="onDelete(row)">移除临时文件</m-button>
  39. </div>
  40. </template>
  41. </m-table>
  42. </div>
  43. </template>
  44. <script>
  45. import {
  46. getSalaryCalculateTemplate,
  47. uploadSalaryCalculateFiles,
  48. getSalaryCalculateFiles
  49. } from '@/api/salary'
  50. import { dateFormat } from '@/utils/date'
  51. export default {
  52. name: 'salaryCalculateUpload',
  53. data () {
  54. return {
  55. searchValues: {
  56. month: dateFormat('YYYY-mm', new Date()),
  57. category: null
  58. },
  59. queryValues: {},
  60. filesValues: {},
  61. categoryItems: [],
  62. historyItems: [],
  63. formItems: [],
  64. headers: [
  65. { label: '月份', prop: 'month', width: 100 },
  66. { label: '业务线', prop: 'category' },
  67. { label: '文件名', prop: 'fileName' },
  68. { label: '文件', prop: 'history' },
  69. { label: '待上传文件', prop: 'file' },
  70. { label: '操作', prop: 'actions' }
  71. ],
  72. loading: false,
  73. submitLoading: false,
  74. runLoading: false
  75. }
  76. },
  77. computed: {
  78. items () {
  79. const items = this.categoryItems.find(e => e.category === this.queryValues.category)?.files
  80. if (!items) {
  81. return []
  82. }
  83. return items.map(e => {
  84. return {
  85. ...e,
  86. history: this.historyItems.find(h => h.fileType === e.fileType)?.fileOriginalFilename
  87. }
  88. })
  89. },
  90. searchItems () {
  91. return [
  92. {
  93. label: '月份',
  94. prop: 'month',
  95. type: 'datePicker',
  96. options: {
  97. clearable: false,
  98. type: 'month',
  99. format: 'yyyy-MM',
  100. valueFormat: 'yyyy-MM',
  101. placeholder: '选择更新月份'
  102. }
  103. },
  104. {
  105. label: '业务线',
  106. prop: 'category',
  107. type: 'select',
  108. options: {
  109. clearable: false,
  110. placeholder: '选择业务线',
  111. items: this.categoryItems.map(e => {
  112. return {
  113. label: e.category,
  114. value: e.category
  115. }
  116. })
  117. }
  118. }
  119. ]
  120. }
  121. },
  122. // created () {
  123. // this.onInit()
  124. // },
  125. methods: {
  126. async onInit () {
  127. try {
  128. const { data } = await getSalaryCalculateTemplate()
  129. this.categoryItems = data
  130. if (!data.length) {
  131. return
  132. }
  133. this.searchValues.category = data[0].category
  134. this.queryValues = { ...this.searchValues }
  135. this.onChange()
  136. this.onGetHistory()
  137. } catch (error) {
  138. this.$message.error(error)
  139. }
  140. },
  141. async onGetHistory () {
  142. try {
  143. this.loading = true
  144. const { data } = await getSalaryCalculateFiles(this.queryValues)
  145. this.historyItems = data
  146. } catch (error) {
  147. this.$message.error(error)
  148. } finally {
  149. this.loading = false
  150. }
  151. },
  152. onSearch (query) {
  153. if (!query.category) {
  154. this.searchValues.category = this.categoryItems[0]?.category ?? null
  155. }
  156. this.queryValues = { ...this.searchValues }
  157. this.onGetHistory()
  158. },
  159. onChange () {
  160. const items = this.categoryItems.find(e => e.category === this.queryValues.category)?.files ?? []
  161. if (!items.length) {
  162. this.filesValues = {}
  163. return
  164. }
  165. this.filesValues = {
  166. ...items.reduce((res, v) => {
  167. res[v.fileType] = null
  168. return res
  169. }, {})
  170. }
  171. },
  172. onExceed (files, fileList, key) {
  173. this.filesValues[key] = files[0]
  174. },
  175. onImport (e, key) {
  176. this.filesValues[key] = e.file
  177. },
  178. onRemove (key) {
  179. this.filesValues[key] = null
  180. },
  181. onDelete (row) {
  182. this.filesValues[row.fileType] = null
  183. },
  184. async onSave () {
  185. if (Object.values(this.filesValues).every(e => e === null)) {
  186. this.$message.warning('请先上传文件')
  187. return
  188. }
  189. const h = this.$createElement
  190. this.$confirm(h('div', [
  191. h('p', undefined, '确定要更新文件吗?'),
  192. h('p', undefined, `更新月份:${this.queryValues.month}`),
  193. h('p', undefined, `更新物业线:${this.queryValues.category}`),
  194. h('p', { style: 'color: red' }, '上传文件后,将覆盖之前的文件,请谨慎操作!')
  195. ]), '提示', {
  196. confirmButtonText: '确定',
  197. cancelButtonText: '取消',
  198. type: 'warning'
  199. }).then(async () => {
  200. this.submitLoading = true
  201. try {
  202. const formData = new FormData()
  203. Object.keys(this.filesValues).forEach(key => {
  204. if (!this.filesValues[key]) {
  205. return
  206. }
  207. formData.append('files', this.filesValues[key])
  208. formData.append('fileTypes', key)
  209. })
  210. formData.append('month', this.queryValues.month)
  211. formData.append('category', this.queryValues.category)
  212. await uploadSalaryCalculateFiles(formData)
  213. this.$message.success('保存成功')
  214. this.onGetHistory()
  215. } catch (error) {
  216. this.$message.error(error)
  217. } finally {
  218. this.submitLoading = false
  219. }
  220. }).catch(_ => {})
  221. },
  222. onRun () {}
  223. }
  224. }
  225. </script>
  226. <style lang="scss" scoped>
  227. .d-flex {
  228. display: flex;
  229. }
  230. .content {
  231. width: 50%;
  232. min-width: 500px;
  233. margin: 0 auto;
  234. }
  235. .buttons {
  236. display: flex;
  237. align-items: center;
  238. justify-content: center;
  239. }
  240. ::v-deep .el-upload-list__item .el-icon-close {
  241. display: inline-block;
  242. &::after {
  243. content: '移除';
  244. }
  245. }
  246. .header {
  247. display: flex;
  248. justify-content: flex-end;
  249. }
  250. </style>