Files
t/pages2/editCms/preview.vue
T
root 99c139d6ce fix: Vue2 到 Vue3 迁移兼容修复
- 修复 uni-popup-dialog/uni-data-picker keypress.js 中 $once 在 H5 端报错(改用生命周期钩子清理监听)
- main.js 补 $delete globalProperties polyfill(z-paging 自动高度逻辑依赖)
- App.vue onLaunch 补设备信息初始化,修复 X-Device-Id 恒为 unknown
- 68 处 ::v-deep、/deep/ 旧深度选择器替换为 :deep()(含 login-page.scss)
- zetank-personalpage 组件 .sync 修饰符改为 v-model:xxx(Vue3 已移除 .sync)
- vite.config.js HBuilderX 路径支持 HBUILDERX_HOME 环境变量覆盖
- 根 package.json 清理 image-grid 插件遗留元数据
- 收录此前未提交的 uView Vue3 兜底补丁(common/uview-init.js 及各组件 props.js)
2026-09-06 19:36:36 +08:00

651 lines
15 KiB
Vue
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.
<template>
<view class="body">
<uni-nav-bar
title="预览"
leftText="取消"
left-icon="left"
right-text="完成"
backgroundColor="#ffffff"
color="#000000"
@clickRight="success()"
@clickLeft="back()">
</uni-nav-bar>
<view class="v-preview" v-if="temp && temp.temptele_src">
<image :src="temp.temptele_src" alt="" class="img" mode="widthFix" />
</view>
<view class="" :style="backgrond_color">
<u-parse :content="titleContent"></u-parse>
<view class="">
<view class="meta">
<view class="author">
<cloud-image
height="64rpx" width="64rpx" borderRadius="50%"
:src="userInfo.avatar_file.url"></cloud-image>
<text class="at" :style="color">{{ userInfo.nickname || '' }}</text>
<text class="split">·</text>
<text class="date" :style="color">刚刚</text>
</view>
</view>
<view class="">
<view class="" v-for="(item, index) in cms.cmsLst" :key="index">
<u-parse
:content="item.html"
v-if="item.type === 'image' || item.type === 'video'">
</u-parse>
<view class="" v-if="item.type === 'image'"
style="width: 100wv;margin-top: 30rpx;margin-bottom: 30rpx;">
<cloud-image
width="100%"
height="500rpx"
mode="aspectFit"
:src="item.image.src">
</cloud-image>
</view>
<view class="" v-if="item.type === 'video'"
style="width: 100wv;margin-top: 30rpx;margin-bottom: 30rpx;">
<video
style="width: 100%; height: 500rpx;"
:src="item.video.src"
enable-danmu
danmu-btn
controls>
</video>
</view>
<view class="" v-if="item.type === 'vote'">
<uni-card>
<view class="vote-container">
<text class="vote-title">{{ item.vote.voteTitle }}</text>
<text class="deadline">截止时间:{{ item.vote.datetime }}</text>
<view class="" v-if="item.vote.type === voteType[0]">
<u-radio-group
v-model="item.vote.selectValue"
placement="column"
@change="groupChange"
wrap
>
<u-radio
:customStyle="{marginBottom: '8px'}"
v-for="(radio, radioIndex) in item.vote.voteLst"
:key="radioIndex"
:label="radio.value"
:name="radio.value"
@change="radioChange"
style="width: 100%;"
>
</u-radio>
</u-radio-group>
</view>
<view class="" v-if="item.vote.type === voteType[1]">
<u-checkbox-group
v-model="item.vote.selectValue"
placement="column"
@change="checkboxChange"
>
<u-checkbox
:customStyle="{marginBottom: '8px'}"
v-for="(checkbox, checkboxIndex) in item.vote.voteLst"
:key="checkboxIndex"
:label="checkbox.value"
:name="checkbox.value"
>
</u-checkbox>
</u-checkbox-group>
</view>
<view class="" v-if="item.vote.type === voteType[2]">
<u-checkbox-group
v-model="item.vote.selectValue"
placement="column"
@change="checkboxChange"
>
<view class="">
<u-checkbox
:customStyle="{marginBottom: '8px'}"
v-for="(checkbox, checkboxIndex) in item.vote.voteLst"
:key="checkboxIndex"
:label="checkbox.value"
:name="checkbox.value"
:disabled="isCheckboxDisabled(item.vote.selectValue, checkbox.value)"
>
</u-checkbox>
</view>
</u-checkbox-group>
</view>
<view class=""
v-if="isExpired"
:disabled="isExpired || !selectedValue"
style="border-top: 3rpx solid #ccc;padding-top: 20rpx;margin-top: 20rpx;
text-align: center;;">
已截止
</view>
<view class=""
v-else
:disabled="isExpired || !selectedValue"
style="border-top: 3rpx solid #ccc;padding-top: 20rpx;margin-top: 20rpx;
text-align: center;;">
{{ isExpired ? '已截止' : '点击登录后投票' }}
</view>
</view>
</uni-card>
</view>
</view>
</view>
</view>
</view>
<u-tabbar :value="tabbarValue"
>
<u-tabbar-item
v-for="(item, index) in tabbarText"
:key="index"
@click="tabbarClick"
:text="item.text">
</u-tabbar-item>
</u-tabbar>
<hqs-popup :title="tabbarText[tabbarValue].text" :from="popFrom" :mask-click="maskClick"
@back="onBack"
v-model="showPop">
<view class="page-container" v-if="tabbarText[tabbarValue].text === '模板'">
<media-list
:dataType="'template'"
:pageSize="12"
:currentTemplate="updateTemplateConfig"
@update="updateTemplate"
/>
</view>
<view class="page-container" v-if="tabbarText[tabbarValue].text === '音乐'">
<media-list
:dataType="'music'"
:pageSize="12"
:currentTemplate="updateTemplateConfig"
@update="updateTemplate"
/>
</view>
<view class="page-container" v-if="tabbarText[tabbarValue].text === '排版'">
</view>
</hqs-popup>
<uni-grid :column="3" :highlight="true" @change="change" :show-border="false">
<uni-grid-item v-for="(item, index) in gridLst" :index="index" :key="index">
<view class="grid-item-box">
<uni-icons :type="item.icon" :size="30"
:color="item.select_flag?select_icon_color:icon_color" />
<text class="text" :style="item.select_flag?select_font_color:icon_font_color">
{{item.value?item.value:0}}
</text>
</view>
</uni-grid-item>
</uni-grid>
</view>
</template>
<script>
import { ref, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { store } from '@/pages3/uni_modules/uni-id-pages/common/store.js'
import uRadioGroup from "@/uni_modules/uview-ui/components/u-radio-group/u-radio-group.vue"
import uRadio from "@/uni_modules/uview-ui/components/u-radio/u-radio.vue"
import uParse from "@/uni_modules/uview-ui/components/u-parse/u-parse.vue"
import uTabbar from "@/uni_modules/uview-ui/components/u-tabbar/u-tabbar.vue"
import uTabbarItem from "@/uni_modules/uview-ui/components/u-tabbar-item/u-tabbar-item.vue"
import mediaList from "@/components/image-grid/media-list.vue"
import cloudImage from "@/components/cloud-image.vue"
import uCheckboxGroup from "@/uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue"
import uCheckbox from "@/uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue"
export default {
components: {
uTabbar,
uTabbarItem,
mediaList,
uParse,
cloudImage,
uRadioGroup,
uRadio,
uCheckboxGroup,
uCheckbox
},
setup() {
const voteType = ref(["单选(默认)", "多选,无限制", "多选, 最多两项"])
const voteEndTime = ref('2025-04-20 23:59:59')
const cms = ref({})
const temp = ref({})
const titleContent = ref("")
const tabbarValue = ref(0)
const showPop = ref(false)
const maskClick = ref(true)
const popFrom = ref('bottom')
const list = ref(new Array(20).fill(0))
const currentTemplate = ref("")
const tabbarText = ref([
{ text: "模板" },
{ text: "音乐" },
{ text: "排版" }
])
const userInfo = computed(() => store.userInfo)
const isExpired = computed(() => new Date() > new Date(voteEndTime.value))
const btn_send_commends_color = computed(() => {
if (!temp.value) return ""
return `background-color: ${temp.value.btn_send_commends_color};`
})
const backgrond_color = computed(() => {
if (!temp.value) return ""
return `background-color: ${temp.value.backgrond_color};`
})
const color = computed(() => {
if (!temp.value) return ""
return `color: ${temp.value.font_color};`
})
const select_icon_color = computed(() => {
if (!temp.value) return ""
return `${temp.value.select_icon_color};`
})
const icon_color = computed(() => {
if (!temp.value) return ""
return `${temp.value.icon_color};`
})
onShow(async () => {
let storedCms = uni.getStorageSync("cms")
titleContent.value = storedCms.title_html
cms.value = storedCms
await getTemp()
})
async function getTemp() {
if (currentTemplate.value === "not_image") {
temp.value = {}
}
if (!currentTemplate.value) {
temp.value = {}
return
}
const res = await uniCloud.importObject("uni-cms-articles").getTemp({
temp_id: currentTemplate.value
})
if (res.code === 200) {
temp.value = res.data
}
}
async function updateTemplate(e) {
currentTemplate.value = e
await getTemp()
}
function onBack() {
uni.showToast({ title: 'test' })
}
function tabbarClick(e) {
tabbarValue.value = e
showPopupFrom()
}
function showPopupFrom() {
showPop.value = true
}
function isCheckboxDisabled(arr, name) {
if (arr.length < 2 || arr.includes(name)) {
return false
}
return true
}
function checkboxChange(e) {
console.log(e)
}
function groupChange(n) {
console.log('groupChange', n)
}
function radioChange(n) {
console.log('radioChange', n)
}
function formatDate(date, format) {
const map = {
'yyyy': date.getFullYear(),
'MM': String(date.getMonth() + 1).padStart(2, '0'),
'dd': String(date.getDate()).padStart(2, '0'),
'HH': String(date.getHours()).padStart(2, '0'),
'mm': String(date.getMinutes()).padStart(2, '0'),
'ss': String(date.getSeconds()).padStart(2, '0')
}
return format.replace(/yyyy|MM|dd|HH|mm|ss/g, matched => map[matched])
}
function formatTime() {
return formatDate(new Date(), 'yyyy-MM-dd HH:mm')
}
async function success() {
let storedCms = uni.getStorageSync("cms")
let id = storedCms._id
let title = storedCms.title
let title_html = storedCms.title_html
let title_delta = storedCms.title_delta
let temp_id = currentTemplate.value
let edit_type = "mobile"
let view_count = 0
let article_status = 1
let user_id = userInfo.value._id
let cmsLst = storedCms.cmsLst
let excerpt = ""
let res = await uniCloud.importObject("user-info").getIP({ uid: userInfo.value._id })
let last_modify_ip = res.code === 200 ? res.data.last_login_ip : ""
if (id) {
let query = {
id,
title: storedCms.title,
user_id,
title_html: storedCms.title_html,
title_delta: storedCms.title_delta,
thumbnail: storedCms.thumbnail,
p_type: storedCms.p_type,
category_id: storedCms.category_id,
temp_id,
edit_type,
view_count,
cmsLst: storedCms.cmsLst,
excerpt,
last_modify_ip,
article_status,
}
await uniCloud.importObject("uni-cms-articles").update_cms_articles(query)
} else {
let query = {
title: storedCms.title,
user_id,
title_html: storedCms.title_html,
title_delta: storedCms.title_delta,
thumbnail: storedCms.thumbnail,
p_type: storedCms.p_type,
category_id: storedCms.category_id,
temp_id,
edit_type,
view_count,
cmsLst: storedCms.cmsLst,
excerpt,
last_modify_ip,
article_status,
}
await uniCloud.importObject("uni-cms-articles").add_cms_articles(query)
}
uni.setStorageSync("cms", "")
uni.switchTab({ url: "/pages/my/my" })
}
async function back() {
uni.navigateBack({
delta: 1,
fail: (err) => {
uni.navigateTo({ url: "/pages2/editCms/editCms" })
}
})
}
return {
voteType,
voteEndTime,
cms,
temp,
titleContent,
tabbarValue,
showPop,
maskClick,
popFrom,
list,
currentTemplate,
tabbarText,
userInfo,
isExpired,
btn_send_commends_color,
backgrond_color,
color,
select_icon_color,
icon_color,
getTemp,
updateTemplate,
onBack,
tabbarClick,
showPopupFrom,
isCheckboxDisabled,
checkboxChange,
groupChange,
radioChange,
formatDate,
formatTime,
success,
back,
}
}
}
</script>
<style lang="scss" scoped>
.grid-container {
display: flex;
gap: 10px;
padding: 15px;
background: #f5f5f5;
}
.grid-item {
flex: 1;
min-width: 0;
aspect-ratio: 1;
background: white;
border-radius: 8px;
overflow: hidden;
}
.page-container {
padding: 20rpx 0;
}
.rectangle-img {
width: 100%;
height: 100%;
object-fit: cover;
aspect-ratio: 16/9;
}
.meta {
position: relative;
z-index: 1;
padding-top: 20rpx;
.title {
.text {
font-size: 40rpx;
line-height: 66rpx;
font-weight: bold;
color: #333;
}
}
.excerpt {
margin-top: 10rpx;
.text {
font-size: 26rpx;
line-height: 40rpx;
color: #999;
}
}
.author {
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: row;
margin-top: 20rpx;
.at,
.split,
.date {
font-size: 26rpx;
color: #ccc;
}
.split {
margin: 0 10rpx;
}
}
}
.body {
padding: 20rpx;
.cms-body {
display: flex;
min-height: 60hv;
width: 100wv;
}
}
.v-preview {
.img {
width: 100%;
}
.btn-area {
position: relative;
top: -50rpx;
}
.red-btn-area {
display: flex;
justify-content: center;
padding: 10rpx 0;
margin: 0 40rpx 20rpx 40rpx;
font-size: 20rpx;
.red-btn {
position: relative;
color: #fff;
font-weight: 700;
font-size: 24rpx;
height: 40rpx;
line-height: 40rpx;
margin: 0;
background-image: linear-gradient(to bottom, #c11c1f, #5c0201);
+.red-btn {
margin-left: 20rpx;
}
}
}
.red-btn-plain-area {
display: flex;
justify-content: center;
padding: 10rpx 0;
margin: 0 40rpx;
font-size: 21rpx;
border-top: 2px solid;
border-bottom: 2px solid;
border-image: linear-gradient(to right,
#fff,
#f44336bf,
#b13636,
#f44336bf,
#fff) 1;
.red-btn-plain {
position: relative;
color: #b13636;
font-weight: 700;
padding-left: 15rpx;
+.red-btn-plain {
margin-left: 10rpx;
&::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 2px;
height: 20rpx;
background-color: #b13636;
}
}
}
}
}
.vote-container {
padding: 20rpx;
}
.vote-title {
font-size: 16px;
font-weight: bold;
color: #333;
display: block;
margin-bottom: 10rpx;
}
.deadline {
font-size: 12px;
color: #999;
margin-bottom: 30rpx;
display: block;
}
.radio-group {
margin-bottom: 40rpx;
}
.option-item {
display: flex;
align-items: center;
margin: 15rpx 0;
}
.option-label {
margin-left: 20rpx;
font-size: 14px;
}
.vote-btn {
background-color: #2979FF;
color: white;
border-radius: 8rpx;
font-size: 14px;
margin-top: 30rpx;
&[disabled] {
background-color: #CCCCCC;
}
}
</style>