小说网站前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
7.9 KiB

  1. <template>
  2. <el-dialog
  3. :model-value="visible"
  4. @update:model-value="$emit('update:visible', $event)"
  5. :title="isEdit ? '编辑作家信息' : '申请成为创作者'"
  6. width="500px"
  7. :show-close="true"
  8. :close-on-click-modal="false"
  9. center
  10. class="author-application-modal"
  11. >
  12. <div class="application-form">
  13. <div class="form-item">
  14. <div class="required-label">笔名</div>
  15. <el-input v-model="penName" placeholder="请输入..." />
  16. </div>
  17. <div class="form-item">
  18. <div class="required-label">简介</div>
  19. <el-input
  20. v-model="introduction"
  21. type="textarea"
  22. :rows="4"
  23. placeholder="请输入..."
  24. />
  25. </div>
  26. <el-button
  27. type="primary"
  28. class="submit-button"
  29. :loading="loading"
  30. :disabled="!isValid"
  31. @click="handleSubmit"
  32. >
  33. {{ isEdit ? '保存修改' : '成为创作者' }}
  34. </el-button>
  35. </div>
  36. </el-dialog>
  37. </template>
  38. <script>
  39. import { ref, computed, watch } from 'vue';
  40. import { ElMessage } from 'element-plus';
  41. import { useMainStore } from '@/store';
  42. import { writerApi } from '@/api/user';
  43. export default {
  44. name: 'AuthorApplicationModal',
  45. props: {
  46. visible: {
  47. type: Boolean,
  48. required: true
  49. }
  50. },
  51. emits: ['update:visible', 'application-success'],
  52. setup(props, { emit }) {
  53. const store = useMainStore();
  54. // 表单数据
  55. const penName = ref('');
  56. const introduction = ref('');
  57. const loading = ref(false);
  58. const writerId = ref(null); // 作家ID,用于判断是新增还是编辑
  59. const isEdit = ref(false); // 是否为编辑模式
  60. // 表单验证
  61. const isValid = computed(() => {
  62. return penName.value.trim() !== '' && introduction.value.trim() !== '';
  63. });
  64. // 获取作家信息
  65. const getMyWriter = async () => {
  66. try {
  67. // 首先检查用户是否已经是作家
  68. if (!store.isCurrentAuthor) {
  69. // 不是作家,直接进入申请模式
  70. resetForm();
  71. isEdit.value = false;
  72. return;
  73. }
  74. // 是作家,获取作家详细信息进行回显
  75. const response = await writerApi.getMyWriter();
  76. if (response.result) {
  77. const writerInfo = response.result;
  78. penName.value = writerInfo.name || '';
  79. introduction.value = writerInfo.details || '';
  80. writerId.value = writerInfo.id || null;
  81. isEdit.value = true;
  82. } else {
  83. // 虽然是作家但获取不到详细信息,仍然进入申请模式
  84. resetForm();
  85. isEdit.value = false;
  86. }
  87. } catch (error) {
  88. console.error('获取作家信息失败:', error);
  89. // 获取失败时,根据store中的作家状态来决定模式
  90. if (store.isCurrentAuthor) {
  91. // 是作家但获取信息失败,进入编辑模式但不填充信息
  92. resetForm();
  93. isEdit.value = true;
  94. } else {
  95. // 不是作家,进入申请模式
  96. resetForm();
  97. isEdit.value = false;
  98. }
  99. }
  100. };
  101. // 提交申请
  102. const handleSubmit = async () => {
  103. if (!isValid.value) {
  104. ElMessage.warning('请填写完整信息');
  105. return;
  106. }
  107. try {
  108. loading.value = true;
  109. // 准备提交数据
  110. const data = {
  111. penName: penName.value.trim(),
  112. details: introduction.value.trim()
  113. };
  114. // 如果是编辑模式,添加ID
  115. if (writerId.value) {
  116. data.id = writerId.value;
  117. }
  118. // 调用API
  119. const response = await writerApi.saveOrUpdateWriter(data);
  120. if (response.code === 200) {
  121. ElMessage.success(isEdit.value ? '修改成功' : '申请成功');
  122. // 如果是新申请成功,需要更新用户的作家状态
  123. if (!isEdit.value) {
  124. // 重新获取最新的用户信息以更新作家状态
  125. try {
  126. await store.fetchLatestUserInfo();
  127. } catch (error) {
  128. console.error('更新用户信息失败:', error);
  129. // 即使更新失败,也手动设置作家状态
  130. store.setAsAuthor();
  131. }
  132. }
  133. // 触发成功回调
  134. emit('application-success', {
  135. penName: penName.value,
  136. introduction: introduction.value,
  137. isEdit: isEdit.value
  138. });
  139. // 关闭弹窗
  140. emit('update:visible', false);
  141. } else {
  142. ElMessage.error(response.message || '提交失败,请稍后重试');
  143. }
  144. } catch (error) {
  145. console.error('提交失败:', error);
  146. ElMessage.error('提交失败,请稍后重试');
  147. } finally {
  148. loading.value = false;
  149. }
  150. };
  151. // 重置表单
  152. const resetForm = () => {
  153. penName.value = '';
  154. introduction.value = '';
  155. writerId.value = null;
  156. isEdit.value = false;
  157. };
  158. // 监听弹窗显示状态,打开时获取作家信息
  159. watch(
  160. () => props.visible,
  161. (newVisible) => {
  162. if (newVisible) {
  163. getMyWriter();
  164. }
  165. }
  166. );
  167. return {
  168. penName,
  169. introduction,
  170. loading,
  171. isValid,
  172. isEdit,
  173. handleSubmit
  174. };
  175. }
  176. };
  177. </script>
  178. <style lang="scss" scoped>
  179. @use 'sass:color';
  180. .author-application-modal {
  181. // 全局共享样式
  182. :deep(.el-input__wrapper),
  183. :deep(.el-textarea__inner),
  184. :deep(.el-button) {
  185. box-sizing: border-box;
  186. }
  187. :deep(.el-input__wrapper) {
  188. padding: 0 15px;
  189. height: 44px !important;
  190. line-height: 44px !important;
  191. }
  192. :deep(.el-input__inner),
  193. :deep(.el-textarea__inner) {
  194. font-size: 15px;
  195. }
  196. .application-form {
  197. padding: 10px 0;
  198. .form-item {
  199. margin-bottom: 20px;
  200. .required-label {
  201. margin-bottom: 8px;
  202. font-size: 14px;
  203. font-weight: 500;
  204. color: #333;
  205. &::before {
  206. content: '*';
  207. color: #f56c6c;
  208. margin-right: 4px;
  209. }
  210. }
  211. }
  212. .submit-button {
  213. width: 100%;
  214. height: 44px;
  215. margin-top: 10px;
  216. background-color: #0A2463;
  217. border-color: #0A2463;
  218. &:hover {
  219. background-color: color.adjust(#0A2463, $lightness: -10%);
  220. border-color: color.adjust(#0A2463, $lightness: -10%);
  221. }
  222. }
  223. }
  224. }
  225. </style>