Export.jsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { useState } from 'react'
  2. import { Card, Row, Col, DatePicker, Button, Space, message, Divider, Alert } from 'antd'
  3. import { DownloadOutlined, FileExcelOutlined } from '@ant-design/icons'
  4. import dayjs from 'dayjs'
  5. import { exportApi } from '../services/api'
  6. function Export() {
  7. const [monthValue, setMonthValue] = useState(dayjs())
  8. const [yearValue, setYearValue] = useState(dayjs())
  9. const [monthlyLoading, setMonthlyLoading] = useState(false)
  10. const [yearlyLoading, setYearlyLoading] = useState(false)
  11. const [error, setError] = useState(null)
  12. // Download file helper
  13. const downloadFile = (blob, filename) => {
  14. const url = window.URL.createObjectURL(blob)
  15. const link = document.createElement('a')
  16. link.href = url
  17. link.download = filename
  18. document.body.appendChild(link)
  19. link.click()
  20. document.body.removeChild(link)
  21. window.URL.revokeObjectURL(url)
  22. }
  23. // Generate export timestamp for filename (YYMMDDHHmm format)
  24. const getExportTimestamp = () => {
  25. const now = dayjs()
  26. return now.format('YYMMDDHHmm')
  27. }
  28. // Handle monthly export
  29. const handleMonthlyExport = async () => {
  30. if (!monthValue) {
  31. message.warning('请选择月份')
  32. return
  33. }
  34. setMonthlyLoading(true)
  35. setError(null)
  36. try {
  37. const year = monthValue.year()
  38. const month = monthValue.month() + 1
  39. const response = await exportApi.monthly(year, month)
  40. const timestamp = getExportTimestamp()
  41. const filename = `work_report_${year}-${String(month).padStart(2, '0')}_${timestamp}.xlsx`
  42. downloadFile(response.data, filename)
  43. message.success('月度报表导出成功')
  44. } catch (error) {
  45. const errorMsg = '导出失败: ' + (error.message || '未知错误')
  46. setError(errorMsg)
  47. message.error(errorMsg)
  48. } finally {
  49. setMonthlyLoading(false)
  50. }
  51. }
  52. // Handle yearly export
  53. const handleYearlyExport = async () => {
  54. if (!yearValue) {
  55. message.warning('请选择年份')
  56. return
  57. }
  58. setYearlyLoading(true)
  59. setError(null)
  60. try {
  61. const year = yearValue.year()
  62. const response = await exportApi.yearly(year)
  63. const timestamp = getExportTimestamp()
  64. const filename = `work_report_${year}_${timestamp}.xlsx`
  65. downloadFile(response.data, filename)
  66. message.success('年度报表导出成功')
  67. } catch (error) {
  68. const errorMsg = '导出失败: ' + (error.message || '未知错误')
  69. setError(errorMsg)
  70. message.error(errorMsg)
  71. } finally {
  72. setYearlyLoading(false)
  73. }
  74. }
  75. return (
  76. <div>
  77. {error && (
  78. <Alert
  79. message="导出错误"
  80. description={error}
  81. type="error"
  82. showIcon
  83. closable
  84. style={{ marginBottom: 16 }}
  85. onClose={() => setError(null)}
  86. />
  87. )}
  88. <Row gutter={[24, 24]}>
  89. <Col xs={24} md={12}>
  90. <Card
  91. title={
  92. <Space>
  93. <FileExcelOutlined style={{ color: '#52c41a' }} />
  94. 月度报表导出
  95. </Space>
  96. }
  97. >
  98. <p style={{ color: '#666', marginBottom: 16 }}>
  99. 导出指定月份的工作记录明细和汇总统计
  100. </p>
  101. <Space direction="vertical" size="middle" style={{ width: '100%' }}>
  102. <div>
  103. <span style={{ marginRight: 8 }}>选择月份:</span>
  104. <DatePicker
  105. picker="month"
  106. value={monthValue}
  107. onChange={setMonthValue}
  108. allowClear={false}
  109. style={{ width: 200 }}
  110. placeholder="选择月份"
  111. format="YYYY-MM"
  112. />
  113. </div>
  114. <Button
  115. type="primary"
  116. icon={<DownloadOutlined />}
  117. onClick={handleMonthlyExport}
  118. loading={monthlyLoading}
  119. block
  120. >
  121. 导出月度报表
  122. </Button>
  123. </Space>
  124. </Card>
  125. </Col>
  126. <Col xs={24} md={12}>
  127. <Card
  128. title={
  129. <Space>
  130. <FileExcelOutlined style={{ color: '#1890ff' }} />
  131. 年度报表导出
  132. </Space>
  133. }
  134. >
  135. <p style={{ color: '#666', marginBottom: 16 }}>
  136. 导出指定年份的工作记录明细和按月汇总统计
  137. </p>
  138. <Space direction="vertical" size="middle" style={{ width: '100%' }}>
  139. <div>
  140. <span style={{ marginRight: 8 }}>选择年份:</span>
  141. <DatePicker
  142. picker="year"
  143. value={yearValue}
  144. onChange={setYearValue}
  145. allowClear={false}
  146. style={{ width: 200 }}
  147. placeholder="选择年份"
  148. />
  149. </div>
  150. <Button
  151. type="primary"
  152. icon={<DownloadOutlined />}
  153. onClick={handleYearlyExport}
  154. loading={yearlyLoading}
  155. block
  156. >
  157. 导出年度报表
  158. </Button>
  159. </Space>
  160. </Card>
  161. </Col>
  162. </Row>
  163. <Divider />
  164. <Card title="报表说明" size="small">
  165. <Row gutter={[16, 16]}>
  166. <Col xs={24} md={12}>
  167. <h4>月度报表包含:</h4>
  168. <ul style={{ paddingLeft: 20, color: '#666' }}>
  169. <li>明细表: 人员、日期、物品、单价、数量、总价</li>
  170. <li>月度汇总: 每人总金额及合计</li>
  171. </ul>
  172. </Col>
  173. <Col xs={24} md={12}>
  174. <h4>年度报表包含:</h4>
  175. <ul style={{ paddingLeft: 20, color: '#666' }}>
  176. <li>明细表: 人员、日期、物品、单价、数量、总价</li>
  177. <li>年度汇总: 每人按月统计及年度合计</li>
  178. </ul>
  179. </Col>
  180. </Row>
  181. </Card>
  182. </div>
  183. )
  184. }
  185. export default Export