useGoods.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. import {
  2. ref
  3. } from 'vue';
  4. import dayjs from 'dayjs';
  5. import $url from '@/sheep/url';
  6. import {
  7. formatDate
  8. } from '@/sheep/util';
  9. /**
  10. * 格式化销量
  11. * @param {'exact' | string} type 格式类型:exact=精确值,其它=大致数量
  12. * @param {number} num 销量
  13. * @return {string} 格式化后的销量字符串
  14. */
  15. export function formatSales(type, num) {
  16. let prefix = type !== 'exact' && num < 10 ? '销量' : '已售';
  17. return formatNum(prefix, type, num)
  18. }
  19. /**
  20. * 格式化兑换量
  21. * @param {'exact' | string} type 格式类型:exact=精确值,其它=大致数量
  22. * @param {number} num 销量
  23. * @return {string} 格式化后的销量字符串
  24. */
  25. export function formatExchange(type, num) {
  26. return formatNum('已兑换', type, num)
  27. }
  28. /**
  29. * 格式化库存
  30. * @param {'exact' | any} type 格式类型:exact=精确值,其它=大致数量
  31. * @param {number} num 销量
  32. * @return {string} 格式化后的销量字符串
  33. */
  34. export function formatStock(type, num) {
  35. return formatNum('库存', type, num)
  36. }
  37. /**
  38. * 格式化数字
  39. * @param {string} prefix 前缀
  40. * @param {'exact' | string} type 格式类型:exact=精确值,其它=大致数量
  41. * @param {number} num 销量
  42. * @return {string} 格式化后的销量字符串
  43. */
  44. export function formatNum(prefix, type, num) {
  45. num = (num || 0);
  46. // 情况一:精确数值
  47. if (type === 'exact') {
  48. return prefix + num;
  49. }
  50. // 情况二:小于等于 10
  51. if (num < 10) {
  52. return `${prefix}≤10`;
  53. }
  54. // 情况三:大于 10,除第一位外,其它位都显示为0
  55. // 例如:100 - 199 显示为 100+
  56. // 9000 - 9999 显示为 9000+
  57. const numStr = num.toString();
  58. const first = numStr[0];
  59. const other = '0'.repeat(numStr.length - 1);
  60. return `${prefix}${first}${other}+`;
  61. }
  62. // 格式化价格
  63. export function formatPrice(e) {
  64. return e.length === 1 ? e[0] : e.join('~');
  65. }
  66. // 视频格式后缀列表
  67. const VIDEO_SUFFIX_LIST = ['.avi', '.mp4']
  68. /**
  69. * 转换商品轮播的链接列表:根据链接的后缀,判断是视频链接还是图片链接
  70. *
  71. * @param {string[]} urlList 链接列表
  72. * @return {{src: string, type: 'video' | 'image' }[]} 转换后的链接列表
  73. */
  74. export function formatGoodsSwiper(urlList) {
  75. return urlList?.filter(url => url).map((url, key) => {
  76. const isVideo = VIDEO_SUFFIX_LIST.some(suffix => url.includes(suffix));
  77. const type = isVideo ? 'video' : 'image'
  78. const src = $url.cdn(url);
  79. return {
  80. type,
  81. src
  82. }
  83. }) || [];
  84. }
  85. /**
  86. * 格式化订单状态的颜色
  87. *
  88. * @param order 订单
  89. * @return {string} 颜色的 class 名称
  90. */
  91. export function formatOrderColor(order) {
  92. if (order.status === 0) {
  93. return 'info-color';
  94. }
  95. if (order.status === 10 ||
  96. order.status === 20 ||
  97. (order.status === 30 && !order.commentStatus)) {
  98. return 'warning-color';
  99. }
  100. if (order.status === 30 && order.commentStatus) {
  101. return 'success-color';
  102. }
  103. return 'danger-color';
  104. }
  105. /**
  106. * 格式化订单状态
  107. *
  108. * @param order 订单
  109. */
  110. export function formatOrderStatus(order) {
  111. if (order.status === 0) {
  112. return '待付款';
  113. }
  114. if (order.status === 10 && order.deliveryType === 1) {
  115. return '待发货';
  116. }
  117. if (order.status === 10 && order.deliveryType === 2) {
  118. return '待核销';
  119. }
  120. if (order.status === 20) {
  121. return '待收货';
  122. }
  123. if (order.status === 30 && !order.commentStatus) {
  124. return '待评价';
  125. }
  126. if (order.status === 30 && order.commentStatus) {
  127. return '已完成';
  128. }
  129. return '已关闭';
  130. }
  131. /**
  132. * 格式化订单状态的描述
  133. *
  134. * @param order 订单
  135. */
  136. export function formatOrderStatusDescription(order) {
  137. if (order.status === 0) {
  138. return `请在 ${ formatDate(order.payExpireTime) } 前完成支付`;
  139. }
  140. if (order.status === 10) {
  141. return '商家未发货,请耐心等待';
  142. }
  143. if (order.status === 20) {
  144. return '商家已发货,请耐心等待';
  145. }
  146. if (order.status === 30 && !order.commentStatus) {
  147. return '已收货,快去评价一下吧';
  148. }
  149. if (order.status === 30 && order.commentStatus) {
  150. return '交易完成,感谢您的支持';
  151. }
  152. return '交易关闭';
  153. }
  154. /**
  155. * 处理订单的 button 操作按钮数组
  156. *
  157. * @param order 订单
  158. */
  159. export function handleOrderButtons(order) {
  160. order.buttons = []
  161. if (order.type === 3) { // 查看拼团
  162. order.buttons.push('combination');
  163. }
  164. if (order.status === 20) { // 确认收货
  165. order.buttons.push('confirm');
  166. }
  167. if (order.logisticsId > 0) { // 查看物流
  168. order.buttons.push('express');
  169. }
  170. if (order.status === 0) { // 取消订单 / 发起支付
  171. order.buttons.push('cancel');
  172. order.buttons.push('pay');
  173. }
  174. if (order.status === 30 && !order.commentStatus) { // 发起评价
  175. order.buttons.push('comment');
  176. }
  177. if (order.status === 40) { // 删除订单
  178. order.buttons.push('delete');
  179. }
  180. }
  181. /**
  182. * 格式化售后状态
  183. *
  184. * @param afterSale 售后
  185. */
  186. export function formatAfterSaleStatus(afterSale) {
  187. if (afterSale.status === 10) {
  188. return '申请售后';
  189. }
  190. if (afterSale.status === 20) {
  191. return '商品待退货';
  192. }
  193. if (afterSale.status === 30) {
  194. return '商家待收货';
  195. }
  196. if (afterSale.status === 40) {
  197. return '等待退款';
  198. }
  199. if (afterSale.status === 50) {
  200. return '退款成功';
  201. }
  202. if (afterSale.status === 61) {
  203. return '买家取消';
  204. }
  205. if (afterSale.status === 62) {
  206. return '商家拒绝';
  207. }
  208. if (afterSale.status === 63) {
  209. return '商家拒收货';
  210. }
  211. return '未知状态';
  212. }
  213. /**
  214. * 格式化售后状态的描述
  215. *
  216. * @param afterSale 售后
  217. */
  218. export function formatAfterSaleStatusDescription(afterSale) {
  219. if (afterSale.status === 10) {
  220. return '退款申请待商家处理';
  221. }
  222. if (afterSale.status === 20) {
  223. return '请退货并填写物流信息';
  224. }
  225. if (afterSale.status === 30) {
  226. return '退货退款申请待商家处理';
  227. }
  228. if (afterSale.status === 40) {
  229. return '等待退款';
  230. }
  231. if (afterSale.status === 50) {
  232. return '退款成功';
  233. }
  234. if (afterSale.status === 61) {
  235. return '退款关闭';
  236. }
  237. if (afterSale.status === 62) {
  238. return `商家不同意退款申请,拒绝原因:${afterSale.auditReason}`;
  239. }
  240. if (afterSale.status === 63) {
  241. return `商家拒绝收货,不同意退款,拒绝原因:${afterSale.auditReason}`;
  242. }
  243. return '未知状态';
  244. }
  245. /**
  246. * 处理售后的 button 操作按钮数组
  247. *
  248. * @param afterSale 售后
  249. */
  250. export function handleAfterSaleButtons(afterSale) {
  251. afterSale.buttons = [];
  252. if ([10, 20, 30].includes(afterSale.status)) { // 取消订单
  253. afterSale.buttons.push('cancel');
  254. }
  255. if (afterSale.status === 20) { // 退货信息
  256. afterSale.buttons.push('delivery');
  257. }
  258. }
  259. /**
  260. * 倒计时
  261. * @param toTime 截止时间
  262. * @param fromTime 起始时间,默认当前时间
  263. * @return {{s: string, ms: number, h: string, m: string}} 持续时间
  264. */
  265. export function useDurationTime(toTime, fromTime = '') {
  266. toTime = getDayjsTime(toTime);
  267. if (fromTime === '') {
  268. fromTime = dayjs();
  269. }
  270. let duration = ref(toTime - fromTime);
  271. if (duration.value > 0) {
  272. setTimeout(() => {
  273. if (duration.value > 0) {
  274. duration.value -= 1000;
  275. }
  276. }, 1000);
  277. }
  278. let durationTime = dayjs.duration(duration.value);
  279. return {
  280. h: (durationTime.months() * 30 * 24 + durationTime.days() * 24 + durationTime.hours())
  281. .toString()
  282. .padStart(2, '0'),
  283. m: durationTime.minutes().toString().padStart(2, '0'),
  284. s: durationTime.seconds().toString().padStart(2, '0'),
  285. ms: durationTime.$ms,
  286. };
  287. }
  288. /**
  289. * 转换为 Dayjs
  290. * @param {any} time 时间
  291. * @return {dayjs.Dayjs}
  292. */
  293. function getDayjsTime(time) {
  294. time = time.toString();
  295. if (time.indexOf('-') > 0) {
  296. // 'date'
  297. return dayjs(time);
  298. }
  299. if (time.length > 10) {
  300. // 'timestamp'
  301. return dayjs(parseInt(time));
  302. }
  303. if (time.length === 10) {
  304. // 'unixTime'
  305. return dayjs.unix(parseInt(time));
  306. }
  307. }
  308. /**
  309. * 将分转成元
  310. *
  311. * @param price 分,例如说 100 分
  312. * @returns {string} 元,例如说 1.00 元
  313. */
  314. export function fen2yuan(price) {
  315. return (price / 100.0).toFixed(2)
  316. }
  317. /**
  318. * 从商品 SKU 数组中,转换出商品属性的数组
  319. *
  320. * 类似结构:[{
  321. * id: // 属性的编号
  322. * name: // 属性的名字
  323. * values: [{
  324. * id: // 属性值的编号
  325. * name: // 属性值的名字
  326. * }]
  327. * }]
  328. *
  329. * @param skus 商品 SKU 数组
  330. */
  331. export function convertProductPropertyList(skus) {
  332. let result = [];
  333. for (const sku of skus) {
  334. if (!sku.properties) {
  335. continue
  336. }
  337. for (const property of sku.properties) {
  338. // ① 先处理属性
  339. let resultProperty = result.find(item => item.id === property.propertyId)
  340. if (!resultProperty) {
  341. resultProperty = {
  342. id: property.propertyId,
  343. name: property.propertyName,
  344. values: []
  345. }
  346. result.push(resultProperty)
  347. }
  348. // ② 再处理属性值
  349. let resultValue = resultProperty.values.find(item => item.id === property.valueId)
  350. if (!resultValue) {
  351. resultProperty.values.push({
  352. id: property.valueId,
  353. name: property.valueName
  354. })
  355. }
  356. }
  357. }
  358. return result;
  359. }
  360. /**
  361. * 格式化满减送活动的规则
  362. *
  363. * @param activity 活动信息
  364. * @param rule 优惠规格
  365. * @returns {string} 规格字符串
  366. */
  367. export function formatRewardActivityRule(activity, rule) {
  368. if (activity.conditionType === 10) {
  369. return `满 ${fen2yuan(rule.limit)} 元减 ${fen2yuan(rule.discountPrice)} 元`;
  370. }
  371. if (activity.conditionType === 20) {
  372. return `满 ${rule.limit} 件减 ${fen2yuan(rule.discountPrice)} 元`;
  373. }
  374. return '';
  375. }
  376. // 新增将时间搓转换为开始时间-结束时间的格式
  377. export function formatDateRange(startTimestamp, endTimestamp) {
  378. // 定义一个辅助函数来格式化时间戳为 YYYY.MM.DD 格式
  379. const formatDate = (timestamp) => {
  380. const date = new Date(timestamp);
  381. const year = date.getFullYear();
  382. const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,所以需要+1
  383. const day = String(date.getDate()).padStart(2, '0');
  384. return `${year}.${month}.${day}`;
  385. };
  386. // 格式化开始和结束时间
  387. const start = formatDate(startTimestamp);
  388. const end = formatDate(endTimestamp);
  389. // 返回格式化的日期范围
  390. return `${start}-${end}`;
  391. }
  392. //处理活动信息
  393. export function handList(orders) {
  394. const typeMap = {
  395. '1': '秒杀活动',
  396. '2': '砍价活动',
  397. '3': '拼团活动',
  398. '4': '限时折扣',
  399. '5': '满减送',
  400. '6': '会员折扣',
  401. '7': '优惠券',
  402. '8': '积分'
  403. };
  404. // 给每个订单对象添加 typeName 属性
  405. let updatedOrders = orders.map(order => {
  406. return {
  407. ...order, // 展开现有的订单对象属性
  408. typeName: typeMap[order.type] // 添加 typeName 属性
  409. };
  410. });
  411. return updatedOrders
  412. };
  413. //根据skuid来修改价格并添加时间
  414. export function handListPrice(array,array2) {
  415. // 将 array2 转换为一个以 skuId 为键的对象,以便于快速查找
  416. const array2Map = array2.reduce((acc, item) => {
  417. acc[item.skuId] = { price: item.price, type: item.type,endTime:item.endTime };
  418. return acc;
  419. }, {});
  420. // 遍历 array 数组并更新 price 和 type
  421. array.forEach(item => {
  422. if (array2Map[item.id]) {
  423. item.oldPrice = item.price
  424. // 如果在 array2Map 中找到了对应的 skuId(即 id)
  425. item.price = array2Map[item.id].price;
  426. item.type = array2Map[item.id].type;
  427. item.endTime = array2Map[item.id].endTime;
  428. }
  429. });
  430. // 返回更新后的 array
  431. return array;
  432. };
  433. //处理活动数据
  434. export function handActitList(rules) {
  435. const rules2 = {
  436. reduc: rules.map(item => ({
  437. discountPrice: item.discountPrice,
  438. limit: item.limit,
  439. bull: true // 默认为 true
  440. })),
  441. cou: rules.map(item => ({
  442. discountPrice: item.discountPrice,
  443. value: item.couponCounts.reduce((acc, count) => acc + count, 0), // 计算 couponCounts 中各项之和
  444. bull: item.givePoint // 对应 givePoint
  445. })),
  446. ship: rules.map(item => ({
  447. discountPrice: item.discountPrice,
  448. bull: item.freeDelivery // 对应 freeDelivery
  449. })),
  450. scor: rules.map(item => ({
  451. discountPrice: item.discountPrice,
  452. value: item.point, // 直接使用 point
  453. bull: item.givePoint // 对应 givePoint
  454. }))
  455. };
  456. return rules2
  457. };