diff --git a/.cursor/rules/karpathy-guidelines.md b/.cursor/rules/karpathy-guidelines.mdc similarity index 94% rename from .cursor/rules/karpathy-guidelines.md rename to .cursor/rules/karpathy-guidelines.mdc index 01f09a19a..5c43fb30e 100644 --- a/.cursor/rules/karpathy-guidelines.md +++ b/.cursor/rules/karpathy-guidelines.mdc @@ -1,8 +1,9 @@ --- +description: Karpathy 行为准则——先想清楚、极简、手术式改动、可验证目标 alwaysApply: true --- -# Karpathy-inspired coding guidelines +# Karpathy behavioral guidelines Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed. @@ -13,6 +14,7 @@ Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-s **Don't assume. Don't hide confusion. Surface tradeoffs.** Before implementing: + - State your assumptions explicitly. If uncertain, ask. - If multiple interpretations exist, present them - don't pick silently. - If a simpler approach exists, say so. Push back when warranted. @@ -35,12 +37,14 @@ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, sim **Touch only what you must. Clean up only your own mess.** When editing existing code: + - Don't "improve" adjacent code, comments, or formatting. - Don't refactor things that aren't broken. - Match existing style, even if you'd do it differently. - If you notice unrelated dead code, mention it - don't delete it. When your changes create orphans: + - Remove imports/variables/functions that YOUR changes made unused. - Don't remove pre-existing dead code unless asked. @@ -51,11 +55,13 @@ The test: Every changed line should trace directly to the user's request. **Define success criteria. Loop until verified.** Transform tasks into verifiable goals: + - "Add validation" → "Write tests for invalid inputs, then make them pass" - "Fix the bug" → "Write a test that reproduces it, then make it pass" - "Refactor X" → "Ensure tests pass before and after" For multi-step tasks, state a brief plan: + ``` 1. [Step] → verify: [check] 2. [Step] → verify: [check] diff --git a/.cursor/skills/git-commit/SKILL.md b/.cursor/skills/git-commit/SKILL.md new file mode 100644 index 000000000..840191f79 --- /dev/null +++ b/.cursor/skills/git-commit/SKILL.md @@ -0,0 +1,170 @@ +--- +name: git-commit +description: 按 GitLab TBID 强制校验规范提交 Git 变更并在对话中总结。提交信息必须以 [TBID:项目ID-任务编号] 开头。用户说「提交」「提交并总结」「帮我 commit」时使用;不写 .cursor/commit-summary 文件。 +--- + +# Git 提交(TBID 规范) + +**2026 年 6 月 12 日起**,GitLab 仓库开启 Commit Message 强制校验:**所有提交必须包含 `[TBID:项目ID-任务编号]`,否则推送将被拒绝。** + +## 何时触发 + +- 「提交并总结」「帮我 commit」「直接提交」「记录并提交」 +- 「总结这次改了什么并提交」(只对话总结 + commit,不写 md 文件) +- 「修正提交信息」「改 commit message」(按下方「错误提交修正」处理) + +## Commit Message 格式(强制) + +``` +[TBID:项目ID-任务编号] <提交类型> <问题/功能简述> +``` + +类型后可加冒号(如 `feat:`),与不加冒号(如 `fix `)均可;推荐统一为 `type:` 后接简述。 + +**正确示例:** + +``` +[TBID:PROJ-1001] fix 解决用户登录超时问题 +[TBID:PROJ-1002] feat: 新增用户注册验证码功能 +[TBID:WA-641] style: 赠品缩进改为固定 20px +``` + +### [TBID:项目ID-任务编号](必填,放开头) + +- 格式固定:`[TBID:项目ID-任务编号]`,关联 Teambition 任务 +- 示例:`[TBID:ECX-8754]`、`[TBID:WA-641]`、`[TBID:LAXZE-7377]` +- **用户未提供完整 TBID 时必须先询问**,禁止猜测或使用占位符 + +### 提交类型(必填) + +| type | 说明 | +|------|------| +| `feat` | 新功能、新特性 | +| `fix` | 修改 bug | +| `perf` | 性能优化(不改变代码行为) | +| `refactor` | 代码重构(不改变行为与功能) | +| `docs` | 文档修改 | +| `style` | 代码格式修改(**非 CSS**;删多余行、缩进等) | +| `test` | 测试用例新增、修改 | +| `build` | 影响构建或依赖(如 pom 依赖) | +| `revert` | 恢复上一次提交 | +| `ci` | CI 相关(Dockerfile 等) | +| `chore` | 其他(不在上述类型中) | +| `release` | 发布新版本 | +| `workflow` | 工作流相关文件修改 | + +用户指定 type 时以用户为准。 + +### 问题/功能简述(必填) + +- 一句话描述本次提交,**不超过 50 字** +- 写「做了什么」,不要堆文件路径列表 + +## 流程 + +### 1. 获取变更 + +```bash +git status -sb +git diff --stat +git diff +``` + +若有 staged 变更,再执行 `git diff --cached`。 + +### 2. 对话总结(不写文件) + +用中文简要说明: + +- 涉及哪些文件/模块 +- 主要改了什么 +- 拟用的完整 commit message(含 TBID、type、简述) + +**禁止**创建或更新 `.cursor/commit-summary/` 下任何 md 文件。 + +**发现不合理代码时**:只指出问题与建议,**不得擅自修改**;先询问用户是否需要一并处理,待确认后再动代码。 + +### 3. 是否提交 + +| 用户意图 | 动作 | +|----------|------| +| 仅「总结」「看看改了啥」 | 只输出总结,不 `git add` / `git commit` | +| 「并提交」「直接 commit」 | 继续步骤 4 | + +### 4. 执行提交 + +1. **只提交已有 diff**:不得顺带改代码;有问题在提交前说明 +2. **不改无关代码**:先向用户说明并询问,**禁止擅自改动** +3. **暂存**:未指定文件时 add 相关变更;用户指定路径则只 add 指定项 +4. **排除敏感文件**:`.env`、密钥等勿加入暂存,并提醒用户 +5. **提交**(message 必须含 TBID): + +```bash +git commit -m "$(cat <<'EOF' +[TBID:项目ID-任务编号] type: 问题/功能简述 +EOF +)" +``` + +6. **确认**:回复「已提交」+ commit hash + 一句话总结 +7. **不 push**:除非用户明确要求 + +## 错误提交修正(未推送前) + +推送被拦截或发现 message 不符合规范时: + +### 仅最近 1 次提交写错 + +```bash +git commit --amend -m "[TBID:XXXX-123] fix: 正确描述" +``` + +### 最近 N 次提交都写错 + +```bash +git rebase -i HEAD~N +``` + +将需修改的提交前的 `pick` 改为 `reword`,保存后依次修改每条 message。 + +> 交互式 rebase 需用户确认;Agent 仅在用户明确要求修正历史提交信息时执行,且不使用 `-i` 以外的 destructive 操作。 + +### 查看未推送的提交 + +```bash +git log --oneline origin/<分支名>..HEAD +``` + +## 代码改动边界 + +- 提交、总结、review 过程中发现不合理代码:**先问用户,再改** +- 用户未确认前,不得把「顺手修复」混进本次 commit + +## 安全约束 + +- 不修改 git config +- 不执行 destructive 命令(force push、hard reset 等),除非用户明确要求 +- 不 skip hooks(`--no-verify` 等),除非用户明确要求 +- **`--amend` / `rebase -i reword`**:仅用于修正 commit message(TBID 规范),且符合用户 amend 规则(HEAD 为自己创建、未 push 等) + +## 示例对话 + +**用户**:`提交 WA-641,赠品缩进改 20px` + +**Agent**: + +1. 查看 diff → 3 个 trade scss 文件 +2. 总结:订单列表/结算/详情赠品 margin-left 改为 20px +3. `git commit -m "[TBID:WA-641] style: 赠品缩进改为固定 20px"` +4. 回复:已提交 `515c73472` + +**用户**:`推送被拒,上次 commit 没写 TBID` + +**Agent**: + +1. 确认未 push → `git commit --amend -m "[TBID:WA-641] style: 赠品缩进改为固定 20px"` +2. 提醒用户再次 push + +**用户**:`先总结我改了啥` + +**Agent**:只输出 diff 总结,不 commit,并问是否需要提交及 TBID。 diff --git a/src/components/sp-float-layout/index.js b/src/components/sp-float-layout/index.js index 1ee788161..094f66e11 100644 --- a/src/components/sp-float-layout/index.js +++ b/src/components/sp-float-layout/index.js @@ -27,7 +27,7 @@ function SpFloatLayout(props) { className={classNames('sp-float-layout', className, { active: open })} - catchMove + catchMove={open} > diff --git a/src/components/sp-float-layout/index.scss b/src/components/sp-float-layout/index.scss index 340b251b7..c51852c16 100644 --- a/src/components/sp-float-layout/index.scss +++ b/src/components/sp-float-layout/index.scss @@ -12,6 +12,8 @@ z-index: 1000; // display: none; transform: translate3D(0, 110%, 0); + pointer-events: none; + &__overlay { position: absolute; top: 0; @@ -34,6 +36,7 @@ // transition: all .3s linear; } &.active { + pointer-events: auto; transform: translate3D(0, 0, 0); // display: block; #{$self}__overlay { diff --git a/src/components/sp-image/index.scss b/src/components/sp-image/index.scss index 1d74fc5c6..c5e1b3b00 100644 --- a/src/components/sp-image/index.scss +++ b/src/components/sp-image/index.scss @@ -60,6 +60,10 @@ &.sp-image--loaded { opacity: 1; } + img { + width: 100%; + height: 100%; + } } } diff --git a/src/components/sp-page/index.scss b/src/components/sp-page/index.scss index 3df7910fd..24e8116d4 100644 --- a/src/components/sp-page/index.scss +++ b/src/components/sp-page/index.scss @@ -70,7 +70,7 @@ bottom: 0; left: 0; right: 0; - z-index: $z-index-level-3; + z-index: $z-index-level-5; background: #fff; } diff --git a/src/components/sp-render-goods/compact-card.jsx b/src/components/sp-render-goods/compact-card.jsx index b7ca8188c..d5880a215 100644 --- a/src/components/sp-render-goods/compact-card.jsx +++ b/src/components/sp-render-goods/compact-card.jsx @@ -54,7 +54,6 @@ function SpGoodsCompactCard(props) { return ( @@ -178,7 +177,6 @@ SpGoodsCompactCard.defaultProps = { className: '', id: '', info: null, - key: '', onClick: null, mode: 'aspectFill', width: 218, diff --git a/src/components/sp-render-goods/grid-card.jsx b/src/components/sp-render-goods/grid-card.jsx index c338a217c..ef1c91edf 100644 --- a/src/components/sp-render-goods/grid-card.jsx +++ b/src/components/sp-render-goods/grid-card.jsx @@ -42,7 +42,6 @@ function SpGoodsGridCard(props) { return ( @@ -131,7 +130,6 @@ SpGoodsGridCard.defaultProps = { className: '', id: '', info: null, - key: '', onClick: null, mode: 'aspectFill', width: 200, diff --git a/src/components/sp-render-goods/hero-card.jsx b/src/components/sp-render-goods/hero-card.jsx index 56184a6f5..77b2bc2ed 100644 --- a/src/components/sp-render-goods/hero-card.jsx +++ b/src/components/sp-render-goods/hero-card.jsx @@ -35,7 +35,6 @@ function SpGoodsHeroCard(props) { return ( @@ -154,7 +153,6 @@ SpGoodsHeroCard.defaultProps = { className: '', id: '', info: null, - key: '', onClick: null, mode: 'aspectFill', width: 200, diff --git a/src/components/sp-screen-ad/index.js b/src/components/sp-screen-ad/index.js index b26bec72e..e1566afb4 100644 --- a/src/components/sp-screen-ad/index.js +++ b/src/components/sp-screen-ad/index.js @@ -55,6 +55,12 @@ export default class ScreenAd extends Component { } const isHave = res.is_enable === 1 && (res.app === 'all' || res.app.indexOf(client[env]) !== -1) const { showAdv } = this.props + if (!isHave) { + if (!showAdv) { + this.props.onUpdateShowAdv(true) + } + return + } if (isHave && res.show_time === 'once' && showAdv) { this.props.onUpdateShowAdv(true) return diff --git a/src/hocs/withPageWrapper.js b/src/hocs/withPageWrapper.js index c12dad65d..02a4d2a51 100644 --- a/src/hocs/withPageWrapper.js +++ b/src/hocs/withPageWrapper.js @@ -177,10 +177,11 @@ function withPageWrapper(Component) { if (dtid) { params['distributor_id'] = dtid + } else if (shopInfo?.distributor_id) { + // 用户已在店铺列表手动切店时,优先保留当前店铺,避免 LBS 再次按定位覆盖 + params['distributor_id'] = shopInfo.distributor_id } else if (forceLocation && entryLaunch.isEntryStoreLbsEnabled() && isLocation) { await appendLocationParams() - } else if (shopInfo?.distributor_id) { - params['distributor_id'] = shopInfo?.distributor_id } else if (entryLaunch.isEntryStoreLbsEnabled() && isLocation) { await appendLocationParams() } diff --git a/src/pages/home/wgts/full-slider/index.jsx b/src/pages/home/wgts/full-slider/index.jsx index 436aca3f6..58b2941a9 100644 --- a/src/pages/home/wgts/full-slider/index.jsx +++ b/src/pages/home/wgts/full-slider/index.jsx @@ -82,6 +82,13 @@ function WgtFullSlider(props) { }) }, [immersive, isShowHomeHeader, isTab, footerHeight]) + // footerHeight 由 SpPage onReady 异步注入,需在变化后重新计算高度 + useEffect(() => { + if (show) { + setHeight() + } + }, [show, setHeight]) + // 切换视频播放 const togglePlay = (itemIndex) => { const item = localData[itemIndex] diff --git a/src/pages/home/wgts/slider/index.scss b/src/pages/home/wgts/slider/index.scss index 86fd306a3..64a4e72d8 100644 --- a/src/pages/home/wgts/slider/index.scss +++ b/src/pages/home/wgts/slider/index.scss @@ -107,7 +107,7 @@ bottom: 0px; left: 0; right: 0; - z-index: 999; + z-index: 2; } &.left { diff --git a/src/pages/index.js b/src/pages/index.js index 11f1d6b58..cffb537f0 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -345,6 +345,7 @@ function Home() { pageData?.base?.isImmersive ? 0 : gNavbarH }px - ${footerHeight})` draft.navbarHeight = gNavbarH + draft.footerHeight = footerHeight }) }} > @@ -391,12 +392,6 @@ function Home() { {/* 小程序收藏提示 */} {isWeixin && } - {/* 开屏广告 */} - {isWeixin && !showAdv && } - - {/* 优惠券包 */} - {VERSION_STANDARD && } - {/* Sku选择器 */} + + {/* 全屏弹层需放在 ScrollView 外,真机上 scroll-view 内 fixed 层叠会异常 */} + {/* 开屏广告 */} + {isWeixin && !showAdv && } + {/* 优惠券包 微信端等开屏广告关闭(showAdv=true)后再弹券包,避免与开屏叠层 */} + {VERSION_STANDARD && (!isWeixin || showAdv) && } ) } diff --git a/src/subpages/purchase/espier-detail.js b/src/subpages/purchase/espier-detail.js index 0d582c9d2..a9e3b29de 100644 --- a/src/subpages/purchase/espier-detail.js +++ b/src/subpages/purchase/espier-detail.js @@ -3,9 +3,9 @@ * See LICENSE file for license details. */ import React, { useEffect, useRef, useMemo, useState } from 'react' -import { useSelector } from 'react-redux' +import { useSelector, useDispatch } from 'react-redux' import Taro from '@tarojs/taro' -import { View, Text, Swiper, SwiperItem, Video } from '@tarojs/components' +import { View, Text, Swiper, SwiperItem, Video, Image } from '@tarojs/components' import { AtFloatLayout, AtButton } from 'taro-ui' import { useImmer } from 'use-immer' import { @@ -35,6 +35,7 @@ import { import doc from '@/doc' import entryLaunch from '@/utils/entryLaunch' import { useNavigation } from '@/hooks' +import { updateChooseAddress } from '@/store/slices/user' import { ACTIVITY_LIST } from '@/consts' import { $t, ti, useTranslation } from '@/i18n' import { WgtFilm, WgtSlider, WgtImgHotZone } from '@/pages/home/wgts' @@ -178,12 +179,15 @@ const initialState = { recommendList: [], activityId: '', enterpriseId: '', - isParameter: false + isParameter: false, + imgHeightList: [], + defaultImageHeight: 520 } function EspierDetail(props) { const { i18n } = useTranslation() const pageRef = useRef() + const dispatch = useDispatch() const { userInfo, address } = useSelector((state) => state.user) const { colorPrimary, openRecommend } = useSelector((state) => state.sys) const { @@ -219,13 +223,27 @@ function EspierDetail(props) { recommendList, activityId, enterpriseId, - isParameter + isParameter, + imgHeightList, + defaultImageHeight } = state useEffect(() => { init() }, []) + useEffect(() => { + loadDefaultAddress() + }, []) + + const loadDefaultAddress = async () => { + const { list } = await api.member.addressList() + const defaultAddress = list?.find((item) => item.is_def > 0) || list?.[0] + if (defaultAddress) { + dispatch(updateChooseAddress(defaultAddress)) + } + } + useEffect(() => { const eid = curEnterpriseId || enterpriseId || purchase_share_info?.enterprise_id if (!eid) { @@ -358,8 +376,19 @@ function EspierDetail(props) { subscribe } draft.promotionActivity = data.promotionActivity + draft.imgHeightList = new Array(data?.imgs?.length).fill(draft.defaultImageHeight) }) + getMultipleImageInfo(data.imgs) + .then((heights) => { + setState((draft) => { + draft.imgHeightList = heights + }) + }) + .catch((error) => { + console.log('计算图片高度失败,使用默认高度:', error) + }) + if (isAPP() && userInfo) { try { Taro.SAPPShare.init({ @@ -393,18 +422,56 @@ function EspierDetail(props) { }) } + const getMultipleImageInfo = async (imageUrls = []) => { + let windowWidth = defaultImageHeight + try { + const sys = Taro.getSystemInfoSync() + if (sys && sys.windowWidth) windowWidth = sys.windowWidth + } catch (e) { + console.log('获取系统信息失败,使用默认宽度:', e) + } + + const promises = imageUrls.map(async (url) => { + try { + const imageInfo = await Taro.getImageInfo({ src: url }) + const imgWidth = Number(imageInfo?.width) || 0 + const imgHeight = Number(imageInfo?.height) || 0 + if (imgWidth > 0 && imgHeight > 0) { + return Math.round((windowWidth * imgHeight) / imgWidth) + } + return Math.round(windowWidth) + } catch (error) { + console.log('获取图片信息失败:', url, error) + return Math.round(windowWidth) + } + }) + + return Promise.all(promises) + } + const handleChooseDeliveryAddress = () => { Taro.navigateTo({ url: '/marketing/pages/member/address?isPicker=choose' }) } - const onChangeSwiper = (e) => { - setState((draft) => { + const onChangeSwiper = async (e) => { + await setState((draft) => { draft.curImgIdx = e.detail.current }) } + const setSwiperCss = (item) => { + return { + height: '100%', + width: '100%', + 'background-size': 'cover', + 'background-image': `url(${item})`, + 'background-repeat': 'no-repeat', + 'background-position': 'center' + } + } + const onChangeToolBar = (key) => { setState((draft) => { draft.skuPanelOpen = true @@ -412,8 +479,6 @@ function EspierDetail(props) { }) } - const { windowWidth } = Taro.getSystemInfoSync() - let sessionFrom = {} if (info) { sessionFrom['商品'] = info.itemName @@ -488,15 +553,13 @@ function EspierDetail(props) { className='goods-swiper' // current={curImgIdx} onChange={onChangeSwiper} + style={{ height: (imgHeightList[curImgIdx] || defaultImageHeight) + 'px' }} > {info.imgs.map((img, idx) => ( - + + + ))} diff --git a/src/subpages/purchase/espier-detail.scss b/src/subpages/purchase/espier-detail.scss index 5a222a825..f0df8b62a 100644 --- a/src/subpages/purchase/espier-detail.scss +++ b/src/subpages/purchase/espier-detail.scss @@ -122,7 +122,16 @@ } .goods-swiper { - height: 750px; + transition: height 0.2s ease-in-out; + overflow: hidden; + .swiperitem__img { + width: 100%; + height: 100%; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + } } .video-container { diff --git a/src/subpages/purchase/select-company-email.js b/src/subpages/purchase/select-company-email.js index 54a112e04..5d9685c63 100644 --- a/src/subpages/purchase/select-company-email.js +++ b/src/subpages/purchase/select-company-email.js @@ -28,12 +28,12 @@ function PurchaseAuthEmail() { const [vcode, setVcode] = useState('') const [countdown, setCountdown] = useState(0) const [enterpriseName, setEnterpriseName] = useState('') - const [activityBg, setActivityBg] = useState('') const sendCodeLockRef = useRef(false) const { showModal } = useModal() const dispatch = useDispatch() const { params } = useRouter() const { appName } = useSelector((state) => state.sys) + const { curEnterpriseLogo } = useSelector((state) => state.purchase) const { enterprise_id, enterprise_name, @@ -85,10 +85,8 @@ function PurchaseAuthEmail() { (item) => String(item?.id ?? item?.enterprise_id) === String(enterprise_id) ) setEnterpriseName(found?.name || '') - setActivityBg(found?.logo || '') } catch (e) { setEnterpriseName('') - setActivityBg('') } } @@ -237,7 +235,11 @@ function PurchaseAuthEmail() { return ( - + { + const list = OnlyRefundShow ? tabList : tabList1 + return list[curTabIdx]?.type + }, [OnlyRefundShow, tabList, tabList1, curTabIdx]) + + const realRefundFee = useMemo(() => { + if (!info) return '0.00' + const rFee = info.items + .filter((item) => item.checked) + .reduce((sum, { price, num, refundNum }) => sum + (price / num) * refundNum, 0) + return rFee.toFixed(2) + }, [info]) + + const realRefundPoint = useMemo(() => { + if (!info) return 0 + return info.items + .filter((item) => item.checked) + .reduce((sum, { point, num, refundNum, leftAftersalesNum }) => { + if (leftAftersalesNum == refundNum) { + return Math.ceil(sum + (point / num) * refundNum) + } + if (num > refundNum) { + return Math.floor(sum + (point / num) * refundNum) + } + return sum + (point / num) * refundNum + }, 0) + }, [info]) + useEffect(() => { const syncTitle = () => setNavigationBarTitle($t('b3d4a245.45eb0c')) syncTitle() @@ -114,14 +141,6 @@ function TradeAfterSale(props) { } }, []) - useEffect(() => { - if (openRefundType) { - pageRef.current.pageLock() - } else { - pageRef.current.pageUnLock() - } - }, [openRefundType]) - const onCancel = () => { Taro.navigateBack() } @@ -167,39 +186,6 @@ function TradeAfterSale(props) { }) } - const getRealRefundFee = () => { - let rFee = 0 - if (info) { - const { items } = info - rFee = items - .filter((item) => item.checked) - .reduce((sum, { price, num, refundNum }) => sum + (price / num) * refundNum, 0) - } - return rFee.toFixed(2) - } - - const getRealRefundPoint = () => { - let rPoint = 0 - if (info) { - const { items } = info - rPoint = items - .filter((item) => item.checked) - .reduce((sum, { point, num, refundNum, leftAftersalesNum }) => { - console.log(sum + (point / num) * refundNum, '---') - console.log(refundNum, leftAftersalesNum, '---') - if (leftAftersalesNum == refundNum) { - // 可申请数量=退货数量时,向上取整 积分47 总数2件 可申请为1件 申请1件 退24积分 - return Math.ceil(sum + (point / num) * refundNum) - } else if (num > refundNum) { - // 总数大于退货数量时,向下取整 积分47 总数2件 可申请2件 申请1件 退23积分 - return Math.floor(sum + (point / num) * refundNum) - } - return sum + (point / num) * refundNum - }, 0) - } - return rPoint - } - const onChangeRefundType = ({ value }) => { setState((draft) => { draft.selectRefundValue = value @@ -221,7 +207,7 @@ function TradeAfterSale(props) { if (!reasons?.[reasonIndex]) { return showToast($t('44d65d28.d030d6')) } - const aftersales_type = OnlyRefundShow ? tabList[curTabIdx].type : tabList1[curTabIdx].type + const aftersales_type = currentAftersalesType const reason = reasons?.[reasonIndex] let params = { detail: checkedItems.map(({ id: _id, refundNum }) => { @@ -283,7 +269,6 @@ function TradeAfterSale(props) { return ( @@ -293,8 +278,7 @@ function TradeAfterSale(props) { } > - - + - + {/* */} - + - {curTabIdx == 1 && ( + {currentAftersalesType === 'REFUND_GOODS' && ( )} - - +