LeftContent.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { css, cx } from "@linaria/core";
  2. import { useAuth } from "@queenjs-modules/auth";
  3. import {
  4. IconCamera,
  5. IconDashboard,
  6. IconDownload,
  7. IconSettings,
  8. } from "@queenjs/icons";
  9. import { Avatar, Divider } from "ant-design-vue";
  10. import { defineComponent } from "vue";
  11. import { array, object } from "vue-types";
  12. import Logo from "./Logo";
  13. export default defineComponent({
  14. setup() {
  15. const auth = useAuth();
  16. const footerOptions: TextListProps[] = [
  17. {
  18. label: "退出",
  19. icon: IconDownload,
  20. onClick: auth.actions.logout,
  21. },
  22. ];
  23. const menuOptions = [
  24. {
  25. link: "/workbench/promotion",
  26. label: "我的推广",
  27. icon: IconDashboard,
  28. // suffix: "7",
  29. },
  30. {
  31. link: "/workstage/material",
  32. label: "我的素材",
  33. icon: IconCamera,
  34. // suffix: "32",
  35. },
  36. {
  37. link: "/settings",
  38. label: "设置",
  39. icon: IconSettings,
  40. },
  41. ];
  42. return () => {
  43. const { userInfo } = auth.store;
  44. return (
  45. <div class={cx(rootStyles, "p-30px h-1/1 flex flex-col")}>
  46. <div class="mt-20px">
  47. <Logo />
  48. </div>
  49. <div class="my-50px flex items-center">
  50. <Avatar size={76} src={userInfo.avatar} />
  51. <div class="ml-20px flex-1">
  52. <p class="mb-10px text-16px font-bold">{userInfo.name}</p>
  53. <div class="text-12px text-gray">
  54. {userInfo.desc || "这个人很懒,什么都没留下..."}
  55. </div>
  56. </div>
  57. </div>
  58. <router-link to="/">
  59. <TextListItem
  60. option={{
  61. label: "资源中心",
  62. suffix: <span class="icon_new">new</span>,
  63. icon: (
  64. <img
  65. class="w-18px mr-10px"
  66. src={require("@/assets/imgs/img-resource.png")}
  67. alt=""
  68. />
  69. ),
  70. }}
  71. />
  72. </router-link>
  73. <Divider />
  74. <div class="flex-1">
  75. {menuOptions?.map((option, index) => (
  76. <router-link to={option.link} key={index}>
  77. <TextListItem key={index} option={option} />
  78. </router-link>
  79. ))}
  80. </div>
  81. <div class="mb-30px">
  82. <TextList options={footerOptions} />
  83. </div>
  84. </div>
  85. );
  86. };
  87. },
  88. });
  89. const rootStyles = css`
  90. .icon_new {
  91. border-radius: 14px;
  92. padding: 5px 10px;
  93. text-transform: uppercase;
  94. font-size: 12px;
  95. line-height: 1;
  96. background: linear-gradient(90deg, #9788ff 0%, #7e6bff 100%);
  97. color: #fff;
  98. }
  99. .router-link-exact-active {
  100. display: block;
  101. border-radius: 4px;
  102. background-color: #414141;
  103. > div {
  104. color: @inf-text-color;
  105. }
  106. }
  107. `;
  108. type TextListProps = {
  109. label?: string;
  110. suffix?: any;
  111. icon?: any;
  112. link?: string;
  113. onClick?: () => void;
  114. };
  115. const TextList = defineComponent({
  116. props: {
  117. options: array<TextListProps>(),
  118. },
  119. setup(props) {
  120. return () => {
  121. return (
  122. <div>
  123. {props.options?.map((option, index) => (
  124. <TextListItem key={index} option={option} />
  125. ))}
  126. </div>
  127. );
  128. };
  129. },
  130. });
  131. const TextListItem = defineComponent({
  132. props: { option: object<TextListProps>() },
  133. setup(props) {
  134. return () => {
  135. const { option = {} } = props;
  136. return (
  137. <div
  138. class={cx("flex items-center justify-between", itemStyles)}
  139. onClick={() => option.onClick?.()}
  140. >
  141. {option.icon && <option.icon class="mr-8px text-20px" />}
  142. <div class="flex-1">{option.label}</div>
  143. {option.suffix && typeof option.suffix == "string" ? (
  144. <span>{option.suffix}</span>
  145. ) : (
  146. option.suffix
  147. )}
  148. </div>
  149. );
  150. };
  151. },
  152. });
  153. const itemStyles = css`
  154. margin-top: 10px;
  155. border-radius: 4px;
  156. padding: 10px 25px 10px 20px;
  157. color: @inf-text-sub-color;
  158. cursor: pointer;
  159. &:hover {
  160. background: #414141;
  161. }
  162. `;