Menu.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <ElMenu class="menu" mode="horizontal" @select="handleSelect">
  3. <ElMenuItem class="menu-logo" index="logo" disabled>
  4. Devcloud
  5. </ElMenuItem>
  6. <ElSubmenu index="project">
  7. <template #title>{{selectedProject.name}}</template>
  8. <template v-if="projectList.length > 0">
  9. <ElMenuItem v-for="project in projectList" :key="project.id" :index="`project-${project.id}`">{{project.name}}</ElMenuItem>
  10. </template>
  11. <template v-else>
  12. <ElMenuItem disabled>暂无项目</ElMenuItem>
  13. </template>
  14. </ElSubmenu>
  15. <template v-if="userLoggedIn">
  16. <ElSubmenu index="user" class="user">
  17. <template #title>{{userInfo.username}}</template>
  18. <ElMenuItem index="user-project">创建项目</ElMenuItem>
  19. <ElMenuItem index="user-invite">邀请成员</ElMenuItem>
  20. <ElMenuItem index="user-logout">登出</ElMenuItem>
  21. </ElSubmenu>
  22. </template>
  23. <template v-else>
  24. <ElButton type="text" @click="login" class="user">登录</ElButton>
  25. </template>
  26. </ElMenu>
  27. <ElDrawer v-model="showProjectDrawer">
  28. <template #title><span>创建项目</span></template>
  29. <div class="drawer-content">
  30. <div class="form-container">
  31. <ElForm :model="createProjectForm">
  32. <ElFormItem label="项目名" prop="name">
  33. <ElInput v-model="createProjectForm.name" placeholder="请输入要创建的项目名"></ElInput>
  34. </ElFormItem>
  35. <ElFormItem label="项目描述" prop="description">
  36. <ElInput
  37. v-model="createProjectForm.description"
  38. placeholder="请输入项目描述"
  39. type="textarea"
  40. :autosize="{ minRows: 3, maxRows: 3}"
  41. ></ElInput>
  42. </ElFormItem>
  43. <ElFormItem>
  44. <ElButton @click="createProject" type="primary">创建</ElButton>
  45. </ElFormItem>
  46. </ElForm>
  47. </div>
  48. </div>
  49. </ElDrawer>
  50. <ElDrawer v-model="showInviteDrawer">
  51. <template #title><span>邀请成员</span></template>
  52. <div class="drawer-content">
  53. <div class="form-container">
  54. <ElForm :model="inviteProjectForm">
  55. <ElFormItem label="项目" prop="projectId">
  56. <ElSelect v-model="inviteProjectForm.projectId" placeholder="请选择成员将要加入的项目">
  57. <ElOption v-for="project in projectList" :key="project.id" :value="project.id" :label="project.name"></ElOption>
  58. </ElSelect>
  59. </ElFormItem>
  60. <ElFormItem label="手机号" prop="phone">
  61. <ElInput v-model="inviteProjectForm.phone" placeholder="请输入成员注册所用手机号"></ElInput>
  62. </ElFormItem>
  63. <ElFormItem>
  64. <ElButton @click="inviteMember" type="primary">邀请</ElButton>
  65. </ElFormItem>
  66. </ElForm>
  67. </div>
  68. </div>
  69. </ElDrawer>
  70. </template>
  71. <script lang="ts">
  72. import { ElMessage } from 'element-plus';
  73. import { useProjectList } from '@/composable/useProject';
  74. import { useUser } from '@/composable/useUser';
  75. import { defineComponent, ref, reactive } from 'vue';
  76. import { PortalAPI, ProjectAPI } from '@/api';
  77. import { WorkspaceDispatcher } from '@/store/dispatchers';
  78. export default defineComponent({
  79. name: 'Menu',
  80. setup() {
  81. const { projectList, selectedProject, handleProjectChange } = useProjectList();
  82. const { userInfo, userLoggedIn, userLogOut } = useUser();
  83. const showProjectDrawer = ref(false);
  84. const showInviteDrawer = ref(false);
  85. const openProjectDrawer = () => {
  86. showProjectDrawer.value = true;
  87. };
  88. const openInviteDrawer = () => {
  89. showInviteDrawer.value = true;
  90. };
  91. const createProjectForm = reactive({
  92. name: '',
  93. description: '',
  94. });
  95. const createProject = async () => {
  96. await ProjectAPI.createProject(createProjectForm.name, createProjectForm.description);
  97. showProjectDrawer.value = false;
  98. WorkspaceDispatcher.refreshProjectList();
  99. };
  100. interface InviteProjectForm {
  101. projectId: undefined | number;
  102. phone: string;
  103. }
  104. const inviteProjectForm = reactive<InviteProjectForm>({
  105. projectId: undefined,
  106. phone: '',
  107. });
  108. const inviteMember = async () => {
  109. let invitedUserId: number;
  110. const res = await PortalAPI.getUserIdByPhoneNumber(inviteProjectForm.phone) as unknown as {id: number};
  111. if (res) {
  112. invitedUserId = res.id;
  113. } else {
  114. ElMessage({
  115. type: 'error',
  116. message: '成员不存在,请再次确认手机号',
  117. });
  118. return;
  119. }
  120. if (!inviteProjectForm.projectId) {
  121. ElMessage({
  122. type: 'error',
  123. message: '请选择有效的项目',
  124. });
  125. return;
  126. }
  127. await ProjectAPI.addProjectMember({
  128. projectId: inviteProjectForm.projectId,
  129. invitedUserId,
  130. });
  131. showInviteDrawer.value = false;
  132. if (selectedProject.value.id !== -1) { WorkspaceDispatcher.changeProject(selectedProject.value.id); }
  133. };
  134. const handleSelect = (index: string) => {
  135. const [type, id] = index.split('-');
  136. switch (type) {
  137. case 'logo': {
  138. break;
  139. }
  140. case 'project': {
  141. handleProjectChange(parseInt(id, 10));
  142. break;
  143. }
  144. case 'user': {
  145. if (id === 'project') {
  146. openProjectDrawer();
  147. } else if (id === 'invite') {
  148. openInviteDrawer();
  149. } else if (id === 'logout') {
  150. userLogOut();
  151. }
  152. break;
  153. }
  154. default:
  155. console.warn('unknown type of sub-menu');
  156. break;
  157. }
  158. };
  159. const login = () => {
  160. window.location = `http://${process.env.VUE_APP_PORTAL_HOST}/api/interaction?scope=openid&client_id=seec-seec&redirect_uri=${
  161. encodeURI(`http://${window.location.host}/`)
  162. }` as unknown as Location;
  163. };
  164. return {
  165. projectList,
  166. selectedProject,
  167. handleSelect,
  168. userInfo,
  169. userLoggedIn,
  170. userLogOut,
  171. showProjectDrawer,
  172. showInviteDrawer,
  173. createProjectForm,
  174. createProject,
  175. inviteProjectForm,
  176. inviteMember,
  177. login,
  178. };
  179. },
  180. });
  181. </script>
  182. <style scoped>
  183. .menu {
  184. width: 100%;
  185. }
  186. .menu-logo {
  187. color: #000000;
  188. font-size: 24px;
  189. font-weight: bolder;
  190. line-height: 58px;
  191. margin-left: 30px;
  192. transition: all .2s linear;
  193. user-select: none;
  194. }
  195. .menu-logo.is-disabled {
  196. opacity: 1;
  197. cursor: default;
  198. }
  199. .user {
  200. float: right;
  201. height: 60px;
  202. margin: 0 20px;
  203. }
  204. .drawer-content {
  205. display: flex;
  206. justify-content: center;
  207. }
  208. .form-container {
  209. width: 80%;
  210. }
  211. </style>