SysnotionConfig.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <template>
  2. <div class="sysnotion-config">
  3. <div class="tophead">
  4. <div @click="rollback()"
  5. ><img src="@/views/message/reportmessage/img/rollback.png" />返回</div
  6. >
  7. <span >{{ disabled ? '新建' : '查看'}}系统通知</span>
  8. </div>
  9. <div class="content">
  10. <div class="left">
  11. <!-- 基本配置 -->
  12. <BasicInfo ref="basicInfoRef" :data-soure="ruleForm" :is-disabled="isDisabled" />
  13. <!-- 内容配置区域 -->
  14. <ContentConfig ref="contentConfigRef" :data-soure="ruleForm" :is-disabled="isDisabled" :key="initKey"/>
  15. <!-- 按钮区域 -->
  16. <div class="btns" v-if="disabled">
  17. <div style="position: absolute; right: 0; bottom: 0">
  18. <el-button @click="onCancel">取消</el-button>
  19. <el-button @click="onSave">暂存</el-button>
  20. <el-button type="primary" @click="submitForm">确定发布</el-button>
  21. </div>
  22. </div>
  23. </div>
  24. <!-- 实时预览 -->
  25. <RightCard :rule-form="ruleForm" />
  26. </div>
  27. </div>
  28. </template>
  29. <script lang="ts" setup>
  30. import { useRoute, useRouter } from 'vue-router';
  31. import { ref, reactive, onMounted, computed } from 'vue';
  32. import { storeToRefs } from 'pinia';
  33. import { ElMessage, ElMessageBox } from 'element-plus';
  34. import { useUserStore } from '@/store/modules/user';
  35. import {
  36. addSystemMessage,
  37. confirmReportConfig,
  38. updateSystemMessage,
  39. viewSystemMessage,
  40. } from '@/api/message/sysnotion-config';
  41. import {
  42. RuleFormView,
  43. MessageTypeEnum,
  44. ContentTypeEnum,
  45. RuleFormAdd,
  46. SysMessageStatus,
  47. } from './type';
  48. import { recipientTypeEnum } from '../systemNotifications/type';
  49. import BasicInfo from './compontents/BasicInfo.vue';
  50. import ContentConfig from './compontents/ContentConfig.vue';
  51. import RightCard from './compontents/RightCard.vue';
  52. const isDisabled = ref<boolean>(false); // 是可编辑还是只查看状态
  53. const useUser = useUserStore();
  54. const { info } = storeToRefs(useUser);
  55. const basicInfoRef = ref<InstanceType<typeof BasicInfo>>();
  56. const contentConfigRef = ref<InstanceType<typeof ContentConfig>>();
  57. const ruleForm = reactive<RuleFormView>({
  58. messageType: MessageTypeEnum.TEXT,
  59. title: '',
  60. bannerUrl: '',
  61. pushChannel: [],
  62. expirationTime: '',
  63. recipientType: recipientTypeEnum.all, // 默认全员
  64. userGroupList: [],
  65. customUserList: [],
  66. introduction: '',
  67. contentType: ContentTypeEnum.RICHTEXT,
  68. content: '',
  69. contentUrl: '',
  70. operator: info.value.nickname,
  71. status: SysMessageStatus.DRAFT,
  72. });
  73. // 原始数据副本
  74. // let originalData: RuleFormView = {
  75. // ...ruleForm,
  76. // };
  77. const router = useRouter();
  78. const rollback = () => {
  79. router.back();
  80. };
  81. const route = useRoute();
  82. const sysId = Number(route.query.id as string);
  83. const viewModel = route.query.viewModel as string;
  84. const initKey = ref(0)
  85. const disabled = computed(() => !isDisabled.value || viewModel === 'edit');
  86. /**
  87. * 获取当前系统配置信息
  88. */
  89. const fetchSystemMessage = async () => {
  90. // 首次暂存后切换到编辑模式,因为路由没有发生变化,组件也不会发生变化,
  91. // sysId会一直为undefined,但此时 ruleForm.id 是存在的
  92. const messageId = sysId || ruleForm.id;
  93. // 查看 或 编辑状态
  94. if (messageId) {
  95. isDisabled.value = true;
  96. const res = await viewSystemMessage(messageId);
  97. if (res.status === SysMessageStatus.DRAFT && viewModel === 'edit') {
  98. // 如果未发布,还是可以编辑的
  99. isDisabled.value = false;
  100. } else {
  101. isDisabled.value = true;
  102. }
  103. ruleForm.id = messageId;
  104. initKey.value += 1;
  105. Object.entries(res).forEach(([key, value]) => {
  106. ruleForm[key] = value;
  107. });
  108. }
  109. };
  110. /**
  111. * 取消按钮
  112. */
  113. const onCancel = () => {
  114. // TODO:比对数据。 暂时不上
  115. // const changes = compareData(ruleForm, originalData);
  116. ElMessageBox.confirm('你填写的数据若未及时保存,离开页面后将会丢失', '提示', {
  117. confirmButtonText: '确认取消',
  118. cancelButtonText: '继续留在页面',
  119. type: 'warning',
  120. })
  121. .then(() => {
  122. router.push('/message/systemNotifications');
  123. })
  124. .catch(() => {});
  125. };
  126. /**
  127. * 暂存功能。 未正式发布之前,可继续编辑
  128. */
  129. const onSave = async () => {
  130. try {
  131. await saveSysData();
  132. } catch (error) {
  133. ElMessage.error(error as string);
  134. }
  135. };
  136. const saveSysData = async() => {
  137. // 基础配置信息。
  138. const isValidSuccess = await basicInfoRef.value?.validate();
  139. const baseInfoData = await basicInfoRef.value?.buildFromData();
  140. if (!isValidSuccess) return;
  141. // 内容配置信息。
  142. const contentConfigData = contentConfigRef.value?.buildFormdata();
  143. const params: RuleFormAdd = {
  144. ...baseInfoData!,
  145. ...contentConfigData,
  146. };
  147. // 请求体,不需要 operator 和 status
  148. delete params.operator;
  149. delete params.status;
  150. const messageId = sysId || ruleForm.id;
  151. if (!messageId) {
  152. // 首次保存
  153. ruleForm.id = await addSystemMessage(params);
  154. ElMessage.success('暂存成功!');
  155. await router.replace(`/message/sys-notification?id=${ruleForm.id}`);
  156. fetchSystemMessage();
  157. } else {
  158. // 继续编辑
  159. await updateSystemMessage(params);
  160. ElMessage.success('编辑成功!');
  161. }
  162. }
  163. const submitForm = async() => {
  164. try {
  165. await saveSysData();
  166. if (!ruleForm.id) return;
  167. confirmReportConfig(ruleForm.id).then(() => {
  168. ElMessage({
  169. message: '下发成功!',
  170. type: 'success',
  171. });
  172. router.push('/message/systemNotifications');
  173. });
  174. } catch (error) {
  175. ElMessage.error(error as string);
  176. }
  177. };
  178. // 比对方法
  179. const compareData = (newData: RuleFormView, oldData: RuleFormView) => {
  180. const diff: Partial<Omit<RuleFormView, 'content'>> = {};
  181. for (const key in newData) {
  182. if (newData[key as keyof RuleFormView] !== oldData[key as keyof RuleFormView]) {
  183. diff[key as keyof RuleFormView] = newData[key as keyof RuleFormView];
  184. }
  185. }
  186. return diff;
  187. };
  188. onMounted(() => {
  189. fetchSystemMessage();
  190. });
  191. </script>
  192. <style lang="scss" scoped>
  193. .sysnotion-config {
  194. position: relative;
  195. height: calc(100vh - 64px - 18px);
  196. background-color: rgba(255, 255, 255, 1);
  197. box-sizing: border-box !important;
  198. .tophead {
  199. display: flex;
  200. gap: 20px;
  201. width: 100%;
  202. height: 50px;
  203. padding: 16px 0 14px 21px;
  204. border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  205. div {
  206. display: flex;
  207. align-items: center;
  208. font-weight: 400;
  209. font-size: 14px;
  210. color: #303133;
  211. line-height: 22px;
  212. cursor: pointer;
  213. img {
  214. margin-right: 4px;
  215. }
  216. }
  217. }
  218. .content {
  219. display: flex;
  220. width: 100%;
  221. height: calc(100vh - 64px - 18px - 50px);
  222. padding: 0 30px 0 0;
  223. .left {
  224. display: flex;
  225. flex-direction: column;
  226. flex: 1;
  227. position: relative;
  228. padding: 21px;
  229. border-right: 1px solid rgba(0, 0, 0, 0.06);
  230. overflow-y: auto;
  231. .el-form-outer {
  232. display: flex;
  233. flex-direction: column;
  234. gap: 32px;
  235. }
  236. .transprant {
  237. :deep(.el-form-item__label::before) {
  238. content: '**';
  239. opacity: 0;
  240. }
  241. }
  242. .btns {
  243. margin-top: 35px;
  244. flex: 1;
  245. width: 100%;
  246. position: relative;
  247. }
  248. }
  249. }
  250. }
  251. </style>