Commit bd2039accbc99cdfddbea62a63c3704e58034873

Authored by Vben
1 parent 3b2c40be

refactor: remove useExpose

CHANGELOG.zh_CN.md
1 ## Wip 1 ## Wip
2 2
  3 +### ✨ Refactor
  4 +
  5 +- 移除`useExpose`,使用组件自身提供的`expose`代替
  6 +
3 ### ✨ Features 7 ### ✨ Features
4 8
5 - **CropperImage** `Cropper` 头像裁剪新增圆形裁剪功能 9 - **CropperImage** `Cropper` 头像裁剪新增圆形裁剪功能
src/components/Table/src/BasicTable.vue
@@ -59,7 +59,6 @@ @@ -59,7 +59,6 @@
59 import { createTableContext } from './hooks/useTableContext'; 59 import { createTableContext } from './hooks/useTableContext';
60 import { useTableFooter } from './hooks/useTableFooter'; 60 import { useTableFooter } from './hooks/useTableFooter';
61 import { useTableForm } from './hooks/useTableForm'; 61 import { useTableForm } from './hooks/useTableForm';
62 - import { useExpose } from '/@/hooks/core/useExpose';  
63 import { useDesign } from '/@/hooks/web/useDesign'; 62 import { useDesign } from '/@/hooks/web/useDesign';
64 63
65 import { omit } from 'lodash-es'; 64 import { omit } from 'lodash-es';
@@ -91,7 +90,7 @@ @@ -91,7 +90,7 @@
91 'change', 90 'change',
92 'columns-change', 91 'columns-change',
93 ], 92 ],
94 - setup(props, { attrs, emit, slots }) { 93 + setup(props, { attrs, emit, slots, expose }) {
95 const tableElRef = ref<ComponentRef>(null); 94 const tableElRef = ref<ComponentRef>(null);
96 const tableData = ref<Recordable[]>([]); 95 const tableData = ref<Recordable[]>([]);
97 96
@@ -290,7 +289,7 @@ @@ -290,7 +289,7 @@
290 }; 289 };
291 createTableContext({ ...tableAction, wrapRef, getBindValues }); 290 createTableContext({ ...tableAction, wrapRef, getBindValues });
292 291
293 - useExpose<TableActionType>(tableAction); 292 + expose(tableAction);
294 293
295 emit('register', tableAction, formActions); 294 emit('register', tableAction, formActions);
296 295
src/components/Tree/src/Tree.vue
@@ -25,7 +25,6 @@ @@ -25,7 +25,6 @@
25 25
26 import { useTree } from './useTree'; 26 import { useTree } from './useTree';
27 import { useContextMenu } from '/@/hooks/web/useContextMenu'; 27 import { useContextMenu } from '/@/hooks/web/useContextMenu';
28 - import { useExpose } from '/@/hooks/core/useExpose';  
29 import { useDesign } from '/@/hooks/web/useDesign'; 28 import { useDesign } from '/@/hooks/web/useDesign';
30 29
31 import { basicProps } from './props'; 30 import { basicProps } from './props';
@@ -44,7 +43,7 @@ @@ -44,7 +43,7 @@
44 inheritAttrs: false, 43 inheritAttrs: false,
45 props: basicProps, 44 props: basicProps,
46 emits: ['update:expandedKeys', 'update:selectedKeys', 'update:value', 'change', 'check'], 45 emits: ['update:expandedKeys', 'update:selectedKeys', 'update:value', 'change', 'check'],
47 - setup(props, { attrs, slots, emit }) { 46 + setup(props, { attrs, slots, emit, expose }) {
48 const state = reactive<State>({ 47 const state = reactive<State>({
49 checkStrictly: props.checkStrictly, 48 checkStrictly: props.checkStrictly,
50 expandedKeys: props.expandedKeys || [], 49 expandedKeys: props.expandedKeys || [],
@@ -277,7 +276,7 @@ @@ -277,7 +276,7 @@
277 }, 276 },
278 }; 277 };
279 278
280 - useExpose<TreeActionType>(instance); 279 + expose(instance);
281 280
282 function renderAction(node: TreeItem) { 281 function renderAction(node: TreeItem) {
283 const { actionList } = props; 282 const { actionList } = props;
src/components/Verify/index.ts
1 -import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; 1 +import { withInstall } from '/@/utils/index';
  2 +import basicDragVerify from './src/DragVerify.vue';
  3 +import rotateDragVerify from './src/ImgRotate.vue';
2 4
3 -export const BasicDragVerify = createAsyncComponent(() => import('./src/DragVerify'));  
4 -export const RotateDragVerify = createAsyncComponent(() => import('./src/ImgRotate'));  
5 -  
6 -export * from './src/types'; 5 +export const BasicDragVerify = withInstall(basicDragVerify);
  6 +export const RotateDragVerify = withInstall(rotateDragVerify);
  7 +export * from './src/typing';
src/components/Verify/src/DragVerify.less deleted 100644 → 0
1 -@radius: 4px;  
2 -  
3 -.darg-verify {  
4 - position: relative;  
5 - overflow: hidden;  
6 - text-align: center;  
7 - background-color: rgb(238, 238, 238);  
8 - border: 1px solid #ddd;  
9 - border-radius: @radius;  
10 -  
11 - &-bar {  
12 - position: absolute;  
13 - width: 0;  
14 - height: 36px;  
15 - background-color: @success-color;  
16 - border-radius: @radius;  
17 -  
18 - &.to-left {  
19 - width: 0 !important;  
20 - transition: width 0.3s;  
21 - }  
22 - }  
23 -  
24 - &-content {  
25 - position: absolute;  
26 - top: 0;  
27 - font-size: 12px;  
28 - -webkit-text-size-adjust: none;  
29 - background-color: -webkit-gradient(  
30 - linear,  
31 - left top,  
32 - right top,  
33 - color-stop(0, #333),  
34 - color-stop(0.4, #333),  
35 - color-stop(0.5, #fff),  
36 - color-stop(0.6, #333),  
37 - color-stop(1, #333)  
38 - );  
39 - animation: slidetounlock 3s infinite;  
40 - -webkit-background-clip: text;  
41 - -moz-user-select: none;  
42 - -webkit-user-select: none;  
43 - -o-user-select: none;  
44 - -ms-user-select: none;  
45 - user-select: none;  
46 - -webkit-text-fill-color: transparent;  
47 -  
48 - &.success {  
49 - -webkit-text-fill-color: @white;  
50 - }  
51 -  
52 - & > * {  
53 - -webkit-text-fill-color: #333;  
54 - }  
55 - }  
56 -  
57 - &-action {  
58 - position: absolute;  
59 - top: 0;  
60 - left: 0;  
61 - display: flex;  
62 - cursor: move;  
63 - background-color: @white;  
64 - border-radius: @radius;  
65 - justify-content: center;  
66 - align-items: center;  
67 -  
68 - &__icon {  
69 - cursor: inherit;  
70 - }  
71 -  
72 - &.to-left {  
73 - left: 0 !important;  
74 - transition: left 0.3s;  
75 - }  
76 - }  
77 -}  
78 -  
79 -@-webkit-keyframes slidetounlock {  
80 - 0% {  
81 - background-position: -120px 0;  
82 - }  
83 -  
84 - 100% {  
85 - background-position: 120px 0;  
86 - }  
87 -}  
src/components/Verify/src/DragVerify.tsx renamed to src/components/Verify/src/DragVerify.vue
1 -import { defineComponent, ref, computed, unref, reactive, watch, watchEffect } from 'vue';  
2 -import { useTimeoutFn } from '/@/hooks/core/useTimeout';  
3 -import { useEventListener } from '/@/hooks/event/useEventListener';  
4 -import { basicProps } from './props';  
5 -import { getSlot } from '/@/utils/helper/tsxHelper';  
6 -import './DragVerify.less';  
7 -import { CheckOutlined, DoubleRightOutlined } from '@ant-design/icons-vue';  
8 -import type { DragVerifyActionType } from './types';  
9 -import { useExpose } from '/@/hooks/core/useExpose';  
10 -export default defineComponent({  
11 - name: 'BaseDargVerify',  
12 - props: basicProps,  
13 - emits: ['success', 'update:value', 'change', 'start', 'move', 'end'],  
14 - setup(props, { emit, slots }) {  
15 - const state = reactive({  
16 - isMoving: false,  
17 - isPassing: false,  
18 - moveDistance: 0,  
19 - toLeft: false,  
20 - startTime: 0,  
21 - endTime: 0,  
22 - });  
23 -  
24 - const wrapElRef = ref<HTMLDivElement | null>(null);  
25 - const barElRef = ref<HTMLDivElement | null>(null);  
26 - const contentElRef = ref<HTMLDivElement | null>(null);  
27 - const actionElRef = ref<HTMLDivElement | null>(null);  
28 -  
29 - watch(  
30 - () => state.isPassing,  
31 - (isPassing) => {  
32 - if (isPassing) {  
33 - const { startTime, endTime } = state;  
34 - const time = (endTime - startTime) / 1000;  
35 - emit('success', { isPassing, time: time.toFixed(1) });  
36 - emit('update:value', isPassing);  
37 - emit('change', isPassing);  
38 - }  
39 - }  
40 - );  
41 -  
42 - watchEffect(() => {  
43 - state.isPassing = !!props.value;  
44 - });  
45 -  
46 - const getActionStyleRef = computed(() => {  
47 - const { height, actionStyle } = props;  
48 - const h = `${parseInt(height as string)}px`;  
49 - return {  
50 - left: 0,  
51 - width: h,  
52 - height: h,  
53 - ...actionStyle,  
54 - };  
55 - });  
56 - const getWrapStyleRef = computed(() => {  
57 - const { height, width, circle, wrapStyle } = props;  
58 - const h = parseInt(height as string);  
59 - const w = `${parseInt(width as string)}px`;  
60 - return {  
61 - width: w,  
62 - height: `${h}px`,  
63 - lineHeight: `${h}px`,  
64 - borderRadius: circle ? h / 2 + 'px' : 0,  
65 - ...wrapStyle,  
66 - };  
67 - });  
68 -  
69 - const getBarStyleRef = computed(() => {  
70 - const { height, circle, barStyle } = props;  
71 - const h = parseInt(height as string);  
72 - return {  
73 - height: `${h}px`,  
74 - borderRadius: circle ? h / 2 + 'px 0 0 ' + h / 2 + 'px' : 0,  
75 - ...barStyle,  
76 - };  
77 - }); 1 +<script lang="tsx">
  2 + import { defineComponent, ref, computed, unref, reactive, watch, watchEffect } from 'vue';
  3 + import { useTimeoutFn } from '/@/hooks/core/useTimeout';
  4 + import { useEventListener } from '/@/hooks/event/useEventListener';
  5 + import { basicProps } from './props';
  6 + import { getSlot } from '/@/utils/helper/tsxHelper';
  7 + import { CheckOutlined, DoubleRightOutlined } from '@ant-design/icons-vue';
78 8
79 - const getContentStyleRef = computed(() => {  
80 - const { height, width, contentStyle } = props;  
81 - const h = `${parseInt(height as string)}px`;  
82 - const w = `${parseInt(width as string)}px`; 9 + export default defineComponent({
  10 + name: 'BaseDargVerify',
  11 + props: basicProps,
  12 + emits: ['success', 'update:value', 'change', 'start', 'move', 'end'],
  13 + setup(props, { emit, slots, expose }) {
  14 + const state = reactive({
  15 + isMoving: false,
  16 + isPassing: false,
  17 + moveDistance: 0,
  18 + toLeft: false,
  19 + startTime: 0,
  20 + endTime: 0,
  21 + });
83 22
84 - return {  
85 - height: h,  
86 - width: w,  
87 - ...contentStyle,  
88 - };  
89 - }); 23 + const wrapElRef = ref<HTMLDivElement | null>(null);
  24 + const barElRef = ref<HTMLDivElement | null>(null);
  25 + const contentElRef = ref<HTMLDivElement | null>(null);
  26 + const actionElRef = ref<HTMLDivElement | null>(null);
90 27
91 - function getEventPageX(e: MouseEvent | TouchEvent) {  
92 - return (e as MouseEvent).pageX || (e as TouchEvent).touches[0].pageX;  
93 - } 28 + useEventListener({
  29 + el: document,
  30 + name: 'mouseup',
  31 + listener: () => {
  32 + if (state.isMoving) {
  33 + resume();
  34 + }
  35 + },
  36 + });
94 37
95 - useEventListener({  
96 - el: document,  
97 - name: 'mouseup',  
98 - listener: () => {  
99 - if (state.isMoving) {  
100 - resume(); 38 + const getActionStyleRef = computed(() => {
  39 + const { height, actionStyle } = props;
  40 + const h = `${parseInt(height as string)}px`;
  41 + return {
  42 + left: 0,
  43 + width: h,
  44 + height: h,
  45 + ...actionStyle,
  46 + };
  47 + });
  48 +
  49 + const getWrapStyleRef = computed(() => {
  50 + const { height, width, circle, wrapStyle } = props;
  51 + const h = parseInt(height as string);
  52 + const w = `${parseInt(width as string)}px`;
  53 + return {
  54 + width: w,
  55 + height: `${h}px`,
  56 + lineHeight: `${h}px`,
  57 + borderRadius: circle ? h / 2 + 'px' : 0,
  58 + ...wrapStyle,
  59 + };
  60 + });
  61 +
  62 + const getBarStyleRef = computed(() => {
  63 + const { height, circle, barStyle } = props;
  64 + const h = parseInt(height as string);
  65 + return {
  66 + height: `${h}px`,
  67 + borderRadius: circle ? h / 2 + 'px 0 0 ' + h / 2 + 'px' : 0,
  68 + ...barStyle,
  69 + };
  70 + });
  71 +
  72 + const getContentStyleRef = computed(() => {
  73 + const { height, width, contentStyle } = props;
  74 + const h = `${parseInt(height as string)}px`;
  75 + const w = `${parseInt(width as string)}px`;
  76 +
  77 + return {
  78 + height: h,
  79 + width: w,
  80 + ...contentStyle,
  81 + };
  82 + });
  83 +
  84 + watch(
  85 + () => state.isPassing,
  86 + (isPassing) => {
  87 + if (isPassing) {
  88 + const { startTime, endTime } = state;
  89 + const time = (endTime - startTime) / 1000;
  90 + emit('success', { isPassing, time: time.toFixed(1) });
  91 + emit('update:value', isPassing);
  92 + emit('change', isPassing);
  93 + }
101 } 94 }
102 - },  
103 - });  
104 - function handleDragStart(e: MouseEvent | TouchEvent) {  
105 - if (state.isPassing) {  
106 - return; 95 + );
  96 +
  97 + watchEffect(() => {
  98 + state.isPassing = !!props.value;
  99 + });
  100 +
  101 + function getEventPageX(e: MouseEvent | TouchEvent) {
  102 + return (e as MouseEvent).pageX || (e as TouchEvent).touches[0].pageX;
107 } 103 }
108 104
109 - const actionEl = unref(actionElRef);  
110 - if (!actionEl) return;  
111 - emit('start', e);  
112 - state.moveDistance = getEventPageX(e) - parseInt(actionEl.style.left.replace('px', ''), 10);  
113 - state.startTime = new Date().getTime();  
114 - state.isMoving = true;  
115 - }  
116 - function getOffset(el: HTMLDivElement) {  
117 - const actionWidth = parseInt(el.style.width);  
118 - const { width } = props;  
119 - const widthNum = parseInt(width as string);  
120 - const offset = widthNum - actionWidth - 6;  
121 - return { offset, widthNum, actionWidth };  
122 - }  
123 - function handleDragMoving(e: MouseEvent | TouchEvent) {  
124 - const { isMoving, moveDistance } = state;  
125 - if (isMoving) { 105 + function handleDragStart(e: MouseEvent | TouchEvent) {
  106 + if (state.isPassing) {
  107 + return;
  108 + }
126 const actionEl = unref(actionElRef); 109 const actionEl = unref(actionElRef);
127 - const barEl = unref(barElRef);  
128 - if (!actionEl || !barEl) return;  
129 - const { offset, widthNum, actionWidth } = getOffset(actionEl);  
130 - const moveX = getEventPageX(e) - moveDistance;  
131 -  
132 - emit('move', {  
133 - event: e,  
134 - moveDistance,  
135 - moveX,  
136 - });  
137 - if (moveX > 0 && moveX <= offset) {  
138 - actionEl.style.left = `${moveX}px`;  
139 - barEl.style.width = `${moveX + actionWidth / 2}px`;  
140 - } else if (moveX > offset) {  
141 - actionEl.style.left = `${widthNum - actionWidth}px`;  
142 - barEl.style.width = `${widthNum - actionWidth / 2}px`;  
143 - if (!props.isSlot) {  
144 - checkPass(); 110 + if (!actionEl) return;
  111 + emit('start', e);
  112 + state.moveDistance = getEventPageX(e) - parseInt(actionEl.style.left.replace('px', ''), 10);
  113 + state.startTime = new Date().getTime();
  114 + state.isMoving = true;
  115 + }
  116 +
  117 + function getOffset(el: HTMLDivElement) {
  118 + const actionWidth = parseInt(el.style.width);
  119 + const { width } = props;
  120 + const widthNum = parseInt(width as string);
  121 + const offset = widthNum - actionWidth - 6;
  122 + return { offset, widthNum, actionWidth };
  123 + }
  124 +
  125 + function handleDragMoving(e: MouseEvent | TouchEvent) {
  126 + const { isMoving, moveDistance } = state;
  127 + if (isMoving) {
  128 + const actionEl = unref(actionElRef);
  129 + const barEl = unref(barElRef);
  130 + if (!actionEl || !barEl) return;
  131 + const { offset, widthNum, actionWidth } = getOffset(actionEl);
  132 + const moveX = getEventPageX(e) - moveDistance;
  133 +
  134 + emit('move', {
  135 + event: e,
  136 + moveDistance,
  137 + moveX,
  138 + });
  139 + if (moveX > 0 && moveX <= offset) {
  140 + actionEl.style.left = `${moveX}px`;
  141 + barEl.style.width = `${moveX + actionWidth / 2}px`;
  142 + } else if (moveX > offset) {
  143 + actionEl.style.left = `${widthNum - actionWidth}px`;
  144 + barEl.style.width = `${widthNum - actionWidth / 2}px`;
  145 + if (!props.isSlot) {
  146 + checkPass();
  147 + }
145 } 148 }
146 } 149 }
147 } 150 }
148 - }  
149 151
150 - function handleDragOver(e: MouseEvent | TouchEvent) {  
151 - const { isMoving, isPassing, moveDistance } = state;  
152 - if (isMoving && !isPassing) {  
153 - emit('end', e);  
154 - const actionEl = unref(actionElRef);  
155 - const barEl = unref(barElRef);  
156 - if (!actionEl || !barEl) return;  
157 - const moveX = getEventPageX(e) - moveDistance;  
158 - const { offset, widthNum, actionWidth } = getOffset(actionEl);  
159 - if (moveX < offset) {  
160 - if (!props.isSlot) {  
161 - resume();  
162 - } else {  
163 - setTimeout(() => {  
164 - if (!props.value) {  
165 - resume();  
166 - } else {  
167 - const contentEl = unref(contentElRef);  
168 - if (contentEl) {  
169 - contentEl.style.width = `${parseInt(barEl.style.width)}px`; 152 + function handleDragOver(e: MouseEvent | TouchEvent) {
  153 + const { isMoving, isPassing, moveDistance } = state;
  154 + if (isMoving && !isPassing) {
  155 + emit('end', e);
  156 + const actionEl = unref(actionElRef);
  157 + const barEl = unref(barElRef);
  158 + if (!actionEl || !barEl) return;
  159 + const moveX = getEventPageX(e) - moveDistance;
  160 + const { offset, widthNum, actionWidth } = getOffset(actionEl);
  161 + if (moveX < offset) {
  162 + if (!props.isSlot) {
  163 + resume();
  164 + } else {
  165 + setTimeout(() => {
  166 + if (!props.value) {
  167 + resume();
  168 + } else {
  169 + const contentEl = unref(contentElRef);
  170 + if (contentEl) {
  171 + contentEl.style.width = `${parseInt(barEl.style.width)}px`;
  172 + }
170 } 173 }
171 - }  
172 - }, 0); 174 + }, 0);
  175 + }
  176 + } else {
  177 + actionEl.style.left = `${widthNum - actionWidth}px`;
  178 + barEl.style.width = `${widthNum - actionWidth / 2}px`;
  179 + checkPass();
173 } 180 }
174 - } else {  
175 - actionEl.style.left = `${widthNum - actionWidth}px`;  
176 - barEl.style.width = `${widthNum - actionWidth / 2}px`;  
177 - checkPass(); 181 + state.isMoving = false;
178 } 182 }
179 - state.isMoving = false;  
180 } 183 }
181 - }  
182 184
183 - function checkPass() {  
184 - if (props.isSlot) {  
185 - resume();  
186 - return; 185 + function checkPass() {
  186 + if (props.isSlot) {
  187 + resume();
  188 + return;
  189 + }
  190 + state.endTime = new Date().getTime();
  191 + state.isPassing = true;
  192 + state.isMoving = false;
187 } 193 }
188 - state.endTime = new Date().getTime();  
189 - state.isPassing = true;  
190 - state.isMoving = false;  
191 - }  
192 194
193 - function resume() {  
194 - state.isMoving = false;  
195 - state.isPassing = false;  
196 - state.moveDistance = 0;  
197 - state.toLeft = false;  
198 - state.startTime = 0;  
199 - state.endTime = 0;  
200 - const actionEl = unref(actionElRef);  
201 - const barEl = unref(barElRef);  
202 - const contentEl = unref(contentElRef);  
203 - if (!actionEl || !barEl || !contentEl) return;  
204 - state.toLeft = true;  
205 - useTimeoutFn(() => { 195 + function resume() {
  196 + state.isMoving = false;
  197 + state.isPassing = false;
  198 + state.moveDistance = 0;
206 state.toLeft = false; 199 state.toLeft = false;
207 - actionEl.style.left = '0';  
208 - barEl.style.width = '0';  
209 - // The time is consistent with the animation time  
210 - }, 300);  
211 - contentEl.style.width = unref(getContentStyleRef).width;  
212 - } 200 + state.startTime = 0;
  201 + state.endTime = 0;
  202 + const actionEl = unref(actionElRef);
  203 + const barEl = unref(barElRef);
  204 + const contentEl = unref(contentElRef);
  205 + if (!actionEl || !barEl || !contentEl) return;
  206 + state.toLeft = true;
  207 + useTimeoutFn(() => {
  208 + state.toLeft = false;
  209 + actionEl.style.left = '0';
  210 + barEl.style.width = '0';
  211 + // The time is consistent with the animation time
  212 + }, 300);
  213 + contentEl.style.width = unref(getContentStyleRef).width;
  214 + }
213 215
214 - useExpose<DragVerifyActionType>({  
215 - resume,  
216 - }); 216 + expose({
  217 + resume,
  218 + });
217 219
218 - return () => {  
219 - const renderBar = () => {  
220 - const cls = [`darg-verify-bar`];  
221 - if (state.toLeft) {  
222 - cls.push('to-left');  
223 - }  
224 - return <div class={cls} ref={barElRef} style={unref(getBarStyleRef)} />;  
225 - }; 220 + return () => {
  221 + const renderBar = () => {
  222 + const cls = [`darg-verify-bar`];
  223 + if (state.toLeft) {
  224 + cls.push('to-left');
  225 + }
  226 + return <div class={cls} ref={barElRef} style={unref(getBarStyleRef)} />;
  227 + };
226 228
227 - const renderContent = () => {  
228 - const cls = [`darg-verify-content`];  
229 - const { isPassing } = state;  
230 - const { text, successText } = props; 229 + const renderContent = () => {
  230 + const cls = [`darg-verify-content`];
  231 + const { isPassing } = state;
  232 + const { text, successText } = props;
231 233
232 - isPassing && cls.push('success'); 234 + isPassing && cls.push('success');
233 235
234 - return (  
235 - <div class={cls} ref={contentElRef} style={unref(getContentStyleRef)}>  
236 - {getSlot(slots, 'text', isPassing) || (isPassing ? successText : text)}  
237 - </div>  
238 - );  
239 - }; 236 + return (
  237 + <div class={cls} ref={contentElRef} style={unref(getContentStyleRef)}>
  238 + {getSlot(slots, 'text', isPassing) || (isPassing ? successText : text)}
  239 + </div>
  240 + );
  241 + };
  242 +
  243 + const renderAction = () => {
  244 + const cls = [`darg-verify-action`];
  245 + const { toLeft, isPassing } = state;
  246 + if (toLeft) {
  247 + cls.push('to-left');
  248 + }
  249 + return (
  250 + <div
  251 + class={cls}
  252 + onMousedown={handleDragStart}
  253 + onTouchstart={handleDragStart}
  254 + style={unref(getActionStyleRef)}
  255 + ref={actionElRef}
  256 + >
  257 + {getSlot(slots, 'actionIcon', isPassing) ||
  258 + (isPassing ? (
  259 + <CheckOutlined class={`darg-verify-action__icon`} />
  260 + ) : (
  261 + <DoubleRightOutlined class={`darg-verify-action__icon`} />
  262 + ))}
  263 + </div>
  264 + );
  265 + };
240 266
241 - const renderAction = () => {  
242 - const cls = [`darg-verify-action`];  
243 - const { toLeft, isPassing } = state;  
244 - if (toLeft) {  
245 - cls.push('to-left');  
246 - }  
247 return ( 267 return (
248 <div 268 <div
249 - class={cls}  
250 - onMousedown={handleDragStart}  
251 - onTouchstart={handleDragStart}  
252 - style={unref(getActionStyleRef)}  
253 - ref={actionElRef} 269 + class="darg-verify"
  270 + ref={wrapElRef}
  271 + style={unref(getWrapStyleRef)}
  272 + onMousemove={handleDragMoving}
  273 + onTouchmove={handleDragMoving}
  274 + onMouseleave={handleDragOver}
  275 + onMouseup={handleDragOver}
  276 + onTouchend={handleDragOver}
254 > 277 >
255 - {getSlot(slots, 'actionIcon', isPassing) ||  
256 - (isPassing ? (  
257 - <CheckOutlined class={`darg-verify-action__icon`} />  
258 - ) : (  
259 - <DoubleRightOutlined class={`darg-verify-action__icon`} />  
260 - ))} 278 + {renderBar()}
  279 + {renderContent()}
  280 + {renderAction()}
261 </div> 281 </div>
262 ); 282 );
263 }; 283 };
  284 + },
  285 + });
  286 +</script>
  287 +<style lang="less">
  288 + @radius: 4px;
  289 +
  290 + .darg-verify {
  291 + position: relative;
  292 + overflow: hidden;
  293 + text-align: center;
  294 + background-color: rgb(238, 238, 238);
  295 + border: 1px solid #ddd;
  296 + border-radius: @radius;
264 297
265 - return (  
266 - <div  
267 - class="darg-verify"  
268 - ref={wrapElRef}  
269 - style={unref(getWrapStyleRef)}  
270 - onMousemove={handleDragMoving}  
271 - onTouchmove={handleDragMoving}  
272 - onMouseleave={handleDragOver}  
273 - onMouseup={handleDragOver}  
274 - onTouchend={handleDragOver}  
275 - >  
276 - {renderBar()}  
277 - {renderContent()}  
278 - {renderAction()}  
279 - </div> 298 + &-bar {
  299 + position: absolute;
  300 + width: 0;
  301 + height: 36px;
  302 + background-color: @success-color;
  303 + border-radius: @radius;
  304 +
  305 + &.to-left {
  306 + width: 0 !important;
  307 + transition: width 0.3s;
  308 + }
  309 + }
  310 +
  311 + &-content {
  312 + position: absolute;
  313 + top: 0;
  314 + font-size: 12px;
  315 + -webkit-text-size-adjust: none;
  316 + background-color: -webkit-gradient(
  317 + linear,
  318 + left top,
  319 + right top,
  320 + color-stop(0, #333),
  321 + color-stop(0.4, #333),
  322 + color-stop(0.5, #fff),
  323 + color-stop(0.6, #333),
  324 + color-stop(1, #333)
280 ); 325 );
281 - };  
282 - },  
283 -}); 326 + animation: slidetounlock 3s infinite;
  327 + -webkit-background-clip: text;
  328 + -moz-user-select: none;
  329 + -webkit-user-select: none;
  330 + -o-user-select: none;
  331 + -ms-user-select: none;
  332 + user-select: none;
  333 + -webkit-text-fill-color: transparent;
  334 +
  335 + &.success {
  336 + -webkit-text-fill-color: @white;
  337 + }
  338 +
  339 + & > * {
  340 + -webkit-text-fill-color: #333;
  341 + }
  342 + }
  343 +
  344 + &-action {
  345 + position: absolute;
  346 + top: 0;
  347 + left: 0;
  348 + display: flex;
  349 + cursor: move;
  350 + background-color: @white;
  351 + border-radius: @radius;
  352 + justify-content: center;
  353 + align-items: center;
  354 +
  355 + &__icon {
  356 + cursor: inherit;
  357 + }
  358 +
  359 + &.to-left {
  360 + left: 0 !important;
  361 + transition: left 0.3s;
  362 + }
  363 + }
  364 + }
  365 +
  366 + @-webkit-keyframes slidetounlock {
  367 + 0% {
  368 + background-position: -120px 0;
  369 + }
  370 +
  371 + 100% {
  372 + background-position: 120px 0;
  373 + }
  374 + }
  375 +</style>
src/components/Verify/src/ImgRotate.less deleted 100644 → 0
1 -.ir-dv {  
2 - position: relative;  
3 - display: flex;  
4 - flex-direction: column;  
5 - align-items: center;  
6 -  
7 - &-img__wrap {  
8 - position: relative;  
9 - overflow: hidden;  
10 - border-radius: 50%;  
11 -  
12 - img {  
13 - width: 100%;  
14 - border-radius: 50%;  
15 -  
16 - &.to-origin {  
17 - transition: transform 0.3s;  
18 - }  
19 - }  
20 - }  
21 -  
22 - &-img__tip {  
23 - position: absolute;  
24 - bottom: 10px;  
25 - left: 0;  
26 - z-index: 1;  
27 - display: block;  
28 - width: 100%;  
29 - height: 30px;  
30 - font-size: 12px;  
31 - line-height: 30px;  
32 - color: @white;  
33 - text-align: center;  
34 -  
35 - &.success {  
36 - background-color: fade(@success-color, 60%);  
37 - }  
38 -  
39 - &.error {  
40 - background-color: fade(@error-color, 60%);  
41 - }  
42 -  
43 - &.normal {  
44 - background-color: rgba(0, 0, 0, 0.3);  
45 - }  
46 - }  
47 -  
48 - &-drag__bar {  
49 - margin-top: 20px;  
50 - }  
51 -}  
src/components/Verify/src/ImgRotate.tsx renamed to src/components/Verify/src/ImgRotate.vue
1 -import './ImgRotate.less';  
2 -  
3 -import type { MoveData, DragVerifyActionType } from './types';  
4 -  
5 -import { defineComponent, computed, unref, reactive, watch, ref, getCurrentInstance } from 'vue';  
6 -import { useTimeoutFn } from '/@/hooks/core/useTimeout';  
7 -  
8 -import BasicDragVerify from './DragVerify';  
9 -  
10 -import { hackCss } from '/@/utils/domUtils';  
11 -  
12 -import { rotateProps } from './props';  
13 -import { useI18n } from '/@/hooks/web/useI18n';  
14 -  
15 -export default defineComponent({  
16 - name: 'ImgRotateDargVerify',  
17 - inheritAttrs: false,  
18 - props: rotateProps,  
19 - emits: ['success', 'change', 'update:value'],  
20 - setup(props, { emit, attrs }) {  
21 - const basicRef = ref<Nullable<DragVerifyActionType>>(null);  
22 - const state = reactive({  
23 - showTip: false,  
24 - isPassing: false,  
25 - imgStyle: {},  
26 - randomRotate: 0,  
27 - currentRotate: 0,  
28 - toOrigin: false,  
29 - startTime: 0,  
30 - endTime: 0,  
31 - draged: false,  
32 - });  
33 - const { t } = useI18n();  
34 -  
35 - watch(  
36 - () => state.isPassing,  
37 - (isPassing) => {  
38 - if (isPassing) {  
39 - const { startTime, endTime } = state;  
40 - const time = (endTime - startTime) / 1000;  
41 - emit('success', { isPassing, time: time.toFixed(1) });  
42 - emit('change', isPassing);  
43 - emit('update:value', isPassing); 1 +<script lang="tsx">
  2 + import type { MoveData, DragVerifyActionType } from './typing';
  3 + import { defineComponent, computed, unref, reactive, watch, ref, getCurrentInstance } from 'vue';
  4 + import { useTimeoutFn } from '/@/hooks/core/useTimeout';
  5 + import BasicDragVerify from './DragVerify.vue';
  6 + import { hackCss } from '/@/utils/domUtils';
  7 + import { rotateProps } from './props';
  8 + import { useI18n } from '/@/hooks/web/useI18n';
  9 +
  10 + export default defineComponent({
  11 + name: 'ImgRotateDargVerify',
  12 + inheritAttrs: false,
  13 + props: rotateProps,
  14 + emits: ['success', 'change', 'update:value'],
  15 + setup(props, { emit, attrs }) {
  16 + const basicRef = ref<Nullable<DragVerifyActionType>>(null);
  17 + const state = reactive({
  18 + showTip: false,
  19 + isPassing: false,
  20 + imgStyle: {},
  21 + randomRotate: 0,
  22 + currentRotate: 0,
  23 + toOrigin: false,
  24 + startTime: 0,
  25 + endTime: 0,
  26 + draged: false,
  27 + });
  28 + const { t } = useI18n();
  29 +
  30 + watch(
  31 + () => state.isPassing,
  32 + (isPassing) => {
  33 + if (isPassing) {
  34 + const { startTime, endTime } = state;
  35 + const time = (endTime - startTime) / 1000;
  36 + emit('success', { isPassing, time: time.toFixed(1) });
  37 + emit('change', isPassing);
  38 + emit('update:value', isPassing);
  39 + }
44 } 40 }
  41 + );
  42 +
  43 + const getImgWrapStyleRef = computed(() => {
  44 + const { imgWrapStyle, imgWidth } = props;
  45 + return {
  46 + width: `${imgWidth}px`,
  47 + height: `${imgWidth}px`,
  48 + ...imgWrapStyle,
  49 + };
  50 + });
  51 +
  52 + const getFactorRef = computed(() => {
  53 + const { minDegree, maxDegree } = props;
  54 + if (minDegree === maxDegree) {
  55 + return Math.floor(1 + Math.random() * 1) / 10 + 1;
  56 + }
  57 + return 1;
  58 + });
  59 + function handleStart() {
  60 + state.startTime = new Date().getTime();
45 } 61 }
46 - );  
47 -  
48 - const getImgWrapStyleRef = computed(() => {  
49 - const { imgWrapStyle, imgWidth } = props;  
50 - return {  
51 - width: `${imgWidth}px`,  
52 - height: `${imgWidth}px`,  
53 - ...imgWrapStyle,  
54 - };  
55 - });  
56 62
57 - const getFactorRef = computed(() => {  
58 - const { minDegree, maxDegree } = props;  
59 - if (minDegree === maxDegree) {  
60 - return Math.floor(1 + Math.random() * 1) / 10 + 1; 63 + function handleDragBarMove(data: MoveData) {
  64 + state.draged = true;
  65 + const { imgWidth, height, maxDegree } = props;
  66 + const { moveX } = data;
  67 + const currentRotate = Math.ceil(
  68 + (moveX / (imgWidth! - parseInt(height as string))) * maxDegree! * unref(getFactorRef)
  69 + );
  70 + state.currentRotate = currentRotate;
  71 + state.imgStyle = hackCss('transform', `rotateZ(${state.randomRotate - currentRotate}deg)`);
61 } 72 }
62 - return 1;  
63 - });  
64 - function handleStart() {  
65 - state.startTime = new Date().getTime();  
66 - }  
67 73
68 - function handleDragBarMove(data: MoveData) {  
69 - state.draged = true;  
70 - const { imgWidth, height, maxDegree } = props;  
71 - const { moveX } = data;  
72 - const currentRotate = Math.ceil(  
73 - (moveX / (imgWidth! - parseInt(height as string))) * maxDegree! * unref(getFactorRef)  
74 - );  
75 - state.currentRotate = currentRotate;  
76 - state.imgStyle = hackCss('transform', `rotateZ(${state.randomRotate - currentRotate}deg)`);  
77 - } 74 + function handleImgOnLoad() {
  75 + const { minDegree, maxDegree } = props;
  76 + const ranRotate = Math.floor(minDegree! + Math.random() * (maxDegree! - minDegree!)); // 生成随机角度
  77 + state.randomRotate = ranRotate;
  78 + state.imgStyle = hackCss('transform', `rotateZ(${ranRotate}deg)`);
  79 + }
78 80
79 - function handleImgOnLoad() {  
80 - const { minDegree, maxDegree } = props;  
81 - const ranRotate = Math.floor(minDegree! + Math.random() * (maxDegree! - minDegree!)); // 生成随机角度  
82 - state.randomRotate = ranRotate;  
83 - state.imgStyle = hackCss('transform', `rotateZ(${ranRotate}deg)`);  
84 - } 81 + function handleDragEnd() {
  82 + const { randomRotate, currentRotate } = state;
  83 + const { diffDegree } = props;
  84 +
  85 + if (Math.abs(randomRotate - currentRotate) >= (diffDegree || 20)) {
  86 + state.imgStyle = hackCss('transform', `rotateZ(${randomRotate}deg)`);
  87 + state.toOrigin = true;
  88 + useTimeoutFn(() => {
  89 + state.toOrigin = false;
  90 + state.showTip = true;
  91 + // 时间与动画时间保持一致
  92 + }, 300);
  93 + } else {
  94 + checkPass();
  95 + }
  96 + state.showTip = true;
  97 + }
  98 + function checkPass() {
  99 + state.isPassing = true;
  100 + state.endTime = new Date().getTime();
  101 + }
85 102
86 - function handleDragEnd() {  
87 - const { randomRotate, currentRotate } = state;  
88 - const { diffDegree } = props;  
89 -  
90 - if (Math.abs(randomRotate - currentRotate) >= (diffDegree || 20)) {  
91 - state.imgStyle = hackCss('transform', `rotateZ(${randomRotate}deg)`);  
92 - state.toOrigin = true;  
93 - useTimeoutFn(() => {  
94 - state.toOrigin = false;  
95 - state.showTip = true;  
96 - // 时间与动画时间保持一致  
97 - }, 300);  
98 - } else {  
99 - checkPass(); 103 + function resume() {
  104 + state.showTip = false;
  105 + const basicEl = unref(basicRef);
  106 + if (!basicEl) {
  107 + return;
  108 + }
  109 + state.isPassing = false;
  110 +
  111 + basicEl.resume();
  112 + handleImgOnLoad();
  113 + }
  114 +
  115 + const instance = getCurrentInstance() as any;
  116 + if (instance) {
  117 + instance.resume = resume;
  118 + }
  119 + // handleImgOnLoad();
  120 + return () => {
  121 + const { src } = props;
  122 + const { toOrigin, isPassing, startTime, endTime } = state;
  123 + const imgCls: string[] = [];
  124 + if (toOrigin) {
  125 + imgCls.push('to-origin');
  126 + }
  127 + const time = (endTime - startTime) / 1000;
  128 +
  129 + return (
  130 + <div class="ir-dv">
  131 + <div class={`ir-dv-img__wrap`} style={unref(getImgWrapStyleRef)}>
  132 + <img
  133 + src={src}
  134 + onLoad={handleImgOnLoad}
  135 + width={parseInt(props.width as string)}
  136 + class={imgCls}
  137 + style={state.imgStyle}
  138 + onClick={() => {
  139 + resume();
  140 + }}
  141 + />
  142 + {state.showTip && (
  143 + <span class={[`ir-dv-img__tip`, state.isPassing ? 'success' : 'error']}>
  144 + {state.isPassing
  145 + ? t('component.verify.time', { time: time.toFixed(1) })
  146 + : t('component.verify.error')}
  147 + </span>
  148 + )}
  149 + {!state.showTip && !state.draged && (
  150 + <span class={[`ir-dv-img__tip`, 'normal']}>{t('component.verify.redoTip')}</span>
  151 + )}
  152 + </div>
  153 + <BasicDragVerify
  154 + class={`ir-dv-drag__bar`}
  155 + onMove={handleDragBarMove}
  156 + onEnd={handleDragEnd}
  157 + onStart={handleStart}
  158 + ref={basicRef}
  159 + {...{ ...attrs, ...props }}
  160 + value={isPassing}
  161 + isSlot={true}
  162 + />
  163 + </div>
  164 + );
  165 + };
  166 + },
  167 + });
  168 +</script>
  169 +<style lang="less">
  170 + .ir-dv {
  171 + position: relative;
  172 + display: flex;
  173 + flex-direction: column;
  174 + align-items: center;
  175 +
  176 + &-img__wrap {
  177 + position: relative;
  178 + overflow: hidden;
  179 + border-radius: 50%;
  180 +
  181 + img {
  182 + width: 100%;
  183 + border-radius: 50%;
  184 +
  185 + &.to-origin {
  186 + transition: transform 0.3s;
  187 + }
100 } 188 }
101 - state.showTip = true;  
102 - }  
103 - function checkPass() {  
104 - state.isPassing = true;  
105 - state.endTime = new Date().getTime();  
106 } 189 }
107 190
108 - function resume() {  
109 - state.showTip = false;  
110 - const basicEl = unref(basicRef);  
111 - if (!basicEl) {  
112 - return; 191 + &-img__tip {
  192 + position: absolute;
  193 + bottom: 10px;
  194 + left: 0;
  195 + z-index: 1;
  196 + display: block;
  197 + width: 100%;
  198 + height: 30px;
  199 + font-size: 12px;
  200 + line-height: 30px;
  201 + color: @white;
  202 + text-align: center;
  203 +
  204 + &.success {
  205 + background-color: fade(@success-color, 60%);
113 } 206 }
114 - state.isPassing = false;  
115 207
116 - basicEl.resume();  
117 - handleImgOnLoad(); 208 + &.error {
  209 + background-color: fade(@error-color, 60%);
  210 + }
  211 +
  212 + &.normal {
  213 + background-color: rgba(0, 0, 0, 0.3);
  214 + }
118 } 215 }
119 216
120 - const instance = getCurrentInstance() as any;  
121 - if (instance) {  
122 - instance.resume = resume; 217 + &-drag__bar {
  218 + margin-top: 20px;
123 } 219 }
124 - // handleImgOnLoad();  
125 - return () => {  
126 - const { src } = props;  
127 - const { toOrigin, isPassing, startTime, endTime } = state;  
128 - const imgCls: string[] = [];  
129 - if (toOrigin) {  
130 - imgCls.push('to-origin');  
131 - }  
132 - const time = (endTime - startTime) / 1000;  
133 -  
134 - return (  
135 - <div class="ir-dv">  
136 - <div class={`ir-dv-img__wrap`} style={unref(getImgWrapStyleRef)}>  
137 - <img  
138 - src={src}  
139 - onLoad={handleImgOnLoad}  
140 - width={parseInt(props.width as string)}  
141 - class={imgCls}  
142 - style={state.imgStyle}  
143 - onClick={() => {  
144 - resume();  
145 - }}  
146 - />  
147 - {state.showTip && (  
148 - <span class={[`ir-dv-img__tip`, state.isPassing ? 'success' : 'error']}>  
149 - {state.isPassing  
150 - ? t('component.verify.time', { time: time.toFixed(1) })  
151 - : t('component.verify.error')}  
152 - </span>  
153 - )}  
154 - {!state.showTip && !state.draged && (  
155 - <span class={[`ir-dv-img__tip`, 'normal']}>{t('component.verify.redoTip')}</span>  
156 - )}  
157 - </div>  
158 - <BasicDragVerify  
159 - class={`ir-dv-drag__bar`}  
160 - onMove={handleDragBarMove}  
161 - onEnd={handleDragEnd}  
162 - onStart={handleStart}  
163 - ref={basicRef}  
164 - {...{ ...attrs, ...props }}  
165 - value={isPassing}  
166 - isSlot={true}  
167 - />  
168 - </div>  
169 - );  
170 - };  
171 - },  
172 -}); 220 + }
  221 +</style>
src/components/Verify/src/types.ts renamed to src/components/Verify/src/typing.ts
src/hooks/core/useExpose.ts deleted 100644 → 0
1 -import { getCurrentInstance } from 'vue';  
2 -  
3 -// expose public api  
4 -export function useExpose<T>(apis: T) {  
5 - const instance = getCurrentInstance();  
6 - if (instance) {  
7 - Object.assign(instance.proxy, apis);  
8 - }  
9 -}