SourceItem.tsx 4.7 KB

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