index.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <div class="p-3 d-flex flex-cln">
  3. <div class="bg-fff flex1 ov-hd d-flex flex-cln">
  4. <div class="pd-16 d-flex a-c border-bottom">
  5. <div class="flex1 ov-hd">
  6. <span class="f-s-18 c-333 f-w-6">编辑会议宣传门户</span>
  7. <el-button @click="router.go(-1)" text type="primary">
  8. <el-icon>
  9. <Back />
  10. </el-icon>
  11. 返回上一级
  12. </el-button>
  13. </div>
  14. <div class="d-flex a-c">
  15. <el-button v-if="form.id" @click="setBgMusic">设置背景音乐</el-button>
  16. <el-button @click="router.go(-1)">取消</el-button>
  17. <el-button @click="previewTpl" type="primary">预览</el-button>
  18. </div>
  19. </div>
  20. <div class="flex1 ov-hd d-flex">
  21. <div class="bg-#fff w-200 box-sizing-border over-auto">
  22. <MeetingTplList v-if="meetid" :meetid="meetid" @selectItem="selectItem" :list="list"
  23. @setIndex="setIndexTpl" @addMeetingTpls="addMeetingTpls" @delete="deleteListTpl"
  24. @changeLabel="changeLabel"></MeetingTplList>
  25. </div>
  26. <div class="flex1 ov-hd d-flex flex-cln a-c bg-#f7f7f7">
  27. <div v-if="form.id" @click="changeLabel(form)" class="w-750 pd2-10-0 f-w-5 f-s-18">
  28. {{ form?.label }}
  29. <el-icon>
  30. <EditPen />
  31. </el-icon>
  32. </div>
  33. <MeetingTplH5 v-if="form.id" v-model="form" @activated="activated"
  34. @deleteItemEvents="deleteItemEvents" @muisc="setMuisc"></MeetingTplH5>
  35. </div>
  36. <div class="bg-#fff w-300">
  37. <MeetingTplEvents v-if="curEvent" v-model="curEvent" :dict="dict" @save="saveEevent" :list="list">
  38. </MeetingTplEvents>
  39. </div>
  40. </div>
  41. </div>
  42. </div>
  43. <H5ModelLook v-if="showPreviewTpl" v-model:show="showPreviewTpl" :src="previewTplStr" title="预览"></H5ModelLook>
  44. </template>
  45. <script setup lang="ts" name="ptpl-edit-index">
  46. import router from '@/router';
  47. import { MeetingTplH5, MeetingTplList, MeetingTplEvents } from '../../models';
  48. import { useRoute } from 'vue-router';
  49. import { httpRequests } from '@/utils/httpRequests';
  50. import { importFileGetUrls } from '@/utils/models';
  51. import { H5ModelLook } from '@/views/components';
  52. const VITE_APP_MEETING_URL = ref(import.meta.env.VITE_APP_MEETING_URL || '');
  53. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  54. const dict = proxy?.useDict('page_event')
  55. const { page_event } = toRefs<any>(dict);
  56. const showPreviewTpl = ref(false);
  57. // 获取地址栏参数
  58. const meetid = ref<string>('');
  59. const form = ref<any>({});
  60. onMounted(() => {
  61. const route = useRoute();
  62. meetid.value = (route.query.meetid as string) || '';
  63. });
  64. const curEvent = ref<any>(null);
  65. const activated = (item: any) => {
  66. curEvent.value = item;
  67. };
  68. const selectItem = (item: any) => {
  69. form.value.id = null;
  70. setTimeout(() => {
  71. form.value = { ...item };
  72. curEvent.value = null;
  73. }, 100);
  74. };
  75. const saveEevent = async (item: any) => {
  76. if (!form.value?.events || !form.value?.events.length) return;
  77. const index = form.value.events.findIndex((it: any) => it.id === item.id);
  78. if (index === -1) return;
  79. const oldItem = form.value.events[index];
  80. form.value.events[index] = { ...item, x: oldItem.x, y: oldItem.y, w: oldItem.w, h: oldItem.h };
  81. // 保存成功
  82. const res: any = await httpRequests.post(`/dgtmedicine/trainpage/edit`, form.value);
  83. if (!res || res.code !== 200) return;
  84. proxy?.$modal.msgSuccess('保存成功');
  85. };
  86. const deleteItemEvents = (item: any) => {
  87. if (curEvent.value?.id === item.id) {
  88. curEvent.value = null;
  89. }
  90. };
  91. // 预览
  92. const previewTplStr = ref<string>('');
  93. const previewTpl = async () => {
  94. if (!list.value?.length) {
  95. return proxy?.$modal.msgWarning('请先添加页面');
  96. }
  97. previewTplStr.value = `${VITE_APP_MEETING_URL.value}?id=${list.value[0].id}`;
  98. showPreviewTpl.value = true;
  99. };
  100. const list = ref<any>([]);
  101. const itemsData = ref<any>([]);
  102. const getList = async () => {
  103. const res: any = await httpRequests.get(`/dgtmedicine/trainpage/listByTrainId/${meetid.value}`,);
  104. if (!res || res.code !== 200) return;
  105. list.value = res.data;
  106. };
  107. const addMeetingTpls = async () => {
  108. const res: any[] = await importFileGetUrls(['png', 'jpg', 'jpeg'], true);
  109. // 过滤掉code不为200的
  110. if (!res || !res.length) return;
  111. const datas = res.filter(item => item.code === 200).map(item => item.data);
  112. const promises = datas.map(item => {
  113. return httpRequests.post('/dgtmedicine/trainpage/add', {
  114. trainId: meetid.value,
  115. label: '页面名称',
  116. img: item.url,
  117. homeFlag: 0,
  118. events: []
  119. });
  120. });
  121. const results = await Promise.all(promises);
  122. const successResults = results.filter(item => item && item.code === 200).map(item => item.data);
  123. if (!successResults.length) return;
  124. getList();
  125. }
  126. const deleteListTpl = async (item: any) => {
  127. ElMessageBox({
  128. title: '删除提示',
  129. cancelButtonText: '我再看看',
  130. confirmButtonText: '确认删除',
  131. showCancelButton: true,
  132. confirmButtonClass: 'el-button--danger',
  133. message: h('p', null, [h('div', null, ``), h('div', null, [h('span', null, '删除后页面和触发事件将同步删除,无法撤回,请谨慎操作!')])]),
  134. callback: async (action: string) => {
  135. if (action === 'confirm') {
  136. const res = await httpRequests.get(`/dgtmedicine/trainpage/remove/${item.id}`);
  137. if (res) {
  138. ElMessage.success('删除成功');
  139. if (item.id === form.value.id) {
  140. form.value = {};
  141. curEvent.value = null;
  142. }
  143. getList();
  144. }
  145. }
  146. }
  147. });
  148. };
  149. const setIndexTpl = async (item) => {
  150. ElMessageBox({
  151. title: '提示',
  152. cancelButtonText: '我再看看',
  153. confirmButtonText: '确认设置',
  154. showCancelButton: true,
  155. message: h('p', null, [h('div', null, ``), h('div', null, [h('span', null, '是否设置该页面为会议宣传门户首页?')])]),
  156. callback: async (action: string) => {
  157. if (action === 'confirm') {
  158. const res = await httpRequests.get(`/dgtmedicine/trainpage/setHomePage/${item.id}`);
  159. if (res) {
  160. ElMessage.success('设置成功');
  161. getList();
  162. }
  163. }
  164. }
  165. });
  166. }
  167. const setMuisc = (item: any) => {
  168. if (form.value.id === item.id) {
  169. form.value = { ...form.value, ...item }
  170. }
  171. };
  172. const changeLabel = async (item: any) => {
  173. const { value: label } = await ElMessageBox.prompt('请输入页面名称', '修改页面名称', {
  174. confirmButtonText: '保存',
  175. cancelButtonText: '取消',
  176. inputValue: item.label,
  177. inputPattern: /^(?!\s*$).+/,
  178. inputErrorMessage: '页面名称不能为空'
  179. });
  180. if (label !== undefined) {
  181. const res = await httpRequests.post('/dgtmedicine/trainpage/edit', { ...item, label });
  182. if (res && res.code === 200) {
  183. ElMessage.success('修改成功');
  184. getList();
  185. if (item.id === form.value.id) {
  186. form.value.label = label;
  187. }
  188. }
  189. }
  190. };
  191. // 设置背景音乐
  192. const setBgMusic = async () => {
  193. const res: any[] = await importFileGetUrls(['mp3'], false);
  194. if (!res || !res.length) return;
  195. const music = res.find(item => item.code === 200);
  196. if (!music || !music.data || !music.data.url) return;
  197. form.value.bgMusic = music.data.url;
  198. const musicParams = {
  199. id: form.value.id,
  200. bgmRact: form.value.bgmRact || {
  201. x: 100,
  202. y: 100,
  203. w: 50,
  204. h: 50
  205. },
  206. bgm: music.data.url
  207. };
  208. const saveRes = await httpRequests.post('/dgtmedicine/trainpage/setBgm', musicParams);
  209. if (saveRes && saveRes.code === 200) {
  210. ElMessage.success('设置背景音乐成功');
  211. getList();
  212. if (form.value.id) {
  213. form.value = { ...form.value, ...musicParams }
  214. }
  215. }
  216. };
  217. // 发布页面
  218. const publishTpl = async () => {
  219. if (!form.value?.id) {
  220. ElMessage.warning('请先选择一个页面进行发布');
  221. return;
  222. };
  223. const res: any = await httpRequests.post(`/dgtmedicine/trainpage/edit`, form.value);
  224. if (!res || res.code !== 200) return;
  225. ElMessage.success('发布成功');
  226. };
  227. onMounted(() => {
  228. getList();
  229. });
  230. </script>