From 466f6fa57f087b068a50864d43e6f64787e02192 Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Thu, 18 Aug 2022 15:54:23 +0800 Subject: [PATCH 01/12] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DInfiniteloading?= =?UTF-8?q?=20=E7=BB=84=E4=BB=B6=20pullTxt=E3=80=81loadTxt=20=E5=92=8C=20l?= =?UTF-8?q?oadMoreTxt=20=E5=8F=82=E6=95=B0=E6=97=A0=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/infiniteloading/infiniteloading.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/packages/infiniteloading/infiniteloading.tsx b/src/packages/infiniteloading/infiniteloading.tsx index fb573b8b7e..c78f9b01f1 100644 --- a/src/packages/infiniteloading/infiniteloading.tsx +++ b/src/packages/infiniteloading/infiniteloading.tsx @@ -124,6 +124,7 @@ export const Infiniteloading: FunctionComponent< } setIsInfiniting(true) loadMore && loadMore(infiniteDone) + return true }) } @@ -188,7 +189,7 @@ export const Infiniteloading: FunctionComponent< return ( window.requestAnimationFrame || window.webkitRequestAnimationFrame || - function (callback) { + function fn(callback) { window.setTimeout(callback, 1000 / 60) } ) @@ -234,7 +235,7 @@ export const Infiniteloading: FunctionComponent< } beforeScrollTop.current = resScrollTop scrollChange && scrollChange(resScrollTop) - return offsetDistance <= threshold && direction == 'down' + return offsetDistance <= threshold && direction === 'down' } return ( @@ -250,7 +251,7 @@ export const Infiniteloading: FunctionComponent<
- {locale.infiniteloading.pullRefreshText || pullTxt} + {pullTxt || locale.infiniteloading.pullRefreshText}
@@ -260,13 +261,13 @@ export const Infiniteloading: FunctionComponent<
- {locale.infiniteloading.loadText || loadTxt} + {loadTxt || locale.infiniteloading.loadText}
) : ( !hasMore && (
- {locale.infiniteloading.loadMoreText || loadMoreTxt} + {loadMoreTxt || locale.infiniteloading.loadMoreText}
) )} From d76f4ede80d0b4dae5884cf76bc23ce6e4256e23 Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Wed, 14 Sep 2022 14:57:48 +0800 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20taro=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/config.json | 8 +- src/packages/barrage/barrage.scss | 9 +- src/packages/barrage/barrage.taro.tsx | 12 +- src/packages/barrage/barrage.tsx | 2 +- src/packages/barrage/demo.scss | 3 + src/packages/barrage/demo.taro.tsx | 2 +- src/packages/barrage/demo.tsx | 2 +- .../circleprogress/circleprogress.scss | 3 + .../circleprogress/circleprogress.taro.tsx | 127 ++++++---- src/packages/circleprogress/demo.taro.tsx | 2 +- src/packages/infiniteloading/demo.taro.tsx | 23 -- src/packages/infiniteloading/doc.taro.md | 7 + .../infiniteloading/infiniteloading.taro.tsx | 183 ++++---------- .../infiniteloading/infiniteloading.tsx | 1 + src/packages/overlay/demo.scss | 3 + src/packages/overlay/demo.taro.tsx | 2 +- src/packages/overlay/demo.tsx | 2 +- src/packages/uploader/demo.taro.tsx | 3 +- src/packages/uploader/upload.ts | 51 ++++ src/packages/uploader/uploader.taro.tsx | 228 +++++++++--------- src/packages/video/doc.taro.md | 7 + src/sites/mobile-taro/src/app.config.ts | 9 +- 23 files changed, 350 insertions(+), 340 deletions(-) create mode 100644 src/packages/infiniteloading/doc.taro.md create mode 100644 src/packages/video/doc.taro.md diff --git a/package.json b/package.json index 3a6b9de3c4..1dad63dd48 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "@rollup/plugin-commonjs": "^21.0.1", "@rollup/plugin-node-resolve": "^13.1.1", "@rollup/plugin-typescript": "^8.3.0", + "@tarojs/components": "^3.5.5", "@tarojs/taro": "3.4.13", "@testing-library/jest-dom": "^5.16.3", "@testing-library/react": "^13.3.0", diff --git a/src/config.json b/src/config.json index 7a038924ca..ce88a0ea94 100644 --- a/src/config.json +++ b/src/config.json @@ -521,7 +521,7 @@ "desc": "用于将本地的图片或文件上传至服务器。", "sort": 1, "show": true, - "taro": false, + "taro": true, "author": "swag~jun" }, { @@ -614,7 +614,7 @@ "desc": "列表滚动到底部自动加载更多数据。", "sort": 5, "show": true, - "taro": false, + "taro": true, "author": "swag~jun" }, { @@ -685,7 +685,7 @@ "desc": "展示操作或任务的当前进度。", "sort": 7, "show": true, - "taro": false, + "taro": true, "author": "swag~jun" }, { @@ -962,7 +962,7 @@ "desc": "用于话语和词组的轮播展示,适用于视频中或其他类似需求中。", "sort": 2, "show": true, - "taro": false, + "taro": true, "author": "swag~jun" }, { diff --git a/src/packages/barrage/barrage.scss b/src/packages/barrage/barrage.scss index 26759c2949..bf21113426 100644 --- a/src/packages/barrage/barrage.scss +++ b/src/packages/barrage/barrage.scss @@ -8,7 +8,7 @@ box-sizing: border-box; background-color: #f7f8fa; .barrage-item { - width: 100px; + width: 120px; // max-width: 150px; display: block; position: absolute; @@ -19,7 +19,12 @@ text-align: center; white-space: pre; transform: translateX(100%); - background: linear-gradient(to right, rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0)); + background: linear-gradient( + to right, + rgba(0, 0, 0, 0.15), + rgba(0, 0, 0, 0) + ); + box-sizing: border-box; &.move { will-change: transform; animation-name: moving; diff --git a/src/packages/barrage/barrage.taro.tsx b/src/packages/barrage/barrage.taro.tsx index 6bc49109f6..104e265a13 100644 --- a/src/packages/barrage/barrage.taro.tsx +++ b/src/packages/barrage/barrage.taro.tsx @@ -45,7 +45,6 @@ const InternalBarrage: ForwardRefRenderFunction< } const barrageBody = useRef(null) const barrageContainer = useRef(null) - const barrageCWidth = useRef(0) const timer = useRef(0) const index = useRef(0) @@ -60,10 +59,7 @@ const InternalBarrage: ForwardRefRenderFunction< })) useEffect(() => { - if (barrageBody.current) { - barrageCWidth.current = barrageBody.current.offsetWidth - run() - } + run() return () => { clearInterval(timer.current) } @@ -84,17 +80,15 @@ const InternalBarrage: ForwardRefRenderFunction< el.classList.add('barrage-item') ;(barrageContainer.current as HTMLDivElement).appendChild(el) - const query = Taro.createSelectorQuery() + Taro.createSelectorQuery() .select('.barrage-item') .boundingClientRect((res) => { - const width = res?.width + console.log('res', res) const height = res?.height el.classList.add('move') el.style.animationDuration = `${speeds}ms` el.style.top = `${(_index % rows) * (height + top) + 20}px` - // el.style.width = `${width}px` - el.style.setProperty('--move-distance', `-${barrageCWidth.current}px`) el.dataset.index = `${_index}` el.addEventListener('animationend', () => { ;(barrageContainer.current as HTMLDivElement).removeChild(el) diff --git a/src/packages/barrage/barrage.tsx b/src/packages/barrage/barrage.tsx index edd4aae3fb..be95b7bf6b 100644 --- a/src/packages/barrage/barrage.tsx +++ b/src/packages/barrage/barrage.tsx @@ -88,7 +88,7 @@ const InternalBarrage: ForwardRefRenderFunction< el.classList.add('move') el.style.animationDuration = `${speeds}ms` el.style.top = `${(_index % rows) * (height + top) + 20}px` - el.style.width = `${width + 20}px` + el.style.width = `${width}px` el.style.setProperty('--move-distance', `-${barrageCWidth.current}px`) el.dataset.index = `${_index}` el.addEventListener('animationend', () => { diff --git a/src/packages/barrage/demo.scss b/src/packages/barrage/demo.scss index 80f865475c..3f96259e05 100644 --- a/src/packages/barrage/demo.scss +++ b/src/packages/barrage/demo.scss @@ -1,3 +1,6 @@ +.demo-barrage { + min-height: 100vh; +} .barrage-demo-wrap, .barrage-demo { padding: 20px 0; diff --git a/src/packages/barrage/demo.taro.tsx b/src/packages/barrage/demo.taro.tsx index f1afd6cce1..78bafd6b77 100644 --- a/src/packages/barrage/demo.taro.tsx +++ b/src/packages/barrage/demo.taro.tsx @@ -76,7 +76,7 @@ const BarrageDemo = () => { return ( <> -
+

{translated['84aa6bce']}

{ translated['4d14b3e0'], translated['448f995e'], ] - console.log(11, translated) + const barrageRef = useRef(null) const addBarrage = () => { const n = Math.random() diff --git a/src/packages/circleprogress/circleprogress.scss b/src/packages/circleprogress/circleprogress.scss index 8cf155e776..205f644ef6 100644 --- a/src/packages/circleprogress/circleprogress.scss +++ b/src/packages/circleprogress/circleprogress.scss @@ -1,3 +1,6 @@ +.demo-circleprogress { + min-height: 100vh; +} .nut-circleprogress { position: relative; diff --git a/src/packages/circleprogress/circleprogress.taro.tsx b/src/packages/circleprogress/circleprogress.taro.tsx index 0613ad7d5f..dd3e7baf07 100644 --- a/src/packages/circleprogress/circleprogress.taro.tsx +++ b/src/packages/circleprogress/circleprogress.taro.tsx @@ -1,4 +1,4 @@ -import React, { FunctionComponent } from 'react' +import React, { useState, useEffect, FunctionComponent } from 'react' import classNames from 'classnames' import { isObject } from '@/utils' import bem from '@/utils/bem' @@ -20,8 +20,8 @@ const defaultProps = { strokeWidth: 5, radius: 50, strokeLinecap: 'round', - circleColor: '', - pathColor: '', + circleColor: '#fa2c19', + pathColor: '#e5e9f2', clockwise: true, } as CircleProgressProps @@ -44,9 +44,12 @@ export const CircleProgress: FunctionComponent< ...defaultProps, ...props, } + const [oldValue, setOldValue] = useState(progress) + const b = bem('circleprogress') const classes = classNames(className, b('')) const refRandomId = Math.random().toString(36).slice(-8) + let lastTime = 0 const styles: React.CSSProperties = { height: `${Number(radius) * 2}px`, @@ -54,31 +57,45 @@ export const CircleProgress: FunctionComponent< ...style, } - const pathStyle = { - stroke: pathColor, - } - - const hoverStyle = () => { - const perimeter = 283 - const offset = (perimeter * Number(progress)) / 100 - return { - stroke: isObject(circleColor) ? `url(#${refRandomId})` : circleColor, - strokeDasharray: `${offset}px ${perimeter}px`, + useEffect(() => { + let rafId: number | undefined + const startTime = Date.now() + const startRate = Number(oldValue) // 30 + const endRate = Number(progress) // 40 + const duration = Math.abs(((startRate - endRate) * 1000) / +100) // 100 + const animate = () => { + const now = Date.now() + const progress = Math.min((now - startTime) / duration, 1) + const rate = progress * (endRate - startRate) + startRate + setOldValue(Math.min(Math.max(+rate, 0), 100)) + if (endRate > startRate ? rate < endRate : rate > endRate) { + rafId = requestAnimationFrame(animate) + } } - } + if (rafId) { + cancelAnimationFrame(rafId) + } + rafId = requestAnimationFrame(animate) + }, [progress]) - const path = () => { - const isWise = clockwise ? 1 : 0 - return `M 50 50 m -45 0 a 45 45 0 1 ${isWise} 90 0 a 45 45 0 1 ${isWise} -90 0` + const requestAnimationFrame = function (callback: Function) { + var currTime = new Date().getTime() + var timeToCall = Math.max(0, 16.7 - (currTime - lastTime)) + lastTime = currTime + timeToCall + var id = setTimeout(function () { + callback() + }, timeToCall) + lastTime = currTime + timeToCall + return id } - const hoverColor = () => { - return isObject(circleColor) ? `url(#${refRandomId})` : circleColor + const cancelAnimationFrame = function (id: any) { + clearTimeout(id) } const stop = () => { if (!isObject(circleColor)) { - return + return [] } const color = circleColor as IColor const colorArr = Object.keys(color).sort( @@ -97,36 +114,50 @@ export const CircleProgress: FunctionComponent< return stopArr } + const transColor = (color: string | undefined) => { + return color && color.replace('#', '%23') + } + const format = (progress: string | number) => + Math.min(Math.max(+progress, 0), 100) + + const circleStyle = () => { + let stopArr: Array = stop() + let stopDom: string[] = [] + if (stopArr) { + stopArr.map((item: { key?: string; value?: string }) => { + let obj = '' + obj = `%3Cstop offset='${item.key}' stop-color='${transColor( + item.value + )}'/%3E` + stopDom.push(obj) + }) + } + let perimeter = 283 + let progress = +oldValue + let offset = + (perimeter * Number(format(parseFloat(progress.toFixed(1))))) / 100 + const isWise = props.clockwise ? 1 : 0 + const color = isObject(circleColor) + ? `url(%23${refRandomId})` + : transColor(circleColor) + let d = `M 50 50 m 0 -45 a 45 45 0 1 ${isWise} 0 90 a 45 45 0 1, ${isWise} 0 -90` + const pa = `%3Cdefs%3E%3ClinearGradient id='${refRandomId}' x1='100%25' y1='0%25' x2='0%25' y2='0%25'%3E${stopDom}%3C/linearGradient%3E%3C/defs%3E` + const path = `%3Cpath d='${d}' stroke-width='${strokeWidth}' stroke='${transColor( + props.pathColor + )}' fill='none'/%3E` + const path1 = `%3Cpath d='${d}' stroke-width='${strokeWidth}' stroke-dasharray='${offset},${perimeter}' stroke-linecap='round' stroke='${transColor( + color + )}' fill='none'/%3E` + return { + background: `url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E${pa}${path}${path1}%3C/svg%3E")`, + width: '100%', + height: '100%', + } + } + return (
- - - - {stop()?.map((item: any, index) => { - return ( - - ) - })} - - - - - +
{children ||
{progress}%
}
diff --git a/src/packages/circleprogress/demo.taro.tsx b/src/packages/circleprogress/demo.taro.tsx index 4ab9321e99..6b92db71ec 100644 --- a/src/packages/circleprogress/demo.taro.tsx +++ b/src/packages/circleprogress/demo.taro.tsx @@ -74,7 +74,7 @@ const CircleProgressDemo = () => { return ( <> -
+

{translated['84aa6bce']}

diff --git a/src/packages/infiniteloading/demo.taro.tsx b/src/packages/infiniteloading/demo.taro.tsx index 3bae14af27..6c46098f29 100644 --- a/src/packages/infiniteloading/demo.taro.tsx +++ b/src/packages/infiniteloading/demo.taro.tsx @@ -132,29 +132,6 @@ const InfiniteloadingDemo = () => { -

{translated.eb4236fe}

- -
    - - {refreshList.map((item, index) => { - return ( -
  • - {item} -
  • - ) - })} -
    -
-
-

{translated['9ed40460']}

    diff --git a/src/packages/infiniteloading/doc.taro.md b/src/packages/infiniteloading/doc.taro.md new file mode 100644 index 0000000000..87bcff8957 --- /dev/null +++ b/src/packages/infiniteloading/doc.taro.md @@ -0,0 +1,7 @@ +# InfiniteLoading 滚动加载 + +### 介绍 + +列表滚动到底部自动加载更多数据。 + +#### 直接使用 Taro 现有 ScrollView 组件开发 [参考文档](https://docs.taro.zone/docs/components/viewContainer/scroll-view) \ No newline at end of file diff --git a/src/packages/infiniteloading/infiniteloading.taro.tsx b/src/packages/infiniteloading/infiniteloading.taro.tsx index 918171b665..d5ccaca2b0 100644 --- a/src/packages/infiniteloading/infiniteloading.taro.tsx +++ b/src/packages/infiniteloading/infiniteloading.taro.tsx @@ -2,6 +2,8 @@ import React, { useState, useEffect, useRef, FunctionComponent } from 'react' import classNames from 'classnames' import bem from '@/utils/bem' import Icon from '@/packages/icon/index.taro' +import { ScrollView } from '@tarojs/components' +import Taro from '@tarojs/taro' import { useConfig } from '@/packages/configprovider/configprovider.taro' import { IComponent, ComponentDefaults } from '@/utils/typings' @@ -9,6 +11,7 @@ import { IComponent, ComponentDefaults } from '@/utils/typings' export interface InfiniteloadingProps extends IComponent { hasMore: boolean threshold: number + upperThreshold: number containerId: string useWindow: boolean useCapture: boolean @@ -31,6 +34,7 @@ const defaultProps = { ...ComponentDefaults, hasMore: true, threshold: 200, + upperThreshold: 40, containerId: '', useWindow: true, useCapture: false, @@ -52,6 +56,7 @@ export const Infiniteloading: FunctionComponent< children, hasMore, threshold, + upperThreshold, containerId, useWindow, useCapture, @@ -65,7 +70,6 @@ export const Infiniteloading: FunctionComponent< refresh, loadMore, scrollChange, - ...restProps } = { ...defaultProps, ...props, @@ -74,8 +78,10 @@ export const Infiniteloading: FunctionComponent< const scroller = useRef(null) const refreshTop = useRef(null) const scrollEl = useRef(window) + const scrollHeight = useRef(0) + const scrollTop = useRef(0) + const direction = useRef('down') const isTouching = useRef(false) - const beforeScrollTop = useRef(0) const refreshMaxH = useRef(0) const y = useRef(0) const distance = useRef(0) @@ -84,27 +90,21 @@ export const Infiniteloading: FunctionComponent< const classes = classNames(className, b()) useEffect(() => { - const parentElement = getParentElement( - scroller.current as HTMLDivElement - ) as Node & ParentNode - scrollEl.current = useWindow ? window : parentElement - scrollEl.current.addEventListener('scroll', handleScroll, useCapture) - - return () => { - scrollEl.current.removeEventListener('scroll', handleScroll, useCapture) - } + refreshMaxH.current = upperThreshold + setTimeout(() => { + getScrollHeight() + }, 200) }, [hasMore, isInfiniting]) - useEffect(() => { - const element = scroller.current as HTMLDivElement - element.addEventListener('touchmove', touchMove, { passive: false }) - - return () => { - element.removeEventListener('touchmove', touchMove, { - passive: false, - } as EventListenerOptions) - } - }, []) + /** 获取需要滚动的距离 */ + const getScrollHeight = () => { + const parentElement = getParentElement('scroller') + parentElement + .boundingClientRect((rect) => { + scrollHeight.current = rect.height + }) + .exec() + } const getStyle = () => { return { @@ -115,20 +115,10 @@ export const Infiniteloading: FunctionComponent< } } - const getParentElement = (el: HTMLElement) => { - return containerId - ? document.querySelector(`#${containerId}`) - : el && el.parentNode - } - - const handleScroll = () => { - requestAniFrame()(() => { - if (!isScrollAtBottom() || !hasMore || isInfiniting) { - return false - } - setIsInfiniting(true) - loadMore && loadMore(infiniteDone) - }) + const getParentElement = (el: string) => { + return Taro.createSelectorQuery().select( + !!containerId ? `#${containerId} #${el}` : `#${el}` + ) } const infiniteDone = () => { @@ -143,112 +133,43 @@ export const Infiniteloading: FunctionComponent< isTouching.current = false } - const touchStart = (event: React.TouchEvent) => { - if (beforeScrollTop.current === 0 && !isTouching.current && isOpenRefresh) { - y.current = event.touches[0].pageY - isTouching.current = true - const childHeight = ( - (refreshTop.current as HTMLDivElement).firstElementChild as HTMLElement - ).offsetHeight - refreshMaxH.current = Math.floor(childHeight * 1 + 10) - } - } - - const touchMove = (event: any) => { - distance.current = event.touches[0].pageY - y.current - if (distance.current > 0 && isTouching.current) { - event.preventDefault() - if (distance.current >= refreshMaxH.current) { - distance.current = refreshMaxH.current - ;( - refreshTop.current as HTMLDivElement - ).style.height = `${distance.current}px` - } else { - ;( - refreshTop.current as HTMLDivElement - ).style.height = `${distance.current}px` - } - } else { - distance.current = 0 - ;( - refreshTop.current as HTMLDivElement - ).style.height = `${distance.current}px` - isTouching.current = false + const scrollAction = (e: any) => { + if (e.detail.scrollTop <= 0) { + // 滚动到最顶部 + e.detail.scrollTop = 0 + } else if (e.detail.scrollTop >= scrollHeight.current) { + // 滚动到最底部 + e.detail.scrollTop = scrollHeight.current } - } - - const touchEnd = () => { - if (distance.current < refreshMaxH.current) { - distance.current = 0 - ;( - refreshTop.current as HTMLDivElement - ).style.height = `${distance.current}px` + if ( + e.detail.scrollTop > scrollTop.current || + e.detail.scrollTop >= scrollHeight.current + ) { + direction.current = 'down' } else { - refresh && refresh(refreshDone) + direction.current = 'up' } + scrollTop.current = e.detail.scrollTop + scrollChange && scrollChange(e.detail.scrollTop) } - const requestAniFrame = () => { - return ( - window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - function (callback) { - window.setTimeout(callback, 1000 / 60) - } - ) - } - - const getWindowScrollTop = () => { - return window.pageYOffset !== undefined - ? window.pageYOffset - : (document.documentElement || document.body.parentNode || document.body) - .scrollTop - } - - const calculateTopPosition = (el: HTMLElement): number => { - return !el - ? 0 - : el.offsetTop + calculateTopPosition(el.offsetParent as HTMLElement) - } - - const isScrollAtBottom = () => { - let offsetDistance = 0 - let resScrollTop = 0 - let direction = 'down' - const windowScrollTop = getWindowScrollTop() - if (useWindow) { - if (scroller.current) { - offsetDistance = - calculateTopPosition(scroller.current) + - scroller.current.offsetHeight - - windowScrollTop - - window.innerHeight - } - resScrollTop = windowScrollTop + const lower = () => { + if (direction.current == 'up' || !hasMore || isInfiniting) { + return false } else { - const { scrollHeight, clientHeight, scrollTop } = - scrollEl.current as HTMLElement - offsetDistance = scrollHeight - clientHeight - scrollTop - resScrollTop = scrollTop - } - if (beforeScrollTop.current > resScrollTop) { - direction = 'up' - } else { - direction = 'down' + setIsInfiniting(true) + loadMore && loadMore(infiniteDone) } - beforeScrollTop.current = resScrollTop - scrollChange && scrollChange(resScrollTop) - return offsetDistance <= threshold && direction == 'down' } return ( -
    @@ -285,7 +206,7 @@ export const Infiniteloading: FunctionComponent< ) )}
    -
    + ) } diff --git a/src/packages/infiniteloading/infiniteloading.tsx b/src/packages/infiniteloading/infiniteloading.tsx index 825719b06c..85ea955f81 100644 --- a/src/packages/infiniteloading/infiniteloading.tsx +++ b/src/packages/infiniteloading/infiniteloading.tsx @@ -156,6 +156,7 @@ export const Infiniteloading: FunctionComponent< } const touchMove = (event: any) => { + console.log('touchMove', event) distance.current = event.touches[0].pageY - y.current if (distance.current > 0 && isTouching.current) { event.preventDefault() diff --git a/src/packages/overlay/demo.scss b/src/packages/overlay/demo.scss index e5e8fd4c88..4d88615f63 100644 --- a/src/packages/overlay/demo.scss +++ b/src/packages/overlay/demo.scss @@ -1,3 +1,6 @@ +.demo-overlay { + min-height: 100vh; +} .wrapper { display: flex; height: 100%; diff --git a/src/packages/overlay/demo.taro.tsx b/src/packages/overlay/demo.taro.tsx index 6538886816..56eb1243a6 100644 --- a/src/packages/overlay/demo.taro.tsx +++ b/src/packages/overlay/demo.taro.tsx @@ -60,7 +60,7 @@ const OverlayDemo = () => { } return ( <> -
    +

    {translated['84aa6bce']}

    @@ -454,7 +473,7 @@ const InternalUploader: ForwardRefRenderFunction< color="rgba(0,0,0,0.6)" className="close" name="failure" - click={() => onDelete(item, index)} + onClick={() => onDelete(item, index)} /> )} @@ -518,7 +537,7 @@ const InternalUploader: ForwardRefRenderFunction< color="#808080" className="nut-uploader__preview-img__file__del" name="del" - click={() => onDelete(item, index)} + onClick={() => onDelete(item, index)} /> {/* 缺少进度条组件,待更新 */}
    @@ -536,28 +555,7 @@ const InternalUploader: ForwardRefRenderFunction< color="#808080" name={uploadIcon} /> - {capture ? ( - - ) : ( - - )} +
    )}
diff --git a/src/packages/video/doc.taro.md b/src/packages/video/doc.taro.md new file mode 100644 index 0000000000..28d8d70cf7 --- /dev/null +++ b/src/packages/video/doc.taro.md @@ -0,0 +1,7 @@ +# Video 视频播放器 + +### 介绍 + +原生video实现的视频播放器 + +#### 直接使用 Taro 现有 video 组件开发 [参考文档](https://taro-docs.jd.com/taro/docs/components/media/video) \ No newline at end of file diff --git a/src/sites/mobile-taro/src/app.config.ts b/src/sites/mobile-taro/src/app.config.ts index 5ec8fecda1..5354fd45c8 100644 --- a/src/sites/mobile-taro/src/app.config.ts +++ b/src/sites/mobile-taro/src/app.config.ts @@ -39,6 +39,7 @@ const subPackages = [ 'pages/picker/index', 'pages/shortpassword/index', 'pages/textarea/index', + 'pages/uploader/index', 'pages/searchbar/index', 'pages/numberkeyboard/index', ], @@ -47,6 +48,7 @@ const subPackages = [ root: 'feedback', pages: [ 'pages/actionsheet/index', + 'pages/infiniteloading/index', 'pages/switch/index', 'pages/pulltorefresh/index', ], @@ -54,6 +56,7 @@ const subPackages = [ { root: 'exhibition', pages: [ + 'pages/circleprogress/index', 'pages/noticebar/index', 'pages/steps/index', 'pages/swiper/index', @@ -71,7 +74,11 @@ const subPackages = [ }, { root: 'business', - pages: ['pages/card/index', 'pages/timeselect/index'], + pages: [ + 'pages/barrage/index', + 'pages/card/index', + 'pages/timeselect/index', + ], }, ] From da7ea2cb5b4d2579af8496c82f9898f982c89bc9 Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Wed, 14 Sep 2022 17:44:22 +0800 Subject: [PATCH 03/12] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config.json b/src/config.json index ce88a0ea94..e2256a2dcb 100644 --- a/src/config.json +++ b/src/config.json @@ -610,6 +610,7 @@ "version": "0.1.0", "name": "Infiniteloading", "type": "component", + "tarodoc": true, "cName": "滚动加载", "desc": "列表滚动到底部自动加载更多数据。", "sort": 5, @@ -900,6 +901,7 @@ "name": "Video", "type": "component", "cName": "视频播放器", + "tarodoc": true, "desc": "原生video实现的视频播放器", "sort": 20, "show": true, From 0e01d99b93e5f5d6aae310b9e84c3c25183ebac3 Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Mon, 19 Sep 2022 11:05:37 +0800 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Euploader?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E8=A1=A5=E9=BD=90=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/button/button.tsx | 2 + src/packages/progress/progress.tsx | 2 + .../uploader/__tests__/uploader.spec.tsx | 14 +- src/packages/uploader/demo.scss | 4 +- src/packages/uploader/demo.tsx | 85 +++++++++- src/packages/uploader/doc.en-US.md | 152 ++++++++++++++--- src/packages/uploader/doc.md | 155 +++++++++++++++--- src/packages/uploader/doc.zh-TW.md | 147 ++++++++++++++--- src/packages/uploader/upload.ts | 8 +- src/packages/uploader/uploader.taro.tsx | 11 +- src/packages/uploader/uploader.tsx | 125 ++++++++------ 11 files changed, 556 insertions(+), 149 deletions(-) diff --git a/src/packages/button/button.tsx b/src/packages/button/button.tsx index 4739943f63..dca644186e 100644 --- a/src/packages/button/button.tsx +++ b/src/packages/button/button.tsx @@ -66,6 +66,8 @@ export const Button: FunctionComponent> = (props) => { onClick, className, style, + iconClassPrefix, + iconFontClassName, ...rest } = { ...defaultProps, diff --git a/src/packages/progress/progress.tsx b/src/packages/progress/progress.tsx index 356db2dbe6..8f7264f4ba 100644 --- a/src/packages/progress/progress.tsx +++ b/src/packages/progress/progress.tsx @@ -78,6 +78,8 @@ export const Progress: FunctionComponent< iconSize, rounded, children, + iconClassPrefix, + iconFontClassName, ...rest } = { ...defaultProps, ...props } diff --git a/src/packages/uploader/__tests__/uploader.spec.tsx b/src/packages/uploader/__tests__/uploader.spec.tsx index 84cfa9952d..e4dcadddfd 100644 --- a/src/packages/uploader/__tests__/uploader.spec.tsx +++ b/src/packages/uploader/__tests__/uploader.spec.tsx @@ -24,7 +24,7 @@ test('should render base uploader props', () => { accept=".jpg" maximize={1024 * 50} maximum={2} - change={change} + onChange={change} /> ) const input = container.querySelectorAll('.nut-uploader__input')[0] @@ -77,8 +77,8 @@ test('should render base uploader other props', () => { isPreview uploadIcon="dongdong" uploadIconSize="20px" - removeImage={onDelete} - fileItemClick={fileItemClick} + onRemove={onDelete} + onFileItemClick={fileItemClick} /> ) } @@ -166,8 +166,8 @@ test('before-delete prop return false', () => { { + onRemove={onDelete} + onBeforeDelete={() => { return false }} /> @@ -195,8 +195,8 @@ test('before-delete prop return true', () => { { + onRemove={onDelete} + onBeforeDelete={() => { return true }} /> diff --git a/src/packages/uploader/demo.scss b/src/packages/uploader/demo.scss index 3246a56f83..1619f7386d 100644 --- a/src/packages/uploader/demo.scss +++ b/src/packages/uploader/demo.scss @@ -1,3 +1,3 @@ -.demo.bg-w { - background: #fff; +.demo-uploader { + padding: 57px 17px 15px 17px !important; } diff --git a/src/packages/uploader/demo.tsx b/src/packages/uploader/demo.tsx index 800baabfad..bc632027d1 100644 --- a/src/packages/uploader/demo.tsx +++ b/src/packages/uploader/demo.tsx @@ -1,7 +1,9 @@ -import React, { useRef } from 'react' +import React, { useState, useRef } from 'react' import { useTranslate } from '../../sites/assets/locale' import { Uploader, FileItem, FileType } from './uploader' import Button from '@/packages/button' +import Progress from '@/packages/progress' +import './demo.scss' interface uploadRefState { submit: () => void @@ -17,7 +19,10 @@ interface T { '25e04d44': string d06e873e: string ca3903f3: string + upload_progress_action: string '84aa6bce': string + upload_list_show: string + upload_default_progress: string a4afedb5: string '37c65f47': string bb5caa9c: string @@ -26,6 +31,7 @@ interface T { b7454181: string '5c393e52': string e3217a8d: string + upload_xhr_custom: string '67fffe24': string fcf01d1a: string '7db1a8b2': string @@ -42,7 +48,10 @@ const UploaderDemo = () => { '25e04d44': 'oversize触发文件大小不能超过50kb', d06e873e: 'start触发', ca3903f3: 'delete事件触发', + upload_progress_action: 'progress事件触发', '84aa6bce': '基础用法', + upload_list_show: '基础用法-上传列表展示', + upload_default_progress: '自定义上传使用默认进度条', a4afedb5: '上传状态', '37c65f47': '自定义上传样式', bb5caa9c: '上传文件', @@ -51,6 +60,7 @@ const UploaderDemo = () => { b7454181: '限制上传大小(每个文件最大不超过50kb)', '5c393e52': '图片压缩(在beforeupload钩子中处理)', e3217a8d: '自定义数据 FormData、headers', + upload_xhr_custom: '自定义 xhr 上传方式(before-xhr-upload)', '67fffe24': '选中文件后,通过按钮手动执行上传', fcf01d1a: '执行上传', '7db1a8b2': '禁用状态', @@ -65,7 +75,10 @@ const UploaderDemo = () => { '25e04d44': 'oversize觸發檔大小不能超過50kb', d06e873e: 'start觸發', ca3903f3: 'delete事件觸發', + upload_progress_action: 'progress事件觸發', '84aa6bce': '基础用法', + upload_list_show: '基礎用法-上傳列表展示', + upload_default_progress: '自定義上傳使用默認進度條', a4afedb5: '上傳狀態', '37c65f47': '自定義上傳樣式', bb5caa9c: '上傳檔', @@ -74,6 +87,7 @@ const UploaderDemo = () => { b7454181: '限制上傳大小(每個檔案最大不超過50kb)', '5c393e52': '圖片壓縮(在beforeupload鉤子中處理)', e3217a8d: '自定義數據 FormData、headers', + upload_xhr_custom: '自定義 xhr 上傳方式(before-xhr-upload)', '67fffe24': '選取檔後,通過按鈕手動執行上傳', fcf01d1a: '執行上傳', '7db1a8b2': '禁用狀態', @@ -88,7 +102,10 @@ const UploaderDemo = () => { '25e04d44': 'The oversize trigger file size cannot exceed 50kb', d06e873e: 'start triggered', ca3903f3: 'The delete event is triggered', + upload_progress_action: 'The progress event is triggered', '84aa6bce': 'Basic usage', + upload_list_show: 'Basic usage - upload list display', + upload_default_progress: 'Custom upload uses default progress bar', a4afedb5: 'Upload status', '37c65f47': 'Customize the upload style', bb5caa9c: 'Upload the file', @@ -97,6 +114,7 @@ const UploaderDemo = () => { b7454181: 'Limit upload size (maximum 50kb per file)', '5c393e52': 'Image compression (handled in a foreupload hook)', e3217a8d: 'Custom data FormData, headers', + upload_xhr_custom: 'Custom xhr upload method (before-xhr-upload)', '67fffe24': 'After selecting Chinese, manually perform the upload via the button', fcf01d1a: 'Perform the upload', @@ -104,6 +122,7 @@ const UploaderDemo = () => { }, }) + const [progressPercent, setProgressPercent] = useState(0) const uploadRef = useRef(null) const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' const formData = { @@ -164,6 +183,10 @@ const UploaderDemo = () => { const onStart = () => { console.log(translated.d06e873e) } + const onProgress = ({ event, options, percentage }: any) => { + setProgressPercent(percentage) + console.log(translated.upload_progress_action) + } const onDelete = (file: FileItem, fileList: FileItem[]) => { console.log(translated.ca3903f3, file, fileList) } @@ -180,45 +203,82 @@ const UploaderDemo = () => { const f = await new File([blob], files[0].name, { type: files[0].type }) return [f] } + const beforeXhrUpload = (xhr: XMLHttpRequest, options: any) => { + if (options.method.toLowerCase() == 'put') { + xhr.send(options.sourceFile) + } else { + xhr.send(options.formData) + } + } const submitUpload = () => { ;(uploadRef.current as uploadRefState).submit() } return ( <> -
+

{translated['84aa6bce']}

- +

{translated.a4afedb5}

+ +

{translated.upload_list_show}

+ + + +

{translated['37c65f47']}

+ +

{translated.upload_default_progress}

+ + + +
+ +

{translated['27f1376e']}

-

{translated.a4afedb5}

- +

{translated['0e5eaea3']}

+

{translated.b7454181}

+

{translated['5c393e52']}

- + +

{translated.e3217a8d}

{ headers={formData} withCredentials /> + +

{translated.upload_xhr_custom}

+ +

{translated['67fffe24']}

{ +

{translated['7db1a8b2']}

diff --git a/src/packages/uploader/doc.en-US.md b/src/packages/uploader/doc.en-US.md index cf9b39b0b4..e8ad70610a 100644 --- a/src/packages/uploader/doc.en-US.md +++ b/src/packages/uploader/doc.en-US.md @@ -32,6 +32,62 @@ export default App; ``` ::: +### upload status + +:::demo +``` tsx +import React, { useState } from "react"; +import { Uploader } from '@nutui/nutui-react'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const defaultFileList: FileType[] = [ + { + name: 'file1.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'success', + message: 'Uploaded successfully', + type: 'image', + uid: '123', + }, + { + name: 'file2.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'error', + message: 'upload failed', + type: 'image', + uid: '124', + }, + { + name: 'file3.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'uploading', + message: 'uploading...', + type: 'image', + uid: '125', + }, + ] + const onDelete = (file: FileItem, fileList: FileItem[]) => { + console.log(translated.ca3903f3, file, fileList) + } + return ( + <> +

upload status

+ + + ) +} +export default App; +``` +::: + ### Customize the upload style :::demo @@ -45,7 +101,7 @@ const App = () => { <>

Customize the upload style

- @@ -56,19 +112,33 @@ export default App; ``` ::: -### Direct camera up (mobile) +### Custom upload uses default progress bar :::demo ``` tsx import React, { useState } from "react"; -import { Uploader, Button } from '@nutui/nutui-react'; +import { Uploader, Button, Progress } from '@nutui/nutui-react'; const App = () => { const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const [progressPercent, setProgressPercent] = useState(0) + const onProgress = ({ event, options, percentage }: any) => { + setProgressPercent(percentage) + } return ( <> -

Direct camera up (mobile)

- +

Custom upload uses default progress bar

+ + + +
+ ) } @@ -76,7 +146,7 @@ export default App; ``` ::: -### Upload status +### Direct camera up (mobile) :::demo ``` tsx @@ -85,13 +155,10 @@ import { Uploader, Button } from '@nutui/nutui-react'; const App = () => { const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' - const onDelete = (file: FileItem, fileList: FileItem[]) => { - console.log('delete event start', file, fileList) - } return ( <> -

Upload status

- +

Direct camera up (mobile)

+ ) } @@ -99,7 +166,6 @@ export default App; ``` ::: - ### Limit the number of uploads to 5 :::demo @@ -172,6 +238,36 @@ export default App; ``` ::: +### Custom xhr upload method (before-xhr-upload) +:::demo +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const beforeXhrUpload = (xhr: XMLHttpRequest, options: any) => { + if (options.method.toLowerCase() == 'put') { + xhr.send(options.sourceFile); + } else { + xhr.send(options.formData); + } + }; + return ( + <> +

Custom xhr upload method (before-xhr-upload)

+ + + ) +} +export default App; +``` +::: + ### Manual upload :::demo @@ -223,27 +319,32 @@ export default App; | Attribute |Description | Type | Default | |-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|------------------| +| autoUpload | Whether to upload the file immediately after selecting it, if false, you need to manually execute the ref submit method to upload | Boolean | true | | name | The name of the `input` tag `name`, the file parameter name sent to the background | String | "file" | | url | The interface address of the upload server | String | - | +| defaultFileList | List of uploaded files by default | FileItem[] | [] | | isPreview | Whether to display the preview image after the upload is successful | Boolean | true | | defaultImg | When uploading a default image URL in a non-image ('image') format | String | '' | | isDeletable | Whether to display the delete button | Boolean | true | | method | The http method of upload request | String | "post" | +| listType | The built-in style of the upload list, supports two basic styles picture, list | String | "picture" | | capture | Capture, can be set to[camera](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#htmlattrdefcapture),,turn on the camera directly | String | false | | maximize | You can set the maximum upload file size (bytes) | Number丨String | Number.MAX_VALUE | | maximum | File upload limit | Number丨String | 1 | -| clearInput | Whether to clear the `input` content, set to `true` to support repeated selection and upload of the same file | Boolean | false | +| clearInput | Whether to clear the `input` content, set to `true` to support repeated selection and upload of the same file | Boolean | true | | accept | File types that can be accepted. See[Des](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/Input/file#%E9%99%90%E5%88%B6%E5%85%81%E8%AE%B8%E7%9A%84%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B) | String | * | | headers | Set request headers | Object | {} | | data | Uploading extra params or function which can return uploading extra params formData | Object | {} | | uploadIcon | Upload area[icon name](#/zh-CN/icon)or image link | String | "photograph" | +| uploadIconSize | Upload area [icon size](#/icon) size, such as `20px` `2em` `2rem` | String or Number | - | | xhrState | The success status (status) value of the interface response | Number | 200 | -| withCredentials | The ajax upload with cookie sent | Boolean | fasle | -| multiple | Whether to support multiple file selection | Boolean | fasle | -| disabled | Whether to disable file upload | Boolean | fasle | +| withCredentials | Support for sending cookie credential information | Boolean | false | +| multiple | Whether to support multiple file selection | Boolean | false | +| disabled | Whether to disable file upload | Boolean | false | | timeout | timeout, in milliseconds | Number丨String | 1000 * 30 | -| beforeUpload | Hook before reading the file, return false to stop reading the file, can return Promise | Function | null | -| beforeDelete | Hook before delete the file, return false to stop reading the file, can return Promise | Function(file): boolean 丨Promise | - | +| onBeforeUpload | The pre-upload function needs to return a `Promise` object | Function | null | +| onBeforeXhrUpload | When performing an XHR upload, the custom method | Function(xhr,option) | null | +| onBeforeDelete | Callback when file is removed. If the return value is false, it will not be removed. Supports returning a `Promise` object, which is not removed when the `Promise` object resolves(false) or rejects | Function(file): boolean 丨Promise | - | @@ -262,11 +363,12 @@ export default App; | Event | Description | Arguments | |----------|------------------------|----------------------| -| start | File upload starts | options | -| progress | The progress of the file upload | event,options | -| oversize | Triggered when the file size exceeds the limit | files | -| success | Uploaded successfully | responseText,options | -| failure | Upload failed | responseText,options | -| change | The state when the uploaded file changes | fileList,event | -| removeImage | File delete event | files,fileList | +| onStart | File upload starts | options | +| onProgress | The progress of the file upload | event,options,percentage | +| onOversize | Triggered when the file size exceeds the limit | files | +| onSuccess | Uploaded successfully | responseText,options | +| onFailure | Upload failed | responseText,options | +| onChange | The state when the uploaded file changes | fileList,event | +| onRemove | The state before the file was deleted | files,fileList | +| onFileItemClick | File delete event | fileItem | diff --git a/src/packages/uploader/doc.md b/src/packages/uploader/doc.md index 98605b1034..506e2e8af7 100644 --- a/src/packages/uploader/doc.md +++ b/src/packages/uploader/doc.md @@ -32,6 +32,62 @@ export default App; ``` ::: +### 上传状态 + +:::demo +``` tsx +import React, { useState } from "react"; +import { Uploader } from '@nutui/nutui-react'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const defaultFileList: FileType[] = [ + { + name: '文件1.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'success', + message: '上传成功', + type: 'image', + uid: '123', + }, + { + name: '文件2.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'error', + message: '上传失败', + type: 'image', + uid: '124', + }, + { + name: '文件3.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'uploading', + message: '上传中...', + type: 'image', + uid: '125', + }, + ] + const onDelete = (file: FileItem, fileList: FileItem[]) => { + console.log(translated.ca3903f3, file, fileList) + } + return ( + <> +

