Skip to content

Commit b5fb700

Browse files
committed
refactor: mp/draft拆分组件
1 parent 30b8eea commit b5fb700

File tree

6 files changed

+701
-631
lines changed

6 files changed

+701
-631
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<template>
2+
<div>
3+
<p>封面:</p>
4+
<div class="thumb-div">
5+
<el-image
6+
v-if="newsItem.thumbUrl"
7+
style="width: 300px; max-height: 300px"
8+
:src="newsItem.thumbUrl"
9+
fit="contain"
10+
/>
11+
<Icon
12+
v-else
13+
icon="ep:plus"
14+
class="avatar-uploader-icon"
15+
:class="isFirst ? 'avatar' : 'avatar1'"
16+
/>
17+
<div class="thumb-but">
18+
<el-upload
19+
:action="UPLOAD_URL"
20+
:headers="HEADERS"
21+
multiple
22+
:limit="1"
23+
:file-list="fileList"
24+
:data="uploadData"
25+
:before-upload="onBeforeUpload"
26+
:on-error="onUploadError"
27+
:on-success="onUploadSuccess"
28+
>
29+
<template #trigger>
30+
<el-button size="small" type="primary" :loading="isUploading" disabled="isUploading">
31+
{{ isUploading ? '正在上传' : '本地上传' }}
32+
</el-button>
33+
</template>
34+
<el-button
35+
size="small"
36+
type="primary"
37+
@click="showImageDialog = true"
38+
style="margin-left: 5px"
39+
>
40+
素材库选择
41+
</el-button>
42+
<template #tip>
43+
<div class="el-upload__tip">支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M</div>
44+
</template>
45+
</el-upload>
46+
</div>
47+
<el-dialog
48+
title="选择图片"
49+
v-model="showImageDialog"
50+
width="80%"
51+
append-to-body
52+
destroy-on-close
53+
>
54+
<WxMaterialSelect
55+
:objData="{ type: 'image', accountId: accountId }"
56+
@select-material="onMaterialSelected"
57+
/>
58+
</el-dialog>
59+
</div>
60+
</div>
61+
</template>
62+
63+
<script setup lang="ts">
64+
import WxMaterialSelect from '@/views/mp/components/wx-material-select/main.vue'
65+
import { getAccessToken } from '@/utils/auth'
66+
import type { UploadFiles, UploadProps, UploadRawFile } from 'element-plus'
67+
import { NewsItem } from './types'
68+
69+
const message = useMessage()
70+
71+
const UPLOAD_URL = 'http://localhost:8000/upload/' //import.meta.env.VITE_BASE_URL + '/admin-api/mp/material/upload-permanent' // 上传永久素材的地址
72+
const HEADERS = { Authorization: 'Bearer ' + getAccessToken() } // 设置上传的请求头部
73+
74+
const props = defineProps<{
75+
modelValue: NewsItem
76+
isFirst: boolean
77+
}>()
78+
79+
const emit = defineEmits<{
80+
(e: 'update:modelValue', v: NewsItem)
81+
}>()
82+
const newsItem = computed<NewsItem>({
83+
get() {
84+
return props.modelValue
85+
},
86+
set(val) {
87+
emit('update:modelValue', val)
88+
}
89+
})
90+
91+
const accountId = inject<number>('accountId')
92+
const showImageDialog = ref(false)
93+
94+
const fileList = ref<UploadFiles>([])
95+
interface UploadData {
96+
type: 'image' | 'video' | 'audio'
97+
accountId?: number
98+
}
99+
const uploadData: UploadData = reactive({
100+
type: 'image',
101+
accountId: accountId
102+
})
103+
const isUploading = ref(false)
104+
105+
/** 素材选择完成事件*/
106+
const onMaterialSelected = (item: any) => {
107+
showImageDialog.value = false
108+
newsItem.value.thumbMediaId = item.mediaId
109+
newsItem.value.thumbUrl = item.url
110+
}
111+
112+
// ======================== 文件上传 ========================
113+
const onBeforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
114+
const isType = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/jpg'].includes(
115+
rawFile.type
116+
)
117+
if (!isType) {
118+
message.error('上传图片格式不对!')
119+
return false
120+
}
121+
122+
if (rawFile.size / 1024 / 1024 > 2) {
123+
message.error('上传图片大小不能超过 2M!')
124+
return false
125+
}
126+
// 校验通过
127+
return true
128+
}
129+
130+
const onUploadSuccess: UploadProps['onSuccess'] = (res: any) => {
131+
if (res.code !== 0) {
132+
message.error('上传出错:' + res.msg)
133+
return false
134+
}
135+
136+
// 重置上传文件的表单
137+
fileList.value = []
138+
139+
// 设置草稿的封面字段
140+
newsItem.value.thumbMediaId = res.data.mediaId
141+
newsItem.value.thumbUrl = res.data.url
142+
}
143+
144+
const onUploadError = (err: Error) => {
145+
message.error('上传失败: ' + err.message)
146+
}
147+
</script>
148+
149+
<style lang="scss" scoped>
150+
.el-upload__tip {
151+
margin-left: 5px;
152+
}
153+
154+
.thumb-div {
155+
display: inline-block;
156+
width: 100%;
157+
text-align: center;
158+
159+
.avatar-uploader-icon {
160+
width: 120px;
161+
height: 120px;
162+
font-size: 28px;
163+
line-height: 120px;
164+
color: #8c939d;
165+
text-align: center;
166+
border: 1px solid #d9d9d9;
167+
}
168+
169+
.avatar {
170+
width: 230px;
171+
height: 120px;
172+
}
173+
174+
.avatar1 {
175+
width: 120px;
176+
height: 120px;
177+
}
178+
179+
.thumb-but {
180+
margin: 5px;
181+
}
182+
}
183+
</style>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<template>
2+
<div class="waterfall" v-loading="props.loading">
3+
<template v-for="item in props.list" :key="item.articleId">
4+
<div class="waterfall-item" v-if="item.content && item.content.newsItem">
5+
<WxNews :articles="item.content.newsItem" />
6+
<!-- 操作按钮 -->
7+
<el-row>
8+
<el-button
9+
type="success"
10+
circle
11+
@click="emit('publish', item)"
12+
v-hasPermi="['mp:free-publish:submit']"
13+
>
14+
<Icon icon="fa:upload" />
15+
</el-button>
16+
<el-button
17+
type="primary"
18+
circle
19+
@click="emit('update', item)"
20+
v-hasPermi="['mp:draft:update']"
21+
>
22+
<Icon icon="ep:edit" />
23+
</el-button>
24+
<el-button
25+
type="danger"
26+
circle
27+
@click="emit('delete', item)"
28+
v-hasPermi="['mp:draft:delete']"
29+
>
30+
<Icon icon="ep:delete" />
31+
</el-button>
32+
</el-row>
33+
</div>
34+
</template>
35+
</div>
36+
</template>
37+
38+
<script setup lang="ts">
39+
import WxNews from '@/views/mp/components/wx-news/main.vue'
40+
41+
import { Article } from './types'
42+
43+
const props = defineProps<{
44+
list: Article[]
45+
loading: boolean
46+
}>()
47+
48+
const emit = defineEmits<{
49+
(e: 'publish', v: Article)
50+
(e: 'update', v: Article)
51+
(e: 'delete', v: Article)
52+
}>()
53+
</script>
54+
55+
<style lang="scss" scoped>
56+
.waterfall {
57+
width: 100%;
58+
column-gap: 10px;
59+
column-count: 5;
60+
margin: 0 auto;
61+
62+
.waterfall-item {
63+
padding: 10px;
64+
margin-bottom: 10px;
65+
break-inside: avoid;
66+
border: 1px solid #eaeaea;
67+
}
68+
}
69+
70+
@media (min-width: 992px) and (max-width: 1300px) {
71+
.waterfall {
72+
column-count: 3;
73+
}
74+
}
75+
76+
@media (min-width: 768px) and (max-width: 991px) {
77+
.waterfall {
78+
column-count: 2;
79+
}
80+
}
81+
82+
@media (max-width: 767px) {
83+
.waterfall {
84+
column-count: 1;
85+
}
86+
}
87+
</style>

0 commit comments

Comments
 (0)