Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 共享到商店侧栏接口、交互调整 --story=121000017 #7655

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion frontend/desktop/src/config/i18n/cn.js
Original file line number Diff line number Diff line change
Expand Up @@ -1828,7 +1828,9 @@ const cn = {
'场景名称重复:': '场景名称重复:',
'场景名称长度最小3个字符': '场景名称长度最小3个字符',
'请输入群 ID,多个 ID 以分号隔开': '请输入群 ID,多个 ID 以分号隔开',
'当前环境配置周期任务间隔不低于 n 分钟,如有特殊需求请联系管理员配置': '当前环境配置周期任务间隔不低于 {n} 分钟,如有特殊需求请联系管理员配置'
'当前环境配置周期任务间隔不低于 n 分钟,如有特殊需求请联系管理员配置': '当前环境配置周期任务间隔不低于 {n} 分钟,如有特殊需求请联系管理员配置',
'仅支持上传.mp4,.mov文件': '仅支持上传.mp4,.mov文件',
'选择视频文件': '选择视频文件'
}

export default cn
4 changes: 3 additions & 1 deletion frontend/desktop/src/config/i18n/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -1862,7 +1862,9 @@ const en = {
'场景名称重复:': 'Duplicate scene name:',
'场景名称长度最小3个字符': 'The scene name must be at least 3 characters long',
'请输入群 ID,多个 ID 以分号隔开': 'Please enter group IDs, separated by semicolons if there are multiple IDs',
'当前环境配置周期任务间隔不低于 n 分钟,如有特殊需求请联系管理员配置': 'In the current environment, the interval for scheduled tasks is no less than {n} minutes. If you have special requirements, please contact the administrator for configuration'
'当前环境配置周期任务间隔不低于 n 分钟,如有特殊需求请联系管理员配置': 'In the current environment, the interval for scheduled tasks is no less than {n} minutes. If you have special requirements, please contact the administrator for configuration',
'仅支持上传.mp4,.mov文件': 'Only .mp4 and .mov files are supported for upload',
'选择视频文件': 'Select video file'
}

