neo-cmp-cli 1.13.12 → 1.13.15

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.
Files changed (67) hide show
  1. package/README.md +1 -1
  2. package/dist/neo/neoEnvManager.js +1 -1
  3. package/dist/neo/neoLogin.js +1 -1
  4. package/dist/neo/neoRequire.js +1 -1
  5. package/dist/neo/neoService.js +1 -1
  6. package/dist/package.json.js +1 -1
  7. package/package.json +1 -1
  8. package/template/antd-custom-cmp-template/package.json +1 -1
  9. package/template/asset-manage-template/package.json +1 -1
  10. package/template/echarts-custom-cmp-template/package.json +1 -1
  11. package/template/empty-custom-cmp-template/package.json +1 -1
  12. package/template/map-custom-cmp-template/package.json +1 -1
  13. package/template/neo-bi-cmps/docs/gartner-pipeline-apis.md +45 -73
  14. package/template/neo-bi-cmps/package.json +1 -1
  15. package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/README.md +52 -0
  16. package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/index.tsx +183 -0
  17. package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/model.ts +90 -0
  18. package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/style.scss +218 -0
  19. package/template/neo-bi-cmps/src/components/filterBar__c/README.md +35 -0
  20. package/template/neo-bi-cmps/src/components/filterBar__c/index.tsx +200 -0
  21. package/template/neo-bi-cmps/src/components/filterBar__c/model.ts +72 -0
  22. package/template/neo-bi-cmps/src/components/filterBar__c/style.scss +212 -0
  23. package/template/neo-bi-cmps/src/components/forecastChart__c/README.md +31 -0
  24. package/template/neo-bi-cmps/src/components/forecastChart__c/index.tsx +158 -0
  25. package/template/neo-bi-cmps/src/components/forecastChart__c/model.ts +40 -0
  26. package/template/neo-bi-cmps/src/components/forecastChart__c/style.scss +154 -0
  27. package/template/neo-bi-cmps/src/components/forecastGrid__c/README.md +36 -0
  28. package/template/neo-bi-cmps/src/components/forecastGrid__c/index.tsx +86 -0
  29. package/template/neo-bi-cmps/src/components/forecastGrid__c/model.ts +62 -0
  30. package/template/neo-bi-cmps/src/components/forecastGrid__c/style.scss +48 -0
  31. package/template/neo-bi-cmps/src/components/gapCloser__c/README.md +24 -0
  32. package/template/neo-bi-cmps/src/components/gapCloser__c/index.tsx +100 -0
  33. package/template/neo-bi-cmps/src/components/gapCloser__c/model.ts +46 -0
  34. package/template/neo-bi-cmps/src/components/gapCloser__c/style.scss +60 -0
  35. package/template/neo-bi-cmps/src/components/kpiCards__c/README.md +35 -0
  36. package/template/neo-bi-cmps/src/components/kpiCards__c/index.tsx +70 -0
  37. package/template/neo-bi-cmps/src/components/kpiCards__c/model.ts +50 -0
  38. package/template/neo-bi-cmps/src/components/kpiCards__c/style.scss +33 -0
  39. package/template/neo-bi-cmps/src/components/oppList__c/README.md +52 -0
  40. package/template/neo-bi-cmps/src/components/oppList__c/index.tsx +285 -0
  41. package/template/neo-bi-cmps/src/components/oppList__c/model.ts +86 -0
  42. package/template/neo-bi-cmps/src/components/oppList__c/style.scss +133 -0
  43. package/template/neo-bi-cmps/src/components/pipelineFunnel__c/README.md +39 -0
  44. package/template/neo-bi-cmps/src/components/pipelineFunnel__c/index.tsx +130 -0
  45. package/template/neo-bi-cmps/src/components/pipelineFunnel__c/model.ts +66 -0
  46. package/template/neo-bi-cmps/src/components/pipelineFunnel__c/style.scss +133 -0
  47. package/template/neo-bi-cmps/src/components/stageSwitch__c/README.md +36 -0
  48. package/template/neo-bi-cmps/src/components/stageSwitch__c/index.tsx +118 -0
  49. package/template/neo-bi-cmps/src/components/stageSwitch__c/model.ts +92 -0
  50. package/template/neo-bi-cmps/src/components/stageSwitch__c/style.scss +89 -0
  51. package/template/neo-bi-cmps/src/components/stageTimeChart__c/README.md +37 -0
  52. package/template/neo-bi-cmps/src/components/stageTimeChart__c/index.tsx +126 -0
  53. package/template/neo-bi-cmps/src/components/stageTimeChart__c/model.ts +57 -0
  54. package/template/neo-bi-cmps/src/components/stageTimeChart__c/style.scss +140 -0
  55. package/template/neo-bi-cmps/src/components/tabSwitch__c/README.md +37 -0
  56. package/template/neo-bi-cmps/src/components/tabSwitch__c/index.tsx +80 -0
  57. package/template/neo-bi-cmps/src/components/tabSwitch__c/model.ts +45 -0
  58. package/template/neo-bi-cmps/src/components/tabSwitch__c/style.scss +37 -0
  59. package/template/neo-custom-cmp-template/package.json +1 -1
  60. package/template/neo-h5-cmps/package.json +1 -1
  61. package/template/neo-order-cmps/package.json +1 -1
  62. package/template/neo-web-entity-grid/package.json +1 -1
  63. package/template/neo-web-form/package.json +1 -1
  64. package/template/neo-web-form/src/components/batchAddTable__c/index.tsx +17 -17
  65. package/template/react-custom-cmp-template/package.json +1 -1
  66. package/template/react-ts-custom-cmp-template/package.json +1 -1
  67. package/template/vue2-custom-cmp-template/package.json +1 -1
