Skip to content

Commit db0eb45

Browse files
authored
Merge pull request #237 from hmydgz/dev
✨ feat(作业编辑器): 新增 skillTimes 字段 #196
2 parents 202939a + bbfe530 commit db0eb45

File tree

7 files changed

+140
-26
lines changed

7 files changed

+140
-26
lines changed

src/components/ActionCard.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@ import { FCC } from 'types'
66

77
import { CardTitle } from 'components/CardTitle'
88
import { FactItem } from 'components/FactItem'
9-
import type { CopilotDocV1 } from 'models/copilot.schema'
9+
import { CopilotDocV1 } from 'models/copilot.schema'
1010
import { findActionType } from 'models/types'
1111

12-
import {
13-
findOperatorDirection,
14-
findOperatorSkillUsage,
15-
} from '../models/operator'
12+
import { findOperatorDirection, getSkillUsageTitle } from '../models/operator'
1613
import { formatDuration } from '../utils/times'
1714

1815
interface ActionCardProps {
@@ -57,7 +54,7 @@ export const ActionCard: FC<ActionCardProps> = ({
5754
{'skillUsage' in action && (
5855
<FactItem
5956
dense
60-
title={findOperatorSkillUsage(action.skillUsage).title}
57+
title={getSkillUsageTitle(action.skillUsage, action.skillTimes)}
6158
icon="swap-horizontal"
6259
/>
6360
)}

src/components/editor/action/EditorActionAdd.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { CopilotDocV1 } from 'models/copilot.schema'
2929
import { useLevels } from '../../../apis/arknights'
3030
import { findLevelByStageName } from '../../../models/level'
3131
import { EditorOperatorName } from '../operator/EditorOperator'
32+
import { EditorOperatorSkillTimes } from '../operator/EditorOperatorSkillTimes'
3233
import { EditorOperatorSkillUsage } from '../operator/EditorOperatorSkillUsage'
3334
import {
3435
EditorActionPreDelay,
@@ -70,13 +71,15 @@ export const EditorActionAdd = ({
7071
reset,
7172
setError,
7273
handleSubmit,
74+
setValue,
7375
formState: { errors },
7476
} = useForm<CopilotDocV1.Action>({
7577
defaultValues: defaultAction,
7678
})
7779

7880
const type = useWatch({ control, name: 'type' })
7981
const stageName = useWatch({ control: operationControl, name: 'stageName' })
82+
const skillUsage = useWatch({ control, name: 'skillUsage' })
8083

8184
const levels = useLevels().data?.data || []
8285
const level = useMemo(
@@ -104,6 +107,15 @@ export const EditorActionAdd = ({
104107
}
105108
}, [reset, action, type])
106109

110+
useEffect(() => {
111+
setValue(
112+
'skillTimes',
113+
skillUsage === CopilotDocV1.SkillUsageType.ReadyToUseTimes
114+
? (action as CopilotDocV1.ActionSkillUsage)?.skillTimes ?? 1
115+
: undefined,
116+
)
117+
}, [skillUsage])
118+
107119
const onSubmit = handleSubmit((values) => {
108120
if ('name' in values) {
109121
values.name = values.name?.trim()
@@ -222,7 +234,7 @@ export const EditorActionAdd = ({
222234
)}
223235

224236
{type === 'SkillUsage' && (
225-
<div className="flex">
237+
<div className="flex gap-2">
226238
<FormField2
227239
label="技能用法"
228240
field="skillUsage"
@@ -238,6 +250,22 @@ export const EditorActionAdd = ({
238250
defaultValue={0}
239251
/>
240252
</FormField2>
253+
254+
{skillUsage === CopilotDocV1.SkillUsageType.ReadyToUseTimes && (
255+
<FormField2
256+
label="技能使用次数"
257+
field="skillTimes"
258+
error={
259+
(errors as FieldErrors<CopilotDocV1.ActionSkillUsage>)
260+
.skillTimes
261+
}
262+
>
263+
<EditorOperatorSkillTimes
264+
control={control as Control<CopilotDocV1.ActionSkillUsage>}
265+
name="skillTimes"
266+
/>
267+
</FormField2>
268+
)}
241269
</div>
242270
)}
243271

src/components/editor/operator/EditorOperatorItem.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import clsx from 'clsx'
44

55
import type { CopilotDocV1 } from 'models/copilot.schema'
66

7-
import { OPERATORS, findOperatorSkillUsage } from '../../../models/operator'
7+
import { OPERATORS, getSkillUsageTitle } from '../../../models/operator'
88
import { SortableItemProps } from '../../dnd'
99
import { CardDeleteOption, CardEditOption } from '../CardOptions'
1010
import { OperatorAvatar } from './EditorOperator'
@@ -26,7 +26,10 @@ export const EditorOperatorItem = ({
2626
listeners,
2727
}: EditorOperatorItemProps) => {
2828
const id = OPERATORS.find(({ name }) => name === operator.name)?.id
29-
const skillUsage = findOperatorSkillUsage(operator.skillUsage).title
29+
const skillUsage = getSkillUsageTitle(
30+
operator.skillUsage as CopilotDocV1.SkillUsageType,
31+
operator.skillTimes,
32+
)
3033

3134
const skill = `${
3235
[null, '一', '二', '三'][operator.skill ?? 1] ?? '未知'
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useController } from 'react-hook-form'
2+
3+
import { EditorFieldProps } from 'components/editor/EditorFieldProps'
4+
import type { CopilotDocV1 } from 'models/copilot.schema'
5+
6+
import { NumericInput2 } from '../NumericInput2'
7+
8+
export const EditorOperatorSkillTimes = <
9+
T extends CopilotDocV1.Operator | CopilotDocV1.ActionSkillUsage,
10+
>({
11+
name,
12+
control,
13+
...controllerProps
14+
}: EditorFieldProps<T, CopilotDocV1.SkillTimes>) => {
15+
const {
16+
field: { onChange, onBlur, value },
17+
} = useController({
18+
name,
19+
control,
20+
...controllerProps,
21+
})
22+
23+
return (
24+
<NumericInput2
25+
defaultValue={0}
26+
onValueChange={(val) => onChange(Math.min(val, 100))}
27+
onBlur={onBlur}
28+
placeholder="技能使用次数"
29+
value={value ?? ''}
30+
large
31+
min={1}
32+
max={100}
33+
/>
34+
)
35+
}

src/components/editor/operator/EditorPerformerOperator.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import {
1010

1111
import { CardTitle } from 'components/CardTitle'
1212
import { EditorResetButton } from 'components/editor/EditorResetButton'
13-
import type { CopilotDocV1 } from 'models/copilot.schema'
13+
import { CopilotDocV1 } from 'models/copilot.schema'
1414

1515
import { FormField2 } from '../../FormField'
1616
import { EditorOperatorName } from './EditorOperator'
1717
import { EditorOperatorGroupSelect } from './EditorOperatorGroupSelect'
1818
import { EditorOperatorSkill } from './EditorOperatorSkill'
19+
import { EditorOperatorSkillTimes } from './EditorOperatorSkillTimes'
1920
import { EditorOperatorSkillUsage } from './EditorOperatorSkillUsage'
2021

2122
export interface EditorOperatorFormValues extends CopilotDocV1.Operator {
@@ -50,6 +51,7 @@ export const EditorPerformerOperator = ({
5051
handleSubmit,
5152
setError,
5253
formState: { errors },
54+
watch,
5355
} = useForm<EditorOperatorFormValues>()
5456

5557
const findGroupByOperator = (operator?: CopilotDocV1.Operator) =>
@@ -72,6 +74,16 @@ export const EditorPerformerOperator = ({
7274
setValue('groupName', findGroupByOperator(getValues())?.name)
7375
}, [reset, getValues, groups])
7476

77+
const skillUsage = watch('skillUsage')
78+
useEffect(() => {
79+
setValue(
80+
'skillTimes',
81+
skillUsage === CopilotDocV1.SkillUsageType.ReadyToUseTimes
82+
? operator?.skillTimes ?? 1
83+
: undefined,
84+
)
85+
}, [skillUsage, setValue])
86+
7587
const onSubmit: SubmitHandler<EditorOperatorFormValues> = (values) => {
7688
values.name = values.name.trim()
7789
values.groupName = values.groupName?.trim()
@@ -125,13 +137,8 @@ export const EditorPerformerOperator = ({
125137
/>
126138
</FormField2>
127139

128-
<div className="flex flex-col lg:flex-row">
129-
<FormField2
130-
label="技能"
131-
field="skill"
132-
error={errors.skill}
133-
className="mr-2"
134-
>
140+
<div className="flex flex-col lg:flex-row gap-2 flex-wrap">
141+
<FormField2 label="技能" field="skill" error={errors.skill}>
135142
<EditorOperatorSkill control={control} name="skill" />
136143
</FormField2>
137144

@@ -142,6 +149,16 @@ export const EditorPerformerOperator = ({
142149
>
143150
<EditorOperatorSkillUsage control={control} name="skillUsage" />
144151
</FormField2>
152+
153+
{skillUsage === CopilotDocV1.SkillUsageType.ReadyToUseTimes && (
154+
<FormField2
155+
label="技能使用次数"
156+
field="skillTimes"
157+
error={errors.skillTimes}
158+
>
159+
<EditorOperatorSkillTimes control={control} name="skillTimes" />
160+
</FormField2>
161+
)}
145162
</div>
146163

147164
<div className="flex">

src/models/copilot.schema.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export namespace CopilotDocV1 {
6464
export interface ActionSkillUsage extends ActionBase {
6565
skillUsage: SkillUsageType
6666
type: Type.SkillUsage
67+
skillTimes?: number
6768
}
6869

6970
export interface ActionUtil extends ActionBase {
@@ -129,9 +130,32 @@ export namespace CopilotDocV1 {
129130
*/
130131
skill?: number
131132
skillUsage?: SkillUsageType
133+
/**
134+
* 技能使用次数,可选,默认为 1
135+
*/
136+
skillTimes?: number
137+
}
138+
139+
export enum SkillUsageType {
140+
/**
141+
* 不自动使用
142+
*/
143+
None = 0,
144+
/**
145+
* 好了就用
146+
*/
147+
ReadyToUse = 1,
148+
/**
149+
* 好了就用-指定次数
150+
*/
151+
ReadyToUseTimes = 2,
152+
/**
153+
* 自动使用
154+
*/
155+
Automatically = 3,
132156
}
133157

134-
export type SkillUsageType = 0 | 1 | 2 | 3
158+
export type SkillTimes = number
135159

136160
export interface Requirements {
137161
elite?: number

src/models/operator.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { IconName } from '@blueprintjs/core'
22

3-
import type { CopilotDocV1 } from 'models/copilot.schema'
3+
import { CopilotDocV1 } from 'models/copilot.schema'
44

55
import {
66
DetailedSelectChoice,
@@ -11,7 +11,7 @@ import OPERATORS from '../models/generated/operators.json'
1111

1212
export { OPERATORS }
1313

14-
const defaultSkillUsage: CopilotDocV1.SkillUsageType = 0
14+
const defaultSkillUsage = CopilotDocV1.SkillUsageType.None
1515

1616
export type DetailedOperatorSkillUsage = DetailedSelectChoice
1717

@@ -20,29 +20,29 @@ export const operatorSkillUsages: readonly DetailedSelectItem[] = [
2020
type: 'choice',
2121
icon: 'disable',
2222
title: '不自动使用',
23-
value: 0,
23+
value: CopilotDocV1.SkillUsageType.None,
2424
description:
2525
'不由 MAA Copilot 自动开启技能、或干员技能并不需要操作开启(自动触发)。若需要手动开启技能,请添加「使用技能」动作',
2626
},
2727
{
2828
type: 'choice',
2929
icon: 'automatic-updates',
3030
title: '好了就用',
31-
value: 1,
31+
value: CopilotDocV1.SkillUsageType.ReadyToUse,
3232
description: '有多少次用多少次,例如:棘刺 3 技能、桃金娘 1 技能等',
3333
},
3434
{
3535
type: 'choice',
3636
icon: 'circle',
37-
title: '好了就用(一次)',
38-
value: 2,
39-
description: '仅使用一次,例如:山 2 技能',
37+
title: '好了就用(指定次数)',
38+
value: CopilotDocV1.SkillUsageType.ReadyToUseTimes,
39+
description: '默认仅使用一次,例如:山 2 技能',
4040
},
4141
{
4242
type: 'choice',
4343
icon: 'predictive-analysis',
4444
title: '自动判断使用时机',
45-
value: 3,
45+
value: CopilotDocV1.SkillUsageType.Automatically,
4646
description: '(锐意开发中) 画饼.jpg',
4747
disabled: true,
4848
},
@@ -65,6 +65,16 @@ export function findOperatorSkillUsage(
6565
)
6666
}
6767

68+
export function getSkillUsageTitle(
69+
skillUsage: CopilotDocV1.SkillUsageType,
70+
skillTimes?: CopilotDocV1.SkillTimes,
71+
) {
72+
if (skillUsage === CopilotDocV1.SkillUsageType.ReadyToUseTimes) {
73+
return `好了就用(${skillTimes ? `${skillTimes}次` : '指定次数'})`
74+
}
75+
return findOperatorSkillUsage(skillUsage).title
76+
}
77+
6878
export interface OperatorDirection {
6979
icon?: IconName
7080
title: string

0 commit comments

Comments
 (0)