Files
PC-Light-Forum/component/item-head/item-head.js
DESKTOP-RQ919RC\Pc 275b78b221 refactor(editor): 重构编辑器组件及样式,优化功能实现
重构编辑器工具栏样式及功能,使用wangEditor替换原有实现
优化图片和视频上传逻辑,增加自定义校验和上传处理
调整编辑器样式,修复对齐功能及段落标题样式
更新表情选择器位置逻辑,支持上下方向显示
统一组件导入方式,添加版本控制参数防止缓存
2025-11-26 19:01:26 +08:00

169 lines
8.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// my-component.js
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入Vue 已挂载到 window
const { defineComponent, ref, provide, onMounted, inject } = Vue;
const { report } = await import(withVer("../report/report.js"));
// 定义组件(直接使用模板)
export const itemHead = defineComponent({
name: "item-head",
props: {
itemdata: {
type: Object,
default: () => {},
},
page: {
type: String,
default: "",
},
},
setup(props) {
let sectionn = ref([]);
let tags = ref([]);
let item = ref({ ...props.itemdata });
if (!item.value.hidden) item.value.hidden = 0;
// item.value['best'] = 0
// item.value['recommend'] = 1
let timestamp = ref(strtimeago(item.value.release_at, 4));
if (item.value.type == "tenement") timestamp = timeago(item.value.updatetime, 2);
sectionn.value = item.value.sectionn || [];
const sectionNameSet = new Set(sectionn.value.map((item) => item.name));
tags.value = item.value?.tags || [];
tags.value = tags.value?.filter((tagName) => !sectionNameSet.has(tagName)) || [];
// const sectionSet = new Set(sectionn.value);
// tags.value = item.value.tags?.filter((tag) => !sectionSet.has(tag));
let show = ref(false);
const cutShow = () => {
show.value = !show.value; // 修改为切换显示状态
};
let reportState = ref(false);
provide("reportState", reportState);
let ismanager = ref(false); // 添加管理员状态变量
let permissions = ref([]);
onMounted(() => {
setTimeout(() => {
permissions.value = window["permissions"] || [];
ismanager.value = permissions.value.indexOf("topic:manager") >= 0;
}, 1000);
});
// 举报
const report = () => {
cutShow();
reportState.value = true;
};
// 隐藏
const hide = () => {
const target = item.value;
managerHide(target.token, target.hidden, target.type).then((value) => {
target.hidden = value;
item.value = target;
cutShow();
});
};
// 推荐
const recommend = () => {
const target = item.value;
managerRecommend(target.token, target.recommend).then((value) => {
target.recommend = value;
item.value = target;
cutShow();
});
};
// 精华
const essence = () => {
const target = item.value;
managerEssence(target.token, target.best).then((value) => {
target.best = value;
item.value = target;
cutShow();
});
};
// let handleDelete = inject("handleDelete");
let itemHead = ref(null);
// 删除
const deleteItem = () => {
const target = item.value;
managerDelete(target.token)
.then(() => {
const targetNode = itemHead.value;
if (!targetNode) return;
const parentItemBox = targetNode.parentElement;
if (parentItemBox?.classList.contains("item-box")) parentItemBox.style.display = "none";
})
.finally(() => {
cutShow();
});
};
// 编辑
const edit = () => {
const target = item.value;
redirectToExternalWebsite(`/publish?uniqid=${target.uniqid}`);
};
const goPersonalHomepage = (token) => {
console.log("token", token);
if (!token) return;
redirectToExternalWebsite(`/u/${token}`);
};
const openedit = (type) => {
let url = ``;
if (type == "offer") url = `https://offer.gter.net/post/modify?id=${item.value.token}`;
else if (type == "offer_summary") url = `https://offer.gter.net/post/summary`;
redirectToExternalWebsite(url);
};
const anonymousState = ref(false);
const cutAnonymous = () => {
anonymousState.value = !anonymousState.value;
};
const cutAnonymousState = (state) => {
const target = item.value;
ajax("/v2/api/forum/setTopicAnonymousStatus", {
token: target.token,
anonymous: state,
})
.then((res) => {
console.log("res", res);
if (res.code != 200) return;
const data = res.data || {};
target.anonymous = data.anonymous || 0;
item.value = target;
creationAlertBox("success", res.message || "操作成功");
})
.finally(() => {
cutAnonymous();
});
};
return { itemHead, cutAnonymousState, cutAnonymous, anonymousState, openedit, edit, deleteItem, goPersonalHomepage, reportState, cutShow, show, item, timestamp, sectionn, tags, ismanager, report, hide, recommend, essence };
},
components: {
report,
},
template: `<div class="item-head flexacenter" ref="itemHead"> <div class="user-box flexacenter" @click="goPersonalHomepage(item?.user?.uniqid)"> <img class="avatar" :src="item?.user?.avatar || item.avatar" /> <div class="name">{{ item?.user?.nickname || item.nickname || "匿名用户" }}</div> <img class="group" v-if="item.user?.groupimage" :src="item.user?.groupimage" /> </div> <div class="time">{{ timestamp }}</div> <div class="flex1"></div> <div class="circlePen flexcenter" @click="openedit(item.type)" v-if="page == 'edit' && (item.type == 'offer' || item.type == 'offer_summary')"> <img class="icon" src="/img/pen-icon.png" /> </div> <div class="flexacenter" style="position: relative;"> <div class="anonymous-box flexcenter" @click.stop="cutAnonymous" v-if="page == 'edit' && (item.type == 'vote' || item.type == 'interviewexperience')"> <span v-if="item.anonymous == 0">公开</span> <span v-else>匿名</span> </div> <!-- 是否 公开发表 --> <template v-if="anonymousState"> <div class="mask" @click.stop="cutAnonymous"></div> <div class="isPublicityBox"> <div class="isPublicity-item" :class="{'green': item.anonymous == 0}" @click.stop="cutAnonymousState(0)">公开发表 <img v-if="item.anonymous == 0" class="isPublicityIcon" src="/img/u1829.svg"></image> </div> <div class="isPublicity-item" :class="{'green': item.anonymous != 0}" @click.stop="cutAnonymousState(1)">匿名发表 <img v-if="item.anonymous != 0" class="isPublicityIcon" src="/img/u1829.svg"></image> </div> </div> </template> </div> <div class="view flexacenter"> <img class="icon" src="/img/eye-icon.svg" /> <div class="text">{{ item.views }}</div> </div> <div v-if="item.type != 'tenement'" class="btn flexcenter" @click.stop="cutShow"> <img class="icon" src="/img/dot-dot-dot-gray.png" /> </div> <div v-if="show"> <div class="mask" @click.stop="cutShow"></div> <div class="operate"> <div class="item" @click.stop="report">举报</div> <template v-if="ismanager"> <div class="item" @click.stop="hide">{{ item.hidden == 0 ? "隐藏" : "显示" }}</div> <div class="item" @click.stop="recommend">{{ item.recommend == 1 ? "取消" : "" }}推荐</div> <div class="item" @click.stop="essence">{{ item.best == 1 ? "取消" : "" }}精华</div> </template> <template v-if="item.type == 'thread' && item.ismyself"> <div class="item" @click.stop="edit">编辑</div> <div class="item" @click.stop="deleteItem">删除</div> </template> <div class="item" v-if="page == 'edit' && item.type == 'vote'" @click.stop="deleteItem">删除</div> </div> </div></div><div class="label flexflex" v-if="sectionn?.length || tags?.length || item.recommend == 1 || item.best == 1"> <img class="item icon" v-if="item.recommend == 1" src="/img/recommend-icon.png" /> <img class="item icon" v-if="item.best == 1" src="/img/essence-icon.png" /> <a class="item blue" v-for="(item, index) in sectionn" :key="item" :href="'/section/' + item.uniqid" target="_blank">{{ item.name }}</a> <a class="item" v-for="(item, index) in tags" :key="item" :href="'/tag/' + item" target="_blank">{{ item }}</a></div><report v-if="reportState" :itemdata="item"></report>`,
});