IntroUpdateModal.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <template>
  2. <!-- 只有当数据加载完成且 isVisible 为 true 时才显示页面 -->
  3. <div class="introduce-update-container" v-if="isVisible && !isLoading">
  4. <div class="input-group">
  5. <label for="title-input">标题:</label>
  6. <input id="title-input" v-model="updatedIntro.title" type="text" placeholder="请输入修改后标题">
  7. </div>
  8. <div class="input-group">
  9. <label>内容:</label>
  10. <!-- 使用富文本框组件 -->
  11. <RichTextEditor v-model="updatedIntro.intro" />
  12. </div>
  13. <div class="button-container">
  14. <button @click="updateIntro" :disabled="isUpdating" class="submit-button">提交更新</button>
  15. </div>
  16. </div>
  17. </template>
  18. <script setup lang="ts">
  19. import { ref, onMounted, watch } from 'vue';
  20. import axios from 'axios';
  21. import RichTextEditor from './RichTextEditor.vue';
  22. import { ElMessage } from 'element-plus';
  23. // 定义 targetId 和 isVisible 为 prop
  24. const props = defineProps({
  25. targetId: {
  26. type: Number,
  27. required: true
  28. },
  29. isVisible: {
  30. type: Boolean,
  31. default: false
  32. }
  33. });
  34. const emits = defineEmits(['updateSuccess']);
  35. // 存储更新用的介绍数据
  36. const updatedIntro = ref({
  37. title: '',
  38. intro: ''
  39. });
  40. // 更新状态
  41. const isUpdating = ref(false);
  42. // 加载状态
  43. const isLoading = ref(true);
  44. // 从后端获取介绍数据
  45. const fetchData = async () => {
  46. try {
  47. isLoading.value = true;
  48. const response = await axios.get(`https://soilgd.com:5000/software-intro/${props.targetId}`);
  49. const { title, intro } = response.data;
  50. // 仅将换行符替换为 <br>,避免影响视频标签
  51. let processedIntro = intro.replace(/\r\n/g, '<br>');
  52. updatedIntro.value.title = title;
  53. updatedIntro.value.intro = processedIntro;
  54. } catch (err: any) {
  55. console.error('请求数据时发生错误:', err.message);
  56. } finally {
  57. // 数据加载完成,将加载状态设为 false
  58. isLoading.value = false;
  59. }
  60. };
  61. onMounted(() => {
  62. console.log('子组件挂载时接收到的 targetId:', props.targetId);
  63. if (props.isVisible) {
  64. // 发起数据请求
  65. fetchData();
  66. }
  67. });
  68. // 监听 targetId 变化,当 targetId 改变时重新获取数据
  69. watch(() => props.targetId, (newTargetId, oldTargetId) => {
  70. console.log(`targetId 从 ${oldTargetId} 变为 ${newTargetId}`);
  71. if (props.isVisible) {
  72. fetchData();
  73. }
  74. });
  75. // 更新介绍信息
  76. const updateIntro = async () => {
  77. isUpdating.value = true;
  78. try {
  79. // 将 <br> 标签替换回换行符
  80. let processedIntro = updatedIntro.value.intro.replace(/<br>/gi, '\r\n');
  81. const dataToSend = {
  82. title: updatedIntro.value.title,
  83. intro: processedIntro
  84. };
  85. // 发送 PUT 请求更新数据http
  86. const response = await axios.put(`https://soilgd.com:5000/software-intro/${props.targetId}`, dataToSend, {
  87. headers: {
  88. 'Content-Type': 'application/json'
  89. }
  90. });
  91. console.log('介绍更新成功!');
  92. ElMessage.success('更新成功!');
  93. emits('updateSuccess');
  94. } catch (err: any) {
  95. if (err.response) {
  96. console.error(`服务器错误: ${err.response.status} - ${err.response.data.message}`);
  97. } else if (err.request) {
  98. console.error('网络连接错误,请检查网络设置。');
  99. } else {
  100. console.error('请求设置错误: ' + err.message);
  101. }
  102. } finally {
  103. isUpdating.value = false;
  104. }
  105. };
  106. </script>
  107. <style scoped lang="scss">
  108. .introduce-update-container {
  109. margin-top: 20px;
  110. padding: 20px;
  111. border: 1px solid #ccc;
  112. border-radius: 5px;
  113. width: 90%;
  114. margin-left: auto;
  115. margin-right: auto;
  116. /* 让容器高度自适应内容 */
  117. height: auto;
  118. overflow: auto;
  119. }
  120. .input-group {
  121. margin-bottom: 20px;
  122. display: flex;
  123. align-items: start; /* 让标签和输入框顶部对齐 */
  124. }
  125. .input-group label {
  126. min-width: 80px; /* 固定标签宽度 */
  127. margin-right: 10px;
  128. text-align: left; /* 文字左对齐 */
  129. }
  130. .input-group input,
  131. .input-group .rich-text-editor {
  132. flex: 1;
  133. padding: 10px;
  134. border: 1px solid #ccc;
  135. border-radius: 3px;
  136. /* 让输入框和富文本编辑器高度自适应内容 */
  137. height: auto;
  138. min-height: auto;
  139. }
  140. .button-container {
  141. text-align: right;
  142. margin-top: 10px; /* 增加按钮与输入框的间距 */
  143. }
  144. .submit-button {
  145. padding: 10px 20px;
  146. background-color: #007BFF;
  147. color: white;
  148. border: none;
  149. border-radius: 3px;
  150. cursor: pointer;
  151. transition: background-color 0.3s ease;
  152. &:hover {
  153. background-color: #0056b3;
  154. }
  155. &:disabled {
  156. background-color: #ccc;
  157. cursor: not-allowed;
  158. }
  159. }
  160. </style>