reconciled.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <template>
  2. <div class="reconciled">
  3. <!-- 头部 -->
  4. <div class="header">
  5. <el-button class="back-btn" @click="goBack"> 返回 </el-button>
  6. <h2 class="title">已到账期金额</h2>
  7. </div>
  8. <div class="table-box">
  9. <ProTable
  10. ref="proTable"
  11. :columns="columns"
  12. :request-api="getTableList"
  13. :init-param="initParam"
  14. :data-callback="dataCallback"
  15. :pagination="true"
  16. :height="tableHeight"
  17. >
  18. <!-- 表格操作 -->
  19. <template #operation="scope">
  20. <el-button type="primary" link @click="toDetail(scope.row)"> 查看详情 </el-button>
  21. </template>
  22. </ProTable>
  23. <el-dialog v-model="dialogVisible" title="详情" width="500px">
  24. <h3 class="orderInfo">
  25. {{ reconciled.couponName }}
  26. </h3>
  27. <el-row class="couponRow">
  28. <el-col :span="12"> 实际收益: &yen;{{ formatNumber(reconciled.money / 100) }} </el-col>
  29. <el-col :span="12">
  30. <!-- {{ `技术服务费(${unposted.commission / 100 || 3}%)` }}: 后续后端会变成可控的-->
  31. {{ `技术服务费(${commissionRate}%):` }}
  32. {{ formatNumber(reconciled.commission / 100) }}
  33. </el-col>
  34. </el-row>
  35. <el-row class="couponRow">
  36. <el-col :span="12"> 售价: &yen;{{ formatNumber(reconciled.orderPrice) }} </el-col>
  37. </el-row>
  38. <h3 class="orderInfo">订单信息</h3>
  39. <div>
  40. <div class="couponRow">下单时间: {{ reconciled.orderTime != null ? reconciled.orderTime : "--" }}</div>
  41. <div class="couponRow">验券时间: {{ reconciled.checkTime != null ? reconciled.checkTime : "--" }}</div>
  42. <div class="couponRow">入账时间: {{ reconciled.createdTime != null ? reconciled.createdTime : "--" }}</div>
  43. </div>
  44. </el-dialog>
  45. </div>
  46. </div>
  47. </template>
  48. <script setup lang="tsx" name="voucherManagement">
  49. import { onActivated, onMounted, reactive, ref } from "vue";
  50. import ProTable from "@/components/ProTable/index.vue";
  51. import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
  52. import { getPaymentCycle } from "@/api/modules/homeEntry";
  53. import { localGet } from "@/utils";
  54. import { useRouter } from "vue-router";
  55. const commissionRate = localGet("commissionRate") || "";
  56. const router = useRouter();
  57. const dialogVisible = ref(false);
  58. const reconciled = ref<any>({});
  59. // 计算表格高度
  60. const tableHeight = ref<string>("calc(100vh - 200px)");
  61. // 返回
  62. const goBack = () => {
  63. router.back();
  64. };
  65. const toDetail = (row: any) => {
  66. dialogVisible.value = true;
  67. reconciled.value = row;
  68. };
  69. // 格式化数字为千分位
  70. const formatNumber = (value: any): string => {
  71. if (value === null || value === undefined || value === "") {
  72. return "0.00";
  73. }
  74. const num = typeof value === "string" ? parseFloat(value) : Number(value);
  75. if (isNaN(num)) {
  76. return "0.00";
  77. }
  78. // 保留两位小数并添加千分位
  79. return num.toLocaleString("zh-CN", {
  80. minimumFractionDigits: 2,
  81. maximumFractionDigits: 2
  82. });
  83. };
  84. // ProTable 实例(需要在使用它的地方之前定义)
  85. const proTable = ref<ProTableInstance>();
  86. // 表格配置项
  87. const columns = reactive<ColumnProps<any>[]>([
  88. {
  89. prop: "couponName",
  90. label: "商品名称"
  91. },
  92. {
  93. prop: "createdTime",
  94. label: "入账时间",
  95. search: {
  96. el: "date-picker",
  97. props: {
  98. type: "daterange",
  99. "range-separator": " - ",
  100. "start-placeholder": "开始日期",
  101. "end-placeholder": "结束日期"
  102. }
  103. }
  104. },
  105. { prop: "operation", label: "操作", fixed: "right", width: 330 }
  106. ]);
  107. // 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
  108. const initParam = reactive({
  109. storeId: localGet("createdId"),
  110. incomeType: 0,
  111. paymentType: 1,
  112. startTime: null,
  113. endTime: null
  114. });
  115. // 页面加载时触发查询
  116. onMounted(async () => {
  117. proTable.value?.getTableList();
  118. });
  119. // 从其他页面返回时触发查询
  120. onActivated(() => {
  121. proTable.value?.getTableList();
  122. });
  123. // dataCallback 是对于返回的表格数据做处理,如果你后台返回的数据不是 list && total 这些字段,可以在这里进行处理成这些字段
  124. // 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行
  125. const dataCallback = (data: any) => {
  126. return {
  127. list: data.data?.records || data.records || [],
  128. total: data.data?.total || data.total || 0
  129. };
  130. };
  131. // 格式化日期为 yyyy-mm-dd
  132. const formatDate = (date: string | Date) => {
  133. const d = new Date(date);
  134. const year = d.getFullYear();
  135. const month = String(d.getMonth() + 1).padStart(2, "0");
  136. const day = String(d.getDate()).padStart(2, "0");
  137. return `${year}-${month}-${day}`;
  138. };
  139. // 如果你想在请求之前对当前请求参数做一些操作,可以自定义如下函数:params 为当前所有的请求参数(包括分页),最后返回请求列表接口
  140. // 默认不做操作就直接在 ProTable 组件上绑定 :requestApi="getUserList"
  141. const getTableList = (params: any) => {
  142. let newParams = JSON.parse(JSON.stringify(params));
  143. // 处理 createdTime 参数,转换为 startTime 和 endTime
  144. if (newParams.createdTime && Array.isArray(newParams.createdTime) && newParams.createdTime.length === 2) {
  145. newParams.startTime = formatDate(newParams.createdTime[0]);
  146. newParams.endTime = formatDate(newParams.createdTime[1]);
  147. delete newParams.createdTime;
  148. } else {
  149. // 如果没有选择日期范围,清空 startTime 和 endTime
  150. newParams.startTime = null;
  151. newParams.endTime = null;
  152. }
  153. return getPaymentCycle(newParams);
  154. };
  155. </script>
  156. <style lang="scss" scoped>
  157. .reconciled {
  158. display: flex;
  159. flex-direction: column;
  160. height: 100%;
  161. overflow: hidden;
  162. }
  163. .table-box {
  164. display: flex;
  165. flex: 1;
  166. flex-direction: column;
  167. overflow: hidden;
  168. :deep(.table-main) {
  169. display: flex;
  170. flex: 1;
  171. flex-direction: column;
  172. overflow: hidden;
  173. .el-table {
  174. flex: 1;
  175. overflow: hidden;
  176. }
  177. .el-table__body-wrapper {
  178. overflow-y: auto !important;
  179. }
  180. }
  181. }
  182. .header {
  183. position: relative;
  184. display: flex;
  185. align-items: center;
  186. padding: 15px;
  187. background: #ffffff;
  188. border-radius: 5px;
  189. box-shadow: 0 0 12px rgb(0 0 0 / 5%);
  190. .back-btn {
  191. padding: 8px 16px;
  192. font-size: 14px;
  193. color: #606266;
  194. background-color: #f5f7fa;
  195. border: 1px solid #dcdfe6;
  196. border-radius: 4px;
  197. &:hover {
  198. color: #409eff;
  199. background-color: #ecf5ff;
  200. border-color: #b3d8ff;
  201. }
  202. }
  203. .title {
  204. position: absolute;
  205. left: 50%;
  206. margin: 0;
  207. font-size: 18px;
  208. font-weight: bold;
  209. color: #333333;
  210. transform: translateX(-50%);
  211. }
  212. }
  213. .orderInfo {
  214. padding-bottom: 20px;
  215. font-size: 18px;
  216. font-weight: bold;
  217. }
  218. .couponRow {
  219. padding-bottom: 20px;
  220. }
  221. .couponRow:last-child {
  222. padding-bottom: 0;
  223. }
  224. // 在组件样式中添加
  225. .date-range {
  226. display: block; // 确保换行生效
  227. padding: 0 8px; // 可选:增加内边距
  228. word-wrap: break-word; // 长单词内换行
  229. white-space: normal; // 允许自然换行
  230. }
  231. .table-header-btn {
  232. .button {
  233. margin-bottom: 10px;
  234. }
  235. .tabs {
  236. :deep(.el-tabs__nav-wrap::after) {
  237. height: 0;
  238. }
  239. }
  240. }
  241. .reject-reason-content {
  242. padding: 20px 0;
  243. .reject-reason-item {
  244. display: flex;
  245. margin-bottom: 20px;
  246. &:last-child {
  247. margin-bottom: 0;
  248. }
  249. .reject-reason-label {
  250. flex-shrink: 0;
  251. min-width: 100px;
  252. font-size: 14px;
  253. font-weight: 500;
  254. color: #606266;
  255. }
  256. .reject-reason-value {
  257. flex: 1;
  258. font-size: 14px;
  259. color: #303133;
  260. word-break: break-word;
  261. &.reject-reason-text {
  262. min-height: 80px;
  263. padding: 12px;
  264. line-height: 1.6;
  265. white-space: pre-wrap;
  266. background-color: #f5f7fa;
  267. border-radius: 4px;
  268. }
  269. }
  270. }
  271. }
  272. </style>