discover.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. <template>
  2. <div class="pcPages" :style="warpCss">
  3. <div class="discover-bos" :style="boxCss">
  4. <!-- 头部 -->
  5. <div class="home-title flex-row-between" :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}">
  6. <div @click="onPath(componentData.titleUrl)">
  7. <span :style="titleCss" class="mr-[10px] color-[#101828] font-size-[20px] fw-600 hover-color">{{ componentData.title }}</span>
  8. <span :style="subtitleCss" class="color-[#364153] font-size-[14px]">{{ componentData.subtitle }}</span>
  9. </div>
  10. <div class="title-more flex-row-start">
  11. <div @click="onPath(item.url)" class="ml-[10px] hover-color" v-for="(item, index) in componentData.labelList" :key="index">
  12. {{ item.title }}
  13. </div>
  14. </div>
  15. </div>
  16. <!-- 中间区域 -->
  17. <div class="discover-box">
  18. <el-image
  19. class="discover-image"
  20. :src="componentData.imageUrl ? componentData.imageUrl : figure"
  21. :fit="componentData.imageUrl ? (componentData.imgType == 1 ? 'fill' : componentData.imgType == 2 ? 'contain' : 'cover') : 'cover'"
  22. :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}"
  23. @click="onPath(componentData.url)"
  24. />
  25. <div
  26. class="plan-bos"
  27. :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}"
  28. v-if="componentData.planList.length"
  29. >
  30. <div class="plan-head">方案推荐</div>
  31. <div v-for="(item, index) in componentData.planList" :key="index" class="plan-list hover-color" @click="onPath(item.url)">
  32. <el-image
  33. class="plan-image"
  34. :src="item.imageUrl ? item.imageUrl : figure"
  35. :fit="item.imgType == 1 ? 'fill' : item.imgType == 2 ? 'contain' : 'cover'"
  36. :style="componentData.imageRadius ? { borderRadius: componentData.imageRadius + 'px' } : {}"
  37. />
  38. <div class="plan-box flex-column-between">
  39. <div class="plan-title ellipsis zi-hover">{{ item.title }}</div>
  40. <div class="plan-subtitle">{{ item.subtitle }}</div>
  41. </div>
  42. </div>
  43. </div>
  44. <div
  45. class="detect-bos"
  46. :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}"
  47. v-if="componentData.detectList.length"
  48. >
  49. <div class="detect-head">发现</div>
  50. <div class="detect-box">
  51. <div class="detect-two">
  52. <div
  53. @click="onPath(componentData.detectList[0].url)"
  54. class="detect-list hover-color"
  55. :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}"
  56. >
  57. <div class="detect-item">
  58. <div class="detect-title ellipsis zi-hover">{{ componentData.detectList[0].title }}</div>
  59. <div class="detect-subtitle mt-[6px] h-[32px]">{{ componentData.detectList[0].subtitle }}</div>
  60. <div class="detect-btn" :style="{ backgroundColor: componentData.boxColor }">立即进入</div>
  61. </div>
  62. <el-image
  63. class="detect-image"
  64. :src="componentData.detectList[0].imageUrl ? componentData.detectList[0].imageUrl : figure"
  65. :fit="componentData.detectList[0].imgType == 1 ? 'fill' : componentData.detectList[0].imgType == 2 ? 'contain' : 'cover'"
  66. :style="componentData.imageRadius ? { borderRadius: componentData.imageRadius + 'px' } : {}"
  67. />
  68. </div>
  69. <div
  70. @click="onPath(componentData.detectList[1].url)"
  71. class="detect-list hover-color"
  72. :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}"
  73. >
  74. <div class="detect-item">
  75. <div class="detect-title ellipsis zi-hover">{{ componentData.detectList[1].title }}</div>
  76. <div class="detect-subtitle mt-[6px] h-[32px]">{{ componentData.detectList[1].subtitle }}</div>
  77. <div class="detect-btn" :style="{ backgroundColor: componentData.boxColor }">立即进入</div>
  78. </div>
  79. <el-image
  80. class="detect-image"
  81. :src="componentData.detectList[1].imageUrl ? componentData.detectList[1].imageUrl : figure"
  82. :fit="componentData.detectList[1].imgType == 1 ? 'fill' : componentData.detectList[1].imgType == 2 ? 'contain' : 'cover'"
  83. :style="componentData.imageRadius ? { borderRadius: componentData.imageRadius + 'px' } : {}"
  84. />
  85. </div>
  86. </div>
  87. <div
  88. class="detect-one flex-column-between hover-color"
  89. :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}"
  90. @click="onPath(componentData.detectList[2].url)"
  91. >
  92. <div>
  93. <div class="detect-title ellipsis zi-hover">{{ componentData.detectList[2].title }}</div>
  94. <div class="detect-subtitle mt-[6px]">{{ componentData.detectList[2].subtitle }}</div>
  95. </div>
  96. <el-image
  97. class="detect-img"
  98. :src="componentData.detectList[2].imageUrl ? componentData.detectList[2].imageUrl : figure"
  99. :fit="componentData.detectList[2].imgType == 1 ? 'fill' : componentData.detectList[2].imgType == 2 ? 'contain' : 'cover'"
  100. :style="componentData.imageRadius ? { borderRadius: componentData.imageRadius + 'px' } : {}"
  101. />
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. <!-- 底部 -->
  107. <div class="discover-foot">
  108. <div class="discover-tab" :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}">
  109. <div class="tab-head" :style="{ color: componentData.boxColor }">采购导航</div>
  110. <div class="tab-bos">
  111. <div @click="onPath(item.url)" v-for="(item, index) in componentData.tabList" :key="index" class="tab-list flex-row-center hover-color">
  112. {{ item.title }}
  113. </div>
  114. </div>
  115. </div>
  116. <template v-for="(item, index) in dataList" :key="index">
  117. <div
  118. v-if="Number(index) < 4"
  119. class="goods-bos flex-column-between hover-color"
  120. :style="componentData.boxRadius ? { borderRadius: componentData.boxRadius + 'px' } : {}"
  121. @click="onPath('/item?id=' + item.id + '&productNo=' + item.productNo)"
  122. >
  123. <img
  124. class="goods-img"
  125. :src="item.productImage ? item.productImage : figure"
  126. alt=""
  127. :style="componentData.imageRadius ? { borderRadius: componentData.imageRadius + 'px' } : {}"
  128. />
  129. <div>
  130. <div class="goods-name zi-hover">{{ item.itemName || '商品名称' }}</div>
  131. <div>
  132. <span class="goods-price" :style="{ color: componentData.boxColor }">¥{{ item.memberPrice || '0.00' }}</span>
  133. <span class="goods-marketPrice">¥{{ item.marketPrice }}</span>
  134. </div>
  135. </div>
  136. </div>
  137. </template>
  138. </div>
  139. </div>
  140. </div>
  141. </template>
  142. <script setup lang="ts">
  143. import { onPath } from '@/utils/siteConfig';
  144. import figure from '@/assets/images/figure.png';
  145. import { getDiyProductPage, getCustomerProductPage } from '@/api/home/diy';
  146. const props = defineProps<{
  147. row?: any;
  148. datas?: any;
  149. }>();
  150. const componentData = props.row || {};
  151. const dataList = ref<any>([{}, {}, {}, {}]);
  152. onMounted(() => {
  153. if (props.datas) {
  154. dataList.value = props.datas;
  155. } else {
  156. getDataList();
  157. }
  158. });
  159. const getDataList = () => {
  160. dataList.value = [{}, {}, {}, {}];
  161. if (componentData.goodsIds.length > 0) {
  162. const apiFunc = componentData.clientId && componentData.clientId !== 'undefined' ? getCustomerProductPage : getDiyProductPage;
  163. const queryParams = {
  164. pageNum: 1,
  165. pageSize: 10,
  166. ids: componentData.goodsIds.join(','),
  167. customerId: ''
  168. };
  169. if (componentData.clientId && componentData.clientId != 'undefined') {
  170. queryParams.customerId = componentData.clientId;
  171. } else {
  172. delete queryParams.customerId;
  173. }
  174. apiFunc(queryParams).then((res) => {
  175. if (res.code == 200) {
  176. dataList.value = res.rows;
  177. }
  178. });
  179. }
  180. };
  181. const warpCss = computed(() => {
  182. let style = '';
  183. style += 'position:relative;';
  184. //背景颜色
  185. if (componentData.pageStartBgColor) {
  186. if (componentData.pageStartBgColor && componentData.pageEndBgColor)
  187. style += `background:linear-gradient(${componentData.pageGradientAngle},${componentData.pageStartBgColor},${componentData.pageEndBgColor});`;
  188. else if (componentData.pageStartBgColor) style += `background: ${componentData.pageStartBgColor};`;
  189. else if (componentData.pageEndBgColor) style += `background: ${componentData.pageEndBgColor};`;
  190. }
  191. //背景图片
  192. if (componentData.componentBgUrl) {
  193. style += `background-image:url('${componentData.componentBgUrl}');`;
  194. style += 'background-size: cover;background-repeat: no-repeat;';
  195. }
  196. //边距
  197. if (componentData.padding) {
  198. if (componentData.padding.top > 0) {
  199. style += 'padding-top:' + componentData.padding.top + 'px' + ';';
  200. }
  201. if (componentData.padding.bottom > 0) {
  202. style += 'padding-bottom:' + componentData.padding.bottom + 'px' + ';';
  203. }
  204. style += 'padding-right:' + componentData.padding.both + 'px' + ';';
  205. style += 'padding-left:' + componentData.padding.both + 'px' + ';';
  206. }
  207. //圆角
  208. if (componentData.topRounded) style += 'border-top-left-radius:' + componentData.topRounded + 'px;';
  209. if (componentData.topRounded) style += 'border-top-right-radius:' + componentData.topRounded + 'px;';
  210. if (componentData.bottomRounded) style += 'border-bottom-left-radius:' + componentData.bottomRounded + 'px;';
  211. if (componentData.bottomRounded) style += 'border-bottom-right-radius:' + componentData.bottomRounded + 'px;';
  212. //间距
  213. if (componentData.margin) {
  214. if (componentData.margin.top > 0) {
  215. style += 'margin-top:' + componentData.margin.top + 'px' + ';';
  216. }
  217. if (componentData.margin.bottom > 0) {
  218. style += 'margin-bottom:' + componentData.margin.bottom + 'px' + ';';
  219. }
  220. }
  221. return style;
  222. });
  223. //组件样式
  224. const boxCss = computed(() => {
  225. let style = '';
  226. if (componentData.componentStartBgColor && componentData.componentEndBgColor)
  227. style += `background:linear-gradient(${componentData.componentGradientAngle},${componentData.componentStartBgColor},${componentData.componentEndBgColor});`;
  228. else if (componentData.componentStartBgColor) style += 'background-color:' + componentData.componentStartBgColor + ';';
  229. else if (componentData.componentEndBgColor) style += 'background-color:' + componentData.componentEndBgColor + ';';
  230. if (componentData.number) style += 'flex:' + `0 0 calc((100% - ${(componentData.number - 1) * 10}px) / ${componentData.number})` + ';';
  231. return style;
  232. });
  233. // 标题样式
  234. const titleCss = computed(() => {
  235. let style = '';
  236. if (componentData.titleColor) style += 'color:' + componentData.titleColor + ';';
  237. if (componentData.titleSize) style += 'font-size:' + componentData.titleSize + 'px;';
  238. if (componentData.titleWeight) style += 'font-weight:' + componentData.titleWeight + ';';
  239. return style;
  240. });
  241. // 副标题样式
  242. const subtitleCss = computed(() => {
  243. let style = '';
  244. if (componentData.subtitleColor) style += 'color:' + componentData.subtitleColor + ';';
  245. if (componentData.subtitleSize) style += 'font-size:' + componentData.subtitleSize + 'px;';
  246. return style;
  247. });
  248. </script>
  249. <style lang="scss" scoped>
  250. .pcPages {
  251. width: 100%;
  252. max-width: 1500px;
  253. min-width: 1200px;
  254. margin: 0 auto;
  255. .discover-bos {
  256. width: 100%;
  257. .home-title {
  258. width: 100%;
  259. background-color: #ffffff;
  260. padding: 15px 20px;
  261. border-radius: 5px;
  262. cursor: pointer;
  263. .title-more {
  264. font-size: 14px;
  265. color: #333333;
  266. }
  267. }
  268. }
  269. //中间区域
  270. .discover-box {
  271. height: 340px;
  272. width: 100%;
  273. margin-top: 10px;
  274. display: flex;
  275. gap: 10px;
  276. .discover-image {
  277. width: 230px;
  278. height: 340px;
  279. border-radius: 5px;
  280. cursor: pointer;
  281. }
  282. // 方案
  283. .plan-bos {
  284. flex: 1;
  285. height: 340px;
  286. background: #ffffff;
  287. padding: 0px 15px;
  288. display: flex;
  289. flex-direction: column;
  290. min-width: 0;
  291. border-radius: 5px;
  292. .plan-head {
  293. font-weight: 600;
  294. font-size: 16px;
  295. color: #101828;
  296. height: 50px;
  297. line-height: 50px;
  298. }
  299. .plan-list {
  300. flex: 1;
  301. display: flex;
  302. border-bottom: 1px solid #e5e7eb;
  303. cursor: pointer;
  304. width: 100%;
  305. margin-bottom: 14px;
  306. &:last-child {
  307. border-bottom: none;
  308. margin-bottom: 0;
  309. }
  310. .plan-image {
  311. width: 72px;
  312. height: 72px;
  313. margin-right: 10px;
  314. }
  315. .plan-box {
  316. height: 72px;
  317. flex: 1;
  318. padding: 8px 0px 8px 5px;
  319. width: 0;
  320. .plan-title {
  321. font-weight: 600;
  322. font-size: 14px;
  323. color: #101828;
  324. }
  325. .plan-subtitle {
  326. height: 34px;
  327. font-weight: 400;
  328. font-size: 12px;
  329. color: #364153;
  330. display: -webkit-box;
  331. -webkit-line-clamp: 2;
  332. line-clamp: 2;
  333. /* 添加标准属性 */
  334. -webkit-box-orient: vertical;
  335. overflow: hidden;
  336. text-overflow: ellipsis;
  337. }
  338. }
  339. }
  340. }
  341. .detect-bos {
  342. flex: 1;
  343. height: 340px;
  344. background: #ffffff;
  345. padding: 0px 15px 15px 15px;
  346. border-radius: 5px;
  347. .detect-head {
  348. font-weight: 600;
  349. font-size: 16px;
  350. color: #101828;
  351. height: 50px;
  352. line-height: 50px;
  353. }
  354. .detect-box {
  355. display: flex;
  356. gap: 10px;
  357. .detect-title {
  358. font-weight: 600;
  359. font-size: 14px;
  360. color: #101828;
  361. }
  362. .detect-subtitle {
  363. font-weight: 400;
  364. font-size: 12px;
  365. color: #364153;
  366. display: -webkit-box;
  367. -webkit-line-clamp: 2;
  368. line-clamp: 2;
  369. /* 添加标准属性 */
  370. -webkit-box-orient: vertical;
  371. overflow: hidden;
  372. text-overflow: ellipsis;
  373. }
  374. .detect-two {
  375. flex: 1;
  376. width: 0;
  377. .detect-list {
  378. width: 100%;
  379. height: 132.5px;
  380. border: 1px solid #e5e7eb;
  381. margin-top: 10px;
  382. padding: 25px 10px;
  383. display: flex;
  384. gap: 10px;
  385. cursor: pointer;
  386. &:first-child {
  387. margin-top: 0;
  388. }
  389. .detect-item {
  390. flex: 1;
  391. width: 0;
  392. .detect-btn {
  393. width: 68px;
  394. height: 24px;
  395. text-align: center;
  396. line-height: 24px;
  397. font-size: 12px;
  398. color: #ffffff;
  399. margin-top: 12px;
  400. }
  401. }
  402. .detect-image {
  403. height: 72px;
  404. width: 72px;
  405. }
  406. }
  407. }
  408. .detect-one {
  409. cursor: pointer;
  410. width: 180px;
  411. height: 275px;
  412. border: 1px solid #e5e7eb;
  413. background-color: #ffffff;
  414. padding: 25px 10px;
  415. .detect-img {
  416. height: 124px;
  417. width: 124px;
  418. margin: 0 auto;
  419. }
  420. }
  421. }
  422. }
  423. }
  424. //底部
  425. .discover-foot {
  426. display: flex;
  427. gap: 10px;
  428. margin-top: 10px;
  429. .discover-tab {
  430. width: 230px;
  431. height: 310px;
  432. background: #ffffff;
  433. padding: 0 15px 15px 15px;
  434. border-radius: 5px;
  435. .tab-head {
  436. font-weight: 600;
  437. font-size: 16px;
  438. height: 50px;
  439. line-height: 50px;
  440. }
  441. .tab-bos {
  442. display: flex;
  443. flex-wrap: wrap;
  444. justify-content: space-between;
  445. gap: 10px 0;
  446. .tab-list {
  447. width: 94px;
  448. height: 32px;
  449. background: #f4f4f4;
  450. font-size: 14px;
  451. color: #101828;
  452. border-radius: 4px 4px 4px 4px;
  453. cursor: pointer;
  454. &:hover {
  455. background: var(--el-color-primary);
  456. color: #ffffff !important;
  457. }
  458. }
  459. }
  460. }
  461. .goods-bos {
  462. flex: 0 0 calc((100% - 270px) / 4);
  463. width: 0;
  464. background: #ffffff;
  465. height: 310px;
  466. padding: 15px 20px;
  467. border-radius: 5px;
  468. cursor: pointer;
  469. .goods-img {
  470. width: 100%;
  471. height: 190px;
  472. border-radius: 5px;
  473. }
  474. .goods-name {
  475. width: 100%;
  476. display: -webkit-box;
  477. -webkit-line-clamp: 3;
  478. line-clamp: 3;
  479. /* 添加标准属性 */
  480. -webkit-box-orient: vertical;
  481. overflow: hidden;
  482. text-overflow: ellipsis;
  483. font-size: 14px;
  484. color: #101828;
  485. height: 57px;
  486. }
  487. .goods-price {
  488. font-size: 16px;
  489. margin-top: 5px;
  490. color: #e7000b;
  491. font-weight: 600;
  492. }
  493. .goods-marketPrice {
  494. font-size: 12px;
  495. color: #99a1af;
  496. line-height: 20px;
  497. text-decoration-line: line-through;
  498. margin-left: 6px;
  499. }
  500. }
  501. }
  502. }
  503. </style>