|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { useState, useEffect } from 'react'; |
|
|
import { API, showError, showSuccess, copy } from '../../helpers'; |
|
|
import { ITEMS_PER_PAGE } from '../../constants'; |
|
|
import { |
|
|
REDEMPTION_ACTIONS, |
|
|
REDEMPTION_STATUS, |
|
|
} from '../../constants/redemption.constants'; |
|
|
import { Modal } from '@douyinfe/semi-ui'; |
|
|
import { useTranslation } from 'react-i18next'; |
|
|
import { useTableCompactMode } from '../common/useTableCompactMode'; |
|
|
|
|
|
export const useRedemptionsData = () => { |
|
|
const { t } = useTranslation(); |
|
|
|
|
|
|
|
|
const [redemptions, setRedemptions] = useState([]); |
|
|
const [loading, setLoading] = useState(true); |
|
|
const [searching, setSearching] = useState(false); |
|
|
const [activePage, setActivePage] = useState(1); |
|
|
const [pageSize, setPageSize] = useState(ITEMS_PER_PAGE); |
|
|
const [tokenCount, setTokenCount] = useState(0); |
|
|
const [selectedKeys, setSelectedKeys] = useState([]); |
|
|
|
|
|
|
|
|
const [editingRedemption, setEditingRedemption] = useState({ |
|
|
id: undefined, |
|
|
}); |
|
|
const [showEdit, setShowEdit] = useState(false); |
|
|
|
|
|
|
|
|
const [formApi, setFormApi] = useState(null); |
|
|
|
|
|
|
|
|
const [compactMode, setCompactMode] = useTableCompactMode('redemptions'); |
|
|
|
|
|
|
|
|
const formInitValues = { |
|
|
searchKeyword: '', |
|
|
}; |
|
|
|
|
|
|
|
|
const getFormValues = () => { |
|
|
const formValues = formApi ? formApi.getValues() : {}; |
|
|
return { |
|
|
searchKeyword: formValues.searchKeyword || '', |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const setRedemptionFormat = (redemptions) => { |
|
|
setRedemptions(redemptions); |
|
|
}; |
|
|
|
|
|
|
|
|
const loadRedemptions = async (page = 1, pageSize) => { |
|
|
setLoading(true); |
|
|
try { |
|
|
const res = await API.get( |
|
|
`/api/redemption/?p=${page}&page_size=${pageSize}`, |
|
|
); |
|
|
const { success, message, data } = res.data; |
|
|
if (success) { |
|
|
const newPageData = data.items; |
|
|
setActivePage(data.page <= 0 ? 1 : data.page); |
|
|
setTokenCount(data.total); |
|
|
setRedemptionFormat(newPageData); |
|
|
} else { |
|
|
showError(message); |
|
|
} |
|
|
} catch (error) { |
|
|
showError(error.message); |
|
|
} |
|
|
setLoading(false); |
|
|
}; |
|
|
|
|
|
|
|
|
const searchRedemptions = async () => { |
|
|
const { searchKeyword } = getFormValues(); |
|
|
if (searchKeyword === '') { |
|
|
await loadRedemptions(1, pageSize); |
|
|
return; |
|
|
} |
|
|
|
|
|
setSearching(true); |
|
|
try { |
|
|
const res = await API.get( |
|
|
`/api/redemption/search?keyword=${searchKeyword}&p=1&page_size=${pageSize}`, |
|
|
); |
|
|
const { success, message, data } = res.data; |
|
|
if (success) { |
|
|
const newPageData = data.items; |
|
|
setActivePage(data.page || 1); |
|
|
setTokenCount(data.total); |
|
|
setRedemptionFormat(newPageData); |
|
|
} else { |
|
|
showError(message); |
|
|
} |
|
|
} catch (error) { |
|
|
showError(error.message); |
|
|
} |
|
|
setSearching(false); |
|
|
}; |
|
|
|
|
|
|
|
|
const manageRedemption = async (id, action, record) => { |
|
|
setLoading(true); |
|
|
let data = { id }; |
|
|
let res; |
|
|
|
|
|
try { |
|
|
switch (action) { |
|
|
case REDEMPTION_ACTIONS.DELETE: |
|
|
res = await API.delete(`/api/redemption/${id}/`); |
|
|
break; |
|
|
case REDEMPTION_ACTIONS.ENABLE: |
|
|
data.status = REDEMPTION_STATUS.UNUSED; |
|
|
res = await API.put('/api/redemption/?status_only=true', data); |
|
|
break; |
|
|
case REDEMPTION_ACTIONS.DISABLE: |
|
|
data.status = REDEMPTION_STATUS.DISABLED; |
|
|
res = await API.put('/api/redemption/?status_only=true', data); |
|
|
break; |
|
|
default: |
|
|
throw new Error('Unknown operation type'); |
|
|
} |
|
|
|
|
|
const { success, message } = res.data; |
|
|
if (success) { |
|
|
showSuccess('操作成功完成!'); |
|
|
let redemption = res.data.data; |
|
|
let newRedemptions = [...redemptions]; |
|
|
if (action !== REDEMPTION_ACTIONS.DELETE) { |
|
|
record.status = redemption.status; |
|
|
} |
|
|
setRedemptions(newRedemptions); |
|
|
} else { |
|
|
showError(message); |
|
|
} |
|
|
} catch (error) { |
|
|
showError(error.message); |
|
|
} |
|
|
setLoading(false); |
|
|
}; |
|
|
|
|
|
|
|
|
const refresh = async (page = activePage) => { |
|
|
const { searchKeyword } = getFormValues(); |
|
|
if (searchKeyword === '') { |
|
|
await loadRedemptions(page, pageSize); |
|
|
} else { |
|
|
await searchRedemptions(); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const handlePageChange = (page) => { |
|
|
setActivePage(page); |
|
|
const { searchKeyword } = getFormValues(); |
|
|
if (searchKeyword === '') { |
|
|
loadRedemptions(page, pageSize); |
|
|
} else { |
|
|
searchRedemptions(); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const handlePageSizeChange = (size) => { |
|
|
setPageSize(size); |
|
|
setActivePage(1); |
|
|
const { searchKeyword } = getFormValues(); |
|
|
if (searchKeyword === '') { |
|
|
loadRedemptions(1, size); |
|
|
} else { |
|
|
searchRedemptions(); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const rowSelection = { |
|
|
onSelect: (record, selected) => {}, |
|
|
onSelectAll: (selected, selectedRows) => {}, |
|
|
onChange: (selectedRowKeys, selectedRows) => { |
|
|
setSelectedKeys(selectedRows); |
|
|
}, |
|
|
}; |
|
|
|
|
|
|
|
|
const handleRow = (record, index) => { |
|
|
|
|
|
const isExpired = (rec) => { |
|
|
return ( |
|
|
rec.status === REDEMPTION_STATUS.UNUSED && |
|
|
rec.expired_time !== 0 && |
|
|
rec.expired_time < Math.floor(Date.now() / 1000) |
|
|
); |
|
|
}; |
|
|
|
|
|
if (record.status !== REDEMPTION_STATUS.UNUSED || isExpired(record)) { |
|
|
return { |
|
|
style: { |
|
|
background: 'var(--semi-color-disabled-border)', |
|
|
}, |
|
|
}; |
|
|
} else { |
|
|
return {}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const copyText = async (text) => { |
|
|
if (await copy(text)) { |
|
|
showSuccess('已复制到剪贴板!'); |
|
|
} else { |
|
|
Modal.error({ |
|
|
title: '无法复制到剪贴板,请手动复制', |
|
|
content: text, |
|
|
size: 'large', |
|
|
}); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const batchCopyRedemptions = async () => { |
|
|
if (selectedKeys.length === 0) { |
|
|
showError(t('请至少选择一个兑换码!')); |
|
|
return; |
|
|
} |
|
|
|
|
|
let keys = ''; |
|
|
for (let i = 0; i < selectedKeys.length; i++) { |
|
|
keys += selectedKeys[i].name + ' ' + selectedKeys[i].key + '\n'; |
|
|
} |
|
|
await copyText(keys); |
|
|
}; |
|
|
|
|
|
|
|
|
const batchDeleteRedemptions = async () => { |
|
|
Modal.confirm({ |
|
|
title: t('确定清除所有失效兑换码?'), |
|
|
content: t('将删除已使用、已禁用及过期的兑换码,此操作不可撤销。'), |
|
|
onOk: async () => { |
|
|
setLoading(true); |
|
|
const res = await API.delete('/api/redemption/invalid'); |
|
|
const { success, message, data } = res.data; |
|
|
if (success) { |
|
|
showSuccess(t('已删除 {{count}} 条失效兑换码', { count: data })); |
|
|
await refresh(); |
|
|
} else { |
|
|
showError(message); |
|
|
} |
|
|
setLoading(false); |
|
|
}, |
|
|
}); |
|
|
}; |
|
|
|
|
|
|
|
|
const closeEdit = () => { |
|
|
setShowEdit(false); |
|
|
setTimeout(() => { |
|
|
setEditingRedemption({ |
|
|
id: undefined, |
|
|
}); |
|
|
}, 500); |
|
|
}; |
|
|
|
|
|
|
|
|
const removeRecord = (key) => { |
|
|
let newDataSource = [...redemptions]; |
|
|
if (key != null) { |
|
|
let idx = newDataSource.findIndex((data) => data.key === key); |
|
|
if (idx > -1) { |
|
|
newDataSource.splice(idx, 1); |
|
|
setRedemptions(newDataSource); |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
loadRedemptions(1, pageSize) |
|
|
.then() |
|
|
.catch((reason) => { |
|
|
showError(reason); |
|
|
}); |
|
|
}, [pageSize]); |
|
|
|
|
|
return { |
|
|
|
|
|
redemptions, |
|
|
loading, |
|
|
searching, |
|
|
activePage, |
|
|
pageSize, |
|
|
tokenCount, |
|
|
selectedKeys, |
|
|
|
|
|
|
|
|
editingRedemption, |
|
|
showEdit, |
|
|
|
|
|
|
|
|
formApi, |
|
|
formInitValues, |
|
|
|
|
|
|
|
|
compactMode, |
|
|
setCompactMode, |
|
|
|
|
|
|
|
|
loadRedemptions, |
|
|
searchRedemptions, |
|
|
manageRedemption, |
|
|
refresh, |
|
|
copyText, |
|
|
removeRecord, |
|
|
|
|
|
|
|
|
setActivePage, |
|
|
setPageSize, |
|
|
setSelectedKeys, |
|
|
setEditingRedemption, |
|
|
setShowEdit, |
|
|
setFormApi, |
|
|
setLoading, |
|
|
|
|
|
|
|
|
handlePageChange, |
|
|
handlePageSizeChange, |
|
|
rowSelection, |
|
|
handleRow, |
|
|
closeEdit, |
|
|
getFormValues, |
|
|
|
|
|
|
|
|
batchCopyRedemptions, |
|
|
batchDeleteRedemptions, |
|
|
|
|
|
|
|
|
t, |
|
|
}; |
|
|
}; |
|
|
|