Files
PC-Light-Forum/component/item-head/item-head.js
DESKTOP-RQ919RC\Pc 1a49ba60ce feat(组件): 优化移动端分享功能并调整样式
调整推荐和精华图标高度为25px
为移动端添加点击分享直接复制链接功能
修复itemBottom组件中itemvalue拼写错误
添加响应式布局样式适配不同屏幕尺寸
2025-12-18 18:33:52 +08:00

172 lines
9.2 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, defineAsyncComponent } = Vue;
// const { report } = await import(withVer("../report/report.js"));
const report = defineAsyncComponent(() => import(withVer("../report/report.js")).then((m) => m.report));
// 定义组件(直接使用模板)
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([]);
let valueUrl = ref("");
onMounted(() => {
setTimeout(() => {
permissions.value = window["permissions"] || [];
ismanager.value = permissions.value.indexOf("topic:manager") >= 0;
}, 1000);
const valueA = document.querySelector(".valueA");
valueUrl.value = valueA.innerText;
});
// 举报
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) => {
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) => {
if (res.code != 200) return;
const data = res.data || {};
target.anonymous = data.anonymous || 0;
item.value = target;
creationAlertBox("success", res.message || "操作成功");
})
.finally(() => {
cutAnonymous();
});
};
return { valueUrl, 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="valueUrl + '/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="valueUrl + '/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="valueUrl + '/img/u1829.svg'"></image> </div> </div> </template> </div> <div class="view flexacenter"> <img class="icon" :src="valueUrl + '/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="valueUrl + '/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"> <a class="item icon" v-if="item.recommend == 1 && item.best != 1" target="_blank" href="/recommend"> <img style="height: 25px;" :src="valueUrl + '/img/recommend-icon.png'" /> </a> <a class="item icon" v-if="item.best == 1" target="_blank" href="/best"> <img style="height: 25px;" v-if="item.best == 1" :src="valueUrl + '/img/essence-icon.png'" /> </a> <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>`,
});