SourceItem.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import Thumbnail from "@/components/Thumbnail";
  2. import { css, cx } from "@linaria/core";
  3. import { useAuth } from "@queenjs-modules/auth";
  4. import { IconMore } from "@queenjs/icons";
  5. import { Dropdown, Menu, Tag } from "ant-design-vue";
  6. import dayjs from "dayjs";
  7. import { defineUI } from "queenjs";
  8. import { defineComponent, reactive } from "vue";
  9. import { any, bool, object } from "vue-types";
  10. const VideoItem = defineComponent({
  11. props: {
  12. record: object<any>(),
  13. },
  14. emits: ["click"],
  15. setup(props, { emit }) {
  16. const state = reactive({
  17. play: false,
  18. });
  19. return () => {
  20. const { record } = props;
  21. const { play } = state;
  22. return (
  23. <div
  24. style={{ aspectRatio: 1.5 }}
  25. class="overflow-hidden"
  26. onMouseenter={() => (state.play = true)}
  27. onMouseleave={() => (state.play = false)}
  28. onClick={() => emit("click", record.file.url)}
  29. >
  30. {!play ? (
  31. <Thumbnail
  32. class="w-1/1 h-1/1"
  33. size={240}
  34. objectContain={false}
  35. src={record.thumbnail}
  36. />
  37. ) : (
  38. <video
  39. muted
  40. autoplay
  41. controls={false}
  42. src={record.file.url}
  43. class="w-1/1 h-1/1 object-cover"
  44. />
  45. )}
  46. </div>
  47. );
  48. };
  49. },
  50. });
  51. const ImageItem = defineComponent({
  52. props: {
  53. record: object<any>(),
  54. },
  55. emits: ["click"],
  56. setup(props, { emit }) {
  57. return () => {
  58. const { record } = props;
  59. return (
  60. <Thumbnail
  61. size={240}
  62. class="draggable-item"
  63. style={{ aspectRatio: 1 }}
  64. onClick={() => emit("click", record.file.url)}
  65. objectContain={true}
  66. src={record.file.url}
  67. />
  68. );
  69. };
  70. },
  71. });
  72. export default defineUI({
  73. props: {
  74. record: any(),
  75. tagable: bool().def(false),
  76. isVideo: bool().def(false),
  77. },
  78. emits: ["edit", "preview", "menu", "click"],
  79. setup(props, { emit }) {
  80. const auth = useAuth();
  81. const state = reactive({
  82. play: false,
  83. });
  84. return () => {
  85. const { record } = props;
  86. //@ts-ignore
  87. const isSys = (auth.store.userInfo.roles || []).indexOf("system") > -1;
  88. return (
  89. <div class={cx(itemStyles, "relative")}>
  90. {props.isVideo ? (
  91. <VideoItem
  92. onClick={(data) => emit("click", data)}
  93. record={props.record}
  94. />
  95. ) : (
  96. <ImageItem
  97. onClick={(data) => emit("click", data)}
  98. record={props.record}
  99. />
  100. )}
  101. {isSys && props.tagable && (
  102. <Tag
  103. color={record.published ? "green" : "#E88B00"}
  104. // color="rgba(0, 0, 0, 0.4)"
  105. class="absolute top-0 left-0 z-1 !rounded-none"
  106. >
  107. {record.published ? "已发布" : "未发布"}
  108. </Tag>
  109. )}
  110. {props.tagable && (
  111. <div class="item_footer rounded-b-4px flex items-center justify-between p-4px">
  112. <div class="flex-1 w-0">
  113. {/* <div class="text-white text-bold truncate">{record.title}</div> */}
  114. <div class="flex items-center text-opacity-60 text-white text-12px">
  115. {dayjs(record.createTime).format("YYYY.MM.DD")}
  116. </div>
  117. </div>
  118. <Dropdown
  119. placement="bottom"
  120. overlay={
  121. <Menu class="w-90px">
  122. <Menu.Item>
  123. <div onClick={() => emit("menu", "delete")}>删除</div>
  124. </Menu.Item>
  125. {isSys && !record.published && (
  126. <Menu.Item>
  127. <div onClick={() => emit("menu", "publish")}>
  128. 发布平台
  129. </div>
  130. </Menu.Item>
  131. )}
  132. {isSys && record.published && (
  133. <Menu.Item>
  134. <div onClick={() => emit("menu", "unpublish")}>
  135. 取消发布
  136. </div>
  137. </Menu.Item>
  138. )}
  139. </Menu>
  140. }
  141. >
  142. <IconMore class="ml-10px text-22px cursor-pointer" />
  143. </Dropdown>
  144. </div>
  145. )}
  146. </div>
  147. );
  148. };
  149. },
  150. });
  151. const itemStyles = css`
  152. .item_footer {
  153. background: #414141;
  154. }
  155. .icon_action {
  156. background-color: rgba(0, 0, 0, 0.8);
  157. &.orange {
  158. background-color: rgba(232, 139, 0, 0.8);
  159. }
  160. }
  161. `;