feat: 打通 HBuilderX CLI 构建 + 修复文章闭环静态盲区
构建: - 新增 tools/build.js:junction HBuilderX 工具链,CLI 构建 h5/mp-weixin - vue 指向补丁版 @dcloudio/uni-h5-vue(官方 npm vue 不导出 isInSSRComponentSetup) - 设 HX_APP_ROOT 避免退化成 H5 空壳产物;产物完整性校验 校验工具: - 新增 check-cloud-methods.js:acorn 解析云对象方法,比对 94 处调用点 - 新增 check-android-contract.js:Kotlin 侧云对象契约校验 - audit-project.js 修 downloadFile 误报(注释未剥离);tools/ 排除出扫描 - package.json 声明此前隐式依赖的 acorn 功能: - 补 uni-cms-articles.getPublishedArticles(安卓端依赖但此前不存在) - 修 u-parse <audio> 引用已移除组件导致 H5 构建失败
This commit is contained in:
@@ -45,8 +45,9 @@ export default {
|
||||
this.className
|
||||
]
|
||||
},
|
||||
styles () {
|
||||
let style = this.data.data.style
|
||||
styles () {
|
||||
let style = this.data?.data?.style || ''
|
||||
|
||||
|
||||
if (this.width) {
|
||||
style += `;width:${this.width}px`
|
||||
@@ -61,14 +62,16 @@ export default {
|
||||
this.loadImagePath()
|
||||
},
|
||||
methods: {
|
||||
async loadImagePath () {
|
||||
const parseImages = await parseImageUrl({
|
||||
insert: {image: this.data.data.value},
|
||||
attributes: this.data.data.attributes,
|
||||
}, "editor")
|
||||
async loadImagePath () {
|
||||
const value = this.data?.data?.value || ''
|
||||
if (!value) return
|
||||
const parseImages = await parseImageUrl({
|
||||
insert: {image: value},
|
||||
attributes: this.data?.data?.attributes || {},
|
||||
}, "editor")
|
||||
|
||||
this.imagePath = parseImages[0].src
|
||||
},
|
||||
this.imagePath = parseImages?.[0]?.src || ''
|
||||
},
|
||||
imagePreview () {
|
||||
uni.$emit('imagePreview', this.data.data.value)
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view class="content" :style="color">
|
||||
<template v-for="op in content">
|
||||
<view class="content" :style="{ color }">
|
||||
<template v-for="(op, index) in content" :key="index">
|
||||
<render-text
|
||||
v-if="op.type === 'paragraph'"
|
||||
:data="op.data"
|
||||
@@ -8,7 +8,7 @@
|
||||
:style="op.style"
|
||||
></render-text>
|
||||
<render-image
|
||||
v-else-if="op.type === 'image' && op.data.length > 0"
|
||||
v-else-if="op.type === 'image' && Array.isArray(op.data) && op.data.length > 0"
|
||||
:data="op.data[0]"
|
||||
:className="op.class"
|
||||
:style="op.style"
|
||||
@@ -83,16 +83,9 @@ export default {
|
||||
mounted() {
|
||||
this.initImage()
|
||||
},
|
||||
// #ifdef VUE2
|
||||
beforeDestroy() {
|
||||
uni.$off('imagePreview')
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
beforeUnmount () {
|
||||
uni.$off('imagePreview')
|
||||
},
|
||||
// #endif
|
||||
beforeUnmount () {
|
||||
uni.$off('imagePreview', this.imagePreview)
|
||||
},
|
||||
methods: {
|
||||
// 初始化图片
|
||||
async initImage() {
|
||||
@@ -104,7 +97,8 @@ export default {
|
||||
}
|
||||
|
||||
// 监听图片预览
|
||||
uni.$on('imagePreview', this.imagePreview)
|
||||
uni.$off('imagePreview', this.imagePreview)
|
||||
uni.$on('imagePreview', this.imagePreview)
|
||||
},
|
||||
// 点击图片预览
|
||||
imagePreview(src) {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<template>
|
||||
<view :class="['list', data.type]">
|
||||
<view class="list-item" v-for="(item, index) in data.items">
|
||||
<text class="dot">{{data.type === 'ordered' ? `${index + 1}.` : '•'}}</text>
|
||||
<render-text :data="item.data" reset class="reset-default"></render-text>
|
||||
<view class="list-item" v-for="(item, index) in (data.items || [])" :key="index">
|
||||
<text class="dot">{{data.type === 'ordered' ? `${index + 1}.` : '•'}}</text>
|
||||
<view class="item-content">
|
||||
<render-text :data="item.data || []" reset class="reset-default"></render-text>
|
||||
<render-list v-if="item.children" :data="item.children"></render-list>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<view class="video">
|
||||
<video
|
||||
class="v"
|
||||
:src="data.attributes.src"
|
||||
:poster="data.attributes.poster"
|
||||
:src="data.value || data.attributes?.src || ''"
|
||||
:poster="data.attributes?.poster || ''"
|
||||
></video>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -34,8 +34,11 @@
|
||||
|
||||
</view>
|
||||
|
||||
<view class="meta">
|
||||
<view class="author">
|
||||
<view class="meta">
|
||||
<view class="title" v-if="data.title_html || data.title">
|
||||
<u-parse :content="data.title_html || data.title"></u-parse>
|
||||
</view>
|
||||
<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>
|
||||
@@ -49,16 +52,16 @@
|
||||
<view class="" v-if="data.edit_type === 'mobile'">
|
||||
|
||||
|
||||
<view class="" v-for="(item, index) in data.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;">
|
||||
<view class="" v-for="(item, index) in (data.cmsLst || [])" :key="index">
|
||||
<u-parse :content="item.html || item.text || ''" v-if="item.type === 'text' || item.type === 'title'">
|
||||
</u-parse>
|
||||
<view class="" v-if="item.type === 'image'"
|
||||
style="width: 100vw;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;">
|
||||
style="width: 100vw;margin-top: 30rpx;margin-bottom: 30rpx;">
|
||||
<!-- <cloud-image
|
||||
width="100%"
|
||||
height="500rpx"
|
||||
@@ -220,7 +223,7 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<render-article-detail :content="data.content" :color="color" :content-images="data.content_images"
|
||||
<render-article-detail :content="data.content" :color="temp.font_color || '#333'" :content-images="data.content_images"
|
||||
:ad-config="{ adpId, watchAdUniqueType }"></render-article-detail>
|
||||
</view>
|
||||
|
||||
@@ -527,7 +530,12 @@
|
||||
const nowMonths = (date.getUTCFullYear() - 1970) * 12 + date.getUTCMonth() + 1;
|
||||
|
||||
console.log(nowMonths);
|
||||
const audioContext = wx.createInnerAudioContext()
|
||||
// #ifdef MP-WEIXIN
|
||||
const audioContext = wx.createInnerAudioContext()
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
const audioContext = null
|
||||
// #endif
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -803,7 +811,7 @@
|
||||
const res = await uniCloud.importObject("article_info").isSelectVote(query);
|
||||
console.log(res);
|
||||
if (res.code === 200) {
|
||||
this.$set(this.isSelectVoteValue, vote_id, res.isSelectVote);
|
||||
this.isSelectVoteValue[vote_id] = res.isSelectVote;
|
||||
}
|
||||
},
|
||||
isExpired(voteEndTime) {
|
||||
@@ -1255,34 +1263,33 @@
|
||||
|
||||
|
||||
},
|
||||
async getMusicUrl() {
|
||||
console.log(this.detail_music);
|
||||
if (!this.detail_music) {
|
||||
return
|
||||
}
|
||||
const url = await uniCloud.getTempFileURL({
|
||||
fileList: [this.detail_music.music_url_id]
|
||||
});
|
||||
const musicPath = url.fileList[0].tempFileURL
|
||||
audioContext['src'] = musicPath
|
||||
if (this.isPlay && audioContext['src']) {
|
||||
async getMusicUrl() {
|
||||
if (!audioContext || !this.detail_music) return
|
||||
const musicId = typeof this.detail_music === 'string'
|
||||
? this.detail_music
|
||||
: (this.detail_music.music_url_id || this.detail_music.src || '')
|
||||
if (!musicId) return
|
||||
const url = await uniCloud.getTempFileURL({ fileList: [musicId] })
|
||||
const musicPath = url.fileList?.[0]?.tempFileURL
|
||||
if (!musicPath) return
|
||||
audioContext.src = musicPath
|
||||
if (this.isPlay) audioContext.play()
|
||||
},
|
||||
onPlay() {
|
||||
if (!audioContext) return
|
||||
if (this.isPlay) {
|
||||
this.onStop()
|
||||
return
|
||||
}
|
||||
this.isPlay = true
|
||||
audioContext.play()
|
||||
}
|
||||
},
|
||||
onPlay() {
|
||||
if (this.isPlay) {
|
||||
this.onStop()
|
||||
return
|
||||
}
|
||||
this.isPlay = true
|
||||
console.log(audioContext);
|
||||
audioContext.play()
|
||||
},
|
||||
onStop() {
|
||||
audioContext.pause();
|
||||
audioContext.stop()
|
||||
this.isPlay = false
|
||||
},
|
||||
},
|
||||
onStop() {
|
||||
if (!audioContext) return
|
||||
audioContext.pause()
|
||||
audioContext.stop()
|
||||
this.isPlay = false
|
||||
},
|
||||
|
||||
async onUnlockContent() {
|
||||
this.$refs.detail.loadData()
|
||||
@@ -2446,8 +2453,8 @@
|
||||
|
||||
.cms-body {
|
||||
display: flex;
|
||||
min-height: 60hv;
|
||||
width: 100wv;
|
||||
min-height: 60vh;
|
||||
width: 100vw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,14 @@
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<!-- 音频 -->
|
||||
<audio v-else-if="n.name=='audio'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
|
||||
<!--
|
||||
原实现用的是 <audio> 内置组件,但新版 uni-h5 已移除该组件导出
|
||||
(@dcloudio/uni-h5 不再 export Audio),H5 端编译会直接失败在
|
||||
"Audio is not exported by uni-h5.es.js"。
|
||||
改为普通 view 承载:保留 id/class/style 以维持排版,
|
||||
音频源由父级逻辑按需处理,不再依赖已删除的组件。
|
||||
-->
|
||||
<view v-else-if="n.name=='audio'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :data-i="i" />
|
||||
<!-- #endif -->
|
||||
<view v-else-if="(n.name=='table'&&n.c)||n.name=='li'" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.attrs.style">
|
||||
<node v-if="n.name=='li'" :childs="n.children" :opts="opts" />
|
||||
|
||||
Reference in New Issue
Block a user