fit2cloud-ui-plus 0.0.1-beta.0

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 (89) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +16 -0
  3. package/lib/favicon.bmp +0 -0
  4. package/lib/fit2cloud-ui-plus.es.js +3796 -0
  5. package/lib/fit2cloud-ui-plus.umd.js +1 -0
  6. package/package.json +48 -0
  7. package/src/components/filter-bar/FuFilter.vue +175 -0
  8. package/src/components/filter-bar/FuFilterBar.vue +75 -0
  9. package/src/components/filter-bar/FuFilterConditions.vue +29 -0
  10. package/src/components/filter-bar/FuSearchInput.vue +31 -0
  11. package/src/components/filter-bar/filter-components/FuFilterDate.vue +62 -0
  12. package/src/components/filter-bar/filter-components/FuFilterDateTime.vue +65 -0
  13. package/src/components/filter-bar/filter-components/FuFilterOption.vue +38 -0
  14. package/src/components/filter-bar/filter-components/FuFilterSelect.vue +143 -0
  15. package/src/components/filter-bar/index.ts +19 -0
  16. package/src/components/filter-bar/types.ts +31 -0
  17. package/src/components/read-write-switch/FuInputRwSwitch.vue +44 -0
  18. package/src/components/read-write-switch/FuReadWriteSwitch.vue +91 -0
  19. package/src/components/read-write-switch/FuSelectRwSwitch.vue +53 -0
  20. package/src/components/read-write-switch/index.ts +13 -0
  21. package/src/components/search-bar/FuComplexSearch.vue +108 -0
  22. package/src/components/search-bar/FuQuickSearch.vue +43 -0
  23. package/src/components/search-bar/FuSearchBar.vue +165 -0
  24. package/src/components/search-bar/FuSearchBarButton.vue +14 -0
  25. package/src/components/search-bar/FuSearchContions.vue +24 -0
  26. package/src/components/search-bar/index.ts +13 -0
  27. package/src/components/search-bar/store.ts +25 -0
  28. package/src/components/speed-dial/FuSpeedDial.vue +280 -0
  29. package/src/components/speed-dial/FuSpeedDialActionButton.vue +88 -0
  30. package/src/components/speed-dial/FuSpeedDialButton.vue +42 -0
  31. package/src/components/speed-dial/FuSpeedDialItem.vue +88 -0
  32. package/src/components/speed-dial/index.ts +11 -0
  33. package/src/components/split-pane/FuSplitPane.vue +228 -0
  34. package/src/components/split-pane/index.ts +8 -0
  35. package/src/components/steps/FuHorizontalNavigation.vue +18 -0
  36. package/src/components/steps/FuHorizontalSteps.vue +94 -0
  37. package/src/components/steps/FuStep.vue +13 -0
  38. package/src/components/steps/FuSteps.vue +22 -0
  39. package/src/components/steps/FuStepsFooter.ts +79 -0
  40. package/src/components/steps/FuVerticalNavigation.vue +35 -0
  41. package/src/components/steps/FuVerticalSteps.vue +79 -0
  42. package/src/components/steps/Stepper.ts +188 -0
  43. package/src/components/steps/index.ts +11 -0
  44. package/src/components/table/FuTable.vue +145 -0
  45. package/src/components/table/FuTableBody.ts +40 -0
  46. package/src/components/table/FuTablePagination.vue +42 -0
  47. package/src/components/table/index.ts +15 -0
  48. package/src/components/table/table-column-dropdown/FuTableColumnDropdown.vue +102 -0
  49. package/src/components/table/table-column-dropdown/index.ts +7 -0
  50. package/src/components/table/table-column-select/FuTableColumnSelect.vue +22 -0
  51. package/src/components/table/table-column-select/FuTableColumnSelectDialog.vue +99 -0
  52. package/src/components/table/table-column-select/FuTableColumnSelectPopover.vue +80 -0
  53. package/src/components/table/table-column-select/index.ts +8 -0
  54. package/src/components/table/table-column-select/utils.ts +59 -0
  55. package/src/components/table/table-operations/FuTableButton.vue +19 -0
  56. package/src/components/table/table-operations/FuTableMoreButton.vue +52 -0
  57. package/src/components/table/table-operations/FuTableOperations.vue +88 -0
  58. package/src/components/table/table-operations/index.ts +12 -0
  59. package/src/components/tabs/FuTabs.vue +84 -0
  60. package/src/components/tabs/index.ts +8 -0
  61. package/src/components/virtual-scroller/FuVirtualHorizontalScroll.js +96 -0
  62. package/src/components/virtual-scroller/FuVirtualScroll.js +15 -0
  63. package/src/components/virtual-scroller/FuVirtualVerticalScroll.js +95 -0
  64. package/src/components/virtual-scroller/index.js +10 -0
  65. package/src/hooks/index.ts +3 -0
  66. package/src/hooks/use-global-config/index.ts +32 -0
  67. package/src/hooks/use-locale/index.ts +47 -0
  68. package/src/index.ts +19 -0
  69. package/src/locale/index.ts +12 -0
  70. package/src/locale/lang/en.ts +58 -0
  71. package/src/locale/lang/zh-cn.ts +58 -0
  72. package/src/locale/lang/zh-tw.ts +58 -0
  73. package/src/styles/common/config.scss +5 -0
  74. package/src/styles/common/function.scss +81 -0
  75. package/src/styles/common/mixins.scss +85 -0
  76. package/src/styles/common/variables.scss +28 -0
  77. package/src/styles/components/filter-bar.scss +227 -0
  78. package/src/styles/components/read-write-switch.scss +6 -0
  79. package/src/styles/components/search-bar.scss +285 -0
  80. package/src/styles/components/speed-dial.scss +107 -0
  81. package/src/styles/components/split-pane.scss +111 -0
  82. package/src/styles/components/steps.scss +110 -0
  83. package/src/styles/components/table.scss +105 -0
  84. package/src/styles/components/tabs.scss +10 -0
  85. package/src/styles/components/virtual-scroller.scss +24 -0
  86. package/src/styles/index.scss +11 -0
  87. package/src/tools/theme.ts +23 -0
  88. package/src/tools/time.ts +30 -0
  89. package/src/tools/utils.ts +60 -0
