adspecs 0.1.16 → 0.1.19

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 (33) hide show
  1. package/.adspecs/extensions/git/commands/adspecs.git.initialize.md +4 -4
  2. package/.adspecs/extensions/git/extension.yml +1 -1
  3. package/.adspecs/extensions/git/git-config.yml +17 -2
  4. package/.adspecs/extensions.yml +32 -0
  5. package/.adspecs/paths.json +17 -0
  6. package/.adspecs/templates/02-/344/272/247/345/223/201/351/234/200/346/261/202/350/257/264/346/230/216/344/271/246/346/250/241/346/235/277.md +4 -0
  7. package/.adspecs/workflows/adspecs/workflow.yml +5 -4
  8. package/.claude-plugin/marketplace.json +1 -1
  9. package/.claude-plugin/plugin.json +1 -1
  10. package/.qoder-plugin/plugin.json +31 -21
  11. package/README.md +121 -128
  12. package/package.json +2 -2
  13. package/references/antd-front-demo/.env +4 -4
  14. package/references/antd-front-demo/.env.develop +12 -0
  15. package/references/antd-front-demo/.env.production +5 -0
  16. package/references/antd-front-demo/package-lock.json +2 -2
  17. package/references/antd-front-demo/package.json +1 -1
  18. package/scripts/sync-version.js +7 -11
  19. package/skills/adspecs-front-prototype/SKILL.md +405 -0
  20. package/skills/adspecs-git-commit/SKILL.md +23 -8
  21. package/skills/adspecs-git-initialize/SKILL.md +54 -0
  22. package/skills/project-init/SKILL.md +1289 -0
  23. package/src/commands/plugin.js +0 -1
  24. package/src/lib/prompts.js +23 -21
  25. package/references/antd-front-demo/src/pages/aps/coil/components/CoilDrawer.tsx +0 -141
  26. package/references/antd-front-demo/src/pages/aps/coil/index.tsx +0 -209
  27. package/references/antd-front-demo/src/pages/aps/optimization/index.tsx +0 -192
  28. package/references/antd-front-demo/src/pages/aps/order/components/OrderDrawer.tsx +0 -251
  29. package/references/antd-front-demo/src/pages/aps/order/index.tsx +0 -273
  30. package/references/antd-front-demo/src/pages/aps/param/index.tsx +0 -153
  31. package/references/antd-front-demo/src/pages/aps/plan/components/CuttingPlanVisualization.tsx +0 -821
  32. package/references/antd-front-demo/src/pages/aps/plan/index.tsx +0 -254
  33. package/references/antd-front-demo/src/pages/aps/task/index.tsx +0 -190