上传状态

+ + + ) +} +export default App; +``` +::: + ### 自定义上传样式 :::demo @@ -45,7 +101,7 @@ const App = () => { <>

自定义上传样式

- @@ -56,19 +112,33 @@ export default App; ``` ::: -### 直接调起摄像头(移动端生效) +### 自定义上传使用默认进度条 :::demo ``` tsx import React, { useState } from "react"; -import { Uploader, Button } from '@nutui/nutui-react'; +import { Uploader, Button, Progress } from '@nutui/nutui-react'; const App = () => { const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const [progressPercent, setProgressPercent] = useState(0) + const onProgress = ({ event, options, percentage }: any) => { + setProgressPercent(percentage) + } return ( <> -

直接调起摄像头(移动端生效)

- +

自定义上传使用默认进度条

+ + + +
+ ) } @@ -76,7 +146,7 @@ export default App; ``` ::: -### 上传状态 +### 直接调起摄像头(移动端生效) :::demo ``` tsx @@ -85,13 +155,10 @@ import { Uploader, Button } from '@nutui/nutui-react'; const App = () => { const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' - const onDelete = (file: FileItem, fileList: FileItem[]) => { - console.log('delete 事件触发', file, fileList) - } return ( <> -

上传状态

- +

直接调起摄像头(移动端生效)

+ ) } @@ -99,7 +166,6 @@ export default App; ``` ::: - ### 限制上传数量5个 :::demo @@ -120,7 +186,7 @@ export default App; ``` ::: -### 限制上传大小(每个文件最大不超过 50kb,也可以在beforeupload中自行处理) +### 限制上传大小(每个文件最大不超过 50kb) :::demo ``` tsx @@ -172,6 +238,37 @@ export default App; ``` ::: +### 自定义 xhr 上传方式(before-xhr-upload) + +:::demo +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const beforeXhrUpload = (xhr: XMLHttpRequest, options: any) => { + if (options.method.toLowerCase() == 'put') { + xhr.send(options.sourceFile); + } else { + xhr.send(options.formData); + } + }; + return ( + <> +

