Compare commits
2 Commits
fb94445e63
...
702d0d6aec
Author | SHA1 | Date | |
---|---|---|---|
|
702d0d6aec | ||
|
ccdb092b29 |
@ -64,71 +64,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 文章封面 -->
|
||||
<!-- <div class="cover-upload fade-in-delay-2">
|
||||
<div class="cover-title">
|
||||
<a-icon type="picture" />
|
||||
<span style="margin-left: 8px">文章封面</span>
|
||||
</div>
|
||||
|
||||
<p class="cover-description">
|
||||
一个好的封面图能够吸引更多读者,建议尺寸 900×500 像素
|
||||
</p>
|
||||
|
||||
<div class="cover-preview hover-lift">
|
||||
<img v-if="coverUrl" :src="coverUrl" alt="文章封面" />
|
||||
<div v-else class="upload-placeholder">
|
||||
<a-icon type="file-image" style="font-size: 48px; color: #d9d9d9" />
|
||||
<p style="margin-top: 16px; color: #999">点击上传封面图片</p>
|
||||
</div>
|
||||
|
||||
<a-upload
|
||||
name="file"
|
||||
:showUploadList="false"
|
||||
:beforeUpload="beforeUpload"
|
||||
@change="handleCoverChange"
|
||||
>
|
||||
<a-button type="primary" class="cover-upload-btn">
|
||||
<a-icon :type="coverUrl ? 'edit' : 'upload'" />
|
||||
{{ coverUrl ? "更换封面" : "上传封面" }}
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- 编辑器容器 -->
|
||||
<div class="editor-container fade-in-delay-2">
|
||||
<Editor
|
||||
:id="tinymceId"
|
||||
:init="init"
|
||||
:disabled="disabled"
|
||||
v-model="myValue"
|
||||
@onClick="onClick"
|
||||
></Editor>
|
||||
<div class="word-count">字数: {{ wordCount }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容预览区域 -->
|
||||
<div v-if="showPreview" class="preview-container fade-in">
|
||||
<div class="preview-title">
|
||||
<a-icon type="eye" />
|
||||
<span>文章预览</span>
|
||||
<div class="tinymce-editor">
|
||||
<div class="editor-container">
|
||||
<Editor
|
||||
:id="tinymceId"
|
||||
:init="init"
|
||||
:disabled="disabled"
|
||||
v-model="myValue"
|
||||
@onClick="onClick"
|
||||
></Editor>
|
||||
</div>
|
||||
|
||||
<div class="preview-content" v-html="myValue"></div>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="publish-container">
|
||||
<a-button @click="togglePreview" style="margin-right: 16px">
|
||||
<a-icon :type="showPreview ? 'eye-invisible' : 'eye'" />
|
||||
{{ showPreview ? "关闭预览" : "预览文章" }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="primary" class="publish-btn" @click="confirmPublish">
|
||||
<a-icon type="plus" />
|
||||
发布文章
|
||||
</a-button>
|
||||
<div class="editor-footer">
|
||||
<div class="word-count">字数:{{ wordCount }}</div>
|
||||
<div class="button-group">
|
||||
<a-button type="primary" class="publish-btn" @click="SendTinymce">
|
||||
<a-icon type="plus" />
|
||||
发布文章
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -498,7 +454,7 @@ export default {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.tinymce-editor .ant-select-selection-search {
|
||||
.tinymce-editor .ant-select-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ export const routes = [
|
||||
path: '/account/CompetitionAssistant',
|
||||
name: 'CompetitionAssistant',
|
||||
meta: { title: '竞赛助手', auth: 0 },
|
||||
component: () => import('@/views/CompetitionAssistant.vue'),
|
||||
component: () => import('@/views/user/Ai.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -6,14 +6,7 @@
|
||||
<div class="stat-number">{{ articleCount }}</div>
|
||||
<div class="stat-title">发布文章</div>
|
||||
</div>
|
||||
<div class="stat-card glow-border">
|
||||
<div class="stat-number">{{ viewCount }}</div>
|
||||
<div class="stat-title">文章浏览</div>
|
||||
</div>
|
||||
<div class="stat-card glow-border">
|
||||
<div class="stat-number">{{ likeCount }}</div>
|
||||
<div class="stat-title">获得点赞</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card glow-border">
|
||||
<div class="stat-number">{{ matchs.length }}</div>
|
||||
<div class="stat-title">参与比赛</div>
|
||||
@ -129,16 +122,6 @@
|
||||
<div v-if="noTitleKey === 'article'">
|
||||
<!-- 文章筛选和排序 -->
|
||||
<div class="article-filter">
|
||||
<a-radio-group
|
||||
v-model="articleFilter"
|
||||
buttonStyle="solid"
|
||||
@change="filterArticles"
|
||||
>
|
||||
<a-radio-button value="all">全部文章</a-radio-button>
|
||||
<a-radio-button value="hot">热门文章</a-radio-button>
|
||||
<a-radio-button value="recent">最近发布</a-radio-button>
|
||||
</a-radio-group>
|
||||
|
||||
<a-button type="primary" icon="plus" @click="createNewArticle">
|
||||
发布文章
|
||||
</a-button>
|
||||
@ -152,7 +135,7 @@
|
||||
class="article-item"
|
||||
v-for="(article, index) in articles"
|
||||
:key="index"
|
||||
@click="viewArticle(article.id)"
|
||||
@click="viewArticle(article)"
|
||||
>
|
||||
<div class="article-cover">
|
||||
<img :src="getArticleImage(article)" :alt="article.title" />
|
||||
@ -168,7 +151,7 @@
|
||||
<a-icon type="calendar" />
|
||||
{{ formatDate(article.publishTime) }}
|
||||
</div>
|
||||
<div class="article-stats">
|
||||
<!-- <div class="article-stats">
|
||||
<span
|
||||
><a-icon type="eye" />
|
||||
{{ article.viewCount || 0 }}</span
|
||||
@ -181,7 +164,7 @@
|
||||
><a-icon type="message" />
|
||||
{{ article.commentCount || 0 }}</span
|
||||
>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -244,14 +227,6 @@ export default {
|
||||
key: "article",
|
||||
tab: "我的文章",
|
||||
},
|
||||
{
|
||||
key: "app",
|
||||
tab: "我的收藏",
|
||||
},
|
||||
{
|
||||
key: "project",
|
||||
tab: "我的评论",
|
||||
},
|
||||
],
|
||||
noTitleKey: "article",
|
||||
matchs: [],
|
||||
@ -294,18 +269,33 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
// 获取比赛信息
|
||||
// 修改 fetchCompetitions 方法
|
||||
fetchCompetitions() {
|
||||
this.teamSpinning = true;
|
||||
this.$api
|
||||
.RegistrationAll()
|
||||
.then((res) => {
|
||||
// 筛选当前用户的比赛记录
|
||||
this.matchs = res.data.filter((match) => {
|
||||
return match.studentId == this.$store.state.user.userId;
|
||||
return match.studentId === this.$store.state.user.userId;
|
||||
});
|
||||
|
||||
// 更新比赛卡片显示
|
||||
this.matchs = this.matchs.map((match) => ({
|
||||
...match,
|
||||
// 确保所需字段都存在
|
||||
competitionName: match.competitionName || "未命名比赛",
|
||||
competitionType: match.competitionType || "未分类",
|
||||
registrationTime:
|
||||
match.registrationTime || new Date().toISOString(),
|
||||
awardLevel: match.awardLevel || "暂无成绩",
|
||||
}));
|
||||
|
||||
this.teamSpinning = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("获取比赛信息失败:", err);
|
||||
this.$message.error("获取比赛信息失败");
|
||||
this.teamSpinning = false;
|
||||
});
|
||||
},
|
||||
@ -447,12 +437,13 @@ export default {
|
||||
|
||||
// 查看文章详情
|
||||
viewArticle(id) {
|
||||
this.$router.push(`/community/pages?id=${id}`);
|
||||
console.log("id", id);
|
||||
this.$router.push(`/community/pages?id=${id?.articleId}`);
|
||||
},
|
||||
|
||||
// 创建新文章
|
||||
createNewArticle() {
|
||||
this.$router.push("/write");
|
||||
this.$router.push("/community/publish");
|
||||
},
|
||||
|
||||
// 标签相关方法
|
||||
|
@ -1,175 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-card :bordered="false" class="ant-pro-components-tag-select">
|
||||
<a-form :form="form" layout="inline">
|
||||
<standard-form-row title="所属类目" block style="padding-bottom: 11px;">
|
||||
<a-form-item>
|
||||
<tag-select>
|
||||
<tag-select-option value="Category1">类目一</tag-select-option>
|
||||
<tag-select-option value="Category2">类目二</tag-select-option>
|
||||
<tag-select-option value="Category3">类目三</tag-select-option>
|
||||
<tag-select-option value="Category4">类目四</tag-select-option>
|
||||
<tag-select-option value="Category5">类目五</tag-select-option>
|
||||
<tag-select-option value="Category6">类目六</tag-select-option>
|
||||
<tag-select-option value="Category7">类目七</tag-select-option>
|
||||
<tag-select-option value="Category8">类目八</tag-select-option>
|
||||
<tag-select-option value="Category9">类目九</tag-select-option>
|
||||
<tag-select-option value="Category10">类目十</tag-select-option>
|
||||
</tag-select>
|
||||
</a-form-item>
|
||||
</standard-form-row>
|
||||
|
||||
<standard-form-row title="其它选项" grid last>
|
||||
<a-row>
|
||||
<a-col :lg="8" :md="10" :sm="10" :xs="24">
|
||||
<a-form-item :wrapper-col="{ sm: { span: 16 }, xs: { span: 24 } }" label="作者">
|
||||
<a-select
|
||||
style="max-width: 200px; width: 100%;"
|
||||
mode="multiple"
|
||||
placeholder="不限"
|
||||
v-decorator="['author']"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-select-option value="lisa">王昭君</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="10" :sm="10" :xs="24">
|
||||
<a-form-item :wrapper-col="{ sm: { span: 16 }, xs: { span: 24 } }" label="好评度">
|
||||
<a-select
|
||||
style="max-width: 200px; width: 100%;"
|
||||
placeholder="不限"
|
||||
v-decorator="['rate']"
|
||||
>
|
||||
<a-select-option value="good">优秀</a-select-option>
|
||||
<a-select-option value="normal">普通</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</standard-form-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<div class="ant-pro-pages-list-projects-cardList">
|
||||
<a-list :loading="loading" :data-source="data" :grid="{ gutter: 24, xl: 4, lg: 3, md: 3, sm: 2, xs: 1 }">
|
||||
<a-list-item slot="renderItem" slot-scope="item">
|
||||
<a-card class="ant-pro-pages-list-projects-card" hoverable>
|
||||
<img slot="cover" :src="item.cover" :alt="item.title" />
|
||||
<a-card-meta :title="item.title">
|
||||
<template slot="description">
|
||||
<ellipsis :length="50">{{ item.description }}</ellipsis>
|
||||
</template>
|
||||
</a-card-meta>
|
||||
<div class="cardItemContent">
|
||||
<span>{{ item.updatedAt | fromNow }}</span>
|
||||
<div class="avatarList">
|
||||
<avatar-list size="small" :max-length="2">
|
||||
<avatar-list-item
|
||||
v-for="(member, i) in item.members"
|
||||
:key="`${item.id}-avatar-${i}`"
|
||||
:src="member.avatar"
|
||||
:tips="member.name"
|
||||
/>
|
||||
</avatar-list>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
// import { TagSelect, StandardFormRow, Ellipsis, AvatarList } from '../../components';
|
||||
import TagSelect from '../../components/TagSelect';
|
||||
import StandardFormRow from '../../components/StandardFormRow';
|
||||
import Ellipsis from '../../components/Ellipsis';
|
||||
import AvatarList from '../../components/AvatarList';
|
||||
const TagSelectOption = TagSelect.Option;
|
||||
const AvatarListItem = AvatarList.Item;
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AvatarList,
|
||||
AvatarListItem,
|
||||
Ellipsis,
|
||||
TagSelect,
|
||||
TagSelectOption,
|
||||
StandardFormRow,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
form: this.$form.createForm(this),
|
||||
loading: true,
|
||||
};
|
||||
},
|
||||
filters: {
|
||||
fromNow(date) {
|
||||
return moment(date).fromNow();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
handleChange(value) {
|
||||
console.log(`selected ${value}`);
|
||||
},
|
||||
getList() {
|
||||
this.$http.get('/list/article', { params: { count: 8 } }).then(res => {
|
||||
console.log('res', res);
|
||||
this.data = res.result;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ant-pro-components-tag-select {
|
||||
:deep(.ant-pro-tag-select .ant-tag) {
|
||||
margin-right: 24px;
|
||||
padding: 0 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.ant-pro-pages-list-projects-cardList {
|
||||
margin-top: 24px;
|
||||
|
||||
:deep(.ant-card-meta-title) {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
:deep(.ant-card-meta-description) {
|
||||
height: 44px;
|
||||
overflow: hidden;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.cardItemContent {
|
||||
display: flex;
|
||||
height: 20px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: -4px;
|
||||
line-height: 20px;
|
||||
|
||||
> span {
|
||||
flex: 1 1;
|
||||
color: rgba(0,0,0,.45);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:deep(.ant-pro-avatar-list) {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
@ -146,13 +146,10 @@
|
||||
data-wow-delay="0.25s"
|
||||
id="cmt225"
|
||||
>
|
||||
<!-- 只有当评论作者是当前用户时才显示删除按钮 -->
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: end;
|
||||
justify-content: flex-end;
|
||||
"
|
||||
v-if="item.userId === userId"
|
||||
class="delete-btn"
|
||||
@click="DeleteComments(item)"
|
||||
>
|
||||
删除
|
||||
@ -160,17 +157,17 @@
|
||||
<div class="msgimg">
|
||||
<img
|
||||
class="avatar"
|
||||
src="https://q2.qlogo.cn/headimg_dl?dst_uin=36926842&spec=100"
|
||||
alt="网友昵称:访客"
|
||||
title="网友昵称:访客"
|
||||
:src="getUserAvatar(item.userId)"
|
||||
:alt="getUserName(item.userId)"
|
||||
:title="getUserName(item.userId)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="msgtxt">
|
||||
<div class="msgname">
|
||||
<span class="autlv aut-6 vs">V</span
|
||||
><span class="autlv autlvname aut-6">游客</span>
|
||||
<span class="dot shafa">沙发</span>
|
||||
<span class="autlv aut-6 vs">{{ getUserRole(item.userId) }}</span>
|
||||
<span class="autlv autlvname aut-6">{{ getUserName(item.userId) }}</span>
|
||||
<span class="dot">{{ index === 0 ? '沙发' : `${index + 1}楼` }}</span>
|
||||
</div>
|
||||
<div class="interact-bar">
|
||||
<span class="interact-time" title="评论时间">{{
|
||||
@ -178,7 +175,8 @@
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="msgarticle">
|
||||
{{ item.commentContent }}<label id="AjaxComment225"></label>
|
||||
{{ item.commentContent }}
|
||||
<label id="AjaxComment225"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -213,6 +211,7 @@ export default {
|
||||
msg: "",
|
||||
comments: [],
|
||||
users: [],
|
||||
userMap: {}, // 用于缓存用户信息
|
||||
};
|
||||
},
|
||||
|
||||
@ -322,20 +321,49 @@ export default {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
getuser() {
|
||||
AllUser()
|
||||
.then((response) => {
|
||||
this.users = response.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed to load users:", error);
|
||||
});
|
||||
// 获取用户信息并缓存
|
||||
async getuser() {
|
||||
try {
|
||||
const response = await AllUser();
|
||||
this.users = response.data;
|
||||
// 创建用户信息映射
|
||||
this.userMap = this.users.reduce((map, user) => {
|
||||
map[user.userId] = user;
|
||||
return map;
|
||||
}, {});
|
||||
} catch (error) {
|
||||
console.error("Failed to load users:", error);
|
||||
this.$message.error("获取用户信息失败");
|
||||
}
|
||||
},
|
||||
|
||||
// 获取用户名
|
||||
getUserName(userId) {
|
||||
const user = this.users.find((u) => u.userId === userId);
|
||||
return user ? user.userName : "未知用户";
|
||||
return this.userMap[userId]?.userName || "未知用户";
|
||||
},
|
||||
},
|
||||
|
||||
// 获取用户头像
|
||||
getUserAvatar(userId) {
|
||||
return this.userMap[userId]?.avatar || "https://onlinephoto.oss-cn-chengdu.aliyuncs.com/hangtian/touxiang.jpg";
|
||||
},
|
||||
|
||||
// 获取用户角色
|
||||
getUserRole(userId) {
|
||||
const user = this.userMap[userId];
|
||||
if (!user) return "V";
|
||||
|
||||
switch(user.role) {
|
||||
case "admin":
|
||||
return "管理员";
|
||||
case "teacher":
|
||||
return "教师";
|
||||
case "student":
|
||||
return "学生";
|
||||
default:
|
||||
return "V";
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style src="@/assets/pages.css"></style>
|
||||
@ -357,4 +385,50 @@ button {
|
||||
.router-link-exact-active {
|
||||
color: none;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 5px 10px;
|
||||
color: #ff4d4f;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.delete-btn:hover {
|
||||
color: #ff7875;
|
||||
}
|
||||
|
||||
.msgname {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.autlv {
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.aut-6.vs {
|
||||
background-color: #3690cf;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dot {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.interact-time {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.msgarticle {
|
||||
margin-top: 8px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
x
Reference in New Issue
Block a user