@@ -0,0 +1,39 @@
1
+ # PipelineFunnel 组件
2
+
3
+ Pipeline漏斗图组件,展示销售管道的漏斗转化情况。
4
+
5
+ ## 使用方式
6
+
7
+ ```tsx
8
+ import PipelineFunnel from './components/pipelineFunnel__c';
9
+
10
+ <PipelineFunnel
11
+ title="Pipeline Funnel"
12
+ totalAmount="$11.1M"
13
+ stages={[
14
+ { name: 'Prospecting', amount: '$3.2M', count: 15, color: '#3b82f6' },
15
+ { name: 'Needs Analysis', amount: '$1.8M', count: 7, conversionRate: '56.3%', color: '#22c55e' },
16
+ ]}
17
+ onStageClick={(name) => console.log('Clicked:', name)}
18
+ />
19
+ ```
20
+
21
+ ## Props
22
+
23
+ | 属性 | 说明 | 类型 | 默认值 |
24
+ |------|------|------|--------|
25
+ | title | 标题 | string | 'Pipeline Funnel' |
26
+ | totalAmount | 总金额 | string | '$11.1M' |
27
+ | stages | 漏斗阶段数据 | FunnelStage[] | [] |
28
+ | showAiButton | 显示AI按钮 | boolean | true |
29
+ | onStageClick | 阶段点击回调 | (stageName: string) => void | - |
30
+
31
+ ## FunnelStage
32
+
33
+ | 属性 | 说明 | 类型 |
34
+ |------|------|------|
35
+ | name | 阶段名称 | string |
36
+ | amount | 金额 | string |
37
+ | count | 数量 | number |
38
+ | conversionRate | 转化率 | string |
39
+ | color | 颜色 | string |
@@ -0,0 +1,130 @@
1
+ /**
2
+ * @file Pipeline漏斗图组件
3
+ * @description 展示销售管道的漏斗转化情况
4
+ */
5
+ import * as React from 'react';
6
+ // @ts-ignore
7
+ import { BaseCmp, StatusHoc, NeoEvent } from 'neo-ui-common';
8
+
9
+ import './style.scss';
10
+
11
+ interface FunnelStage {
12
+ name: string;
13
+ amount: string;
14
+ count: number;
15
+ conversionRate?: string;
16
+ color: string;
17
+ }
18
+
19
+ interface PipelineFunnelProps {
20
+ title?: string;
21
+ totalAmount?: string;
22
+ stages?: FunnelStage[];
23
+ showAiButton?: boolean;
24
+ onStageClick?: (stageName: string) => void;
25
+ className?: string;
26
+ style?: React.CSSProperties;
27
+ }
28
+
29
+ interface PipelineFunnelState {
30
+ loading: boolean;
31
+ }
32
+
33
+ class PipelineFunnel extends BaseCmp<PipelineFunnelProps, PipelineFunnelState> {
34
+ constructor(props: PipelineFunnelProps) {
35
+ super(props);
36
+ this.state = {
37
+ loading: false,
38
+ };
39
+ }
40
+
41
+ componentDidMount() {
42
+ console.log('PipelineFunnel 组件挂载');
43
+ }
44
+
45
+ getFunnelClipPath = (index: number, total: number): string => {
46
+ const offset = index * 10;
47
+ return `polygon(${offset}% 0%, ${100 - offset}% 0%, ${
48
+ 100 - offset - 10
49
+ }% 100%, ${offset + 10}% 100%)`;
50
+ };
51
+
52
+ render() {
53
+ const {
54
+ title = 'Pipeline Funnel',
55
+ totalAmount = '$11.1M',
56
+ stages = [],
57
+ showAiButton = true,
58
+ onStageClick,
59
+ className,
60
+ style,
61
+ } = this.props;
62
+
63
+ return (
64
+ <div className={`pipeline-funnel__c ${className || ''}`} style={style}>
65
+ <div className="funnel-header">
66
+ <h3 className="funnel-title">{title}</h3>
67
+ {showAiButton && (
68
+ <span
69
+ className="ai-btn"
70
+ onClick={() => console.log('AI Analysis clicked')}
71
+ title="AI Analysis"
72
+ >
73
+
74
+ </span>
75
+ )}
76
+ </div>
77
+
78
+ <div className="funnel-total">
79
+ <div className="funnel-total-label">Sales Amount</div>
80
+ <div className="funnel-total-value">{totalAmount}</div>
81
+ </div>
82
+
83
+ <div className="funnel-body">
84
+ <div className="funnel-left-rates">
85
+ {stages.slice(0, -1).map((stage, index) => (
86
+ <div key={index} className="funnel-rate">
87
+ {stage.conversionRate || '—'}
88
+ </div>
89
+ ))}
90
+ </div>
91
+
92
+ <div className="funnel-main">
93
+ {stages.map((stage, index) => (
94
+ <div
95
+ key={index}
96
+ className="funnel-segment"
97
+ style={{ backgroundColor: stage.color }}
98
+ onClick={() => onStageClick?.(stage.name)}
99
+ >
100
+ {stage.name}
101
+ </div>
102
+ ))}
103
+ </div>
104
+
105
+ <div className="funnel-right-data">
106
+ {stages.map((stage, index) => (
107
+ <div key={index} className="funnel-data">
108
+ {stage.amount} / {stage.count}
109
+ </div>
110
+ ))}
111
+ </div>
112
+ </div>
113
+
114
+ <div className="funnel-legend">
115
+ {stages.map((stage, index) => (
116
+ <span key={index} className="legend-item">
117
+ <span
118
+ className="legend-dot"
119
+ style={{ backgroundColor: stage.color }}
120
+ />
121
+ {stage.name}
122
+ </span>
123
+ ))}
124
+ </div>
125
+ </div>
126
+ );
127
+ }
128
+ }
129
+
130
+ export default StatusHoc(PipelineFunnel);
@@ -0,0 +1,66 @@
1
+ export class PipelineFunnelModel {
2
+ label: string = 'Pipeline漏斗图';
3
+ description: string = '展示销售管道的漏斗转化情况,直观显示各阶段金额和数量';
4
+ iconUrl: string = 'https://custom-widgets.bj.bcebos.com/pipelineFunnel.svg';
5
+ targetPage: string[] = ['all'];
6
+ targetDevice: string = 'all';
7
+
8
+ defaultComProps = {
9
+ title: 'Pipeline Funnel',
10
+ totalAmount: '$11.1M',
11
+ stages: [
12
+ {
13
+ name: 'Prospecting',
14
+ amount: '$3.2M',
15
+ count: 15,
16
+ conversionRate: '—',
17
+ color: '#3b82f6',
18
+ },
19
+ {
20
+ name: 'Needs Analysis',
21
+ amount: '$1.8M',
22
+ count: 7,
23
+ conversionRate: '56.3%',
24
+ color: '#22c55e',
25
+ },
26
+ {
27
+ name: 'Proposal/Price Quote',
28
+ amount: '$4.5M',
29
+ count: 8,
30
+ conversionRate: '28.1%',
31
+ color: '#f59e0b',
32
+ },
33
+ {
34
+ name: 'Closed Won',
35
+ amount: '$1.6M',
36
+ count: 3,
37
+ conversionRate: '10.0%',
38
+ color: '#8b5cf6',
39
+ },
40
+ ],
41
+ showAiButton: true,
42
+ };
43
+
44
+ functions = [
45
+ {
46
+ apiKey: 'refreshData',
47
+ label: '刷新数据',
48
+ helpTextKey: '刷新漏斗图数据',
49
+ },
50
+ ];
51
+
52
+ propsSchema = [
53
+ {
54
+ type: 'string',
55
+ name: 'title',
56
+ label: '标题',
57
+ },
58
+ {
59
+ type: 'string',
60
+ name: 'totalAmount',
61
+ label: '总金额',
62
+ },
63
+ ];
64
+ }
65
+
66
+ export default PipelineFunnelModel;
@@ -0,0 +1,133 @@
1
+ .pipeline-funnel__c {
2
+ background: #fff;
3
+ border-radius: 8px;
4
+ padding: 20px;
5
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
6
+
7
+ .funnel-header {
8
+ display: flex;
9
+ justify-content: space-between;
10
+ align-items: center;
11
+ margin-bottom: 16px;
12
+ }
13
+
14
+ .funnel-title {
15
+ font-size: 14px;
16
+ font-weight: 600;
17
+ margin: 0;
18
+ }
19
+
20
+ .ai-btn {
21
+ cursor: pointer;
22
+ font-size: 16px;
23
+ transition: transform 0.2s;
24
+
25
+ &:hover {
26
+ transform: scale(1.1);
27
+ }
28
+ }
29
+
30
+ .funnel-total {
31
+ text-align: center;
32
+ margin-bottom: 16px;
33
+
34
+ .funnel-total-label {
35
+ font-size: 12px;
36
+ color: #888;
37
+ }
38
+
39
+ .funnel-total-value {
40
+ font-size: 22px;
41
+ font-weight: 700;
42
+ }
43
+ }
44
+
45
+ .funnel-body {
46
+ display: flex;
47
+ align-items: stretch;
48
+ gap: 0;
49
+ }
50
+
51
+ .funnel-left-rates {
52
+ width: 100px;
53
+ display: flex;
54
+ flex-direction: column;
55
+ justify-content: center;
56
+ gap: 0;
57
+ font-size: 11px;
58
+ color: #888;
59
+ }
60
+
61
+ .funnel-rate {
62
+ height: 48px;
63
+ display: flex;
64
+ align-items: center;
65
+ }
66
+
67
+ .funnel-main {
68
+ flex: 1;
69
+ display: flex;
70
+ flex-direction: column;
71
+ align-items: center;
72
+ }
73
+
74
+ .funnel-segment {
75
+ width: 100%;
76
+ height: 48px;
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ color: #fff;
81
+ font-size: 12px;
82
+ font-weight: 600;
83
+ cursor: pointer;
84
+ transition: opacity 0.2s;
85
+
86
+ &:hover {
87
+ opacity: 0.85;
88
+ }
89
+ }
90
+
91
+ .funnel-right-data {
92
+ width: 110px;
93
+ display: flex;
94
+ flex-direction: column;
95
+ justify-content: center;
96
+ gap: 0;
97
+ font-size: 11px;
98
+ color: #555;
99
+ text-align: right;
100
+ }
101
+
102
+ .funnel-data {
103
+ height: 48px;
104
+ display: flex;
105
+ align-items: center;
106
+ justify-content: flex-end;
107
+ }
108
+
109
+ .funnel-legend {
110
+ display: flex;
111
+ gap: 12px;
112
+ justify-content: center;
113
+ flex-wrap: wrap;
114
+ margin-top: 16px;
115
+ font-size: 11px;
116
+ color: #666;
117
+ }
118
+
119
+ .legend-item {
120
+ display: flex;
121
+ align-items: center;
122
+ gap: 4px;
123
+ }
124
+
125
+ .legend-dot {
126
+ display: inline-block;
127
+ width: 10px;
128
+ height: 10px;
129
+ border-radius: 50%;
130
+ margin-right: 4px;
131
+ vertical-align: middle;
132
+ }
133
+ }
@@ -0,0 +1,36 @@
1
+ # StageSwitch 组件
2
+
3
+ 阶段切换卡片组件,切换显示不同销售阶段的数据。
4
+
5
+ ## 使用方式
6
+
7
+ ```tsx
8
+ import StageSwitch from './components/stageSwitch__c';
9
+
10
+ <StageSwitch
11
+ stages={[
12
+ { key: 'Prospecting', name: 'Prospecting', amount: '$3.2M', count: 15 },
13
+ { key: 'Proposal', name: 'Proposal', amount: '$4.5M', count: 8 },
14
+ ]}
15
+ activeStage="Prospecting"
16
+ onStageChange={(stage) => console.log('Changed:', stage.key)}
17
+ />
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | 属性 | 说明 | 类型 | 默认值 |
23
+ |------|------|------|--------|
24
+ | stages | 阶段数据 | StageTab[] | [] |
25
+ | activeStage | 当前阶段 | string | 第一个阶段 |
26
+ | onStageChange | 阶段切换回调 | (stage: StageTab) => void | - |
27
+
28
+ ## StageTab
29
+
30
+ | 属性 | 说明 | 类型 |
31
+ |------|------|------|
32
+ | key | 唯一标识 | string |
33
+ | name | 阶段名称 | string |
34
+ | amount | 金额 | string |
35
+ | count | 数量 | number |
36
+ | changes | 变化数据 | { amount, amountDirection, count, countDirection } |
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @file 阶段切换卡片组件
3
+ * @description 切换显示不同销售阶段的数据
4
+ */
5
+ import * as React from 'react';
6
+ // @ts-ignore
7
+ import { BaseCmp, StatusHoc, NeoEvent } from 'neo-ui-common';
8
+
9
+ import './style.scss';
10
+
11
+ interface StageTab {
12
+ key: string;
13
+ name: string;
14
+ amount: string;
15
+ count: number;
16
+ changes?: {
17
+ amount: string;
18
+ amountDirection: 'up' | 'down';
19
+ count: string;
20
+ countDirection: 'up' | 'down';
21
+ };
22
+ }
23
+
24
+ interface StageSwitchProps {
25
+ stages?: StageTab[];
26
+ activeStage?: string;
27
+ onStageChange?: (stage: StageTab) => void;
28
+ className?: string;
29
+ style?: React.CSSProperties;
30
+ }
31
+
32
+ interface StageSwitchState {
33
+ activeStage: string;
34
+ }
35
+
36
+ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
37
+ constructor(props: StageSwitchProps) {
38
+ super(props);
39
+ this.state = {
40
+ activeStage: props.activeStage || (props.stages?.[0]?.key ?? ''),
41
+ };
42
+ }
43
+
44
+ componentDidMount() {
45
+ console.log('StageSwitch 组件挂载');
46
+ }
47
+
48
+ componentWillReceiveProps(nextProps: StageSwitchProps) {
49
+ if (
50
+ nextProps.activeStage &&
51
+ nextProps.activeStage !== this.props.activeStage
52
+ ) {
53
+ this.setState({ activeStage: nextProps.activeStage });
54
+ }
55
+ }
56
+
57
+ handleStageClick(stage: StageTab) {
58
+ this.setState({ activeStage: stage.key });
59
+ const { onStageChange } = this.props;
60
+ if (onStageChange) {
61
+ onStageChange(stage);
62
+ }
63
+ }
64
+
65
+ render() {
66
+ const { stages = [], className, style } = this.props;
67
+ const { activeStage } = this.state;
68
+
69
+ return (
70
+ <div className={`stage-switch__c ${className || ''}`} style={style}>
71
+ <div className="stage-tabs">
72
+ {stages.map((stage) => (
73
+ <div
74
+ key={stage.key}
75
+ className={`stage-tab ${
76
+ activeStage === stage.key ? 'active' : ''
77
+ }`}
78
+ onClick={() => this.handleStageClick(stage)}
79
+ >
80
+ <div className="stage-name">{stage.name}</div>
81
+ <div className="stage-amount-row">
82
+ <span className="stage-amount">{stage.amount}</span>
83
+ <span className="stage-count">({stage.count})</span>
84
+ </div>
85
+ {stage.changes && (
86
+ <div className="stage-sub">
87
+ <span
88
+ className={`change-amount ${
89
+ stage.changes.amountDirection === 'up'
90
+ ? 'positive'
91
+ : 'negative'
92
+ }`}
93
+ >
94
+ {stage.changes.amountDirection === 'up' ? '↑' : '↓'}{' '}
95
+ {stage.changes.amount}
96
+ </span>
97
+ <span> &nbsp; </span>
98
+ <span
99
+ className={`change-count ${
100
+ stage.changes.countDirection === 'up'
101
+ ? 'positive'
102
+ : 'negative'
103
+ }`}
104
+ >
105
+ {stage.changes.countDirection === 'up' ? '↑' : '↓'}{' '}
106
+ {stage.changes.count}
107
+ </span>
108
+ </div>
109
+ )}
110
+ </div>
111
+ ))}
112
+ </div>
113
+ </div>
114
+ );
115
+ }
116
+ }
117
+
118
+ export default StatusHoc(StageSwitch);
@@ -0,0 +1,92 @@
1
+ export class StageSwitchModel {
2
+ label: string = '阶段切换卡片';
3
+ description: string = '切换显示不同销售阶段的数据,包含金额、数量和变化趋势';
4
+ iconUrl: string = 'https://custom-widgets.bj.bcebos.com/stageSwitch.svg';
5
+ targetPage: string[] = ['all'];
6
+ targetDevice: string = 'all';
7
+
8
+ defaultComProps = {
9
+ stages: [
10
+ {
11
+ key: 'Prospecting',
12
+ name: 'Prospecting',
13
+ amount: '$3.2M',
14
+ count: 15,
15
+ changes: {
16
+ amount: '$280K',
17
+ amountDirection: 'up',
18
+ count: '3',
19
+ countDirection: 'up',
20
+ },
21
+ },
22
+ {
23
+ key: 'Needs Analysis',
24
+ name: 'Needs Analysis',
25
+ amount: '$1.8M',
26
+ count: 7,
27
+ changes: {
28
+ amount: '$320K',
29
+ amountDirection: 'down',
30
+ count: '2',
31
+ countDirection: 'down',
32
+ },
33
+ },
34
+ {
35
+ key: 'Proposal',
36
+ name: 'Proposal/Price Quote',
37
+ amount: '$4.5M',
38
+ count: 8,
39
+ changes: {
40
+ amount: '$500K',
41
+ amountDirection: 'up',
42
+ count: '3',
43
+ countDirection: 'up',
44
+ },
45
+ },
46
+ {
47
+ key: 'Closed Won',
48
+ name: 'Closed Won',
49
+ amount: '$1.6M',
50
+ count: 3,
51
+ changes: {
52
+ amount: '$400K',
53
+ amountDirection: 'up',
54
+ count: '1',
55
+ countDirection: 'up',
56
+ },
57
+ },
58
+ {
59
+ key: 'Closed Lost',
60
+ name: 'Closed Lost',
61
+ amount: '$0.9M',
62
+ count: 4,
63
+ changes: {
64
+ amount: '$200K',
65
+ amountDirection: 'down',
66
+ count: '2',
67
+ countDirection: 'up',
68
+ },
69
+ },
70
+ ],
71
+ activeStage: 'Prospecting',
72
+ };
73
+
74
+ functions = [
75
+ {
76
+ apiKey: 'setActiveStage',
77
+ label: '设置当前阶段',
78
+ helpTextKey: '设置当前激活的销售阶段',
79
+ },
80
+ ];
81
+
82
+ propsSchema = [
83
+ {
84
+ type: 'object',
85
+ name: 'stages',
86
+ label: '阶段配置',
87
+ schema: [],
88
+ },
89
+ ];
90
+ }
91
+
92
+ export default StageSwitchModel;
@@ -0,0 +1,89 @@
1
+ .stage-switch__c {
2
+ .stage-tabs {
3
+ display: flex;
4
+ gap: 0;
5
+ margin-bottom: 20px;
6
+ background: #fff;
7
+ border-radius: 8px;
8
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
9
+ overflow: hidden;
10
+ }
11
+
12
+ .stage-tab {
13
+ flex: 1;
14
+ padding: 10px 16px;
15
+ cursor: pointer;
16
+ border-right: 1px solid #f0f0f0;
17
+ transition: all 0.2s;
18
+ position: relative;
19
+
20
+ &:last-child {
21
+ border-right: none;
22
+ }
23
+
24
+ &:hover {
25
+ background: #fafafa;
26
+ }
27
+
28
+ &.active {
29
+ background: #fff;
30
+
31
+ &::before {
32
+ content: '';
33
+ position: absolute;
34
+ top: 0;
35
+ left: 0;
36
+ right: 0;
37
+ height: 3px;
38
+ background: #6366f1;
39
+ }
40
+
41
+ .stage-name {
42
+ color: #6366f1;
43
+ font-weight: 600;
44
+ }
45
+ }
46
+ }
47
+
48
+ .stage-name {
49
+ font-size: 11px;
50
+ color: #888;
51
+ margin-bottom: 2px;
52
+ }
53
+
54
+ .stage-amount-row {
55
+ display: flex;
56
+ align-items: baseline;
57
+ gap: 4px;
58
+ }
59
+
60
+ .stage-amount {
61
+ font-size: 15px;
62
+ font-weight: 700;
63
+ color: #333;
64
+ }
65
+
66
+ .stage-count {
67
+ font-size: 11px;
68
+ color: #999;
69
+ }
70
+
71
+ .stage-sub {
72
+ font-size: 10px;
73
+ color: #999;
74
+ margin-top: 2px;
75
+ }
76
+
77
+ .change-amount,
78
+ .change-count {
79
+ font-weight: 700;
80
+ }
81
+
82
+ .positive {
83
+ color: #16a34a;
84
+ }
85
+
86
+ .negative {
87
+ color: #dc2626;
88
+ }
89
+ }