自定义 xhr 上传方式(before-xhr-upload)

+ + + ) +} +export default App; +``` +::: + ### 手动上传 :::demo @@ -223,27 +320,32 @@ export default App; | 字段 | 说明 | 类型 | 默认值 | |-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|------------------| +| autoUpload | 是否在选取文件后立即进行上传,false 时需要手动执行 ref submit 方法进行上传 | Boolean | true | | name | `input` 标签 `name` 的名称,发到后台的文件参数名 | String | "file" | | url | 上传服务器的接口地址 | String | - | +| defaultFileList | 默认已经上传的文件列表 | FileItem[] | [] | | isPreview | 是否上传成功后展示预览图 | Boolean | true | | defaultImg | 当上传非图片('image')格式的默认图片地址 | String | '' | | isDeletable | 是否展示删除按钮 | Boolean | true | | method | 上传请求的 http method | String | "post" | +| listType | 上传列表的内建样式,支持两种基本样式 picture、list | String | "picture" | | capture | 图片[选取模式](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#htmlattrdefcapture),直接调起摄像头 | String | false | | maximize | 可以设定最大上传文件的大小(字节) | Number丨String | Number.MAX_VALUE | | maximum | 文件上传数量限制 | Number丨String | 1 | -| clearInput | 是否需要清空`input`内容,设为`true`支持重复选择上传同一个文件 | Boolean | false | +| clearInput | 是否需要清空`input`内容,设为`true`支持重复选择上传同一个文件 | Boolean | true | | accept | 允许上传的文件类型,[详细说明](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/Input/file#%E9%99%90%E5%88%B6%E5%85%81%E8%AE%B8%E7%9A%84%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B) | String | * | | headers | 设置上传的请求头部 | Object | {} | | data | 附加上传的信息 formData | Object | {} | | uploadIcon | 上传区域[图标名称](#/zh-CN/icon)或图片链接 | String | "photograph" | +| uploadIconSize | 上传区域[图标尺寸](#/icon)大小,如 `20px` `2em` `2rem` | String or Number | - | | xhrState | 接口响应的成功状态(status)值 | Number | 200 | -| withCredentials | 支持发送 cookie 凭证信息 | Boolean | fasle | -| multiple | 是否支持文件多选 | Boolean | fasle | -| disabled | 是否禁用文件上传 | Boolean | fasle | +| withCredentials | 支持发送 cookie 凭证信息 | Boolean | false | +| multiple | 是否支持文件多选 | Boolean | false | +| disabled | 是否禁用文件上传 | Boolean | false | | timeout | 超时时间,单位为毫秒 | Number丨String | 1000 * 30 | -| beforeUpload | 上传前的函数需要返回一个`Promise`对象 | Function | null | -| beforeDelete | 除文件时的回调,返回值为 false 时不移除。支持返回一个 `Promise` 对象,`Promise` 对象 resolve(false) 或 reject 时不移除 | Function(file): boolean 丨Promise | - | +| onBeforeUpload | 上传前的函数需要返回一个`Promise`对象 | Function | null | +| onBeforeXhrUpload | 执行 XHR 上传时,自定义方式 | Function(xhr,option) | null | +| onBeforeDelete | 除文件时的回调,返回值为 false 时不移除。支持返回一个 `Promise` 对象,`Promise` 对象 resolve(false) 或 reject 时不移除 | Function(file): boolean 丨Promise | - | @@ -262,11 +364,12 @@ export default App; | 名称 | 说明 | 回调参数 | |----------|------------------------|----------------------| -| start | 文件上传开始 | options | -| progress | 文件上传的进度 | event,options | -| oversize | 文件大小超过限制时触发 | files | -| success | 上传成功 | responseText,options | -| failure | 上传失败 | responseText,options | -| change | 上传文件改变时的状态 | fileList,event | -| removeImage | 文件删除之前的状态 | files,fileList | +| onStart | 文件上传开始 | options | +| onProgress | 文件上传的进度 | event,options,percentage | +| onOversize | 文件大小超过限制时触发 | files | +| onSuccess | 上传成功 | responseText,options | +| onFailure | 上传失败 | responseText,options | +| onChange | 上传文件改变时的状态 | fileList,event | +| onRemove | 文件删除之前的状态 | files,fileList | +| onFileItemClick | 文件上传成功后点击触发 | fileItem | diff --git a/src/packages/uploader/doc.zh-TW.md b/src/packages/uploader/doc.zh-TW.md index ade303da81..5f0696e07c 100644 --- a/src/packages/uploader/doc.zh-TW.md +++ b/src/packages/uploader/doc.zh-TW.md @@ -32,6 +32,62 @@ export default App; ``` ::: +### 上传状态 + +:::demo +``` tsx +import React, { useState } from "react"; +import { Uploader } from '@nutui/nutui-react'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const defaultFileList: FileType[] = [ + { + name: '檔1.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'success', + message: '上傳成功', + type: 'image', + uid: '123', + }, + { + name: '檔2.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'error', + message: '上傳失敗', + type: 'image', + uid: '124', + }, + { + name: '檔3.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'uploading', + message: '上傳中...', + type: 'image', + uid: '125', + }, + ] + const onDelete = (file: FileItem, fileList: FileItem[]) => { + console.log(translated.ca3903f3, file, fileList) + } + return ( + <> +

上傳狀態

+ + + ) +} +export default App; +``` +::: + ### 自定義上傳樣式 :::demo @@ -45,7 +101,7 @@ const App = () => { <>

自定義上傳樣式

- @@ -56,19 +112,33 @@ export default App; ``` ::: -### 直接調起攝像頭(移動端生效) +### 自定義上傳使用默認進度條 :::demo ``` tsx import React, { useState } from "react"; -import { Uploader, Button } from '@nutui/nutui-react'; +import { Uploader, Button, Progress } from '@nutui/nutui-react'; const App = () => { const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const [progressPercent, setProgressPercent] = useState(0) + const onProgress = ({ event, options, percentage }: any) => { + setProgressPercent(percentage) + } return ( <> -

直接調起攝像頭(移動端生效)

- +

自定義上傳使用默認進度條

+ + + +
+ ) } @@ -76,7 +146,7 @@ export default App; ``` ::: -### 上傳狀態 +### 直接調起攝像頭(移動端生效) :::demo ``` tsx @@ -85,13 +155,10 @@ import { Uploader, Button } from '@nutui/nutui-react'; const App = () => { const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' - const onDelete = (file: FileItem, fileList: FileItem[]) => { - console.log('delete 事件觸發', file, fileList) - } return ( <> -

上傳狀態

- +

直接調起攝像頭(移動端生效)

+ ) } @@ -99,7 +166,6 @@ export default App; ``` ::: - ### 限制上傳數量5個 :::demo @@ -120,7 +186,7 @@ export default App; ``` ::: -### 限制上傳大小(每個文件最大不超過 50kb,也可以在beforeupload中自行處理) +### 限制上傳大小(每個文件最大不超過 50kb) :::demo ``` tsx @@ -172,6 +238,37 @@ export default App; ``` ::: +### 自定義 xhr 上傳方式(before-xhr-upload) + +:::demo +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const beforeXhrUpload = (xhr: XMLHttpRequest, options: any) => { + if (options.method.toLowerCase() == 'put') { + xhr.send(options.sourceFile); + } else { + xhr.send(options.formData); + } + }; + return ( + <> +

自定義 xhr 上傳方式(before-xhr-upload)

