whistle.mock-plugins 1.2.1-beta.6 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -171,3 +171,5 @@
171
171
  /**![setting](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIGZpbGw9IiNjYWNhY2EiIHZpZXdCb3g9IjY0IDY0IDg5NiA4OTYiIGZvY3VzYWJsZT0iZmFsc2UiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTkyNC44IDYyNS43bC02NS41LTU2YzMuMS0xOSA0LjctMzguNCA0LjctNTcuOHMtMS42LTM4LjgtNC43LTU3LjhsNjUuNS01NmEzMi4wMyAzMi4wMyAwIDAwOS4zLTM1LjJsLS45LTIuNmE0NDMuNzQgNDQzLjc0IDAgMDAtNzkuNy0xMzcuOWwtMS44LTIuMWEzMi4xMiAzMi4xMiAwIDAwLTM1LjEtOS41bC04MS4zIDI4LjljLTMwLTI0LjYtNjMuNS00NC05OS43LTU3LjZsLTE1LjctODVhMzIuMDUgMzIuMDUgMCAwMC0yNS44LTI1LjdsLTIuNy0uNWMtNTIuMS05LjQtMTA2LjktOS40LTE1OSAwbC0yLjcuNWEzMi4wNSAzMi4wNSAwIDAwLTI1LjggMjUuN2wtMTUuOCA4NS40YTM1MS44NiAzNTEuODYgMCAwMC05OSA1Ny40bC04MS45LTI5LjFhMzIgMzIgMCAwMC0zNS4xIDkuNWwtMS44IDIuMWE0NDYuMDIgNDQ2LjAyIDAgMDAtNzkuNyAxMzcuOWwtLjkgMi42Yy00LjUgMTIuNS0uOCAyNi41IDkuMyAzNS4ybDY2LjMgNTYuNmMtMy4xIDE4LjgtNC42IDM4LTQuNiA1Ny4xIDAgMTkuMiAxLjUgMzguNCA0LjYgNTcuMUw5OSA2MjUuNWEzMi4wMyAzMi4wMyAwIDAwLTkuMyAzNS4ybC45IDIuNmMxOC4xIDUwLjQgNDQuOSA5Ni45IDc5LjcgMTM3LjlsMS44IDIuMWEzMi4xMiAzMi4xMiAwIDAwMzUuMSA5LjVsODEuOS0yOS4xYzI5LjggMjQuNSA2My4xIDQzLjkgOTkgNTcuNGwxNS44IDg1LjRhMzIuMDUgMzIuMDUgMCAwMDI1LjggMjUuN2wyLjcuNWE0NDkuNCA0NDkuNCAwIDAwMTU5IDBsMi43LS41YTMyLjA1IDMyLjA1IDAgMDAyNS44LTI1LjdsMTUuNy04NWEzNTAgMzUwIDAgMDA5OS43LTU3LjZsODEuMyAyOC45YTMyIDMyIDAgMDAzNS4xLTkuNWwxLjgtMi4xYzM0LjgtNDEuMSA2MS42LTg3LjUgNzkuNy0xMzcuOWwuOS0yLjZjNC41LTEyLjMuOC0yNi4zLTkuMy0zNXpNNzg4LjMgNDY1LjljMi41IDE1LjEgMy44IDMwLjYgMy44IDQ2LjFzLTEuMyAzMS0zLjggNDYuMWwtNi42IDQwLjEgNzQuNyA2My45YTM3MC4wMyAzNzAuMDMgMCAwMS00Mi42IDczLjZMNzIxIDcwMi44bC0zMS40IDI1LjhjLTIzLjkgMTkuNi01MC41IDM1LTc5LjMgNDUuOGwtMzguMSAxNC4zLTE3LjkgOTdhMzc3LjUgMzc3LjUgMCAwMS04NSAwbC0xNy45LTk3LjItMzcuOC0xNC41Yy0yOC41LTEwLjgtNTUtMjYuMi03OC43LTQ1LjdsLTMxLjQtMjUuOS05My40IDMzLjJjLTE3LTIyLjktMzEuMi00Ny42LTQyLjYtNzMuNmw3NS41LTY0LjUtNi41LTQwYy0yLjQtMTQuOS0zLjctMzAuMy0zLjctNDUuNSAwLTE1LjMgMS4yLTMwLjYgMy43LTQ1LjVsNi41LTQwLTc1LjUtNjQuNWMxMS4zLTI2LjEgMjUuNi01MC43IDQyLjYtNzMuNmw5My40IDMzLjIgMzEuNC0yNS45YzIzLjctMTkuNSA1MC4yLTM0LjkgNzguNy00NS43bDM3LjktMTQuMyAxNy45LTk3LjJjMjguMS0zLjIgNTYuOC0zLjIgODUgMGwxNy45IDk3IDM4LjEgMTQuM2MyOC43IDEwLjggNTUuNCAyNi4yIDc5LjMgNDUuOGwzMS40IDI1LjggOTIuOC0zMi45YzE3IDIyLjkgMzEuMiA0Ny42IDQyLjYgNzMuNkw3ODEuOCA0MjZsNi41IDM5Ljl6TTUxMiAzMjZjLTk3LjIgMC0xNzYgNzguOC0xNzYgMTc2czc4LjggMTc2IDE3NiAxNzYgMTc2LTc4LjggMTc2LTE3Ni03OC44LTE3Ni0xNzYtMTc2em03OS4yIDI1NS4yQTExMS42IDExMS42IDAgMDE1MTIgNjE0Yy0yOS45IDAtNTgtMTEuNy03OS4yLTMyLjhBMTExLjYgMTExLjYgMCAwMTQwMCA1MDJjMC0yOS45IDExLjctNTggMzIuOC03OS4yQzQ1NCA0MDEuNiA0ODIuMSAzOTAgNTEyIDM5MGMyOS45IDAgNTggMTEuNiA3OS4yIDMyLjhBMTExLjYgMTExLjYgMCAwMTYyNCA1MDJjMCAyOS45LTExLjcgNTgtMzIuOCA3OS4yeiIgLz48L3N2Zz4=) */
172
172
 
173
173
  /**![sort-ascending](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIGZpbGw9IiNjYWNhY2EiIHZpZXdCb3g9IjY0IDY0IDg5NiA4OTYiIGZvY3VzYWJsZT0iZmFsc2UiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTgzOS42IDQzMy44TDc0OSAxNTAuNWE5LjI0IDkuMjQgMCAwMC04LjktNi41aC03Ny40Yy00LjEgMC03LjYgMi42LTguOSA2LjVsLTkxLjMgMjgzLjNjLS4zLjktLjUgMS45LS41IDIuOSAwIDUuMSA0LjIgOS4zIDkuMyA5LjNoNTYuNGM0LjIgMCA3LjgtMi44IDktNi44bDE3LjUtNjEuNmg4OWwxNy4zIDYxLjVjMS4xIDQgNC44IDYuOCA5IDYuOGg2MS4yYzEgMCAxLjktLjEgMi44LS40IDIuNC0uOCA0LjMtMi40IDUuNS00LjYgMS4xLTIuMiAxLjMtNC43LjYtNy4xek02NjMuMyAzMjUuNWwzMi44LTExNi45aDYuM2wzMi4xIDExNi45aC03MS4yem0xNDMuNSA0OTIuOUg2NzcuMnYtLjRsMTMyLjYtMTg4LjljMS4xLTEuNiAxLjctMy40IDEuNy01LjR2LTM2LjRjMC01LjEtNC4yLTkuMy05LjMtOS4zaC0yMDRjLTUuMSAwLTkuMyA0LjItOS4zIDkuM3Y0M2MwIDUuMSA0LjIgOS4zIDkuMyA5LjNoMTIyLjZ2LjRMNTg3LjcgODI4LjlhOS4zNSA5LjM1IDAgMDAtMS43IDUuNHYzNi40YzAgNS4xIDQuMiA5LjMgOS4zIDkuM2gyMTEuNGM1LjEgMCA5LjMtNC4yIDkuMy05LjN2LTQzYTkuMiA5LjIgMCAwMC05LjItOS4zek00MTYgNzAyaC03NlYxNzJjMC00LjQtMy42LTgtOC04aC01NmMtNC40IDAtOCAzLjYtOCA4djUzMGgtNzZjLTYuNyAwLTEwLjUgNy44LTYuMyAxM2wxMTIgMTQxLjlhOCA4IDAgMDAxMi42IDBsMTEyLTE0MS45YzQuMS01LjIuNC0xMy02LjMtMTN6IiAvPjwvc3ZnPg==) */
174
+
175
+ /**![unordered-list](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIGZpbGw9IiNjYWNhY2EiIHZpZXdCb3g9IjY0IDY0IDg5NiA4OTYiIGZvY3VzYWJsZT0iZmFsc2UiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTkxMiAxOTJIMzI4Yy00LjQgMC04IDMuNi04IDh2NTZjMCA0LjQgMy42IDggOCA4aDU4NGM0LjQgMCA4LTMuNiA4LTh2LTU2YzAtNC40LTMuNi04LTgtOHptMCAyODRIMzI4Yy00LjQgMC04IDMuNi04IDh2NTZjMCA0LjQgMy42IDggOCA4aDU4NGM0LjQgMCA4LTMuNiA4LTh2LTU2YzAtNC40LTMuNi04LTgtOHptMCAyODRIMzI4Yy00LjQgMC04IDMuNi04IDh2NTZjMCA0LjQgMy42IDggOCA4aDU4NGM0LjQgMCA4LTMuNiA4LTh2LTU2YzAtNC40LTMuNi04LTgtOHpNMTA0IDIyOGE1NiA1NiAwIDEwMTEyIDAgNTYgNTYgMCAxMC0xMTIgMHptMCAyODRhNTYgNTYgMCAxMDExMiAwIDU2IDU2IDAgMTAtMTEyIDB6bTAgMjg0YTU2IDU2IDAgMTAxMTIgMCA1NiA1NiAwIDEwLTExMiAweiIgLz48L3N2Zz4=) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whistle.mock-plugins",
3
- "version": "1.2.1-beta.6",
3
+ "version": "1.2.1",
4
4
  "description": "Whistle 插件,用于快速创建 API 模拟数据",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -5,8 +5,8 @@
5
5
  import React, { useState, useEffect } from 'react';
6
6
  import { useHistory } from 'react-router-dom';
7
7
  import AppLayout from '../components/AppLayout';
8
- import { Card, Row, Col, Button, Modal, Form, Input, message, Switch, Empty, Spin, Typography, Tooltip, Badge, Select, Pagination } from 'antd';
9
- import { PlusOutlined, EditOutlined, DeleteOutlined, ApiOutlined, ExportOutlined, InfoCircleOutlined, CalendarOutlined, SortAscendingOutlined } from '@ant-design/icons';
8
+ import { Card, Row, Col, Button, Modal, Form, Input, message, Switch, Empty, Spin, Typography, Tooltip, Badge, Select, Pagination, Table, Space, Tag } from 'antd';
9
+ import { PlusOutlined, EditOutlined, DeleteOutlined, ApiOutlined, ExportOutlined, InfoCircleOutlined, CalendarOutlined, SortAscendingOutlined, AppstoreOutlined, UnorderedListOutlined } from '@ant-design/icons';
10
10
  import '../styles/mock-data.css';
11
11
  import axios from 'axios';
12
12
 
@@ -40,7 +40,8 @@ const MockData = () => {
40
40
  sortBy: 'name', // name, createdAt, interfaceCount, active
41
41
  sortOrder: 'ascend', // ascend, descend
42
42
  pageSize: 12,
43
- current: 1
43
+ current: 1,
44
+ viewMode: 'card' // card, list
44
45
  };
45
46
  });
46
47
 
@@ -368,6 +369,10 @@ const MockData = () => {
368
369
  saveListConfig({ current: page, pageSize });
369
370
  };
370
371
 
372
+ const handleViewModeChange = (mode) => {
373
+ saveListConfig({ viewMode: mode, current: 1 });
374
+ };
375
+
371
376
  // 获取排序后的功能列表
372
377
  const getSortedFeatures = () => {
373
378
  const sorted = [...mockFeatures].sort((a, b) => {
@@ -516,6 +521,139 @@ const MockData = () => {
516
521
  );
517
522
  };
518
523
 
524
+ // 渲染列表视图
525
+ const renderListView = () => {
526
+ const columns = [
527
+ {
528
+ title: '状态',
529
+ dataIndex: 'active',
530
+ key: 'active',
531
+ width: 100,
532
+ render: (active, record) => (
533
+ <Switch
534
+ checked={active}
535
+ onChange={(checked, e) => {
536
+ e.stopPropagation();
537
+ handleToggleActive(record.id, active);
538
+ }}
539
+ checkedChildren="启用"
540
+ unCheckedChildren="禁用"
541
+ />
542
+ ),
543
+ },
544
+ {
545
+ title: '功能名称',
546
+ dataIndex: 'name',
547
+ key: 'name',
548
+ ellipsis: { tooltip: true },
549
+ render: (name) => (
550
+ <Text strong style={{ fontSize: '14px' }}>{name}</Text>
551
+ ),
552
+ },
553
+ {
554
+ title: '功能描述',
555
+ dataIndex: 'description',
556
+ key: 'description',
557
+ ellipsis: { tooltip: true },
558
+ render: (description) => (
559
+ <Text type="secondary">{description || '无描述'}</Text>
560
+ ),
561
+ },
562
+ {
563
+ title: '接口数量',
564
+ dataIndex: 'interfaceCount',
565
+ key: 'interfaceCount',
566
+ width: 100,
567
+ align: 'center',
568
+ render: (count) => (
569
+ <Badge count={count || 0} showZero style={{ backgroundColor: '#1890ff' }} />
570
+ ),
571
+ },
572
+ {
573
+ title: '创建时间',
574
+ dataIndex: 'createdAt',
575
+ key: 'createdAt',
576
+ width: 120,
577
+ render: (createdAt) => (
578
+ <Text type="secondary">
579
+ {createdAt ? new Date(createdAt).toLocaleDateString() : '未知日期'}
580
+ </Text>
581
+ ),
582
+ },
583
+ {
584
+ title: '操作',
585
+ key: 'action',
586
+ width: 200,
587
+ fixed: 'right',
588
+ render: (_, record) => (
589
+ <Space size="small">
590
+ <Tooltip title="管理接口">
591
+ <Button
592
+ type="link"
593
+ size="small"
594
+ icon={<ApiOutlined />}
595
+ onClick={(e) => {
596
+ e.stopPropagation();
597
+ viewInterfaces(record);
598
+ }}
599
+ >
600
+ 接口
601
+ </Button>
602
+ </Tooltip>
603
+ <Tooltip title="编辑">
604
+ <Button
605
+ type="link"
606
+ size="small"
607
+ icon={<EditOutlined />}
608
+ onClick={(e) => {
609
+ e.stopPropagation();
610
+ openModal(record);
611
+ }}
612
+ />
613
+ </Tooltip>
614
+ <Tooltip title="导出">
615
+ <Button
616
+ type="link"
617
+ size="small"
618
+ icon={<ExportOutlined />}
619
+ onClick={(e) => {
620
+ e.stopPropagation();
621
+ exportFeatureConfig(record);
622
+ }}
623
+ />
624
+ </Tooltip>
625
+ <Tooltip title="删除">
626
+ <Button
627
+ type="link"
628
+ size="small"
629
+ danger
630
+ icon={<DeleteOutlined />}
631
+ onClick={(e) => {
632
+ e.stopPropagation();
633
+ deleteFeature(record.id);
634
+ }}
635
+ />
636
+ </Tooltip>
637
+ </Space>
638
+ ),
639
+ },
640
+ ];
641
+
642
+ return (
643
+ <Table
644
+ columns={columns}
645
+ dataSource={getPaginatedFeatures()}
646
+ rowKey="id"
647
+ pagination={false}
648
+ onRow={(record) => ({
649
+ onClick: () => viewInterfaces(record),
650
+ style: { cursor: 'pointer' }
651
+ })}
652
+ rowClassName={(record) => !record.active ? 'inactive-row' : ''}
653
+ />
654
+ );
655
+ };
656
+
519
657
  return (
520
658
  <AppLayout>
521
659
  <div className="page-container">
@@ -584,7 +722,7 @@ const MockData = () => {
584
722
  </div>
585
723
  </Col>
586
724
 
587
- {/* 排序控制区域 */}
725
+ {/* 排序和视图控制区域 */}
588
726
  <Col xs={24} sm={12} md={8} lg={9}>
