preview.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. <template>
  2. <div class="editor-preview-wrapper">
  3. <div class="top">
  4. <div class="card-container">
  5. <div class="font">
  6. Preview: <span>{{ installStatus ? 'After' : 'Before' }}</span> DeNet Installed
  7. </div>
  8. <!-- 安装之后的卡片样式 -->
  9. <div class="content-after" v-show="installStatus" :style="{ 'width': reviewCanvasParams.width + 'px' }">
  10. <div class="head" :style="{ 'zoom': reviewCanvasParams.zoom }">
  11. <img :src="userInfo.avatarUrl" class="avatar" />
  12. <div class="article-wrapper">
  13. <div class="nickname">
  14. {{ userInfo.name }}
  15. </div>
  16. <div class="name">
  17. @{{ userInfo.nickName }}
  18. </div>
  19. </div>
  20. </div>
  21. <div class="after-cover-wrapper" :style="{ 'zoom': reviewCanvasParams.zoom }">
  22. <install-card :pre_view="true" :iframe_url="previewData.convertUrl"></install-card>
  23. </div>
  24. </div>
  25. <!-- 安装之前的卡片样式 -->
  26. <div class="content-before" v-show="!installStatus"
  27. :style="{ 'width': reviewCanvasParams.width + 'px' }">
  28. <div class="head" :style="{ 'zoom': reviewCanvasParams.zoom }">
  29. <img :src="userInfo.avatarUrl" class="avatar" />
  30. <div class="article-wrapper">
  31. <div class="nickname">
  32. {{ userInfo.name }}
  33. </div>
  34. <div class="name">
  35. @{{ userInfo.nickName }}
  36. </div>
  37. </div>
  38. </div>
  39. <div class="card-wrapper" :style="{ 'zoom': reviewCanvasParams.zoom }">
  40. <img class="cover" v-if="previewData.linkImagePath && previewData.appId"
  41. :src="previewData.linkImagePath" />
  42. <iframe class="iframe" :src="previewData.convertUrl" scrolling="no" v-else></iframe>
  43. <div class="bottom-bar">
  44. <div class="site-url">DeNet.me</div>
  45. <div class="desc">
  46. <template v-if="previewData.appId">
  47. {{ previewData.currentApp.linkTitle }}
  48. </template>
  49. <template v-else>
  50. {{ previewData.currentApp.defaultTit ? defaultLinkTitle :
  51. previewData.currentApp.name
  52. }}
  53. </template>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. <div class="setting">
  60. <div class="font">Settings</div>
  61. <slot></slot>
  62. </div>
  63. </div>
  64. <div class="bottom">
  65. <div class="btn" @click="publishHandler">NEXT</div>
  66. </div>
  67. </div>
  68. </template>
  69. <script setup>
  70. import { ref, defineEmits, reactive, defineProps, onMounted, nextTick, onUnmounted, watch } from "vue";
  71. import { message } from "ant-design-vue";
  72. import installCard from '@/view/content/tool-box/index.vue'
  73. import { postPublish } from "@/http/publishApi";
  74. import { getChromeStorage, setChromeStorage } from "@/uilts/chromeExtension"
  75. import { getUser } from "@/http/publishApi"
  76. let installStatus = ref(false);
  77. let userInfo = ref({});
  78. let submitIng = ref(false);
  79. let reviewCanvasParams = reactive({
  80. width: 620,
  81. zoom: 1
  82. });
  83. let timer = ref(null);
  84. let loadingHide = null;
  85. const props = defineProps({
  86. previewData: {
  87. type: Object,
  88. default: () => {
  89. return {
  90. convertUrl: '',
  91. originUrl: '',
  92. appId: ''
  93. }
  94. }
  95. },
  96. screenshotWebsiteData: {
  97. type: Object,
  98. default: () => {
  99. return {
  100. url: '',
  101. status: ''
  102. }
  103. }
  104. },
  105. defaultLinkTitle: {
  106. type: String,
  107. default: ''
  108. },
  109. showCom: {
  110. type: String,
  111. default: 'EDITOR'
  112. },
  113. certNftProjectId: {
  114. type: String,
  115. default: ''
  116. }
  117. })
  118. watch(() => props.screenshotWebsiteData,
  119. (newVal) => {
  120. let { appId } = props.previewData;
  121. if (loadingHide && (!appId || appId && !props.previewData.linkImagePath) && (newVal.url || newVal.status)) {
  122. loadingHide();
  123. loadingHide = null;
  124. submitPublish();
  125. }
  126. },
  127. {
  128. deep: true
  129. })
  130. watch(() => props.showCom,
  131. (newVal) => {
  132. if (newVal == 'EDITOR' && loadingHide) {
  133. loadingHide();
  134. loadingHide = null;
  135. }
  136. },
  137. {
  138. deep: true
  139. })
  140. const emits = defineEmits(["publishFinish"]);
  141. const getUserInfo = (cb) => {
  142. getChromeStorage('userInfo', (res) => {
  143. if (res) {
  144. userInfo.value = res;
  145. }
  146. cb && cb(res);
  147. })
  148. }
  149. const getUserName = (screenName) => {
  150. getUser({
  151. params: {
  152. screenName
  153. }
  154. }).then(res => {
  155. console.log(res);
  156. if (res.code == 0) {
  157. userInfo.value.name = res.data.name || ''
  158. }
  159. });
  160. }
  161. const calcPreviewCanvasParams = () => {
  162. nextTick(() => {
  163. let containerDom = document.querySelector('.card-container');
  164. let domHeight = containerDom && containerDom.offsetHeight || 490;
  165. const canvasHeight = 780, canvasWidth = 620;
  166. if (domHeight < canvasHeight) {
  167. //比例: 高 / 宽
  168. let hWRatio = canvasHeight / canvasWidth;
  169. //缩小宽度 = 高度 / 比例
  170. let width = canvasWidth / hWRatio;
  171. if (width > canvasWidth) {
  172. width = canvasWidth;
  173. }
  174. //缩小比例
  175. let zoom = width / canvasWidth;
  176. if (zoom > 1) {
  177. zoom = 1;
  178. }
  179. reviewCanvasParams.width = width;
  180. reviewCanvasParams.zoom = zoom;
  181. } else {
  182. reviewCanvasParams.width = canvasWidth;
  183. reviewCanvasParams.zoom = 1;
  184. }
  185. });
  186. }
  187. const publishHandler = () => {
  188. let { appId } = props.previewData;
  189. if (loadingHide) {
  190. return;
  191. }
  192. if ((!appId || appId && !props.previewData.linkImagePath) &&
  193. (!props.screenshotWebsiteData.url && !props.screenshotWebsiteData.status)) {
  194. loadingHide = message.loading('loading...', 0);
  195. return;
  196. }
  197. submitPublish();
  198. }
  199. const submitPublish = () => {
  200. let { convertUrl, originUrl, appId, currentApp } = props.previewData;
  201. if (submitIng.value) {
  202. return;
  203. }
  204. setHistoryData(currentApp);
  205. let linkTitle = currentApp.defaultTit ? '' : currentApp.name;
  206. let postBizData = {
  207. convertUrl,
  208. originUrl,
  209. appId,
  210. linkTitle: !appId ? linkTitle : '',
  211. linkImagePath: props.screenshotWebsiteData.url
  212. };
  213. if (props.certNftProjectId !== '') {
  214. postBizData['certNftProjectId'] = props.certNftProjectId;
  215. }
  216. let data = {
  217. params: {
  218. postBizData: JSON.stringify(postBizData),
  219. postSrc: 1, // 1 twitter
  220. postType: 3, //3 Tool box
  221. },
  222. };
  223. submitIng.value = true;
  224. postPublish(data).then((res) => {
  225. submitIng.value = false;
  226. if (res.code == 0) {
  227. let publishRes = res.data;
  228. emits("publishFinish", { publishRes });
  229. } else {
  230. }
  231. }).catch((err) => {
  232. console.log(err);
  233. });
  234. }
  235. const setHistoryData = async (params) => {
  236. const maxLength = 9;
  237. let { list = [] } = await getChromeStorage('toolBoxAppHistoryData') || {};
  238. if (list.length) {
  239. let hasSite = list.find(item => item.defaultUrl == params.defaultUrl);
  240. if (hasSite) {
  241. return;
  242. }
  243. list.unshift(params);
  244. if (list.length > maxLength) {
  245. list.length = maxLength;
  246. }
  247. setChromeStorage({
  248. toolBoxAppHistoryData: JSON.stringify({
  249. list: list
  250. })
  251. })
  252. } else {
  253. setChromeStorage({
  254. toolBoxAppHistoryData: JSON.stringify({
  255. list: [params]
  256. })
  257. })
  258. }
  259. };
  260. onMounted(() => {
  261. calcPreviewCanvasParams();
  262. getUserInfo((res) => {
  263. if (res) {
  264. getUserName(res.nickName);
  265. }
  266. clearInterval(timer.value);
  267. timer.value = setInterval(() => {
  268. installStatus.value = !installStatus.value;
  269. }, 3000)
  270. });
  271. window.addEventListener('resize', function () {
  272. calcPreviewCanvasParams();
  273. })
  274. })
  275. onUnmounted(() => {
  276. clearInterval(timer.value);
  277. })
  278. </script>
  279. <style lang="scss" scoped>
  280. .editor-preview-wrapper {
  281. width: 100%;
  282. height: 100%;
  283. .top {
  284. width: 100%;
  285. height: calc(100% - 80px);
  286. display: flex;
  287. justify-content: space-between;
  288. padding: 20px 40px;
  289. box-sizing: border-box;
  290. .card-container {
  291. height: 100%;
  292. margin-right: 32px;
  293. .content-after,
  294. .content-before {
  295. position: relative;
  296. }
  297. .head {
  298. position: absolute;
  299. z-index: 1100;
  300. top: 20px;
  301. left: 17px;
  302. display: flex;
  303. .avatar {
  304. width: 47px;
  305. height: 47px;
  306. border-radius: 50%;
  307. object-fit: cover;
  308. margin-right: 13px;
  309. }
  310. .article-wrapper {
  311. display: flex;
  312. .nickname {
  313. font-weight: 500;
  314. }
  315. .nickname,
  316. .name {
  317. font-size: 15px;
  318. }
  319. .name {
  320. color: #566370;
  321. margin-left: 7px;
  322. }
  323. }
  324. }
  325. .content-after {
  326. background: url('@/assets/img/img-tool-box-preview-after.png');
  327. width: 387px;
  328. height: calc(100% - 30px);
  329. overflow: hidden;
  330. background-size: cover;
  331. background-repeat: no-repeat;
  332. border: 1px solid #E6E6E6;
  333. border-radius: 13px;
  334. box-sizing: border-box;
  335. .after-cover-wrapper {
  336. position: absolute;
  337. z-index: 100;
  338. top: 108px;
  339. left: 78px;
  340. width: 425px;
  341. height: 458px;
  342. border-radius: 10px;
  343. // border: 1px solid #D1D9DD;
  344. }
  345. }
  346. .content-before {
  347. background: url('@/assets/img/img-tool-box-preview-before.png');
  348. background-size: cover;
  349. background-repeat: no-repeat;
  350. height: calc(100% - 30px);
  351. overflow: hidden;
  352. border: 1px solid #E6E6E6;
  353. border-radius: 13px;
  354. box-sizing: border-box;
  355. .card-wrapper {
  356. width: 448px;
  357. height: 300px;
  358. border: 1px solid #E6E6E6;
  359. background: #ffffff;
  360. box-sizing: border-box;
  361. overflow: hidden;
  362. position: relative;
  363. box-sizing: border-box;
  364. border-radius: 16px;
  365. left: 70px;
  366. top: 90px;
  367. .iframe {
  368. height: calc(100% - 71px);
  369. width: 100%;
  370. border: none;
  371. pointer-events: none;
  372. cursor: default;
  373. }
  374. .cover {
  375. height: calc(100% - 73px);
  376. width: 100%;
  377. object-fit: cover;
  378. }
  379. .bottom-bar {
  380. width: 100%;
  381. height: 73px;
  382. padding: 10px 10px 0 13px;
  383. border-top: 1px solid rgba(0, 0, 0, 0.3);
  384. .site-url {
  385. color: #566370;
  386. font-size: 14px;
  387. line-height: 20px;
  388. }
  389. .desc {
  390. font-weight: 500;
  391. font-size: 15px;
  392. line-height: 21px;
  393. font-weight: 500;
  394. }
  395. }
  396. }
  397. }
  398. }
  399. .font {
  400. height: 30px;
  401. font-weight: 600;
  402. font-size: 20px;
  403. span {
  404. color: #1D9BF0;
  405. }
  406. }
  407. .setting {
  408. flex: 1;
  409. }
  410. }
  411. .bottom {
  412. width: 100%;
  413. height: 80px;
  414. box-shadow: 0px -1px 0px #ECECEC;
  415. box-sizing: border-box;
  416. border-bottom-left-radius: 16px;
  417. display: flex;
  418. align-items: center;
  419. justify-content: flex-end;
  420. .btn {
  421. width: 200px;
  422. height: 50px;
  423. background: #1D9BF0;
  424. border-radius: 10000px;
  425. display: flex;
  426. align-items: center;
  427. justify-content: center;
  428. font-weight: 700;
  429. font-size: 18px;
  430. color: #fff;
  431. margin-right: 30px;
  432. cursor: pointer;
  433. }
  434. }
  435. }
  436. </style>