diff --git a/package.json b/package.json index 3a6b9de3c4cc73a83c3e66f4538086784ba2852a..1dad63dd486479e9413f8a7ea0725de972ba128b 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 7a038924cab040f3c31755618fb9307f704635fb..ce88a0ea94269d6502baec11188f2a8ef62e0da7 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 26759c29493aea5ee3421095bef4bc4f1da9cd67..bf21113426f455c53458f471582311cd14f03f66 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 6bc49109f628f4528e198ba390eb6087cf45fbf9..104e265a13cde0ecd55d113696cb52892fe1db64 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 edd4aae3fb838d5145542dc2eba363401de47ff6..be95b7bf6bbfa4cefce504abba0bb1417e1d6f6d 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 80f865475ce6a6ad5438f06c0219efad9407490a..3f96259e0561a6b295daf00c91a85be8a431837f 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 f1afd6cce1459f015fe2b6df52c1860acb51f08a..78bafd6b772e7f33bfc8f67bbbe64921f91a33e7 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 8cf155e7764d44b337b3569bcc333c2cd99df038..205f644ef6760991e7c9546078165a94e4443f00 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 0613ad7d5fed71791752662430e3ecef864e28c3..dd3e7baf074fca59c56befc774a7c2f0e000c118 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 4ab9321e9958c01cd7934cc8348e44a720b0f0a2..6b92db71ec30e44e9c4299037c77cfdd5f7c6c00 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 3bae14af27d868cf3867308e21e12b63f6343723..6c46098f29653ec694f28ac4fb3fb83703a4a258 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 0000000000000000000000000000000000000000..87bcff89578751d4fdc57ac06255c28a906388c2 --- /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 918171b665241b4c5a0dc9b3e85537f4b74337f1..d5ccaca2b0b9aa8a38cc789c4c1d5f668845f3d1 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 825719b06c2744ade224a3ac27290541aae92eb8..85ea955f81435056bec5482ffb34df892f75d0e0 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 e5e8fd4c887eb249e18e681aed4ca796d671b935..4d88615f63f75b3881ab19db45433e2ba86816e4 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 6538886816b3e124774249558d1a998fd5c2056c..56eb1243a62696e094e6538f25850c89145bf45f 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 0000000000000000000000000000000000000000..28d8d70cf70d2a8b6a21e019cf411858f42e6b20 --- /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 5ec8fecda166801884326ddd412e1288bc734416..5354fd45c86a5ae598fd57eb2681f3162a9d3b50 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', + ], }, ]