金币系统前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

515 lines
14 KiB

3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
  1. <template>
  2. <!-- 这是线上充值明细页面 -->
  3. <div class="filter-box">
  4. <el-form :model="detailY" ref="ruleFormRef">
  5. <el-form-item prop="jwcode" >
  6. <el-text class="mx-1" size="large">精网号</el-text>
  7. <el-input
  8. v-model="detailY.jwcode"
  9. placeholder="请输入精网号"
  10. style="width: 220px"
  11. />
  12. </el-form-item>
  13. <el-form-item prop="deptName">
  14. <el-text class="mx-1" size="large">地区</el-text>
  15. <el-select
  16. v-model="detailY.deptName"
  17. placeholder="请选择所属地区"
  18. style="width: 240px"
  19. clearable
  20. >
  21. <el-option
  22. v-for="item in areaList"
  23. :key="item"
  24. :label="item"
  25. :value="item"
  26. />
  27. </el-select>
  28. </el-form-item>
  29. <el-form-item prop="orderNo">
  30. <el-text class="mx-1" size="large">订单号</el-text>
  31. <el-input
  32. v-model="detailY.orderNo"
  33. placeholder="请输入订单号"
  34. style="width: 220px"
  35. />
  36. </el-form-item>
  37. <!-- <el-form-item prop="type" label="充值类型">
  38. <el-input
  39. v-model="detailY.type"
  40. placeholder="请输入充值类型"
  41. style="width: 220px"
  42. />
  43. </el-form-item> -->
  44. <el-form-item prop="payStyle">
  45. <el-text class="mx-1" size="large">充值平台</el-text>
  46. <el-select
  47. v-model="detailY.payStyle"
  48. placeholder="请选择充值平台"
  49. style="width: 240px"
  50. clearable
  51. >
  52. <el-option
  53. v-for="item in platformList"
  54. :key="item"
  55. :label="item"
  56. :value="item"
  57. />
  58. </el-select>
  59. </el-form-item>
  60. <el-form-item prop="createTime">
  61. <el-text class="mx-1" size="large">充值时间</el-text>
  62. <el-date-picker
  63. v-model="detailY.createTime"
  64. type="daterange"
  65. start-placeholder="开始日期"
  66. end-placeholder="结束日期"
  67. style="width: 240px"
  68. format="YYYY-MM-DD HH:mm:ss"
  69. value-format="YYYY-MM-DD HH:mm:ss"
  70. :unlinkPanels="true"
  71. />
  72. </el-form-item>
  73. <el-col :span="10">
  74. <el-form-item>
  75. <el-button type="primary" @click="search">查询</el-button>
  76. <el-button type="success" @click="reset(ruleFormRef)">重置</el-button>
  77. <el-button type="primary" @click="exportExcel">导出excel</el-button>
  78. </el-form-item>
  79. </el-col>
  80. </el-form>
  81. </div>
  82. <div class="table-box">
  83. <div>金豆总数充值金豆总数{{ countValue }}合计金额数{{ priceValue }}</div>
  84. <el-table :data="tableData" style="width: 100%" height="584px">
  85. <el-table-column type="index" label="序号" width="100px" fixed="left">
  86. <template #default="scope">
  87. <span>{{
  88. scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
  89. }}</span>
  90. </template>
  91. </el-table-column>
  92. <el-table-column fixed="left" prop="name" label="姓名" width="150" />
  93. <el-table-column fixed="left" prop="jwcode" label="精网号" width="120" />
  94. <el-table-column prop="deptName" label="地区" width="120" />
  95. <el-table-column prop="orderNo" label="订单号" width="120" />
  96. <el-table-column prop="count" label="金豆数量" width="120">
  97. </el-table-column>
  98. <!-- <el-table-column prop="moneyBuy" label="付费金豆" width="120">
  99. </el-table-column>
  100. <el-table-column prop="moneyFree" label="免费金豆" width="120">
  101. </el-table-column> -->
  102. <el-table-column prop="price" label="金额"></el-table-column>
  103. <!-- <el-table-column prop="type" label="类型"></el-table-column> -->
  104. <el-table-column prop="payStyle" label="充值平台" width="140">
  105. </el-table-column>
  106. <!-- <el-table-column prop="notes" label="备注" width="210"></el-table-column> -->
  107. <el-table-column
  108. prop="successTime"
  109. label="充值时间"
  110. width="210"
  111. show-overflow-tooltip
  112. >
  113. <template #default="scope">
  114. <span>{{
  115. !!scope.row.successTime
  116. ? moment.unix(scope.row.time).format('YYYY-MM-DD HH:mm:ss')
  117. : '-'
  118. }}</span>
  119. </template>
  120. </el-table-column>
  121. </el-table>
  122. <!-- 分页 -->
  123. <div class="pagination">
  124. <el-pagination
  125. background
  126. :page-size="getObj.pageSize"
  127. :page-sizes="[5, 10, 20, 50, 100]"
  128. layout="total, sizes, prev, pager, next, jumper"
  129. :total="total"
  130. @size-change="handlePageSizeChange"
  131. @current-change="handleCurrentChange"
  132. >
  133. </el-pagination>
  134. </div>
  135. </div>
  136. <!-- 这是导出excel的弹窗 -->
  137. <el-dialog
  138. v-model="dialogVisible"
  139. title="请选择导出条件"
  140. width="500"
  141. :close-on-click-modal="false"
  142. @close="
  143. () => {
  144. dialogVisible = false
  145. isExport = false
  146. }
  147. "
  148. >
  149. <template #footer>
  150. <el-form
  151. ref="ruleFormRef"
  152. style="max-width: 600px"
  153. :model="excelData"
  154. :rules="rules"
  155. label-width="auto"
  156. class="demo-ruleForm"
  157. status-icon
  158. >
  159. <el-form-item prop="activityName" label="精网号:">
  160. <el-input
  161. v-model="excelData.jwcode"
  162. placeholder="请输入精网号"
  163. style="width: 220px"
  164. />
  165. </el-form-item>
  166. <el-form-item label="所属地区:"
  167. ><el-select
  168. v-model="excelData.area"
  169. placeholder="请选择所属地区"
  170. style="width: 240px"
  171. clearable
  172. >
  173. <el-option
  174. v-for="item in areaList"
  175. :key="item"
  176. :label="item"
  177. :value="item"
  178. />
  179. </el-select>
  180. </el-form-item>
  181. <el-form-item label="更新时间:">
  182. <el-radio-group v-model="excelData.timegap">
  183. <el-radio value="1">今天</el-radio>
  184. <el-radio value="3">近三天</el-radio>
  185. <el-radio value="7">近一周</el-radio>
  186. <el-radio value="30">近一个月</el-radio>
  187. </el-radio-group>
  188. </el-form-item>
  189. <el-button
  190. type="primary"
  191. size="small"
  192. style="margin-left: 10px"
  193. @click="exportConfirm()"
  194. >确定</el-button
  195. >
  196. </el-form>
  197. </template>
  198. </el-dialog>
  199. </template>
  200. <script setup lang="ts">
  201. import { reactive, ref } from 'vue'
  202. import { FormInstance } from 'element-plus'
  203. import { ElMessage } from 'element-plus'
  204. import moment from 'moment'
  205. import API from '@/util/http'
  206. import { utils, write } from 'xlsx'
  207. import { saveAs } from 'file-saver'
  208. // 充值明细表格
  209. const tableData = ref([])
  210. //分页总条目
  211. const total = ref(100)
  212. const dialogVisible = ref(false)
  213. const excelData = reactive({
  214. jwcode: '',
  215. area: '',
  216. timegap: '',
  217. startTime: '',
  218. endTime: ''
  219. })
  220. const priceValue = ref(0)
  221. const countValue = ref(0)
  222. const areaList = ref<string[]>([])
  223. const isExport = ref<boolean>(false)
  224. const rules = ref({
  225. jwcode: [{ required: true, message: '请输入精网号', trigger: 'blur' }],
  226. area: [{ required: true, message: '请选择所属地区', trigger: 'change' }]
  227. })
  228. const handlePageSizeChange = (val) => {
  229. getObj.value.pageSize = val
  230. getObj.value.pageNum = 1
  231. getInit({})
  232. }
  233. const handleCurrentChange = function (val) {
  234. getObj.value.pageNum = val
  235. getInit({})
  236. }
  237. const platformList = ref<string[]>([
  238. // 'stripe',
  239. // 'ios',
  240. // 'FirstData',
  241. // 'paymentasia',
  242. // 'system',
  243. // '金币系统'
  244. ])
  245. const typeList = ref<string[]>([
  246. '金币换金豆',
  247. '金币换免费金豆',
  248. '赠送金豆',
  249. '购买金豆',
  250. '客服操作'
  251. ])
  252. //搜索表单数据
  253. const detailY = ref({
  254. jwcode: '',
  255. deptName: '',
  256. orderNo: '',
  257. payStyle: '',
  258. type: '',
  259. createTime: ''
  260. })
  261. const getObj = ref({
  262. pageNum: 1,
  263. pageSize: 50
  264. })
  265. const exportExcel = function () {
  266. dialogVisible.value = true
  267. isExport.value = true
  268. }
  269. const exportConfirm = function () {
  270. if (excelData.timegap == '1') {
  271. excelData.startTime = moment().startOf('day').format('YYYY-MM-DD HH:mm:ss')
  272. excelData.endTime = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')
  273. } else if (excelData.timegap == '3') {
  274. excelData.startTime = moment()
  275. .subtract(3, 'days')
  276. .startOf('day')
  277. .format('YYYY-MM-DD HH:mm:ss')
  278. excelData.endTime = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')
  279. } else if (excelData.timegap == '7') {
  280. excelData.startTime = moment()
  281. .subtract(7, 'days')
  282. .startOf('day')
  283. .format('YYYY-MM-DD')
  284. excelData.endTime = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')
  285. } else if (excelData.timegap == '30') {
  286. excelData.startTime = moment()
  287. .subtract(30, 'days')
  288. .startOf('day')
  289. .format('YYYY-MM-DD HH:mm:ss')
  290. excelData.endTime = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')
  291. }
  292. getInit(
  293. {
  294. sortField: '',
  295. sortOrder: ''
  296. },
  297. (data) => {
  298. console.log('导出数据', data)
  299. //导出的数据将字段映射
  300. data = data.map((item) => {
  301. return {
  302. 姓名: item.name,
  303. 精网号: item.jwcode,
  304. 地区: item.deptName,
  305. 订单号: item.orderNo,
  306. 充值平台: item.payStyle,
  307. 金豆数量: item.count,
  308. 充值时间: moment(item.successTime).format('YYYY-MM-DD'),
  309. 金额: item.price
  310. }
  311. })
  312. if (data.length == 0) {
  313. ElMessage.error('没有数据')
  314. isExport.value = false
  315. dialogVisible.value = false
  316. return
  317. }
  318. console.log('导出数据', data)
  319. excelExport(data)
  320. }
  321. )
  322. }
  323. //数据导出excel
  324. const excelExport = async function (data) {
  325. const worksheet = utils.json_to_sheet(data)
  326. const workbook = utils.book_new()
  327. utils.book_append_sheet(workbook, worksheet, 'Sheet1')
  328. const wbout = write(workbook, { bookType: 'xlsx', type: 'array' })
  329. saveAs(
  330. new Blob([wbout], { type: 'application/octet-stream' }),
  331. '数据导出.xlsx'
  332. )
  333. isExport.value = false
  334. dialogVisible.value = false
  335. }
  336. const ruleFormRef = ref<FormInstance>()
  337. //初始化
  338. const getInit = async function (
  339. {
  340. sortField = '',
  341. sortOrder = ''
  342. }: {
  343. sortField?: string
  344. sortOrder?: string
  345. },
  346. callback?: Function
  347. ) {
  348. try {
  349. console.log('搜索参数', getObj.value)
  350. const [startTime, endTime] = detailY.value.createTime
  351. console.log(startTime, endTime)
  352. // 发送POST请求
  353. const result = await API({
  354. url: '/dou/SearchPay',
  355. data: {
  356. pay: {
  357. jwcode: isExport.value ? excelData.jwcode : detailY.value.jwcode,
  358. deptName: isExport.value ? excelData.area : detailY.value.deptName,
  359. startTime: isExport.value ? excelData.startTime : startTime || '',
  360. endTime: isExport.value ? excelData.endTime : endTime || '',
  361. payStyle: isExport.value ? '' : detailY.value.payStyle,
  362. // type: isExport.value ? '' : detailY.value.type,
  363. orderNo: isExport.value ? '' : detailY.value.orderNo,
  364. sortField,
  365. sortOrder
  366. },
  367. pageNum: isExport.value ? '' : getObj.value.pageNum,
  368. pageSize: isExport.value ? '' : getObj.value.pageSize
  369. }
  370. })
  371. if (isExport.value) {
  372. !!callback && callback(result.data)
  373. } else {
  374. tableData.value = result.data.list
  375. total.value = result.data.total
  376. }
  377. } catch (error) {
  378. console.log('请求失败', error)
  379. // 在这里可以处理错误逻辑,比如显示错误提示等
  380. }
  381. }
  382. // const handleSortChange = (column) => {
  383. // const { prop, order } = column
  384. // if (order === 'ascending') {
  385. // getInit({ sortField: prop, sortOrder: 'ASC' })
  386. // } else if (order === 'descending') {
  387. // getInit({ sortField: prop, sortOrder: 'DESC' })
  388. // }
  389. // }
  390. // 精网号、订单号去空格
  391. const trimJwCode = () => {
  392. if (detailY.value.jwcode) {
  393. detailY.value.jwcode = detailY.value.jwcode.replace(/\s/g, '');
  394. }
  395. if (detailY.value.orderNo) {
  396. detailY.value.orderNo = detailY.value.orderNo.replace(/\s/g, '');
  397. }
  398. }
  399. // 搜索
  400. const search = function () {
  401. trimJwCode();
  402. getObj.value.pageNum = 1
  403. getInit({})
  404. getCount()
  405. }
  406. // 重置
  407. const reset = function (formEl) {
  408. formEl.resetFields()
  409. }
  410. //充值平台接口
  411. const getPayPlatform = async () => {
  412. try {
  413. const result = await API({
  414. url: '/dou/SearchStyle'
  415. })
  416. platformList.value = result.data
  417. } catch (error) {
  418. console.log('请求失败', error)
  419. }
  420. }
  421. //获取地区接口
  422. const getArea = async () => {
  423. try {
  424. const result = await API({
  425. url: '/dou/SearchPayIp'
  426. })
  427. areaList.value = result.data
  428. } catch (error) {
  429. console.log('请求失败', error)
  430. }
  431. }
  432. //获取支付方式接口
  433. const getPayType = async () => {
  434. try {
  435. const result = await API({
  436. url: '/dou/getStyle'
  437. })
  438. platformList.value = result.data
  439. // typeList.value = result.data
  440. } catch (error) {
  441. console.log('请求失败', error)
  442. }
  443. }
  444. //获取金豆数接口
  445. const getCount = async () => {
  446. try {
  447. const result = await API({
  448. url: '/dou/getRechargeTotal',
  449. data: {
  450. jwcode: detailY.value.jwcode,
  451. deptName: detailY.value.deptName,
  452. startTime: detailY.value.createTime[0],
  453. endTime: detailY.value.createTime[1],
  454. orderNo: detailY.value.orderNo,
  455. payStyle: detailY.value.payStyle
  456. }
  457. })
  458. if (!!result.data) {
  459. console.log('合计数', result.data)
  460. const { priceTotal, countTotal } = result.data
  461. console.log('金豆总数', priceTotal, countTotal)
  462. priceValue.value = priceTotal
  463. countValue.value = countTotal
  464. } else {
  465. priceValue.value = 0
  466. countValue.value = 0
  467. }
  468. } catch (error) {
  469. console.log('请求失败', error)
  470. }
  471. }
  472. getInit({})
  473. getArea()
  474. getPayType()
  475. getCount()
  476. getPayPlatform()
  477. </script>
  478. <style scoped lang="scss">
  479. .filter-box {
  480. width: 100%;
  481. display: flex;
  482. justify-content: space-between;
  483. align-items: center;
  484. padding: 20px;
  485. padding-bottom: 0px;
  486. box-sizing: border-box;
  487. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  488. margin-bottom: 20px;
  489. border-radius: 5px;
  490. .el-form {
  491. display: flex;
  492. flex-wrap: wrap;
  493. row-gap: 20px;
  494. column-gap: 20px;
  495. }
  496. }
  497. .table-box {
  498. width: 100%;
  499. padding: 20px;
  500. box-sizing: border-box;
  501. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  502. border-radius: 5px;
  503. }
  504. .pagination {
  505. display: flex;
  506. align-items: center;
  507. margin-top: 10px;
  508. }
  509. </style>