裂变星小程序-25.03.04
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.

403 lines
10 KiB

6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
  1. <template>
  2. <view class="page">
  3. <navbar title="文章分享" leftClick @leftClick="$utils.navigateBack" />
  4. <view class="content">
  5. <uv-form
  6. ref="form"
  7. :model="form"
  8. :rules="getRules()"
  9. labelPosition="left"
  10. labelWidth="300rpx"
  11. :labelStyle="{
  12. color: '#1B1B1B',
  13. fontSize: '32rpx',
  14. fontWeight: 'bold',
  15. }"
  16. errorType="toast"
  17. >
  18. <view class="form-item">
  19. <uv-form-item label="用户ID" prop="userId">
  20. <view class="form-item-content">
  21. <text>{{ userId }}</text>
  22. <view style="margin-left: 20rpx;">
  23. <button class="btn-simple" plain @click="$utils.copyText(userId)">
  24. <uv-icon name="file-text" color="#05D9A2" size="28rpx"></uv-icon>
  25. </button>
  26. </view>
  27. </view>
  28. </uv-form-item>
  29. </view>
  30. <view class="form-item">
  31. <uv-form-item label="选择封面图" prop="headImage">
  32. <view class="form-item-content">
  33. <formUpload v-model="form.headImage">
  34. <template v-slot="{ value }">
  35. <view class="flex" style="min-width: 116rpx; height: 45rpx;">
  36. <image
  37. :src="value"
  38. mode="aspectFill"
  39. style="width: 68rpx; height: 68rpx;"
  40. radius="14rpx"
  41. />
  42. <uv-icon style="margin-left: 20rpx" name="arrow-right" color="#000000" size="28rpx"></uv-icon>
  43. </view>
  44. </template>
  45. </formUpload>
  46. </view>
  47. </uv-form-item>
  48. </view>
  49. <view class="form-item">
  50. <uv-form-item label="标题" labelWidth="84rpx" prop="headTitle">
  51. <view class="form-item-content">
  52. <formInput v-model="form.headTitle" placeholder="请输入你的文章标题" width="584rpx"></formInput>
  53. </view>
  54. </uv-form-item>
  55. </view>
  56. <view class="form-item">
  57. <uv-form-item label="设置转发次数(次)" prop="num">
  58. <view class="form-item-content">
  59. <formNumberBox v-model="form.num" ></formNumberBox>
  60. </view>
  61. </uv-form-item>
  62. </view>
  63. <view class="form-item">
  64. <uv-form-item label="选择二维码" prop="wxCodeImage">
  65. <view class="form-item-content">
  66. <formUpload v-model="form.wxCodeImage">
  67. <template v-slot="{ value }">
  68. <view class="flex" style="min-width: 93rpx; height: 45rpx;">
  69. <image
  70. :src="value"
  71. mode="aspectFill"
  72. style="width: 45rpx; height: 45rpx;"
  73. radius="14rpx"
  74. />
  75. <uv-icon style="margin-left: 20rpx" name="arrow-right" color="#000000" size="28rpx"></uv-icon>
  76. </view>
  77. </template>
  78. </formUpload>
  79. </view>
  80. </uv-form-item>
  81. </view>
  82. <view class="form-item">
  83. <uv-form-item label="文章内容" prop="textDetails" labelPosition="top">
  84. <view class="editor__view" style="margin-top: 32rpx;">
  85. <editor id="editor" class="editor"
  86. placeholder="请输入你的文章内容"
  87. @ready="onEditorReady"
  88. @input="onEditroInput"
  89. ></editor>
  90. <view class="flex editor-tools">
  91. <view style="flex: 1;">
  92. <button @click="insertImage" plain class="btn-simple" style="float: left; font-size: 0;">
  93. <image src="../static/record/icon-add.png" style="width: 126rpx; height: 126rpx;" ></image>
  94. </button>
  95. </view>
  96. <view style="flex: 1; text-align: right;">
  97. <text class="editor-count">{{ `${descLen}/${descLengthLimit}` }}</text>
  98. </view>
  99. </view>
  100. </view>
  101. </uv-form-item>
  102. </view>
  103. </uv-form>
  104. </view>
  105. <!-- 审核通过 -->
  106. <button v-if="status === 1" class="button-submit" open-type="share">
  107. 发布
  108. </button>
  109. <!-- 不是 审核中 已发布 -> 创建分享 审核不通过 -->
  110. <button v-else-if="![0,1].includes(status)" class="button-submit" @click="preSubmit">
  111. 提交审核
  112. </button>
  113. <autoCrop ref="autoCropRef" @change="onSubmit"></autoCrop>
  114. </view>
  115. </template>
  116. <script>
  117. import { mapState } from 'vuex'
  118. import shareLog from '@/utils/shareLog'
  119. import formInput from '../components/formInput.vue'
  120. import formNumberBox from '../components/formNumberBox.vue'
  121. import formUpload from '../components/formUpload.vue'
  122. import formTextarea from '../components/formTextarea.vue'
  123. import autoCrop from '../components/autoCrop.vue'
  124. export default {
  125. components: {
  126. formInput,
  127. formNumberBox,
  128. formUpload,
  129. formTextarea,
  130. autoCrop,
  131. },
  132. data() {
  133. return {
  134. id: null,
  135. status: null,
  136. form: {
  137. userId: null,
  138. headImage: null,
  139. headTitle: null,
  140. num: 0,
  141. wxCodeImage: null,
  142. textDetails: null,
  143. },
  144. editorCtx: null,
  145. descLen: 0,
  146. descLengthLimit: 1000,
  147. }
  148. },
  149. computed: {
  150. ...mapState(['userInfo']),
  151. userId() {
  152. return this.userInfo?.intentionCode
  153. },
  154. },
  155. onLoad(option) {
  156. const { id } = option
  157. if (!id) {
  158. return
  159. }
  160. this.id = id
  161. this.fetchDetails(id)
  162. },
  163. onReady() {
  164. this.$refs.form.setRules(this.getRules());
  165. },
  166. onShareAppMessage(res) {
  167. const {
  168. headTitle,
  169. headImage,
  170. } = this.form
  171. let o = {
  172. title : headTitle,
  173. imageUrl: headImage,
  174. path: `/pages_order/sharing/article?id=${this.id}&state=3&shareId=${this.userInfo.id}`
  175. }
  176. //调用增加分享次数的方法
  177. const params = {
  178. id:this.id,
  179. state:"3",
  180. }
  181. this.$fetch('addLogShareInfo', params)
  182. shareLog.insert(this.id)
  183. this.isLocked = false
  184. return o
  185. },
  186. methods: {
  187. onEditorReady() {
  188. uni.createSelectorQuery().select('#editor').context((res) => {
  189. this.editorCtx = res.context
  190. }).exec()
  191. },
  192. onEditroInput(e) {
  193. const { text } = e.detail
  194. this.descLen = text?.length || 0
  195. },
  196. insertImage() {
  197. uni.chooseImage({
  198. count: 1,
  199. sizeType: ['original'],
  200. success: (res) => {
  201. // this.editorCtx.insertImage({
  202. // src: res.tempFilePaths[0],
  203. // alt: '图像',
  204. // })
  205. // todo: check
  206. this.$Oss.ossUpload(res.tempFilePaths[0]).then(url => {
  207. this.editorCtx.insertImage({
  208. src: url,
  209. alt: '图像',
  210. })
  211. })
  212. }
  213. })
  214. },
  215. setEditorContents(html) {
  216. if (!this.editorCtx) {
  217. setTimeout(() => {
  218. this.setEditorContents(html)
  219. }, 200)
  220. return
  221. }
  222. this.editorCtx.setContents({ html })
  223. },
  224. getEditorContents() {
  225. return new Promise((resolve, reject) => {
  226. this.editorCtx.getContents({
  227. success: (e) => {
  228. const { html, text } = e
  229. resolve({ html, text })
  230. },
  231. fail: () => {
  232. reject()
  233. }
  234. })
  235. })
  236. },
  237. getRules() {
  238. const textDetailsValidator = async (rule, value, callback) => {
  239. const textDetails = (await this.getEditorContents())?.html
  240. if (textDetails) {
  241. callback()
  242. return
  243. }
  244. callback(new Error('请输入文章内容'))
  245. }
  246. return {
  247. 'headImage': {
  248. type: 'string',
  249. required: true,
  250. message: '请选择封面图',
  251. },
  252. 'headTitle': {
  253. type: 'string',
  254. required: true,
  255. message: '请输入你的文章标题',
  256. },
  257. 'num': {
  258. type: 'number',
  259. required: true,
  260. message: '请设置转发次数(大于0)',
  261. validator: (rule, value, callback) => {
  262. if (value > 0) {
  263. return true
  264. }
  265. return false;
  266. },
  267. },
  268. 'wxCodeImage': {
  269. type: 'string',
  270. required: true,
  271. message: '请选择二维码',
  272. },
  273. 'textDetails': {
  274. asyncValidator: textDetailsValidator,
  275. },
  276. }
  277. },
  278. async fetchDetails(id) {
  279. try {
  280. const result = await this.$fetch('getArticleShareInfo', { id })
  281. const {
  282. userId,
  283. headImage,
  284. headTitle,
  285. num,
  286. wxCodeImage,
  287. textDetails,
  288. status,
  289. } = result || {}
  290. this.form = {
  291. userId,
  292. headImage,
  293. headTitle,
  294. num,
  295. wxCodeImage,
  296. textDetails,
  297. }
  298. this.status = status
  299. this.setEditorContents(textDetails)
  300. } catch (err) {
  301. }
  302. },
  303. async preSubmit() {
  304. try {
  305. await this.$refs.form.validate()
  306. this.$refs.autoCropRef.set(this.form.headImage)
  307. } catch (err) {
  308. }
  309. },
  310. async onSubmit(headImage) {
  311. try {
  312. await this.$refs.form.validate()
  313. const textDetails = (await this.getEditorContents())?.html
  314. const {
  315. headTitle,
  316. num,
  317. wxCodeImage,
  318. } = this.form
  319. const params = {
  320. userId: this.userId,
  321. headImage,
  322. headTitle,
  323. num,
  324. wxCodeImage,
  325. textDetails,
  326. }
  327. if (this.id) {
  328. params.id = this.id
  329. }
  330. await this.$fetch('saveOrUpdateArticleShare', params)
  331. uni.showToast({
  332. title: '提交成功',
  333. icon: 'none'
  334. })
  335. setTimeout(uni.navigateBack, 1000, -1)
  336. } catch (err) {
  337. }
  338. },
  339. }
  340. }
  341. </script>
  342. <style scoped lang="scss">
  343. @import '../styles/pageForm.scss';
  344. .editor__view {
  345. background-color: #F3F3F3;
  346. border-radius: 12rpx;
  347. }
  348. .editor {
  349. height: 253rpx;
  350. padding: 20rpx;
  351. &-tools {
  352. align-items: flex-end;
  353. padding: 0 20rpx 16rpx 14rpx;
  354. }
  355. &-count {
  356. color: #999999;
  357. font-size: 28rpx;
  358. }
  359. }
  360. </style>