+ + + ) +} +export default App; +``` +::: + ### 手動上傳 :::demo @@ -223,12 +320,15 @@ export default App; | 字段 | 說明 | 類型 | 默認值 | |-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|------------------| +| autoUpload | 是否在選取文件後立即進行上傳,false 時需要手動執行 ref submit 方法進行上傳 | Boolean | true | | name | `input` 標籤 `name` 的名稱,發到後台的文件參數名 | String | "file" | | url | 上傳服務器的接口地址 | String | - | +| defaultFileList | 默認已經上傳的文件列表 | FileItem[] | [] | | isPreview | 是否上傳成功後展示預覽圖 | Boolean | true | | defaultImg | 當上傳非圖片('image')格式的默認圖片地址 | String | '' | | isDeletable | 是否展示刪除按鈕 | Boolean | true | | method | 上傳請求的 http method | String | "post" | +| listType | 上傳列表的內建樣式,支持兩種基本樣式 picture、list | String | "picture" | | capture | 圖片[選取模式](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#htmlattrdefcapture),直接調起攝像頭 | String | false | | maximize | 可以設定最大上傳文件的大小(字節) | Number丨String | Number.MAX_VALUE | | maximum | 文件上傳數量限制 | Number丨String | 1 | @@ -237,13 +337,15 @@ export default App; | headers | 設置上傳的請求頭部 | Object | {} | | data | 附加上傳的信息 formData | Object | {} | | uploadIcon | 上傳區域[圖標名稱](#/zh-CN/icon)或圖片鏈接 | String | "photograph" | +| uploadIconSize | 上傳區域[圖標尺寸](#/icon)大小,如 `20px` `2em` `2rem` | String or Number | - | | xhrState | 接口響應的成功狀態(status)值 | Number | 200 | | withCredentials | 支持發送 cookie 憑證信息 | Boolean | fasle | | multiple | 是否支持文件多選 | Boolean | fasle | | disabled | 是否禁用文件上傳 | Boolean | fasle | | timeout | 超時時間,單位為毫秒 | Number丨String | 1000 * 30 | -| beforeUpload | 上傳前的函數需要返回一個`Promise`對象 | Function | null | -| beforeDelete | 除文件時的回調,返回值為 false 時不移除。支持返回一個 `Promise` 對象,`Promise` 對象 resolve(false) 或 reject 時不移除 | Function(file): boolean 丨Promise | - | +| onBeforeUpload | 上傳前的函數需要返回一個`Promise`對象 | Function | null | +| onBeforeXhrUpload | 執行 XHR 上傳時,自定義方式 | Function(xhr,option) | null | +| onBeforeDelete | 除文件時的回調,返回值為 false 時不移除。支持返回一個 `Promise` 對象,`Promise` 對象 resolve(false) 或 reject 時不移除 | Function(file): boolean 丨Promise | - | @@ -262,11 +364,12 @@ export default App; | 名稱 | 說明 | 回調參數 | |----------|------------------------|----------------------| -| start | 文件上傳開始 | options | -| progress | 文件上傳的進度 | event,options | -| oversize | 文件大小超過限制時觸發 | files | -| success | 上傳成功 | responseText,options | -| failure | 上傳失敗 | responseText,options | -| change | 上傳文件改變時的狀態 | fileList,event | -| removeImage | 文件刪除之前的狀態 | files,fileList | +| onStart | 文件上傳開始 | options | +| onProgress | 文件上傳的進度 | event,options,percentage | +| onOversize | 文件大小超過限制時觸發 | files | +| onSuccess | 上傳成功 | responseText,options | +| onFailure | 上傳失敗 | responseText,options | +| onChange | 上傳文件改變時的狀態 | fileList,event | +| onRemove | 文件刪除之前的狀態 | files,fileList | +| onFileItemClick | 文件上傳成功後點擊觸發 | fileItem | diff --git a/src/packages/uploader/upload.ts b/src/packages/uploader/upload.ts index 8f24e75dfa..cb1c6ff47c 100644 --- a/src/packages/uploader/upload.ts +++ b/src/packages/uploader/upload.ts @@ -7,6 +7,8 @@ export class UploadOptions { formData?: FormData + sourceFile: any + method = 'post' xhrState: string | number = 200 @@ -64,7 +66,11 @@ export class Upload { xhr.setRequestHeader(key, value as string) } options.onStart?.(options) - xhr.send(options.formData) + if (options.beforeXhrUpload) { + options.beforeXhrUpload(xhr, options) + } else { + xhr.send(options.formData) + } } else { console.warn('浏览器不支持 XMLHttpRequest') } diff --git a/src/packages/uploader/uploader.taro.tsx b/src/packages/uploader/uploader.taro.tsx index c1239ed36a..c6e9a3ad20 100644 --- a/src/packages/uploader/uploader.taro.tsx +++ b/src/packages/uploader/uploader.taro.tsx @@ -50,7 +50,7 @@ export interface UploaderProps extends IComponent { sizeType: (keyof sizeType)[] sourceType: (keyof sourceType)[] maximize: number - defaultFileList: FileType[] + defaultFileList: FileItem[] listType: string uploadIcon: string uploadIconSize: string | number @@ -85,9 +85,9 @@ export interface UploaderProps extends IComponent { responseText: XMLHttpRequest['responseText'] option: UploadOptions }) => void - update?: (fileList: any[]) => void + update?: (fileList: FileItem[]) => void oversize?: (file: Taro.chooseImage.ImageFile[]) => void - change?: (param: { fileList: any[] }) => void + change?: (param: { fileList: FileItem[] }) => void beforeUpload?: (file: any[]) => Promise beforeXhrUpload?: ( file: Taro.chooseImage.ImageFile[] @@ -129,7 +129,7 @@ const defaultProps = { export class FileItem { status: FileItemStatus = 'ready' - message = '准备中..' + message: string = '准备中..' uid: string = new Date().getTime().toString() @@ -189,11 +189,10 @@ const InternalUploader: ForwardRefRenderFunction< beforeDelete, ...restProps } = { ...defaultProps, ...props } - const [fileList, setFileList] = useState([]) + const [fileList, setFileList] = useState([]) const [uploadQueue, setUploadQueue] = useState[]>([]) useEffect(() => { - console.log('defaultFileList', defaultFileList) if (defaultFileList) { setFileList(defaultFileList) } diff --git a/src/packages/uploader/uploader.tsx b/src/packages/uploader/uploader.tsx index 894b31af4b..33e0670865 100644 --- a/src/packages/uploader/uploader.tsx +++ b/src/packages/uploader/uploader.tsx @@ -7,6 +7,7 @@ import React, { } from 'react' import classNames from 'classnames' import Icon from '@/packages/icon' +import Progress from '@/packages/progress' import { Upload, UploadOptions } from './upload' import bem from '@/utils/bem' import { useConfig } from '@/packages/configprovider' @@ -48,29 +49,31 @@ export interface UploaderProps extends IComponent { className: string defaultImg: string style: React.CSSProperties - start?: (option: UploadOptions) => void - removeImage?: (file: FileItem, fileList: FileItem[]) => void - success?: (param: { + onStart?: (option: UploadOptions) => void + onRemove?: (file: FileItem, fileList: FileItem[]) => void + onSuccess?: (param: { responseText: XMLHttpRequest['responseText'] option: UploadOptions }) => void - progress?: (param: { + onProgress?: (param: { e: ProgressEvent option: UploadOptions + percentage: string | number }) => void - failure?: (param: { + onFailure?: (param: { responseText: XMLHttpRequest['responseText'] option: UploadOptions }) => void - update?: (fileList: any[]) => void - oversize?: (file: File[]) => void - change?: (param: { + onUpdate?: (fileList: any[]) => void + onOversize?: (file: File[]) => void + onChange?: (param: { fileList: any[] event: React.ChangeEvent }) => void - beforeUpload?: (file: File[]) => Promise - beforeDelete?: (file: FileItem, files: FileItem[]) => boolean - fileItemClick?: (file: FileItem) => void + onBeforeUpload?: (file: File[]) => Promise + onBeforeXhrUpload?: (xhr: XMLHttpRequest, options: any) => void + onBeforeDelete?: (file: FileItem, files: FileItem[]) => boolean + onFileItemClick?: (file: FileItem) => void } const defaultProps = { @@ -93,11 +96,11 @@ const defaultProps = { xhrState: 200, timeout: 1000 * 30, withCredentials: false, - clearInput: false, + clearInput: true, isPreview: true, isDeletable: true, capture: false, - beforeDelete: (file: FileItem, files: FileItem[]) => { + onBeforeDelete: (file: FileItem, files: FileItem[]) => { return true }, } as UploaderProps @@ -115,6 +118,10 @@ export class FileItem { type?: string + path?: string + + percentage: string | number = 0 + formData: FormData = new FormData() } const InternalUploader: ForwardRefRenderFunction< @@ -148,24 +155,26 @@ const InternalUploader: ForwardRefRenderFunction< className, autoUpload, clearInput, - start, - removeImage, - change, - fileItemClick, - progress, - success, - update, - failure, - oversize, - beforeUpload, - beforeDelete, + iconClassPrefix, + iconFontClassName, + onStart, + onRemove, + onChange, + onFileItemClick, + onProgress, + onSuccess, + onUpdate, + onFailure, + onOversize, + onBeforeUpload, + onBeforeXhrUpload, + onBeforeDelete, ...restProps } = { ...defaultProps, ...props } const [fileList, setFileList] = useState([]) const [uploadQueue, setUploadQueue] = useState[]>([]) useEffect(() => { - console.log('defaultFileList', defaultFileList) if (defaultFileList) { setFileList(defaultFileList) } @@ -207,6 +216,10 @@ const InternalUploader: ForwardRefRenderFunction< uploadOption.xhrState = xhrState uploadOption.headers = headers uploadOption.withCredentials = withCredentials + uploadOption.beforeXhrUpload = onBeforeXhrUpload + try { + uploadOption.sourceFile = fileItem.formData.get(name) + } catch (error) {} uploadOption.onStart = (option: UploadOptions) => { clearUploadQueue(index) setFileList((fileList: FileItem[]) => { @@ -219,7 +232,7 @@ const InternalUploader: ForwardRefRenderFunction< }) return [...fileList] }) - start && start(option) + onStart && onStart(option) } uploadOption.onProgress = ( e: ProgressEvent, @@ -230,19 +243,20 @@ const InternalUploader: ForwardRefRenderFunction< if (item.uid === fileItem.uid) { item.status = 'uploading' item.message = locale.uploader.uploading + item.percentage = ((e.loaded / e.total) * 100).toFixed(0) + onProgress && onProgress({ e, option, percentage: item.percentage }) } return item }) return [...fileList] }) - progress && progress({ e, option }) } uploadOption.onSuccess = ( responseText: XMLHttpRequest['responseText'], option: UploadOptions ) => { setFileList((fileList: FileItem[]) => { - update && update(fileList) + onUpdate && onUpdate(fileList) fileList.map((item) => { if (item.uid === fileItem.uid) { item.status = 'success' @@ -252,8 +266,8 @@ const InternalUploader: ForwardRefRenderFunction< }) return [...fileList] }) - success && - success({ + onSuccess && + onSuccess({ responseText, option, }) @@ -272,8 +286,8 @@ const InternalUploader: ForwardRefRenderFunction< }) return [...fileList] }) - failure && - failure({ + onFailure && + onFailure({ responseText, option, }) @@ -330,7 +344,7 @@ const InternalUploader: ForwardRefRenderFunction< return true }) if (oversizes.length) { - oversize && oversize(files) + onOversize && onOversize(files) } if (filterFile.length > maximum) { @@ -346,9 +360,9 @@ const InternalUploader: ForwardRefRenderFunction< const onDelete = (file: FileItem, index: number) => { clearUploadQueue(index) - if (beforeDelete && beforeDelete(file, fileList)) { + if (onBeforeDelete && onBeforeDelete(file, fileList)) { fileList.splice(index, 1) - removeImage && removeImage(file, fileList) + onRemove && onRemove(file, fileList) setFileList([...fileList]) } else { console.log(locale.uploader.deleteWord) @@ -362,8 +376,8 @@ const InternalUploader: ForwardRefRenderFunction< const $el = event.target const { files } = $el - if (beforeUpload) { - beforeUpload(new Array().slice.call(files)).then( + if (onBeforeUpload) { + onBeforeUpload(new Array().slice.call(files)).then( (f: Array) => { const _files: File[] = filterFiles(new Array().slice.call(f)) readFile(_files) @@ -374,7 +388,7 @@ const InternalUploader: ForwardRefRenderFunction< readFile(_files) } - props.change && props.change({ fileList, event }) + onChange && onChange({ fileList, event }) if (clearInput) { clearInputValue($el) @@ -382,7 +396,7 @@ const InternalUploader: ForwardRefRenderFunction< } const handleItemClick = (file: FileItem) => { - fileItemClick && fileItemClick(file) + onFileItemClick && onFileItemClick(file) } return ( @@ -437,8 +451,8 @@ const InternalUploader: ForwardRefRenderFunction< item.status !== 'success' && (
@@ -512,21 +526,28 @@ const InternalUploader: ForwardRefRenderFunction< onClick={() => handleItemClick(item)} >  {item.name}
onDelete(item, index)} /> - {/* 缺少进度条组件,待更新 */} + {item.status === 'uploading' && ( + + )}
)}
@@ -536,8 +557,8 @@ const InternalUploader: ForwardRefRenderFunction< {maximum > fileList.length && listType === 'picture' && !children && (
Date: Mon, 19 Sep 2022 11:11:27 +0800 Subject: [PATCH 05/12] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=A4?= =?UTF-8?q?=E5=A4=84ts=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/uploader/uploader.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/uploader/uploader.tsx b/src/packages/uploader/uploader.tsx index 33e0670865..f1c3d28b31 100644 --- a/src/packages/uploader/uploader.tsx +++ b/src/packages/uploader/uploader.tsx @@ -64,10 +64,10 @@ export interface UploaderProps extends IComponent { responseText: XMLHttpRequest['responseText'] option: UploadOptions }) => void - onUpdate?: (fileList: any[]) => void + onUpdate?: (fileList: FileItem[]) => void onOversize?: (file: File[]) => void onChange?: (param: { - fileList: any[] + fileList: FileItem[] event: React.ChangeEvent }) => void onBeforeUpload?: (file: File[]) => Promise From 2d3542955ed7c793045cc976308d16b72d85ea97 Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Mon, 19 Sep 2022 16:32:47 +0800 Subject: [PATCH 06/12] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E7=89=88=E6=9C=AC=E6=A0=87=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/uploader/doc.en-US.md | 38 +++++++++++++++++++----------- src/packages/uploader/doc.md | 37 ++++++++++++++++++----------- src/packages/uploader/doc.zh-TW.md | 38 +++++++++++++++++++----------- 3 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/packages/uploader/doc.en-US.md b/src/packages/uploader/doc.en-US.md index e8ad70610a..75c426f24f 100644 --- a/src/packages/uploader/doc.en-US.md +++ b/src/packages/uploader/doc.en-US.md @@ -319,7 +319,7 @@ export default App; | Attribute |Description | Type | Default | |-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|------------------| -| autoUpload | Whether to upload the file immediately after selecting it, if false, you need to manually execute the ref submit method to upload | Boolean | true | +| autoUpload `v1.3.4` | Whether to upload the file immediately after selecting it, if false, you need to manually execute the ref submit method to upload | Boolean | true | | name | The name of the `input` tag `name`, the file parameter name sent to the background | String | "file" | | url | The interface address of the upload server | String | - | | defaultFileList | List of uploaded files by default | FileItem[] | [] | @@ -327,7 +327,7 @@ export default App; | defaultImg | When uploading a default image URL in a non-image ('image') format | String | '' | | isDeletable | Whether to display the delete button | Boolean | true | | method | The http method of upload request | String | "post" | -| listType | The built-in style of the upload list, supports two basic styles picture, list | String | "picture" | +| listType `v1.3.4` | The built-in style of the upload list, supports two basic styles picture, list | String | "picture" | | capture | Capture, can be set to[camera](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#htmlattrdefcapture),,turn on the camera directly | String | false | | maximize | You can set the maximum upload file size (bytes) | Number丨String | Number.MAX_VALUE | | maximum | File upload limit | Number丨String | 1 | @@ -336,15 +336,17 @@ export default App; | headers | Set request headers | Object | {} | | data | Uploading extra params or function which can return uploading extra params formData | Object | {} | | uploadIcon | Upload area[icon name](#/zh-CN/icon)or image link | String | "photograph" | -| uploadIconSize | Upload area [icon size](#/icon) size, such as `20px` `2em` `2rem` | String or Number | - | +| uploadIconSize `v1.3.4` | Upload area [icon size](#/icon) size, such as `20px` `2em` `2rem` | String or Number | - | | xhrState | The success status (status) value of the interface response | Number | 200 | | withCredentials | Support for sending cookie credential information | Boolean | false | | multiple | Whether to support multiple file selection | Boolean | false | | disabled | Whether to disable file upload | Boolean | false | | timeout | timeout, in milliseconds | Number丨String | 1000 * 30 | -| onBeforeUpload | The pre-upload function needs to return a `Promise` object | Function | null | -| onBeforeXhrUpload | When performing an XHR upload, the custom method | Function(xhr,option) | null | -| onBeforeDelete | Callback when file is removed. If the return value is false, it will not be removed. Supports returning a `Promise` object, which is not removed when the `Promise` object resolves(false) or rejects | Function(file): boolean 丨Promise | - | +| beforeUpload `v1.3.4(Abandon)` | The pre-upload function needs to return a `Promise` object | Function | null | +| onBeforeUpload `v1.3.4` | The pre-upload function needs to return a `Promise` object | Function | null | +| onBeforeXhrUpload `v1.3.4` | When performing an XHR upload, the custom method | Function(xhr,option) | null | +| beforeDelete `v1.3.4(Abandon)` | Callback when file is removed. If the return value is false, it will not be removed. Supports returning a `Promise` object, which is not removed when the `Promise` object resolves(false) or rejects | Function(file): boolean 丨Promise | - | +| onBeforeDelete `v1.3.4` | Callback when file is removed. If the return value is false, it will not be removed. Supports returning a `Promise` object, which is not removed when the `Promise` object resolves(false) or rejects | Function(file): boolean 丨Promise | - | @@ -363,12 +365,20 @@ export default App; | Event | Description | Arguments | |----------|------------------------|----------------------| -| onStart | File upload starts | options | -| onProgress | The progress of the file upload | event,options,percentage | -| onOversize | Triggered when the file size exceeds the limit | files | -| onSuccess | Uploaded successfully | responseText,options | -| onFailure | Upload failed | responseText,options | -| onChange | The state when the uploaded file changes | fileList,event | -| onRemove | The state before the file was deleted | files,fileList | -| onFileItemClick | File delete event | fileItem | +| onStart `v1.3.4` | File upload starts | options | +| start `v1.3.4(Abandon)` | File upload starts | options | +| onProgress `v1.3.4` | The progress of the file upload | event,options,percentage | +| progress `v1.3.4(Abandon)` | The progress of the file upload | event,options,percentage | +| onOversize `v1.3.4` | Triggered when the file size exceeds the limit | files | +| oversize `v1.3.4(Abandon)` | Triggered when the file size exceeds the limit | files | +| onSuccess `v1.3.4` | Uploaded successfully | responseText,options | +| success `v1.3.4(Abandon)` | Uploaded successfully | responseText,options | +| onFailure `v1.3.4` | Upload failed | responseText,options | +| failure `v1.3.4(Abandon)` | Upload failed | responseText,options | +| onChange `v1.3.4` | The state when the uploaded file changes | fileList,event | +| change `v1.3.4(Abandon)` | The state when the uploaded file changes | fileList,event | +| onRemove `v1.3.4` | The state before the file was deleted | files,fileList | +| remove `v1.3.4(Abandon)` | The state before the file was deleted | files,fileList | +| onFileItemClick `v1.3.4` | File delete event | fileItem | +| fileItemClick `v1.3.4(Abandon)` | File delete event | fileItem | diff --git a/src/packages/uploader/doc.md b/src/packages/uploader/doc.md index 506e2e8af7..d4d24a116d 100644 --- a/src/packages/uploader/doc.md +++ b/src/packages/uploader/doc.md @@ -320,7 +320,7 @@ export default App; | 字段 | 说明 | 类型 | 默认值 | |-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|------------------| -| autoUpload | 是否在选取文件后立即进行上传,false 时需要手动执行 ref submit 方法进行上传 | Boolean | true | +| autoUpload `v1.3.4` | 是否在选取文件后立即进行上传,false 时需要手动执行 ref submit 方法进行上传 | Boolean | true | | name | `input` 标签 `name` 的名称,发到后台的文件参数名 | String | "file" | | url | 上传服务器的接口地址 | String | - | | defaultFileList | 默认已经上传的文件列表 | FileItem[] | [] | @@ -328,7 +328,7 @@ export default App; | defaultImg | 当上传非图片('image')格式的默认图片地址 | String | '' | | isDeletable | 是否展示删除按钮 | Boolean | true | | method | 上传请求的 http method | String | "post" | -| listType | 上传列表的内建样式,支持两种基本样式 picture、list | String | "picture" | +| listType `v1.3.4` | 上传列表的内建样式,支持两种基本样式 picture、list | String | "picture" | | capture | 图片[选取模式](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#htmlattrdefcapture),直接调起摄像头 | String | false | | maximize | 可以设定最大上传文件的大小(字节) | Number丨String | Number.MAX_VALUE | | maximum | 文件上传数量限制 | Number丨String | 1 | @@ -337,15 +337,17 @@ export default App; | headers | 设置上传的请求头部 | Object | {} | | data | 附加上传的信息 formData | Object | {} | | uploadIcon | 上传区域[图标名称](#/zh-CN/icon)或图片链接 | String | "photograph" | -| uploadIconSize | 上传区域[图标尺寸](#/icon)大小,如 `20px` `2em` `2rem` | String or Number | - | +| uploadIconSize `v1.3.4` | 上传区域[图标尺寸](#/icon)大小,如 `20px` `2em` `2rem` | String or Number | - | | xhrState | 接口响应的成功状态(status)值 | Number | 200 | | withCredentials | 支持发送 cookie 凭证信息 | Boolean | false | | multiple | 是否支持文件多选 | Boolean | false | | disabled | 是否禁用文件上传 | Boolean | false | | timeout | 超时时间,单位为毫秒 | Number丨String | 1000 * 30 | -| onBeforeUpload | 上传前的函数需要返回一个`Promise`对象 | Function | null | -| onBeforeXhrUpload | 执行 XHR 上传时,自定义方式 | Function(xhr,option) | null | -| onBeforeDelete | 除文件时的回调,返回值为 false 时不移除。支持返回一个 `Promise` 对象,`Promise` 对象 resolve(false) 或 reject 时不移除 | Function(file): boolean 丨Promise | - | +| beforeUpload `v1.3.4废弃` | 上传前的函数需要返回一个`Promise`对象 | Function | null | +| onBeforeUpload `v1.3.4` | 上传前的函数需要返回一个`Promise`对象 | Function | null | +| onBeforeXhrUpload `v1.3.4` | 执行 XHR 上传时,自定义方式 | Function(xhr,option) | null | +| beforeDelete `v1.3.4废弃` | 除文件时的回调,返回值为 false 时不移除。支持返回一个 `Promise` 对象,`Promise` 对象 resolve(false) 或 reject 时不移除 | Function(file): boolean 丨Promise | - | +| onBeforeDelete `v1.3.4` | 除文件时的回调,返回值为 false 时不移除。支持返回一个 `Promise` 对象,`Promise` 对象 resolve(false) 或 reject 时不移除 | Function(file): boolean 丨Promise | - | @@ -364,12 +366,19 @@ export default App; | 名称 | 说明 | 回调参数 | |----------|------------------------|----------------------| -| onStart | 文件上传开始 | options | -| onProgress | 文件上传的进度 | event,options,percentage | -| onOversize | 文件大小超过限制时触发 | files | -| onSuccess | 上传成功 | responseText,options | -| onFailure | 上传失败 | responseText,options | -| onChange | 上传文件改变时的状态 | fileList,event | -| onRemove | 文件删除之前的状态 | files,fileList | -| onFileItemClick | 文件上传成功后点击触发 | fileItem | +| start `v1.3.4废弃` | 文件上传开始 | options | +| onStart `v1.3.4` | 文件上传开始 | options | +| progress `v1.3.4废弃` | 文件上传的进度 | event,options | +| onProgress `v1.3.4` | 文件上传的进度 | event,options,percentage | +| oversize `v1.3.4废弃` | 文件大小超过限制时触发 | files | +| onOversize `v1.3.4` | 文件大小超过限制时触发 | files | +| success `v1.3.4废弃` | 上传成功 | responseText,options | +| onSuccess `v1.3.4` | 上传成功 | responseText,options | +| failure `v1.3.4废弃` | 上传失败 | responseText,options | +| onFailure `v1.3.4` | 上传失败 | responseText,options | +| onChange `v1.3.4` | 上传文件改变时的状态 | fileList,event | +| change `v1.3.4废弃` | 上传文件改变时的状态 | fileList,event | +| onRemove `v1.3.4` | 文件删除之前的状态 | files,fileList | +| removeImage `v1.3.4废弃` | 文件删除之前的状态 | files,fileList | +| onFileItemClick `v1.3.4` | 文件上传成功后点击触发 | fileItem | diff --git a/src/packages/uploader/doc.zh-TW.md b/src/packages/uploader/doc.zh-TW.md index 5f0696e07c..8956fe31cd 100644 --- a/src/packages/uploader/doc.zh-TW.md +++ b/src/packages/uploader/doc.zh-TW.md @@ -320,7 +320,7 @@ export default App; | 字段 | 說明 | 類型 | 默認值 | |-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|------------------| -| autoUpload | 是否在選取文件後立即進行上傳,false 時需要手動執行 ref submit 方法進行上傳 | Boolean | true | +| autoUpload `v1.3.4` | 是否在選取文件後立即進行上傳,false 時需要手動執行 ref submit 方法進行上傳 | Boolean | true | | name | `input` 標籤 `name` 的名稱,發到後台的文件參數名 | String | "file" | | url | 上傳服務器的接口地址 | String | - | | defaultFileList | 默認已經上傳的文件列表 | FileItem[] | [] | @@ -328,7 +328,7 @@ export default App; | defaultImg | 當上傳非圖片('image')格式的默認圖片地址 | String | '' | | isDeletable | 是否展示刪除按鈕 | Boolean | true | | method | 上傳請求的 http method | String | "post" | -| listType | 上傳列表的內建樣式,支持兩種基本樣式 picture、list | String | "picture" | +| listType `v1.3.4` | 上傳列表的內建樣式,支持兩種基本樣式 picture、list | String | "picture" | | capture | 圖片[選取模式](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#htmlattrdefcapture),直接調起攝像頭 | String | false | | maximize | 可以設定最大上傳文件的大小(字節) | Number丨String | Number.MAX_VALUE | | maximum | 文件上傳數量限制 | Number丨String | 1 | @@ -337,15 +337,17 @@ export default App; | headers | 設置上傳的請求頭部 | Object | {} | | data | 附加上傳的信息 formData | Object | {} | | uploadIcon | 上傳區域[圖標名稱](#/zh-CN/icon)或圖片鏈接 | String | "photograph" | -| uploadIconSize | 上傳區域[圖標尺寸](#/icon)大小,如 `20px` `2em` `2rem` | String or Number | - | +| uploadIconSize `v1.3.4` | 上傳區域[圖標尺寸](#/icon)大小,如 `20px` `2em` `2rem` | String or Number | - | | xhrState | 接口響應的成功狀態(status)值 | Number | 200 | | withCredentials | 支持發送 cookie 憑證信息 | Boolean | fasle | | multiple | 是否支持文件多選 | Boolean | fasle | | disabled | 是否禁用文件上傳 | Boolean | fasle | | timeout | 超時時間,單位為毫秒 | Number丨String | 1000 * 30 | -| onBeforeUpload | 上傳前的函數需要返回一個`Promise`對象 | Function | null | -| onBeforeXhrUpload | 執行 XHR 上傳時,自定義方式 | Function(xhr,option) | null | -| onBeforeDelete | 除文件時的回調,返回值為 false 時不移除。支持返回一個 `Promise` 對象,`Promise` 對象 resolve(false) 或 reject 時不移除 | Function(file): boolean 丨Promise | - | +| beforeUpload `v1.3.4廢棄` | 上傳前的函數需要返回一個`Promise`對象 | Function | null | +| onBeforeUpload `v1.3.4` | 上傳前的函數需要返回一個`Promise`對象 | Function | null | +| onBeforeXhrUpload `v1.3.4` | 執行 XHR 上傳時,自定義方式 | Function(xhr,option) | null | +| beforeDelete `v1.3.4 廢棄` | 除文件時的回調,返回值為 false 時不移除。支持返回一個 `Promise` 對象,`Promise` 對象 resolve(false) 或 reject 時不移除 | Function(file): boolean 丨Promise | - | +| onBeforeDelete `v1.3.4` | 除文件時的回調,返回值為 false 時不移除。支持返回一個 `Promise` 對象,`Promise` 對象 resolve(false) 或 reject 時不移除 | Function(file): boolean 丨Promise | - | @@ -364,12 +366,20 @@ export default App; | 名稱 | 說明 | 回調參數 | |----------|------------------------|----------------------| -| onStart | 文件上傳開始 | options | -| onProgress | 文件上傳的進度 | event,options,percentage | -| onOversize | 文件大小超過限制時觸發 | files | -| onSuccess | 上傳成功 | responseText,options | -| onFailure | 上傳失敗 | responseText,options | -| onChange | 上傳文件改變時的狀態 | fileList,event | -| onRemove | 文件刪除之前的狀態 | files,fileList | -| onFileItemClick | 文件上傳成功後點擊觸發 | fileItem | +| onStart `v1.3.4` | 文件上傳開始 | options | +| start `v1.3.4廢棄` | 文件上傳開始 | options | +| onProgress `v1.3.4` | 文件上傳的進度 | event,options,percentage | +| progress `v1.3.4廢棄` | 文件上傳的進度 | event,options,percentage | +| onOversize `v1.3.4` | 文件大小超過限制時觸發 | files | +| oversize `v1.3.4廢棄` | 文件大小超過限制時觸發 | files | +| onSuccess `v1.3.4` | 上傳成功 | responseText,options | +| success `v1.3.4廢棄` | 上傳成功 | responseText,options | +| onFailure `v1.3.4` | 上傳失敗 | responseText,options | +| failure `v1.3.4廢棄` | 上傳失敗 | responseText,options | +| onChange `v1.3.4` | 上傳文件改變時的狀態 | fileList,event | +| change `v1.3.4廢棄` | 上傳文件改變時的狀態 | fileList,event | +| onRemove `v1.3.4` | 文件刪除之前的狀態 | files,fileList | +| remove `v1.3.4廢棄` | 文件刪除之前的狀態 | files,fileList | +| onFileItemClick `v1.3.4` | 文件上傳成功後點擊觸發 | fileItem | +| fileItemClick `v1.3.4廢棄` | 文件上傳成功後點擊觸發 | fileItem | From 0e76e238bc371469065bc143b31046519842a81c Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Mon, 19 Sep 2022 16:50:24 +0800 Subject: [PATCH 07/12] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Duploader=20taro?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0ts=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/uploader/demo.taro.tsx | 2 +- src/packages/uploader/uploader.taro.tsx | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/packages/uploader/demo.taro.tsx b/src/packages/uploader/demo.taro.tsx index 6bd5f3deb4..6e898af38f 100644 --- a/src/packages/uploader/demo.taro.tsx +++ b/src/packages/uploader/demo.taro.tsx @@ -190,7 +190,7 @@ const UploaderDemo = () => { const onStart = () => { console.log(translated.d06e873e) } - const onDelete = (file: FileItem, fileList: FileItem[]) => { + const onDelete = (file: FileItem, fileList: FileType[]) => { console.log(translated.ca3903f3, file, fileList) } const beforeUpload = async (files: File[]) => { diff --git a/src/packages/uploader/uploader.taro.tsx b/src/packages/uploader/uploader.taro.tsx index c6e9a3ad20..6563faf95b 100644 --- a/src/packages/uploader/uploader.taro.tsx +++ b/src/packages/uploader/uploader.taro.tsx @@ -50,7 +50,7 @@ export interface UploaderProps extends IComponent { sizeType: (keyof sizeType)[] sourceType: (keyof sourceType)[] maximize: number - defaultFileList: FileItem[] + defaultFileList: FileType[] listType: string uploadIcon: string uploadIconSize: string | number @@ -72,7 +72,7 @@ export interface UploaderProps extends IComponent { defaultImg: string style: React.CSSProperties start?: (option: UploadOptions) => void - removeImage?: (file: FileItem, fileList: FileItem[]) => void + removeImage?: (file: FileItem, fileList: FileType[]) => void success?: (param: { responseText: XMLHttpRequest['responseText'] option: UploadOptions @@ -85,14 +85,14 @@ export interface UploaderProps extends IComponent { responseText: XMLHttpRequest['responseText'] option: UploadOptions }) => void - update?: (fileList: FileItem[]) => void + update?: (fileList: FileType[]) => void oversize?: (file: Taro.chooseImage.ImageFile[]) => void - change?: (param: { fileList: FileItem[] }) => void + change?: (param: { fileList: FileType[] }) => void beforeUpload?: (file: any[]) => Promise beforeXhrUpload?: ( file: Taro.chooseImage.ImageFile[] ) => Promise - beforeDelete?: (file: FileItem, files: FileItem[]) => boolean + beforeDelete?: (file: FileItem, files: FileType[]) => boolean fileItemClick?: (file: FileItem) => void } @@ -121,7 +121,7 @@ const defaultProps = { isPreview: true, isDeletable: true, capture: false, - beforeDelete: (file: FileItem, files: FileItem[]) => { + beforeDelete: (file: FileItem, files: FileType[]) => { return true }, } as UploaderProps @@ -189,7 +189,7 @@ const InternalUploader: ForwardRefRenderFunction< beforeDelete, ...restProps } = { ...defaultProps, ...props } - const [fileList, setFileList] = useState([]) + const [fileList, setFileList] = useState[]>([]) const [uploadQueue, setUploadQueue] = useState[]>([]) useEffect(() => { @@ -251,7 +251,7 @@ const InternalUploader: ForwardRefRenderFunction< uploadOption.onStart = (option: UploadOptions) => { clearUploadQueue(index) - setFileList((fileList: FileItem[]) => { + setFileList((fileList: FileType[]) => { fileList.map((item) => { if (item.uid === fileItem.uid) { item.status = 'ready' @@ -267,7 +267,7 @@ const InternalUploader: ForwardRefRenderFunction< e: ProgressEvent, option: UploadOptions ) => { - setFileList((fileList: FileItem[]) => { + setFileList((fileList: FileType[]) => { fileList.map((item) => { if (item.uid === fileItem.uid) { item.status = 'uploading' @@ -283,7 +283,7 @@ const InternalUploader: ForwardRefRenderFunction< responseText: XMLHttpRequest['responseText'], option: UploadOptions ) => { - setFileList((fileList: FileItem[]) => { + setFileList((fileList: FileType[]) => { update && update(fileList) fileList.map((item) => { if (item.uid === fileItem.uid) { @@ -304,7 +304,7 @@ const InternalUploader: ForwardRefRenderFunction< responseText: XMLHttpRequest['responseText'], option: UploadOptions ) => { - setFileList((fileList: FileItem[]) => { + setFileList((fileList: FileType[]) => { fileList.map((item) => { if (item.uid === fileItem.uid) { item.status = 'error' @@ -363,7 +363,7 @@ const InternalUploader: ForwardRefRenderFunction< fileItem.url = file.path } - fileList.push(fileItem) + fileList.push(fileItem as any) setFileList([...fileList]) executeUpload(fileItem, index) }) From 566bceddf231c5192037a91905da3c7cea99f22f Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Tue, 20 Sep 2022 10:50:48 +0800 Subject: [PATCH 08/12] =?UTF-8?q?feat:=20=E6=8F=90=E4=BA=A4taro=E9=80=82?= =?UTF-8?q?=E9=85=8D=E6=96=87=E6=A1=A3=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config.json | 1 + src/packages/uploader/demo.taro.tsx | 154 ++++++---- src/packages/uploader/doc.taro.md | 377 ++++++++++++++++++++++++ src/packages/uploader/uploader.taro.tsx | 122 ++++---- 4 files changed, 537 insertions(+), 117 deletions(-) create mode 100644 src/packages/uploader/doc.taro.md diff --git a/src/config.json b/src/config.json index aa2371e84b..ab5f965b81 100644 --- a/src/config.json +++ b/src/config.json @@ -530,6 +530,7 @@ "version": "0.1.0", "name": "Uploader", "type": "component", + "tarodoc": true, "cName": "上传", "desc": "用于将本地的图片或文件上传至服务器。", "sort": 1, diff --git a/src/packages/uploader/demo.taro.tsx b/src/packages/uploader/demo.taro.tsx index 6e898af38f..5ca8bcc8a5 100644 --- a/src/packages/uploader/demo.taro.tsx +++ b/src/packages/uploader/demo.taro.tsx @@ -1,7 +1,7 @@ -import React, { useRef } from 'react' +import React, { useState, useRef } from 'react' import Taro from '@tarojs/taro' import { useTranslate } from '@/sites/assets/locale/taro' -import { Button, Uploader } from '@/packages/nutui.react.taro' +import { Button, Uploader, Progress } from '@/packages/nutui.react.taro' export type FileItemStatus = | 'ready' @@ -23,8 +23,12 @@ export class FileItem { url?: string + path?: string + type?: string + percentage: string | number = 0 + formData: FormData = new FormData() } @@ -42,7 +46,10 @@ interface T { '25e04d44': string d06e873e: string ca3903f3: string + upload_progress_action: string '84aa6bce': string + upload_list_show: string + upload_default_progress: string a4afedb5: string '37c65f47': string bb5caa9c: string @@ -51,6 +58,7 @@ interface T { b7454181: string '5c393e52': string e3217a8d: string + upload_xhr_custom: string '67fffe24': string fcf01d1a: string '7db1a8b2': string @@ -67,7 +75,10 @@ const UploaderDemo = () => { '25e04d44': 'oversize触发文件大小不能超过50kb', d06e873e: 'start触发', ca3903f3: 'delete事件触发', + upload_progress_action: 'progress事件触发', '84aa6bce': '基础用法', + upload_list_show: '基础用法-上传列表展示', + upload_default_progress: '自定义上传使用默认进度条', a4afedb5: '上传状态', '37c65f47': '自定义上传样式', bb5caa9c: '上传文件', @@ -76,6 +87,7 @@ const UploaderDemo = () => { b7454181: '限制上传大小(每个文件最大不超过50kb)', '5c393e52': '图片压缩(在beforeupload钩子中处理)', e3217a8d: '自定义数据 FormData、headers', + upload_xhr_custom: '自定义 Taro.uploadFile 上传方式(before-xhr-upload)', '67fffe24': '选中文件后,通过按钮手动执行上传', fcf01d1a: '执行上传', '7db1a8b2': '禁用状态', @@ -90,7 +102,10 @@ const UploaderDemo = () => { '25e04d44': 'oversize觸發檔大小不能超過50kb', d06e873e: 'start觸發', ca3903f3: 'delete事件觸發', + upload_progress_action: 'progress事件觸發', '84aa6bce': '基础用法', + upload_list_show: '基礎用法-上傳列表展示', + upload_default_progress: '自定義上傳使用默認進度條', a4afedb5: '上傳狀態', '37c65f47': '自定義上傳樣式', bb5caa9c: '上傳檔', @@ -99,6 +114,7 @@ const UploaderDemo = () => { b7454181: '限制上傳大小(每個檔案最大不超過50kb)', '5c393e52': '圖片壓縮(在beforeupload鉤子中處理)', e3217a8d: '自定義數據 FormData、headers', + upload_xhr_custom: '自定義 Taro.uploadFile 上傳方式(before-xhr-upload)', '67fffe24': '選取檔後,通過按鈕手動執行上傳', fcf01d1a: '執行上傳', '7db1a8b2': '禁用狀態', @@ -113,7 +129,10 @@ const UploaderDemo = () => { '25e04d44': 'The oversize trigger file size cannot exceed 50kb', d06e873e: 'start triggered', ca3903f3: 'The delete event is triggered', + upload_progress_action: 'The progress event is triggered', '84aa6bce': 'Basic usage', + upload_list_show: 'Basic usage - upload list display', + upload_default_progress: 'Custom upload uses default progress bar', a4afedb5: 'Upload status', '37c65f47': 'Customize the upload style', bb5caa9c: 'Upload the file', @@ -122,6 +141,8 @@ const UploaderDemo = () => { b7454181: 'Limit upload size (maximum 50kb per file)', '5c393e52': 'Image compression (handled in a foreupload hook)', e3217a8d: 'Custom data FormData, headers', + upload_xhr_custom: + 'Custom xhr Taro.uploadFile method (before-xhr-upload)', '67fffe24': 'After selecting Chinese, manually perform the upload via the button', fcf01d1a: 'Perform the upload', @@ -129,6 +150,7 @@ const UploaderDemo = () => { }, }) + const [progressPercent, setProgressPercent] = useState(0) const uploadRef = useRef(null) const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' const formData = { @@ -160,51 +182,51 @@ const UploaderDemo = () => { uid: '125', }, ] - const fileToDataURL = (file: Blob): Promise => { - return new Promise((resolve) => { - const reader = new FileReader() - // todo hanyu - reader.onloadend = (e) => resolve((e.target as FileReader).result) - reader.readAsDataURL(file) - }) - } - const dataURLToImage = (dataURL: string): Promise => { - return new Promise((resolve) => { - const img = new Image() - img.onload = () => resolve(img) - img.src = dataURL - }) - } - const canvastoFile = ( - canvas: HTMLCanvasElement, - type: string, - quality: number - ): Promise => { - return new Promise((resolve) => - canvas.toBlob((blob) => resolve(blob), type, quality) - ) - } const onOversize = (files: Taro.chooseImage.ImageFile[]) => { console.log(translated['25e04d44'], files) } const onStart = () => { console.log(translated.d06e873e) } + const onProgress = ({ event, options, percentage }: any) => { + setProgressPercent(percentage) + console.log(translated.upload_progress_action) + } const onDelete = (file: FileItem, fileList: FileType[]) => { console.log(translated.ca3903f3, file, fileList) } - const beforeUpload = async (files: File[]) => { - const canvas = document.createElement('canvas') - const context = canvas.getContext('2d') as CanvasRenderingContext2D - const base64 = await fileToDataURL(files[0]) - const img = await dataURLToImage(base64) - canvas.width = img.width - canvas.height = img.height - context.clearRect(0, 0, img.width, img.height) - context.drawImage(img, 0, 0, img.width, img.height) - const blob = (await canvastoFile(canvas, 'image/jpeg', 0.5)) as Blob - const f = await new File([blob], files[0].name, { type: files[0].type }) - return [f] + const beforeXhrUpload = (taroUploadFile: any, options: any) => { + const uploadTask = taroUploadFile({ + url: options.url, + filePath: options.taroFilePath, + fileType: options.fileType, + header: { + 'Content-Type': 'multipart/form-data', + ...options.headers, + }, + formData: options.formData, + name: options.name, + success(response: { errMsg: any; statusCode: number; data: string }) { + if (options.xhrState == response.statusCode) { + options.onSuccess?.(response, options) + } else { + options.onFailure?.(response, options) + } + }, + fail(e: any) { + options.onFailure?.(e, options) + }, + }) + options.onStart?.(options) + uploadTask.progress( + (res: { + progress: any + totalBytesSent: any + totalBytesExpectedToSend: any + }) => { + options.onProgress?.(res, options) + } + ) } const submitUpload = () => { ;(uploadRef.current as uploadRefState).submit() @@ -213,45 +235,72 @@ const UploaderDemo = () => { <>

{translated['84aa6bce']}

- +

{translated.a4afedb5}

+ +

{translated.upload_list_show}

+ + + +

{translated['37c65f47']}

+ +

{translated.upload_default_progress}

+ + + +
+ +

{translated['27f1376e']}

- -

{translated.a4afedb5}

- + +

{translated['0e5eaea3']}

- + +

{translated.b7454181}

-

{translated['5c393e52']}

- +

{translated.e3217a8d}

+ + +

{translated.upload_xhr_custom}

+

{translated['67fffe24']}

{ +

{translated['7db1a8b2']}

diff --git a/src/packages/uploader/doc.taro.md b/src/packages/uploader/doc.taro.md new file mode 100644 index 0000000000..8f4af16fc4 --- /dev/null +++ b/src/packages/uploader/doc.taro.md @@ -0,0 +1,377 @@ +# uploader-taro 上传 + +### 介绍 + +用于将本地的图片或文件上传至服务器。 + +### 安装 + +``` ts +import { Uploader } from '@nutui/nutui-react-taro'; +``` +### 基本用法 + +``` tsx +import React, { useState } from "react"; +import { Uploader } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const onStart = () => { + console.log('start 触发') + } + return ( + <> +

基础用法

+ + + ) +} +export default App; +``` + +### 上传状态 + +``` tsx +import React, { useState } from "react"; +import { Uploader } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const defaultFileList: FileType[] = [ + { + name: '文件1.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'success', + message: '上传成功', + type: 'image', + uid: '123', + }, + { + name: '文件2.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'error', + message: '上传失败', + type: 'image', + uid: '124', + }, + { + name: '文件3.png', + url: 'https://m.360buyimg.com/babel/jfs/t1/164410/22/25162/93384/616eac6cE6c711350/0cac53c1b82e1b05.gif', + status: 'uploading', + message: '上传中...', + type: 'image', + uid: '125', + }, + ] + const onDelete = (file: FileItem, fileList: FileItem[]) => { + console.log(translated.ca3903f3, file, fileList) + } + return ( + <> +

上传状态

+ + + ) +} +export default App; +``` + +### 自定义上传样式 + +``` tsx +import React, { useState } from "react"; +import { Uploader } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + return ( + <> +

自定义上传样式

+ + + + + ) +} +export default App; +``` + +### 自定义上传使用默认进度条 + +``` tsx +import React, { useState } from "react"; +import { Uploader, Button, Progress } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const [progressPercent, setProgressPercent] = useState(0) + const onProgress = ({ event, options, percentage }: any) => { + setProgressPercent(percentage) + } + return ( + <> +

自定义上传使用默认进度条

+ + + +
+ + + ) +} +export default App; +``` + +### 直接调起摄像头(移动端生效) + +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + return ( + <> +

直接调起摄像头(移动端生效)

+ + + ) +} +export default App; +``` + +### 限制上传数量5个 + +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + return ( + <> +

