ShareModal.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <template>
  2. <t-dialog
  3. v-model:visible="props.visible"
  4. :title="props.title"
  5. :footer="false"
  6. :width="520"
  7. @close="close"
  8. >
  9. <div class="shareModal">
  10. <!-- <div class="item" v-if="shareFlag">
  11. <t-radio-group v-model:value="isShare" @change="onChange">
  12. <t-radio :value="true"> {{$t('分享公开')}} </t-radio>
  13. <t-radio :value="false"> {{$t('不分享')}} </t-radio>
  14. </t-radio-group>
  15. </div> -->
  16. <div class="item">
  17. <t-switch size="small" v-model:value="isShare" @change="onChange"/>
  18. <p class="ml-8" style="color: #fff;">
  19. {{ isShare?"已开启,所有人可查看":"未开启,仅自己可查看" }}
  20. </p>
  21. </div>
  22. <div class="item">
  23. <t-input
  24. v-model:value="link"
  25. :readonly="true"
  26. />
  27. <t-button @click="onSearch">{{$t('复制链接')}}</t-button>
  28. </div>
  29. <div class="desc">{{$t('分享到')}}</div>
  30. <t-loading :loading="loading">
  31. <div class="code-box flex">
  32. <div class="code flex-1">
  33. <img class="code-img" :src="qr">
  34. <p class="subdesc">{{$t('扫一扫')}}</p>
  35. </div>
  36. <!-- <div class="code flex-1">
  37. <img class="code-img" ref="codeImg">
  38. <p class="subdesc">{{$t('微信扫一扫')}}</p>
  39. </div>
  40. <div class="remark">
  41. {{$t('分享私有图纸请确保小程序登录的账号与')}}PC{{$t('端一致')}},{{$t('或者将私有图纸设置为分享公开')}},{{$t('才可以正常扫码预览')}}。
  42. </div> -->
  43. </div>
  44. </t-loading>
  45. </div>
  46. </t-dialog>
  47. </template>
  48. <script lang="ts" setup>
  49. import { defineComponent, nextTick, ref, computed, watch, getCurrentInstance } from "vue";
  50. import QRCode from "qrcode";
  51. import { useRoute } from "vue-router";
  52. import { MessagePlugin } from "tdesign-vue-next";
  53. import axios from "@/http";
  54. import { Meta2dBackData } from "@/services/utils";
  55. import { useUser } from "@/services/user";
  56. import { rootDomain } from "@/services/defaults";
  57. const { proxy } = getCurrentInstance();
  58. const $t = proxy.$t
  59. const props = defineProps<{
  60. visible: boolean;
  61. shared: boolean;
  62. title?: string;
  63. }>();
  64. const emit = defineEmits(["update:visible", "change"]);
  65. const link = ref("");
  66. const isShare = ref(false);
  67. const loading = ref(false);
  68. const shareFlag = ref(false);
  69. const qr = ref("#");
  70. // const wxImg = ref<string>('');
  71. const route = useRoute();
  72. const codeImg = ref<any>();
  73. const { user } = useUser();
  74. function close() {
  75. emit("update:visible", false);
  76. }
  77. function onChange(e) {
  78. share(e);
  79. emit("change",isShare.value);
  80. }
  81. function onSearch() {
  82. copy2clipboard(link.value);
  83. MessagePlugin.success($t("复制链接成功!"));
  84. }
  85. function copy2clipboard(copyText: string) {
  86. //1 手动创建可编辑元素,比如textarea,
  87. var textArea = document.createElement("textarea");
  88. //2 然后将要拷贝的值设置为它的Value
  89. textArea.value = copyText;
  90. //将textarea插入页面
  91. document.body.appendChild(textArea);
  92. //调用textarea的 select() 方法将值选中
  93. textArea.select();
  94. // 3 textarea要设置样式为不可见(使用样式将其移出可视区域即可)
  95. textArea.style.position = "fixed";
  96. textArea.style.top = "-9999px";
  97. textArea.style.left = "-9999px";
  98. // 4 调用document.execCommand('copy')
  99. document.execCommand("copy"); // 复制
  100. // document.execCommand('cut')// 剪切
  101. textArea.remove();
  102. }
  103. //TODO 配置shared无用,图纸不能根据用户id查找
  104. async function share(shared: boolean) {
  105. const id = route.query.id;
  106. if (!id) {
  107. // 提示需要先保存
  108. MessagePlugin.warning($t("请先保存!"));
  109. return;
  110. }
  111. const res: any = await axios.post(`/api/data/v/update`, {
  112. _id: id,
  113. id: id,
  114. shared,
  115. });
  116. if (res.error) {
  117. return;
  118. }
  119. MessagePlugin.success(shared ? $t("分享成功!") : $t("取消分享成功"));
  120. }
  121. async function getQRcode(url: string) {
  122. const q: any = await QRCode.toDataURL(url, { margin: 0 });
  123. qr.value = q;
  124. }
  125. //TODO 小程序码接口
  126. async function getWXCode(id: string) {
  127. const res: any = await axios.get("/api/account/miniprogram/code", {
  128. params: { id },
  129. responseType: "blob",
  130. });
  131. codeImg.value.src = URL.createObjectURL(res); // 将生成的blob对象的值赋值给img的src属性
  132. codeImg.value.onLoad = () => {
  133. URL.revokeObjectURL(codeImg.value.src); // 在图片加载完成后释放
  134. };
  135. }
  136. watch(
  137. () => props.visible,
  138. (newV) => {
  139. if (newV) {
  140. const id = route.query.id;
  141. const url = location.origin+ `/view/v/?id=${id}`;
  142. link.value = url;
  143. const data: Meta2dBackData = meta2d.data();
  144. // 只有图纸的拥有者才有分享和取消分享的曲线
  145. shareFlag.value = (data as any).ownerId === user.id;
  146. nextTick(async () => {
  147. loading.value = true;
  148. isShare.value = props.shared;
  149. try {
  150. await getQRcode(url);
  151. } catch (error) {
  152. MessagePlugin.warning($t("获取二维码失败!"));
  153. }
  154. // try {
  155. // await getWXCode((id as string).split("-").join(""));
  156. // } catch (error) {
  157. // MessagePlugin.warning($t("获取微信小程序码失败!"));
  158. // loading.value = false;
  159. // }
  160. loading.value = false;
  161. });
  162. }
  163. }
  164. );
  165. </script>
  166. <style lang="postcss" scoped>
  167. /* .ant-modal-wrap{
  168. z-index: 9999 !important;
  169. } */
  170. .shareModal {
  171. .item {
  172. display: flex;
  173. align-items: center;
  174. margin-bottom: 24px;
  175. }
  176. .desc {
  177. line-height: 36px;
  178. margin-bottom: 4px;
  179. color: #fff;
  180. }
  181. .code-box {
  182. display: flex;
  183. justify-content: space-between;
  184. color: #fff;
  185. .code {
  186. flex: 1;
  187. display: flex;
  188. flex-direction: column;
  189. justify-content: center;
  190. align-items: center;
  191. .code-img {
  192. width: 120px;
  193. height: 120px;
  194. margin-bottom: 8px;
  195. }
  196. .subdesc{
  197. text-align: center;
  198. }
  199. }
  200. .remark{
  201. width: 26%;
  202. font-size: 14px;
  203. text-align: center;
  204. }
  205. }
  206. }
  207. </style>