<template> <Head> <Title>寄托天下 - 投票发布</Title> <Meta name="keyword" content="留学资讯,留学交流论坛,留学面经,面试经验,寄托天下" /> </Head> <div class="content-box"> <div class="flexacenter save-box save-left" @click="submit(0)"> <img class="save-icon" src="@/assets/img/arrow-gray.png" /> 保存并退出 </div> <div class="flexacenter save-box save-right" @click="abandonSaving"> 放弃保存 <img class="save-icon" src="@/assets/img/cross-icon.png" /> </div> <div class="contentcontent flex1"> <div class="header flexacenter">发起投票</div> <div class="box flex1 flexflex"> <div class="box-left"> <div class="item"> <div class="titletitle flexacenter"> 标题 <div class="asterisk">*</div> </div> <el-input class="item-input headline-textarea" type="textarea" placeholder="请输入" maxlength="60" show-word-limit v-model="info.title" autosize></el-input> </div> <div class="item"> <div class="titletitle flexacenter">详细说明</div> <el-input class="item-input explain-textarea" type="textarea" placeholder="请输入" maxlength="1000" show-word-limit v-model="info.message" autosize></el-input> </div> <div class="item"> <div class="titletitle flexacenter"> 截止投票日期 <div class="asterisk">*</div> </div> <div class="time-box item-input-box flexacenter"> <el-config-provider :locale="zhCn"> <el-date-picker ref="pickerRef" v-model="info.deadline" type="date" placeholder="请选择" size="large" class="flex1 flexacenter" :clear-icon="{}" value-format="YYYY-MM-DD" :disabled-date="setDisabled" /> </el-config-provider> <div class="flexacenter"> <img class="calendar-icon" @click="handlePicker" src="@/assets/img/calendar-icon.svg" /> </div> </div> </div> </div> <div class="box-right flex1"> <div class="item"> <div class="titletitle flexacenter"> 选项 <div class="asterisk">*</div> </div> <div class="option-list flexflex"> <div class="" ref="draggableContainer"> <template v-if="optionList.length == 0"> <div class="option-item flexacenter" v-for="(item, index) in 2" :key="index"> <div class="option-content flexacenter"> <div class="option-text flexcenter">{{ index + 1 }}</div> <el-input class="option-input flex1" placeholder="请输入" /> </div> <div class="option-drag flexcenter"> <img class="option-icon" src="@/assets/img/option-icon.svg" /> </div> </div> </template> <template v-else> <div class="option-item flexacenter" v-for="(item, index) in optionList" :key="item.id"> <div class="option-content flexacenter"> <div class="option-text flexcenter">{{ index + 1 }}</div> <!-- <input class="option-input flex1" placeholder="请输入" v-model="optionList[index]['message']" /> --> <el-input class="option-input flex1" placeholder="请输入" maxlength="100" show-word-limit v-model="optionList[index]['message']" /> <img class="option-cross" v-if="optionList[index]['message']" @click="clearMessage(index)" src="@/assets/img/cross-undertint-icon.svg" /> </div> <div class="option-drag flexcenter"> <img class="option-icon" src="@/assets/img/option-icon.svg" /> </div> <img class="rubbish-icon" v-if="optionList.length > 2" @click="deleteOption(index)" src="@/assets/img/rubbish-icon.svg" /> </div> </template> </div> <div class="option-item option-circusee flexacenter" :class="{ 'hascontent': optionList.length > 2 }"> <div class="option-content flexacenter"> <div class="option-text flexcenter">{{ optionList.length + 1 }}</div> <input class="option-input flex1" disabled value="不懂,围观学习" /> </div> </div> </div> <div class="flexcenter" style="padding-right: 26px;"> <div class="add-box flexcenter" @click="addOption()" v-if="optionList.length < 15"> <img class="add-icon" src="@/assets/img/add-green-icon.svg" /> 添加选项 </div> </div> </div> </div> </div> <div class="hint-box flexcenter">注:请确保以上内容已正确填写,发布后将不能修改</div> </div> </div> <div class="floor-box"> <div class="box flexacenter"> <div class="anonymous-box flexacenter" @click="cutAnonymous()"> <img class="anonymous-icon" v-if="info.anonymous == 0" src="@/assets/img/frame-no.svg" /> <img class="anonymous-icon" v-else src="@/assets/img/frame-pitch.svg" /> 匿名发表 <div class="text">(发布后可修改)</div> </div> <div class="issue-btn flexcenter" @click="submit()">发布</div> </div> </div> </template> <script setup> useHead({ script: [{ src: "https://app.gter.net/bottom?tpl=footer,popupnotification", body: true }] }) import { useRouter } from "vue-router" import { ElMessage } from "element-plus" import zhCn from "element-plus/dist/locale/zh-cn.mjs" import Sortable from "sortablejs" const router = useRouter() const goLogin = inject("goLogin") const setDisabled = time => { // return time.getTime() < Date.now() // 可选历史天、可选当前天、不可选未来天 const today = new Date() const tomorrow = new Date(today) tomorrow.setDate(today.getDate()) const thirtyDaysLater = new Date(today) thirtyDaysLater.setDate(today.getDate() + 29) return time < tomorrow || time > thirtyDaysLater } onMounted(() => {}) onBeforeMount(() => { clearBottom() // clearTop() }) // 清除底部的次数 let clearBottomCount = 0 // 清除 底部 const clearBottom = () => { const indexFooter = document.querySelector("section.index-footer") if (!indexFooter) { clearBottomCount++ setTimeout(() => clearBottom(), 50) return } if (clearBottomCount == 15) return indexFooter.style.display = "none" } // 清除顶部的次数 let clearTopCount = 0 // 清除 顶部 const clearTop = () => { const indexHeader = document.querySelector("header.page-header") if (!indexHeader) { clearTopCount++ setTimeout(() => clearTop(), 50) return } if (clearTopCount == 5) return indexHeader.style.display = "none" } let info = ref({}) let token = "" // 切换匿名状态 const cutAnonymous = () => { info.value["anonymous"] = info.value["anonymous"] == 0 ? 1 : 0 } let loading = false // 加载中 // 提交发布 const submit = (status = 1) => { // status = 0 if (loading) return loading = true let option = [] optionList.value.forEach(element => { if (element["message"].trim() !== "") option.push(element["message"]) }) if (status == 1) { if (option.length < 2) { ElMessage.error("请设置至少2个选项~") loading = false return } const hash = {} for (let i = 0; i < option.length; i++) { if (hash[option[i]]) { ElMessage.error("选项名称不能重复") loading = false return // 有重复值 } hash[option[i]] = true } option.push("不懂,围观学习") } info.value["option"] = option // return publishSubmitHttp({ info: info.value, token, status }) .then(res => { if (res.code != 200) { ElMessage.error(res.message) return } const data = res.data ElMessage.success(res.message) // router.push(`/details/${data["uniqid"]}`) if (status == 0) goToURL(`/index.html`, false) else goToURL(`/details/${data["uniqid"]}`, false) }) .finally(() => (loading = false)) } // 放弃保存 跳跃上一页或者首页 const abandonSaving = () => { if (router.currentRoute.value.meta.previousPage) router.go(-1) else goToURL("./index.html", false) // 跳转到首页 // else router.push("./index.html") // 跳转到首页 } let draggableContainer = ref(null) const sortable = ref(null) onMounted(() => { getinit() initDraggable() }) const getinit = () => { publishInitHttp().then(res => { if (res.code != 200) { ElMessage.error(res.message || "报错了,刷新一下") if (res.code == 401) goLogin() return } const data = res.data // data.info.option = [] const option = data.info?.option || [] if (option.length == 0) { for (let index = 0; index < 2; index++) { optionList.value.push({ id: index, message: "" }) } } else { option.forEach((message, index) => { if (message !== "不懂,围观学习") { optionList.value.push({ id: index, message }) } }) while (optionList.value.length < 2) { optionList.value.push({ id: optionList.value.length, message: "" }) } } let deadline = data["info"]["deadline"] || 0 // console.log("deadline", deadline) if (deadline > 100000) data["info"]["deadline"] = handleDate(deadline) else data["info"]["deadline"] = null if (data["info"]["deadline"]) data["info"]["deadline"] = handleDate(deadline) info.value = data.info token = data.token }) } // 处理初始化 面试时间的 时间戳格式 const handleDate = timestamp => { // 使用Date对象将时间戳转换为日期对象 var date = new Date(timestamp * 1000) // 获取年份、月份和日期 var year = date.getFullYear() var month = ("0" + (date.getMonth() + 1)).slice(-2) // 月份从0开始,需要加1并补0 var day = ("0" + date.getDate()).slice(-2) // 获取日期并补0 // 拼接为yyyy-mm-dd格式的日期字符串 var formattedDate = year + "-" + month + "-" + day return formattedDate } // 初始化拖拽 const initDraggable = () => { if (!draggableContainer.value) { console.warn("容器不能为空") return } sortable.value = Sortable.create(draggableContainer.value, { handle: ".option-drag", draggable: ".option-item", // 允许拖拽的项目类名 direction: "horizontal", forceFallback: true, animation: 300, onUpdate(e) { if (e.oldIndex !== undefined && e.newIndex !== undefined) { // 删除拖拽的元素 const list = [...optionList.value] const item = list.splice(e.oldIndex, 1)[0] // 把删除的元素放到新的位置 list.splice(e.newIndex, 0, item) optionList.value = list } }, }) } let optionList = ref([]) // 特殊的 选项 列表 // 点击添加选项 const addOption = () => { optionList.value.push({ id: optionList.value.length, message: "", }) } // 点击删除选项 const deleteOption = index => { optionList.value.splice(index, 1) optionList.value.forEach((element, index) => { element["id"] = index }) } // 点进清除选项 const clearMessage = index => { optionList.value[index]["message"] = "" } let pickerRef = ref(null) const handlePicker = () => { pickerRef.value.handleOpen() } </script> <style scoped lang="less"> .content-box { display: flex; justify-content: center; padding: 0 122px; } @media (max-width: 920px) { .content-box { display: block; padding: 0 10px; } } .contentcontent { max-width: 1200px; min-width: 900px; min-height: calc(100vh - 120px); background: #fff; margin: 30px auto 90px; border-radius: 16px; display: flex; flex-direction: column; position: relative; .header { font-weight: 650; font-size: 20px; color: #000000; border-bottom: 1px solid #ebebeb; height: 88px; padding-left: 30px; } .box { .titletitle { color: #666666; font-size: 14px; margin-bottom: 10px; } .box-left { border-right: 16px solid #f6f6f6; width: 48.176%; padding: 30px; padding-right: 50px; .item { &:not(:last-of-type) { margin-bottom: 30px; } .item-input { border-radius: 5px; outline: none; width: 100%; font-size: 14px; /deep/ .el-textarea__inner { padding: 13px 14px; border-radius: 5px; box-shadow: none; border: 1px solid rgba(215, 215, 215, 1); } } .headline-textarea { /deep/ .el-textarea__inner { min-height: 70px !important; } } .explain-textarea { /deep/ .el-textarea__inner { min-height: 300px !important; } } } .item-input-box { // width: 482px;S height: 46px; border: 1px solid rgba(215, 215, 215, 1); border-radius: 5px; cursor: pointer; /deep/ .el-input { height: 100%; .el-input__wrapper { height: 100%; box-shadow: none; } } } .time-box { .calendar-icon { width: 17px; // height: 16px; margin: 0 9px; cursor: auto; } /deep/ .el-input { .el-input__prefix { display: none; } } } // } .visible-box { margin: 30px; font-size: 14px; color: #555555; cursor: pointer; user-select: none; .visible-icon { width: 18px; height: 18px; margin-right: 5px; } } } .box-right { padding-top: 30px; padding-left: 56px; padding-right: 30px; .option-list { flex-direction: column; margin-bottom: 53px; .option-item { // transition: all linear 0.3s; &:not(:first-of-type) { margin-top: 20px; } &.option-circusee { // margin-bottom: 53px; transition: all 0.3s; padding-right: 33px; &.hascontent { padding-right: 66px; } .option-content { background: rgba(246, 246, 246, 1); .option-input { background: transparent; } } } .option-content { // width: 470px; // width: 87.69%; flex: 1; height: 46px; border: 1px solid rgba(215, 215, 215, 1); border-radius: 5px; .option-text { width: 14px; height: 14px; color: #333; font-size: 11px; position: relative; margin: 0 10px; border-radius: 50%; border: 1px solid #797979; } .option-input { height: 100%; border: none; outline: none; border-radius: 5px; color: #333; /deep/ .el-input__wrapper { outline: none; border: none; box-shadow: none; padding-right: 10px; } } .option-cross { width: 12px; height: 12px; cursor: pointer; margin-right: 10px; } } .option-drag { padding-left: 15px; .option-icon { width: 18px; height: 16px; } // cursor: move; } .rubbish-icon { width: 13px; height: 14px; margin-left: 20px; cursor: pointer; } } } .add-box { .add-icon { width: 14px; height: 14px; margin-right: 6px; } font-size: 14px; color: #333; cursor: pointer; margin-bottom: 50px; // max-width: max-content; } } } .hint-box { height: 58px; background-color: rgba(246, 246, 246, 1); color: #555555; font-size: 13px; } } .asterisk { color: #fa9183; margin-left: 5px; } .floor-box { width: 100vw; min-width: 900px; height: 90px; background-color: rgba(255, 255, 255, 1); -moz-box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.192156862745098); -webkit-box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.192156862745098); box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.192156862745098); position: fixed; bottom: 0; .box { max-width: 1200px; min-width: 900px; height: 100%; margin: 0 auto; justify-content: space-between; padding: 0 30px; .anonymous-box { cursor: pointer; color: #333333; font-size: 14px; user-select: none; .text { color: rgb(170, 170, 170); font-size: 13px; } .anonymous-icon { width: 18px; height: 18px; } } .issue-btn { width: 200px; height: 46px; background-color: rgba(114, 219, 134, 1); border-radius: 190px; font-size: 16px; color: #fff; cursor: pointer; } } } // @media (max-width: 1300px) { // .save-box.save-left { // left: 0 !important; // } // .save-box.save-right { // right: 0 !important; // } // } .save-box { font-size: 14px; color: #666666; position: absolute; // position: fixed; top: 30px; cursor: pointer; transition: all 0.3s; z-index: 1; &.save-left { left: 0px; // left: calc((1200px - 100vw) / 2 + 25px); } &.save-right { right: 0px; // right: calc((1200px - 100vw) / 2 + 25px); .save-icon { width: 16px; height: 16px; margin-left: 10px; } } .save-icon { width: 22px; height: 22px; margin-right: 10px; transform: rotate(180deg); } } </style> <style scoped> /* .list-transition-enter-active, .list-transition-leave-active { transition: all 0.3s; } .list-transition-enter, .list-transition-leave-to { opacity: 0; transform: translateY(20px); } */ </style>