init
This commit is contained in:
60
uni_modules/nutui-uni/components/comment/comment.ts
Normal file
60
uni_modules/nutui-uni/components/comment/comment.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { CLICK_EVENT } from '../_constants'
|
||||
import { commonProps, isString, makeArrayProp, makeObjectProp, makeStringProp } from '../_utils'
|
||||
import type { FollowType, ImagesType, InfoType, VideosType } from './type'
|
||||
|
||||
export const commentProps = {
|
||||
...commonProps,
|
||||
/**
|
||||
* @description 头部样式展示类型,可选: `default`,`complex`
|
||||
*/
|
||||
headerType: makeStringProp<'default' | 'complex'>('default'),
|
||||
/**
|
||||
* @description 评论图片展示行数,可选: `one`,`multi`
|
||||
*/
|
||||
imagesRows: makeStringProp<'one' | 'multi'>('one'),
|
||||
/**
|
||||
* @description 设置评论内容省略行数
|
||||
*/
|
||||
ellipsis: {
|
||||
type: [String, Number, Boolean],
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* @description 视频信息
|
||||
*/
|
||||
videos: makeArrayProp<VideosType>([]),
|
||||
/**
|
||||
* @description 图片信息
|
||||
*/
|
||||
images: makeArrayProp<ImagesType>([]),
|
||||
/**
|
||||
* @description 评论详情
|
||||
*/
|
||||
info: makeObjectProp<InfoType>({} as InfoType),
|
||||
/**
|
||||
* @description
|
||||
*/
|
||||
labels: {
|
||||
type: Function,
|
||||
default: () => '',
|
||||
},
|
||||
/**
|
||||
* @description 追评内容
|
||||
*/
|
||||
follow: makeObjectProp<FollowType>({} as FollowType),
|
||||
/**
|
||||
* @description 配置底部按钮
|
||||
*/
|
||||
operation: makeArrayProp<'replay' | 'like' | 'more'>(['replay', 'like', 'more']),
|
||||
}
|
||||
|
||||
export type CommentProps = ExtractPropTypes<typeof commentProps>
|
||||
|
||||
export const commentEmits = {
|
||||
[CLICK_EVENT]: (val: object) => val instanceof Object,
|
||||
clickOperate: (val: string) => isString(val),
|
||||
clickImages: (val: any) => val instanceof Object,
|
||||
}
|
||||
|
||||
export type CommentEmits = typeof commentEmits
|
||||
122
uni_modules/nutui-uni/components/comment/comment.vue
Normal file
122
uni_modules/nutui-uni/components/comment/comment.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import { CLICK_EVENT, PREFIX } from '../_constants'
|
||||
import { getMainClass } from '../_utils'
|
||||
import NutIcon from '../icon/icon.vue'
|
||||
import { commentEmits, commentProps } from './comment'
|
||||
import ComentBottom from './components/CmtBottom.vue'
|
||||
import CommentHeader from './components/CmtHeader.vue'
|
||||
import ComentImages from './components/CmtImages.vue'
|
||||
|
||||
const props = defineProps(commentProps)
|
||||
const emit = defineEmits(commentEmits)
|
||||
const classes = computed(() => {
|
||||
return getMainClass(props, componentName)
|
||||
})
|
||||
|
||||
const conEllipsis = computed(() => {
|
||||
if (props.ellipsis)
|
||||
return props.ellipsis
|
||||
|
||||
return props.headerType === 'complex' ? 6 : 2
|
||||
})
|
||||
function clickOperate(t: string) {
|
||||
emit('clickOperate', t)
|
||||
}
|
||||
|
||||
function handleClick() {
|
||||
emit(CLICK_EVENT, props.info)
|
||||
}
|
||||
|
||||
function clickImages(value: any) {
|
||||
emit('clickImages', value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-comment`
|
||||
|
||||
export default defineComponent({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view v-if="info && Object.keys(info)" :class="classes" :style="customStyle">
|
||||
<!-- 根据展示信息的多少,分为3种展示风格:simple,base,complex -->
|
||||
<CommentHeader
|
||||
:type="headerType"
|
||||
:info="info"
|
||||
:labels="labels"
|
||||
@handle-click="handleClick"
|
||||
>
|
||||
<template #labels>
|
||||
<slot name="commentLabels" />
|
||||
</template>
|
||||
</CommentHeader>
|
||||
|
||||
<slot name="feature" />
|
||||
|
||||
<!-- #ifndef H5 -->
|
||||
<!-- BUG web端使用 rich-text自定义 style 会导致内存泄漏 -->
|
||||
<rich-text
|
||||
class="nut-comment__main"
|
||||
:style="`-webkit-line-clamp:${conEllipsis}`"
|
||||
:nodes="info.content"
|
||||
@click="handleClick"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef H5 -->
|
||||
<text
|
||||
class="nut-comment__main"
|
||||
:style="`-webkit-line-clamp:${conEllipsis}`"
|
||||
@click="handleClick"
|
||||
>
|
||||
{{ info.content }}
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
|
||||
<ComentImages
|
||||
:images="images"
|
||||
:videos="videos"
|
||||
:type="imagesRows"
|
||||
@click-images="clickImages"
|
||||
/>
|
||||
|
||||
<view v-if="follow && follow.days > 0" class="nut-comment__follow" @click="handleClick">
|
||||
<view class="nut-comment__follow-title">
|
||||
购买{{ follow.days }}天后追评
|
||||
</view>
|
||||
<view class="nut-comment__follow-com">
|
||||
{{ follow.content }}
|
||||
</view>
|
||||
<view
|
||||
v-if="follow.images && follow.images.length > 0"
|
||||
class="nut-comment__follow-img"
|
||||
@click="clickImages(follow.images)"
|
||||
>
|
||||
{{ follow.images.length }} 张追评图片 <NutIcon name="right" size="12px" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<ComentBottom
|
||||
:type="headerType"
|
||||
:info="info"
|
||||
:operation="operation"
|
||||
@click-operate="clickOperate"
|
||||
@handle-click="handleClick"
|
||||
/>
|
||||
|
||||
<slot name="commentShopReply" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import './index';
|
||||
</style>
|
||||
@@ -0,0 +1,188 @@
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue'
|
||||
import { defineComponent, onMounted, ref } from 'vue'
|
||||
import { PREFIX } from '../../_constants'
|
||||
import { useTranslate } from '../../../locale'
|
||||
import NutIcon from '../../icon/icon.vue'
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'base', // simple,base,complex
|
||||
},
|
||||
info: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
operation: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => ['replay', 'like', 'more'],
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['clickOperate', 'handleClick'])
|
||||
|
||||
const showPopver = ref(false)
|
||||
|
||||
const mergeOp = ref([])
|
||||
|
||||
onMounted(() => {
|
||||
const deOp = ['replay', 'like', 'more']
|
||||
|
||||
if (props.operation) {
|
||||
props.operation.forEach((name: string) => {
|
||||
if (deOp.includes(name))
|
||||
(mergeOp.value as any).push(name)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
function operate(type: string) {
|
||||
if (type === 'more')
|
||||
showPopver.value = !showPopver.value
|
||||
|
||||
emit('clickOperate', type)
|
||||
}
|
||||
|
||||
function handleClick() {
|
||||
emit('handleClick')
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-comment-bottom`
|
||||
const { translate } = useTranslate(componentName)
|
||||
export default defineComponent ({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="nut-comment-bottom">
|
||||
<view class="nut-comment-bottom__lable" @click="handleClick">
|
||||
<span v-if="type !== 'complex'" style="display: inline;white-space:none;">
|
||||
{{ info.size }}
|
||||
</span>
|
||||
</view>
|
||||
|
||||
<view class="nut-comment-bottom__cpx">
|
||||
<template v-for="(name, i) in mergeOp" :key="i">
|
||||
<view class="nut-comment-bottom__cpx-item" :class="[`nut-comment-bottom__cpx-item--${name}`]" @click="operate(name)">
|
||||
<template v-if="name !== 'more'">
|
||||
<text>{{ info[name] }}</text>
|
||||
<NutIcon v-if="name === 'like'" name="fabulous" />
|
||||
<NutIcon v-else name="comment" />
|
||||
</template>
|
||||
<template v-if="name === 'more'">
|
||||
<NutIcon name="more-x" />
|
||||
<view v-if="showPopver" class="nut-comment-bottom__cpx-item-popover" @click="operate('popover')">
|
||||
{{
|
||||
translate('complaintsText')
|
||||
}}
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.nut-theme-dark {
|
||||
.nut-comment {
|
||||
&-bottom {
|
||||
&__cpx {
|
||||
color: $dark-color;
|
||||
|
||||
&-item {
|
||||
text {
|
||||
color: $dark-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nut-comment {
|
||||
&-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-right: 5px;
|
||||
color: $comment-bottom-label-color;
|
||||
|
||||
&__lable {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
|
||||
// stylelint-disable-next-line at-rule-no-unknown
|
||||
@include oneline-ellipsis;
|
||||
}
|
||||
|
||||
&__cpx {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
color: $black;
|
||||
|
||||
&-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 18px;
|
||||
|
||||
text {
|
||||
margin-right: 5px;
|
||||
color: $black;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&-popover {
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
right: 18px;
|
||||
width: max-content;
|
||||
padding: 10px;
|
||||
background: $white;
|
||||
border-radius: 5px 0 5px 5px;
|
||||
box-shadow: 0 0 6px $disable-color;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
right: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
content: "";
|
||||
border-top: 10px solid transparent;
|
||||
border-right: 0 solid transparent;
|
||||
border-bottom: 10px solid $white;
|
||||
border-left: 14px solid transparent;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: -22px;
|
||||
right: -1px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
content: "";
|
||||
border-top: 10px solid transparent;
|
||||
border-right: 0 solid transparent;
|
||||
border-bottom: 10px solid rgb(114 113 113 / 10%);
|
||||
border-left: 14px solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,242 @@
|
||||
<script setup lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { PREFIX } from '../../_constants'
|
||||
import NutRate from '../../rate/rate.vue'
|
||||
|
||||
defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'default', // default,complex
|
||||
},
|
||||
info: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['handleClick'])
|
||||
|
||||
function handleClick() {
|
||||
emit('handleClick')
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-comment-header`
|
||||
|
||||
export default defineComponent ({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="info" class="nut-comment-header" @click="handleClick">
|
||||
<view class="nut-comment-header__user">
|
||||
<view class="nut-comment-header__user-avter">
|
||||
<image v-if="info.avatar" :src="info.avatar" />
|
||||
</view>
|
||||
|
||||
<view v-if="type === 'default'" :class="[`nut-comment-header__user-${type}`]">
|
||||
<view :class="[`nut-comment-header__user-${type}-name`]">
|
||||
<text>{{ info.nickName }}</text>
|
||||
<slot name="labels" />
|
||||
</view>
|
||||
|
||||
<view class="nut-comment-header__user-score">
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<NutRate
|
||||
v-model="info.score"
|
||||
size="12"
|
||||
spacing="5"
|
||||
readonly
|
||||
@change="handleClick"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else :class="[`nut-comment-header__user-${type}`]">
|
||||
<text :class="[`nut-comment-header__user-${type}-name`]">
|
||||
{{ info.nickName }}
|
||||
</text>
|
||||
<slot name="labels" />
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="info.time" class="nut-comment-header__time">
|
||||
{{ info.time }}
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="type === 'complex'" :class="[`nut-comment-header__${type}-score`]">
|
||||
<NutRate
|
||||
v-model="info.score"
|
||||
size="12"
|
||||
spacing="3"
|
||||
readonly
|
||||
/>
|
||||
<i :class="[`nut-comment-header__${type}-score-i`]" />
|
||||
<view :class="[`nut-comment-header__${type}-score-size`]">
|
||||
{{ info.size }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.nut-theme-dark {
|
||||
.nut-comment {
|
||||
&-header {
|
||||
&__user {
|
||||
&-name {
|
||||
color: $dark-color;
|
||||
}
|
||||
|
||||
&-default {
|
||||
&-name {
|
||||
color: $dark-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nut-comment {
|
||||
&-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&__user {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
|
||||
&-avter {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 50%;
|
||||
|
||||
image {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&-name {
|
||||
/* stylelint-disable-next-line at-rule-no-unknown */
|
||||
@include oneline-ellipsis;
|
||||
|
||||
width: auto;
|
||||
max-width: 80px;
|
||||
margin-right: 5px;
|
||||
font-size: 12px;
|
||||
color: $comment-header-user-name-color;
|
||||
}
|
||||
|
||||
&-default {
|
||||
flex: 1;
|
||||
|
||||
&-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 3px;
|
||||
|
||||
/* stylelint-disable-next-line at-rule-no-unknown */
|
||||
@include oneline-ellipsis;
|
||||
|
||||
font-size: 12px;
|
||||
color: $comment-header-user-name-color;
|
||||
|
||||
> text {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-complex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: $comment-header-user-name-color;
|
||||
|
||||
&-name {
|
||||
max-width: 80px;
|
||||
margin-right: 10px;
|
||||
|
||||
/* stylelint-disable-next-line at-rule-no-unknown */
|
||||
@include text-ellipsis;
|
||||
}
|
||||
|
||||
image {
|
||||
max-width: 50px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&-score {
|
||||
.nut-rate-item {
|
||||
display: block !important;
|
||||
line-height: 10px;
|
||||
|
||||
.nut-icon {
|
||||
line-height: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__time {
|
||||
width: 100px;
|
||||
font-size: 12px;
|
||||
color: $comment-header-time-color;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&__complex-score {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.nut-rate-item {
|
||||
display: block !important;
|
||||
line-height: 12px;
|
||||
|
||||
.nut-icon {
|
||||
line-height: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&-i {
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 6px;
|
||||
margin: 0 8px 0 6px;
|
||||
font-style: inherit;
|
||||
background: $text-color;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
&-size {
|
||||
/* stylelint-disable-next-line at-rule-no-unknown */
|
||||
@include oneline-ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
&__labels--item {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
margin-right: 4px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,228 @@
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue'
|
||||
import { defineComponent, onMounted, ref, watch } from 'vue'
|
||||
import { PREFIX } from '../../_constants'
|
||||
import NutIcon from '../../icon/icon.vue'
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'one', // one multi
|
||||
},
|
||||
videos: {
|
||||
type: Array as PropType<VideosType[]>,
|
||||
default: () => [],
|
||||
},
|
||||
images: {
|
||||
type: Array as PropType<ImagesType[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['click', 'clickImages'])
|
||||
|
||||
interface VideosType {
|
||||
id: number | string
|
||||
mainUrl: string
|
||||
videoUrl: string
|
||||
}
|
||||
interface ImagesType {
|
||||
smallImgUrl: string
|
||||
bigImgUrl: string
|
||||
imgUrl: string
|
||||
}
|
||||
|
||||
const totalImages = ref<(VideosType | ImagesType)[]>([])
|
||||
|
||||
watch(
|
||||
() => [props.videos, props.images],
|
||||
(value) => {
|
||||
if (value[0].length > 0) {
|
||||
value[0].forEach((el: any) => {
|
||||
el.type = 'video'
|
||||
})
|
||||
}
|
||||
totalImages.value = (value[0] as any).concat(value[1])
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.videos.length > 0) {
|
||||
props.videos.forEach((el: any) => {
|
||||
el.type = 'video'
|
||||
})
|
||||
}
|
||||
totalImages.value = (props.videos as any).concat(props.images)
|
||||
})
|
||||
|
||||
function showImages(type: string, index: string | number) {
|
||||
const { videos, images } = props
|
||||
|
||||
const i = type === 'img' ? (index as number) - videos.length : index
|
||||
emit('clickImages', {
|
||||
type,
|
||||
index: i,
|
||||
value: type === 'img' ? images[i as number] : videos[i as number],
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-comment-images`
|
||||
|
||||
export default defineComponent({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view :class="`nut-comment-images nut-comment-images--${type}`">
|
||||
<!-- videos -->
|
||||
<view
|
||||
v-for="(itV, index) in videos"
|
||||
:key="itV.id"
|
||||
class="nut-comment-images__item nut-comment-images__item--video"
|
||||
@click="showImages('video', index)"
|
||||
>
|
||||
<image :src="itV.mainUrl" />
|
||||
<view class="nut-comment-images__play" />
|
||||
</view>
|
||||
<!-- images -->
|
||||
<template v-for="(itI, index) in images" :key="index">
|
||||
<view
|
||||
v-if="(type === 'multi' && videos.length + index < 9) || type !== 'multi'"
|
||||
class="nut-comment-images__item nut-comment-images__item--imgbox"
|
||||
@click="showImages('img', index + videos.length)"
|
||||
>
|
||||
<image :src="itI.smallImgUrl ? itI.smallImgUrl : itI.imgUrl" />
|
||||
|
||||
<view
|
||||
v-if="type === 'multi' && totalImages.length > 9 && videos.length + index > 7"
|
||||
class="nut-comment-images__mask"
|
||||
>
|
||||
<text>共 {{ totalImages.length }} 张</text>
|
||||
<NutIcon name="right" size="12px" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.nut-comment {
|
||||
&-images {
|
||||
display: flex;
|
||||
margin: 10px 0 12px;
|
||||
overflow: auto hidden;
|
||||
|
||||
&__item {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-right: 5px;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
|
||||
image {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
// &--imgbox {
|
||||
// // background: #f00;
|
||||
// }
|
||||
|
||||
&--video {
|
||||
// stylelint-disable-next-line rule-empty-line-before
|
||||
image {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
// height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
font-size: 12px;
|
||||
line-height: 90px;
|
||||
color: rgb(255 255 255 / 100%);
|
||||
background: rgb(0 0 0 / 50%);
|
||||
}
|
||||
}
|
||||
|
||||
&-images--multi {
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
margin: 10px auto 15px;
|
||||
overflow: hidden;
|
||||
|
||||
.nut-comment-images__item {
|
||||
width: calc(34% - 8px);
|
||||
height: 90px;
|
||||
margin: 8px 8px 0 0;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.svg-demo {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
&:nth-child(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: block;
|
||||
width: 105px;
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
&-images__play {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: rgb(0 0 0 / 50%);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%);
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
left: 15px;
|
||||
display: block;
|
||||
content: "";
|
||||
border-top: 9px solid transparent;
|
||||
border-bottom: 9px solid transparent;
|
||||
border-left: 15px solid #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
83
uni_modules/nutui-uni/components/comment/index.scss
Normal file
83
uni_modules/nutui-uni/components/comment/index.scss
Normal file
@@ -0,0 +1,83 @@
|
||||
@import '../rate/index';
|
||||
|
||||
.nut-theme-dark {
|
||||
.nut-comment {
|
||||
&__follow {
|
||||
&-title {
|
||||
color: $dark-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.nut-comment-shop {
|
||||
border-top: 1px solid $dark-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nut-comment {
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
|
||||
|
||||
|
||||
&__main {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
&__follow {
|
||||
&-title {
|
||||
position: relative;
|
||||
padding-left: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: $black;
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
top: 13%;
|
||||
left: 0;
|
||||
color: $primary-color;
|
||||
opacity: 0.4;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
&-com {
|
||||
margin: 8px 0 8px 8px;
|
||||
|
||||
@include moreline-ellipsis(6);
|
||||
}
|
||||
|
||||
&-img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 0 8px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.nut-comment-shop {
|
||||
width: 100%;
|
||||
padding-top: 10px;
|
||||
margin-top: 20px;
|
||||
border-top: 1px solid rgb(0 0 0 / 10%);
|
||||
|
||||
@include moreline-ellipsis(6);
|
||||
|
||||
text {
|
||||
color: $comment-shop-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
uni_modules/nutui-uni/components/comment/index.ts
Normal file
2
uni_modules/nutui-uni/components/comment/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export type * from './comment'
|
||||
export type * from './type'
|
||||
60
uni_modules/nutui-uni/components/comment/type.ts
Normal file
60
uni_modules/nutui-uni/components/comment/type.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
export interface VideosType {
|
||||
id: number | string
|
||||
mainUrl: string
|
||||
videoUrl: string
|
||||
}
|
||||
export interface ImagesType {
|
||||
smallImgUrl: string
|
||||
bigImgUrl: string
|
||||
imgUrl: string
|
||||
}
|
||||
|
||||
export interface InfoType {
|
||||
/**
|
||||
* @description 评论详情
|
||||
*/
|
||||
content: string
|
||||
/**
|
||||
* @description 评论人的姓名
|
||||
*/
|
||||
nickName: string
|
||||
/**
|
||||
* @description 评论星星数
|
||||
*/
|
||||
score: string | number
|
||||
/**
|
||||
* @description 评论人头像
|
||||
*/
|
||||
avatar: string
|
||||
/**
|
||||
* @description 评论时间
|
||||
*/
|
||||
time: string
|
||||
/**
|
||||
* @description 评论人购买的商品规格
|
||||
*/
|
||||
size: string
|
||||
/**
|
||||
* @description 此评论的回复数
|
||||
*/
|
||||
replay: number
|
||||
/**
|
||||
* @description 此评论的点赞数
|
||||
*/
|
||||
like: number
|
||||
}
|
||||
|
||||
export interface FollowType {
|
||||
/**
|
||||
* @description 购买多少天后进行追评
|
||||
*/
|
||||
days: number
|
||||
/**
|
||||
* @description 追评内容
|
||||
*/
|
||||
content: string
|
||||
/**
|
||||
* @description 追评图片
|
||||
*/
|
||||
images: []
|
||||
}
|
||||
Reference in New Issue
Block a user