| 1 | import { |
| 2 | AccountInfo, |
| 3 | AccountPlatInfoMap, |
| 4 | IAccountPlatInfo, |
| 5 | } from '../../account/comment'; |
| 6 | import { IPubParams } from '../children/videoPage/videoPage'; |
| 7 | import { memo, useMemo } from 'react'; |
| 8 | import { parseTopicString } from '@/utils'; |
| 9 | import { AccountStatus, PlatType, XhsAccountAbnormal } from '@@/AccountEnum'; |
| 10 | import { Alert, Tooltip } from 'antd'; |
| 11 | import { InfoCircleOutlined } from '@ant-design/icons'; |
| 12 | |
| 13 | // 错误状态 |
| 14 | export enum PubParamsErrStatusEnum { |
| 15 | // 登录错误 |
| 16 | LOGIN = 1, |
| 17 | // 参数错误 |
| 18 | PARAMS = 2, |
| 19 | } |
| 20 | export interface ErrPubParamsItem { |
| 21 | // 这个错误提示会在账户tab显示 |
| 22 | message: string; |
| 23 | // 错误类型,用户区分是否需要显示重新登录的错误提示 |
| 24 | errType: PubParamsErrStatusEnum; |
| 25 | // 参数错误提示消息 |
| 26 | parErrMsg?: string; |
| 27 | // 发生错误的平台 |
| 28 | plat?: PlatType; |
| 29 | } |
| 30 | |
| 31 | export type ErrPubParamsMapType = Map<string | number, ErrPubParamsItem>; |
| 32 | |
| 33 | interface IPubParamsVerifyItem<T = undefined> { |
| 34 | id: string | number; |
| 35 | account?: AccountInfo; |
| 36 | pubParams: IPubParams; |
| 37 | other: T; |
| 38 | } |
| 39 | |
| 40 | /** |
| 41 | * 发布参数校验是否复合平台规范 |
| 42 | * @param data |
| 43 | * @param moreVerify |
| 44 | */ |
| 45 | export default function <T>( |
| 46 | data: IPubParamsVerifyItem<T>[], |
| 47 | moreVerify?: { |
| 48 | // 错误参数扩展 |
| 49 | moreErrorVerifyCallback?: ( |
| 50 | item: IPubParamsVerifyItem<T>, |
| 51 | errParamsMapTemp: ErrPubParamsMapType, |
| 52 | platInfo: IAccountPlatInfo, |
| 53 | ) => void; |
| 54 | // 警告参数扩展 |
| 55 | moreWranVerifyCallback?: ( |
| 56 | item: IPubParamsVerifyItem<T>, |
| 57 | wranParamsMapTemp: ErrPubParamsMapType, |
| 58 | platInfo: IAccountPlatInfo, |
| 59 | ) => void; |
| 60 | }, |
| 61 | ) { |
| 62 | // 用于判断描述中的话题是否符合规范 |
| 63 | const descTopicRegex = /#\S+#\S+/; |
| 64 | |
| 65 | // 错误参数,发布之前会检测错误参数,防止平台无法发布 |
| 66 | const errParamsMap = useMemo(() => { |
| 67 | const errParamsMapTemp: ErrPubParamsMapType = new Map(); |
| 68 | for (const v of data) { |
| 69 | if (!v.account) continue; |
| 70 | const platInfo = AccountPlatInfoMap.get(v.account!.type)!; |
| 71 | const { topics } = parseTopicString(v.pubParams.describe || ''); |
| 72 | const topicsAll = [...new Set(v.pubParams.topics?.concat(topics))]; |
| 73 | const { topicMax } = platInfo.commonPubParamsConfig; |
| 74 | |
| 75 | (() => { |
| 76 | // 错误信息--------------------- |
| 77 | // 登录状态校验 |
| 78 | if (v.account && v.account.status === AccountStatus.DISABLE) { |
| 79 | return errParamsMapTemp.set(v.id, { |
| 80 | message: '登录失效', |
| 81 | errType: PubParamsErrStatusEnum.LOGIN, |
| 82 | parErrMsg: '登录失效,请重新登录', |
| 83 | }); |
| 84 | } |
| 85 | // 快手要求封面必须大于 400x400 |
| 86 | if ( |
| 87 | v.account?.type === PlatType.KWAI && |
| 88 | v.pubParams.cover && |
| 89 | (v.pubParams.cover.width < 400 || v.pubParams.cover.height < 400) |
| 90 | ) { |
| 91 | return errParamsMapTemp.set(v.id, { |
| 92 | message: '参数错误', |
| 93 | errType: PubParamsErrStatusEnum.PARAMS, |
| 94 | parErrMsg: '封面最小尺寸400*400', |
| 95 | }); |
| 96 | } |
| 97 | // 话题校验 |
| 98 | if (topicsAll.length > topicMax) { |
| 99 | return errParamsMapTemp.set(v.id, { |
| 100 | message: '参数错误', |
| 101 | errType: PubParamsErrStatusEnum.PARAMS, |
| 102 | parErrMsg: `${platInfo.name}话题最多不能超过${topicMax}个`, |
| 103 | }); |
| 104 | } |
| 105 | /** |
| 106 | * 抖音的话题和活动奖励校验 |
| 107 | * 抖音规定活动奖励 + 话题不能超过5个 |
| 108 | */ |
| 109 | if ( |
| 110 | v.account?.type === PlatType.Douyin && |
| 111 | topicsAll.length + |
| 112 | v.pubParams.diffParams![PlatType.Douyin]!.activitys!.length > |
| 113 | topicMax |
| 114 | ) { |
| 115 | return errParamsMapTemp.set(v.id, { |
| 116 | message: '参数错误', |
| 117 | errType: PubParamsErrStatusEnum.PARAMS, |
| 118 | parErrMsg: `话题 + 活动奖励不能超过${topicMax}个`, |
| 119 | }); |
| 120 | } |
| 121 | // 小红书账号异常情况处理 |
| 122 | if ( |
| 123 | v.account?.type === PlatType.Xhs && |
| 124 | v.account.abnormalStatus && |
| 125 | v.account.abnormalStatus[PlatType.Xhs] === |
| 126 | XhsAccountAbnormal.Abnormal |
| 127 | ) { |
| 128 | return errParamsMapTemp.set(v.id, { |
| 129 | message: '账号错误', |
| 130 | errType: PubParamsErrStatusEnum.PARAMS, |
| 131 | parErrMsg: `小红书账号异常,无法发布作品,请检查后重试!`, |
| 132 | }); |
| 133 | } |
| 134 | // 判断描述中的话题中间是否用空格分割,如:#话题1#话题2#话题3 这种格式错误 |
| 135 | if (descTopicRegex.test(v.pubParams.describe || '')) { |
| 136 | return errParamsMapTemp.set(v.id, { |
| 137 | message: '参数错误', |
| 138 | errType: PubParamsErrStatusEnum.PARAMS, |
| 139 | parErrMsg: `描述中的话题必须使用空格分割,如:“#话题1 #话题2”`, |
| 140 | }); |
| 141 | } |
| 142 | |
| 143 | if (moreVerify?.moreErrorVerifyCallback) |
| 144 | moreVerify?.moreErrorVerifyCallback(v, errParamsMapTemp, platInfo); |
| 145 | })(); |
| 146 | |
| 147 | // 通用参数 |
| 148 | if (errParamsMapTemp.has(v.id)) { |
| 149 | errParamsMapTemp.set(v.id, { |
| 150 | ...errParamsMapTemp.get(v.id)!, |
| 151 | plat: v.account.type, |
| 152 | }); |
| 153 | } |
| 154 | } |
| 155 | return errParamsMapTemp; |
| 156 | }, [data]); |
| 157 | |
| 158 | // 警告参数,警告参数只会展示,不会阻止平台发布 |
| 159 | const warnParamsMap = useMemo(() => { |
| 160 | const warnParamsMapTemp: ErrPubParamsMapType = new Map(); |
| 161 | for (const v of data) { |
| 162 | if (!v.account) continue; |
| 163 | const platInfo = AccountPlatInfoMap.get(v.account!.type)!; |
| 164 | |
| 165 | if (moreVerify?.moreWranVerifyCallback) |
| 166 | moreVerify?.moreWranVerifyCallback(v, warnParamsMapTemp, platInfo); |
| 167 | } |
| 168 | return warnParamsMapTemp; |
| 169 | }, [data]); |
| 170 | |
| 171 | return { |
| 172 | errParamsMap, |
| 173 | warnParamsMap, |
| 174 | }; |
| 175 | } |
| 176 | |
| 177 | // 用于展示校验的结果 |
| 178 | export const PubParamsVerifyInfo = memo( |
| 179 | ({ |
| 180 | id, |
| 181 | warnParamsMap, |
| 182 | errParamsMap, |
| 183 | onAccountRestart, |
| 184 | style, |
| 185 | }: { |
| 186 | id?: string | number; |
| 187 | errParamsMap?: ErrPubParamsMapType; |
| 188 | warnParamsMap?: ErrPubParamsMapType; |
| 189 | onAccountRestart: (plat?: PlatType) => void; |
| 190 | style?: React.CSSProperties; |
| 191 | }) => { |
| 192 | const errPubParams = useMemo(() => { |
| 193 | let errPubParams: ErrPubParamsItem | undefined = undefined; |
| 194 | if (!errParamsMap) return errPubParams; |
| 195 | for (const [itemId, errPubParamsItem] of errParamsMap) { |
| 196 | if (itemId === id) { |
| 197 | errPubParams = errPubParamsItem; |
| 198 | break; |
| 199 | } |
| 200 | } |
| 201 | return errPubParams; |
| 202 | }, [id, errParamsMap]); |
| 203 | |
| 204 | const paramsWarningList = useMemo(() => { |
| 205 | if (!warnParamsMap) return []; |
| 206 | return Array.from(warnParamsMap) |
| 207 | .map(([itemId, item]) => (itemId === id ? item : undefined)) |
| 208 | .filter((v) => v !== undefined); |
| 209 | }, [warnParamsMap, id]); |
| 210 | |
| 211 | return ( |
| 212 | <> |
| 213 | {errPubParams && ( |
| 214 | <Alert |
| 215 | type="error" |
| 216 | showIcon |
| 217 | message={ |
| 218 | errPubParams.errType === PubParamsErrStatusEnum.LOGIN ? ( |
| 219 | <> |
| 220 | 登录失效,请 |
| 221 | <a |
| 222 | style={{ fontSize: '13px' }} |
| 223 | onClick={() => { |
| 224 | onAccountRestart(errPubParams.plat); |
| 225 | }} |
| 226 | > |
| 227 | 重新登录 |
| 228 | </a> |
| 229 | </> |
| 230 | ) : ( |
| 231 | errPubParams.parErrMsg |
| 232 | ) |
| 233 | } |
| 234 | style={style} |
| 235 | /> |
| 236 | )} |
| 237 | |
| 238 | {paramsWarningList.length !== 0 && ( |
| 239 | <Alert |
| 240 | type="warning" |
| 241 | showIcon |
| 242 | icon={ |
| 243 | <Tooltip title="这是参数警告,参数警告不会阻止您的发布!"> |
| 244 | <InfoCircleOutlined /> |
| 245 | </Tooltip> |
| 246 | } |
| 247 | message={ |
| 248 | <> |
| 249 | {paramsWarningList.map((v, i) => { |
| 250 | return <p key={i}>{v.parErrMsg}</p>; |
| 251 | })} |
| 252 | </> |
| 253 | } |
| 254 | style={style} |
| 255 | /> |
| 256 | )} |
| 257 | </> |
| 258 | ); |
| 259 | }, |
| 260 | ); |
| 261 |