Compare commits
No commits in common. "9f7e43a21a9b3d3cb3a3d22448d00ab31fcb1a68" and "353d8e006941c6ef8ad97d5767031424b6ab0deb" have entirely different histories.
9f7e43a21a
...
353d8e0069
|
|
@ -47,16 +47,6 @@
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="vg-compose-remove-btn" @click.stop="removeItem(item)">×</button>
|
<button type="button" class="vg-compose-remove-btn" @click.stop="removeItem(item)">×</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
v-if="mediaList.length < maxMediaCount"
|
|
||||||
class="vg-compose-media-item vg-compose-media-item--tile vg-compose-add-tile"
|
|
||||||
@click="onReferenceEmptyAreaClick"
|
|
||||||
:title="`还可以继续上传,最多 ${maxMediaCount} 张`">
|
|
||||||
<div class="vg-compose-media-preview vg-compose-add-preview">
|
|
||||||
<div class="vg-compose-add-icon">+</div>
|
|
||||||
<div class="vg-compose-add-text">继续上传</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="vg-mod-foot muted">{{ mediaList.length }}/{{ maxMediaCount }}</div>
|
<div class="vg-mod-foot muted">{{ mediaList.length }}/{{ maxMediaCount }}</div>
|
||||||
|
|
@ -687,12 +677,12 @@ const confirmPickAssets = () => {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const remain = props.maxMediaCount - mediaList.value.length
|
const remain = props.maxMediaCount - mediaList.value.length
|
||||||
if (remain <= 0) {
|
if (remain <= 0 && !isReferenceMode) {
|
||||||
Message.warning(`最多添加 ${props.maxMediaCount} 个参考素材`)
|
Message.warning(`最多添加 ${props.maxMediaCount} 个参考素材`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const selected = files.slice(0, remain)
|
const selected = files.slice(0, remain || files.length)
|
||||||
const uploadingEntries = []
|
const uploadingEntries = []
|
||||||
|
|
||||||
for (const file of selected) {
|
for (const file of selected) {
|
||||||
|
|
@ -1997,38 +1987,6 @@ defineExpose({
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-compose-add-tile {
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px dashed rgba(0, 202, 224, 0.45);
|
|
||||||
background: rgba(0, 202, 224, 0.06);
|
|
||||||
transition: all 0.15s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-compose-add-tile:hover {
|
|
||||||
border-color: rgba(0, 202, 224, 0.75);
|
|
||||||
background: rgba(0, 202, 224, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-compose-add-preview {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-compose-add-icon {
|
|
||||||
font-size: 24px;
|
|
||||||
color: rgba(0, 202, 224, 0.75);
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-compose-add-text {
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(255, 255, 255, 0.65);
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-compose-media-preview {
|
.vg-compose-media-preview {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
@ -2084,8 +2042,7 @@ defineExpose({
|
||||||
padding: 8px 10px 10px;
|
padding: 8px 10px 10px;
|
||||||
background: rgba(0, 0, 0, 0.18);
|
background: rgba(0, 0, 0, 0.18);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
/* @候选面板 absolute 需要溢出显示;否则会被父级裁切 */
|
overflow: hidden;
|
||||||
overflow: visible;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-compose-right-body {
|
.vg-compose-right-body {
|
||||||
|
|
@ -2122,8 +2079,7 @@ defineExpose({
|
||||||
flex: 1 1 0%;
|
flex: 1 1 0%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
/* @候选面板为 absolute,会在内容较多时溢出裁切;需要显示完整 */
|
overflow: hidden;
|
||||||
overflow: visible;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
@ -2235,6 +2191,7 @@ defineExpose({
|
||||||
max-height: 72px;
|
max-height: 72px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
vertical-align: middle;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2245,6 +2202,7 @@ defineExpose({
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-rich-editor :deep(.vg-inline-ref-audio) {
|
.vg-rich-editor :deep(.vg-inline-ref-audio) {
|
||||||
|
|
@ -2290,17 +2248,14 @@ defineExpose({
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 8px;
|
left: 8px;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
top: 8px;
|
|
||||||
bottom: 8px;
|
bottom: 8px;
|
||||||
/* 高度与富文本框一致;内容超出时内部滚动 */
|
max-height: 180px;
|
||||||
max-height: none;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background: rgba(22, 24, 30, 0.98);
|
background: rgba(22, 24, 30, 0.98);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
|
||||||
/* 层级要足够高,避免 @候选面板在参考图模式下被上层区域遮挡 */
|
z-index: 20;
|
||||||
z-index: 99999;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-mention-item {
|
.vg-mention-item {
|
||||||
|
|
|
||||||
|
|
@ -182,28 +182,7 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="上传文件" required>
|
<a-form-item label="上传文件" required>
|
||||||
<div
|
<input class="asset-file-input" type="file" @change="onFileChange" />
|
||||||
class="asset-file-dropzone"
|
|
||||||
:class="{ 'asset-file-dropzone--dragover': createUploadDragOver }"
|
|
||||||
@click="triggerCreateFilePicker"
|
|
||||||
@dragenter.prevent="onCreateUploadDragEnter"
|
|
||||||
@dragover.prevent="onCreateUploadDragOver"
|
|
||||||
@dragleave.prevent="onCreateUploadDragLeave"
|
|
||||||
@drop.prevent="onCreateUploadDrop">
|
|
||||||
<input
|
|
||||||
ref="createAssetFileInput"
|
|
||||||
class="asset-file-input"
|
|
||||||
type="file"
|
|
||||||
style="display: none"
|
|
||||||
@change="onFileChange" />
|
|
||||||
<div class="asset-file-dropzone-content">
|
|
||||||
<div class="asset-file-dropzone-icon">+</div>
|
|
||||||
<div class="asset-file-dropzone-text">点击选择或拖拽上传</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="createForm.previewUrl && createForm.assetType === 'Image'" class="asset-file-preview">
|
|
||||||
<img :src="createForm.previewUrl" alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="asset-file-hint">{{ createForm.fileName || '未选择文件' }}</div>
|
<div class="asset-file-hint">{{ createForm.fileName || '未选择文件' }}</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="素材名称">
|
<a-form-item label="素材名称">
|
||||||
|
|
@ -258,12 +237,9 @@ export default {
|
||||||
groupId: '',
|
groupId: '',
|
||||||
file: null,
|
file: null,
|
||||||
fileName: '',
|
fileName: '',
|
||||||
previewUrl: '',
|
|
||||||
localPreviewUrl: '',
|
|
||||||
name: '',
|
name: '',
|
||||||
assetType: 'Image'
|
assetType: 'Image'
|
||||||
},
|
},
|
||||||
createUploadDragOver: false,
|
|
||||||
filters: {
|
filters: {
|
||||||
groupId: '',
|
groupId: '',
|
||||||
name: '',
|
name: '',
|
||||||
|
|
@ -289,40 +265,7 @@ export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadGroups()
|
this.loadGroups()
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
createAssetVisible(val) {
|
|
||||||
if (!val) this.clearCreateUploadPreview()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
clearCreateUploadPreview() {
|
|
||||||
if (this.createForm?.localPreviewUrl) {
|
|
||||||
try {
|
|
||||||
URL.revokeObjectURL(this.createForm.localPreviewUrl)
|
|
||||||
} catch (_) {}
|
|
||||||
}
|
|
||||||
this.createForm.previewUrl = ''
|
|
||||||
this.createForm.localPreviewUrl = ''
|
|
||||||
},
|
|
||||||
setCreateFormFile(file) {
|
|
||||||
this.createForm.file = file || null
|
|
||||||
this.createForm.fileName = file?.name || ''
|
|
||||||
|
|
||||||
const mime = String(file?.type || '').toLowerCase()
|
|
||||||
// 根据文件类型自动设置素材类型,避免与文件不匹配
|
|
||||||
if (mime.startsWith('image/')) this.createForm.assetType = 'Image'
|
|
||||||
else if (mime.startsWith('video/')) this.createForm.assetType = 'Video'
|
|
||||||
else if (mime.startsWith('audio/')) this.createForm.assetType = 'Audio'
|
|
||||||
|
|
||||||
// 图片预览
|
|
||||||
this.clearCreateUploadPreview()
|
|
||||||
if (mime.startsWith('image/')) {
|
|
||||||
try {
|
|
||||||
this.createForm.localPreviewUrl = URL.createObjectURL(file)
|
|
||||||
this.createForm.previewUrl = this.createForm.localPreviewUrl
|
|
||||||
} catch (_) {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formatAssetTypeLabel(it) {
|
formatAssetTypeLabel(it) {
|
||||||
const t = String(it?.AssetType || it?.assetType || '').trim()
|
const t = String(it?.AssetType || it?.assetType || '').trim()
|
||||||
if (!t) return '-'
|
if (!t) return '-'
|
||||||
|
|
@ -390,7 +333,6 @@ export default {
|
||||||
this.createForm.fileName = ''
|
this.createForm.fileName = ''
|
||||||
this.createForm.name = ''
|
this.createForm.name = ''
|
||||||
this.createForm.assetType = 'Image'
|
this.createForm.assetType = 'Image'
|
||||||
this.clearCreateUploadPreview()
|
|
||||||
this.createAssetVisible = true
|
this.createAssetVisible = true
|
||||||
},
|
},
|
||||||
async loadGroups() {
|
async loadGroups() {
|
||||||
|
|
@ -428,28 +370,10 @@ export default {
|
||||||
this.createForm.groupId = gid
|
this.createForm.groupId = gid
|
||||||
this.searchAssets(1)
|
this.searchAssets(1)
|
||||||
},
|
},
|
||||||
triggerCreateFilePicker() {
|
|
||||||
const el = this.$refs.createAssetFileInput
|
|
||||||
if (el && typeof el.click === 'function') el.click()
|
|
||||||
},
|
|
||||||
onCreateUploadDragEnter() {
|
|
||||||
this.createUploadDragOver = true
|
|
||||||
},
|
|
||||||
onCreateUploadDragOver() {
|
|
||||||
this.createUploadDragOver = true
|
|
||||||
},
|
|
||||||
onCreateUploadDragLeave() {
|
|
||||||
this.createUploadDragOver = false
|
|
||||||
},
|
|
||||||
onCreateUploadDrop(e) {
|
|
||||||
this.createUploadDragOver = false
|
|
||||||
const file = e?.dataTransfer?.files?.[0]
|
|
||||||
if (!file) return
|
|
||||||
this.setCreateFormFile(file)
|
|
||||||
},
|
|
||||||
onFileChange(e) {
|
onFileChange(e) {
|
||||||
const file = e?.target?.files?.[0]
|
const file = e?.target?.files?.[0]
|
||||||
this.setCreateFormFile(file)
|
this.createForm.file = file || null
|
||||||
|
this.createForm.fileName = file?.name || ''
|
||||||
},
|
},
|
||||||
async createAsset() {
|
async createAsset() {
|
||||||
const groupId = String(this.createForm.groupId || '').trim()
|
const groupId = String(this.createForm.groupId || '').trim()
|
||||||
|
|
@ -466,12 +390,6 @@ export default {
|
||||||
const uploadUrl = extractUploadUrlFromResponse(uploadRes)
|
const uploadUrl = extractUploadUrlFromResponse(uploadRes)
|
||||||
if (!uploadUrl) throw new Error(uploadRes?.msg || '上传后未返回文件地址')
|
if (!uploadUrl) throw new Error(uploadRes?.msg || '上传后未返回文件地址')
|
||||||
|
|
||||||
// 图片上传成功后,在上传组件展示远程预览(替换本地预览)
|
|
||||||
if (this.createForm.assetType === 'Image') {
|
|
||||||
this.clearCreateUploadPreview()
|
|
||||||
this.createForm.previewUrl = uploadUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) 再通过 /api/byteAsset/createAsset(JSON) 用 url 创建素材
|
// 2) 再通过 /api/byteAsset/createAsset(JSON) 用 url 创建素材
|
||||||
const res = await this.$axios({
|
const res = await this.$axios({
|
||||||
url: ASSET_CREATE_API,
|
url: ASSET_CREATE_API,
|
||||||
|
|
@ -484,18 +402,11 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
this.$message.success(this.createForm.assetType === 'Image' ? '上传图片成功' : '上传成功')
|
this.$message.success('新增素材成功')
|
||||||
this.createForm.file = null
|
this.createForm.file = null
|
||||||
|
this.createForm.fileName = ''
|
||||||
this.createForm.name = ''
|
this.createForm.name = ''
|
||||||
const isImage = this.createForm.assetType === 'Image'
|
this.createAssetVisible = false
|
||||||
if (isImage) {
|
|
||||||
// 图片模式下延迟关闭,避免用户来不及看到上传组件缩略图
|
|
||||||
setTimeout(() => {
|
|
||||||
this.createAssetVisible = false
|
|
||||||
}, 500)
|
|
||||||
} else {
|
|
||||||
this.createAssetVisible = false
|
|
||||||
}
|
|
||||||
this.searchAssets(1)
|
this.searchAssets(1)
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(res.msg || '新增素材失败')
|
this.$message.error(res.msg || '新增素材失败')
|
||||||
|
|
@ -861,68 +772,6 @@ export default {
|
||||||
color: rgba(255, 255, 255, 0.88);
|
color: rgba(255, 255, 255, 0.88);
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-file-dropzone {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
min-height: 38px;
|
|
||||||
padding: 10px 12px;
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 1px dashed rgba(255, 255, 255, 0.18);
|
|
||||||
background: rgba(0, 0, 0, 0.18);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.15s ease-in-out;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-file-dropzone--dragover {
|
|
||||||
border-color: rgba(0, 202, 224, 0.65);
|
|
||||||
background: rgba(0, 202, 224, 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-file-dropzone-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-file-dropzone-icon {
|
|
||||||
width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid rgba(0, 202, 224, 0.35);
|
|
||||||
background: rgba(0, 202, 224, 0.08);
|
|
||||||
color: rgba(0, 202, 224, 0.8);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 18px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-file-dropzone-text {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-file-preview {
|
|
||||||
margin-top: 10px;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 160px;
|
|
||||||
border-radius: 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
||||||
background: rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-file-preview img {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-file-hint {
|
.asset-file-hint {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
|
||||||
|
|
@ -1081,12 +1081,9 @@ export default {
|
||||||
}
|
}
|
||||||
params.text = first.text || text
|
params.text = first.text || text
|
||||||
params.content = contentItems
|
params.content = contentItems
|
||||||
// 后端要求:reference_url 需要使用资产标识(asset://assetId)时优先传 asset://
|
const firstPreview = attachments.find((x) => x?.mediaType === 'image' && /^https?:\/\//i.test(String(x?.url || '')))
|
||||||
// 展示用仍然可以是 https url,但提交 content/reference_url 要与 assetId 关联。
|
|
||||||
const firstPreview = attachments.find((x) => x?.mediaType === 'image')
|
|
||||||
if (firstPreview) {
|
if (firstPreview) {
|
||||||
const aid = String(firstPreview?.assetId || '').trim()
|
params.referenceUrl = firstPreview.url
|
||||||
params.referenceUrl = aid ? `asset://${aid}` : firstPreview.url
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue