Compare commits
3 Commits
715666b5b6
...
1c432ea890
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c432ea890 | |||
| 04ff2fb4df | |||
| 594324c459 |
@@ -123,8 +123,8 @@ a {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
transition:
|
transition:
|
||||||
opacity 0.22s cubic-bezier(0.4, 0, 0.2, 1),
|
opacity 0.24s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
transform 0.22s cubic-bezier(0.4, 0, 0.2, 1);
|
transform 0.24s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-fade-slide-enter-from {
|
.page-fade-slide-enter-from {
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ export default defineComponent({
|
|||||||
v-slots={{
|
v-slots={{
|
||||||
default: ({ Component, route }: any) => (
|
default: ({ Component, route }: any) => (
|
||||||
<KeepAlive include={cachedViews.value}>
|
<KeepAlive include={cachedViews.value}>
|
||||||
<Transition name="page-fade-slide" mode="out-in">
|
<Transition name="page-fade-slide">
|
||||||
{Component ? h(Component, { key: route.path }) : null}
|
{Component ? h(Component, { key: route.path }) : null}
|
||||||
</Transition>
|
</Transition>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
|
|||||||
@@ -107,12 +107,7 @@ function renderBodyCell({
|
|||||||
<Button type="link" size="small" onClick={() => onEdit(record)}>
|
<Button type="link" size="small" onClick={() => onEdit(record)}>
|
||||||
编辑
|
编辑
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button type="link" size="small" onClick={() => onToggleStatus(record)}>
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
style={isEnabled ? { color: '#faad14' } : { color: '#52c41a' }}
|
|
||||||
onClick={() => onToggleStatus(record)}
|
|
||||||
>
|
|
||||||
{isEnabled ? '禁用' : '启用'}
|
{isEnabled ? '禁用' : '启用'}
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="link" size="small" danger onClick={() => onDelete(record)}>
|
<Button type="link" size="small" danger onClick={() => onDelete(record)}>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { computed, reactive, toRef, Ref, h } from 'vue';
|
import { computed, reactive, toRef, Ref, h } from 'vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { StatusTag, type StatusTagTone } from '@/components';
|
import { StatusTag, type StatusTagTone } from '@/components';
|
||||||
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
||||||
|
|
||||||
@@ -108,6 +109,15 @@ const MOCK_DATA = Array.from({ length: 12 }, (_, i) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 临时排序:对假数据按创建时间倒序排列。
|
||||||
|
* 【注意】实际项目中排序由后端接口负责,对接后端后请删除此函数及相关调用。
|
||||||
|
*/
|
||||||
|
const sortByTimeDesc = (list: any[], field: string) =>
|
||||||
|
[...list].sort((a, b) => dayjs(b[field]).valueOf() - dayjs(a[field]).valueOf());
|
||||||
|
|
||||||
|
const SORTED_MOCK_DATA = sortByTimeDesc(MOCK_DATA, 'createTime');
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Model
|
// Model
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -130,11 +140,11 @@ export function useBannerModel() {
|
|||||||
|
|
||||||
// ===== 表格状态 =====
|
// ===== 表格状态 =====
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [dataSource, setDataSource] = useState<any[]>(MOCK_DATA);
|
const [dataSource, setDataSource] = useState<any[]>(SORTED_MOCK_DATA);
|
||||||
const [pagination, setPagination] = useState({
|
const [pagination, setPagination] = useState({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: MOCK_DATA.length,
|
total: SORTED_MOCK_DATA.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===== 弹窗状态 =====
|
// ===== 弹窗状态 =====
|
||||||
@@ -180,8 +190,8 @@ export function useBannerModel() {
|
|||||||
status: filterForm.status,
|
status: filterForm.status,
|
||||||
});
|
});
|
||||||
// TODO: 替换为真实 API 调用
|
// TODO: 替换为真实 API 调用
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
setPagination({ ...pagination.value, total: MOCK_DATA.length });
|
setPagination({ ...pagination.value, total: SORTED_MOCK_DATA.length });
|
||||||
message.success('查询成功');
|
message.success('查询成功');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
message.error(error.msg || '查询失败');
|
message.error(error.msg || '查询失败');
|
||||||
@@ -194,8 +204,8 @@ export function useBannerModel() {
|
|||||||
const handleReset = useThrottleFn(() => {
|
const handleReset = useThrottleFn(() => {
|
||||||
filterForm.searchTitle = '';
|
filterForm.searchTitle = '';
|
||||||
filterForm.status = '';
|
filterForm.status = '';
|
||||||
setPagination({ current: 1, pageSize: 10, total: MOCK_DATA.length });
|
setPagination({ current: 1, pageSize: 10, total: SORTED_MOCK_DATA.length });
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const handlePageChange = (page: number, pageSize: number) => {
|
const handlePageChange = (page: number, pageSize: number) => {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
.imageGrid {
|
.imageGrid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(5, 1fr);
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ interface EventRegulationModalProps {
|
|||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 规程文字 */
|
/** 规程内容 */
|
||||||
const REGULATION_TEXT = [
|
const REGULATION_TEXT = [
|
||||||
'一、赛事目的:推动羽毛球运动发展,提高运动员技术水平,增进体育文化交流。',
|
'一、赛事目的:推动羽毛球运动发展,提高运动员技术水平,增进体育文化交流。',
|
||||||
'二、参赛资格:凡身体健康、年龄符合要求的羽毛球爱好者均可报名参加。',
|
'二、参赛资格:凡身体健康、年龄符合要求的羽毛球爱好者均可报名参加。',
|
||||||
@@ -35,16 +35,16 @@ export default defineComponent({
|
|||||||
<Modal
|
<Modal
|
||||||
visible={props.visible}
|
visible={props.visible}
|
||||||
title="赛事规程"
|
title="赛事规程"
|
||||||
width={760}
|
width={880}
|
||||||
onCancel={props.onClose}
|
onCancel={props.onClose}
|
||||||
footer={null}
|
footer={null}
|
||||||
centered
|
centered
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
wrapClassName={styles.eventRegulationModalMain}
|
wrapClassName={styles.eventRegulationModalMain}
|
||||||
>
|
>
|
||||||
{/* 规程文字 */}
|
{/* 规程内容 */}
|
||||||
<div class={styles.section}>
|
<div class={styles.section}>
|
||||||
<div class={styles.sectionTitle}>规程文字</div>
|
<div class={styles.sectionTitle}>规程内容</div>
|
||||||
<div class={styles.textBlock}>{REGULATION_TEXT}</div>
|
<div class={styles.textBlock}>{REGULATION_TEXT}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ function renderBodyCell({
|
|||||||
text,
|
text,
|
||||||
record,
|
record,
|
||||||
onView,
|
onView,
|
||||||
|
onViewRegulation,
|
||||||
onAudit,
|
onAudit,
|
||||||
onToggleShelf,
|
onToggleShelf,
|
||||||
}: {
|
}: {
|
||||||
@@ -44,6 +45,7 @@ function renderBodyCell({
|
|||||||
text: any;
|
text: any;
|
||||||
record: any;
|
record: any;
|
||||||
onView: (record: any) => void;
|
onView: (record: any) => void;
|
||||||
|
onViewRegulation: (record: any) => void;
|
||||||
onAudit: (record: any) => void;
|
onAudit: (record: any) => void;
|
||||||
onToggleShelf: (record: any) => void;
|
onToggleShelf: (record: any) => void;
|
||||||
}) {
|
}) {
|
||||||
@@ -62,7 +64,7 @@ function renderBodyCell({
|
|||||||
|
|
||||||
if (column.key === 'regulation') {
|
if (column.key === 'regulation') {
|
||||||
return (
|
return (
|
||||||
<a style={{ cursor: 'pointer' }} onClick={() => onView(record)}>
|
<a style={{ cursor: 'pointer' }} onClick={() => onViewRegulation(record)}>
|
||||||
查看
|
查看
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
@@ -89,7 +91,7 @@ function renderBodyCell({
|
|||||||
<Button type="link" size="small" onClick={() => onView(record)}>
|
<Button type="link" size="small" onClick={() => onView(record)}>
|
||||||
查看
|
查看
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="link" size="small" danger onClick={() => onToggleShelf(record)}>
|
<Button type="link" size="small" onClick={() => onToggleShelf(record)}>
|
||||||
下架
|
下架
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
@@ -100,12 +102,7 @@ function renderBodyCell({
|
|||||||
<Button type="link" size="small" onClick={() => onView(record)}>
|
<Button type="link" size="small" onClick={() => onView(record)}>
|
||||||
查看
|
查看
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button type="link" size="small" onClick={() => onToggleShelf(record)}>
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
style={{ color: '#52c41a' }}
|
|
||||||
onClick={() => onToggleShelf(record)}
|
|
||||||
>
|
|
||||||
上架
|
上架
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
@@ -313,6 +310,7 @@ export default defineComponent({
|
|||||||
renderBodyCell({
|
renderBodyCell({
|
||||||
...args,
|
...args,
|
||||||
onView: handleView,
|
onView: handleView,
|
||||||
|
onViewRegulation: handleViewRegulation,
|
||||||
onAudit: handleAudit,
|
onAudit: handleAudit,
|
||||||
onToggleShelf: handleToggleShelf,
|
onToggleShelf: handleToggleShelf,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { computed, reactive, toRef, Ref, h } from 'vue';
|
import { computed, reactive, toRef, Ref, h } from 'vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { StatusTag, type StatusTagTone } from '@/components';
|
import { StatusTag, type StatusTagTone } from '@/components';
|
||||||
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
||||||
|
|
||||||
@@ -61,12 +62,21 @@ const MOCK_DATA = Array.from({ length: 12 }, (_, i) => ({
|
|||||||
needIdCardImage: i % 2 === 0 ? '是' : '否',
|
needIdCardImage: i % 2 === 0 ? '是' : '否',
|
||||||
creatorNickname: ['张运营', '李管理', '王策划', '赵赛事'][i % 4],
|
creatorNickname: ['张运营', '李管理', '王策划', '赵赛事'][i % 4],
|
||||||
creatorPhone: ['13800138001', '13900139002', '13700137003', '13600136004'][i % 4],
|
creatorPhone: ['13800138001', '13900139002', '13700137003', '13600136004'][i % 4],
|
||||||
createTime: '2026-07-01 14:30:00',
|
createTime: `2026-07-${String((i % 10) + 1).padStart(2, '0')} ${String((i * 3 + 8) % 24).padStart(2, '0')}:${String((i * 17 + 11) % 60).padStart(2, '0')}:${String((i * 13 + 7) % 60).padStart(2, '0')}`,
|
||||||
status: (['pending', 'enrolling', 'deleted', 'removed', 'rejected'] as const)[i % 5],
|
status: (['pending', 'enrolling', 'deleted', 'removed', 'rejected'] as const)[i % 5],
|
||||||
enrolledCount: [128, 256, 512, 64, 0][i % 5],
|
enrolledCount: [128, 256, 512, 64, 0][i % 5],
|
||||||
cancelledCount: [5, 12, 8, 3, 0][i % 5],
|
cancelledCount: [5, 12, 8, 3, 0][i % 5],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 临时排序:对假数据按创建时间倒序排列。
|
||||||
|
* 【注意】实际项目中排序由后端接口负责,对接后端后请删除此函数及相关调用。
|
||||||
|
*/
|
||||||
|
const sortByTimeDesc = (list: any[], field: string) =>
|
||||||
|
[...list].sort((a, b) => dayjs(b[field]).valueOf() - dayjs(a[field]).valueOf());
|
||||||
|
|
||||||
|
const SORTED_MOCK_DATA = sortByTimeDesc(MOCK_DATA, 'createTime');
|
||||||
|
|
||||||
/** 状态标签映射 */
|
/** 状态标签映射 */
|
||||||
const STATUS_MAP: Record<string, { label: string; tone: StatusTagTone }> = {
|
const STATUS_MAP: Record<string, { label: string; tone: StatusTagTone }> = {
|
||||||
pending: { label: '待审核', tone: 'warning' },
|
pending: { label: '待审核', tone: 'warning' },
|
||||||
@@ -109,11 +119,11 @@ export function useEventListModel() {
|
|||||||
|
|
||||||
// ===== 表格状态 =====
|
// ===== 表格状态 =====
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [dataSource, setDataSource] = useState<any[]>(MOCK_DATA);
|
const [dataSource, setDataSource] = useState<any[]>(SORTED_MOCK_DATA);
|
||||||
const [pagination, setPagination] = useState({
|
const [pagination, setPagination] = useState({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: MOCK_DATA.length,
|
total: SORTED_MOCK_DATA.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===== 表格列配置 =====
|
// ===== 表格列配置 =====
|
||||||
@@ -213,8 +223,8 @@ export function useEventListModel() {
|
|||||||
needIdCardImage: filterForm.needIdCardImage,
|
needIdCardImage: filterForm.needIdCardImage,
|
||||||
});
|
});
|
||||||
// TODO: 替换为真实 API 调用
|
// TODO: 替换为真实 API 调用
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
setPagination({ ...pagination.value, total: MOCK_DATA.length });
|
setPagination({ ...pagination.value, total: SORTED_MOCK_DATA.length });
|
||||||
message.success('查询成功');
|
message.success('查询成功');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
message.error(error.msg || '查询失败');
|
message.error(error.msg || '查询失败');
|
||||||
@@ -234,8 +244,8 @@ export function useEventListModel() {
|
|||||||
filterForm.publicEvent = '';
|
filterForm.publicEvent = '';
|
||||||
filterForm.needIdCard = '';
|
filterForm.needIdCard = '';
|
||||||
filterForm.needIdCardImage = '';
|
filterForm.needIdCardImage = '';
|
||||||
setPagination({ current: 1, pageSize: 10, total: MOCK_DATA.length });
|
setPagination({ current: 1, pageSize: 10, total: SORTED_MOCK_DATA.length });
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const handlePageChange = (page: number, pageSize: number) => {
|
const handlePageChange = (page: number, pageSize: number) => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { computed, reactive, toRef, Ref, h } from 'vue';
|
import { computed, reactive, toRef, Ref, h } from 'vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { StatusTag, type StatusTagTone } from '@/components';
|
import { StatusTag, type StatusTagTone } from '@/components';
|
||||||
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
||||||
|
|
||||||
@@ -131,8 +132,8 @@ const MOCK_DATA = Array.from({ length: 12 }, (_, i) => {
|
|||||||
registrant: ['张报名', '李报名', '王报名', '赵报名'][i % 4],
|
registrant: ['张报名', '李报名', '王报名', '赵报名'][i % 4],
|
||||||
registrantPhone: ['13800138001', '13900139002', '13700137003', '13600136004'][i % 4],
|
registrantPhone: ['13800138001', '13900139002', '13700137003', '13600136004'][i % 4],
|
||||||
registrantCount: [1, 2, 1, 3][i % 4],
|
registrantCount: [1, 2, 1, 3][i % 4],
|
||||||
orderTime: '2026-07-15 10:30:00',
|
orderTime: `2026-07-${String((i % 12) + 1).padStart(2, '0')} ${String((i * 2 + 8) % 24).padStart(2, '0')}:${String((i * 13 + 7) % 60).padStart(2, '0')}:${String((i * 11 + 3) % 60).padStart(2, '0')}`,
|
||||||
payTime: '2026-07-15 10:32:15',
|
payTime: `2026-07-${String((i % 12) + 1).padStart(2, '0')} ${String((i * 2 + 8) % 24).padStart(2, '0')}:${String((i * 13 + 9) % 60).padStart(2, '0')}:${String((i * 11 + 5) % 60).padStart(2, '0')}`,
|
||||||
totalAmount,
|
totalAmount,
|
||||||
discountAmount,
|
discountAmount,
|
||||||
paidAmount: totalAmount - discountAmount,
|
paidAmount: totalAmount - discountAmount,
|
||||||
@@ -144,6 +145,15 @@ const MOCK_DATA = Array.from({ length: 12 }, (_, i) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 临时排序:对假数据按订单时间倒序排列。
|
||||||
|
* 【注意】实际项目中排序由后端接口负责,对接后端后请删除此函数及相关调用。
|
||||||
|
*/
|
||||||
|
const sortByTimeDesc = (list: any[], field: string) =>
|
||||||
|
[...list].sort((a, b) => dayjs(b[field]).valueOf() - dayjs(a[field]).valueOf());
|
||||||
|
|
||||||
|
const SORTED_MOCK_DATA = sortByTimeDesc(MOCK_DATA, 'orderTime');
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 金额汇总假数据
|
// 金额汇总假数据
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -188,11 +198,11 @@ export function useOrderModel() {
|
|||||||
|
|
||||||
// ===== 表格状态 =====
|
// ===== 表格状态 =====
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [dataSource, setDataSource] = useState<any[]>(MOCK_DATA);
|
const [dataSource, setDataSource] = useState<any[]>(SORTED_MOCK_DATA);
|
||||||
const [pagination, setPagination] = useState({
|
const [pagination, setPagination] = useState({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: MOCK_DATA.length,
|
total: SORTED_MOCK_DATA.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===== 金额汇总 =====
|
// ===== 金额汇总 =====
|
||||||
@@ -300,8 +310,8 @@ export function useOrderModel() {
|
|||||||
refundStatus: filterForm.refundStatus,
|
refundStatus: filterForm.refundStatus,
|
||||||
});
|
});
|
||||||
// TODO: 替换为真实 API 调用
|
// TODO: 替换为真实 API 调用
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
setPagination({ ...pagination.value, total: MOCK_DATA.length });
|
setPagination({ ...pagination.value, total: SORTED_MOCK_DATA.length });
|
||||||
setSummary(MOCK_SUMMARY);
|
setSummary(MOCK_SUMMARY);
|
||||||
message.success('查询成功');
|
message.success('查询成功');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -319,8 +329,8 @@ export function useOrderModel() {
|
|||||||
filterForm.searchPlayerName = '';
|
filterForm.searchPlayerName = '';
|
||||||
filterForm.orderStatus = '';
|
filterForm.orderStatus = '';
|
||||||
filterForm.refundStatus = '';
|
filterForm.refundStatus = '';
|
||||||
setPagination({ current: 1, pageSize: 10, total: MOCK_DATA.length });
|
setPagination({ current: 1, pageSize: 10, total: SORTED_MOCK_DATA.length });
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
setSummary(MOCK_SUMMARY);
|
setSummary(MOCK_SUMMARY);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ function renderBodyCell({
|
|||||||
if (column.key === 'action') {
|
if (column.key === 'action') {
|
||||||
const isActive = record.status === 'active';
|
const isActive = record.status === 'active';
|
||||||
return (
|
return (
|
||||||
<Button type="link" size="small" danger={isActive} onClick={() => onToggleStatus(record)}>
|
<Button type="link" size="small" onClick={() => onToggleStatus(record)}>
|
||||||
{isActive ? '禁用' : '启用'}
|
{isActive ? '禁用' : '启用'}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { computed, reactive, toRef, Ref, h } from 'vue';
|
import { computed, reactive, toRef, Ref, h } from 'vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { StatusTag, type StatusTagTone } from '@/components';
|
import { StatusTag, type StatusTagTone } from '@/components';
|
||||||
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
||||||
|
|
||||||
@@ -38,9 +39,18 @@ const MOCK_DATA = Array.from({ length: 12 }, (_, i) => ({
|
|||||||
? ['https://picsum.photos/seed/idcard-a/120/80', 'https://picsum.photos/seed/idcard-b/120/80']
|
? ['https://picsum.photos/seed/idcard-a/120/80', 'https://picsum.photos/seed/idcard-b/120/80']
|
||||||
: [],
|
: [],
|
||||||
status: (i % 4 === 3 ? 'disabled' : 'active') as string,
|
status: (i % 4 === 3 ? 'disabled' : 'active') as string,
|
||||||
loginTime: '2026-07-20 14:30:00',
|
loginTime: `2026-07-${String((i % 20) + 1).padStart(2, '0')} ${String((i * 3 + 6) % 24).padStart(2, '0')}:${String((i * 17 + 11) % 60).padStart(2, '0')}:${String((i * 13 + 7) % 60).padStart(2, '0')}`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 临时排序:对假数据按登录时间倒序排列。
|
||||||
|
* 【注意】实际项目中排序由后端接口负责,对接后端后请删除此函数及相关调用。
|
||||||
|
*/
|
||||||
|
const sortByTimeDesc = (list: any[], field: string) =>
|
||||||
|
[...list].sort((a, b) => dayjs(b[field]).valueOf() - dayjs(a[field]).valueOf());
|
||||||
|
|
||||||
|
const SORTED_MOCK_DATA = sortByTimeDesc(MOCK_DATA, 'loginTime');
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Model
|
// Model
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -68,11 +78,11 @@ export function useUserModel() {
|
|||||||
|
|
||||||
// ===== 表格状态 =====
|
// ===== 表格状态 =====
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [dataSource, setDataSource] = useState<any[]>(MOCK_DATA);
|
const [dataSource, setDataSource] = useState<any[]>(SORTED_MOCK_DATA);
|
||||||
const [pagination, setPagination] = useState({
|
const [pagination, setPagination] = useState({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: MOCK_DATA.length,
|
total: SORTED_MOCK_DATA.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===== 表格列配置 =====
|
// ===== 表格列配置 =====
|
||||||
@@ -123,8 +133,8 @@ export function useUserModel() {
|
|||||||
status: filterForm.status,
|
status: filterForm.status,
|
||||||
});
|
});
|
||||||
// TODO: 替换为真实 API 调用
|
// TODO: 替换为真实 API 调用
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
setPagination({ ...pagination.value, total: MOCK_DATA.length });
|
setPagination({ ...pagination.value, total: SORTED_MOCK_DATA.length });
|
||||||
message.success('查询成功');
|
message.success('查询成功');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
message.error(error.msg || '查询失败');
|
message.error(error.msg || '查询失败');
|
||||||
@@ -138,8 +148,8 @@ export function useUserModel() {
|
|||||||
filterForm.searchUserName = '';
|
filterForm.searchUserName = '';
|
||||||
filterForm.searchPhone = '';
|
filterForm.searchPhone = '';
|
||||||
filterForm.status = '';
|
filterForm.status = '';
|
||||||
setPagination({ current: 1, pageSize: 10, total: MOCK_DATA.length });
|
setPagination({ current: 1, pageSize: 10, total: SORTED_MOCK_DATA.length });
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const handlePageChange = (page: number, pageSize: number) => {
|
const handlePageChange = (page: number, pageSize: number) => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { computed, reactive, toRef, Ref, h } from 'vue';
|
import { computed, reactive, toRef, Ref, h } from 'vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { StatusTag, type StatusTagTone } from '@/components';
|
import { StatusTag, type StatusTagTone } from '@/components';
|
||||||
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
||||||
|
|
||||||
@@ -38,6 +39,15 @@ const MOCK_DATA = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 临时排序:对假数据按创建时间倒序排列。
|
||||||
|
* 【注意】实际项目中排序由后端接口负责,对接后端后请删除此函数及相关调用。
|
||||||
|
*/
|
||||||
|
const sortByTimeDesc = (list: any[], field: string) =>
|
||||||
|
[...list].sort((a, b) => dayjs(b[field]).valueOf() - dayjs(a[field]).valueOf());
|
||||||
|
|
||||||
|
const SORTED_MOCK_DATA = sortByTimeDesc(MOCK_DATA, 'createTime');
|
||||||
|
|
||||||
/** 角色下用户列表 mock */
|
/** 角色下用户列表 mock */
|
||||||
const MOCK_USERS: Record<string, any[]> = {
|
const MOCK_USERS: Record<string, any[]> = {
|
||||||
R20250601001: [
|
R20250601001: [
|
||||||
@@ -159,11 +169,11 @@ export function useRoleModel() {
|
|||||||
|
|
||||||
// ===== 表格状态 =====
|
// ===== 表格状态 =====
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [dataSource, setDataSource] = useState<any[]>(MOCK_DATA);
|
const [dataSource, setDataSource] = useState<any[]>(SORTED_MOCK_DATA);
|
||||||
const [pagination, setPagination] = useState({
|
const [pagination, setPagination] = useState({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: MOCK_DATA.length,
|
total: SORTED_MOCK_DATA.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===== 弹窗状态 =====
|
// ===== 弹窗状态 =====
|
||||||
@@ -202,8 +212,8 @@ export function useRoleModel() {
|
|||||||
try {
|
try {
|
||||||
console.log('搜索条件:', { keyword: debouncedKeyword.value });
|
console.log('搜索条件:', { keyword: debouncedKeyword.value });
|
||||||
// TODO: 替换为真实 API 调用
|
// TODO: 替换为真实 API 调用
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
setPagination({ ...pagination.value, total: MOCK_DATA.length });
|
setPagination({ ...pagination.value, total: SORTED_MOCK_DATA.length });
|
||||||
message.success('查询成功');
|
message.success('查询成功');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
message.error(error.msg || '查询失败');
|
message.error(error.msg || '查询失败');
|
||||||
@@ -215,8 +225,8 @@ export function useRoleModel() {
|
|||||||
/** 重置 */
|
/** 重置 */
|
||||||
const handleReset = useThrottleFn(() => {
|
const handleReset = useThrottleFn(() => {
|
||||||
filterForm.searchKeyword = '';
|
filterForm.searchKeyword = '';
|
||||||
setPagination({ current: 1, pageSize: 10, total: MOCK_DATA.length });
|
setPagination({ current: 1, pageSize: 10, total: SORTED_MOCK_DATA.length });
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const handlePageChange = (page: number, pageSize: number) => {
|
const handlePageChange = (page: number, pageSize: number) => {
|
||||||
|
|||||||
@@ -28,13 +28,7 @@ function renderBodyCell({
|
|||||||
<Button type="link" size="small" onClick={() => onEdit(record)}>
|
<Button type="link" size="small" onClick={() => onEdit(record)}>
|
||||||
编辑
|
编辑
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button type="link" size="small" onClick={() => onToggleStatus(record)}>
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
danger={isActive}
|
|
||||||
style={isActive ? {} : { color: '#52c41a' }}
|
|
||||||
onClick={() => onToggleStatus(record)}
|
|
||||||
>
|
|
||||||
{isActive ? '禁用' : '启用'}
|
{isActive ? '禁用' : '启用'}
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { computed, reactive, toRef, Ref, h } from 'vue';
|
import { computed, reactive, toRef, Ref, h } from 'vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { StatusTag, type StatusTagTone } from '@/components';
|
import { StatusTag, type StatusTagTone } from '@/components';
|
||||||
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
import { useState, useDebounce, useThrottleFn } from '@/hooks';
|
||||||
|
|
||||||
@@ -58,6 +59,15 @@ const MOCK_DATA = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 临时排序:对假数据按创建时间倒序排列。
|
||||||
|
* 【注意】实际项目中排序由后端接口负责,对接后端后请删除此函数及相关调用。
|
||||||
|
*/
|
||||||
|
const sortByTimeDesc = (list: any[], field: string) =>
|
||||||
|
[...list].sort((a, b) => dayjs(b[field]).valueOf() - dayjs(a[field]).valueOf());
|
||||||
|
|
||||||
|
const SORTED_MOCK_DATA = sortByTimeDesc(MOCK_DATA, 'createTime');
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Model
|
// Model
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -81,11 +91,11 @@ export function useUserModel() {
|
|||||||
|
|
||||||
// ===== 表格状态 =====
|
// ===== 表格状态 =====
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [dataSource, setDataSource] = useState<any[]>(MOCK_DATA);
|
const [dataSource, setDataSource] = useState<any[]>(SORTED_MOCK_DATA);
|
||||||
const [pagination, setPagination] = useState({
|
const [pagination, setPagination] = useState({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: MOCK_DATA.length,
|
total: SORTED_MOCK_DATA.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===== 弹窗状态 =====
|
// ===== 弹窗状态 =====
|
||||||
@@ -144,8 +154,8 @@ export function useUserModel() {
|
|||||||
status: filterForm.status,
|
status: filterForm.status,
|
||||||
});
|
});
|
||||||
// TODO: 替换为真实 API 调用
|
// TODO: 替换为真实 API 调用
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
setPagination({ ...pagination.value, total: MOCK_DATA.length });
|
setPagination({ ...pagination.value, total: SORTED_MOCK_DATA.length });
|
||||||
message.success('查询成功');
|
message.success('查询成功');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
message.error(error.msg || '查询失败');
|
message.error(error.msg || '查询失败');
|
||||||
@@ -159,8 +169,8 @@ export function useUserModel() {
|
|||||||
filterForm.searchKeyword = '';
|
filterForm.searchKeyword = '';
|
||||||
filterForm.role = '';
|
filterForm.role = '';
|
||||||
filterForm.status = '';
|
filterForm.status = '';
|
||||||
setPagination({ current: 1, pageSize: 10, total: MOCK_DATA.length });
|
setPagination({ current: 1, pageSize: 10, total: SORTED_MOCK_DATA.length });
|
||||||
setDataSource(MOCK_DATA);
|
setDataSource(SORTED_MOCK_DATA);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const handlePageChange = (page: number, pageSize: number) => {
|
const handlePageChange = (page: number, pageSize: number) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user