@@ -0,0 +1,88 @@
1
+ <template>
2
+ <transition :css="false" @before-enter="beforeEnter" @enter="enter" @leave="leave">
3
+ <div v-if="isActive" class="fu-speed-dial-item" :style="itemSize">
4
+ <slot>
5
+ <fu-speed-dial-action-button :index="index" v-bind="$attrs" />
6
+ </slot>
7
+ </div>
8
+ </transition>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import {
13
+ inject,
14
+ computed
15
+ } from 'vue'
16
+ import FuSpeedDialActionButton from "@/components/speed-dial/FuSpeedDialActionButton.vue";
17
+ defineOptions({ name: "FuSpeedDialItem" });
18
+ const props = defineProps({
19
+ index: {
20
+ type: Number,
21
+ required: true
22
+ },
23
+ })
24
+ const FuSpeedDial = inject('FuSpeedDial')
25
+
26
+ const config = computed(() => {
27
+ return FuSpeedDial.config;
28
+ })
29
+
30
+ const direction = computed(() => {
31
+ return FuSpeedDial.direction;
32
+ })
33
+ const isActive = computed(() => {
34
+ return FuSpeedDial.active;
35
+ })
36
+
37
+ const size = computed(() => {
38
+ return FuSpeedDial.size;
39
+ })
40
+
41
+ const spacing = computed(() => {
42
+ return config.value.item.spacing || 0;
43
+ })
44
+
45
+ const directionPosition = computed(() => {
46
+ if (["top", "left"].includes(direction.value)) {
47
+ return -config.value.fab.size - spacing.value
48
+ }
49
+ return config.value.fab.size + spacing.value
50
+ })
51
+
52
+ const itemSize = computed(() => {
53
+ let size = config.value.fab.size + "px";
54
+ return {
55
+ width: size,
56
+ height: size,
57
+ }
58
+ })
59
+
60
+ function setPosition(el: HTMLElement, position: any) {
61
+ if (["top", "bottom"].includes(direction.value)) {
62
+ el.style.transform = "translateY(" + position + ")"
63
+ } else {
64
+ el.style.transform = "translateX(" + position + ")"
65
+ }
66
+ }
67
+ function beforeEnter(el: HTMLElement) {
68
+ el.style.transition = "all 0.3s"
69
+ el.style.position = "absolute"
70
+ setPosition(el, 0)
71
+ el.style.opacity = "0"
72
+ }
73
+ function enter(el: HTMLElement, done: Function) {
74
+ let position = props.index * directionPosition.value + "px"
75
+ setTimeout(() => {
76
+ setPosition(el, position)
77
+ el.style.opacity = "1"
78
+ done()
79
+ })
80
+ }
81
+ function leave(el: HTMLElement, done: Function) {
82
+ setPosition(el, 0)
83
+ el.style.opacity = "0"
84
+ setTimeout(() => {
85
+ done()
86
+ }, 200)
87
+ }
88
+ </script>
@@ -0,0 +1,11 @@
1
+ import FuSpeedDial from "./FuSpeedDial.vue"
2
+ import FuSpeedDialItem from "./FuSpeedDialItem.vue"
3
+
4
+ import type { App } from 'vue'
5
+
6
+ FuSpeedDial.install = (app: App): void => {
7
+ app.component(FuSpeedDial.name, FuSpeedDial)
8
+ app.component(FuSpeedDialItem.name, FuSpeedDialItem)
9
+ }
10
+
11
+ export default FuSpeedDial;
@@ -0,0 +1,228 @@
1
+ <template>
2
+ <div :style="{ cursor, userSelect }" class="fu-split-pane" ref="outerWrapper">
3
+ <div :class="[`is-${direction}`, 'fu-split-pane__left']"
4
+ :style="{ [attr]: isReverse ? valueAnother : `${usedValue}px`, 'padding-right': padding }">
5
+ <slot :name="isHorizontal ? 'left' : 'top'"></slot>
6
+ </div>
7
+ <div :class="resizerClasses" :style="{ [resizerAttr]: `${usedValue}px`, ...resizerStyle }" @mousedown="onMouseDown"
8
+ @mouseover="hover = true" @mouseleave="hover = false">
9
+ <div class="icon" v-if="resizerType === 'resizer'">
10
+ <slot name="resizer">
11
+ <i class="el-icon-more"></i>
12
+ </slot>
13
+ </div>
14
+ </div>
15
+ <div :class="[`is-${direction}`, 'fu-split-pane__right']"
16
+ :style="{ [attr]: isReverse ? `${usedValue}px` : valueAnother, 'padding-left': padding }">
17
+ <slot :name="isHorizontal ? 'right' : 'bottom'"></slot>
18
+ </div>
19
+ </div>
20
+ </template>
21
+
22
+ <script lang="ts" setup>
23
+ import { ref, onMounted, watch, computed, nextTick, getCurrentInstance } from "vue";
24
+ defineOptions({ name: "FuSplitPane" });
25
+ const props = defineProps({
26
+ min: {
27
+ type: [Number, String],
28
+ default: "10px",
29
+ },
30
+ left: [Number, String],
31
+ right: [Number, String],
32
+ top: [Number, String],
33
+ bottom: [Number, String],
34
+ direction: {
35
+ validator: (val: string) => ["vertical", "horizontal"].includes(val),
36
+ default: "horizontal",
37
+ },
38
+ localKey: String,
39
+ resizable: {
40
+ type: Boolean,
41
+ default: true,
42
+ },
43
+ resizerType: {
44
+ validator: (val: string) => ["resizer", "line"].includes(val),
45
+ default: "resizer",
46
+ },
47
+ resizerClass: String,
48
+ resizerStyle: Object,
49
+ resizerHoverClass: String,
50
+
51
+ });
52
+ const emit = defineEmits(["changeSplit"])
53
+
54
+ const instance = getCurrentInstance()
55
+
56
+ const active = ref(false)
57
+ const usedValue = ref(0)
58
+ const oldValue = ref(0)
59
+ const initOffset = ref(0)
60
+ const hover = ref(false)
61
+
62
+ watch(() => props.left, (newValue, oldValue) => {
63
+ if (newValue !== oldValue) {
64
+ nextTick(() => {
65
+ usedValue.value = defaultValue.value;
66
+ });
67
+ }
68
+ }, { immediate: true })
69
+
70
+ watch(() => props.bottom, (newValue, oldValue) => {
71
+ if (newValue !== oldValue) {
72
+ nextTick(() => {
73
+ usedValue.value = defaultValue.value;
74
+ });
75
+ }
76
+ }, { immediate: true })
77
+
78
+
79
+ const isReverse = computed(() => {
80
+ return props.right || props.bottom;
81
+ })
82
+
83
+ const isHorizontal = computed(() => {
84
+ return props.direction === "horizontal";
85
+ })
86
+
87
+ const userSelect = computed(() => {
88
+ return active.value ? "none" : "" as any
89
+ })
90
+
91
+ const cursor = computed(() => {
92
+ return active.value && props.resizable
93
+ ? isHorizontal.value
94
+ ? "col-resize"
95
+ : "row-resize"
96
+ : "";
97
+ })
98
+
99
+ const outerWrapperSize = computed(() => {
100
+ return instance.refs.outerWrapper[offsetSize.value];
101
+ })
102
+
103
+ const offsetSize = computed(() => {
104
+ return isHorizontal.value ? "offsetWidth" : "offsetHeight";
105
+ })
106
+
107
+ const defaultValue = computed(() => {
108
+ if (isHorizontal.value) {
109
+ return props.left
110
+ ? getMin(percentToValue(props.left))
111
+ : (props.right && getMin(percentToValue(props.right))) ||
112
+ outerWrapperSize.value / 2;
113
+ } else {
114
+ return props.top
115
+ ? getMin(percentToValue(props.top))
116
+ : (props.bottom && getMin(percentToValue(props.bottom))) ||
117
+ outerWrapperSize.value / 2;
118
+ }
119
+ })
120
+ const valueAnother = computed(() => {
121
+ return `calc(100% - ${usedValue.value}px)`;
122
+ })
123
+
124
+ const attr = computed(() => {
125
+ return isHorizontal.value ? "width" : "height";
126
+ })
127
+
128
+ const resizerAttr = computed(() => {
129
+ return isHorizontal.value
130
+ ? isReverse.value
131
+ ? "right"
132
+ : "left"
133
+ : isReverse.value
134
+ ? "bottom"
135
+ : "top" ;
136
+ })
137
+ const saveKey = computed(() => {
138
+ return "Fu-SP-" + props.localKey;
139
+ })
140
+ const resizerClasses = computed(() => {
141
+ const classes = [
142
+ `fu-split-pane__${props.resizerType}`,
143
+ `is-${props.direction}`,
144
+ props.resizable && "is-resizable",
145
+ props.resizerClass,
146
+ hover.value && (props.resizerHoverClass || "hover"),
147
+ ];
148
+ return classes;
149
+ })
150
+ const padding = computed(() => {
151
+ return props.resizerType === "resizer" && isHorizontal.value && "3px" as any;
152
+ })
153
+
154
+
155
+
156
+ function onMouseDown(e: MouseEvent) {
157
+ initOffset.value = isHorizontal.value ? e.pageX : e.pageY;
158
+ oldValue.value = usedValue.value;
159
+ active.value = true;
160
+ document.addEventListener("mousemove", onMouseMove);
161
+ document.addEventListener("mouseup", onMouseUp);
162
+ }
163
+ function onMouseUp() {
164
+ active.value = false;
165
+ document.removeEventListener("mousemove", onMouseMove);
166
+ document.removeEventListener("mouseup", onMouseUp);
167
+ emit("changeSplit", usedValue.value);
168
+ }
169
+ function onMouseMove(e: MouseEvent) {
170
+ if (!props.resizable) return;
171
+ if (active.value) {
172
+ const currentPage = isHorizontal.value ? e.pageX : e.pageY;
173
+ const offset = currentPage - initOffset.value;
174
+ const value = isReverse.value
175
+ ? oldValue.value - offset
176
+ : oldValue.value + offset;
177
+ if (
178
+ value > percentToValue(props.min) &&
179
+ value < outerWrapperSize.value - percentToValue(props.min)
180
+ ) {
181
+ usedValue.value = value;
182
+ writeValue();
183
+ }
184
+ }
185
+ }
186
+ // 百分比换算成像素
187
+ function percentToValue(val: any) {
188
+ const size = instance.refs.outerWrapper[offsetSize.value];
189
+ if (typeof val === "string" && val.includes("%")) {
190
+ return (parseInt(val) / 100) * size;
191
+ } else {
192
+ return parseInt(val);
193
+ }
194
+ }
195
+ // 是否取最小值
196
+ function getMin(val: any) {
197
+ return val < percentToValue(props.min)
198
+ ? percentToValue(props.min)
199
+ : val;
200
+ }
201
+ // localStorage储存数值
202
+ function writeValue() {
203
+ const obj = {
204
+ [resizerAttr.value]: usedValue.value,
205
+ };
206
+ if (props.localKey) {
207
+ localStorage.setItem(saveKey.value, JSON.stringify(obj));
208
+ }
209
+ }
210
+
211
+ function readValue() {
212
+ if (props.localKey) {
213
+ const local = localStorage.getItem(saveKey.value);
214
+ if (local && local[resizerAttr.value]) {
215
+ usedValue.value = parseInt(local) || defaultValue.value;
216
+ } else {
217
+ usedValue.value = defaultValue.value;
218
+ }
219
+ } else {
220
+ usedValue.value = defaultValue.value;
221
+ }
222
+ }
223
+
224
+ onMounted(() => {
225
+ readValue()
226
+ });
227
+ </script>
228
+
@@ -0,0 +1,8 @@
1
+ import FuSplitPane from './FuSplitPane.vue';
2
+
3
+ import type { App } from 'vue'
4
+ FuSplitPane.install = (app: App): void => {
5
+ app.component(FuSplitPane.name, FuSplitPane);
6
+ };
7
+
8
+ export default FuSplitPane;
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <el-steps :active="stepper.index" v-bind="stepper">
3
+ <el-step v-for="(step, index) in steps" :key="index" v-bind="step" @click.native="click(index)"
4
+ :class="disable(index) && 'fu-step--disable'" />
5
+ </el-steps>
6
+ </template>
7
+
8
+ <script lang="ts" setup>
9
+ const props = defineProps({
10
+ stepper: Object,
11
+ steps: Array,
12
+ disable: Function,
13
+ })
14
+ const emit = defineEmits(["active"])
15
+ function click(index: number) {
16
+ (!props.disable(index)) && emit("active", index);
17
+ }
18
+ </script>
@@ -0,0 +1,94 @@
1
+ <script>
2
+ import FuHorizontalNavigation from "./FuHorizontalNavigation";
3
+ import FuStepsFooter from "./FuStepsFooter";
4
+ import { Step, Stepper } from "./Stepper";
5
+
6
+ export default {
7
+ name: "FuHorizontalSteps",
8
+ components: { FuHorizontalNavigation, FuStepsFooter },
9
+ data() {
10
+ return {
11
+ stepper: new Stepper(),
12
+ };
13
+ },
14
+ created() {
15
+ this.stepper.activeSet.add(0);
16
+ },
17
+ provide() {
18
+ return {
19
+ stepper: this.stepper,
20
+ };
21
+ },
22
+ watch: {
23
+ "stepper.index"(value) {
24
+ this.$emit("change", this.stepper.steps[value]);
25
+ },
26
+ },
27
+ computed: {
28
+ heightStyle() {
29
+ return {
30
+ height: parseInt(this.stepper?.height) + "px" || "auto",
31
+ };
32
+ },
33
+ },
34
+ render(h) {
35
+ // let currentNode;
36
+ let steps = [];
37
+ if (this.$slots.default) {
38
+ this.$slots.default.forEach((node, index) => {
39
+ const options = {
40
+ index: index,
41
+ ...node.data.attrs,
42
+ };
43
+ const step = new Step(options);
44
+ steps.push(step);
45
+ // if (this.stepper.isCurrent(index)) {
46
+ // currentNode = node;
47
+ // }
48
+ });
49
+ }
50
+ this.stepper.steps = steps;
51
+ this.stepper = Object.assign(this.stepper, this.$attrs);
52
+ return (
53
+ <div class="fu-steps fu-steps--horizontal">
54
+ <fu-horizontal-navigation
55
+ stepper={this.stepper}
56
+ steps={steps}
57
+ disable={this.disable}
58
+ vOn:active={this.active} />
59
+ <div class="fu-steps__wrapper">
60
+ <div class="fu-steps__container" style={this.heightStyle}>
61
+ <transition name="carousel" mode="out-in">
62
+ {this._l(
63
+ this.$slots.default,
64
+ (item, index) => this.stepper.index === index && item
65
+ )}
66
+ </transition>
67
+ </div>
68
+ </div>
69
+ <div class="fu-steps__footer">
70
+ {this.$slots.footer || <fu-steps-footer vOn:stepperFn={this.$func} />}
71
+ </div>
72
+ </div>
73
+ );
74
+ },
75
+
76
+ methods: {
77
+ active(index) {
78
+ this.stepper.active(index);
79
+ },
80
+ next() {
81
+ this.stepper.next();
82
+ },
83
+ prev() {
84
+ this.stepper.prev();
85
+ },
86
+ disable(index) {
87
+ return !this.stepper.isActive(index);
88
+ },
89
+ $func(name) {
90
+ this.$emit(name);
91
+ },
92
+ },
93
+ };
94
+ </script>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div class="fu-step" v-loading="loading">
3
+ <slot/>
4
+ </div>
5
+ </template>
6
+ <script lang="ts" setup>
7
+ import { inject, computed } from 'vue'
8
+ defineOptions({ name: "FuStep" });
9
+ const stepper = inject('stepper')
10
+ const loading = computed(() => {
11
+ return stepper?.isLoading || false;
12
+ })
13
+ </script>
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import { defineComponent, h } from 'vue'
3
+ import FuHorizontalSteps from "./FuHorizontalSteps";
4
+ import FuVerticalSteps from "./FuVerticalSteps";
5
+
6
+ export default defineComponent({
7
+ name: 'FuSteps',
8
+ props: ["direction"],
9
+ setup(props, context) {
10
+ const { direction } = props
11
+ return () => {
12
+ if (direction === "vertical") {
13
+ return h(FuVerticalSteps, context.attrs, context.slots)
14
+ } else {
15
+ return h(FuHorizontalSteps, context.attrs, context.slots)
16
+ }
17
+ }
18
+ }
19
+
20
+ })
21
+ </script>
22
+
@@ -0,0 +1,79 @@
1
+ import {
2
+ defineComponent,
3
+ h,
4
+ inject,
5
+ ref,
6
+ computed
7
+ } from 'vue'
8
+ export default defineComponent({
9
+ name: "FuStepsFooter",
10
+ setup(props, { emit }) {
11
+ const stepper = inject('stepper')
12
+ const disabledButton = ref(false)
13
+
14
+ const isFirst = computed(() => {
15
+ return stepper.isFirst(stepper.index);
16
+ })
17
+ const isLast = computed(() => {
18
+ return stepper.isLast(stepper.index);
19
+ })
20
+
21
+ const showCancel = computed(() => {
22
+ return stepper.showCancel !== false;
23
+ })
24
+
25
+ const disabled = computed(() => {
26
+ return stepper?.isLoading || disabledButton.value;
27
+ })
28
+ const button = (value: string) => {
29
+ return h(
30
+ 'el-button',
31
+ {
32
+ disabled: disabled,
33
+ size: stepper.buttonSize, // configSize
34
+ onClick: () => clickHandle(value)
35
+ },
36
+ stepper[`${value}ButtonText`]
37
+ );
38
+ };
39
+
40
+ function clickHandle(fnName: string) {
41
+ stepper[fnName]
42
+ ? stepper[fnName]()
43
+ : emit("stepperFn", fnName);
44
+ disabledButton.value = true;
45
+ setTimeout(() => {
46
+ disabledButton.value = false;
47
+ }, 500);
48
+ }
49
+ return () => {
50
+ return h(
51
+ 'div',
52
+ {
53
+ class: `fu-steps__footer--${stepper.footerAlign}`,
54
+ },
55
+ [
56
+ h(
57
+ 'div',
58
+ {
59
+ class: 'fu-steps__footer--block',
60
+ style: 'margin-right:10px'
61
+ },
62
+ showCancel && button("cancel")
63
+ ),
64
+ h(
65
+ 'div',
66
+ {
67
+ class: 'fu-steps__footer--block',
68
+ },
69
+ [
70
+ !isFirst && button("prev"),
71
+ isLast ? button("finish") : button("next")
72
+ ]
73
+ ),
74
+ ]
75
+ );
76
+ }
77
+ }
78
+ })
79
+
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <el-steps :active="stepper.index" v-bind="stepper">
3
+ <el-step v-for="(step, i) in steps" :key="i" v-bind="step" @click="click(i)"
4
+ :class="disable(i) && 'fu-step--disable'">
5
+ <template #description>
6
+ <span>{{ step.description }}</span>
7
+ <el-collapse-transition>
8
+ <div class="fu-steps__container" v-if="i === stepper.index" :style="heightStyle">
9
+ <slot v-bind:step="step"></slot>
10
+ </div>
11
+ </el-collapse-transition>
12
+ </template>
13
+ </el-step>
14
+ </el-steps>
15
+ </template>
16
+
17
+ <script lang="ts" setup>
18
+ import { computed } from "vue";
19
+ const props = defineProps({
20
+ stepper: Object,
21
+ steps: Array,
22
+ disable: Function,
23
+ })
24
+ const emit = defineEmits(["active"])
25
+
26
+ const heightStyle = computed(() => {
27
+ return {
28
+ height: parseInt(props.stepper?.height) + "px" || "auto",
29
+ };
30
+ })
31
+
32
+ function click(index: number) {
33
+ !props.disable(index) && emit("active", index);
34
+ }
35
+ </script>
@@ -0,0 +1,79 @@
1
+ <script>
2
+ import FuVerticalNavigation from "./FuVerticalNavigation.vue";
3
+ import FuStepsFooter from "./FuStepsFooter";
4
+ import { Stepper, Step } from "./Stepper";
5
+
6
+ export default {
7
+ name: "FuVerticalSteps",
8
+ components: { FuVerticalNavigation, FuStepsFooter },
9
+ data() {
10
+ return {
11
+ stepper: new Stepper(),
12
+ };
13
+ },
14
+ created() {
15
+ this.stepper.activeSet.add(0);
16
+ },
17
+ provide() {
18
+ return {
19
+ stepper: this.stepper,
20
+ };
21
+ },
22
+ watch: {
23
+ "stepper.index"(value) {
24
+ this.$emit("change", this.stepper.steps[value]);
25
+ },
26
+ },
27
+ render() {
28
+ let currentNode;
29
+ let steps = [];
30
+ if (this.$slots.default) {
31
+ this.$slots.default.forEach((node, index) => {
32
+ const options = {
33
+ index: index,
34
+ ...node.data.attrs,
35
+ };
36
+ const step = new Step(options);
37
+ steps.push(step);
38
+ if (this.stepper.isCurrent(index)) {
39
+ currentNode = node;
40
+ }
41
+ });
42
+ }
43
+ this.stepper.steps = steps;
44
+ this.stepper = Object.assign(this.stepper, this.$attrs);
45
+ return (
46
+ <div class="fu-steps fu-steps--vertical">
47
+ <fu-vertical-navigation
48
+ stepper={this.stepper}
49
+ steps={steps}
50
+ v-on:active={this.active}
51
+ disable={this.disable} >
52
+ {currentNode}
53
+ </fu-vertical-navigation>
54
+ <div class="fu-steps__footer">
55
+ <fu-steps-footer vOn:stepperFn={this.$func} />
56
+ </div>
57
+ </div>
58
+ );
59
+ },
60
+
61
+ methods: {
62
+ active(index) {
63
+ this.stepper.active(index);
64
+ },
65
+ next() {
66
+ this.stepper.next();
67
+ },
68
+ prev() {
69
+ this.stepper.prev();
70
+ },
71
+ disable(index) {
72
+ return !this.stepper.isActive(index);
73
+ },
74
+ $func(name) {
75
+ this.$emit(name);
76
+ },
77
+ },
78
+ };
79
+ </script>