LeftContent.tsx 4.4 KB

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