index.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <script setup lang="ts">
  2. import IframeEditor from "./iframe-editor.vue";
  3. import { useCompShallowRef } from "@/utils/useCompRef";
  4. import { magicApi } from "@/utils/database/magic-api-request";
  5. import { getAllWards } from "@/api/login";
  6. import XcElOption from "@/components/xiao-chan/xc-el-option/XcElOption.vue";
  7. import * as api from "@/api/dashboardEditor/dashboardEditor";
  8. import { type TDashboardTemplate } from "@/api/dashboardEditor/dashboardEditor";
  9. import { BizException, ExceptionEnum } from "@/utils/BizException";
  10. import { stringIsBlank } from "@/utils/blank-utils";
  11. import SystemDeptSelect from "@/components/system/dept-select/SystemDeptSelect.vue";
  12. import { getDept } from "@/api/public-api";
  13. const dashboardEditorRef = useCompShallowRef(IframeEditor);
  14. const store = reactive({
  15. dataSource: [] as { code: string; name: string; group: string }[],
  16. group: {},
  17. currentWard: null,
  18. wardList: [],
  19. currentTemplate: {} as null | TDashboardTemplate,
  20. collapseValue: "",
  21. templateType: 0,
  22. templateTypeList: [] as { code: number; name: string; url: string }[],
  23. });
  24. const tmpGroupDataSource = computed(() => {
  25. const tmp = {};
  26. store.dataSource.forEach(item => {
  27. if (tmp[item.group]) {
  28. tmp[item.group].push(item);
  29. } else {
  30. tmp[item.group] = [item];
  31. }
  32. });
  33. return tmp;
  34. });
  35. async function handleWardChange() {
  36. const { currentWard, templateType } = store;
  37. store.currentTemplate = await api.getDashboardTemplateByWardCode(
  38. currentWard,
  39. templateType
  40. );
  41. dashboardEditorRef.value.clearHtml();
  42. if (store.currentTemplate == null) {
  43. dashboardEditorRef.value.insertTable(17, 11);
  44. } else {
  45. dashboardEditorRef.value.setHtml(
  46. store.currentTemplate.htmlDataTemp || store.currentTemplate.htmlData || ""
  47. );
  48. }
  49. }
  50. function handleTemplateTypeChange() {
  51. queryDataSource();
  52. handleWardChange();
  53. }
  54. function queryDataSource() {
  55. const tmp = store.templateTypeList.find(item => {
  56. return item.code === store.templateType;
  57. });
  58. magicApi({
  59. url: tmp.url,
  60. method: "post",
  61. data: { isSource: true },
  62. })
  63. .then(res => {
  64. store.dataSource = res.data;
  65. store.group = res.group;
  66. })
  67. .catch(() => {
  68. store.dataSource = [];
  69. store.group = {};
  70. });
  71. }
  72. onMounted(() => {
  73. magicApi({
  74. url: "/public/dashboard/getTemplateType",
  75. method: "get",
  76. }).then(res => {
  77. store.templateTypeList = res;
  78. queryDataSource();
  79. });
  80. getDept()
  81. .then(res => {
  82. store.wardList = res;
  83. store.wardList.unshift({
  84. code: "defaultTemp",
  85. name: "默认模板",
  86. });
  87. })
  88. .catch(() => {
  89. store.wardList = [];
  90. });
  91. });
  92. async function handleSave(htmlData) {
  93. if (store.currentWard == null) {
  94. BizException(ExceptionEnum.MESSAGE_ERROR, "请先选择病区");
  95. }
  96. if (store.currentTemplate == null) {
  97. store.currentTemplate = {
  98. wardCode: store.currentWard,
  99. htmlDataTemp: htmlData,
  100. templateType: store.templateType,
  101. };
  102. } else {
  103. store.currentTemplate.htmlDataTemp = htmlData;
  104. store.currentTemplate.wardCode = store.currentWard;
  105. store.currentTemplate.templateType = store.templateType;
  106. }
  107. store.currentTemplate = await api.saveTemplate(store.currentTemplate);
  108. }
  109. async function handleRelease() {
  110. if (stringIsBlank(store.currentTemplate?.htmlDataTemp)) {
  111. BizException(ExceptionEnum.MESSAGE_ERROR, "请先设置模板");
  112. }
  113. if (stringIsBlank(store.currentTemplate?.id)) {
  114. BizException(ExceptionEnum.MESSAGE_ERROR, "请先保存");
  115. }
  116. await api.release(store.currentTemplate.id);
  117. }
  118. function handlePreview() {
  119. if (stringIsBlank(store.currentTemplate?.id)) {
  120. BizException(ExceptionEnum.MESSAGE_ERROR, "请先打开模板");
  121. }
  122. window.open(
  123. `${location.origin}/inpatientBoardV2?tempId=${store.currentTemplate.id}&ward=${store.currentWard}`,
  124. "_blank"
  125. );
  126. }
  127. defineOptions({
  128. name: "dashboardEditor",
  129. });
  130. </script>
  131. <template>
  132. <div class="layout_container layout-horizontal">
  133. <aside style="width: 15vw" class="layout_card">
  134. <div class="layout_container">
  135. <header>
  136. <el-alert
  137. type="error"
  138. effect="dark"
  139. title="列宽可能拖动,但是列高不行,因为高度是不确定的,发布后才能看到效果。"
  140. :closable="false"
  141. ></el-alert>
  142. <el-form style="width: 100%">
  143. <el-form-item label="病区:">
  144. <el-select
  145. style="width: 100%"
  146. v-model="store.currentWard"
  147. @change="handleWardChange"
  148. >
  149. <xc-el-option :data="store.wardList" />
  150. </el-select>
  151. </el-form-item>
  152. <el-form-item label="类型:">
  153. <el-select
  154. v-model="store.templateType"
  155. @change="handleTemplateTypeChange"
  156. >
  157. <xc-el-option :data="store.templateTypeList" />
  158. </el-select>
  159. </el-form-item>
  160. <el-form-item>
  161. <el-button type="primary" @click="handleRelease">发布</el-button>
  162. </el-form-item>
  163. </el-form>
  164. </header>
  165. <div class="layout_main layout_container">
  166. <el-divider>数据源</el-divider>
  167. <div style="padding: 10px" class="layout_main">
  168. <el-collapse>
  169. <el-collapse-item
  170. v-for="(value, key) in store.group"
  171. :title="value"
  172. >
  173. <el-row :gutter="10">
  174. <el-col
  175. style="margin-top: 8px"
  176. :span="24 / 3"
  177. v-for="item in tmpGroupDataSource[key]"
  178. @click="
  179. () => {
  180. dashboardEditorRef.insert(item);
  181. }
  182. "
  183. >
  184. <el-tag size="large" style="width: 100%">
  185. {{ item.name }}
  186. </el-tag>
  187. </el-col>
  188. </el-row>
  189. </el-collapse-item>
  190. </el-collapse>
  191. </div>
  192. </div>
  193. </div>
  194. </aside>
  195. <div class="layout_main">
  196. <IframeEditor ref="dashboardEditorRef" @save="handleSave" />
  197. </div>
  198. </div>
  199. </template>
  200. <style lang="scss"></style>