export default en
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
:name="option.name">
</bk-option>
</bk-select>
<p v-if="repeatSceneInfo.scene_id" class="scene-repeat-tips">
<p v-if="repeatSceneInfo.url" class="scene-repeat-tips">
<span>{{ $t('场景名称重复:') }}</span>
<a target="_blank" :href="repeatSceneInfo.url">
{{ repeatSceneInfo.scene_name }}
Expand Down Expand Up @@ -151,14 +151,25 @@
project_id: [String, Number]
},
data () {
const defaultEditorContent = [
'## 1. 背景',
'*为什么要开发这个场景*',
'## 2. 适用场景',
'*这个场景解决什么问题*',
'## 3.使用流程',
'### 3.1 前置条件',
'*如有*',
'### 3.2 xxx',
'## 4. FAQ'
]
const formData = {
id: undefined,
type: 'create',
name: '',
category: '',
labels: [],
risk_level: '',
usage_content: { content: '' }
usage_content: { content: defaultEditorContent.join('\n\n') }
}
return {
formData: tools.deepClone(formData),
Expand Down Expand Up @@ -224,8 +235,8 @@
this.loadMarkedRiskLevel()
])
this.categoryList = resp1.data
this.tagList = resp2.data.results
this.riskLevelList = resp3.data.results
this.tagList = resp2.data
this.riskLevelList = resp3.data
} catch (error) {
console.warn(error)
} finally {
Expand Down Expand Up @@ -272,7 +283,7 @@
try {
this.recordLoading = true
const resp = await this.loadSharedTemplateRecord()
this.recordList = resp.data.data
this.recordList = resp.data
} catch (error) {
console.warn(error)
} finally {
Expand Down Expand Up @@ -336,10 +347,12 @@
params.templates = [...new Set(selectedTplIds)]

const resp = await this.sharedTemplateRecord(params)
if (!resp.result) {
this.repeatSceneInfo = resp.data
return
this.repeatSceneInfo = {
...resp.data,
result: resp.result
}
if (!resp.result) return

this.showSuccessMessage()
this.$emit('close')
} catch (error) {
Expand All @@ -357,7 +370,9 @@
tag: 'div'
},
on: {
click: this.jumpSreStore
click: () => {
window.open(this.repeatSceneInfo.scene_url, '_target')
}
}
}, [
h('span', {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
<template>
<div class="editorContainer">
<div :id="randomId" ref="editorRef"></div>
<div :id="randomId" ref="editorRef" style="height: 100%"></div>
<div ref="uploadVideoBtn" v-show="editor">
<bk-popover
ref="uploadPop"
width="450"
:is-show="isShow"
theme="light"
trigger="click"
@after-hidden="isShow = $event"
>
<span class="uploadVideoBtn common-icon-play"></span>
<template #content>
<div style="padding-bottom: 40px">
<div style="font-weight: 600; color: #555; display: block; margin: 20px 0 5px">
{{ $t('选择视频文件') }}
</div>
<videoUpload ref="videoInputRef" :scene-type="sceneType"></videoUpload>
<div style="position: absolute; right: 40px; bottom: 20px">
<bk-button theme="primary" size="small" @click="uploadFile">{{ $t('确认') }}</bk-button>
<bk-button size="small" @click="toggleIsShow(false)">{{ $t('取消') }}</bk-button>
</div>
</div>
</template>
</bk-popover>
</div>
</div>
</template>
<script>
import Editor from '@toast-ui/editor'
import { mapActions } from 'vuex'
import axios from 'axios'
import VideoUpload from './videoUpload.vue'

export default {
components: {
VideoUpload
},
model: {
prop: 'value',
event: 'change'
Expand All @@ -27,7 +54,8 @@
return {
randomId: `editor${(Math.random() * 100000).toFixed(0)}`,
editor: null,
timer: null
timer: null,
isShow: false
}
},
computed: {
Expand All @@ -47,13 +75,24 @@
},
mounted () {
setTimeout(() => {
const videoTool = {
name: '上传视频',
el: this.$refs.uploadVideoBtn,
tooltip: 'Insert Video'
}
const editorRef = this.$refs.editorRef
this.editor = new Editor({
el: this.$refs.editorRef,
height: '336px',
el: editorRef,
height: Math.max(editorRef.clientHeight, 450).toString() + 'px',
initialEditType: 'markdown',
previewStyle: 'tab',
initialValue: this.value,
hideModeSwitch: true
plugins: [this.getVideoPlugins],
toolbarItems: [
['heading', 'bold', 'italic'],
['quote', 'ul', 'ol'],
['image', videoTool, 'table', 'link', 'codeblock']
]
})
this.editor.addHook('addImageBlobHook', this.handleFileUpload)
this.editor.on('change', () => {
Expand All @@ -64,32 +103,86 @@
},
methods: {
...mapActions('templateMarket/', [
'getFileUploadAddr'
'getFileUploadAddr',
'uploadFileToUrl'
]),
getVideoPlugins () {
const toHTMLRenderers = {
video (node) {
const src = node.literal.replaceAll('\\', '')
return [
{
type: 'openTag',
tagName: 'video',
attributes: {
controls: true,
src,
class: 'markdownVideo'
},
outerNewLine: true
},
{ type: 'closeTag', tagName: 'video', outerNewLine: true }
]
}
}
return { toHTMLRenderers }
},
async handleFileUpload (blob, cb) {
try {
// 这里补充上传图片逻辑并将url通过cb传回
const resp = await this.getFileUploadAddr({
file_name: blob.name,
file_name: blob.name.replaceAll(' ', ''),
scene_type: this.sceneType
})
await axios({
url: resp.upload_url,
method: 'put',
data: blob, // 直接将 File 对象作为请求体
withCredentials: false,
headers: {
'content-Type': blob.type // 使用文件本身的类型
// 如果需要添加额外的请求头,可以在这里添加
// 'Authorization': 'Bearer your-token',
}
await this.uploadFileToUrl({
upload_url: resp.upload_url,
blob
})
cb(resp.download_url)
} catch (error) {
console.warn(error)
}
},
async uploadFile () {
const url = await this.$refs.videoInputRef.uploadFiles()
if (url) {
const content = ['\n', '$$video', `${url}`, '$$', ''].join('\n')
this.editor.replaceSelection(content)
}
this.isShow = false
this.$refs.uploadPop.hideHandler()
return true
},
toggleIsShow (val) {
this.isShow = val
if (val) {
this.$refs.uploadPop.showHandler()
} else {
this.$refs.uploadPop.hideHandler()
}
}
}
}

</script>
<style lang="scss" scoped>
/deep/.markdownVideo {
width: 100%;
}
.editorContainer {
height: 100%;
}
.uploadVideoBtn {
display: flex;
height: 32px;
width: 32px;
cursor: pointer;
justify-content: center;
font-size: 20px;
align-items: center;
border-radius: 3px;
&:hover {
background-color: #fff;
border: 1px solid #e4e7ee;
}
}
</style>
Loading
Loading