@@ -1,254 +0,0 @@
1
- import { useRef, useState } from 'react';
2
- import { Space, Tag, Popconfirm, message, Modal, Table, Descriptions } from 'antd';
3
- import { ProTable } from '@ant-design/pro-components';
4
- import type { ActionType, ProColumns } from '@ant-design/pro-components';
5
- import { useTranslation } from 'react-i18next';
6
- import { Access } from '@/components/Access';
7
- import { getPlanPage, deletePlan, confirmPlan, getPlanDetail, exportWorkInstruction } from '@/api/aps/plan';
8
- import type { CuttingPlanVO, PlanDetailVO, SmallCoilVO } from '@/types/aps/plan';
9
- import CuttingPlanVisualization from './components/CuttingPlanVisualization';
10
-
11
- const PlanPage: React.FC = () => {
12
- const { t } = useTranslation('aps/plan');
13
- const { t: tc } = useTranslation('common');
14
- const actionRef = useRef<ActionType>(null);
15
- const [detailOpen, setDetailOpen] = useState(false);
16
- const [detailData, setDetailData] = useState<PlanDetailVO | null>(null);
17
- const [detailLoading, setDetailLoading] = useState(false);
18
-
19
- const handleDelete = (planId: string) => async () => {
20
- await deletePlan(planId);
21
- message.success(tc('success'));
22
- actionRef.current?.reload();
23
- };
24
-
25
- const handleConfirm = (planId: string) => async () => {
26
- await confirmPlan(planId);
27
- message.success(tc('success'));
28
- actionRef.current?.reload();
29
- };
30
-
31
- const handleDetail = async (planId: string) => {
32
- setDetailOpen(true);
33
- setDetailLoading(true);
34
- try {
35
- const res = await getPlanDetail(planId);
36
- setDetailData(res.data);
37
- } finally {
38
- setDetailLoading(false);
39
- }
40
- };
41
-
42
- const handleExport = async (planId: string) => {
43
- await exportWorkInstruction(planId, 'excel');
44
- message.success(tc('success'));
45
- };
46
-
47
- const smallCoilColumns = [
48
- {
49
- title: t('smallCoilId'),
50
- dataIndex: 'smallCoilId',
51
- key: 'smallCoilId',
52
- width: 120,
53
- },
54
- {
55
- title: t('width'),
56
- dataIndex: 'width',
57
- key: 'width',
58
- width: 100,
59
- },
60
- {
61
- title: t('length'),
62
- dataIndex: 'length',
63
- key: 'length',
64
- width: 100,
65
- },
66
- {
67
- title: t('weight'),
68
- dataIndex: 'weight',
69
- key: 'weight',
70
- width: 100,
71
- },
72
- {
73
- title: t('outerDiameter'),
74
- dataIndex: 'outerDiameter',
75
- key: 'outerDiameter',
76
- width: 120,
77
- },
78
- {
79
- title: t('orderId'),
80
- dataIndex: 'orderId',
81
- key: 'orderId',
82
- width: 120,
83
- render: (orderId: string | undefined) => orderId || <Tag>{t('unassigned')}</Tag>,
84
- },
85
- {
86
- title: t('region'),
87
- dataIndex: 'region',
88
- key: 'region',
89
- width: 80,
90
- },
91
- ];
92
-
93
- const columns: ProColumns<CuttingPlanVO>[] = [
94
- {
95
- title: t('planId'),
96
- dataIndex: 'planId',
97
- ellipsis: true,
98
- width: 180,
99
- },
100
- {
101
- title: t('coilId'),
102
- dataIndex: 'coilId',
103
- width: 100,
104
- },
105
- {
106
- title: t('coilAlloy'),
107
- dataIndex: 'coilAlloy',
108
- search: false,
109
- width: 80,
110
- },
111
- {
112
- title: t('coilTemper'),
113
- dataIndex: 'coilTemper',
114
- search: false,
115
- width: 80,
116
- },
117
- {
118
- title: t('coilWidth'),
119
- dataIndex: 'coilWidth',
120
- search: false,
121
- width: 100,
122
- },
123
- {
124
- title: t('coilWeight'),
125
- dataIndex: 'coilWeight',
126
- search: false,
127
- width: 100,
128
- },
129
- {
130
- title: t('totalCuts'),
131
- dataIndex: 'totalCuts',
132
- search: false,
133
- width: 100,
134
- },
135
- {
136
- title: t('theoreticalUtilization'),
137
- dataIndex: 'theoreticalUtilization',
138
- search: false,
139
- width: 140,
140
- render: (_, record) => `${record.theoreticalUtilization.toFixed(2)}%`,
141
- },
142
- {
143
- title: t('score'),
144
- dataIndex: 'score',
145
- search: false,
146
- width: 100,
147
- render: (_, record) => record.score.toFixed(4),
148
- },
149
- {
150
- title: t('createTime'),
151
- dataIndex: 'createTime',
152
- search: false,
153
- width: 180,
154
- },
155
- {
156
- title: tc('operation'),
157
- key: 'action',
158
- fixed: 'right',
159
- search: false,
160
- width: 250,
161
- render: (_, record) => (
162
- <Space>
163
- <Access code="aps:plan:query">
164
- <a onClick={() => handleDetail(record.planId)}>{t('actions.detail')}</a>
165
- </Access>
166
- <Access code="aps:plan:confirm">
167
- <Popconfirm title={t('confirmConfirm')} onConfirm={handleConfirm(record.planId)}>
168
- <a>{t('actions.confirm')}</a>
169
- </Popconfirm>
170
- </Access>
171
- <Access code="aps:plan:export">
172
- <a onClick={() => handleExport(record.planId)}>{t('actions.export')}</a>
173
- </Access>
174
- <Access code="aps:plan:delete">
175
- <Popconfirm title={t('deleteConfirm')} onConfirm={handleDelete(record.planId)}>
176
- <a style={{ color: '#ff4d4f' }}>{t('actions.delete')}</a>
177
- </Popconfirm>
178
- </Access>
179
- </Space>
180
- ),
181
- },
182
- ];
183
-
184
- return (
185
- <>
186
- <ProTable<CuttingPlanVO>
187
- columns={columns}
188
- actionRef={actionRef}
189
- rowKey="planId"
190
- headerTitle={t('title')}
191
- request={async (params) => {
192
- const { current, pageSize, ...rest } = params;
193
- const { data } = await getPlanPage({
194
- pageNo: current!,
195
- pageSize: pageSize!,
196
- ...rest,
197
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
198
- } as any);
199
- return { data: data.list, total: data.total, success: true };
200
- }}
201
- pagination={{ defaultPageSize: 10, showSizeChanger: true }}
202
- scroll={{ x: 1400 }}
203
- />
204
-
205
- <Modal
206
- title={t('actions.detail')}
207
- open={detailOpen}
208
- onCancel={() => setDetailOpen(false)}
209
- footer={null}
210
- width={1200}
211
- >
212
- {detailData && (
213
- <>
214
- <Descriptions bordered column={2} size="small" style={{ marginBottom: 16 }}>
215
- <Descriptions.Item label={t('planId')}>{detailData.planId}</Descriptions.Item>
216
- <Descriptions.Item label={t('coilId')}>{detailData.coilId}</Descriptions.Item>
217
- <Descriptions.Item label={t('coilAlloy')}>{detailData.coilAlloy}</Descriptions.Item>
218
- <Descriptions.Item label={t('coilTemper')}>{detailData.coilTemper}</Descriptions.Item>
219
- <Descriptions.Item label={t('coilWidth')}>{detailData.coilWidth} mm</Descriptions.Item>
220
- <Descriptions.Item label={t('coilWeight')}>{detailData.coilWeight} 吨</Descriptions.Item>
221
- <Descriptions.Item label={t('totalCuts')}>{detailData.totalCuts}</Descriptions.Item>
222
- <Descriptions.Item label={t('theoreticalUtilization')}>
223
- {detailData.theoreticalUtilization.toFixed(2)}%
224
- </Descriptions.Item>
225
- <Descriptions.Item label={t('score')}>{detailData.score.toFixed(4)}</Descriptions.Item>
226
- <Descriptions.Item label={t('createTime')}>{detailData.createTime}</Descriptions.Item>
227
- <Descriptions.Item label={t('verticalCuts')} span={2}>
228
- {detailData.verticalCuts}
229
- </Descriptions.Item>
230
- <Descriptions.Item label={t('horizontalCuts')} span={2}>
231
- {detailData.horizontalCuts}
232
- </Descriptions.Item>
233
- </Descriptions>
234
-
235
- <CuttingPlanVisualization plan={detailData} />
236
-
237
- <h4 style={{ marginTop: 16 }}>{t('smallCoils')}</h4>
238
- <Table<SmallCoilVO>
239
- columns={smallCoilColumns}
240
- dataSource={detailData.smallCoils}
241
- rowKey="smallCoilId"
242
- size="small"
243
- pagination={false}
244
- scroll={{ x: 800 }}
245
- loading={detailLoading}
246
- />
247
- </>
248
- )}
249
- </Modal>
250
- </>
251
- );
252
- };
253
-
254
- export default PlanPage;
@@ -1,190 +0,0 @@
1
- import { useRef } from 'react';
2
- import { Space, Tag, Popconfirm, Progress, message } from 'antd';
3
- import { useNavigate } from 'react-router-dom';
4
- import { ProTable } from '@ant-design/pro-components';
5
- import type { ActionType, ProColumns } from '@ant-design/pro-components';
6
- import { useTranslation } from 'react-i18next';
7
- import { Access } from '@/components/Access';
8
- import { getTaskPage, cancelTask, resumeTask, deleteTask } from '@/api/aps/task';
9
- import type { OptimizationTaskVO } from '@/types/aps/task';
10
- import { TASK_STATUS, TASK_TYPE, TASK_PHASE } from '@/types/aps/task';
11
-
12
- const TaskPage: React.FC = () => {
13
- const { t } = useTranslation('aps/task');
14
- const { t: tc } = useTranslation('common');
15
- const actionRef = useRef<ActionType>(null);
16
- const navigate = useNavigate();
17
-
18
- const handleCancel = (taskId: string) => async () => {
19
- await cancelTask(taskId);
20
- message.success(tc('success'));
21
- actionRef.current?.reload();
22
- };
23
-
24
- const handleResume = (taskId: string) => async () => {
25
- await resumeTask(taskId);
26
- message.success(tc('success'));
27
- actionRef.current?.reload();
28
- };
29
-
30
- const handleDelete = (taskId: string) => async () => {
31
- await deleteTask(taskId);
32
- message.success(tc('success'));
33
- actionRef.current?.reload();
34
- };
35
-
36
- const columns: ProColumns<OptimizationTaskVO>[] = [
37
- {
38
- title: t('taskId'),
39
- dataIndex: 'taskId',
40
- ellipsis: true,
41
- width: 180,
42
- },
43
- {
44
- title: t('taskType'),
45
- dataIndex: 'taskType',
46
- valueType: 'select',
47
- valueEnum: {
48
- SINGLE_COIL: { text: TASK_TYPE.SINGLE_COIL.label },
49
- GLOBAL_OPTIMIZATION: { text: TASK_TYPE.GLOBAL_OPTIMIZATION.label },
50
- },
51
- width: 120,
52
- render: (_, record) => {
53
- const item = TASK_TYPE[record.taskType as keyof typeof TASK_TYPE];
54
- return item ? <Tag color={item.color}>{item.label}</Tag> : '-';
55
- },
56
- },
57
- {
58
- title: t('status'),
59
- dataIndex: 'status',
60
- valueType: 'select',
61
- valueEnum: {
62
- PENDING: { text: TASK_STATUS.PENDING.label, status: 'Default' },
63
- RUNNING: { text: TASK_STATUS.RUNNING.label, status: 'Processing' },
64
- PAUSED: { text: TASK_STATUS.PAUSED.label, status: 'Warning' },
65
- COMPLETED: { text: TASK_STATUS.COMPLETED.label, status: 'Success' },
66
- FAILED: { text: TASK_STATUS.FAILED.label, status: 'Error' },
67
- CANCELLED: { text: TASK_STATUS.CANCELLED.label, status: 'Default' },
68
- },
69
- width: 100,
70
- render: (_, record) => {
71
- const item = TASK_STATUS[record.status as keyof typeof TASK_STATUS];
72
- return item ? <Tag color={item.color}>{item.label}</Tag> : '-';
73
- },
74
- },
75
- {
76
- title: t('progress'),
77
- dataIndex: 'progress',
78
- search: false,
79
- width: 150,
80
- render: (_, record) => (
81
- <Progress
82
- percent={record.progress}
83
- size="small"
84
- status={
85
- record.status === 'RUNNING' ? 'active' :
86
- record.status === 'COMPLETED' ? 'success' :
87
- record.status === 'FAILED' ? 'exception' : 'normal'
88
- }
89
- />
90
- ),
91
- },
92
- {
93
- title: t('currentPhase'),
94
- dataIndex: 'currentPhase',
95
- search: false,
96
- width: 120,
97
- render: (_, record) => {
98
- if (!record.currentPhase) return '-';
99
- const item = TASK_PHASE[record.currentPhase as keyof typeof TASK_PHASE];
100
- return item ? <Tag color={item.color}>{item.label}</Tag> : '-';
101
- },
102
- },
103
- {
104
- title: t('progressDesc'),
105
- dataIndex: 'progressDesc',
106
- search: false,
107
- ellipsis: true,
108
- width: 180,
109
- },
110
- {
111
- title: t('errorMessage'),
112
- dataIndex: 'errorMessage',
113
- search: false,
114
- ellipsis: true,
115
- width: 200,
116
- render: (_, record) => record.errorMessage || '-',
117
- },
118
- {
119
- title: t('createdBy'),
120
- dataIndex: 'createdBy',
121
- search: false,
122
- width: 100,
123
- },
124
- {
125
- title: t('createTime'),
126
- dataIndex: 'createTime',
127
- search: false,
128
- width: 180,
129
- },
130
- {
131
- title: tc('operation'),
132
- key: 'action',
133
- fixed: 'right',
134
- search: false,
135
- width: 200,
136
- render: (_, record) => (
137
- <Space>
138
- {(record.status === 'RUNNING' || record.status === 'PENDING') && (
139
- <Access code="aps:task:cancel">
140
- <Popconfirm title={t('cancelConfirm')} onConfirm={handleCancel(record.taskId)}>
141
- <a>{t('actions.cancel')}</a>
142
- </Popconfirm>
143
- </Access>
144
- )}
145
- {(record.status === 'FAILED' || record.status === 'CANCELLED' || record.status === 'PAUSED') && (
146
- <Access code="aps:task:resume">
147
- <Popconfirm title={t('resumeConfirm')} onConfirm={handleResume(record.taskId)}>
148
- <a>{t('actions.resume')}</a>
149
- </Popconfirm>
150
- </Access>
151
- )}
152
- {record.status === 'COMPLETED' && record.resultRef && (
153
- <Access code="aps:plan:query">
154
- <a onClick={() => navigate(`/aps/plan?planId=${record.resultRef}`)}>{t('actions.viewResult')}</a>
155
- </Access>
156
- )}
157
- <Access code="aps:task:delete">
158
- <Popconfirm title={t('deleteConfirm')} onConfirm={handleDelete(record.taskId)}>
159
- <a style={{ color: '#ff4d4f' }}>{t('actions.delete')}</a>
160
- </Popconfirm>
161
- </Access>
162
- </Space>
163
- ),
164
- },
165
- ];
166
-
167
- return (
168
- <ProTable<OptimizationTaskVO>
169
- columns={columns}
170
- actionRef={actionRef}
171
- rowKey="taskId"
172
- headerTitle={t('title')}
173
- request={async (params) => {
174
- const { current, pageSize, ...rest } = params;
175
- const { data } = await getTaskPage({
176
- pageNo: current!,
177
- pageSize: pageSize!,
178
- ...rest,
179
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
180
- } as any);
181
- return { data: data.list, total: data.total, success: true };
182
- }}
183
- pagination={{ defaultPageSize: 10, showSizeChanger: true }}
184
- scroll={{ x: 1600 }}
185
- polling={5000} // Auto-refresh every 5 seconds for running tasks
186
- />
187
- );
188
- };
189
-
190
- export default TaskPage;