Skip to content

Commit

Permalink
feat: 新增 Comment 组件
Browse files Browse the repository at this point in the history
  • Loading branch information
yangxiaolu1993 committed Apr 18, 2022
1 parent 9fa5f29 commit af7fc35
Show file tree
Hide file tree
Showing 15 changed files with 1,348 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,17 @@
"tarodoc": false,
"type": "component",
"author": "yangxiaolu"
},
{
"version": "3.0.0",
"name": "Comment",
"cType": "特色组件",
"cName": "商品评论",
"desc": "商品评论",
"show": true,
"tarodoc": false,
"type": "component",
"author": "yangxiaolu"
}
]
}
Expand Down
1 change: 1 addition & 0 deletions src/packages/__VUE/comment/__tests__/comment.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import { mount } from '@vue/test-utils';
1 change: 1 addition & 0 deletions src/packages/__VUE/comment/comment_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"Comment":{"videos":[{"mainUrl":"https://img.300hu.com/4c1f7a6atransbjngwcloud1oss/3a5abb98377496264567160833/imageSampleSnapshot/1604738160_777980391.100_1344.jpg","videoUrl":"https://vod.300hu.com/4c1f7a6atransbjngwcloud1oss/3a5abb98377496264567160833/v.f30.mp4?source=1&h265=v.f1022_h265.mp4"}],"images":[{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/153847/3/5051/62777/5fa65e01Ec88cecb9/36ba206949050b39.jpg"},{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/131794/19/15190/57841/5fa65e03E75c12ef1/0d1ac3a87ff9e398.jpg"},{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/155091/12/4926/68141/5fa65e03E9d8c5120/9c71b6e49f1eb3c3.jpg"},{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/138774/29/13635/70364/5fa65e04E1669ad70/c97839098a18d92e.jpg"},{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/120265/1/17811/70109/5fa65e05Eb23a84e3/e156fc1d316922c4.jpg"},{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/120265/1/17811/70109/5fa65e05Eb23a84e3/e156fc1d316922c4.jpg"},{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/155091/12/4926/68141/5fa65e03E9d8c5120/9c71b6e49f1eb3c3.jpg"},{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/138774/29/13635/70364/5fa65e04E1669ad70/c97839098a18d92e.jpg"},{"smallImgUrl":"","bigImgUrl":"","imgUrl":"https://img30.360buyimg.com/imagetools/jfs/t1/138774/29/13635/70364/5fa65e04E1669ad70/c97839098a18d92e.jpg"}],"info":{"content":"产品包装:塑料瓶,但是能接受,也很喜欢。","nickName":"星***_","score":5,"avatar":"//nutui.jd.com/3x/demo-3.1.18/logo-red.png","time":"2021-09-09","size":"雪域白【碎屏险套装】全网通;8G+256【12期免息】","replay":23,"like":1},"follow":{"days":128,"content":"12月份开始用,用到现在,我的脸干的不行,一天都紧紧巴巴,打算换套别的用,不知道是不是不合适,还是假的呢!","images":["//img30.360buyimg.com/imagetools/jfs/t1/120265/1/17811/70109/5fa65e05Eb23a84e3/e156fc1d316922c4.jpg"]}}}
82 changes: 82 additions & 0 deletions src/packages/__VUE/comment/components/CmtBottom.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<view class="nut-comment-bottom">
<view @click="handleClick" class="nut-comment-bottom__lable">
<span v-if="type != 'complex'">{{ 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', `nut-comment-bottom__cpx-item--${name}`]" @click="operate(name)">
<template v-if="name != 'more'">
<span>{{ info[name] }}</span>
<nut-icon :name="name == 'like' ? 'fabulous' : 'comment'"></nut-icon>
</template>
<template v-if="name == 'more'">
<nut-icon name="more-x"></nut-icon>
<view class="nut-comment-bottom__cpx-item-popover" v-if="showPopver" @click="operate('popover')">
我要投诉
</view>
</template>
</view>
</template>
</view>
</view>
</template>
<script lang="ts">
import { ref, watch, onMounted } from 'vue';
import { createComponent } from '../../../utils/create';
const { componentName, create } = createComponent('comment-bottom');
export default create({
props: {
type: {
type: String,
default: 'base' // simple,base,complex
},
info: {
type: Object,
default: () => {}
},
operation: {
type: Array,
default: ['replay', 'like', 'more']
}
},
components: {},
emits: ['clickOperate', 'handleClick'],
setup(props, { emit }) {
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);
}
});
}
});
const operate = (type: string) => {
if (type == 'more') {
showPopver.value = !showPopver.value;
}
emit('clickOperate', type);
};
const handleClick = () => {
emit('handleClick');
};
return { showPopver, operate, mergeOp, handleClick };
}
});
</script>
66 changes: 66 additions & 0 deletions src/packages/__VUE/comment/components/CmtHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<template>
<view>
<view class="nut-comment-header" @click="handleClick" v-if="info">
<view class="nut-comment-header__user">
<view class="nut-comment-header__user-avter">
<img v-if="info.avatar" :src="info.avatar" />
</view>

