瑶都万能墙
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
9.9 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
10 months ago
10 months ago
1 year ago
1 year ago
10 months ago
1 year ago
10 months ago
10 months ago
1 year ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
10 months ago
10 months ago
10 months ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
10 months ago
10 months ago
10 months ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
10 months ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
11 months ago
1 year ago
11 months ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. <template>
  2. <view class="publishPost">
  3. <navbar
  4. leftClick
  5. @leftClick="$utils.navigateBack"
  6. title="发布动态"/>
  7. <!-- <view class="title-input box">
  8. <input type="text" placeholder="取个吸引人的标题吧" v-model="form.title"/>
  9. </view> -->
  10. <view class="content-input">
  11. <uv-textarea
  12. v-model="form.title"
  13. :maxlength="200"
  14. autoHeight
  15. count
  16. style="min-height: 400rpx;"
  17. placeholder="说点什么吧"></uv-textarea>
  18. </view>
  19. <view class="images box">
  20. <uv-upload
  21. :fileList="fileList"
  22. :maxCount="imageMax"
  23. multiple
  24. width="150rpx"
  25. height="150rpx"
  26. name="fileList"
  27. @delete="deleteImage"
  28. @afterRead="afterRead"
  29. :previewFullImage="true"
  30. accept="media"
  31. :sizeType="['original', 'compressed']"
  32. :sourceType="['album', 'camera']"></uv-upload>
  33. </view>
  34. <view class="category">
  35. <view class="title">
  36. 选择分类
  37. </view>
  38. <view class="tagList">
  39. <view
  40. :class="{act : t.id == form.classId}"
  41. @click="clickCategory(t, i)"
  42. v-for="(t, i) in category"
  43. :key="i">
  44. {{ t.title }}
  45. </view>
  46. </view>
  47. </view>
  48. <!-- <view class="category">
  49. <view class="title">
  50. 选择地区
  51. </view>
  52. <view class="tagList">
  53. <view
  54. :class="{act : t.name == form.address}"
  55. @click="clickAddress(t, i)"
  56. v-for="(t, i) in cityList"
  57. :key="i">
  58. {{ t.name }}
  59. </view>
  60. </view>
  61. </view> -->
  62. <view class="category"
  63. v-if="categoryRole.includes('code')">
  64. <view class="title">
  65. 上传微信二维码必填
  66. </view>
  67. <view class="images box">
  68. <uv-upload
  69. :fileList="codeFileList"
  70. :maxCount="1"
  71. multiple
  72. width="150rpx"
  73. height="150rpx"
  74. name="codeFileList"
  75. @delete="deleteImage"
  76. @afterRead="afterRead"
  77. :previewFullImage="true"></uv-upload>
  78. </view>
  79. </view>
  80. <view class="title-input box"
  81. v-if="categoryRole.includes('phone')">
  82. <input type="text" placeholder="手机号码(选填)" v-model="form.phone"/>
  83. </view>
  84. <view class="title-input box"
  85. v-if="categoryRole.includes('address')"
  86. @click="selectAddr">
  87. <input type="text"
  88. placeholder="选择位置(选填)"
  89. disabled
  90. v-model="form.address"/>
  91. <uv-icon
  92. size="40rpx"
  93. name="map"></uv-icon>
  94. </view>
  95. <view class="title-input box"
  96. @click="$refs.pickerHospital.open()"
  97. v-if="categoryRole.includes('shop')">
  98. <input type="text"
  99. v-if="!form.shop"
  100. placeholder="关联店铺(选填)"/>
  101. <view class="shop-box"
  102. v-else>
  103. <view class="title">
  104. {{ form.shop.title }}
  105. </view>
  106. <view class="desc">
  107. {{ form.shop.address }}
  108. </view>
  109. </view>
  110. </view>
  111. <view class="configBtn"
  112. @click="$refs.configPopup.open()">
  113. 发布须知
  114. </view>
  115. <view class="uni-color-btn"
  116. @click="submit">
  117. 发布
  118. </view>
  119. <configPopup
  120. ref="configPopup"
  121. :text="headInfo.save_no && headInfo.save_no.keyDetails"
  122. />
  123. <pickerHospital
  124. mixinsListApi="getStorePage"
  125. descKeyName="address"
  126. keyName="title"
  127. searchKey="title"
  128. ref="pickerHospital"
  129. @select="selectShop"
  130. />
  131. </view>
  132. </template>
  133. <script>
  134. import { mapState } from 'vuex'
  135. import Position from '@/utils/position.js'
  136. import pickerHospital from '@/components/base/pickerHospital.vue'
  137. import { subscribeBeforePublish } from '@/utils/subscribeMessage.js'
  138. export default {
  139. components : {
  140. pickerHospital,
  141. },
  142. data() {
  143. return {
  144. form : {
  145. title : '',
  146. classId : 0,
  147. address : '',
  148. phone : '',
  149. shop : '',
  150. },
  151. id : 0,
  152. fileList : [],
  153. codeFileList : [],
  154. imageMax : 9,
  155. };
  156. },
  157. computed : {
  158. ...mapState(['cityList', 'category', 'headInfo']),
  159. categoryRole(){
  160. if(!this.form.classId){
  161. return []
  162. }
  163. for(let i = 0;i < this.category.length;i++){
  164. let c = this.category[i]
  165. if(c.id == this.form.classId){
  166. return c.linkType ? c.linkType.split(',') : []
  167. // return 'code,phone,address,shop'.split(',')
  168. }
  169. }
  170. return []
  171. },
  172. },
  173. onLoad(args) {
  174. this.id = args.id
  175. this.form.classId = this.category[0].id
  176. // this.form.address = this.cityList[0].name
  177. this.imageMax = args.imageMax || 9
  178. this.getDateil()
  179. },
  180. onShow() {
  181. this.$store.commit('getCategory')
  182. },
  183. methods : {
  184. clickCategory(item, index){
  185. this.form.classId = item.id
  186. },
  187. clickAddress(item, index){
  188. this.form.address = item.name
  189. },
  190. getDateil(){
  191. if(!this.id){
  192. return
  193. }
  194. let self = this
  195. this.$api('getPostDetail', {
  196. id : this.id
  197. }, res => {
  198. if (res.code == 200) {
  199. self.form.id = res.result.id
  200. self.form.title = res.result.title
  201. self.form.address = res.result.address || self.form.address
  202. self.form.classId = res.result.classId || self.form.classId
  203. self.form.latitude = res.result.latitude || self.form.latitude
  204. self.form.longitude = res.result.longitude || self.form.longitude
  205. self.form.shop = res.result.shop || self.form.shop
  206. self.form.shopId = res.result.shopId || self.form.shopId
  207. if(res.result.wxImage){
  208. self.codeFileList = [
  209. {
  210. url : res.result.wxImage
  211. }
  212. ]
  213. }
  214. if(res.result.image){
  215. res.result.image.split(',')
  216. .forEach(url => {
  217. if(url.trim()){
  218. // 根据文件扩展名判断类型
  219. const isVideo = this.isVideoFile(url.trim())
  220. self.fileList.push({
  221. url: url.trim(),
  222. type: isVideo ? 'video' : 'image'
  223. })
  224. }
  225. })
  226. }
  227. }
  228. })
  229. },
  230. deleteImage(e){
  231. this[e.name].splice(e.index, 1)
  232. },
  233. afterRead(e){
  234. let self = this
  235. e.file.forEach(file => {
  236. // 检测文件类型
  237. const isVideo = this.isVideoFile(file.url || file.path)
  238. self.$Oss.ossUpload(file.url).then(url => {
  239. self[e.name].push({
  240. url,
  241. type: isVideo ? 'video' : 'image'
  242. })
  243. })
  244. })
  245. },
  246. // 检测是否为视频文件
  247. isVideoFile(filePath) {
  248. const videoExtensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.webm', '.m4v', '.3gp']
  249. const fileName = filePath.toLowerCase()
  250. return videoExtensions.some(ext => fileName.includes(ext))
  251. },
  252. // 提交
  253. async submit(){
  254. // if(this.fileList.length == 0){
  255. // return uni.showToast({
  256. // title: '请上传图片',
  257. // icon : 'none'
  258. // })
  259. // }
  260. if (this.$utils.verificationAll(this.form, {
  261. title: '说点什么吧',
  262. })) {
  263. return
  264. }
  265. if(this.categoryRole.includes('code') && this.codeFileList.length == 0){
  266. return uni.showToast({
  267. title: '请上传微信二维码',
  268. icon : 'none'
  269. })
  270. }
  271. // 在发布前订阅消息通知
  272. await subscribeBeforePublish()
  273. delete this.form.shop
  274. // 将所有文件(图片和视频)合并到 image 字段
  275. this.form.image = this.fileList.map((item) => item.url).join(",")
  276. this.form.wxImage = this.codeFileList.map((item) => item.url).join(",")
  277. this.$api('publishPost', this.form, res => {
  278. if(res.code == 200){
  279. uni.showToast({
  280. title: '发布成功!',
  281. icon: 'none'
  282. })
  283. setTimeout(uni.navigateBack, 1000, -1)
  284. }
  285. })
  286. },
  287. //地图上选择地址
  288. selectAddr() {
  289. Position.selectAddress(success => {
  290. this.setAddress(success)
  291. })
  292. },
  293. //提取用户选择的地址信息复制给表单数据
  294. setAddress(res) {
  295. //经纬度信息
  296. this.form.latitude = res.latitude
  297. this.form.longitude = res.longitude
  298. if (res.name) { //用户直接选择城市的逻辑
  299. // if (!res.address && res.name) { //用户直接选择城市的逻辑
  300. return this.form.address = res.name
  301. }
  302. // if (res.address || res.name) {
  303. // return this.form.address = res.address + res.name
  304. // }
  305. this.form.address = '' //用户啥都没选就点击勾选
  306. this.form.latitude = ''
  307. this.form.longitude = ''
  308. },
  309. // 选择关联的店铺
  310. selectShop(shop){
  311. this.form.shop = shop
  312. this.form.shopId = shop.id
  313. this.$refs.pickerHospital.close()
  314. },
  315. }
  316. }
  317. </script>
  318. <style lang="scss" scoped>
  319. .publishPost{
  320. background-color: #fff;
  321. min-height: 100vh;
  322. font-size: 28rpx;
  323. padding-bottom: 150rpx;
  324. /deep/ .uv-textarea{
  325. background-color: transparent;
  326. border: none;
  327. }
  328. /deep/ .uv-textarea__count{
  329. background-color: transparent !important;
  330. }
  331. .box{
  332. padding: 0 20rpx;
  333. }
  334. .images{
  335. display: flex;
  336. flex-wrap: wrap;
  337. padding: 20rpx;
  338. }
  339. .title-input{
  340. margin: 10rpx;
  341. border-bottom: 1px solid #00000015;
  342. padding-bottom: 25rpx;
  343. margin-bottom: 15rpx;
  344. display: flex;
  345. align-items: center;
  346. justify-content: space-between;
  347. input{
  348. width: 100%;
  349. }
  350. .shop-box{
  351. .title{
  352. font-size: 28rpx;
  353. }
  354. .desc{
  355. margin-top: 10rpx;
  356. color: #888;
  357. font-size: 24rpx;
  358. }
  359. }
  360. }
  361. .content-input{
  362. min-height: 400rpx;
  363. /deep/ .uv-textarea{
  364. min-height: 400rpx;
  365. }
  366. }
  367. .upTop{
  368. .title{
  369. padding-top: 20rpx;
  370. padding-left: 20rpx;
  371. border-top: 1px solid #00000015;
  372. display: flex;
  373. align-items: center;
  374. }
  375. .list{
  376. padding-top: 30rpx;
  377. width: 100%;
  378. .item{
  379. display: flex;
  380. padding: 20rpx;
  381. padding-left: 80rpx;
  382. justify-content: space-between;
  383. width: 600rpx;
  384. border-bottom: 1px solid #00000015;
  385. align-items: center;
  386. }
  387. }
  388. }
  389. .configBtn{
  390. padding: 20rpx;
  391. color: #777;
  392. padding-top: 40rpx;
  393. font-size: 28rpx;
  394. }
  395. .confirmationPopup{
  396. display: flex;
  397. flex-direction: column;
  398. align-items: center;
  399. justify-content: center;
  400. width: 100%;
  401. height: 300rpx;
  402. image{
  403. margin-top: 40rpx;
  404. }
  405. .info{
  406. margin-top: 40rpx;
  407. font-size: 26rpx;
  408. }
  409. }
  410. }
  411. .category{
  412. padding: 20rpx;
  413. .title{
  414. // font-weight: 900;
  415. // font-size: 30rpx;
  416. }
  417. .tagList{
  418. display: flex;
  419. flex-wrap: wrap;
  420. padding: 10rpx 0;
  421. view{
  422. background: rgba($uni-color, 0.1);
  423. padding: 10rpx 20rpx;
  424. margin: 10rpx;
  425. border-radius: 10rpx;
  426. font-size: 26rpx;
  427. }
  428. .act{
  429. color: #fff;
  430. background: $uni-color;
  431. }
  432. }
  433. }
  434. </style>