|
@@ -1,55 +1,53 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <view class="active-box">
|
|
|
|
|
- <!-- 热门标签 -->
|
|
|
|
|
- <view v-if="config.hot" class="btn-tag-star">
|
|
|
|
|
- <uni-icons type="star-filled" size="16" color="#ffd700"></uni-icons>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 图片区域 -->
|
|
|
|
|
- <view class="img crm-cursor" @click="handleClick">
|
|
|
|
|
- <image :src="imageSrc" mode="aspectFill" />
|
|
|
|
|
- <view v-if="config.imageTitle" class="imgTitle">{{ t(config.imageTitle) }}</view>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 内容区域 -->
|
|
|
|
|
- <view class="content">
|
|
|
|
|
- <view class="title">
|
|
|
|
|
- <span class="name crm-cursor crm-one-font" @click="handleClick">
|
|
|
|
|
- {{ t(config.title) }}
|
|
|
|
|
- </span>
|
|
|
|
|
- <span v-if="config.time" class="time">{{ config.time }}</span>
|
|
|
|
|
|
|
+ <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
|
|
|
|
|
+ <view class="active-box">
|
|
|
|
|
+ <!-- 热门标签 -->
|
|
|
|
|
+ <view v-if="config.hot" class="btn-tag-star">
|
|
|
|
|
+ <uni-icons type="star-filled" size="16" color="#ffd700"></uni-icons>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
- <view v-if="config.description" class="des crm-one-font">
|
|
|
|
|
- {{ t(config.description) }}
|
|
|
|
|
|
|
+ <!-- 图片区域 -->
|
|
|
|
|
+ <view class="img crm-cursor" @click="handleClick">
|
|
|
|
|
+ <image :src="imageSrc" mode="widthFix" />
|
|
|
|
|
+ <!-- <view v-if="config.imageTitle" class="imgTitle">{{ t(config.imageTitle) }}</view> -->
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
- <!-- 按钮区域 -->
|
|
|
|
|
- <view class="bottom">
|
|
|
|
|
- <template v-for="(btn, index) in config.buttons" :key="index">
|
|
|
|
|
- <span v-if="shouldShowButton(btn)" :class="['btn', getButtonType(btn)]" @click="handleButtonClick(btn)">
|
|
|
|
|
- {{ t(btn.text) }}
|
|
|
|
|
- <template v-if="btn.suffix && state[btn.suffix]">
|
|
|
|
|
- {{ state[btn.suffix] }}
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-if="btn.suffixText">
|
|
|
|
|
- {{ t(btn.suffixText) }}
|
|
|
|
|
|
|
+ <!-- 内容区域 -->
|
|
|
|
|
+ <view class="content">
|
|
|
|
|
+ <view class="content-box">
|
|
|
|
|
+ <view v-if="config.time" class="time">{{ config.time }}</view>
|
|
|
|
|
+ <view class="title" @click="handleClick">{{ t(config.title) }}</view>
|
|
|
|
|
+ <view v-if="config.description" class="des crm-one-font">{{ t(config.description) }}</view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 按钮区域 -->
|
|
|
|
|
+ <view class="bottom">
|
|
|
|
|
+ <template v-for="(btn, index) in config.buttons" :key="index">
|
|
|
|
|
+ <span v-if="shouldShowButton(btn)" :class="['btn', getButtonType(btn)]"
|
|
|
|
|
+ @click="handleButtonClick(btn)">
|
|
|
|
|
+ {{ t(btn.text) }}
|
|
|
|
|
+ <template v-if="btn.suffix && state[btn.suffix]">
|
|
|
|
|
+ {{ state[btn.suffix] }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-if="btn.suffixText">
|
|
|
|
|
+ {{ t(btn.suffixText) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span v-else-if="btn.elseType && btn.condition" :class="['btn', btn.elseType]">
|
|
|
|
|
+ {{ t(btn.text) }}
|
|
|
|
|
+ </span>
|
|
|
</template>
|
|
</template>
|
|
|
- </span>
|
|
|
|
|
- <span v-else-if="btn.elseType && btn.condition" :class="['btn', btn.elseType]">
|
|
|
|
|
- {{ t(btn.text) }}
|
|
|
|
|
- </span>
|
|
|
|
|
- </template>
|
|
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
|
|
+ </uni-col>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { computed } from 'vue'
|
|
import { computed } from 'vue'
|
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
|
|
|
|
-const { t, locale} = useI18n()
|
|
|
|
|
|
|
+const { t, locale } = useI18n()
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
const props = defineProps<{
|
|
|
config: any
|
|
config: any
|
|
@@ -71,7 +69,7 @@ const imageSrc = computed(() => {
|
|
|
const shouldShowButton = (btn: any): boolean => {
|
|
const shouldShowButton = (btn: any): boolean => {
|
|
|
if (!btn.condition) return true
|
|
if (!btn.condition) return true
|
|
|
if (!props.state) return false
|
|
if (!props.state) return false
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
const conditionStr = btn.condition
|
|
const conditionStr = btn.condition
|
|
|
const evalStr = conditionStr.replace(/([a-zA-Z_][a-zA-Z0-9_.]*)/g, (match) => {
|
|
const evalStr = conditionStr.replace(/([a-zA-Z_][a-zA-Z0-9_.]*)/g, (match) => {
|
|
@@ -123,132 +121,197 @@ const handleButtonClick = (btn: any) => {
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
|
|
|
+@import "@/uni.scss";
|
|
|
|
|
+
|
|
|
.active-box {
|
|
.active-box {
|
|
|
|
|
+ width: 100%;
|
|
|
position: relative;
|
|
position: relative;
|
|
|
- display: flex;
|
|
|
|
|
- background-color: #fff;
|
|
|
|
|
- border-radius: 16rpx;
|
|
|
|
|
- padding: 30rpx;
|
|
|
|
|
- margin-bottom: 20rpx;
|
|
|
|
|
- box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
|
+ margin-bottom: px2rpx(20);
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ // overflow: hidden;
|
|
|
|
|
+ aspect-ratio: 3 / 4;
|
|
|
|
|
|
|
|
.btn-tag-star {
|
|
.btn-tag-star {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
- top: 0;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- z-index: 1;
|
|
|
|
|
|
|
+ top: px2rpx(30);
|
|
|
|
|
+ left: px2rpx(30);
|
|
|
|
|
+ z-index: 2;
|
|
|
|
|
+ background: linear-gradient(135deg, #ffd700 0%, #ffb347 100%);
|
|
|
|
|
+ padding: px2rpx(12) px2rpx(28);
|
|
|
|
|
+ border-radius: px2rpx(40);
|
|
|
|
|
+ font-size: px2rpx(26);
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #0f1423;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: px2rpx(8);
|
|
|
|
|
+ box-shadow: 0 px2rpx(4) px2rpx(12) rgba(255, 215, 0, 0.3);
|
|
|
|
|
+ letter-spacing: px2rpx(1);
|
|
|
|
|
+ text-transform: uppercase;
|
|
|
|
|
+
|
|
|
|
|
+ .uni-icons {
|
|
|
|
|
+ font-size: px2rpx(28) !important;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.img {
|
|
.img {
|
|
|
- width: 200rpx;
|
|
|
|
|
- height: 200rpx;
|
|
|
|
|
- margin-right: 30rpx;
|
|
|
|
|
- border-radius: 12rpx;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
|
|
+ width: 100%;
|
|
|
position: relative;
|
|
position: relative;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
|
|
|
image {
|
|
image {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
- height: 100%;
|
|
|
|
|
object-fit: cover;
|
|
object-fit: cover;
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .imgTitle {
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- bottom: 0;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- right: 0;
|
|
|
|
|
- background: rgba(0, 0, 0, 0.5);
|
|
|
|
|
- color: #fff;
|
|
|
|
|
- font-size: 24rpx;
|
|
|
|
|
- padding: 8rpx;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
|
|
+ transition: transform 0.6s ease;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.content {
|
|
.content {
|
|
|
- flex: 1;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ padding: 0 px2rpx(14);
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ margin-top: px2rpx(-20);
|
|
|
|
|
|
|
|
- .title {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ .content-box {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: space-between;
|
|
|
|
|
- margin-bottom: 10rpx;
|
|
|
|
|
-
|
|
|
|
|
- .name {
|
|
|
|
|
- font-size: 32rpx;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: #333;
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
- text-overflow: ellipsis;
|
|
|
|
|
- white-space: nowrap;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ padding: 0 px2rpx(14);
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ background-color: var(--color-white);
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .time {
|
|
|
|
|
- font-size: 24rpx;
|
|
|
|
|
- color: #999;
|
|
|
|
|
- margin-left: 16rpx;
|
|
|
|
|
- white-space: nowrap;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .title {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ margin: px2rpx(20) 0;
|
|
|
|
|
+ font-size: px2rpx(24);
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ color: var(--color-error);
|
|
|
|
|
+ line-height: 1.3;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ margin-bottom: px2rpx(12);
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .time {
|
|
|
|
|
+ margin-top: px2rpx(20);
|
|
|
|
|
+ width: fit-content;
|
|
|
|
|
+ font-size: px2rpx(12);
|
|
|
|
|
+ color: var(--color-error);
|
|
|
|
|
+ background-color:
|
|
|
|
|
+ color-mix(in oklab, var(--color-error) 10%, transparent);
|
|
|
|
|
+ line-height: px2rpx(20);
|
|
|
|
|
+ padding: px2rpx(5) px2rpx(7);
|
|
|
|
|
+ border-radius: px2rpx(2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.des {
|
|
.des {
|
|
|
- font-size: 28rpx;
|
|
|
|
|
- color: #666;
|
|
|
|
|
- margin-bottom: 20rpx;
|
|
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ font-size: px2rpx(14);
|
|
|
|
|
+ color: var(--color-slate-900);
|
|
|
|
|
+ margin-bottom: px2rpx(40);
|
|
|
display: -webkit-box;
|
|
display: -webkit-box;
|
|
|
-webkit-line-clamp: 2;
|
|
-webkit-line-clamp: 2;
|
|
|
-webkit-box-orient: vertical;
|
|
-webkit-box-orient: vertical;
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
- line-height: 1.4;
|
|
|
|
|
|
|
+ line-height: 1.2;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.bottom {
|
|
.bottom {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
flex-wrap: wrap;
|
|
|
- gap: 16rpx;
|
|
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: px2rpx(20);
|
|
|
|
|
|
|
|
.btn {
|
|
.btn {
|
|
|
- padding: 10rpx 24rpx;
|
|
|
|
|
- border-radius: 40rpx;
|
|
|
|
|
- font-size: 24rpx;
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
- transition: all 0.3s;
|
|
|
|
|
|
|
+ color: var(--color-white);
|
|
|
|
|
+ padding: px2rpx(16);
|
|
|
|
|
+ font-size: px2rpx(14);
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ transition: all 0.3s ease;
|
|
|
display: inline-flex;
|
|
display: inline-flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
white-space: nowrap;
|
|
white-space: nowrap;
|
|
|
|
|
+ letter-spacing: px2rpx(1);
|
|
|
|
|
+ text-transform: uppercase;
|
|
|
|
|
|
|
|
&.red {
|
|
&.red {
|
|
|
- background-color: #ff4d4f;
|
|
|
|
|
- color: #fff;
|
|
|
|
|
- border: 1rpx solid #ff4d4f;
|
|
|
|
|
-
|
|
|
|
|
- &:active {
|
|
|
|
|
- opacity: 0.8;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ background-color: var(--color-secondary);
|
|
|
|
|
+ border: 1px solid #333333;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
&.gray {
|
|
&.gray {
|
|
|
- background-color: #f5f5f5;
|
|
|
|
|
- color: #999;
|
|
|
|
|
- border: 1rpx solid #e5e5e5;
|
|
|
|
|
|
|
+ padding: px2rpx(8) px2rpx(16);
|
|
|
|
|
+ font-size: px2rpx(11);
|
|
|
|
|
+ background-color: var(--color-navy-200);
|
|
|
|
|
+ border: 1px solid var(--color-sky-100);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
&.check {
|
|
&.check {
|
|
|
- background-color: #e6f7ff;
|
|
|
|
|
- color: #1890ff;
|
|
|
|
|
- border: 1rpx solid #91d5ff;
|
|
|
|
|
-
|
|
|
|
|
- &:active {
|
|
|
|
|
- opacity: 0.8;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ padding: px2rpx(8) px2rpx(16);
|
|
|
|
|
+ font-size: px2rpx(11);
|
|
|
|
|
+ background-color: var(--color-error);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 列表项样式(用于底部链接)
|
|
|
|
|
+ .link-list {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: px2rpx(30);
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ margin-top: px2rpx(30);
|
|
|
|
|
+ padding-top: px2rpx(30);
|
|
|
|
|
+ border-top: px2rpx(1) solid rgba(255, 215, 0, 0.2);
|
|
|
|
|
+
|
|
|
|
|
+ .link-item {
|
|
|
|
|
+ color: #8e9aaf;
|
|
|
|
|
+ font-size: px2rpx(26);
|
|
|
|
|
+ transition: color 0.3s;
|
|
|
|
|
+
|
|
|
|
|
+ &:active {
|
|
|
|
|
+ color: #ffd700;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &::before {
|
|
|
|
|
+ content: '•';
|
|
|
|
|
+ color: #ffd700;
|
|
|
|
|
+ margin-right: px2rpx(8);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 针对不同屏幕尺寸的响应式调整
|
|
|
|
|
+@media screen and (max-width: 767px) {
|
|
|
|
|
+ .active-box {
|
|
|
|
|
+
|
|
|
|
|
+ .title {
|
|
|
|
|
+ width: px2rpx(200) !important;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+// 添加悬停效果(仅H5)
|
|
|
|
|
+/* #ifdef H5 */
|
|
|
|
|
+.active-box:hover {
|
|
|
|
|
+ // transform: translateY(-6rpx);
|
|
|
|
|
+ // box-shadow: 0 p 60rpx rgba(0, 0, 0, 0.5);
|
|
|
|
|
+ // transition: all 0.3s ease;
|
|
|
|
|
+
|
|
|
|
|
+ .img image {
|
|
|
|
|
+ transform: scale(1.05);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* #endif */
|
|
|
</style>
|
|
</style>
|