Commit dc7417ed authored by yuwenwen's avatar yuwenwen

修改BUG,PC端添加表情展示

parent e7445cb8
@font-face {
font-family: "iconfont"; /* Project id 5028537 */
src: url('iconfont.woff2?t=1758609551078') format('woff2'),
url('iconfont.woff?t=1758609551078') format('woff'),
url('iconfont.ttf?t=1758609551078') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 40rpx;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-chijing:before {
content: "\e600";
}
.icon-dai:before {
content: "\e601";
}
.icon-mogui:before {
content: "\e602";
}
.icon-ganga:before {
content: "\e603";
}
.icon-qin:before {
content: "\e604";
}
.icon-nu:before {
content: "\e605";
}
.icon-shengqi:before {
content: "\e606";
}
.icon-ma:before {
content: "\e607";
}
.icon-bishi:before {
content: "\e608";
}
.icon-maimeng:before {
content: "\e609";
}
.icon-jingdai:before {
content: "\e60a";
}
.icon-kulian:before {
content: "\e60b";
}
...@@ -7,6 +7,7 @@ import './assets/styles/element-variables.scss' ...@@ -7,6 +7,7 @@ import './assets/styles/element-variables.scss'
import '@/assets/styles/index.scss' // global css import '@/assets/styles/index.scss' // global css
import '@/assets/styles/ruoyi.scss' // ruoyi css import '@/assets/styles/ruoyi.scss' // ruoyi css
import '../public/iconfont/iconfont.css'
import App from './App' import App from './App'
import store from './store' import store from './store'
import router from './router' import router from './router'
......
const emotions = [{
code: 'icon-chijing',
name: '吃惊',
symbol: '[吃惊]'
},
{
code: 'icon-dai',
name: '',
symbol: '[呆]'
},
{
code: 'icon-mogui',
name: '魔鬼',
symbol: '[魔鬼]'
},
{
code: 'icon-ganga',
name: '尴尬',
symbol: '[尴尬]'
},
{
code: 'icon-qin',
name: '',
symbol: '[亲]'
},
{
code: 'icon-nu',
name: '',
symbol: '[怒]'
},
{
code: 'icon-shengqi',
name: '生气',
symbol: '[生气]'
},
{
code: 'icon-ma',
name: '',
symbol: '[骂]'
},
{
code: 'icon-bishi',
name: '鄙视',
symbol: '[鄙视]'
},
{
code: 'icon-maimeng',
name: '卖萌',
symbol: '[卖萌]'
},
{
code: 'icon-jingdai',
name: '惊呆',
symbol: '[惊呆]'
},
{
code: 'icon-kulian',
name: '哭脸',
symbol: '[哭脸]'
},
]
export default emotions;
\ No newline at end of file
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
</template> </template>
</div> </div>
<div class="dynamic-content-box"> <div class="dynamic-content-box">
<div class="text">{{ form.content }}</div> <div class="text" v-html="formatContent(form.content)"></div>
<div class="imgs" v-if="form.type == 'IMAGE' && form.attachments && form.attachments.length > 0"> <div class="imgs" v-if="form.type == 'IMAGE' && form.attachments && form.attachments.length > 0">
<template v-for="(item, index) in form.attachments"> <template v-for="(item, index) in form.attachments">
<el-image class="item" :src="item.url" :preview-src-list="[item.url]"></el-image> <el-image class="item" :src="item.url" :preview-src-list="[item.url]"></el-image>
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<img src="@/assets/images/favorite-active.png" v-if="form.isLike == 1" class="icon"></img> <img src="@/assets/images/favorite-active.png" v-if="form.isLike == 1" class="icon"></img>
<div class="num">{{ form.likeCount }}</div> <div class="num">{{ form.likeCount }}</div>
</div> </div>
<div class="comment-box"> <div class="comment-box" style="border-top: 0;">
<img class="icon" src="@/assets/images/comment-icon.png"></img> <img class="icon" src="@/assets/images/comment-icon.png"></img>
<div class="text">评论</div> <div class="text">评论</div>
</div> </div>
...@@ -63,18 +63,18 @@ ...@@ -63,18 +63,18 @@
<div class="datetime">{{ item.createTime }}</div> <div class="datetime">{{ item.createTime }}</div>
</div> </div>
<div class="content"> <div class="content">
<div class="text" v-if="!item.replyNickName" > <div class="text" v-if="!item.replyNickName">
{{item.content}} {{ item.content }}
</div> </div>
<div class="text" v-else> <div class="text" v-else>
回复<span style="color: #0058B6;">{{item.replyNickName}}:</span>{{item.content}} 回复<span style="color: #0058B6;">{{ item.replyNickName }}:</span>{{ item.content }}
</div> </div>
<div class="operation-text"> <div class="operation-text">
<div v-if="item.isFeatured==1" style="color: #F2AC39;margin-right: 10rpx;">精选</div> <div v-if="item.isFeatured == 1" style="color: #F2AC39;margin-right: 10rpx;">精选</div>
<div v-if="item.isSelf==1" @click.stop="handleDelete(item)">删除</div> <div @click.stop="handleDelete(item)">删除</div>
</div> </div>
</div> </div>
</div> </div>
<div class="show-more-box" v-if="commentList.length < total" @click="loadMore"> <div class="show-more-box" v-if="commentList.length < total" @click="loadMore">
加载更多 加载更多
...@@ -86,6 +86,8 @@ ...@@ -86,6 +86,8 @@
</template> </template>
<script> <script>
import { detailData, getMomentComments } from '@/api/moments' import { detailData, getMomentComments } from '@/api/moments'
import { delData } from '@/api/comment';
import emotions from '@/utils/emjo';
export default { export default {
data() { data() {
return { return {
...@@ -97,14 +99,21 @@ export default { ...@@ -97,14 +99,21 @@ export default {
}, },
commentList: [], commentList: [],
total: 0, total: 0,
currentRow:{} currentRow: {},
emotions,
// 预创建表情符号到iconfont的映射表,提高性能
emotionMap: {}
} }
}, },
methods: { methods: {
openModal(row) { openModal(row) {
this.visible = true; this.visible = true;
this.currentRow = {...row} this.currentRow = { ...row }
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1;
// 初始化表情映射表
this.emotions.forEach(emotion => {
this.emotionMap[emotion.symbol] = emotion.code;
});
this.commentList = []; this.commentList = [];
this.getData(); this.getData();
this.getComments() this.getComments()
...@@ -128,9 +137,83 @@ export default { ...@@ -128,9 +137,83 @@ export default {
this.queryParams.pageNum += 1; this.queryParams.pageNum += 1;
this.getComments() this.getComments()
}, },
// 删除评论 // 删除
handleDelete(){ handleDelete(row) {
this.$modal.confirm('确认要删除评论内容为:' + row.content + '的数据吗?').then(function () {
return delData(row.id);
}).then(() => {
this.$modal.msgSuccess("删除成功");
this.commentList = [];
this.getComments()
this.$emit('refresh')
})
},
/**
* 将内容中的表情符号转换为iconfont标签
* @param {string} content - 原始内容
* @returns {string} 转换后的HTML字符串
*/
formatContent(content) {
if (!content) return '';
let result = '';
let remainingContent = content;
// 提取所有表情符号并按长度排序(长表情优先匹配)
const emotionSymbols = Object.keys(this.emotionMap).sort((a, b) => b.length - a.length);
while (remainingContent.length > 0) {
let found = false;
// 查找是否有表情符号
for (const symbol of emotionSymbols) {
if (remainingContent.startsWith(symbol)) {
// 添加表情标签
result += `<i class="iconfont ${this.emotionMap[symbol]} emotion-icon"></i>`;
remainingContent = remainingContent.slice(symbol.length);
found = true;
break;
}
}
// 如果没有找到表情,提取普通文本
if (!found) {
// 找到下一个表情的位置
let nextEmotionIndex = remainingContent.length;
for (const symbol of emotionSymbols) {
const index = remainingContent.indexOf(symbol);
if (index !== -1 && index < nextEmotionIndex) {
nextEmotionIndex = index;
}
}
// 提取文本并进行HTML转义,防止XSS
const text = this.escapeHtml(remainingContent.slice(0, nextEmotionIndex));
result += text;
remainingContent = remainingContent.slice(nextEmotionIndex);
}
}
return result;
},
/**
* HTML转义处理,防止XSS攻击
* @param {string} str - 需要转义的字符串
* @returns {string} 转义后的字符串
*/
escapeHtml(str) {
if (!str) return '';
return str.replace(/[&<>"']/g, char => {
const entities = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;'
};
return entities[char] || char;
});
} }
} }
...@@ -369,29 +452,33 @@ export default { ...@@ -369,29 +452,33 @@ export default {
} }
} }
.content{ .content {
color: black; color: black;
margin: 5px 0; margin: 5px 0;
display: flex; display: flex;
.text {
width: calc(100% - 90px); .text {
} width: calc(100% - 90px);
}
.operation-text {
width:90px; .operation-text {
text-align: right; width: 90px;
font-size: 12px; text-align: right;
display: flex; font-size: 12px;
align-items: center; display: flex;
justify-content: flex-end; align-items: center;
} justify-content: flex-end;
.mr10{ cursor: pointer;
margin-right: 6px; }
}
.add-text { .mr10 {
color: #0058B6; margin-right: 6px;
} }
}
.add-text {
color: #0058B6;
}
}
.tips { .tips {
font-size: 12px; font-size: 12px;
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
</el-form-item> </el-form-item>
<el-form-item label="创建时间"> <el-form-item label="创建时间">
<el-date-picker placeholder="请选择" type="daterange" format="yyyy-MM-dd" value-format="yyyy-MM-dd" <el-date-picker placeholder="请选择" type="daterange" format="yyyy-MM-dd" value-format="yyyy-MM-dd"
v-model="dateRange" range-separator="至" start-placeholder="开始时间" v-model="dateRange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间"
end-placeholder="结束时间" @change="dateChange"></el-date-picker> @change="dateChange"></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button> <el-button type="primary" @click="handleQuery">查询</el-button>
...@@ -21,7 +21,11 @@ ...@@ -21,7 +21,11 @@
</el-row> </el-row>
<el-table :data="tableList"> <el-table :data="tableList">
<el-table-column label="序号" width="55" type="index" align="center"></el-table-column> <el-table-column label="序号" width="55" type="index" align="center"></el-table-column>
<el-table-column label="动态内容" prop="content" align="center"></el-table-column> <el-table-column label="动态内容" prop="content" align="center">
<template #default="{ row }">
<div v-html="formatContent(row.content)" class="content-container"></div>
</template>
</el-table-column>
<el-table-column label="话题" align="center" prop="topicNames" width="240"></el-table-column> <el-table-column label="话题" align="center" prop="topicNames" width="240"></el-table-column>
<el-table-column label="帐号" prop="userName" align="center" width="140"></el-table-column> <el-table-column label="帐号" prop="userName" align="center" width="140"></el-table-column>
<el-table-column label="姓名" prop="nickName" align="center" width="120"></el-table-column> <el-table-column label="姓名" prop="nickName" align="center" width="120"></el-table-column>
...@@ -39,13 +43,14 @@ ...@@ -39,13 +43,14 @@
:limit.sync="queryParams.pageSize" @pagination="getList" /> :limit.sync="queryParams.pageSize" @pagination="getList" />
</div> </div>
<!-- 动态详情 --> <!-- 动态详情 -->
<detail-dialog ref="detailDialogRef"></detail-dialog> <detail-dialog ref="detailDialogRef" @refresh="getList"></detail-dialog>
</div> </div>
</template> </template>
<script> <script>
import { listData, delData } from '@/api/moments'; import { listData, delData } from '@/api/moments';
import DetailDialog from './DetailDialog.vue'; import DetailDialog from './DetailDialog.vue';
import emotions from '@/utils/emjo';
export default { export default {
name: 'Moments', name: 'Moments',
data() { data() {
...@@ -57,13 +62,19 @@ export default { ...@@ -57,13 +62,19 @@ export default {
tableList: [], tableList: [],
total: 0, total: 0,
dateRange: [], dateRange: [],
emotions,
// 预创建表情符号到iconfont的映射表,提高性能
emotionMap: {}
} }
}, },
components: { components: {
DetailDialog DetailDialog
}, },
created() { created() {
// 初始化表情映射表
this.emotions.forEach(emotion => {
this.emotionMap[emotion.symbol] = emotion.code;
});
}, },
mounted() { mounted() {
this.getList() this.getList()
...@@ -77,7 +88,6 @@ export default { ...@@ -77,7 +88,6 @@ export default {
this.total = res.total this.total = res.total
}) })
}, },
// 新增 // 新增
handleDetail(row) { handleDetail(row) {
this.$refs.detailDialogRef.openModal(row) this.$refs.detailDialogRef.openModal(row)
...@@ -91,8 +101,8 @@ export default { ...@@ -91,8 +101,8 @@ export default {
this.getList() this.getList()
}) })
}, },
dateChange(val){ dateChange(val) {
if(val.length > 0){ if (val.length > 0) {
this.queryParams['params[startTime]'] = val[0] this.queryParams['params[startTime]'] = val[0]
this.queryParams['params[endTime]'] = val[1] this.queryParams['params[endTime]'] = val[1]
} }
...@@ -110,6 +120,73 @@ export default { ...@@ -110,6 +120,73 @@ export default {
} }
this.dateRange = [] this.dateRange = []
this.getList() this.getList()
},
/**
* 将内容中的表情符号转换为iconfont标签
* @param {string} content - 原始内容
* @returns {string} 转换后的HTML字符串
*/
formatContent(content) {
if (!content) return '';
let result = '';
let remainingContent = content;
// 提取所有表情符号并按长度排序(长表情优先匹配)
const emotionSymbols = Object.keys(this.emotionMap).sort((a, b) => b.length - a.length);
while (remainingContent.length > 0) {
let found = false;
// 查找是否有表情符号
for (const symbol of emotionSymbols) {
if (remainingContent.startsWith(symbol)) {
// 添加表情标签
result += `<i class="iconfont ${this.emotionMap[symbol]} emotion-icon"></i>`;
remainingContent = remainingContent.slice(symbol.length);
found = true;
break;
}
}
// 如果没有找到表情,提取普通文本
if (!found) {
// 找到下一个表情的位置
let nextEmotionIndex = remainingContent.length;
for (const symbol of emotionSymbols) {
const index = remainingContent.indexOf(symbol);
if (index !== -1 && index < nextEmotionIndex) {
nextEmotionIndex = index;
}
}
// 提取文本并进行HTML转义,防止XSS
const text = this.escapeHtml(remainingContent.slice(0, nextEmotionIndex));
result += text;
remainingContent = remainingContent.slice(nextEmotionIndex);
}
}
return result;
},
/**
* HTML转义处理,防止XSS攻击
* @param {string} str - 需要转义的字符串
* @returns {string} 转义后的字符串
*/
escapeHtml(str) {
if (!str) return '';
return str.replace(/[&<>"']/g, char => {
const entities = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;'
};
return entities[char] || char;
});
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment