MiniproLiveForm.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. <template><page-meta :root-font-size="fontSize+'px'"></page-meta>
  2. <seller-base :show="false" class="scroll-view-wrapper">
  3. <view class="scroll-view-wrapper scroll-view div container live-form">
  4. <view class="div common-header-wrap">
  5. <view :style="'height:'+navHeight+'px'"></view>
  6. <view class="common-header-holder"></view>
  7. <view class="common-header-fixed">
  8. <title-header />
  9. <uni-nav-bar :title="getTitle" class="common-header" left-icon="back" @clickLeft="goBack">
  10. </uni-nav-bar>
  11. </view>
  12. </view>
  13. <view class="div notice">
  14. <text class="span">主播微信号需要通过人脸认证</text>
  15. <view class="div common-btn ds-button-small btn" @click="showPopup('showQrcode')"><text class="span">认证</text></view>
  16. </view>
  17. <view class="div main-content">
  18. <flex-line class="field-line menu-item" :show-border="true"><text class="span field-name">直播标题</text><view class="div field-line-right" slot="right"><input class="field-input" :disabled="minipro_live_info.minipro_live_room_id" v-model="minipro_live_info.minipro_live_name" /></view></flex-line>
  19. <view class="div">
  20. <flex-line :is-link="true" :show-border="true">
  21. <text class="span line-name">直播时间</text>
  22. <view class="span" slot="right">
  23. <uni-datetime-picker class="common-datetime-picker" type="datetimerange" v-model="timeRange"
  24. :start="$moment().format('YYYY-MM-DD HH:mm')"></uni-datetime-picker>
  25. </view>
  26. </flex-line>
  27. </view>
  28. <flex-line class="field-line menu-item" :show-border="true"><text class="span field-name">主播昵称</text><view class="div field-line-right" slot="right"><input class="field-input" :disabled="minipro_live_info.minipro_live_room_id" v-model="minipro_live_info.minipro_live_nickname" /></view></flex-line>
  29. <flex-line class="field-line menu-item" :show-border="true"><text class="span field-name">主播微信号</text><view class="div field-line-right" slot="right"><input class="field-input" :disabled="minipro_live_info.minipro_live_room_id" v-model="minipro_live_info.minipro_live_wxid" /></view></flex-line>
  30. <flex-line class="pt-5" :show-border="true">
  31. <text class="span">直播封面</text>
  32. <view class="div" slot="right">
  33. <view class="div user-avatar-wrapper">
  34. <view class="div user-avatar">
  35. <uni-file-picker class="common-avatar" v-model="imageValue['feedsImg']" fileMediatype="image" mode="grid" :limit="1"
  36. :auto-upload="false" @select="uploadImage('feedsImg',$event)" @delete="dropImage('feedsImg')" :image-styles="{
  37. width:'160px',
  38. height:'160px',
  39. }"></uni-file-picker>
  40. </view>
  41. </view>
  42. </view>
  43. </flex-line>
  44. <flex-line class="pt-5" :show-border="true">
  45. <text class="span">直播背景</text>
  46. <view class="div" slot="right">
  47. <view class="div user-avatar-wrapper">
  48. <view class="div user-avatar">
  49. <uni-file-picker class="common-avatar" v-model="imageValue['coverImg']" fileMediatype="image" mode="grid" :limit="1"
  50. :auto-upload="false" @select="uploadImage('coverImg',$event)" @delete="dropImage('coverImg')" :image-styles="{
  51. width:'160px',
  52. height:'160px',
  53. }"></uni-file-picker>
  54. </view>
  55. </view>
  56. </view>
  57. </flex-line>
  58. <view class="div" @click="showPopup('popupSelect')">
  59. <flex-line :is-link="true" :show-border="true"><text class="span line-name">选择商品</text><text class="span" slot="right">{{selectGoodsId.length?('已选' + selectGoodsId.length + '件'):''}}</text></flex-line>
  60. </view>
  61. <view class="div pt-10 pb-10">
  62. <view class="div common-btn ds-button-large" @click="submit">保存</view>
  63. </view>
  64. </view>
  65. <uni-popup background-color="#fff" ref="popupSelect" type="right">
  66. <view :style="'width:'+screenWidth+'px'" class="common-popup-wrapper">
  67. <view class="div common-header-wrap">
  68. <view :style="'height:'+navHeight+'px'"></view>
  69. <view class="common-header-holder"></view>
  70. <view class="common-header-fixed">
  71. <title-header />
  72. <uni-nav-bar title="选择商品" class="common-header" left-icon="back" @clickLeft="hidePopup('popupSelect')">
  73. </uni-nav-bar>
  74. </view>
  75. </view>
  76. <view class="scroll-view-wrapper scroll-view div common-popup-content">
  77. <scroll-view style="position: absolute;top:0;right:0;left:0;bottom:0" class="scroll-view div" @scrolltolower="loadMore" scroll-y="true">
  78. <view class="div select-goods" v-if="selectGoodsList">
  79. <view class="ul" v-if="selectGoodsList.length">
  80. <view class="li" v-for="item in selectGoodsList" v-bind:key="item.goods_commonid" :class="{'active':item.minipro_live_goods_info && selectGoodsId.indexOf(item.minipro_live_goods_info.minipro_live_goods_result_id)>-1,'disable':!item.minipro_live_goods_info || item.minipro_live_goods_info.minipro_live_goods_state!=2 || item.minipro_live_goods_info.minipro_live_goods_close==1}" @click="selectedGoods(item)">
  81. <view class="div p-img">
  82. <image mode="aspectFit" class="img" :src="item.goods_image_url"/>
  83. </view>
  84. <view class="div p-info">
  85. <view class="p name">{{item.goods_name}}</view>
  86. <view class="p price">{{item.goods_price}}</view>
  87. </view>
  88. <view v-if="item.minipro_live_goods_info && item.minipro_live_goods_info.minipro_live_goods_close==1" class="div state">
  89. <text class="span">已关闭</text>
  90. </view>
  91. <view v-else class="div state">
  92. <text class="span" v-if="!item.minipro_live_goods_info || !item.minipro_live_goods_info.minipro_live_goods_state">审核中</text>
  93. <text class="span" v-if="item.minipro_live_goods_info && item.minipro_live_goods_info.minipro_live_goods_state==2">已通过</text>
  94. <text class="span" v-if="item.minipro_live_goods_info && item.minipro_live_goods_info.minipro_live_goods_state==3">未通过</text>
  95. </view>
  96. </view>
  97. </view>
  98. <empty-record v-else></empty-record>
  99. </view>
  100. </scroll-view>
  101. </view>
  102. </view>
  103. </uni-popup>
  104. <!--认证小程序码-->
  105. <uni-popup background-color="#fff" ref="showQrcode" type="right" >
  106. <view :style="'width:'+screenWidth+'px'" class="common-popup-wrapper">
  107. <view class="div common-header-wrap">
  108. <view :style="'height:'+navHeight+'px'"></view>
  109. <view class="common-header-holder"></view>
  110. <view class="common-header-fixed">
  111. <title-header />
  112. <uni-nav-bar title="认证小程序码" class="common-header" left-icon="back" @clickLeft="hidePopup('showQrcode')">
  113. </uni-nav-bar>
  114. </view>
  115. </view>
  116. <view class="div common-popup-content" style="text-align: center">
  117. <scroll-view style="position: absolute;top:0;right:0;left:0;bottom:0" scroll-y="true">
  118. <image mode="aspectFit" class="img refer_qrcode_logo" src="../../../static/image/minipro_live_verify.png">
  119. </scroll-view>
  120. </view>
  121. </view>
  122. </uni-popup>
  123. <tui-picture-cropper v-if="cropperOption.imgUrl" :width="cropperOption.autoCropWidth" :height="cropperOption.autoCropHeight" :imageUrl="cropperOption.img" @ready="cropReady" @cropper="useCrop" @back="cropBack"></tui-picture-cropper>
  124. </view>
  125. </seller-base>
  126. </template>
  127. <script>
  128. import {getFontSize} from '@/util/common'
  129. import TitleHeader from '../../TitleHeader'
  130. import SellerBase from '../SellerBase'
  131. import tuiPictureCropper from "@/components/thorui/tui-picture-cropper/tui-picture-cropper"
  132. import { getRoomInfo, addRoom, uploadMedia, getGoodsList, importRoomGoods } from '../../../api/sellerMiniproLive'
  133. import EmptyRecord from '../../EmptyRecord'
  134. import flexLine from '../../flexLine'
  135. export default {
  136. components:{
  137. TitleHeader,
  138. SellerBase,
  139. flexLine,
  140. EmptyRecord,
  141. tuiPictureCropper
  142. },
  143. props: {
  144. ifComponent: {
  145. type: Boolean,
  146. default: false
  147. },
  148. query: {
  149. type: Object,
  150. default: function () {
  151. return { action: 'add', minipro_live_id: 0 }
  152. }
  153. }
  154. },
  155. computed:{
  156. fontSize(){
  157. return getFontSize()
  158. },
  159. isAddMode () {
  160. let mode = this.ifComponent ? this.query.action : this.action
  161. // add: 添加地址,edit: 编辑地址
  162. if (mode === 'add') {
  163. return true
  164. } else {
  165. return false
  166. }
  167. },
  168. getTitle () {
  169. if (this.isAddMode) {
  170. return '新增直播'
  171. } else {
  172. return '修改直播'
  173. }
  174. }
  175. },
  176. data(){
  177. return {
  178. navHeight: 0,
  179. imageValue:{},
  180. screenWidth:0,
  181. action:'',
  182. cropperOption: {
  183. img: '',
  184. canMove: false,
  185. autoCrop: true,
  186. autoCropWidth: 100,
  187. autoCropHeight: 100,
  188. maxImgSize: 500,
  189. outputType: 'png'
  190. },
  191. cropType: '',
  192. timeRange: [],
  193. minipro_live_info: {},
  194. params: { 'page': 0, 'per_page': 10 },
  195. loading: false, // 是否加载更多
  196. isMore: true, // 是否有更多
  197. selectGoodsList: false,
  198. selectGoodsId: [],
  199. keyword: '',
  200. showimage: '',
  201. isshow: false
  202. }
  203. },
  204. onLoad: function (option) {
  205. this.action = option.action
  206. this.initLive()
  207. this.loadMore()
  208. },
  209. watch: {
  210. query: function (val) {
  211. this.minipro_live_id = val.minipro_live_id
  212. this.initLive()
  213. }
  214. },
  215. mounted(){
  216. // #ifdef MP-WEIXIN
  217. this.navHeight = uni.getMenuButtonBoundingClientRect().height
  218. // #endif
  219. this.screenWidth=uni.getSystemInfoSync().screenWidth
  220. },
  221. methods:{
  222. showPopup(id){
  223. this.$refs[id].open()
  224. },
  225. hidePopup(id){
  226. this.$refs[id].close()
  227. },
  228. goBack () {
  229. if (this.ifComponent) {
  230. this.$emit('closeLiveApplyForm')
  231. } else {
  232. uni.navigateBack({delta:1})
  233. }
  234. },
  235. initLive () {
  236. if (!this.isAddMode) {
  237. getRoomInfo(this.minipro_live_id).then(res => {
  238. var minipro_live_info = res.result.minipro_live_info
  239. this.timeRange = [minipro_live_info.minipro_live_start_time,minipro_live_info.minipro_live_end_time]
  240. this.minipro_live_info = minipro_live_info
  241. if(this.minipro_live_info.feedsImg){
  242. this.imageValue['feedsImg']=[{
  243. name:'feedsImg',
  244. extname:'jpg',
  245. url:this.minipro_live_info.feedsImgUrl
  246. }]
  247. }
  248. if(this.minipro_live_info.coverImg){
  249. this.imageValue['coverImg']=[{
  250. name:'coverImg',
  251. extname:'jpg',
  252. url:this.minipro_live_info.coverImgUrl
  253. }]
  254. }
  255. }).catch(function (error) {
  256. uni.showToast({icon:'none',title: error.message})
  257. })
  258. }
  259. },
  260. submit () {
  261. uni.showLoading({ title: '加载中' })
  262. var data=Object.assign({},this.minipro_live_info)
  263. if(this.timeRange.length){
  264. data=Object.assign({minipro_live_start_time:this.timeRange[0],minipro_live_end_time:this.timeRange[1]},this.minipro_live_info)
  265. }
  266. addRoom(data).then(res => {
  267. this.minipro_live_info.minipro_live_room_id = res.result.roomId
  268. if (this.selectGoodsId.length) {
  269. this.importRoomGoods(res.result.roomId)
  270. } else {
  271. this.finish()
  272. }
  273. uni.hideLoading()
  274. }).catch(error => {
  275. uni.hideLoading()
  276. uni.showToast({icon:'none',title: error.message})
  277. })
  278. },
  279. finish () {
  280. uni.hideLoading()
  281. if (this.ifComponent) {
  282. this.$emit('addRoom')
  283. } else {
  284. uni.navigateTo({url:'/pages/seller/minipro_live/MiniproLiveList'})
  285. }
  286. },
  287. importRoomGoods (roomId) {
  288. importRoomGoods({ roomId: roomId, ids: this.selectGoodsId }).then(res => {
  289. this.finish()
  290. }).catch(error => {
  291. uni.hideLoading()
  292. uni.showToast({icon:'none',title: error.message})
  293. })
  294. },
  295. loadMore () {
  296. this.loading = true
  297. this.params.page = ++this.params.page
  298. if (this.isMore) {
  299. this.loading = false
  300. this.getSelectGoodsList(true)
  301. }
  302. },
  303. reload () {
  304. // 重新加载数据
  305. this.params.page = 0
  306. this.isMore = true
  307. this.selectGoodsList = []
  308. this.loadMore()
  309. },
  310. // 获取商品列表 用于设置产品分佣
  311. getSelectGoodsList () {
  312. getGoodsList(this.params).then(res => {
  313. if (this.selectGoodsList) {
  314. this.selectGoodsList = this.selectGoodsList.concat(res.result.goods_list)
  315. } else {
  316. this.selectGoodsList = res.result.goods_list
  317. }
  318. if (res.result.hasmore) {
  319. this.isMore = true
  320. } else {
  321. this.isMore = false
  322. }
  323. }).catch(function (error) {
  324. uni.showToast({icon:'none',title: error.message})
  325. })
  326. },
  327. // 选择商品
  328. selectedGoods (item) {
  329. if (item.minipro_live_goods_info && item.minipro_live_goods_info.minipro_live_goods_state == 2 && item.minipro_live_goods_info.minipro_live_goods_close != 1) {
  330. var index = this.selectGoodsId.indexOf(item.minipro_live_goods_info.minipro_live_goods_result_id)
  331. if (index > -1) {
  332. this.selectGoodsId.splice(index, 1)
  333. } else {
  334. if (this.selectGoodsId.length >= 10) {
  335. uni.showToast({icon:'none',title: '最多选10件商品'})
  336. return
  337. }
  338. this.selectGoodsId.push(item.minipro_live_goods_info.minipro_live_goods_result_id)
  339. }
  340. }
  341. },
  342. openImage (src) {
  343. this.showimage = src
  344. this.isshow = true
  345. },
  346. dropImage (type) {
  347. if (type == 'feedsImg') {
  348. this.minipro_live_info.feedsImg = ''
  349. } else {
  350. this.minipro_live_info.coverImg = ''
  351. }
  352. this.$forceUpdate()
  353. },
  354. useCrop (res) {
  355. let type = this.cropType
  356. var formdata={
  357. filePath:res.url,
  358. name:'file',
  359. id:'file'
  360. }
  361. if (type == 'feedsImg') {
  362. formdata['save']=1
  363. }
  364. uni.showLoading({ title: '加载中' })
  365. uploadMedia(formdata).then(res => {
  366. if (type == 'feedsImg') {
  367. this.minipro_live_info.feedsImg = res.result.media_id
  368. this.minipro_live_info.minipro_live_image = res.result.file_name
  369. this.imageValue[index]=[{
  370. name:index,
  371. extname:'jpg',
  372. url:res.result.file_path
  373. }]
  374. } else {
  375. this.minipro_live_info.coverImg = res.result.media_id
  376. }
  377. this.hidePopup('showCrop')
  378. this.cropperOption.imgUrl=''
  379. this.$forceUpdate()
  380. uni.hideLoading()
  381. }).catch(function (error) {
  382. uni.showToast({icon:'none',title: error.message})
  383. uni.hideLoading()
  384. this.cropperOption.imgUrl=''
  385. this.$forceUpdate()
  386. })
  387. },
  388. cropReady(){
  389. this.cropperOption.img = this.cropperOption.imgUrl
  390. },
  391. cropBack(){
  392. this.cropperOption.imgUrl=''
  393. this.$forceUpdate()
  394. },
  395. uploadImage (type, event) {
  396. let that = this
  397. this.cropType = type
  398. let file = event.tempFiles[0]
  399. if (type == 'feedsImg') {
  400. that.minipro_live_info.feedsImgUrl = file.path
  401. } else {
  402. that.minipro_live_info.coverImgUrl = file.path
  403. }
  404. that.cropperOption.imgUrl = file.path
  405. that.cropperOption.autoCropWidth = uni.getSystemInfoSync().windowWidth
  406. that.cropperOption.autoCropHeight = uni.getSystemInfoSync().windowWidth
  407. that.cropperOption.maxImgSize = uni.getSystemInfoSync().windowHeight - 40
  408. that.$forceUpdate()
  409. }
  410. }
  411. }
  412. </script>
  413. <style lang="scss" scoped>
  414. .scroll-view-wrapper{display: flex;flex-direction: column;}
  415. .scroll-view{flex:1}
  416. .common-header{
  417. .btn{background: #000;color: #fff;box-shadow: 0px 2px 4px #d2d2d2;}
  418. }
  419. .main-content{padding:0 $pageSpace;background: #fff;}
  420. .select-goods .li{height:3rem;padding:.6rem;display:flex;}
  421. .select-goods .li.active{background: rgba(255, 203, 203, 0.5) }
  422. .select-goods .li .p-img{}
  423. .select-goods .li .p-img .img{width:3rem;height: 3rem;}
  424. .select-goods .li .p-info{margin-left:1rem;flex:1}
  425. .select-goods .li .p-info .p{line-height:1rem;}
  426. .select-goods .li .p-info .price{font-size:$fontSize;color:$primaryColor;height:2rem;overflow: hidden}
  427. .select-goods .li .p-info .name{font-size:$subFontSize;}
  428. .select-goods .li .state{font-size:$subFontSize}
  429. .select-goods .li.disable{position: relative;opacity: .5}
  430. .user-avatar-wrapper{display: inline-block;vertical-align: top;margin-right: .5rem;margin-bottom:.5rem}
  431. .user-avatar-wrapper .del-btn{position:absolute;bottom:.2rem;right:.2rem}
  432. .notice{font-size:$subFontSize;padding:.5rem;background:#FCF8E3;color:#C09853;line-height: 1.65rem;
  433. .red{color:#F00}
  434. .btn{float:right}
  435. }
  436. .refer_qrcode_logo{width:60%;top:30%;position: relative;}
  437. </style>