list.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. <template>
  2. <div>
  3. <a-card size="small" :bordered="false" class="searchBoxNormal">
  4. <!-- 搜索条件 -->
  5. <div ref="tableSearch" class="table-page-search-wrapper">
  6. <a-form layout="inline">
  7. <a-row :gutter="15">
  8. <a-col :md="6" :sm="24">
  9. <a-form-item label="费用单号" :label-col="{ span:7 }" :wrapper-col="{ span:17}">
  10. <a-input id="salesManagementList-expenseAccountNo" v-model.trim="queryParam.expenseAccountNo" allowClear placeholder="请输入销售单号"/>
  11. </a-form-item>
  12. </a-col>
  13. <a-col :md="4" :sm="24">
  14. <a-form-item label="申请人" :label-col="{ span:7 }" :wrapper-col="{ span:17}">
  15. <employee style="width: 100%;" id="salesManagementList-Employee" v-model="queryParam.applyPersonSn"></employee>
  16. </a-form-item>
  17. </a-col>
  18. <a-col :md="4" :sm="24">
  19. <a-form-item label="费用类型">
  20. <expenseType
  21. id="salesManagementList-expenseType"
  22. :changeOnSelect="true"
  23. v-model="expenseTypes"
  24. @change="expenseChange"
  25. placeholder="请选择费用类型"
  26. ></expenseType>
  27. </a-form-item>
  28. </a-col>
  29. <a-col :md="4" :sm="24">
  30. <a-form-item label="费用发生月份">
  31. <a-month-picker
  32. placeholder="请选择月份"
  33. locale="zh-cn"
  34. v-model="queryParam.expenseDate"
  35. @change="onChange"
  36. :disabled-date="disabledDate"
  37. style="width: 100%;"/>
  38. </a-form-item>
  39. </a-col>
  40. <template v-if="advanced">
  41. <a-col :md="6" :sm="24">
  42. <a-form-item label="主题">
  43. <a-input id="salesManagementList-title" v-model.trim="queryParam.title" allowClear placeholder="请输入主题"/>
  44. </a-form-item>
  45. </a-col>
  46. <a-col :md="4" :sm="24">
  47. <a-form-item label="打印状态">
  48. <v-select
  49. v-model="queryParam.printStatus"
  50. ref="printStatus"
  51. id="pushOrder-printStatus"
  52. code="EXPENSE_ACCOUNT_PRINT_STATUS"
  53. placeholder="请选择打印状态"
  54. allowClear></v-select>
  55. </a-form-item>
  56. </a-col>
  57. <a-col :md="4" :sm="24">
  58. <a-form-item label="状态">
  59. <v-select
  60. v-model="queryParam.state"
  61. ref="state"
  62. id="salesManagementList-state"
  63. code="EXPENSE_STATE"
  64. placeholder="请选择状态"
  65. allowClear></v-select>
  66. </a-form-item>
  67. </a-col>
  68. <a-col :md="6" :sm="24">
  69. <a-form-item label="销售单号">
  70. <a-input id="salesManagementList-salesBillNo" v-model.trim="queryParam.salesBillNo" allowClear placeholder="请输入销售单号"/>
  71. </a-form-item>
  72. </a-col>
  73. <!-- <a-col :md="4" :sm="24" v-show="isShowCustomerSearch">
  74. <a-form-item label="客服">
  75. <customerService ref="customerName" v-model="queryParam.bizUserSn"></customerService>
  76. </a-form-item>
  77. </a-col> -->
  78. </template>
  79. <a-col :md="6" :sm="24">
  80. <span class="table-page-search-submitButtons">
  81. <a-button type="primary" :disabled="disabled" @click="searchForm">查询</a-button>
  82. <a-button style="margin-left: 8px" :disabled="disabled" @click="resetSearchForm()">重置</a-button>
  83. <a @click="advanced=!advanced" style="margin-left: 8px">
  84. {{ advanced ? '收起' : '展开' }}
  85. <a-icon :type="advanced ? 'up' : 'down'"/>
  86. </a>
  87. </span>
  88. </a-col>
  89. </a-row>
  90. </a-form>
  91. </div>
  92. </a-card>
  93. <a-card size="small" :bordered="false" class="salesManagementList-wrap">
  94. <a-spin :spinning="spinning" tip="Loading...">
  95. <!-- 操作按钮 -->
  96. <div class="table-operator">
  97. <a-button type="primary" v-if="$hasPermissions('B_eRNew')" @click="handleEdit()">新增</a-button>
  98. <a-button type="primary" v-if="$hasPermissions('B_eRPrint')" :loading="spinning" @click="handlePlPrint()" ghost>批量打印</a-button>
  99. <a-checkbox v-model="printRemark" v-if="$hasPermissions('B_eRPrint')" id="print-remark">打印备注</a-checkbox>
  100. <span style="margin-left: 8px" v-if="$hasPermissions('B_eRPrint')">
  101. <template v-if="rowSelectionInfo && rowSelectionInfo.selectedRowKeys.length>0">{{ `已选 ${rowSelectionInfo.selectedRowKeys.length} 项` }}</template>
  102. </span>
  103. </div>
  104. <!-- 列表 -->
  105. <s-table
  106. class="sTable fixPagination"
  107. ref="table"
  108. :row-selection="$hasPermissions('B_eRPrint')?{ columnWidth: '4%', getCheckboxProps: record => ({ props: { disabled: false } })}:null"
  109. @rowSelection="rowSelectionFun"
  110. :style="{ height: tableHeight+70+'px' }"
  111. size="small"
  112. :rowKey="(record) => record.id"
  113. :columns="columns"
  114. :pageSize="30"
  115. :data="loadData"
  116. :scroll="{ y: tableHeight }"
  117. :defaultLoadData="false"
  118. bordered>
  119. <!-- 单号 -->
  120. <template slot="expenseAccountNo" slot-scope="text, record">
  121. <span v-if="$hasPermissions('B_eRdetail')" class="link-bule" @click="handleDetail(record)">{{ record.expenseAccountNo }}</span>
  122. <div v-else>{{ record.expenseAccountNo||'--' }}</div>
  123. </template>
  124. <!-- 总数量 -->
  125. <template slot="totalQty" slot-scope="text, record">
  126. {{ record.totalQty }}
  127. </template>
  128. <!-- 费用类型 -->
  129. <template slot="expenseType" slot-scope="text, record">
  130. <div>{{ record.expenseTypeName || '--' }}<span v-if="record.expenseType2">/{{ record.expenseTypeName2 || '--' }}</span><span v-if="record.expenseType3">/{{ record.expenseTypeName3 || '--' }}</span></div>
  131. </template>
  132. <!-- 操作 -->
  133. <template slot="action" slot-scope="text, record">
  134. <a-button
  135. v-if="record.state=='WAIT_SUBMIT'&&$hasPermissions('B_ERtEdit')"
  136. size="small"
  137. type="link"
  138. class="button-info"
  139. @click="handleEdit(record)"
  140. >
  141. 编辑
  142. </a-button>
  143. <a-button
  144. v-if="record.state=='WAIT_SUBMIT'&&$hasPermissions('B_ERDel')"
  145. size="small"
  146. type="link"
  147. class="button-error"
  148. @click="handleDel(record)"
  149. >
  150. 删除
  151. </a-button>
  152. <a-button
  153. v-if="record.state!='WAIT_SUBMIT'&&$hasPermissions('B_ERAudit')"
  154. size="small"
  155. type="link"
  156. class="button-info"
  157. @click="handleSH(record)"
  158. >
  159. 审核进度
  160. </a-button>
  161. <a-button
  162. v-if="record.state=='AUDIT_REJECT'"
  163. size="small"
  164. type="link"
  165. class="button-info"
  166. @click="againEdit(record)"
  167. >
  168. 再次编辑
  169. </a-button>
  170. <!-- <span v-if="record.state=='AUDIT_REJECT' || record.state=='AUDIT_PASS'">--</span> -->
  171. </template>
  172. </s-table>
  173. </a-spin>
  174. <!-- 审核进度 -->
  175. <verifyModal v-drag :openModal="openModal" :itemSn="itemSn" @close="openModal=false"></verifyModal>
  176. <!-- 新增 -->
  177. <baseDataModal :show="openBaseModal" @close="openBaseModal=false"></baseDataModal>
  178. <!-- 打印预览 -->
  179. <commonModal
  180. modalTit="费用报销单打印预览"
  181. width="700pt"
  182. okText="立即打印"
  183. :openModal="showTipModal"
  184. @cancel="showTipModal=false"
  185. @ok="$refs.printModal.prints()">
  186. <previewModal v-if="showTipModal" ref="printModal" @printOk="printOk"></previewModal>
  187. </commonModal>
  188. </a-card>
  189. </div>
  190. </template>
  191. <script>
  192. import { commonMixin } from '@/utils/mixin'
  193. import locale from 'ant-design-vue/es/date-picker/locale/zh_CN'
  194. import moment from 'moment'
  195. import subarea from '@/views/common/subarea.js'
  196. import employee from './employee.js'
  197. import { STable, VSelect } from '@/components'
  198. import verifyModal from './verifyModal.vue'
  199. import previewModal from './previewModal.vue'
  200. import commonModal from '@/views/common/commonModal.vue'
  201. import expenseType from '@/views/common/expenseType.js'
  202. import { getBatchLastProcessInstance } from '@/api/financeBook'
  203. import customerService from '@/views/common/customerService'
  204. import { expenseAccountList, expenseAccountDelete, expenseAccountAgainEdit, expenseAcctDetailFindList, expenseAccountUpdateBatch } from '@/api/expenseManagement'
  205. import baseDataModal from './baseDataModal.vue'
  206. export default {
  207. name: 'ExpenseReimbursementList',
  208. mixins: [commonMixin],
  209. components: { STable, VSelect, subarea, verifyModal, baseDataModal, employee, expenseType, previewModal, commonModal, customerService },
  210. data () {
  211. const _this = this
  212. return {
  213. locale,
  214. spinning: false,
  215. advanced: true, // 高级搜索 展开/关闭
  216. disabled: false, // 查询、重置按钮是否可操作
  217. openModal: false, // 审核进度弹框是否显示
  218. openBaseModal: false, // 基础信息新建
  219. showTipModal: false,
  220. itemSn: '', // 费用单sn
  221. tableHeight: 0,
  222. expenseTypes: [],
  223. // 查询参数
  224. queryParam: {
  225. expenseDate: moment().format('YYYY-MM'), // 月份
  226. expenseAccountNo: '', // 费用单号
  227. title: '', // 主题
  228. expenseType: undefined, // 费用类型
  229. expenseType2: undefined, // 费用类型2
  230. expenseType3: undefined, // 费用类型3
  231. printStatus: undefined, // 打印状态
  232. state: undefined, // 状态
  233. salesBillNo: '', // 销售单号
  234. bizUserSn: undefined
  235. },
  236. columns: [
  237. { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
  238. { title: '费用单号', width: '8%', align: 'center', scopedSlots: { customRender: 'expenseAccountNo' } },
  239. { title: '申请人', dataIndex: 'applyPersonName', width: '6%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
  240. { title: '申请部门', dataIndex: 'applyDepartmentName', width: '8%', align: 'left', customRender: function (text) { return text || '--' } },
  241. { title: '费用类型', scopedSlots: { customRender: 'expenseType' }, width: '8%', align: 'left' },
  242. { title: '费用发生月份', dataIndex: 'expenseDate', width: '6%', align: 'center', customRender: function (text) { return moment(text).format('YYYY年MM月') || '--' } },
  243. { title: '主题', dataIndex: 'title', width: '10%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
  244. { title: '合计金额', dataIndex: 'applyExpenseTotal', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  245. { title: '创建时间', dataIndex: 'createDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
  246. { title: '审核时间', dataIndex: 'finishDate', width: '8%', align: 'center', customRender: function (text, record) { return record.state == 'AUDIT_REJECT' || record.state == 'AUDIT_PASS' ? text : '--' } },
  247. { title: '打印状态', dataIndex: 'printStatusDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
  248. { title: '状态', dataIndex: 'stateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
  249. { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
  250. ],
  251. // 加载数据方法 必须为 Promise 对象
  252. loadData: parameter => {
  253. this.disabled = true
  254. this.spinning = true
  255. delete parameter.tableId
  256. delete parameter.index
  257. const params = Object.assign(parameter, this.queryParam)
  258. if (params.expenseDate) {
  259. params.expenseDate = params.expenseDate + '-01'
  260. }
  261. return expenseAccountList(params).then(res => {
  262. let data
  263. if (res.status == 200) {
  264. data = res.data
  265. const no = (data.pageNo - 1) * data.pageSize
  266. for (var i = 0; i < data.list.length; i++) {
  267. data.list[i].no = no + i + 1
  268. data.list[i].content = data.list[i].content ? data.list[i].content.replace(/\n+/, '\n').split('\n') : ''
  269. }
  270. this.disabled = false
  271. }
  272. this.spinning = false
  273. return data
  274. })
  275. },
  276. rowSelectionInfo: null, // 批量选择的数据
  277. printRemark: false // 是否打印备注
  278. }
  279. },
  280. methods: {
  281. // 表格选中项
  282. rowSelectionFun (obj) {
  283. this.rowSelectionInfo = obj || null
  284. },
  285. printOk (data) {
  286. if (data && data.status == 200) {
  287. const rows = this.rowSelectionInfo && this.rowSelectionInfo.selectedRows || []
  288. const ret = []
  289. rows.map(item => {
  290. ret.push({
  291. id: item.id,
  292. printStatus: 'PRINT'
  293. })
  294. })
  295. expenseAccountUpdateBatch(ret).then(res => {
  296. if (res.status == 200) {
  297. this.$refs.table.refresh()
  298. this.$refs.table.clearSelected()
  299. }
  300. this.spinning = false
  301. this.showTipModal = false
  302. })
  303. } else {
  304. this.spinning = false
  305. }
  306. },
  307. // 批量打印
  308. async handlePlPrint () {
  309. const _this = this
  310. const rows = _this.rowSelectionInfo && _this.rowSelectionInfo.selectedRows || []
  311. const slen = rows.length
  312. if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && slen < 1)) {
  313. _this.$message.warning('请在列表勾选后再进行批量操作!')
  314. return false
  315. }
  316. this.spinning = true
  317. const pageData = []
  318. const businessSnList = []
  319. for (let i = 0; i < rows.length; i++) {
  320. // 费用明细
  321. const fyListData = await expenseAcctDetailFindList({ expenseAccountSn: rows[i].expenseAccountSn }).then(res => res.data)
  322. // 审核明细,待提交状态不获取
  323. if (rows[i].state != 'WAIT_SUBMIT') {
  324. businessSnList.push(rows[i].expenseAccountSn)
  325. }
  326. pageData.push({
  327. printRemark: this.printRemark,
  328. expenseInfo: rows[i],
  329. fyListData: fyListData,
  330. spListData: []
  331. })
  332. }
  333. // 获取审核进度信息
  334. const spListData = await getBatchLastProcessInstance({ 'businessType''EXPENSES', 'businessSnList': businessSnList }).then(res => res.data)
  335. pageData.map(item => {
  336. if (spListData) {
  337. const sp = spListData[item.expenseInfo.expenseAccountSn]
  338. item.spListData = sp ? sp.taskVOList : []
  339. }
  340. })
  341. console.log(pageData)
  342. // 打开预览弹框
  343. this.showTipModal = true
  344. this.$nextTick(() => {
  345. this.$refs.printModal.setData(pageData)
  346. this.spinning = false
  347. })
  348. },
  349. onChange (date, dateString) {
  350. this.queryParam.expenseDate = dateString
  351. },
  352. disabledDate (current) {
  353. return current && current > moment().endOf('day')
  354. },
  355. expenseChange (val, opts) {
  356. console.log(val, opts)
  357. this.expenseTypes = val || []
  358. this.queryParam.expenseType = val && val[0] ? val[0] : ''
  359. this.queryParam.expenseType2 = val && val[1] ? val[1] : ''
  360. this.queryParam.expenseType3 = val && val[2] ? val[2] : ''
  361. },
  362. // 详情
  363. handleDetail (row) {
  364. this.$router.push({ name: 'expenseReimbursementListDetail', params: { sn: row.expenseAccountSn } })
  365. },
  366. // 新增、编辑
  367. handleEdit (row) {
  368. if (row && row.expenseAccountSn) {
  369. this.$router.push({ name: 'expenseReimbursementEdit', params: { sn: row.expenseAccountSn } })
  370. } else {
  371. this.openBaseModal = true
  372. }
  373. },
  374. // 删除
  375. handleDel (row) {
  376. const _this = this
  377. this.$confirm({
  378. title: '提示',
  379. content: '确认要删除吗?',
  380. centered: true,
  381. closable: true,
  382. onOk () {
  383. _this.spinning = true
  384. expenseAccountDelete({ expenseAccountSn: row.expenseAccountSn }).then(res => {
  385. if (res.status == 200) {
  386. _this.$message.success(res.message)
  387. _this.$refs.table.refresh()
  388. _this.spinning = false
  389. } else {
  390. _this.spinning = false
  391. }
  392. })
  393. }
  394. })
  395. },
  396. // 审核进度
  397. handleSH (row) {
  398. this.openModal = true
  399. this.itemSn = row.expenseAccountSn
  400. },
  401. // 再次编辑
  402. againEdit (row) {
  403. const _this = this
  404. this.$confirm({
  405. title: '操作提示',
  406. content: '系统将自动生成一个新的费用报销单,与原审核不通过的单据内容相同。您可以对新单据进行编辑、提交等操作,原单据保持不变,确认操作吗?',
  407. centered: true,
  408. closable: true,
  409. onOk () {
  410. _this.spinning = true
  411. expenseAccountAgainEdit({ expenseAccountSn: row.expenseAccountSn }).then(res => {
  412. if (res.status == 200) {
  413. _this.$message.success(res.message)
  414. _this.resetSearchForm()
  415. }
  416. _this.spinning = false
  417. })
  418. }
  419. })
  420. },
  421. searchForm () {
  422. this.$refs.table.refresh(true)
  423. this.$refs.table.clearSelected()
  424. },
  425. // 重置
  426. resetSearchForm () {
  427. this.queryParam = {
  428. expenseDate: '', // 月份
  429. expenseAccountNo: '', // 费用单号
  430. title: '', // 主题
  431. expenseType: undefined, // 费用类型
  432. expenseType2: undefined, // 费用类型2
  433. expenseType3: undefined, // 费用类型3
  434. state: undefined, // 状态
  435. printStatus: undefined,
  436. applyPersonSn: undefined,
  437. salesBillNo: '', // 销售单号
  438. bizUserSn: undefined
  439. }
  440. this.expenseTypes = []
  441. this.searchForm()
  442. },
  443. pageInit () {
  444. const _this = this
  445. this.$nextTick(() => { // 页面渲染完成后的回调
  446. _this.setTableH()
  447. })
  448. },
  449. setTableH () {
  450. const tableSearchH = this.$refs.tableSearch.offsetHeight
  451. this.tableHeight = window.innerHeight - tableSearchH - 240
  452. }
  453. },
  454. watch: {
  455. advanced (newValue, oldValue) {
  456. const _this = this
  457. this.$nextTick(() => { // 页面渲染完成后的回调
  458. _this.setTableH()
  459. })
  460. },
  461. '$store.state.app.winHeight' (newValue, oldValue) { // 窗口变更时,需同时更改表格高度
  462. this.setTableH()
  463. }
  464. },
  465. mounted () {
  466. if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
  467. this.pageInit()
  468. this.resetSearchForm()
  469. }
  470. },
  471. activated () {
  472. // 如果是新页签打开,则重置当前页面
  473. if (this.$store.state.app.isNewTab) {
  474. this.pageInit()
  475. this.resetSearchForm()
  476. }
  477. // 仅刷新列表,不重置页面
  478. if (this.$store.state.app.updateList) {
  479. this.pageInit()
  480. this.$refs.table.refresh()
  481. }
  482. },
  483. beforeRouteEnter (to, from, next) {
  484. next(vm => {})
  485. }
  486. }
  487. </script>
  488. <style lang="less">
  489. .salesManagementList-wrap{
  490. .sTable{
  491. .badge-con-t{
  492. .ant-badge-count{
  493. transform: scale(0.8);
  494. font-size: 13px;
  495. }
  496. }
  497. }
  498. }
  499. </style>