| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- <template>
- <el-card shadow="never" :class="total > 0 && 'reply-card'">
- <template #header>
- <el-button type="primary" link @click="showInput = !showInput">留言
- <template #icon><el-icon size="16"><tjm-icon-mdi-comment-text-outline /></el-icon></template>
- </el-button>
- <div v-show="showInput" class="reply-form">
- <el-input v-model="messageContent" type="textarea" autosize clearable show-word-limit maxlength="140" placeholder="发布你的留言"></el-input>
- <el-button :loading="isSaving" type="primary" :disabled="!messageContent" @click="submit">发布</el-button>
- </div>
- </template>
- <el-form v-loading="loading">
- <template v-for="(item, index) in replyData" :key="item.id">
- <div class="reply-item">
- <el-form-item :label="`${item.createName}:`">{{ item.messageContent }}</el-form-item>
- <el-form-item class="reply-date-item" :label="formatDate(item.createTime)">
- <div class="handle-button-group">
- <el-tooltip content="删除" placement="top">
- <el-button v-if="item.createId == loginUser" icon="delete" circle @click="reply_del(item)"></el-button>
- </el-tooltip>
- <el-tooltip content="留言" placement="top">
- <el-button circle @click="reply_add(item)">
- <template #icon><tjm-icon-mdi-comment-text-outline /></template>
- </el-button>
- </el-tooltip>
- </div>
- </el-form-item>
- </div>
- <div class="reply-item__children">
- <div class="reply-item" v-for="child in replyChildren[index]" :key="child.id">
- <el-form-item>
- <template #label>{{ child.createName }}:
- <template v-if="child.replyId"><span>回复@</span>{{ child.replyName }}:</template>
- </template>
- {{ child.messageContent }}
- </el-form-item>
- <el-form-item class="reply-date-item" :label="formatDate(child.createTime)">
- <div class="handle-button-group">
- <el-tooltip content="删除" placement="top">
- <el-button v-if="child.createId == loginUser" icon="delete" circle @click="reply_del(child)"></el-button>
- </el-tooltip>
- <el-tooltip content="留言" placement="top">
- <el-button circle @click="reply_add(child)">
- <template #icon><tjm-icon-mdi-comment-text-outline /></template>
- </el-button>
- </el-tooltip>
- </div>
- </el-form-item>
- </div>
- <el-button v-if="item.childrenCount > replyChildrenCount" class="text-reverse" type="primary" link @click="reply_children(item)">共{{ item.childrenCount }}条回复
- <template #icon><el-icon size="22"><tjm-icon-mdi-menu-down /></el-icon></template>
- </el-button>
- </div>
- </template>
- </el-form>
- <template v-if="total > replyCount">
- <el-divider></el-divider>
- <el-button class="text-reverse" type="primary" link>查看全部{{ allTotal }}条留言
- <template #icon><arrow-right /></template>
- </el-button>
- </template>
- <template v-else>
- <el-divider v-if="total">已加载全部留言</el-divider>
- </template>
- </el-card>
- <reply-detail v-if="dialog.detail" ref="replyDetail" :refId="refId" :refType="refType" @success="reloadChildrenTree" @closed="dialog.detail = false"></reply-detail>
- <reply-child-detail v-if="dialog.child" ref="replyChildDetail" @closed="reloadTree(), dialog.child = false"></reply-child-detail>
- </template>
- <script>
- import moment from "moment";
- import API from "@/api/policy/message";
- import replyDetail from "./dialog.vue";
- import replyChildDetail from "./detail.vue";
- import { useUserStore } from "@/store/user";
- export default {
- components: {
- replyDetail,
- replyChildDetail
- },
- props: {
- refId: { type: String, default: "" },
- refType: { type: String, default: "policy_share" },
- replyCount: { type: Number, default: 2 },
- replyChildrenCount: { type: Number, default: 2 }
- },
- data() {
- return {
- loading: false,
- loginUser: useUserStore().userInfo.id,
- params: {
- page: 1,
- size: this.replyCount,
- parentId: 0,
- refId: this.refId,
- refType: this.refType
- },
- total: 0,
- replyData: [],
- replyChildren: [],
- showInput: false,
- isSaving: false,
- messageContent: null,
- dialog: {
- detail: false,
- child: false
- }
- }
- },
- computed: {
- allTotal() {
- return this.total + (this.replyChildren.length && this.replyChildren.map(c => c.length).reduce((p, v) => p + v) || 0);
- }
- },
- mounted() {
- this.reloadTree();
- },
- methods: {
- formatDate(value) {
- return value && moment(value).format("YY-MM-DD HH:mm") || "";
- },
- reloadTree() {
- this.loading = true;
- API.get(this.params).then(res => {
- this.loading = false;
- if (res.code === 200) {
- this.replyData = res.data.records;
- this.total = res.data.total;
- this.reloadChildrenTree();
- } else ElMessage.error(res.msg);
- }).catch(() => this.loading = false);
- },
- reloadChildrenTree(parentId) {
- let promiseArray = [];
- if (parentId) {
- const reply_i = this.replyData.findIndex(c => c.id == parentId);
- this.replyData[reply_i].childrenCount++;
- promiseArray = this.replyData.map(_ => []);
- promiseArray[reply_i] = API.get({ ...this.params, size: this.replyChildrenCount, parentId });
- } else this.replyData.forEach(item => promiseArray.push(API.get({ ...this.params, size: this.replyChildrenCount, parentId: item.id })));
- Promise.all(promiseArray).then(res => {
- this.replyChildren = res.map(r => r.code == 200 && r.data.records || []);
- }).catch(() => {
- this.replyChildren = [];
- });
- },
- submit() {
- if (this.refId && this.refType) {
- const data = {
- parentId: 0,
- refId: this.refId,
- refType: this.refType,
- messageContent: this.messageContent
- }
- this.isSaving = true;
- API.add(data).then(res => {
- this.isSaving = false;
- if (res.code === 200) {
- ElMessage.success("留言成功");
- this.messageContent = null;
- this.reloadTree();
- } else ElMessage.error(res.msg);
- }).catch(() => this.isSaving = false);
- }
- },
- reply_add(data) {
- this.dialog.detail = true;
- nextTick(() => this.$refs.replyDetail.open().setData(data));
- },
- reply_del(data) {
- ElMessageBox.confirm("是否确认删除?", "删除警告", {
- type: "warning",
- confirmButtonText: "确定",
- cancelButtonText: "取消"
- }).then(() => {
- API.del({ ids: data.id }).then(res => {
- if (res.code == 200) {
- ElMessage.success("操作成功");
- this.reloadTree();
- } else ElMessage.error(res.msg);
- });
- }).catch(() => ElMessage.success("已取消"));
- },
- reply_children(data) {
- this.dialog.child = true;
- nextTick(() => this.$refs.replyChildDetail.open().setData(data));
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .text-reverse {
- display: flex;
- flex-direction: row-reverse;
- :deep([class*='el-icon'] + span) {
- margin-left: 0;
- margin-right: 6px;
- font-size: 13px;
- }
- }
- .el-card {
- margin-bottom: 25px;
- border-top: none;
- border-radius: 0 0 var(--el-card-border-radius) var(--el-card-border-radius);
- :deep(.el-card__header) {
- display: flex;
- flex-direction: column;
- align-items: center;
- border-bottom: 0;
- padding: calc(var(--el-card-padding) / 2) var(--el-card-padding);
- .reply-form {
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- width: 80%;
- margin-top: calc(var(--el-card-padding) / 2);
- padding-bottom: calc(var(--el-card-padding) / 2);
- .el-button {
- margin-top: calc(var(--el-card-padding) / 2);
- }
- }
- }
- :deep(.el-card__body) {
- padding: 0;
- .el-divider {
- margin: calc(var(--el-card-padding) / 2) 0;
- border-color: var(--el-border-color-light);
- .el-divider__text {
- color: var(--el-text-color-disabled);
- }
- }
- }
- }
- .reply-card :deep(.el-card__body) {
- display: flex;
- flex-direction: column;
- padding: calc(var(--el-card-padding) / 2) var(--el-card-padding);
- padding-top: 0;
- .el-form {
- flex-basis: 100%;
- padding: calc(var(--el-card-padding) / 2) 10% 0;
- border-top: 1px solid var(--el-card-border-color);
- .el-form-item {
- align-items: baseline;
- margin-bottom: 0;
- padding: 0 6px;
- border-radius: 4px 4px 0 0;
- .el-form-item__label {
- height: fit-content;
- line-height: 22px;
- font-size: 13px;
- color: var(--el-color-primary);
- }
- .el-form-item__content {
- height: fit-content;
- line-height: 22px;
- font-size: 13px;
- color: var(--el-text-color-regular);
- }
- }
- .reply-date-item {
- margin-bottom: 6px;
- align-items: center;
- border-radius: 0 0 4px 4px;
- .el-form-item__label {
- color: var(--el-text-color-placeholder);
- }
- .el-form-item__content {
- justify-content: flex-end;
- .handle-button-group {
- display: none;
- .el-button {
- width: 20px;
- height: 20px;
- padding: 0;
- background-color: transparent;
- border: none;
- &:hover {
- background-color: var(--el-color-primary-light-8);
- }
- }
- }
- }
- }
- .reply-item:hover .el-form-item {
- background: var(--el-color-primary-light-9);
- .el-form-item__content .handle-button-group {
- display: inline-flex;
- }
- }
- .reply-item__children {
- margin-bottom: 6px;
- margin-left: 6px;
- padding-left: 1px;
- border-left: 1px solid var(--el-card-border-color);
- .el-form-item__label span {
- color: var(--el-text-color-regular);
- }
- .reply-item:last-child .reply-date-item {
- margin-bottom: 0;
- }
- .text-reverse {
- margin-left: 3px;
- }
- }
- }
- }
- </style>
|