Skip to content

Commit 9a857ec

Browse files
committed
组件结构重构
1 parent 5c92bf9 commit 9a857ec

File tree

9 files changed

+341
-244
lines changed

9 files changed

+341
-244
lines changed

src/App.vue

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,24 @@
1010
/>
1111
<div class="plot-data add-data" @click="graphData.push({})">+ 添加</div>
1212
</div>
13-
<div class="plot-data output">
14-
<span class="output-title">代码</span>
15-
<pre>{{ formatted }}</pre>
16-
</div>
13+
<CodeDisplay :dataArr="cloneDeep(graphData)" />
1714
</div>
18-
<Graph :key="graphKey" :graphData="graphData" ref="graphRef" />
15+
<Graph :key="graphKey" :graphData="cloneDeep(graphData)" ref="graphRef" />
1916
</div>
2017
</template>
2118

2219
<script setup lang="ts">
2320
import Navbar from "./components/nav.vue";
2421
import Graph from "./components/graph.vue";
2522
import DataBlock from "./components/dataBlock.vue";
23+
import CodeDisplay from "./components/codeDisplay.vue";
2624
import type { FunctionPlotDatum } from "function-plot";
27-
import { reactive, ref, watch } from "vue";
28-
import JSON5 from "json5";
29-
import prettier from "prettier/standalone";
30-
import prettierPluginBabel from "prettier/plugins/babel";
31-
import prettierPluginEstree from "prettier/plugins/estree";
25+
import { reactive, ref } from "vue";
3226
import { cloneDeep } from "lodash-es";
3327
3428
const graphRef = ref<InstanceType<typeof Graph>>();
3529
const graphData = reactive<FunctionPlotDatum[]>([{ fn: "x^2" }]);
3630
const graphKey = ref(0);
37-
const formatted = ref("");
38-
watch(
39-
graphData,
40-
() => {
41-
graphKey.value++;
42-
const dataArr = cloneDeep(graphData);
43-
dataArr.forEach((item) => {
44-
if (item.graphType === "text") delete item.fnType;
45-
});
46-
prettier
47-
.format(JSON5.stringify({ data: dataArr }), {
48-
parser: "json5",
49-
printWidth: 40,
50-
plugins: [prettierPluginBabel, prettierPluginEstree],
51-
})
52-
.then((value) => (formatted.value = value));
53-
},
54-
{ immediate: true, deep: true }
55-
);
5631
</script>
5732

