index.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <template>
  2. <doc-alert title="【回款】回款管理、回款计划" url="https://doc.xindazhou.com/crm/receivable/" />
  3. <doc-alert title="【通用】数据权限" url="https://doc.xindazhou.com/crm/permission/" />
  4. <ContentWrap>
  5. <!-- 搜索工作栏 -->
  6. <el-form
  7. ref="queryFormRef"
  8. :inline="true"
  9. :model="queryParams"
  10. class="-mb-15px"
  11. label-width="68px"
  12. >
  13. <el-form-item label="回款编号" prop="no">
  14. <el-input
  15. v-model="queryParams.no"
  16. class="!w-240px"
  17. clearable
  18. placeholder="请输入回款编号"
  19. @keyup.enter="handleQuery"
  20. />
  21. </el-form-item>
  22. <el-form-item label="客户名称" prop="customerId">
  23. <el-select
  24. v-model="queryParams.customerId"
  25. class="!w-240px"
  26. placeholder="请选择客户"
  27. @keyup.enter="handleQuery"
  28. >
  29. <el-option
  30. v-for="item in customerList"
  31. :key="item.id"
  32. :label="item.name"
  33. :value="item.id"
  34. />
  35. </el-select>
  36. </el-form-item>
  37. <el-form-item>
  38. <el-button @click="handleQuery">
  39. <Icon class="mr-5px" icon="ep:search" />
  40. 搜索
  41. </el-button>
  42. <el-button @click="resetQuery">
  43. <Icon class="mr-5px" icon="ep:refresh" />
  44. 重置
  45. </el-button>
  46. <el-button
  47. v-hasPermi="['crm:receivable:create']"
  48. plain
  49. type="primary"
  50. @click="openForm('create')"
  51. >
  52. <Icon class="mr-5px" icon="ep:plus" />
  53. 新增
  54. </el-button>
  55. <el-button
  56. v-hasPermi="['crm:receivable:export']"
  57. :loading="exportLoading"
  58. plain
  59. type="success"
  60. @click="handleExport"
  61. >
  62. <Icon class="mr-5px" icon="ep:download" />
  63. 导出
  64. </el-button>
  65. </el-form-item>
  66. </el-form>
  67. </ContentWrap>
  68. <!-- 列表 -->
  69. <ContentWrap>
  70. <el-tabs v-model="activeName" @tab-click="handleTabClick">
  71. <el-tab-pane label="我负责的" name="1" />
  72. <el-tab-pane label="我参与的" name="2" />
  73. <el-tab-pane label="下属负责的" name="3" />
  74. </el-tabs>
  75. <el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
  76. <el-table-column align="center" fixed="left" label="回款编号" prop="no" width="180">
  77. <template #default="scope">
  78. <el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
  79. {{ scope.row.no }}
  80. </el-link>
  81. </template>
  82. </el-table-column>
  83. <el-table-column align="center" label="客户名称" prop="customerName" width="120">
  84. <template #default="scope">
  85. <el-link
  86. :underline="false"
  87. type="primary"
  88. @click="openCustomerDetail(scope.row.customerId)"
  89. >
  90. {{ scope.row.customerName }}
  91. </el-link>
  92. </template>
  93. </el-table-column>
  94. <el-table-column align="center" label="合同编号" prop="contractNo" width="180">
  95. <template #default="scope">
  96. <el-link
  97. :underline="false"
  98. type="primary"
  99. @click="openContractDetail(scope.row.contractId)"
  100. >
  101. {{ scope.row.contract.no }}
  102. </el-link>
  103. </template>
  104. </el-table-column>
  105. <el-table-column
  106. :formatter="dateFormatter2"
  107. align="center"
  108. label="回款日期"
  109. prop="returnTime"
  110. width="150px"
  111. />
  112. <el-table-column
  113. align="center"
  114. label="回款金额(元)"
  115. prop="price"
  116. width="140"
  117. :formatter="erpPriceTableColumnFormatter"
  118. />
  119. <el-table-column align="center" label="回款方式" prop="returnType" width="130px">
  120. <template #default="scope">
  121. <dict-tag :type="DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE" :value="scope.row.returnType" />
  122. </template>
  123. </el-table-column>
  124. <el-table-column align="center" label="备注" prop="remark" width="200" />
  125. <el-table-column
  126. align="center"
  127. label="合同金额(元)"
  128. prop="contract.totalPrice"
  129. width="140"
  130. :formatter="erpPriceTableColumnFormatter"
  131. />
  132. <el-table-column align="center" label="负责人" prop="ownerUserName" width="120" />
  133. <el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
  134. <el-table-column
  135. :formatter="dateFormatter"
  136. align="center"
  137. label="更新时间"
  138. prop="updateTime"
  139. width="180px"
  140. />
  141. <el-table-column
  142. :formatter="dateFormatter"
  143. align="center"
  144. label="创建时间"
  145. prop="createTime"
  146. width="180px"
  147. />
  148. <el-table-column align="center" label="创建人" prop="creatorName" width="120" />
  149. <el-table-column align="center" fixed="right" label="回款状态" prop="auditStatus" width="120">
  150. <template #default="scope">
  151. <dict-tag :type="DICT_TYPE.CRM_AUDIT_STATUS" :value="scope.row.auditStatus" />
  152. </template>
  153. </el-table-column>
  154. <el-table-column align="center" fixed="right" label="操作" width="180px">
  155. <template #default="scope">
  156. <el-button
  157. v-hasPermi="['crm:receivable:update']"
  158. link
  159. type="primary"
  160. @click="openForm('update', scope.row.id)"
  161. >
  162. 编辑
  163. </el-button>
  164. <el-button
  165. v-if="scope.row.auditStatus === 0"
  166. v-hasPermi="['crm:receivable:update']"
  167. link
  168. type="primary"
  169. @click="handleSubmit(scope.row)"
  170. >
  171. 提交审核
  172. </el-button>
  173. <el-button
  174. v-else
  175. v-hasPermi="['crm:receivable:update']"
  176. link
  177. type="primary"
  178. @click="handleProcessDetail(scope.row)"
  179. >
  180. 查看审批
  181. </el-button>
  182. <el-button
  183. v-hasPermi="['crm:receivable:delete']"
  184. link
  185. type="danger"
  186. @click="handleDelete(scope.row.id)"
  187. >
  188. 删除
  189. </el-button>
  190. </template>
  191. </el-table-column>
  192. </el-table>
  193. <!-- 分页 -->
  194. <Pagination
  195. v-model:limit="queryParams.pageSize"
  196. v-model:page="queryParams.pageNo"
  197. :total="total"
  198. @pagination="getList"
  199. />
  200. </ContentWrap>
  201. <!-- 表单弹窗:添加/修改 -->
  202. <ReceivableForm ref="formRef" @success="getList" />
  203. </template>
  204. <script lang="ts" setup>
  205. import { DICT_TYPE } from '@/utils/dict'
  206. import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
  207. import download from '@/utils/download'
  208. import * as ReceivableApi from '@/api/crm/receivable'
  209. import ReceivableForm from './ReceivableForm.vue'
  210. import * as CustomerApi from '@/api/crm/customer'
  211. import { TabsPaneContext } from 'element-plus'
  212. import { erpPriceTableColumnFormatter } from '@/utils'
  213. defineOptions({ name: 'Receivable' })
  214. const message = useMessage() // 消息弹窗
  215. const { t } = useI18n() // 国际化
  216. const loading = ref(true) // 列表的加载中
  217. const total = ref(0) // 列表的总页数
  218. const list = ref([]) // 列表的数据
  219. const queryParams = reactive({
  220. pageNo: 1,
  221. pageSize: 10,
  222. sceneType: '1', // 默认和 activeName 相等
  223. no: undefined,
  224. customerId: undefined
  225. })
  226. const queryFormRef = ref() // 搜索的表单
  227. const exportLoading = ref(false) // 导出的加载中
  228. const activeName = ref('1') // 列表 tab
  229. const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表
  230. /** tab 切换 */
  231. const handleTabClick = (tab: TabsPaneContext) => {
  232. queryParams.sceneType = tab.paneName
  233. handleQuery()
  234. }
  235. /** 查询列表 */
  236. const getList = async () => {
  237. loading.value = true
  238. try {
  239. const data = await ReceivableApi.getReceivablePage(queryParams)
  240. list.value = data.list
  241. total.value = data.total
  242. } finally {
  243. loading.value = false
  244. }
  245. }
  246. /** 搜索按钮操作 */
  247. const handleQuery = () => {
  248. queryParams.pageNo = 1
  249. getList()
  250. }
  251. /** 重置按钮操作 */
  252. const resetQuery = () => {
  253. queryFormRef.value.resetFields()
  254. handleQuery()
  255. }
  256. /** 添加/修改操作 */
  257. const formRef = ref()
  258. const openForm = (type: string, id?: number) => {
  259. formRef.value.open(type, id)
  260. }
  261. /** 删除按钮操作 */
  262. const handleDelete = async (id: number) => {
  263. try {
  264. // 删除的二次确认
  265. await message.delConfirm()
  266. // 发起删除
  267. await ReceivableApi.deleteReceivable(id)
  268. message.success(t('common.delSuccess'))
  269. // 刷新列表
  270. await getList()
  271. } catch {}
  272. }
  273. /** 提交审核 **/
  274. const handleSubmit = async (row: ReceivableApi.ReceivableVO) => {
  275. await message.confirm(`您确定提交编号为【${row.no}】的回款审核吗?`)
  276. await ReceivableApi.submitReceivable(row.id)
  277. message.success('提交审核成功!')
  278. await getList()
  279. }
  280. /** 查看审批 */
  281. const handleProcessDetail = (row: ReceivableApi.ReceivableVO) => {
  282. push({ name: 'BpmProcessInstanceDetail', query: { id: row.processInstanceId } })
  283. }
  284. /** 打开回款详情 */
  285. const { push } = useRouter()
  286. const openDetail = (id: number) => {
  287. push({ name: 'CrmReceivableDetail', params: { id } })
  288. }
  289. /** 打开客户详情 */
  290. const openCustomerDetail = (id: number) => {
  291. push({ name: 'CrmCustomerDetail', params: { id } })
  292. }
  293. /** 打开合同详情 */
  294. const openContractDetail = (id: number) => {
  295. push({ name: 'CrmContractDetail', params: { id } })
  296. }
  297. /** 导出按钮操作 */
  298. const handleExport = async () => {
  299. try {
  300. // 导出的二次确认
  301. await message.exportConfirm()
  302. // 发起导出
  303. exportLoading.value = true
  304. const data = await ReceivableApi.exportReceivable(queryParams)
  305. download.excel(data, '回款.xls')
  306. } catch {
  307. } finally {
  308. exportLoading.value = false
  309. }
  310. }
  311. /** 初始化 **/
  312. onMounted(async () => {
  313. await getList()
  314. // 获得客户列表
  315. customerList.value = await CustomerApi.getCustomerSimpleList()
  316. })
  317. </script>