MonacoModal.vue_ 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <template>
  2. <div class="monaco-dialog">
  3. <t-dialog
  4. :header="title"
  5. :visible="visible"
  6. width="900px"
  7. :on-confirm="handleOk"
  8. :on-cancel="cancel"
  9. :on-close="cancel"
  10. >
  11. <t-radio-group
  12. v-if="options"
  13. size="small"
  14. v-model="currentValue"
  15. :default-value="0"
  16. @change="changeOption"
  17. >
  18. <t-tooltip
  19. v-for="option in options"
  20. :content="option.tip"
  21. placement="top"
  22. >
  23. <t-radio-button :value="option.value">
  24. {{ option.name }}</t-radio-button
  25. >
  26. </t-tooltip>
  27. </t-radio-group>
  28. <div ref="monacoDom" class="monaco"></div>
  29. </t-dialog>
  30. </div>
  31. </template>
  32. <script lang="ts">
  33. export interface monacoOption {
  34. key: string;
  35. value?: number | string;
  36. name?: string;
  37. tip?: string;
  38. code?: string;
  39. language: 'javascript' | 'json' | 'markdown';
  40. example?: string;
  41. }
  42. </script>
  43. <script setup lang="ts">
  44. import {
  45. defineComponent,
  46. nextTick,
  47. onMounted,
  48. onUnmounted,
  49. PropType,
  50. reactive,
  51. ref,
  52. watch,
  53. } from 'vue';
  54. import { monaco } from './customMonaco';
  55. const props = defineProps({
  56. visible: {
  57. type: Boolean,
  58. require: true,
  59. },
  60. title: {
  61. type: String,
  62. default: () => {
  63. return 'JavaScript';
  64. },
  65. },
  66. code: {
  67. type: String,
  68. default: () => {
  69. return '';
  70. },
  71. },
  72. language: {
  73. type: String,
  74. default: () => {
  75. return 'javascript';
  76. },
  77. validator: (value: string) => {
  78. // 这个值必须匹配下列字符串中的一个
  79. return ['javascript', 'json', 'markdown'].includes(value);
  80. },
  81. },
  82. options: {
  83. type: Array as PropType<monacoOption[]>,
  84. },
  85. });
  86. const emit = defineEmits(['update:visible', 'changeCode', 'changeOptions']);
  87. let editor: any = null;
  88. function handleOk() {
  89. // 按下确认以后修改外界值
  90. if (props.options) {
  91. props.options[currentValue.value].code = editor.getValue();
  92. emit('changeOptions', props.options);
  93. emit('update:visible', false);
  94. } else {
  95. const code = editor.getValue();
  96. emit('changeCode', code);
  97. emit('update:visible', false);
  98. }
  99. }
  100. function cancel() {
  101. emit('update:visible', false);
  102. }
  103. const curTheme = 'vs-dark'; // 暗主题
  104. const monacoDom: any = ref(null);
  105. const currentValue = ref(0);
  106. let beforeValue = 0;
  107. const changeOption = (e: number) => {
  108. if (editor && props.options) {
  109. if (beforeValue !== e) {
  110. props.options[beforeValue].code = editor.getValue();
  111. beforeValue = e;
  112. }
  113. monaco.editor.setModelLanguage(
  114. editor.getModel(),
  115. props.options[e].language || 'javascript'
  116. );
  117. editor.setValue(props.options[e].code || props.options[e].example || '');
  118. }
  119. };
  120. watch(
  121. () => props.visible,
  122. (newV) => {
  123. // console.log("props.visible", props.visible);
  124. if (newV) {
  125. nextTick(async () => {
  126. if (!editor) {
  127. editor = monaco.editor.create(monacoDom.value, {
  128. theme: curTheme,
  129. automaticLayout: true,
  130. language: props.language,
  131. });
  132. }
  133. if (props.options) {
  134. const option = props.options[currentValue.value];
  135. editor.setValue(option.code || option.example || '');
  136. monaco.editor.setModelLanguage(editor.getModel(), option.language);
  137. } else {
  138. // 可见状态
  139. editor.setValue(props.code);
  140. monaco.editor.setModelLanguage(editor.getModel(), props.language);
  141. }
  142. // 格式化
  143. // setTimeout(() => {
  144. // editor.getAction(["editor.action.formatDocument"])._run();
  145. // }, 300);
  146. });
  147. }
  148. }
  149. );
  150. onUnmounted(() => {
  151. editor?.dispose();
  152. });
  153. </script>
  154. <style lang="postcss" scoped>
  155. .monaco {
  156. height: 400px;
  157. }
  158. </style>