publish.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <CommonTopBanner title="发贴图">
  3. <FlexCol position="relative" padding="space.lg" align="center">
  4. <ProvideVar
  5. :vars="{
  6. FieldBackgroundColor: 'transparent',
  7. UploaderListAddItemBackgroundImage: 'url(https://xy.wenlvti.net/app_static/images/village/ButtonUpload.png)',
  8. UploaderAddIcon: '',
  9. }"
  10. >
  11. <BackgroundBox
  12. backgroundImage="https://xy.wenlvti.net/app_static/images/village/BoxLarge.png"
  13. :backgroundCutBorder="[50,50,50,50]"
  14. :backgroundCutBorderSize="[50,50,50,50]"
  15. direction="column"
  16. gap="gap.md"
  17. width="95%"
  18. :padding="[40, 30]"
  19. >
  20. <Field v-model="title" type="text" placeholder="输入标题(可选)" :maxLength="30" />
  21. <Field
  22. v-model="content"
  23. type="text"
  24. multiline
  25. placeholder="说点什么吧..."
  26. :maxLength="1000"
  27. rows="20"
  28. :inputStyle="{
  29. height: '700rpx',
  30. }"
  31. showWordLimit
  32. />
  33. <Uploader
  34. ref="uploader"
  35. listType="grid"
  36. :maxUploadCount="9"
  37. :upload="uploadImage"
  38. @updateList="onUpdateList"
  39. />
  40. <FlexRow justify="flex-end" align="center">
  41. <Tbutton
  42. :title="title"
  43. :content="content"
  44. :images="images"
  45. @showAi="showAgentPopup = true"
  46. />
  47. </FlexRow>
  48. </BackgroundBox>
  49. <Height :height="50" />
  50. <FlexRow center>
  51. <PrimaryButton
  52. text="发布"
  53. width="500rpx"
  54. @click="publish"
  55. />
  56. </FlexRow>
  57. </ProvideVar>
  58. <Agent
  59. v-model:showAgentPopup="showAgentPopup"
  60. v-model:title="title"
  61. v-model:content="content"
  62. v-model:images="images"
  63. :villageInfo="villageInfoForAI.content.value ?? undefined"
  64. :tag="querys.tag"
  65. @upload="uploader?.pick()"
  66. @close="showAgentPopup = false"
  67. />
  68. </FlexCol>
  69. </CommonTopBanner>
  70. </template>
  71. <script setup lang="ts">
  72. import { onMounted, ref, watch } from 'vue';
  73. import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
  74. import { Debounce } from '@imengyu/imengyu-utils';
  75. import { confirm, toast, alert } from '@/components/dialog/CommonRoot';
  76. import { useAuthStore } from '@/store/auth';
  77. import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
  78. import { envVersion } from '@/common/config/AppCofig';
  79. import CommonContent from '@/api/CommonContent';
  80. import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
  81. import Field from '@/components/form/Field.vue';
  82. import Uploader, { type UploaderInstance } from '@/components/form/Uploader.vue';
  83. import FlexCol from '@/components/layout/FlexCol.vue';
  84. import ProvideVar from '@/components/theme/ProvideVar.vue';
  85. import FlexRow from '@/components/layout/FlexRow.vue';
  86. import Popup from '@/components/dialog/Popup.vue';
  87. import Agent from './components/agent.vue';
  88. import OfficialApi, { PostMessage } from '@/api/light/OfficialApi';
  89. import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
  90. import PrimaryButton from '@/common/components/PrimaryButton.vue';
  91. import Tbutton from './components/tbutton.vue';
  92. import Height from '@/components/layout/space/Height.vue';
  93. import type { UploaderAction, UploaderItem } from '@/components/form/Uploader';
  94. import { back, backAndCallOnPageBack } from '@/components/utils/PageAction';
  95. import LightVillageApi from '@/api/light/LightVillageApi';
  96. const { querys } = useLoadQuerys({
  97. tag: '',
  98. villageId: 0,
  99. }, () => {
  100. if (!(uni as any).shareToOfficialAccount) {
  101. alert({
  102. title: '提示',
  103. content: '抱歉,微信目前不支持在电脑端编写贴图,您可以在手机版微信中编写贴图哦!',
  104. }).then(() => {
  105. back();
  106. })
  107. return;
  108. }
  109. villageInfoForAI.load();
  110. });
  111. const authStore = useAuthStore();
  112. const title = ref('');
  113. const content = ref('');
  114. const images = ref<{
  115. url: string;
  116. localUrl: string;
  117. }[]>([]);
  118. const uploader = ref<UploaderInstance>();
  119. const showAgentPopup = ref(false);
  120. const saveDraftDebunce = new Debounce(1000, () => {
  121. if (title.value || content.value || images.value.length > 0) {
  122. uni.setStorageSync('postDraft', {
  123. title: title.value,
  124. content: content.value,
  125. images: images.value,
  126. });
  127. }
  128. });
  129. const villageInfoForAI = useSimpleDataLoader(async () => {
  130. const villageId = querys.value.villageId;
  131. if (villageId)
  132. return await LightVillageApi.getVillageDetails(villageId);
  133. return null;
  134. }, false);
  135. watch(title, () => saveDraftDebunce.executeWithDelay());
  136. watch(content, () => saveDraftDebunce.executeWithDelay());
  137. watch(images, () => saveDraftDebunce.executeWithDelay());
  138. function loadDraft() {
  139. const draft = uni.getStorageSync('postDraft');
  140. if (draft) {
  141. confirm({
  142. content: '您有上次编辑未完成的草稿,是否要从上次的编辑数据继续?',
  143. confirmText: '继续',
  144. cancelText: '取消',
  145. width: 580,
  146. }).then((res) => {
  147. if (res) {
  148. title.value = draft.title;
  149. content.value = draft.content;
  150. images.value = draft.images;
  151. uploader.value?.setList(images.value.map((image) => ({
  152. url: image.url,
  153. type: 'image',
  154. filePath: image.localUrl,
  155. state: image.url ? 'success' : 'notstart',
  156. })));
  157. } else {
  158. uni.removeStorageSync('postDraft');
  159. }
  160. });
  161. }
  162. }
  163. function uploadImage(item: UploaderAction) {
  164. item.onStart('正在上传');
  165. let task: UniApp.UploadTask | null = null;
  166. CommonContent.uploadFile(item.item.filePath, 'image', 'file', undefined, (_task) => {
  167. task = _task;
  168. task.onProgressUpdate((res) => {
  169. item.onProgress(res.progress);
  170. });
  171. })
  172. .then((res) => {
  173. item.onFinish({
  174. uploadedUrl: res.fullurl,
  175. previewUrl: res.fullurl,
  176. }, '上传成功');
  177. })
  178. .catch((err) => {
  179. item.onError(err);
  180. });
  181. return () => {
  182. task?.abort();
  183. };
  184. }
  185. function publish() {
  186. if (images.value.length === 0) {
  187. toast('请上传图片');
  188. return;
  189. }
  190. const data = {
  191. title: title.value,
  192. content: content.value,
  193. images: images.value.map((image) => image.localUrl),
  194. tags: [
  195. '亮乡源',
  196. `${querys.value.tag || '亮乡源'}`
  197. ],
  198. };
  199. console.log('data', data, authStore.userInfo);
  200. (uni as any).shareToOfficialAccount({
  201. ...data,
  202. success: (postObj: { postUrl: string }) => {
  203. OfficialApi.publishMessage(new PostMessage().setSelfValues({
  204. title: title.value,
  205. content: content.value,
  206. images: images.value.map((image) => image.url),
  207. image: images.value[0].url,
  208. path: `/pages/index`,
  209. villageId: querys.value.villageId,
  210. userId: authStore.userId,
  211. jumpUrl: postObj.postUrl,
  212. topicName: querys.value.tag || '亮乡源',
  213. })).then(() => {
  214. console.log('发布成功');
  215. }).catch((e) => {
  216. console.error(e);
  217. });
  218. uni.removeStorageSync('postDraft');
  219. toast('发布成功, 文章可能需要审核稍后才能展示');
  220. setTimeout(() => {
  221. backAndCallOnPageBack('refreshOfficialAccount', { })
  222. }, 2000);
  223. },
  224. fail: (error: any) => {
  225. console.error(error);
  226. toast('发布失败');
  227. },
  228. });
  229. }
  230. function onUpdateList(list: UploaderItem[]) {
  231. images.value = list.map((item) => ({
  232. url: item.uploadedPath || '',
  233. localUrl: item.filePath,
  234. }));
  235. }
  236. onMounted(() => {
  237. setTimeout(() => {
  238. loadDraft();
  239. if (envVersion === 'develop') {
  240. //showAgentPopup.value = true;
  241. }
  242. }, 1000);
  243. });
  244. </script>