Commit 02ccf52d6c5476e549cc164e980531d45a957d6d

Authored by YunaiV
1 parent 5901ab66

mp:增加发送【图文】消息

yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/news/MpDraftController.http
... ... @@ -19,6 +19,14 @@ tenant-id: {{adminTenentId}}
19 19 "content": "我是内容",
20 20 "contentSourceUrl": "https://www.iocoder.cn",
21 21 "thumbMediaId": "r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn"
  22 + },
  23 + {
  24 + "title": "我是标题 2",
  25 + "author": "我是作者 2",
  26 + "digest": "我是摘要 2",
  27 + "content": "我是内容 2",
  28 + "contentSourceUrl": "https://www.iocoder.cn",
  29 + "thumbMediaId": "r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn"
22 30 }
23 31 ]
24 32 }
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/news/MpFreePublishController.http
... ... @@ -5,7 +5,7 @@ Authorization: Bearer {{token}}
5 5 tenant-id: {{adminTenentId}}
6 6  
7 7 ### 请求 /mp/free-publish/submit 接口 => 成功
8   -POST {{baseUrl}}/mp/free-publish/submit?accountId=1&mediaId=r6ryvl6LrxBU0miaST4Y-pEm50d1qKxNPkZVzrRZthSJHKCgiylCf4tARZfybZ_O
  8 +POST {{baseUrl}}/mp/free-publish/submit?accountId=1&mediaId=r6ryvl6LrxBU0miaST4Y-vilmd7iS51D8IPddxflWrau0hIQ2ovY8YanO5jlgUcM
9 9 Content-Type: application/json
10 10 Authorization: Bearer {{token}}
11 11 tenant-id: {{adminTenentId}}
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/news/MpFreePublishController.java
... ... @@ -44,6 +44,7 @@ public class MpFreePublishController {
44 44 } catch (WxErrorException e) {
45 45 throw exception(FREE_PUBLISH_LIST_FAIL, e.getError().getErrorMsg());
46 46 }
  47 + // todo 芋艿:需要查询对应的缩略图,不然前端无法展示
47 48  
48 49 // 返回分页
49 50 return success(new PageResult<>(publicationRecords.getItems(), publicationRecords.getTotalCount().longValue()));
... ...
yudao-ui-admin/src/api/mp/freePublish.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获得公众号素材分页
  4 +export function getFreePublishPage(query) {
  5 + return request({
  6 + url: '/mp/free-publish/page',
  7 + method: 'get',
  8 + params: query
  9 + })
  10 +}
... ...
yudao-ui-admin/src/views/mp/components/wx-material-select/main.vue
... ... @@ -48,7 +48,7 @@
48 48 </el-table>
49 49 <!-- 分页组件 -->
50 50 <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
51   - @pagination="getMaterialPage"/>
  51 + @pagination="getPage"/>
52 52 </div>
53 53 <div v-else-if="objData.type === 'video'">
54 54 <!-- 列表 -->
... ... @@ -78,41 +78,32 @@
78 78 <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
79 79 @pagination="getMaterialPage"/>
80 80 </div>
81   - <div v-else-if="objData.type == 'news'">
  81 + <div v-else-if="objData.type === 'news'">
82 82 <div class="waterfall" v-loading="loading">
83   - <div class="waterfall-item" v-for="item in list" :key="item.mediaId" v-if="item.content && item.content.articles">
84   - <WxNews :objData="item.content.articles"></WxNews>
  83 + <div class="waterfall-item" v-for="item in list" :key="item.mediaId" v-if="item.content && item.content.newsItem">
  84 + <wx-news :articles="item.content.newsItem" />
85 85 <el-row class="ope-row">
86   - <el-button size="mini" type="success" @click="selectMaterial(item)">选择<i class="el-icon-circle-check el-icon--right"></i></el-button>
  86 + <el-button size="mini" type="success" @click="selectMaterial(item)">
  87 + 选择<i class="el-icon-circle-check el-icon--right"></i>
  88 + </el-button>
87 89 </el-row>
88 90 </div>
89 91 </div>
90   - <div v-if="list.length <=0 && !loading" class="el-table__empty-block">
  92 + <!-- 分页组件 -->
  93 + <div v-if="list.length <= 0 && !loading" class="el-table__empty-block">
91 94 <span class="el-table__empty-text">暂无数据</span>
92 95 </div>
93   - <span slot="footer" class="dialog-footer">
94   - <el-pagination
95   - @size-change="sizeChange"
96   - :current-page.sync="page.currentPage"
97   - :page-sizes="[10, 20]"
98   - :page-size="page.pageSize"
99   - layout="total, sizes, prev, pager, next, jumper"
100   - :total="page.total"
101   - class="pagination"
102   - >
103   - </el-pagination>
104   - </span>
  96 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  97 + @pagination="getMaterialPage"/>