5833
<style>
@@ -104,6 +79,7 @@ watch(
10479
padding-top: 10px;
10580
padding-bottom: 10px;
10681
margin-bottom: 50px;
82+
cursor: default;
10783
}
10884
.add-data:hover {
10985
background: var(--c-bk3);
@@ -136,4 +112,5 @@ watch(
136112
overflow: scroll;
137113
user-select: all;
138114
}
115+
139116
</style>

src/assets/vue.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/components/codeDisplay.vue

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<template>
2+
<div class="plot-data output">
3+
<span class="output-title">代码</span>
4+
<pre>{{ formatted }}</pre>
5+
</div>
6+
</template>
7+
8+
<script setup lang="ts">
9+
import JSON5 from "json5";
10+
import prettier from "prettier/standalone";
11+
import prettierPluginBabel from "prettier/plugins/babel";
12+
import prettierPluginEstree from "prettier/plugins/estree";
13+
import { FunctionPlotDatum } from "function-plot";
14+
import { ref, watch } from "vue";
15+
const { dataArr } = defineProps<{ dataArr: FunctionPlotDatum[] }>();
16+
const formatted = ref("");
17+
watch(
18+
() => dataArr,
19+
() => {
20+
dataArr.forEach((item) => {
21+
if (item.graphType === "text") delete item.fnType;
22+
});
23+
prettier
24+
.format(JSON5.stringify({ data: dataArr }), {
25+
parser: "json5",
26+
printWidth: 40,
27+
plugins: [prettierPluginBabel, prettierPluginEstree],
28+
})
29+
.then((value) => (formatted.value = value));
30+
},
31+
{ immediate: true }
32+
);
33+
</script>
34+
35+
<style>
36+
.plot-data.output {
37+
position: absolute;
38+
left: 0;
39+
right: 0;
40+
bottom: 0;
41+
border-top: var(--c-border) 1px solid;
42+
padding: 20px 15px;
43+
height: 260px;
44+
}
45+
.plot-data.output .output-title {
46+
font-size: 20px;
47+
font-weight: bold;
48+
display: block;
49+
margin-bottom: 10px;
50+
}
51+
.plot-data.output pre {
52+
position: absolute;
53+
top: 60px;
54+
bottom: 15px;
55+
left: 15px;
56+
right: 15px;
57+
margin: 0;
58+
overflow: scroll;
59+
user-select: all;
60+
}
61+
</style>

src/components/dataBlock.vue

Lines changed: 23 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</select>
1010
<select v-model="dataItem.graphType" v-if="dataItem.graphType !== 'text'">
1111
<option
12-
v-if="!getFnType(dataItem.fnType).notAllowedInInterval"
12+
v-if="!fnType.notAllowedInInterval"
1313
:value="undefined"
1414
>
1515
{{ graphTypeArr[0].label }}
@@ -33,65 +33,32 @@
3333
</div>
3434

3535
<div class="inputs">
36-
<div v-for="input in getFnType(dataItem.fnType).inputs" class="input-box">
37-
<span class="input-title">{{ input.title }}</span>
38-
<input
39-
type="text"
40-
v-model="dataItem[input.value]"
41-
:placeholder="input.placeholder"
42-
/>
43-
</div>
44-
<template v-if="getFnType(dataItem.fnType).coord">
45-
<div
46-
v-for="input in getFnType(dataItem.fnType).coord?.filter(
47-
({ folded }) => !(folded && blockFolded)
48-
)"
49-
class="input-box coord"
50-
:class="{ optional: input.optional }"
51-
>
52-
<span class="coord-label">{{ input.label }}</span>
53-
<input
54-
type="number"
55-
@input="handleCoordInput(dataItem!, input, 0, $event)"
56-
:placeholder="input.placeholder[0]"
57-
/>
58-
<span class="coord-label">{{ input.sep }}</span>
59-
<input
60-
type="number"
61-
@input="handleCoordInput(dataItem!, input, 1, $event)"
62-
:placeholder="input.placeholder[1]"
63-
/>
64-
<span class="coord-label">{{ input.fin }}</span>
65-
</div>
66-
</template>
67-
68-
<template v-if="getFnType(dataItem.fnType).switches">
69-
<div
70-
v-for="input in getFnType(dataItem.fnType).switches?.filter(
71-
({ folded }) => !(folded && blockFolded)
72-
)"
73-
class="input-box switches"
74-
@click="
75-
dataItem[input.value]
76-
? delete dataItem[input.value]
77-
: (dataItem[input.value] = true)
78-
"
79-
>
80-
<span
81-
class="switch"
82-
:class="dataItem[input.value] ? 'on' : 'off'"
83-
></span>
84-
{{ input.label }}
85-
</div>
86-
</template>
36+
<StrInputs
37+
:dataItem="dataItem"
38+
:fnType="fnType"
39+
:blockFolded="blockFolded"
40+
/>
41+
<CoordInputs
42+
:dataItem="dataItem"
43+
:fnType="fnType"
44+
:blockFolded="blockFolded"
45+
/>
46+
<SwitchInputs
47+
:dataItem="dataItem"
48+
:fnType="fnType"
49+
:blockFolded="blockFolded"
50+
/>
8751
</div>
8852
</div>
8953
</template>
9054
<script setup lang="ts">
9155
import type { FunctionPlotDatum } from "function-plot";
9256
import { fnTypeArr, graphTypeArr, inputTypeArr, getFnType } from "../consts";
93-
import type { CoordType } from "../consts";
94-
import { ref } from "vue";
57+
import { ref, computed } from "vue";
58+
import StrInputs from "./dataBlockInner/strInputs.vue";
59+
import CoordInputs from "./dataBlockInner/coordInputs.vue";
60+
import SwitchInputs from "./dataBlockInner/switchInputs.vue";
61+
9562
const emit = defineEmits(["delete"]);
9663
const dataItem = defineModel<FunctionPlotDatum>();
9764
const block = ref<HTMLDivElement>();
@@ -109,34 +76,14 @@ function fnTypeChange(
10976
} else {
11077
if (dataItem.graphType === "text" || dataItem.fnType === "implicit")
11178
delete dataItem.graphType;
112-
if (getFnType(dataItem.fnType).notAllowedInInterval && !dataItem.graphType)
79+
if (fnType.value.notAllowedInInterval && !dataItem.graphType)
11380
dataItem.graphType = "polyline";
11481
if (dataItem.fnType === "vector") dataItem.vector = [0, 0];
11582
if (block.value)
11683
block.value.querySelectorAll("input").forEach((ele) => (ele.value = ""));
11784
}
11885
}
119-
function handleCoordInput(
120-
dataItem: FunctionPlotDatum,
121-
input: CoordType,
122-
index: 0 | 1,
123-
event: Event
124-
) {
125-
const raw = (<HTMLInputElement>event.target).value;
126-
const newVal = Number(raw);
127-
const key = input.value,
128-
defaultVal = input.defaultVal ?? [0, 0];
129-
if (!dataItem[key]) {
130-
const coord: [number, number] = [...defaultVal];
131-
coord[index] = newVal;
132-
dataItem[key] = coord;
133-
} else {
134-
if (raw !== "") dataItem[key][index] = newVal;
135-
else if (dataItem[key][1 - index] !== defaultVal[1 - index])
136-
dataItem[key][index] = defaultVal[index];
137-
else delete dataItem[key];
138-
}
139-
}
86+
const fnType = computed(() => getFnType(dataItem.value?.fnType));
14087
</script>
14188