限制上传数量5个

+ + + ) +} +export default App; +``` + + +### 限制上传大小(每个文件最大不超过 50kb) + +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const onOversize = (files: File[]) => { + console.log('oversize 触发 文件大小不能超过 50kb', files) + } + return ( + <> +

限制上传大小(每个文件最大不超过 50kb)

+ + + ) +} +export default App; +``` + + +### 自定义 FormData headers + +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const formData = { + custom: 'test', + } + return ( + <> +

自定义 FormData headers

+ + + ) +} +export default App; +``` + +### 自定义 xhr 上传方式(before-xhr-upload) + +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const beforeXhrUpload = (taroUploadFile: any, options: any) => { + const uploadTask = taroUploadFile({ + url: options.url, + filePath: options.taroFilePath, + fileType: options.fileType, + header: { + 'Content-Type': 'multipart/form-data', + ...options.headers, + }, + formData: options.formData, + name: options.name, + success(response: { errMsg: any; statusCode: number; data: string }) { + if (options.xhrState == response.statusCode) { + options.onSuccess?.(response, options) + } else { + options.onFailure?.(response, options) + } + }, + fail(e: any) { + options.onFailure?.(e, options) + }, + }) + options.onStart?.(options) + uploadTask.progress( + (res: { + progress: any + totalBytesSent: any + totalBytesExpectedToSend: any + }) => { + options.onProgress?.(res, options) + } + ) + } + return ( + <> +

自定义 xhr 上传方式(before-xhr-upload)

+ + + ) +} +export default App; +``` + +### 手动上传 + + +``` tsx +import React, { useState, useRef } from "react"; +import { Uploader, Button } from '@nutui/nutui-react-taro'; + +const App = () => { + const uploadUrl = 'https://my-json-server.typicode.com/linrufeng/demo/posts' + const uploadRef = useRef(null) + const submitUpload = () => { + uploadRef.current.submit() + } + return ( + <> +

手动上传