589
727
  <div className="sort-controls">
590
728
  <div className="control-group">
@@ -615,8 +753,30 @@ const MockData = () => {
615
753
  </div>
616
754
  </Col>
617
755
 
756
+ {/* 视图切换区域 */}
757
+ <Col xs={24} sm={12} md={4} lg={3}>
758
+ <div className="view-mode-controls">
759
+ <Button.Group>
760
+ <Tooltip title="卡片视图">
761
+ <Button
762
+ type={listConfig.viewMode === 'card' ? 'primary' : 'default'}
763
+ icon={<AppstoreOutlined />}
764
+ onClick={() => handleViewModeChange('card')}
765
+ />
766
+ </Tooltip>
767
+ <Tooltip title="列表视图">
768
+ <Button
769
+ type={listConfig.viewMode === 'list' ? 'primary' : 'default'}
770
+ icon={<UnorderedListOutlined />}
771
+ onClick={() => handleViewModeChange('list')}
772
+ />
773
+ </Tooltip>
774
+ </Button.Group>
775
+ </div>
776
+ </Col>
777
+
618
778
  {/* 分页控制区域 */}
619
- <Col xs={24} sm={24} md={8} lg={9}>
779
+ <Col xs={24} sm={24} md={12} lg={6}>
620
780
  <div className="pagination-controls">
621
781
  <div className="control-group">
622
782
  <span className="control-label">每页显示</span>
@@ -649,9 +809,13 @@ const MockData = () => {
649
809
  </div>
650
810
  ) : mockFeatures.length > 0 ? (
651
811
  <>
652
- <Row gutter={[20, 20]} className="feature-grid">
653
- {getPaginatedFeatures().map(feature => renderFeatureCard(feature))}
654
- </Row>
812
+ {listConfig.viewMode === 'card' ? (
813
+ <Row gutter={[20, 20]} className="feature-grid">
814
+ {getPaginatedFeatures().map(feature => renderFeatureCard(feature))}
815
+ </Row>
816
+ ) : (
817
+ renderListView()
818
+ )}
655
819
 
656
820
  {/* 分页组件 */}
657
821
  {mockFeatures.length > listConfig.pageSize && (
@@ -1115,4 +1115,71 @@ input:checked + .slider:before {
1115
1115
  .ant-card-extra {
1116
1116
  margin-right: 60px;
1117
1117
  }
1118
+ }
1119
+
1120
+ /* 视图切换控制样式 */
1121
+ .view-mode-controls {
1122
+ display: flex;
1123
+ justify-content: flex-end;
1124
+ align-items: center;
1125
+ }
1126
+
1127
+ .view-mode-controls .ant-btn-group {
1128
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
1129
+ }
1130
+
1131
+ /* 列表视图样式 */
1132
+ .feature-list-card .ant-table-wrapper {
1133
+ margin-top: 0;
1134
+ }
1135
+
1136
+ .feature-list-card .ant-table {
1137
+ font-size: 14px;
1138
+ }
1139
+
1140
+ .feature-list-card .ant-table-thead > tr > th {
1141
+ background-color: #fafafa;
1142
+ font-weight: 600;
1143
+ color: #262626;
1144
+ padding: 16px;
1145
+ }
1146
+
1147
+ .feature-list-card .ant-table-tbody > tr > td {
1148
+ padding: 16px;
1149
+ }
1150
+
1151
+ .feature-list-card .ant-table-tbody > tr:hover {
1152
+ background-color: #f5f5f5;
1153
+ }
1154
+
1155
+ .feature-list-card .ant-table-tbody > tr.inactive-row {
1156
+ background-color: #fafafa;
1157
+ opacity: 0.7;
1158
+ }
1159
+
1160
+ .feature-list-card .ant-table-tbody > tr.inactive-row:hover {
1161
+ background-color: #f0f0f0;
1162
+ }
1163
+
1164
+ /* 列表视图中的操作按钮样式 */
1165
+ .feature-list-card .ant-btn-link {
1166
+ padding: 4px 8px;
1167
+ height: auto;
1168
+ }
1169
+
1170
+ /* 响应式调整 */
1171
+ @media (max-width: 768px) {
1172
+ .view-mode-controls {
1173
+ justify-content: center;
1174
+ margin-top: 12px;
1175
+ }
1176
+
1177
+ .feature-list-card .ant-table {
1178
+ font-size: 13px;
1179
+ }
1180
+
1181
+ .feature-list-card .ant-table-thead > tr > th,
1182
+ .feature-list-card .ant-table-tbody > tr > td {
1183
+ padding: 12px 8px;
1184
+ }
1118
1185
  }