<view :class="[`nut-comment-header__user-${type}`]" v-if="type == 'default'">
<view :class="[`nut-comment-header__user-${type}-name`]">
<span>{{ info.nickName }}</span>
<slot name="labels"></slot>
</view>

<view class="nut-comment-header__user-score">
<nut-rate v-model="info.score" icon-size="10" spacing="5" readOnly @change="handleClick" />
</view>
</view>

<view :class="[`nut-comment-header__user-${type}`]" v-else>
<span :class="[`nut-comment-header__user-${type}-name`]">{{ info.nickName }}</span>
<slot name="labels"></slot>
</view>
</view>
<view class="nut-comment-header__time" v-if="info.time">{{ info.time }}</view>
</view>
<view :class="[`nut-comment-header__${type}-score`]" v-if="type == 'complex'">
<nut-rate v-model="info.score" icon-size="12" spacing="3" />
<i :class="[`nut-comment-header__${type}-score-i`]"></i>
<view :class="[`nut-comment-header__${type}-score-size`]">{{ info.size }}</view>
</view>
</view>
</template>
<script lang="ts">
import { ref, watch, onMounted } from 'vue';
import { createComponent } from '../../../utils/create';
const { componentName, create } = createComponent('comment-header');
export default create({
props: {
type: {
type: String,
default: 'default' // default,complex
},
info: {
type: Object,
default: () => {}
},
labels: {
type: Function,
default: () => ''
}
},
components: {},
emits: ['handleClick'],
setup(props, { emit }) {
const handleClick = () => {
emit('handleClick');
};
return { handleClick };
}
});
</script>
98 changes: 98 additions & 0 deletions src/packages/__VUE/comment/components/CmtImages.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<template>
<view :class="`nut-comment-images nut-comment-images--${type}`">
<!-- videos -->
<view
class="nut-comment-images__item nut-comment-images__item--video"
v-for="(itV, index) in videos"
:key="itV.id"
@click="showImages('video', index, index)"
>
<img :src="itV.mainUrl" />
<view class="nut-comment-images__play"></view>
</view>
<!-- images -->
<template v-for="(itI, index) in images" :key="itI.id">
<view
class="nut-comment-images__item nut-comment-images__item--imgbox"
v-if="(type == 'multi' && videos.length + index < 9) || type != 'multi'"
@click="showImages('img', index + videos.length)"
>
<img :src="itI.smallImgUrl ? itI.smallImgUrl : itI.imgUrl" />