+ +
+ + + ) +} +export default App; +``` + + +### 禁用状态 + +``` tsx +import React, { useState } from "react"; +import { Uploader, Button } from '@nutui/nutui-react-taro'; + +const App = () => { + return ( + <> +

禁用状态

+ + + ) +} +export default App; +``` + + +### Prop + +| 字段 | 说明 | 类型 | 默认值 | +|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|------------------| +| autoUpload | 是否在选取文件后立即进行上传,false 时需要手动执行 ref submit 方法进行上传 | Boolean | true | +| name | `input` 标签 `name` 的名称,发到后台的文件参数名 | String | "file" | +| url | 上传服务器的接口地址 | String | - | +| defaultFileList | 默认已经上传的文件列表 | FileItem[] | [] | +| isPreview | 是否上传成功后展示预览图 | Boolean | true | +| defaultImg | 当上传非图片('image')格式的默认图片地址 | String | '' | +| isDeletable | 是否展示删除按钮 | Boolean | true | +| method | 上传请求的 http method | String | "post" | +| listType | 上传列表的内建样式,支持两种基本样式 picture、list | String | "picture" | +| maximize | 可以设定最大上传文件的大小(字节) | Number丨String | Number.MAX_VALUE | +| maximum | 文件上传数量限制 | Number丨String | 1 | +| clearInput | 是否需要清空`input`内容,设为`true`支持重复选择上传同一个文件 | Boolean | true | +| headers | 设置上传的请求头部 | Object | {} | +| data | 附加上传的信息 formData | Object | {} | +| uploadIcon | 上传区域[图标名称](#/zh-CN/icon)或图片链接 | String | "photograph" | +| uploadIconSize | 上传区域[图标尺寸](#/icon)大小,如 `20px` `2em` `2rem` | String or Number | - | +| xhrState | 接口响应的成功状态(status)值 | Number | 200 | +| disabled | 是否禁用文件上传 | Boolean | false | +| timeout | 超时时间,单位为毫秒 | Number丨String | 1000 * 30 | +| onBeforeUpload | 上传前的函数需要返回一个`Promise`对象 | Function | null | +| onBeforeXhrUpload | 执行 XHR 上传时,自定义方式 | Function(xhr,option) | null | +| onBeforeDelete | 除文件时的回调,返回值为 false 时不移除。支持返回一个 `Promise` 对象,`Promise` 对象 resolve(false) 或 reject 时不移除 | Function(file): boolean 丨Promise | - | + + + +### FileItem + +| 名称 | 说明 | 默认值 | +|----------|---------------------------------------------------------|---------------------------------| +| status | 文件状态值,可选'ready,uploading,success,error,removed' | "ready" | +| uid | 文件的唯一标识 | new Date().getTime().toString() | +| name | 文件名称 | "" | +| url | 文件路径 | "" | +| type | 文件类型 | "image/jpeg" | +| formData | 上传所需的data | new FormData() | + +### Event + +| 名称 | 说明 | 回调参数 | +|----------|------------------------|----------------------| +| onStart | 文件上传开始 | options | +| onProgress | 文件上传的进度 | event,options,percentage | +| onOversize | 文件大小超过限制时触发 | files | +| onSuccess | 上传成功 | responseText,options | +| onFailure | 上传失败 | responseText,options | +| onChange | 上传文件改变时的状态 | fileList,event | +| onRemove | 文件删除之前的状态 | files,fileList | +| onFileItemClick | 文件上传成功后点击触发 | fileItem | + diff --git a/src/packages/uploader/uploader.taro.tsx b/src/packages/uploader/uploader.taro.tsx index 6563faf95b..9ca76694a3 100644 --- a/src/packages/uploader/uploader.taro.tsx +++ b/src/packages/uploader/uploader.taro.tsx @@ -8,6 +8,7 @@ import React, { import classNames from 'classnames' import Icon from '@/packages/icon/index.taro' import Button from '@/packages/button/index.taro' +import Progress from '@/packages/progress/index.taro' import Taro from '@tarojs/taro' import { Upload, UploadOptions } from './upload' import bem from '@/utils/bem' @@ -55,45 +56,40 @@ export interface UploaderProps extends IComponent { uploadIcon: string uploadIconSize: string | number name: string - accept: string disabled: boolean autoUpload: boolean - multiple: boolean timeout: number data: object method: string xhrState: number | string headers: object - withCredentials: boolean isPreview: boolean isDeletable: boolean - capture: boolean className: string defaultImg: string style: React.CSSProperties - start?: (option: UploadOptions) => void - removeImage?: (file: FileItem, fileList: FileType[]) => void - success?: (param: { + onStart?: (option: UploadOptions) => void + onRemove?: (file: FileItem, fileList: FileType[]) => void + onSuccess?: (param: { responseText: XMLHttpRequest['responseText'] option: UploadOptions }) => void - progress?: (param: { + onProgress?: (param: { e: ProgressEvent option: UploadOptions + percentage: string | number }) => void - failure?: (param: { + onFailure?: (param: { responseText: XMLHttpRequest['responseText'] option: UploadOptions }) => void - update?: (fileList: FileType[]) => void - oversize?: (file: Taro.chooseImage.ImageFile[]) => void - change?: (param: { fileList: FileType[] }) => void - beforeUpload?: (file: any[]) => Promise - beforeXhrUpload?: ( - file: Taro.chooseImage.ImageFile[] - ) => Promise - beforeDelete?: (file: FileItem, files: FileType[]) => boolean - fileItemClick?: (file: FileItem) => void + onUpdate?: (fileList: FileType[]) => void + onOversize?: (file: Taro.chooseImage.ImageFile[]) => void + onChange?: (param: { fileList: FileType[] }) => void + onBeforeUpload?: (file: Taro.chooseImage.ImageFile[]) => Promise + onBeforeXhrUpload?: (xhr: XMLHttpRequest, options: any) => void + onBeforeDelete?: (file: FileItem, files: FileType[]) => boolean + onFileItemClick?: (file: FileItem) => void } const defaultProps = { @@ -106,10 +102,8 @@ const defaultProps = { uploadIconSize: '', listType: 'picture', name: 'file', - accept: '*', disabled: false, autoUpload: true, - multiple: false, maximize: Number.MAX_VALUE, data: {}, headers: {}, @@ -117,11 +111,9 @@ const defaultProps = { defaultImg: '', xhrState: 200, timeout: 1000 * 30, - withCredentials: false, isPreview: true, isDeletable: true, - capture: false, - beforeDelete: (file: FileItem, files: FileType[]) => { + onBeforeDelete: (file: FileItem, files: FileType[]) => { return true }, } as UploaderProps @@ -141,6 +133,8 @@ export class FileItem { path?: string + percentage: string | number = 0 + formData: any = {} } const InternalUploader: ForwardRefRenderFunction< @@ -153,40 +147,36 @@ const InternalUploader: ForwardRefRenderFunction< uploadIcon, uploadIconSize, name, - accept, defaultFileList, listType, disabled, - multiple, url, defaultImg, headers, timeout, method, xhrState, - withCredentials, data, isPreview, isDeletable, maximum, - capture, maximize, className, autoUpload, sizeType, sourceType, - start, - removeImage, - change, - fileItemClick, - progress, - success, - update, - failure, - oversize, - beforeUpload, - beforeXhrUpload, - beforeDelete, + onStart, + onRemove, + onChange, + onFileItemClick, + onProgress, + onSuccess, + onUpdate, + onFailure, + onOversize, + onBeforeUpload, + onBeforeXhrUpload, + onBeforeDelete, ...restProps } = { ...defaultProps, ...props } const [fileList, setFileList] = useState[]>([]) @@ -228,13 +218,11 @@ const InternalUploader: ForwardRefRenderFunction< // 可以指定是原图还是压缩图,默认二者都有 sizeType: sizeType, sourceType: sourceType, - success: onChange, + success: onChangeFn, }) } const executeUpload = (fileItem: FileItem, index: number) => { - console.log('executeUpload fileItem', fileItem, index) - const uploadOption = new UploadOptions() uploadOption.name = name uploadOption.url = url @@ -245,9 +233,7 @@ const InternalUploader: ForwardRefRenderFunction< uploadOption.xhrState = xhrState uploadOption.headers = headers uploadOption.taroFilePath = fileItem.path - uploadOption.beforeXhrUpload = beforeXhrUpload - - console.log('uploadOption', uploadOption) + uploadOption.beforeXhrUpload = onBeforeXhrUpload uploadOption.onStart = (option: UploadOptions) => { clearUploadQueue(index) @@ -260,23 +246,21 @@ const InternalUploader: ForwardRefRenderFunction< }) return [...fileList] }) - start && start(option) + onStart && onStart(option) } - uploadOption.onProgress = ( - e: ProgressEvent, - option: UploadOptions - ) => { + uploadOption.onProgress = (e: any, option: UploadOptions) => { setFileList((fileList: FileType[]) => { fileList.map((item) => { if (item.uid === fileItem.uid) { item.status = 'uploading' item.message = locale.uploader.uploading + item.percentage = e.progress + onProgress && onProgress({ e, option, percentage: item.percentage }) } }) return [...fileList] }) - progress && progress({ e, option }) } uploadOption.onSuccess = ( @@ -284,7 +268,7 @@ const InternalUploader: ForwardRefRenderFunction< option: UploadOptions ) => { setFileList((fileList: FileType[]) => { - update && update(fileList) + onUpdate && onUpdate(fileList) fileList.map((item) => { if (item.uid === fileItem.uid) { item.status = 'success' @@ -293,8 +277,8 @@ const InternalUploader: ForwardRefRenderFunction< }) return [...fileList] }) - success && - success({ + onSuccess && + onSuccess({ responseText, option, }) @@ -313,8 +297,8 @@ const InternalUploader: ForwardRefRenderFunction< }) return [...fileList] }) - failure && - failure({ + onFailure && + onFailure({ responseText, option, }) @@ -336,6 +320,7 @@ const InternalUploader: ForwardRefRenderFunction< const readFile = (files: Taro.chooseImage.ImageFile[]) => { const imgReg = /\.(png|jpeg|jpg|webp|gif)$/i files.forEach((file: Taro.chooseImage.ImageFile, index: number) => { + console.log('file', file) let fileType = file.type const fileItem = new FileItem() if (!fileType && imgReg.test(file.path)) { @@ -381,7 +366,7 @@ const InternalUploader: ForwardRefRenderFunction< return true }) if (oversizes.length) { - oversize && oversize(files) + onOversize && onOversize(files) } let currentFileLength = filterFile.length + fileList.length @@ -393,20 +378,20 @@ const InternalUploader: ForwardRefRenderFunction< const onDelete = (file: FileItem, index: number) => { clearUploadQueue(index) - if (beforeDelete && beforeDelete(file, fileList)) { + if (onBeforeDelete && onBeforeDelete(file, fileList)) { fileList.splice(index, 1) - removeImage && removeImage(file, fileList) + onRemove && onRemove(file, fileList) setFileList([...fileList]) } else { console.log(locale.uploader.deleteWord) } } - const onChange = (res: Taro.chooseImage.SuccessCallbackResult) => { + const onChangeFn = (res: Taro.chooseImage.SuccessCallbackResult) => { // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 const { tempFiles } = res - if (beforeUpload) { - beforeUpload(tempFiles).then((f: Array) => { + if (onBeforeUpload) { + onBeforeUpload(tempFiles).then((f: Array) => { const _files: Taro.chooseImage.ImageFile[] = filterFiles(f) readFile(_files) }) @@ -415,11 +400,11 @@ const InternalUploader: ForwardRefRenderFunction< readFile(_files) } - props.change && props.change({ fileList }) + onChange && onChange({ fileList }) } const handleItemClick = (file: FileItem) => { - fileItemClick && fileItemClick(file) + onFileItemClick && onFileItemClick(file) } return ( @@ -538,7 +523,14 @@ const InternalUploader: ForwardRefRenderFunction< name="del" onClick={() => onDelete(item, index)} /> - {/* 缺少进度条组件,待更新 */} + {item.status === 'uploading' && ( + + )}
)}
From 81189744110cc689bb4f14830d7afab31bb95090 Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Wed, 21 Sep 2022 09:44:26 +0800 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20infiniteloading=E7=9A=84taro?= =?UTF-8?q?=E9=80=82=E9=85=8D=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/infiniteloading.spec.tsx | 4 +- src/packages/infiniteloading/demo.scss | 3 + src/packages/infiniteloading/demo.taro.tsx | 129 +++++------------- src/packages/infiniteloading/demo.tsx | 8 +- src/packages/infiniteloading/doc.en-US.md | 9 +- src/packages/infiniteloading/doc.md | 9 +- src/packages/infiniteloading/doc.zh-TW.md | 9 +- .../infiniteloading/infiniteloading.taro.tsx | 94 ++++++++----- .../infiniteloading/infiniteloading.tsx | 19 ++- 9 files changed, 130 insertions(+), 154 deletions(-) diff --git a/src/packages/infiniteloading/__tests__/infiniteloading.spec.tsx b/src/packages/infiniteloading/__tests__/infiniteloading.spec.tsx index 3367b2509e..e5083fa112 100644 --- a/src/packages/infiniteloading/__tests__/infiniteloading.spec.tsx +++ b/src/packages/infiniteloading/__tests__/infiniteloading.spec.tsx @@ -8,7 +8,7 @@ import { Infiniteloading } from '../infiniteloading' test('pull base', () => { const refresh = jest.fn() const { container } = render( - + ) const track = container.querySelector('.nut-infiniteloading') @@ -59,7 +59,7 @@ test('infiniteloading base', () => { return ( ) diff --git a/src/packages/infiniteloading/demo.scss b/src/packages/infiniteloading/demo.scss index 4573ec3290..a69c414cd9 100644 --- a/src/packages/infiniteloading/demo.scss +++ b/src/packages/infiniteloading/demo.scss @@ -1,3 +1,6 @@ +.demo-infinite { + min-height: 100vh; +} .infiniteUl { height: 300px; width: 100%; diff --git a/src/packages/infiniteloading/demo.taro.tsx b/src/packages/infiniteloading/demo.taro.tsx index 445a2257db..96fdd0623e 100644 --- a/src/packages/infiniteloading/demo.taro.tsx +++ b/src/packages/infiniteloading/demo.taro.tsx @@ -1,46 +1,39 @@ import React, { useState, useEffect } from 'react' import { useTranslate } from '@/sites/assets/locale/taro' -import { Infiniteloading, Cell, Toast } from '@/packages/nutui.react.taro' +import { Infiniteloading, Cell } from '@/packages/nutui.react.taro' +import Taro from '@tarojs/taro' import '@/packages/infiniteloading/demo.scss' interface T { '83913e71': string '84aa6bce': string eb4236fe: string - '9ed40460': string '1254a90a': string } const InfiniteloadingDemo = () => { const [translated] = useTranslate({ 'zh-CN': { '83913e71': '刷新成功', - '84aa6bce': '基础用法', + '84aa6bce': '基础演示', eb4236fe: '下拉刷新', - '9ed40460': '自定义加载文案', '1254a90a': '没有啦~', }, 'zh-TW': { '83913e71': '刷新成功', - '84aa6bce': '基礎用法', + '84aa6bce': '基礎演示', eb4236fe: '下拉刷新', - '9ed40460': '自定義加載文案', '1254a90a': '沒有啦~', }, 'en-US': { '83913e71': 'Refresh successfully', - '84aa6bce': 'Basic usage', + '84aa6bce': 'Basic demo', eb4236fe: 'Pull down to refresh', - '9ed40460': 'custom loading text', '1254a90a': 'nope~', }, }) - const [defultList, setDefultList] = useState([]) - const [customList, setCustomList] = useState([]) - const [refreshList, setRefreshList] = useState([]) + const [defaultList, setDefaultList] = useState([]) const [hasMore, setHasMore] = useState(true) - const [customHasMore, setCustomHasMore] = useState(true) - const [refreshHasMore, setRefreshHasMore] = useState(true) useEffect(() => { init() @@ -48,44 +41,14 @@ const InfiniteloadingDemo = () => { const loadMore = (done: () => void) => { setTimeout(() => { - const curLen = defultList.length + const curLen = defaultList.length for (let i = curLen; i < curLen + 10; i++) { - defultList.push(`${i}`) + defaultList.push(`${i}`) } - if (defultList.length >= 30) { + if (defaultList.length >= 30) { setHasMore(false) } else { - setDefultList([...defultList]) - } - done() - }, 500) - } - - const refreshLoadMore = (done: () => void) => { - setTimeout(() => { - const curLen = refreshList.length - for (let i = curLen; i < curLen + 10; i++) { - refreshList.push(`${i}`) - } - if (refreshList.length >= 30) { - setRefreshHasMore(false) - } else { - setRefreshList([...refreshList]) - } - done() - }, 500) - } - - const customLoadMore = (done: () => void) => { - setTimeout(() => { - const curLen = customList.length - for (let i = curLen; i < curLen + 10; i++) { - customList.push(`${i}`) - } - if (customList.length >= 30) { - setCustomHasMore(false) - } else { - setCustomList([...customList]) + setDefaultList([...defaultList]) } done() }, 500) @@ -93,64 +56,43 @@ const InfiniteloadingDemo = () => { const refresh = (done: () => void) => { setTimeout(() => { - // Toast.text(translated['83913e71']) - toastShow(translated['83913e71']) + Taro.showToast({ + title: translated['83913e71'], + icon: 'success', + duration: 2000, + }) done() }, 1000) } - const [show, SetShow] = useState(false) - const [toastMsg, SetToastMsg] = useState('') - const toastShow = (msg: any) => { - SetToastMsg(msg) - SetShow(true) - } const init = () => { - for (let i = 0; i < 10; i++) { - defultList.push(`${i}`) - customList.push(`${i}`) - refreshList.push(`${i}`) + for (let i = 0; i < 20; i++) { + defaultList.push(`${i}`) } - setDefultList([...defultList]) - setCustomList([...customList]) - setRefreshList([...refreshList]) + setDefaultList([...defaultList]) } return ( <> -
+

{translated['84aa6bce']}

-
    +
      - {defultList.map((item, index) => { - return ( -
    • - {item} -
    • - ) - })} -
      -
    - - -

    {translated['9ed40460']}

    - -
      - - {customList.map((item, index) => { + {defaultList.map((item, index) => { return (
    • {item} @@ -160,13 +102,6 @@ const InfiniteloadingDemo = () => {
    - { - SetShow(false) - }} - />
) diff --git a/src/packages/infiniteloading/demo.tsx b/src/packages/infiniteloading/demo.tsx index 4a62d6bbe0..b7dcfe21a7 100644 --- a/src/packages/infiniteloading/demo.tsx +++ b/src/packages/infiniteloading/demo.tsx @@ -121,7 +121,7 @@ const InfiniteloadingDemo = () => { containerId="scroll" useWindow={false} hasMore={hasMore} - loadMore={loadMore} + onLoadMore={loadMore} > {defultList.map((item, index) => { return ( @@ -143,8 +143,8 @@ const InfiniteloadingDemo = () => { useWindow={false} isOpenRefresh hasMore={refreshHasMore} - loadMore={refreshLoadMore} - refresh={refresh} + onLoadMore={refreshLoadMore} + onRefresh={refresh} > {refreshList.map((item, index) => { return ( @@ -166,7 +166,7 @@ const InfiniteloadingDemo = () => { loadTxt="loading" loadMoreTxt={translated['1254a90a']} hasMore={customHasMore} - loadMore={customLoadMore} + onLoadMore={customLoadMore} > {customList.map((item, index) => { return ( diff --git a/src/packages/infiniteloading/doc.en-US.md b/src/packages/infiniteloading/doc.en-US.md index 1663de6d65..247b39a521 100644 --- a/src/packages/infiniteloading/doc.en-US.md +++ b/src/packages/infiniteloading/doc.en-US.md @@ -280,6 +280,9 @@ export default App; | 事件名 | 说明 | 回调参数 | |--------|----------------|--------------| -| loadMore | Emitted when continues to load | done() | -| scrollChange | Real-time monitoring of roll height | height | -| refresh | Emitted when pull refresh | done() | \ No newline at end of file +| loadMore `v1.3.4(Abandon)` | Emitted when continues to load | done() | +| onLoadMore `v1.3.4` | Emitted when continues to load | done() | +| scrollChange `v1.3.4(Abandon)` | Real-time monitoring of roll height | height | +| onScrollChange `v1.3.4` | Real-time monitoring of roll height | height | +| refresh `v1.3.4(Abandon)` | Emitted when pull refresh | done() | +| onRefresh `v1.3.4` | Emitted when pull refresh | done() | \ No newline at end of file diff --git a/src/packages/infiniteloading/doc.md b/src/packages/infiniteloading/doc.md index 0f4de004c0..9498c8501a 100644 --- a/src/packages/infiniteloading/doc.md +++ b/src/packages/infiniteloading/doc.md @@ -279,6 +279,9 @@ export default App; | 事件名 | 说明 | 回调参数 | |--------|----------------|--------------| -| loadMore | 继续加载的回调函数 | done 函数,用于关闭加载中状态 | -| scrollChange | 实时监听滚动高度 | 滚动高度 | -| refresh | 下拉刷新事件回调 | done 函数,用于关闭加载中状态 | \ No newline at end of file +| loadMore `v1.3.4废弃` | 继续加载的回调函数 | done 函数,用于关闭加载中状态 | +| onLoadMore `v1.3.4` | 继续加载的回调函数 | done 函数,用于关闭加载中状态 | +| scrollChange `v1.3.4废弃` | 实时监听滚动高度 | 滚动高度 | +| onScrollChange `v1.3.4` | 实时监听滚动高度 | 滚动高度 | +| refresh `v1.3.4废弃` | 下拉刷新事件回调 | done 函数,用于关闭加载中状态 | +| onRefresh `v1.3.4` | 下拉刷新事件回调 | done 函数,用于关闭加载中状态 | \ No newline at end of file diff --git a/src/packages/infiniteloading/doc.zh-TW.md b/src/packages/infiniteloading/doc.zh-TW.md index 3e1e25ec8e..be75ef9e06 100644 --- a/src/packages/infiniteloading/doc.zh-TW.md +++ b/src/packages/infiniteloading/doc.zh-TW.md @@ -280,6 +280,9 @@ export default App; | 事件名 | 說明 | 回調參數 | |--------|----------------|--------------| -| loadMore | 繼續加載的回調函數 | done() | -| scrollChange | 實時監聽滾動高度 | 滾動高度 | -| refresh | 下拉刷新事件回調 | done() | \ No newline at end of file +| loadMore `v1.3.4廢棄` | 繼續加載的回調函數 | done() | +| onLoadMore `v1.3.4` | 繼續加載的回調函數 | done() | +| scrollChange `v1.3.4廢棄` | 實時監聽滾動高度 | 滾動高度 | +| onScrollChange `v1.3.4` | 實時監聽滾動高度 | 滾動高度 | +| refresh `v1.3.4廢棄` | 下拉刷新事件回調 | done() | +| onRefresh `v1.3.4` | 下拉刷新事件回調 | done() | \ No newline at end of file diff --git a/src/packages/infiniteloading/infiniteloading.taro.tsx b/src/packages/infiniteloading/infiniteloading.taro.tsx index fe0ac5e436..ad1aa45175 100644 --- a/src/packages/infiniteloading/infiniteloading.taro.tsx +++ b/src/packages/infiniteloading/infiniteloading.taro.tsx @@ -9,11 +9,8 @@ import { IComponent, ComponentDefaults } from '@/utils/typings' export interface InfiniteloadingProps extends IComponent { hasMore: boolean - threshold: number upperThreshold: number containerId: string - useWindow: boolean - useCapture: boolean isOpenRefresh: boolean pullIcon: string pullTxt: string @@ -22,21 +19,16 @@ export interface InfiniteloadingProps extends IComponent { loadMoreTxt: string className: string style: React.CSSProperties - refresh: (param: () => void) => void - loadMore: (param: () => void) => void - scrollChange: (param: number) => void + onRefresh: (param: () => void) => void + onLoadMore: (param: () => void) => void + onScrollChange: (param: number) => void } -declare let window: Window & { webkitRequestAnimationFrame: any } - const defaultProps = { ...ComponentDefaults, hasMore: true, - threshold: 200, upperThreshold: 40, containerId: '', - useWindow: true, - useCapture: false, isOpenRefresh: false, pullIcon: 'https://img10.360buyimg.com/imagetools/jfs/t1/169863/6/4565/6306/60125948E7e92774e/40b3a0cf42852bcb.png', @@ -47,6 +39,17 @@ const defaultProps = { loadMoreTxt: '哎呀,这里是底部了啦', } as InfiniteloadingProps +interface BaseTouchEvent { + /** 触摸事件,当前停留在屏幕中的触摸点信息的数组 */ + touches: Array + + /** 触摸事件,当前变化的触摸点信息的数组 */ + changedTouches: Array + + preventDefault: any +} +interface ITouchEvent extends BaseTouchEvent {} + export const Infiniteloading: FunctionComponent< Partial & React.HTMLAttributes > = (props) => { @@ -54,11 +57,8 @@ export const Infiniteloading: FunctionComponent< const { children, hasMore, - threshold, upperThreshold, containerId, - useWindow, - useCapture, isOpenRefresh, pullIcon, pullTxt, @@ -66,9 +66,9 @@ export const Infiniteloading: FunctionComponent< loadTxt, loadMoreTxt, className, - refresh, - loadMore, - scrollChange, + onRefresh, + onLoadMore, + onScrollChange, iconClassPrefix, iconFontClassName, } = { @@ -76,15 +76,14 @@ export const Infiniteloading: FunctionComponent< ...props, } const [isInfiniting, setIsInfiniting] = useState(false) - const scroller = useRef(null) + const [topDisScoll, setTopDisScoll] = useState(0) const refreshTop = useRef(null) - const scrollEl = useRef(window) const scrollHeight = useRef(0) const scrollTop = useRef(0) const direction = useRef('down') const isTouching = useRef(false) - const refreshMaxH = useRef(0) const y = useRef(0) + const refreshMaxH = useRef(0) const distance = useRef(0) const b = bem('infiniteloading') @@ -109,10 +108,8 @@ export const Infiniteloading: FunctionComponent< const getStyle = () => { return { - height: distance.current < 0 ? `0px` : `${distance.current}px`, - transition: isTouching.current - ? `height 0s cubic-bezier(0.25,0.1,0.25,1)` - : `height 0.2s cubic-bezier(0.25,0.1,0.25,1)`, + height: topDisScoll < 0 ? `0px` : `${topDisScoll}px`, + transition: `height 0.2s cubic-bezier(0.25,0.1,0.25,1)`, } } @@ -128,9 +125,7 @@ export const Infiniteloading: FunctionComponent< const refreshDone = () => { distance.current = 0 - ;( - refreshTop.current as HTMLDivElement - ).style.height = `${distance.current}px` + setTopDisScoll(0) isTouching.current = false } @@ -151,7 +146,7 @@ export const Infiniteloading: FunctionComponent< direction.current = 'up' } scrollTop.current = e.detail.scrollTop - scrollChange && scrollChange(e.detail.scrollTop) + onScrollChange && onScrollChange(e.detail.scrollTop) } const lower = () => { @@ -159,7 +154,39 @@ export const Infiniteloading: FunctionComponent< return false } setIsInfiniting(true) - loadMore && loadMore(infiniteDone) + onLoadMore && onLoadMore(infiniteDone) + } + + const touchStart = (event: ITouchEvent) => { + if (scrollTop.current == 0 && !isTouching.current && isOpenRefresh) { + y.current = event.touches[0].pageY + isTouching.current = true + } + } + + const touchMove = (event: ITouchEvent) => { + distance.current = event.touches[0].pageY - y.current + if (distance.current > 0 && isTouching.current) { + event.preventDefault() + setTopDisScoll(distance.current) + if (distance.current >= refreshMaxH.current) { + distance.current = refreshMaxH.current + setTopDisScoll(refreshMaxH.current) + } + } else { + distance.current = 0 + setTopDisScoll(0) + isTouching.current = false + } + } + + const touchEnd = () => { + if (distance.current < refreshMaxH.current) { + distance.current = 0 + setTopDisScoll(0) + } else { + onRefresh && onRefresh(refreshDone) + } } return ( @@ -170,6 +197,9 @@ export const Infiniteloading: FunctionComponent< style={{ height: '100%' }} onScroll={scrollAction} onScrollToLower={lower} + onTouchStart={touchStart} + onTouchMove={touchMove} + onTouchEnd={touchEnd} >
@@ -180,7 +210,7 @@ export const Infiniteloading: FunctionComponent< name={pullIcon} /> - {locale.infiniteloading.pullRefreshText || pullTxt} + {pullTxt || locale.infiniteloading.pullRefreshText}
@@ -195,13 +225,13 @@ export const Infiniteloading: FunctionComponent< name={loadIcon} />
- {locale.infiniteloading.loadText || loadTxt} + {loadTxt || locale.infiniteloading.loadText}
) : ( !hasMore && (
- {locale.infiniteloading.loadMoreText || loadMoreTxt} + {loadMoreTxt || locale.infiniteloading.loadMoreText}
) )} diff --git a/src/packages/infiniteloading/infiniteloading.tsx b/src/packages/infiniteloading/infiniteloading.tsx index 64957c56fe..7c9c63d210 100644 --- a/src/packages/infiniteloading/infiniteloading.tsx +++ b/src/packages/infiniteloading/infiniteloading.tsx @@ -20,9 +20,9 @@ export interface InfiniteloadingProps extends IComponent { loadMoreTxt: string className: string style: React.CSSProperties - refresh: (param: () => void) => void - loadMore: (param: () => void) => void - scrollChange: (param: number) => void + onRefresh: (param: () => void) => void + onLoadMore: (param: () => void) => void + onScrollChange: (param: number) => void } declare let window: Window & { webkitRequestAnimationFrame: any } @@ -62,9 +62,9 @@ export const Infiniteloading: FunctionComponent< loadTxt, loadMoreTxt, className, - refresh, - loadMore, - scrollChange, + onRefresh, + onLoadMore, + onScrollChange, iconClassPrefix, iconFontClassName, ...restProps @@ -129,7 +129,7 @@ export const Infiniteloading: FunctionComponent< return false } setIsInfiniting(true) - loadMore && loadMore(infiniteDone) + onLoadMore && onLoadMore(infiniteDone) return true }) } @@ -158,7 +158,6 @@ export const Infiniteloading: FunctionComponent< } const touchMove = (event: any) => { - console.log('touchMove', event) distance.current = event.touches[0].pageY - y.current if (distance.current > 0 && isTouching.current) { event.preventDefault() @@ -188,7 +187,7 @@ export const Infiniteloading: FunctionComponent< refreshTop.current as HTMLDivElement ).style.height = `${distance.current}px` } else { - refresh && refresh(refreshDone) + onRefresh && onRefresh(refreshDone) } } @@ -241,7 +240,7 @@ export const Infiniteloading: FunctionComponent< direction = 'down' } beforeScrollTop.current = resScrollTop - scrollChange && scrollChange(resScrollTop) + onScrollChange && onScrollChange(resScrollTop) return offsetDistance <= threshold && direction === 'down' } From ad138ded1a5513b91305c567abd0e3fad7fe3a1d Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Thu, 22 Sep 2022 16:20:36 +0800 Subject: [PATCH 10/12] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9ts=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/infiniteloading/infiniteloading.taro.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/infiniteloading/infiniteloading.taro.tsx b/src/packages/infiniteloading/infiniteloading.taro.tsx index ad1aa45175..f677ac7315 100644 --- a/src/packages/infiniteloading/infiniteloading.taro.tsx +++ b/src/packages/infiniteloading/infiniteloading.taro.tsx @@ -157,14 +157,14 @@ export const Infiniteloading: FunctionComponent< onLoadMore && onLoadMore(infiniteDone) } - const touchStart = (event: ITouchEvent) => { + const touchStart = (event: any) => { if (scrollTop.current == 0 && !isTouching.current && isOpenRefresh) { y.current = event.touches[0].pageY isTouching.current = true } } - const touchMove = (event: ITouchEvent) => { + const touchMove = (event: any) => { distance.current = event.touches[0].pageY - y.current if (distance.current > 0 && isTouching.current) { event.preventDefault() @@ -194,7 +194,7 @@ export const Infiniteloading: FunctionComponent< className={classes} scrollY id="scroller" - style={{ height: '100%' }} + // style={{ height: '100%' }} onScroll={scrollAction} onScrollToLower={lower} onTouchStart={touchStart} From f6562cac1913855bdc962b372da4f83d7ce5f94c Mon Sep 17 00:00:00 2001 From: liuyijun17 <3476078473@qq.com> Date: Tue, 25 Oct 2022 10:32:32 +0800 Subject: [PATCH 11/12] fix: fix/uploader-324 --- src/packages/uploader/uploader.taro.tsx | 18 ++++++++++-------- src/packages/uploader/uploader.tsx | 19 +++++++++++-------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/packages/uploader/uploader.taro.tsx b/src/packages/uploader/uploader.taro.tsx index 9ca76694a3..1529418bf0 100644 --- a/src/packages/uploader/uploader.taro.tsx +++ b/src/packages/uploader/uploader.taro.tsx @@ -515,14 +515,16 @@ const InternalUploader: ForwardRefRenderFunction< />  {item.name}
- onDelete(item, index)} - /> + {isDeletable && ( + onDelete(item, index)} + /> + )} {item.status === 'uploading' && (  {item.name} - onDelete(item, index)} - /> + {isDeletable && ( + onDelete(item, index)} + /> + )} + {item.status === 'uploading' && ( Date: Tue, 25 Oct 2022 17:11:12 +0800 Subject: [PATCH 12/12] =?UTF-8?q?fix:=20=E6=8F=90=E4=BA=A4on=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E7=9A=84=E7=BB=91=E5=AE=9A=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/avatar/__tests__/avatar.spec.tsx | 2 +- src/packages/avatar/avatar.taro.tsx | 7 +-- src/packages/avatar/avatar.tsx | 8 +-- src/packages/avatar/demo.taro.tsx | 2 +- src/packages/avatar/demo.tsx | 2 +- src/packages/avatar/doc.en-US.md | 5 +- src/packages/avatar/doc.md | 5 +- src/packages/avatar/doc.zh-TW.md | 5 +- src/packages/barrage/doc.en-US.md | 2 +- src/packages/barrage/doc.md | 2 +- src/packages/barrage/doc.zh-TW.md | 2 +- .../__tests__/inputnumber.spec.tsx | 33 +++++++----- src/packages/inputnumber/demo.taro.tsx | 8 ++- src/packages/inputnumber/demo.tsx | 8 ++- src/packages/inputnumber/doc.en-US.md | 22 +++++--- src/packages/inputnumber/doc.md | 22 +++++--- src/packages/inputnumber/doc.zh-TW.md | 22 +++++--- src/packages/inputnumber/inputnumber.taro.tsx | 23 +++++++++ src/packages/inputnumber/inputnumber.tsx | 23 +++++++++ src/packages/step/step.taro.tsx | 5 +- src/packages/step/step.tsx | 5 +- src/packages/steps/__tests__/steps.spec.tsx | 2 +- src/packages/steps/demo.taro.tsx | 2 +- src/packages/steps/demo.tsx | 2 +- src/packages/steps/doc.md | 3 +- src/packages/steps/steps.taro.tsx | 2 + src/packages/steps/steps.tsx | 2 + src/packages/video/demo.taro.tsx | 42 +++++++-------- src/packages/video/demo.tsx | 42 +++++++-------- src/packages/video/doc.en-US.md | 51 ++++++++++--------- src/packages/video/doc.md | 51 ++++++++++--------- src/packages/video/doc.zh-TW.md | 51 ++++++++++--------- src/packages/video/video.taro.tsx | 9 ++++ src/packages/video/video.tsx | 9 ++++ 34 files changed, 296 insertions(+), 185 deletions(-) diff --git a/src/packages/avatar/__tests__/avatar.spec.tsx b/src/packages/avatar/__tests__/avatar.spec.tsx index 384f27842e..b8447ee25d 100644 --- a/src/packages/avatar/__tests__/avatar.spec.tsx +++ b/src/packages/avatar/__tests__/avatar.spec.tsx @@ -70,7 +70,7 @@ test('alt props', () => { test('should emit active-avatarror event', () => { const activeAvatar = jest.fn() const { getByTestId } = render( - + ) fireEvent.click(getByTestId('avatar-click')) expect(activeAvatar).toBeCalled() diff --git a/src/packages/avatar/avatar.taro.tsx b/src/packages/avatar/avatar.taro.tsx index b733660fe9..c47dcff373 100644 --- a/src/packages/avatar/avatar.taro.tsx +++ b/src/packages/avatar/avatar.taro.tsx @@ -25,6 +25,7 @@ export interface AvatarProps extends IComponent { alt: string style: React.CSSProperties activeAvatar: (e: MouseEvent) => void + onActiveAvatar: (e: MouseEvent) => void onError: (e: any) => void } @@ -56,6 +57,7 @@ export const Avatar: FunctionComponent< className, style, activeAvatar, + onActiveAvatar, onError, iconClassPrefix, iconFontClassName, @@ -139,9 +141,8 @@ export const Avatar: FunctionComponent< } const clickAvatar: MouseEventHandler = (e: any) => { - if (props.activeAvatar) { - props.activeAvatar(e) - } + activeAvatar && activeAvatar(e) + onActiveAvatar && onActiveAvatar(e) } console.log( diff --git a/src/packages/avatar/avatar.tsx b/src/packages/avatar/avatar.tsx index 66371a419e..edc8ba945e 100644 --- a/src/packages/avatar/avatar.tsx +++ b/src/packages/avatar/avatar.tsx @@ -25,6 +25,7 @@ export interface AvatarProps extends IComponent { alt: string style: React.CSSProperties activeAvatar: (e: MouseEvent) => void + onActiveAvatar: (e: MouseEvent) => void onError: (e: any) => void } @@ -56,6 +57,7 @@ export const Avatar: FunctionComponent< className, style, activeAvatar, + onActiveAvatar, onError, iconClassPrefix, iconFontClassName, @@ -111,7 +113,6 @@ export const Avatar: FunctionComponent< const avatarLength = (children: any) => { for (let i = 0; i < children.length; i++) { - console.log('child', children[i], children[i].classList) if ( children[i] && children[i].classList && @@ -140,9 +141,8 @@ export const Avatar: FunctionComponent< } const clickAvatar: MouseEventHandler = (e: any) => { - if (props.activeAvatar) { - props.activeAvatar(e) - } + activeAvatar && activeAvatar(e) + onActiveAvatar && onActiveAvatar(e) } return ( diff --git a/src/packages/avatar/demo.taro.tsx b/src/packages/avatar/demo.taro.tsx index 3256873ebb..84401b3c90 100644 --- a/src/packages/avatar/demo.taro.tsx +++ b/src/packages/avatar/demo.taro.tsx @@ -140,7 +140,7 @@ const AvatarDemo = () => {

{translated['43f00872']}

- + diff --git a/src/packages/avatar/demo.tsx b/src/packages/avatar/demo.tsx index 81f407b5db..9bc5d1782e 100644 --- a/src/packages/avatar/demo.tsx +++ b/src/packages/avatar/demo.tsx @@ -142,7 +142,7 @@ const AvatarDemo = () => {

{translated['43f00872']}

- + diff --git a/src/packages/avatar/doc.en-US.md b/src/packages/avatar/doc.en-US.md index ad3fa5063f..d9a6e7feb9 100644 --- a/src/packages/avatar/doc.en-US.md +++ b/src/packages/avatar/doc.en-US.md @@ -191,7 +191,7 @@ const App = () => { } return ( <> - + ) } @@ -226,5 +226,6 @@ export default App; | Event | Description | Type | Arguments | | ---------------- | ------------ | -------- | -------- | -| activeAvatar | Emitted when cell is clicked | Function | event | +| activeAvatar `v1.3.8(Abandon)` | Emitted when cell is clicked | Function | event | +| onActiveAvatar `v1.3.8` | Emitted when cell is clicked | Function | event | | onError | Handler when img load error | Function | event | \ No newline at end of file diff --git a/src/packages/avatar/doc.md b/src/packages/avatar/doc.md index 8420f81e37..ffbd04ab50 100644 --- a/src/packages/avatar/doc.md +++ b/src/packages/avatar/doc.md @@ -194,7 +194,7 @@ const App = () => { } return ( <> - + ) } @@ -229,5 +229,6 @@ export default App; | 字段 | 说明 | 类型 | 回调参数 | | ---------------- | ------------ | -------- | -------- | -| activeAvatar | 点击头像触发事件 | Function | event | +| activeAvatar `v1.3.8废弃` | 点击头像触发事件 | Function | event | +| onActiveAvatar `v1.3.8` | 点击头像触发事件 | Function | event | | onError | 图片加载失败的事件 | Function | event | \ No newline at end of file diff --git a/src/packages/avatar/doc.zh-TW.md b/src/packages/avatar/doc.zh-TW.md index f0606b46e6..d01a5c3fb6 100644 --- a/src/packages/avatar/doc.zh-TW.md +++ b/src/packages/avatar/doc.zh-TW.md @@ -192,7 +192,7 @@ const App = () => { } return ( <> - + ) } @@ -227,5 +227,6 @@ export default App; | 字段 | 說明 | 類型 | 回調參數 | | ---------------- | ------------ | -------- | -------- | -| activeAvatar | 點擊頭像觸發事件 | Function | event | +| activeAvatar `v1.3.8廢棄` | 點擊頭像觸發事件 | Function | event | +| onActiveAvatar `v1.3.8` | 點擊頭像觸發事件 | Function | event | | onError | 圖片加載失敗的事件 | Function | event | \ No newline at end of file diff --git a/src/packages/barrage/doc.en-US.md b/src/packages/barrage/doc.en-US.md index 66881efb0c..8bb1c38e25 100644 --- a/src/packages/barrage/doc.en-US.md +++ b/src/packages/barrage/doc.en-US.md @@ -65,7 +65,7 @@ export default App; | top | Vertical distance of barrage | Number | 10 | | loop | Loop play | Boolean | true | -### Events +### Events API | Event | Description | Arguments | |--------|----------------|--------------| diff --git a/src/packages/barrage/doc.md b/src/packages/barrage/doc.md index e804bf737d..2c3b17c0cd 100644 --- a/src/packages/barrage/doc.md +++ b/src/packages/barrage/doc.md @@ -65,7 +65,7 @@ export default App; | top | 弹幕垂直距离 | Number | 10 | | loop | 是否循环播放 | Boolean | true | -### Events +### Events API | 事件名 | 说明 | 回调参数 | |--------|----------------|--------------| diff --git a/src/packages/barrage/doc.zh-TW.md b/src/packages/barrage/doc.zh-TW.md index fc08f311b6..73aa42e2a1 100644 --- a/src/packages/barrage/doc.zh-TW.md +++ b/src/packages/barrage/doc.zh-TW.md @@ -65,7 +65,7 @@ export default App; | top | 彈幕垂直距離 | Number | 10 | | loop | 是否循環播放 | Boolean | true | -### Events +### Events API | 事件名 | 說明 | 回調參數 | |--------|----------------|--------------| diff --git a/src/packages/inputnumber/__tests__/inputnumber.spec.tsx b/src/packages/inputnumber/__tests__/inputnumber.spec.tsx index d6ba6fecc0..44a97fa4f7 100644 --- a/src/packages/inputnumber/__tests__/inputnumber.spec.tsx +++ b/src/packages/inputnumber/__tests__/inputnumber.spec.tsx @@ -17,9 +17,9 @@ test('should add step 2 when trigger click plus button', () => { ) const iconPlus = container.querySelectorAll('.nut-icon-plus')[0] @@ -37,9 +37,9 @@ test('should minis step 2 when trigger click minis button', () => { ) const iconMinus = container.querySelectorAll('.nut-icon-minus')[0] @@ -58,9 +58,9 @@ test('should render max props', () => { modelValue={100} min="2" max="100" - overlimit={overlimit} - add={add} - change={change} + onOverlimit={overlimit} + onAdd={add} + onChangeFuc={change} /> ) const iconPlus = container.querySelectorAll('.nut-icon-plus')[0] @@ -79,9 +79,9 @@ test('should render min props', () => { modelValue={2} min="2" max="100" - overlimit={overlimit} - reduce={reduce} - change={change} + onOverlimit={overlimit} + onReduce={reduce} + onChangeFuc={change} /> ) const iconMinus = container.querySelectorAll('.nut-icon-minus')[0] @@ -107,7 +107,7 @@ test('should not trigger click when disabled props to be true', () => { test('should not focus input when readonly props to be true', () => { const focus = jest.fn() const { container } = render( - + ) const iconMinus = container.querySelectorAll('.nut-icon-minus')[0] fireEvent.click(iconMinus) @@ -138,7 +138,12 @@ test('should update input value when inputValue overlimit', () => { const change = jest.fn() const blur = jest.fn() const { container } = render( - + ) const input = container.querySelectorAll('input')[0] input.value = '200' diff --git a/src/packages/inputnumber/demo.taro.tsx b/src/packages/inputnumber/demo.taro.tsx index 50b0ddb075..c511ae00f8 100644 --- a/src/packages/inputnumber/demo.taro.tsx +++ b/src/packages/inputnumber/demo.taro.tsx @@ -115,7 +115,7 @@ const InputNumberDemo = () => { modelValue={inputState.val3} min="10" max="20" - overlimit={overlimit} + onOverlimit={overlimit} />

{translated['181965e2']}

@@ -137,7 +137,11 @@ const InputNumberDemo = () => {

{translated['65bafb1d']}

- +

{translated['7e2394ae']}

diff --git a/src/packages/inputnumber/demo.tsx b/src/packages/inputnumber/demo.tsx index fa24d82bd6..752f37ff74 100644 --- a/src/packages/inputnumber/demo.tsx +++ b/src/packages/inputnumber/demo.tsx @@ -106,7 +106,7 @@ const InputNumberDemo = () => { modelValue={inputState.val3} min="10" max="20" - overlimit={overlimit} + onOverlimit={overlimit} />

{translated['181965e2']}

@@ -128,7 +128,11 @@ const InputNumberDemo = () => {

{translated['65bafb1d']}

- +

{translated['7e2394ae']}

diff --git a/src/packages/inputnumber/doc.en-US.md b/src/packages/inputnumber/doc.en-US.md index 0f12c7e978..0d48094315 100644 --- a/src/packages/inputnumber/doc.en-US.md +++ b/src/packages/inputnumber/doc.en-US.md @@ -96,7 +96,7 @@ const App = () => { } return ( <> - + ) } @@ -223,7 +223,7 @@ const App = () => { } return ( <> - + ) } @@ -280,9 +280,15 @@ export default App; | Event | Description | Arguments | |-----------|------------------------|--------------------------------| -| add | Triggered when the Add button is clicked | event: Event | -| reduce | Triggered when the decrease button is clicked | event: Event | -| overlimit | Triggered when an unavailable button is clicked | event: Event | -| change | Triggered when the value changes | value: number , event : Event | -| blur | Triggered when the input box blur | event: Event | -| focus | Triggered when the input box focus | event: Event | \ No newline at end of file +| add `v1.3.8(Abandon)` | Triggered when the Add button is clicked | event: Event | +| reduce `v1.3.8(Abandon)` | Triggered when the decrease button is clicked | event: Event | +| overlimit `v1.3.8(Abandon)` | Triggered when an unavailable button is clicked | event: Event | +| change `v1.3.8(Abandon)` | Triggered when the value changes | value: number , event : Event | +| blur `v1.3.8(Abandon)` | Triggered when the input box blur | event: Event | +| focus `v1.3.8(Abandon)` | Triggered when the input box focus | event: Event | +| onAdd `v1.3.8` | Triggered when the Add button is clicked | event: Event | +| onReduce `v1.3.8` | Triggered when the decrease button is clicked | event: Event | +| onOverlimit `v1.3.8` | Triggered when an unavailable button is clicked | event: Event | +| onChangeFuc `v1.3.8` | Triggered when the value changes | value: number , event : Event | +| onBlurFuc `v1.3.8` | Triggered when the input box blur | event: Event | +| onFocus `v1.3.8` | Triggered when the input box focus | event: Event | \ No newline at end of file diff --git a/src/packages/inputnumber/doc.md b/src/packages/inputnumber/doc.md index b7971266ac..270ae31be0 100644 --- a/src/packages/inputnumber/doc.md +++ b/src/packages/inputnumber/doc.md @@ -95,7 +95,7 @@ const App = () => { } return ( <> - + ) } @@ -222,7 +222,7 @@ const App = () => { } return ( <> - + ) } @@ -279,9 +279,15 @@ export default App; | 事件名 | 说明 | 回调参数 | |-----------|------------------------|--------------------------------| -| add | 点击增加按钮时触发 | event: Event | -| reduce | 点击减少按钮时触发 | event: Event | -| overlimit | 点击不可用的按钮时触发 | event: Event | -| change | 值改变时触发 | value: number , event : Event | -| blur | 输入框失去焦点时触发 | event: Event | -| focus | 输入框获得焦点时触发 | event: Event | \ No newline at end of file +| add `v1.3.8废弃` | 点击增加按钮时触发 | event: Event | +| onAdd `v1.3.8` | 点击增加按钮时触发 | event: Event | +| reduce `v1.3.8废弃` | 点击减少按钮时触发 | event: Event | +| onReduce `v1.3.8` | 点击减少按钮时触发 | event: Event | +| overlimit `v1.3.8废弃` | 点击不可用的按钮时触发 | event: Event | +| onOverlimit `v1.3.8` | 点击不可用的按钮时触发 | event: Event | +| change `v1.3.8废弃` | 值改变时触发 | value: number , event : Event | +| onChangeFuc `v1.3.8` | 值改变时触发 | value: number , event : Event | +| blur `v1.3.8废弃` | 输入框失去焦点时触发 | event: Event | +| onBlurFuc `v1.3.8` | 输入框失去焦点时触发 | event: Event | +| focus `v1.3.8废弃` | 输入框获得焦点时触发 | event: Event | +| onFocus `v1.3.8` | 输入框获得焦点时触发 | event: Event | \ No newline at end of file diff --git a/src/packages/inputnumber/doc.zh-TW.md b/src/packages/inputnumber/doc.zh-TW.md index 499ffb7342..6726ab05e4 100644 --- a/src/packages/inputnumber/doc.zh-TW.md +++ b/src/packages/inputnumber/doc.zh-TW.md @@ -95,7 +95,7 @@ const App = () => { } return ( <> - + ) } @@ -222,7 +222,7 @@ const App = () => { } return ( <> - + ) } @@ -279,9 +279,15 @@ export default App; | 事件名 | 說明 | 回調參數 | |-----------|------------------------|--------------------------------| -| add | 點擊增加按鈕時觸發 | event: Event | -| reduce | 點擊減少按鈕時觸發 | event: Event | -| overlimit | 點擊不可用的按鈕時觸發 | event: Event | -| change | 值改變時觸發 | value: number , event : Event | -| blur | 輸入框失去焦點時觸發 | event: Event | -| focus | 輸入框獲得焦點時觸發 | event: Event | \ No newline at end of file +| add `v1.3.8廢棄` | 點擊增加按鈕時觸發 | event: Event | +| reduce `v1.3.8廢棄` | 點擊減少按鈕時觸發 | event: Event | +| overlimit `v1.3.8廢棄` | 點擊不可用的按鈕時觸發 | event: Event | +| change `v1.3.8廢棄` | 值改變時觸發 | value: number , event : Event | +| blur `v1.3.8廢棄` | 輸入框失去焦點時觸發 | event: Event | +| focus `v1.3.8廢棄` | 輸入框獲得焦點時觸發 | event: Event | +| onAdd `v1.3.8` | 點擊增加按鈕時觸發 | event: Event | +| onReduce `v1.3.8` | 點擊減少按鈕時觸發 | event: Event | +| onOverlimit `v1.3.8` | 點擊不可用的按鈕時觸發 | event: Event | +| onChangeFuc `v1.3.8` | 值改變時觸發 | value: number , event : Event | +| onBlurFuc `v1.3.8` | 輸入框失去焦點時觸發 | event: Event | +| onFocus `v1.3.8` | 輸入框獲得焦點時觸發 | event: Event | \ No newline at end of file diff --git a/src/packages/inputnumber/inputnumber.taro.tsx b/src/packages/inputnumber/inputnumber.taro.tsx index 2b3ad37d00..6d6680b45d 100644 --- a/src/packages/inputnumber/inputnumber.taro.tsx +++ b/src/packages/inputnumber/inputnumber.taro.tsx @@ -33,6 +33,15 @@ export interface InputNumberProps extends IComponent { param: string | number, e: MouseEvent | ChangeEvent ) => void + onAdd: (e: MouseEvent) => void + onReduce: (e: MouseEvent) => void + onOverlimit: (e: MouseEvent) => void + onBlurFuc: (e: ChangeEvent) => void + onFocus: (e: FocusEvent) => void + onChangeFuc: ( + param: string | number, + e: MouseEvent | ChangeEvent + ) => void } const defaultProps = { @@ -74,6 +83,12 @@ export const InputNumber: FunctionComponent< overlimit, blur, focus, + onAdd, + onReduce, + onOverlimit, + onBlurFuc, + onFocus, + onChangeFuc, iconClassPrefix, iconFontClassName, ...restProps @@ -123,6 +138,7 @@ export const InputNumber: FunctionComponent< e: MouseEvent | ChangeEvent ) => { const outputValue: number | string = fixedDecimalPlaces(value) + onChangeFuc && onChangeFuc(outputValue, e) change && change(outputValue, e) if (!isAsync) { if (Number(outputValue) < Number(min)) { @@ -136,21 +152,25 @@ export const InputNumber: FunctionComponent< } const reduceNumber = (e: MouseEvent) => { + onReduce && onReduce(e) reduce && reduce(e) if (reduceAllow()) { const outputValue = Number(inputValue) - Number(step) emitChange(outputValue, e) } else { + onOverlimit && onOverlimit(e) overlimit && overlimit(e) } } const addNumber = (e: MouseEvent) => { + onAdd && onAdd(e) add && add(e) if (addAllow()) { const outputValue = Number(inputValue) + Number(step) emitChange(outputValue, e) } else { + onOverlimit && onOverlimit(e) overlimit && overlimit(e) } } @@ -158,6 +178,7 @@ export const InputNumber: FunctionComponent< const changeValue = (e: any) => { const value = Number(e.detail.value) change && change(value, e) + onChangeFuc && onChangeFuc(value, e) if (!isAsync) { if (Number.isNaN(value)) { setInputValue(inputValue) @@ -170,6 +191,7 @@ export const InputNumber: FunctionComponent< const focusValue = (e: FocusEvent) => { if (disabled) return if (readonly) return + onFocus && onFocus(e) focus && focus(e) } @@ -183,6 +205,7 @@ export const InputNumber: FunctionComponent< value = Number(max) } emitChange(value, e) + onBlurFuc && onBlurFuc(e) blur && blur(e) } return ( diff --git a/src/packages/inputnumber/inputnumber.tsx b/src/packages/inputnumber/inputnumber.tsx index bb96cbae86..3d7e080fd7 100644 --- a/src/packages/inputnumber/inputnumber.tsx +++ b/src/packages/inputnumber/inputnumber.tsx @@ -33,6 +33,15 @@ export interface InputNumberProps extends IComponent { param: string | number, e: MouseEvent | ChangeEvent ) => void + onAdd: (e: MouseEvent) => void + onReduce: (e: MouseEvent) => void + onOverlimit: (e: MouseEvent) => void + onBlurFuc: (e: ChangeEvent) => void + onFocus: (e: FocusEvent) => void + onChangeFuc: ( + param: string | number, + e: MouseEvent | ChangeEvent + ) => void } const defaultProps = { @@ -74,6 +83,12 @@ export const InputNumber: FunctionComponent< overlimit, blur, focus, + onAdd, + onReduce, + onOverlimit, + onBlurFuc, + onFocus, + onChangeFuc, iconClassPrefix, iconFontClassName, ...restProps @@ -123,6 +138,7 @@ export const InputNumber: FunctionComponent< e: MouseEvent | ChangeEvent ) => { const outputValue: number | string = fixedDecimalPlaces(value) + onChangeFuc && onChangeFuc(outputValue, e) change && change(outputValue, e) if (!isAsync) { if (Number(outputValue) < Number(min)) { @@ -136,21 +152,25 @@ export const InputNumber: FunctionComponent< } const reduceNumber = (e: MouseEvent) => { + onReduce && onReduce(e) reduce && reduce(e) if (reduceAllow()) { const outputValue = Number(inputValue) - Number(step) emitChange(outputValue, e) } else { + onOverlimit && onOverlimit(e) overlimit && overlimit(e) } } const addNumber = (e: MouseEvent) => { + onAdd && onAdd(e) add && add(e) if (addAllow()) { const outputValue = Number(inputValue) + Number(step) emitChange(outputValue, e) } else { + onOverlimit && onOverlimit(e) overlimit && overlimit(e) } } @@ -158,6 +178,7 @@ export const InputNumber: FunctionComponent< const changeValue = (e: ChangeEvent) => { const input = e.target as HTMLInputElement change && change(input.valueAsNumber, e) + onChangeFuc && onChangeFuc(input.valueAsNumber, e) if (!isAsync) { if (Number.isNaN(input.valueAsNumber)) { setInputValue(inputValue) @@ -170,6 +191,7 @@ export const InputNumber: FunctionComponent< const focusValue = (e: FocusEvent) => { if (disabled) return if (readonly) return + onFocus && onFocus(e) focus && focus(e) } @@ -184,6 +206,7 @@ export const InputNumber: FunctionComponent< value = Number(max) } emitChange(value, e) + onBlurFuc && onBlurFuc(e) blur && blur(e) } return ( diff --git a/src/packages/step/step.taro.tsx b/src/packages/step/step.taro.tsx index f710066af3..4532cedd2a 100644 --- a/src/packages/step/step.taro.tsx +++ b/src/packages/step/step.taro.tsx @@ -56,9 +56,8 @@ export const Step: FunctionComponent< return index === +parent.propSteps.current ? 'process' : 'wait' } const handleClickStep = () => { - if (parent.propSteps?.clickStep) { - parent.propSteps?.clickStep(activeIndex) - } + parent.propSteps?.onClickStep && parent.propSteps?.onClickStep(activeIndex) + parent.propSteps?.clickStep && parent.propSteps?.clickStep(activeIndex) } const b = bem('step') diff --git a/src/packages/step/step.tsx b/src/packages/step/step.tsx index cfcf409341..b3e75edb7f 100644 --- a/src/packages/step/step.tsx +++ b/src/packages/step/step.tsx @@ -56,9 +56,8 @@ export const Step: FunctionComponent< return index === +parent.propSteps.current ? 'process' : 'wait' } const handleClickStep = () => { - if (parent.propSteps?.clickStep) { - parent.propSteps?.clickStep(activeIndex) - } + parent.propSteps?.onClickStep && parent.propSteps?.onClickStep(activeIndex) + parent.propSteps?.clickStep && parent.propSteps?.clickStep(activeIndex) } const b = bem('step') diff --git a/src/packages/steps/__tests__/steps.spec.tsx b/src/packages/steps/__tests__/steps.spec.tsx index 50f1ebb6e0..4a89c3f396 100644 --- a/src/packages/steps/__tests__/steps.spec.tsx +++ b/src/packages/steps/__tests__/steps.spec.tsx @@ -140,7 +140,7 @@ test('should props current changes when trigger click', () => { test('should emited click when step trigger', () => { const handleClickStep = jest.fn() const { getByText } = render( - + {

{translated['74fc5d8a']}

- + 1 diff --git a/src/packages/steps/demo.tsx b/src/packages/steps/demo.tsx index 94db9bd7a2..87c9a1bf46 100644 --- a/src/packages/steps/demo.tsx +++ b/src/packages/steps/demo.tsx @@ -110,7 +110,7 @@ const StepsDemo = () => {

{translated['74fc5d8a']}

- + 1 diff --git a/src/packages/steps/doc.md b/src/packages/steps/doc.md index 7226aba6e3..2fae069df4 100644 --- a/src/packages/steps/doc.md +++ b/src/packages/steps/doc.md @@ -259,7 +259,8 @@ export default App; | 事件名 | 说明 | 回调参数 | |--------|----------------|--------------| -| clickStep | 点击步骤的标题或图标时触发 | index: number | +| clickStep `v1.3.8废弃` | 点击步骤的标题或图标时触发 | index: number | +| onClickStep `v1.3.8` | 点击步骤的标题或图标时触发 | index: number | #### Step diff --git a/src/packages/steps/steps.taro.tsx b/src/packages/steps/steps.taro.tsx index d547ee9308..c216a9c743 100644 --- a/src/packages/steps/steps.taro.tsx +++ b/src/packages/steps/steps.taro.tsx @@ -10,6 +10,7 @@ export interface StepsProps { className: string style: React.CSSProperties clickStep: (index: number) => void + onClickStep: (index: number) => void } const defaultProps = { current: 0, @@ -28,6 +29,7 @@ export const Steps: FunctionComponent< className, progressDot, clickStep, + onClickStep, ...restProps } = propSteps diff --git a/src/packages/steps/steps.tsx b/src/packages/steps/steps.tsx index d547ee9308..c216a9c743 100644 --- a/src/packages/steps/steps.tsx +++ b/src/packages/steps/steps.tsx @@ -10,6 +10,7 @@ export interface StepsProps { className: string style: React.CSSProperties clickStep: (index: number) => void + onClickStep: (index: number) => void } const defaultProps = { current: 0, @@ -28,6 +29,7 @@ export const Steps: FunctionComponent< className, progressDot, clickStep, + onClickStep, ...restProps } = propSteps diff --git a/src/packages/video/demo.taro.tsx b/src/packages/video/demo.taro.tsx index d6a0de5812..192ffbc9a4 100644 --- a/src/packages/video/demo.taro.tsx +++ b/src/packages/video/demo.taro.tsx @@ -95,9 +95,9 @@ const VideoDemo = () => {