14289
<style>
@@ -187,110 +134,4 @@ function handleCoordInput(
187134
.selectors select:focus {
188135
border-color: var(--c-accent);
189136
}
190-
.inputs {
191-
display: flex;
192-
flex-direction: column;
193-
gap: 10px;
194-
}
195-
.inputs .input-box {
196-
position: relative;
197-
display: flex;
198-
}
199-
.inputs .input-box .input-title {
200-
font-style: italic;
201-
letter-spacing: 5px;
202-
font-size: 20px;
203-
font-weight: bold;
204-
margin: auto 5px;
205-
height: fit-content;
206-
}
207-
.inputs input {
208-
color: var(--c-text);
209-
background: var(--c-bk1);
210-
border: var(--c-border) 1px solid;
211-
height: 100%;
212-
font-size: 20px;
213-
border-radius: 5px;
214-
display: block;
215-
width: 100%;
216-
text-indent: 10px;
217-
padding: 10px 0;
218-
}
219-
.inputs :not(.optional) input:placeholder-shown {
220-
border-color: var(--c-red);
221-
}
222-
.inputs input:focus {
223-
border-color: var(--c-accent);
224-
}
225-
226-
.input-box.coord {
227-
display: flex;
228-
}
229-
.input-box.coord.optional {
230-
color: #bbb;
231-
}
232-
.input-box.coord span {
233-
font-size: 18px;
234-
margin: auto 5px;
235-
flex-shrink: 0;
236-
}
237-
.input-box.coord input {
238-
max-width: 8em;
239-
min-width: 3em;
240-
padding: 6px 0;
241-
font-size: 18px;
242-
flex-shrink: 1;
243-
}
244-
245-
.input-box.switches {
246-
align-items: center;
247-
gap: 10px;
248-
padding-left: 5px;
249-
cursor: default;
250-
}
251-
252-
.switch:before,
253-
.switch:after {
254-
position: absolute;
255-
transition: all 0.2s cubic-bezier(0, 0.48, 0.27, 0.98);
256-
}
257-
258-
.switch {
259-
width: 40px;
260-
height: 20px;
261-
border-radius: 5px;
262-
position: relative;
263-
border-radius: 10px;
264-
}
265-
266-
.switch.on {
267-
background: var(--c-accent);
268-
}
269-
270-
.switch.off {
271-
background: var(--c-border);
272-
}
273-
.switch:after {
274-
content: "";
275-
background: #fff;
276-
width: 12px;
277-
height: 12px;
278-
border-radius: 50%;
279-
top: 0;
280-
bottom: 0;
281-
margin: auto 0;
282-
}
283-
.switch.off:after {
284-
left: 4px;
285-
}
286-
.switch.on:after {
287-
left: 24px;
288-
}
289-
.switch:hover {
290-
filter: brightness(110%);
291-
}
292-
293-
.switch:active {
294-
filter: brightness(90%);
295-
}
296137
</style>

0 commit comments

Comments
 (0)