105 98 </div>
106 99 </template>
107 100  
108 101 <script>
109   -
110   - // import { tableOptionVoice } from '@/const/crud/wxmp/wxmaterial_voice'
111   - // import { tableOptionVideo } from '@/const/crud/wxmp/wxmaterial_video'
112 102 import WxNews from '@/views/mp/components/wx-news/main.vue';
113 103 import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue';
114 104 import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue';
115 105 import { getMaterialPage } from "@/api/mp/material";
  106 + import {getFreePublishPage} from "@/api/mp/freePublish";
116 107  
117 108 export default {
118 109 name: "wxMaterialSelect",
... ... @@ -143,56 +134,40 @@
143 134 queryParams: {
144 135 pageNo: 1,
145 136 pageSize: 10,
  137 + accountId: this.objData.accountId,
146 138 },
147 139 // tableOptionVoice: tableOptionVoice,
148 140 // tableOptionVideo: tableOptionVideo,
149 141 }
150 142 },
151 143 created() {
152   - this.getPage(this.page)
  144 + this.getPage()
153 145 },
154 146 methods:{
155   - selectMaterial(item){
  147 + selectMaterial(item) {
156 148 this.$emit('selectMaterial', item)
157 149 },
158   - getPage(page, params) {
  150 + getPage() {
159 151 this.loading = true
160   - if(this.objData.type == 'news'){ // 【图文】
161   - if(this.newsType == '1'){
162   - getPageNews(Object.assign({
163   - current: page.currentPage,
164   - size: page.pageSize,
165   - appId:this.appId,
166   - }, params)).then(response => {
167   - let tableData = response.data.items
168   - tableData.forEach(item => {
169   - item.mediaId = item.articleId
170   - item.content.articles = item.content.newsItem
171   - })
172   - this.list = tableData
173   - this.page.total = response.data.totalCount
174   - this.page.currentPage = page.currentPage
175   - this.page.pageSize = page.pageSize
176   - this.loading = false
177   - })
178   - }else if(this.newsType == '2'){
179   - getPageNewsDraft(Object.assign({
180   - current: page.currentPage,
181   - size: page.pageSize,
182   - appId:this.appId,
183   - }, params)).then(response => {
184   - let tableData = response.data.items
185   - tableData.forEach(item => {
186   - item.mediaId = item.mediaId
187   - item.content.articles = item.content.newsItem
188   - })
189   - this.list = tableData
190   - this.page.total = response.data.totalCount
191   - this.page.currentPage = page.currentPage
192   - this.page.pageSize = page.pageSize
193   - this.loading = false
  152 + if (this.objData.type === 'news' && this.newsType === '1') { // 【图文】+ 【已发布】
  153 + this.getFreePublishPage();
  154 + } else if (this.objData.type === 'news' && this.newsType === '2') { // 【图文】+ 【草稿】
  155 + getPageNewsDraft(Object.assign({
  156 + current: page.currentPage,
  157 + size: page.pageSize,
  158 + appId:this.appId,
  159 + }, params)).then(response => {
  160 + let tableData = response.data.items
  161 + tableData.forEach(item => {
  162 + item.mediaId = item.mediaId
  163 + item.content.articles = item.content.newsItem
194 164 })
195   - }
  165 + this.list = tableData
  166 + this.page.total = response.data.totalCount
  167 + this.page.currentPage = page.currentPage
  168 + this.page.pageSize = page.pageSize
  169 + this.loading = false
  170 + })
196 171 } else { // 【素材】
197 172 this.getMaterialPage();
198 173 }
... ... @@ -208,20 +183,20 @@
208 183 this.loading = false
209 184 })
210 185 },
211   - sizeChange(val) {
212   - this.page.currentPage = 1
213   - this.page.pageSize = val
214   - this.getPage(this.page)
215   - },
216   - currentChange(val) {
217   - this.page.currentPage = val
218   - this.getPage(this.page)
219   - },
220   - /**
221   - * 刷新回调
222   - */
223   - refreshChange(page) {
224   - this.getPage(this.page)
  186 + getFreePublishPage() {
  187 + getFreePublishPage(this.queryParams).then(response => {
  188 + // 将 thumbUrl 转成 picUrl,保证 wx-news 组件可以预览封面
  189 + response.data.list.forEach(item => {
  190 + const newsItem = item.content.newsItem;
  191 + newsItem.forEach(article => {
  192 + article.picUrl = article.thumbUrl;
  193 + })
  194 + })
  195 + this.list = response.data.list
  196 + this.total = response.data.total
  197 + }).finally(() => {
  198 + this.loading = false
  199 + })
225 200 }
226 201 }
227 202 };
... ...
yudao-ui-admin/src/views/mp/components/wx-msg/main.vue
... ... @@ -155,21 +155,23 @@ import { getUser } from &quot;@/api/mp/user&quot;;
155 155 if (!this.objData) {
156 156 return;
157 157 }
158   - if (this.objData.type === 'news') {
159   - this.objData.content.articles = [this.objData.content.articles[0]]
  158 + // 公众号限制:客服消息,公众号只允许发送一条
  159 + if (this.objData.type === 'news'
  160 + && this.objData.articles.length > 1) {
  161 + this.objData.articles = [this.objData.articles[0]]
160 162 this.$message({
161 163 showClose: true,
162   - message: '图文消息条数限制在1条以内,已默认发送第一条',
  164 + message: '图文消息条数限制在 1 条以内,已默认发送第一条',
163 165 type: 'success'
164 166 })
165 167 }
  168 +
  169 + // 执行发送
166 170 this.sendLoading = true
167 171 sendMessage(Object.assign({
168 172 userId: this.userId
169 173 }, {
170   - ...this.objData,
171   - // content: this.objData.repContent,
172   - // TODO 芋艿:临时适配,保证可用
  174 + ...this.objData
173 175 })).then(response => {
174 176 this.sendLoading = false
175 177 // 添加到消息列表,并滚动
... ...
yudao-ui-admin/src/views/mp/components/wx-news/main.vue
... ... @@ -41,7 +41,10 @@
41 41 articles: {
42 42 type: Array // title - 标题;description - 描述;picUrl - 图片连接;url - 跳转链接
43 43 }
44   - }
  44 + },
  45 + created() {
  46 + console.log(this.articles)
  47 + },
45 48 };
46 49 </script>
47 50  
... ...
yudao-ui-admin/src/views/mp/components/wx-reply/main.vue
... ... @@ -118,18 +118,20 @@
118 118 </el-row>
119 119 </el-row>
120 120 </el-tab-pane>
  121 + <!-- 类型 5:图文 -->
121 122 <el-tab-pane name="news">
122 123 <span slot="label"><i class="el-icon-news"></i> 图文</span>
123 124 <el-row>
124   - <div class="select-item" v-if="objData.content">
125   - <WxNews :objData="objData.content.articles"></WxNews>
  125 + <div class="select-item" v-if="objData.articles">
  126 + <wx-news :articles="objData.articles" />
126 127 <el-row class="ope-row">
127   - <el-button type="danger" icon="el-icon-delete" circle @click="deleteObj"></el-button>
  128 + <el-button type="danger" icon="el-icon-delete" circle @click="deleteObj" />
128 129 </el-row>
129 130 </div>
  131 + <!-- 选择素材 -->
130 132 <div v-if="!objData.content">
131 133 <el-row style="text-align: center">
132   - <el-col :span="24" class="col-select2">
  134 + <el-col :span="24">
133 135 <el-button type="success" @click="openMaterial">{{newsType === '1' ? '选择已发布图文' : '选择草稿箱图文'}}<i class="el-icon-circle-check el-icon--right"></i></el-button>
134 136 </el-col>
135 137 </el-row>
... ... @@ -369,7 +371,10 @@
369 371 // 创建 tempObjItem 对象,并设置对应的值
370 372 let tempObjItem = {}
371 373 tempObjItem.type = this.objData.type;
372   - if (this.objData.type === 'music') { // 音乐需要特殊处理,因为选择的是图片的缩略图
  374 + if (this.objData.type === 'news') {
  375 + tempObjItem.articles = item.content.newsItem
  376 + this.objData.articles = item.content.newsItem
  377 + } else if (this.objData.type === 'music') { // 音乐需要特殊处理,因为选择的是图片的缩略图
373 378 tempObjItem.thumbMediaId = item.mediaId
374 379 this.objData.thumbMediaId = item.mediaId
375 380 tempObjItem.thumbMediaUrl = item.url
... ... @@ -431,7 +436,7 @@
431 436 },
432 437 deleteObj() {
433 438 if (this.objData.type === 'news') {
434   - this.objData.articles = []
  439 + this.$delete(this.objData, 'articles');
435 440 } else if(this.objData.type === 'image') {
436 441 this.objData.mediaId = null
437 442 this.objData.url = null
... ...