This commit is contained in:
2025-06-13 20:46:10 +08:00
parent e285692d9c
commit 52e34ffd7c
322 changed files with 3383 additions and 6322 deletions
@@ -33,18 +33,24 @@ function parseEditorImage (blocks = []) {
* @param type {string} 解析类型 media: 媒体库, editor: 编辑器
* @returns {Promise<{src: *, source: *}[]|{src, source: *}[]>}
*/
export async function parseImageUrl (images = [], type = "media") {
console.log(images)
if (type === "editor") {
images = parseEditorImage(images).map(item => item.source)
} else {
if (!Array.isArray(images)) {
images = [images]
images = [images]
}
images = await obj.getCloudImage(images)
}
if (!images) return null
const tcbFiles = images.filter(item => item.startsWith("cloud://"))
if (tcbFiles.length) {
const res = await uniCloud.getTempFileURL({
@@ -66,3 +72,29 @@ export async function parseImageUrl (images = [], type = "media") {
}))
}
}
let obj = {
async getCloudImage(srcLst) {
console.log(srcLst)
for (let i = 0; i < srcLst.length ; i ++ ) {
if (srcLst[i]&&srcLst[i].substring(0, 8) == "cloud://") {
const res = await uniCloud.getTempFileURL({fileList: [srcLst[i]]});
console.log(res)
console.log(res.fileList.tempFileURL)
srcLst[i] = res.fileList[0].tempFileURL
} else if (srcLst[i]&&srcLst[i].substring(0, 8) == "qiniu://") {
console.log(srcLst[i])
const uniCloudStorageExtCo = uniCloud.importObject("ext-storage-co");
const res = await uniCloudStorageExtCo.getTempFileURL({src: srcLst[i]});
console.log(res.fileList[0].tempFileURL)
srcLst[i] = res.fileList[0].tempFileURL
} else {
srcLst[i] = srcLst[i]
}
}
console.log(srcLst)
return srcLst;
},
}
@@ -15,6 +15,7 @@
</template>
<template v-slot:footer>
<image class="thumbnail" :src="data.thumbnail[0]" mode="aspectFill"></image>
</template>
</uni-list-item>
</template>
@@ -1,5 +1,5 @@
<template>
<view class="content">
<view class="content" :style="color">
<template v-for="op in content">
<render-text
v-if="op.type === 'paragraph'"
@@ -62,6 +62,10 @@ export default {
adConfig: {
type: Object,
default: {}
},
color: {
type: String,
default: "#333"
}
},
data() {
File diff suppressed because it is too large Load Diff
@@ -1,255 +0,0 @@
<template>
<unicloud-db v-slot:default="{loading, error, options}" :collection="collection" :options="formData"
:getone="true" :where="where" :manual="true" ref="detail" foreignKey="uni-cms-articles.user_id"
@load="loadData"
class="article">
<template v-if="!loading && articleData">
<view class="preview-tip">此页面仅用于临时预览文章,链接将会在短期内失效。</view>
<view class="meta">
<view class="title">
<text class="text">{{ articleData.title }}</text>
</view>
<view class="excerpt">
<text class="text">{{ articleData.excerpt }}</text>
</view>
<view class="author">
<template v-if="articleData.user_id && articleData.user_id[0]">
<text class="at">{{ articleData.user_id[0].nickname || '' }}</text>
<text class="split">·</text>
</template>
<text class="date">{{ publishTime(articleData.publish_date) }}</text>
</view>
</view>
<render-article-detail
:content="articleData.content"
:content-images="articleData.content_images"
:ad-config="{ adpId, watchAdUniqueType }"
></render-article-detail>
</template>
<view class="detail-loading" v-else>
<uni-icons type="spinner-cycle" size="35px"/>
</view>
</unicloud-db>
</template>
<script>
import uniNavBar from '@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue';
import renderArticleDetail from "@/uni_modules/uni-cms-article/components/render-article-detail/index.vue";
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
const db = uniCloud.database()
const articleDBName = 'uni-cms-articles'
const userDBName = 'uni-id-users'
export default {
components: {
uniNavBar,
renderArticleDetail
},
data() {
return {
id: "", // 文章ID
title: "", // 文章标题
secret: "", // 文章预览密钥
formData: {}, // 表单数据
articleData: null, // 文章数据
// 广告相关配置
adpId: "", // TODO: 请填写广告位ID
watchAdUniqueType: "device" // TODO: 观看广告的唯一标识类型,可选值为 user 或者 device,user 表示用户唯一,device 表示设备唯一
}
},
computed: {
where() {
//拼接where条件 查询条件 ,更多详见 :https://uniapp.dcloud.net.cn/uniCloud/unicloud-db?id=jsquery
return `_id =="${this.id}" && preview_secret =="${this.secret}"`
},
collection() {
return [
db.collection(articleDBName).where(this.where).field('user_id,thumbnail,excerpt,publish_date,title,content,preview_secret,preview_expired,article_status').getTemp(),
db.collection(userDBName).field('_id, nickname').getTemp()
]
}
},
onReady() {
// 开始加载数据,修改 where 条件后才开始去加载 clinetDB 的数据 ,需要等组件渲染完毕后才开始执行 loadData,所以不能再 onLoad 中执行
if (this.id) { // ID 不为空,则发起查询
this.$refs.detail.loadData()
} else {
uni.showToast({
icon: 'none',
title: 'id 不能为空'
})
}
},
onLoad(event) {
//获取文章id,通常 id 来自上一个页面
if (event.id) {
this.id = event.id
this.secret = event.secret
}
// 监听解锁内容事件
uni.$on('onUnlockContent', this.onUnlockContent)
},
onUnload() {
// 页面卸载时,移除监听事件
uni.$off('onUnlockContent', this.onUnlockContent)
},
onPageScroll(e) {
// 根据滚动位置判断是否显示导航栏
if (e.scrollTop > 100) {
uni.setNavigationBarTitle({
title: this.title
})
} else {
uni.setNavigationBarTitle({
title: ''
})
}
},
methods: {
// 将时间戳转换为可读的时间格式
publishTime(timestamp) {
return translatePublishTime(timestamp)
},
// 加载数据
loadData(data) {
if (!data) {
return uni.showModal({
content: "文章不存在/预览密钥不存在",
showCancel: false,
success: () => {
// #ifdef H5
window.close()
// #endif
// #ifndef H5
uni.navigateBack()
// #endif
}
})
}
// 文章已发布,跳转到文章详情页
if (data.article_status === 1) {
uni.showToast({
icon: 'none',
title: '文章已发布'
})
uni.redirectTo({
url: `/uni_modules/uni-cms-article/pages/detail/detail?id=${this.id}`
})
return
}
// 预览已过期,提示用户
if (data.preview_expired < Date.now()) {
return uni.showModal({
content: "预览已失效",
showCancel: false,
success: () => {
// #ifdef H5
window.close()
// #endif
// #ifndef H5
uni.navigateBack()
// #endif
}
})
}
// 设置文章标题
this.title = data.title
this.articleData = data
},
// 监听解锁内容事件,解锁内容后重新加载数据
async onUnlockContent() {
this.$refs.detail.loadData()
}
}
}
</script>
<style scoped lang="scss">
/* #ifdef APP-NVUE */
.article {
background-color: #fff;
}
/* #endif */
@mixin cp {
padding: 0 30rpx;
}
.detail-loading {
margin: 100rpx auto 0;
width: 35px;
height: 35px;
animation: rotate360 2s linear infinite;
}
@keyframes rotate360 {
0% {
transform: rotate(0deg);
transform-origin: center center;
}
100% {
transform: rotate(360deg);
transform-origin: center center;
}
}
.meta {
@include cp;
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;
}
}
}
.preview-tip {
font-size: 13px;
color: #333;
background: #fcd791;
padding: 10px;
}
</style>
@@ -122,7 +122,7 @@
refreshBox,
notCover,
rightSmallCover,
threeCover
threeCover,
},
computed: {
userInfo() {
@@ -180,6 +180,27 @@
.navBarHeight + 'px'; // 计算列表高度
},
methods: {
async getCloudImage(srcLst) {
for (let i = 0; i < srcLst.length ; i ++ ) {
if (srcLst[i]&&srcLst[i].substring(0, 8) == "cloud://") {
const res = await uniCloud.getTempFileURL({fileList: [srcLst[i]]});
console.log(res)
console.log(res.fileList.tempFileURL)
srcLst[i] = res.fileList[0].tempFileURL
} else if (srcLst[i]&&srcLst[i].substring(0, 8) == "qiniu://") {
console.log(srcLst[i])
const uniCloudStorageExtCo = uniCloud.importObject("ext-storage-co");
const res = await uniCloudStorageExtCo.getTempFileURL({src: srcLst[i]});
console.log(res.fileList[0].tempFileURL)
srcLst[i] = res.fileList[0].tempFileURL
} else {
srcLst[i] = srcLst[i]
}
}
return srcLst;
},
dialogConfirm() {
console.log('点击确认')
},
@@ -234,15 +255,22 @@
item.thumbnail = [item.thumbnail]
}
return item
})
// 处理腾讯云文件链接
for (const article of listData) {
const parseImages = await parseImageUrl(article.thumbnail)
const parseImages = await this.getCloudImage(article.thumbnail)
// const parseImages = await parseImageUrl(article.thumbnail)
console.log(parseImages)
article.thumbnail = parseImages ? parseImages.map(image => image.src) : []
article.thumbnail = parseImages;
}
console.log(listData)
this.listData = this.loadType === 'loadMore' ? this.listData.concat(listData) : listData
this.loadType = null
@@ -1,23 +0,0 @@
{
"uni-cms-unlock-record": {
"data": [],
"index": [
{
"IndexName": "unique_article_trans_",
"MgoKeySchema": {
"MgoIndexKeys": [{
"Name": "unique_id",
"Direction": "1"
},{
"Name": "article_id",
"Direction": "1"
},{
"Name": "trans_id",
"Direction": "1"
}],
"MgoIsUnique": false
}
}
]
}
}
@@ -196,6 +196,7 @@ module.exports = {
view_count: db.command.inc(1)
})
}
// 如果查询结果为空,则返回
if (!result.data || result.data.length <= 0) return
@@ -1,209 +1,236 @@
{
"bsonType": "object",
"required": ["user_id", "title", "content"],
"permission": {
"read": true,
"create": "auth.uid != null",
"update": "'admin' in auth.role || doc.user_id == auth.uid",
"delete": "'admin' in auth.role || doc.user_id == auth.uid"
"bsonType": "object",
"required": [
"user_id",
"title",
"content"
],
"permission": {
"read": true,
"create": "auth.uid != null",
"update": "'admin' in auth.role || doc.user_id == auth.uid",
"delete": "'admin' in auth.role || doc.user_id == auth.uid"
},
"properties": {
"_id": {
"description": "存储文档 ID(用户 ID),系统自动生成"
},
"user_id": {
"bsonType": "string",
"description": "文章作者ID, 参考`uni-id-users` 表",
"foreignKey": "uni-id-users._id",
"defaultValue": {
"$env": "uid"
}
},
"edit_type": {
"bsonType": "string",
"description": "编辑器类型(pc/mobile)"
},
"properties": {
"_id": {
"description": "存储文档 ID(用户 ID),系统自动生成"
},
"user_id": {
"bsonType": "string",
"description": "文章作者ID, 参考`uni-id-users` 表",
"foreignKey": "uni-id-users._id",
"defaultValue": {
"$env": "uid"
}
},
"category_id": {
"bsonType": "string",
"title": "分类",
"description": "分类 id,参考`uni-news-categories`表",
"foreignKey": "uni-cms-categories._id",
"enum": {
"collection": "uni-cms-categories",
"field": "name as text, _id as value"
}
},
"title": {
"bsonType": "string",
"title": "标题",
"description": "标题",
"label": "标题",
"trim": "both"
},
"content": {
"bsonType": "object",
"title": "文章内容",
"description": "文章内容; 格式为Quill编辑器的Delta格式",
"label": "文章内容"
},
"excerpt": {
"bsonType": "string",
"title": "文章摘录",
"description": "文章摘录",
"label": "摘要",
"trim": "both"
},
"article_status": {
"bsonType": "int",
"title": "文章状态",
"description": "文章状态:0 草稿箱 1 已发布",
"defaultValue": 0,
"enum": [{
"value": 0,
"text": "草稿箱"
},
{
"value": 1,
"text": "已发布"
}
]
},
"reply_count": {
"bsonType": "int",
"title": "回复数量",
"description": "回复数量",
"defaultValue": 0
},
"like_count": {
"bsonType": "int",
"title": "点赞数量",
"description": "点赞数量",
"defaultValue": 0,
"permission": {
"write": false
}
},
"collect_count": {
"bsonType": "int",
"title": "收藏数量",
"description": "收藏数量",
"defaultValue": 0,
"permission": {
"write": false
}
},
"gift_count": {
"bsonType": "int",
"title": "送礼数量",
"description": "送礼数量",
"defaultValue": 0,
"permission": {
"write": false
}
},
"view_count": {
"bsonType": "int",
"title": "阅读数量",
"description": "阅读数量",
"defaultValue": 0,
"permission": {
"write": false
}
},
"like_count": {
"bsonType": "int",
"title": "点赞数",
"description": "喜欢数、点赞数",
"defaultValue": 0,
"permission": {
"write": false
}
},
"is_sticky": {
"bsonType": "bool",
"title": "是否置顶",
"description": "是否置顶",
"permission": {
"write": false
}
},
"is_essence": {
"bsonType": "bool",
"title": "阅读加精",
"description": "阅读加精",
"permission": {
"write": false
}
},
"comment_status": {
"bsonType": "int",
"title": "开放评论",
"description": "评论状态:0 关闭 1 开放",
"enum": [{
"value": 0,
"text": "关闭"
},
{
"value": 1,
"text": "开放"
}
]
},
"comment_count": {
"bsonType": "int",
"description": "评论数量",
"permission": {
"write": false
}
},
"last_comment_user_id": {
"bsonType": "string",
"description": "最后回复用户 id,参考`uni-id-users` 表",
"foreignKey": "uni-id-users._id"
},
"thumbnail": {
"bsonType": "array",
"title": "封面大图",
"description": "缩略图地址",
"label": "封面大图",
"defaultValue": []
},
"publish_date": {
"bsonType": "timestamp",
"title": "发表时间",
"description": "发表时间",
"defaultValue": {
"$env": "now"
}
},
"publish_ip": {
"bsonType": "string",
"title": "发布文章时IP地址",
"description": "发表时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP"
}
},
"last_modify_date": {
"bsonType": "timestamp",
"title": "最后修改时间",
"description": "最后修改时间",
"defaultValue": {
"$env": "now"
}
},
"last_modify_ip": {
"bsonType": "string",
"description": "最后修改时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP"
}
},
"preview_secret": {
"bsonType": "string",
"description": "文章预览密钥"
},
"preview_expired": {
"bsonType": "timestamp",
"description": "文章预览过期时间"
}
}
}
"title_delta": {
"bsonType": "object",
"description": "标题html片段"
},
"p_type": {
"bsonType": "string",
"description": "兵种选择"
},
"temp_id": {
"bsonType": "string",
"description": "模板ID, 参考`cms-temp` 表",
"foreignKey": "cms-temp._id"
},
"music_url_id": {
"bsonType": "object",
"description": "音乐文件"
},
"category_id": {
"bsonType": "string",
"title": "分类",
"description": "分类 id,参考`uni-news-categories`表",
"foreignKey": "uni-cms-categories._id",
"enum": {
"collection": "uni-cms-categories",
"field": "name as text, _id as value"
}
},
"title": {
"bsonType": "string",
"title": "标题",
"description": "标题",
"label": "标题",
"trim": "both"
},
"title_html": {
"bsonType": "string",
"title": "标题html片段",
"description": "标题html片段",
"label": "标题html片段",
"trim": "both"
},
"cmsLst": {
"bsonType": "array",
"title": "文章内容列表"
},
"content": {
"bsonType": "object",
"title": "文章内容",
"description": "文章内容; 格式为Quill编辑器的Delta格式",
"label": "文章内容"
},
"excerpt": {
"bsonType": "string",
"title": "文章摘录",
"description": "文章摘录",
"label": "摘要",
"trim": "both"
},
"article_status": {
"bsonType": "int",
"title": "文章状态",
"description": "文章状态:0 草稿箱 1 已发布",
"defaultValue": 0,
"enum": [
{
"value": 0,
"text": "草稿箱"
},
{
"value": 1,
"text": "已发布"
}
]
},
"reply_count": {
"bsonType": "int",
"title": "回复数量",
"description": "回复数量",
"defaultValue": 0
},
"like_count": {
"bsonType": "int",
"title": "点赞数",
"description": "喜欢数、点赞数",
"defaultValue": 0,
"permission": {
"write": false
}
},
"collect_count": {
"bsonType": "int",
"title": "收藏数量",
"description": "收藏数量",
"defaultValue": 0,
"permission": {
"write": false
}
},
"gift_count": {
"bsonType": "int",
"title": "送礼数量",
"description": "送礼数量",
"defaultValue": 0,
"permission": {
"write": false
}
},
"view_count": {
"bsonType": "int",
"title": "阅读数量",
"description": "阅读数量",
"defaultValue": 0,
"permission": {
"write": false
}
},
"is_sticky": {
"bsonType": "bool",
"title": "是否置顶",
"description": "是否置顶",
"permission": {
"write": false
}
},
"is_essence": {
"bsonType": "bool",
"title": "阅读加精",
"description": "阅读加精",
"permission": {
"write": false
}
},
"comment_status": {
"bsonType": "int",
"title": "开放评论",
"description": "评论状态:0 关闭 1 开放",
"enum": [
{
"value": 0,
"text": "关闭"
},
{
"value": 1,
"text": "开放"
}
]
},
"comment_count": {
"bsonType": "int",
"description": "评论数量",
"permission": {
"write": false
}
},
"last_comment_user_id": {
"bsonType": "string",
"description": "最后回复用户 id,参考`uni-id-users` 表",
"foreignKey": "uni-id-users._id"
},
"thumbnail": {
"bsonType": "array",
"title": "封面大图",
"description": "缩略图地址",
"label": "封面大图",
"defaultValue": []
},
"publish_date": {
"bsonType": "timestamp",
"title": "发表时间",
"description": "发表时间",
"defaultValue": {
"$env": "now"
}
},
"publish_ip": {
"bsonType": "string",
"title": "发布文章时IP地址",
"description": "发表时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP"
}
},
"last_modify_date": {
"bsonType": "timestamp",
"title": "最后修改时间",
"description": "最后修改时间",
"defaultValue": {
"$env": "now"
}
},
"last_modify_ip": {
"bsonType": "string",
"description": "最后修改时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP"
}
},
"preview_secret": {
"bsonType": "string",
"description": "文章预览密钥"
},
"preview_expired": {
"bsonType": "timestamp",
"description": "文章预览过期时间"
}
}
}