LeftContent.tsx 4.2 KB

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