<view
class="nut-comment-images__mask"
v-if="type == 'multi' && totalImages.length > 9 && videos.length + index > 7"
>
<span>共 {{ totalImages.length }} 张</span>
<nut-icon name="right" size="12"></nut-icon>
</view>
</view>
</template>
</view>
</template>
<script lang="ts">
import { ref, watch, onMounted } from 'vue';
import { createComponent } from '../../../utils/create';
const { componentName, create } = createComponent('comment-images');
export default create({
props: {
type: {
type: String,
default: 'one' // one multi
},
videos: {
type: Array,
default: () => []
},
images: {
type: Array,
default: () => []
}
},
components: {},
emits: ['click', 'clickImages'],
setup(props, { emit }) {
const isShowImage = ref(false);
const initIndex = ref(1);
const totalImages = ref([]);
watch(
() => [props.videos, props.images],
(value) => {
if (value[0].length > 0) {
value[0].forEach((el: any) => {
el.type = 'video';
});
}
totalImages.value = value[0].concat(value[1]);
},
{ deep: true }
);
onMounted(() => {
if (props.videos.length > 0) {
props.videos.forEach((el: any) => {
el.type = 'video';
});
}
totalImages.value = props.videos.concat(props.images);
});
const 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] : videos[i]
});
};
return { isShowImage, initIndex, showImages, totalImages };
}
});
</script>
109 changes: 109 additions & 0 deletions src/packages/__VUE/comment/demo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<template>
<div class="demo">
<h2>评论图片单行展示</h2>
<nut-cell>
<nut-comment
:images="cmt.images"
:videos="cmt.videos"
:info="cmt.info"
:labels="labels"
@click="handleclick"
@clickImages="clickImages"
:operation="['replay']"
>
<template #comment-labels>
<img
class="nut-comment-header__labels--item"
src="https://img11.360buyimg.com/imagetools/jfs/t1/211858/17/4258/12101/618e6f78Ed0edcadc/e83a673555edf59f.jpg"
/>
</template>
</nut-comment>
</nut-cell>

<h2>评论图片多行展示</h2>
<nut-cell>
<nut-comment
headerType="complex"
imagesRows="multi"
:images="cmt.images"
:videos="cmt.videos"
:info="cmt.info"
ellipsis="6"
@clickImages="clickImages"
>
<template #comment-labels>
<img
class="nut-comment-header__labels--item"
src="https://storage.360buyimg.com/imgtools/78925d9440-f9e874d0-e93d-11eb-8e5c-0da9e18a13b1.png"
style="height: 12px"
/>
</template>

<template #comment-shop-reply>
<div class="nut-comment-shop">
<span>京东美妆国际:</span
>尊敬的客户您好,非常抱歉给您带来不愉快的购物体验,关于过敏,什么成分都不存在个别性和普遍性。
</div>
</template>
</nut-comment>
</nut-cell>

<h2>追评展示</h2>
<nut-cell>
<nut-comment
imagesRows="multi"
:images="cmt.images"
:videos="cmt.videos"
:info="cmt.info"
:follow="cmt.follow"
@clickImages="clickImages"
></nut-comment>
</nut-cell>
</div>
</template>
<script lang="ts">
import { onMounted, ref } from '@vue/runtime-core';
import { createComponent } from '../../utils/create';
const { createDemo } = createComponent('comment');
export default createDemo({
props: {},
setup() {
let cmt = ref({});
const labels = () => {
return '<nut-icon name="dongdong" color="#fa2c19"></nut-icon>';
};
const handleclick = (info: any) => {
console.log('进行跳转', info);
};
onMounted(() => {
getData();
});
const getData = () => {
fetch('//storage.360buyimg.com/nutui/3x/comment_data.json')
.then((response) => response.json())
.then((res) => {
cmt.value = res.Comment;
}) //执行结果是 resolve就调用then方法
.catch((err) => console.log('Oh, error', err)); //执行结果是 reject就调用catch方法
};
const clickImages = (imgs: any) => {
console.log('进行图片展示', imgs);
};
return {
cmt,
labels,
handleclick,
clickImages
};
}
});
</script>
<style lang="scss" scoped>
.demo {
}
</style>
Loading

0 comments on commit af7fc35

Please sign in to comment.