Commit 9006e886 authored by zhengke's avatar zhengke

Merge branch 'master' into 1.4.0

parents 104fd92e df476491
......@@ -17,6 +17,7 @@
"@types/ali-oss": "^6.16.11",
"@types/opentype.js": "^1.3.8",
"@types/psd": "^3.4.3",
"@vue/reactivity": "^3.4.29",
"@vueuse/integrations": "^10.7.2",
"ali-oss": "^6.18.1",
"animate.css": "^4.1.1",
......
......@@ -76,5 +76,6 @@ const handleClickMenuItem = (item: ContextmenuItem) => {
position: fixed;
z-index: 9999;
user-select: none;
font-family: Arial, Helvetica, sans-serif;
}
</style>
\ No newline at end of file
......@@ -88,10 +88,11 @@
<template #dropdown>
<div class="MarketPopoverMore row wrap pointer">
<div class="column" v-for="(item, index) in moreList" @click="forward(item)">
<div>
<div style="position: relative;">
<img :src="item.icon" width="34" height="34" />
<span v-if="item.Id==2" style="position: absolute;background: red;right: -25px;top: 0;border-radius: 50%;opacity: 0;" @click.stop="forward(item,1)">&nbsp;</span>
</div>
<span>{{ item.Name }}</span>
<span>{{ item.Id==2?(personalInfor.IsOpenId?item.Name:'已关注公众号' ):item.Name }}</span>
</div>
</div>
</template>
......@@ -100,10 +101,10 @@
<!-- 创建设计 -->
<temDesign :addTem="addVisible" @close="addVisible=false"/>
<OrderReview v-if="orderVisible" :show-person="isShowPerson" :default-type="isShowPerson?1:2" @close="()=>orderVisible=false"></OrderReview>
<follow v-if="isPublicAccount" @close="isPublicAccount=false"></follow>
<follow v-show="isPublicAccount" :show="isPublicAccount" @close="isPublicAccount=false,getInfo()"></follow>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { ref, reactive } from "vue";
import { useUserStore } from "@/store";
import { storeToRefs } from "pinia";
import { useRouter } from "vue-router";
......@@ -142,15 +143,18 @@ const isPublicAccount = ref(false)
const format = (percentage: number) => {
return percentage == 100 ? '' : ``
}
const moreList = [
const moreList = ref(
[
{ icon: require("@/assets/img/homeMore0.png"), Name: "添加到桌面", Id:1, },
{ icon: require("@/assets/img/homeMore1.png"), Name: "关注公众号", Id:2, },
{ icon: require("@/assets/img/homeMore2.png"), Name: "我的订单", Url:'/u/order', Id:3, },
{ icon: require("@/assets/img/homeMore3.png"), Name: "意见反馈", Url:'https://work.weixin.qq.com/kfid/kfc378aada578ca8b0e', Id:4, },
];
] as any);
const TravelDesign = ref({} as any)
const personalInfor = ref({} as any)
const goDesNorm = () => {
openNewBlank('/d')
}
......@@ -158,12 +162,16 @@ const goDesNorm = () => {
const forwardUserCenter = ()=>{
router.push('/u')
}
const forward = (item:any)=>{
const forward = (item:any,type:any)=>{
if(item.Url){
current.value = -1
if(item.Url.includes('http://')||item.Url.includes('https://')) openNewBlank(item.Url)
else router.push(item.Url)
}else{
// if(item.Id==2) isPublicAccount.value = true
if(item.Id==2&&type){
if(item.Id==2&&personalInfor.value.IsOpenId) isPublicAccount.value = true
}
}
}
const loginOutHandler = ()=>{
......@@ -185,6 +193,14 @@ const getDataStatistics = async () => {
TravelDesign.value = response.data.data
}
}
const getInfo = async () => {
const response = await UserServices.GetMemberUserInfo()
if(response.data.resultCode == ApiResult.SUCCESS){
personalInfor.value = response.data.data
}
}
getInfo()
getDataStatistics()
getSampleHandler()
</script>
......
<template>
<div class="followForm">
<div class="followForm" ref="followForm">
<div class="followForm-bj"></div>
<div class="followBox row flex-center">
<div class="followBox-center">
......@@ -7,25 +7,38 @@
style="height: 33.7vw;"/>
<span class="close-btn cursor-pointer column items-center flex-center"
@click="close"><IconClose size="0.83vw"></IconClose></span>
<div v-if="!qrCode||loseEffect" class="q-pt-md" style="position: absolute;right: 11vw;top: 27vw">
<el-icon class="cursor-pointer">
<RefreshRight
v-if="!RefreshLoading"
@click="() => getQrcode(1)"
color="#564bec"
/>
<Refresh v-else color="#564bec"/>
</el-icon>
</div>
<div class="pa followBoxQR" style="font-size: 0.73vw;" v-loading="qrLoading">
<QRCode :value="qrCode" style="width: 13.95vw;height: auto;" v-if="!qrLoading"></QRCode>
<img :src="qrCode" style="width: 13.95vw;height: auto;" v-if="!qrLoading"></img>
<QRCode value="http://www.viitto.com" style="width: 13.95vw;height: auto;" v-if="qrLoading"></QRCode>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from 'vue'
import { ref, onMounted, reactive, watch, onBeforeUnmount } from 'vue'
import { useRouter } from "vue-router";
import { storeToRefs } from 'pinia'
import { useScreenStore } from '@/store'
import { ApiResult } from '@/configs/axios'
import WechatSerice from '@/services/WechatSerice'
const qrCode = ref('none')
import UserServices from '@/services/UserService'
import { ElMessage, FormInstance } from 'element-plus';
import { useUserStore } from '@/store/user';
const user = useUserStore()
const qrCode = ref('')
const qrLoading = ref(false)
const router = useRouter();
......@@ -39,6 +52,10 @@ const props = defineProps({
Details:{
type: Object,
default: {},
},
show: {
type: Boolean,
default: false,
}
})
const params = reactive({
......@@ -49,17 +66,64 @@ const emit = defineEmits<{
(event: 'close'): void,
}>()
const queryTimer = ref<any>(null)
const loseEffect = ref(false)
const scene_id = ref('')
const RefreshLoading = ref(false)
const followForm = ref()
const close = () => {
emit('close')
}
if(model.value==0 && ConfigId.value) params.ConfigId = ConfigId.value
const getQrcode = async () => {
const beginTimerHandler = ()=>{
queryTimer.value = setInterval(async ()=>{
await userLoginHandler(0)
},3000)
}
const stopTimerHandler = async ()=>{
if(queryTimer.value){
clearInterval(queryTimer.value)
queryTimer.value=null
userLoginHandler(1)
}
}
const getQrcode = async (type:any) =>{
qrLoading.value = true
const response = await WechatSerice.GetShowQrcode({})
if(response.data.resultCode == ApiResult.SUCCESS){
qrCode.value = response.data.data
if(type)RefreshLoading.value = true
const result = await UserServices.GetShowQrcode(1)
if(result.data.resultCode==ApiResult.SUCCESS){
if(result.data.data&&result.data.data.url) qrCode.value = result.data.data.url
if(result.data.data&&result.data.data.scene_id) {
beginTimerHandler()
scene_id.value = result.data.data.scene_id
}
loseEffect.value = false
qrLoading.value = false
}else qrLoading.value = false
if(type)RefreshLoading.value = false
}
const userLoginHandler = async (type:any)=>{
const result = await user.setUserWechatLoginAsync(scene_id.value,type)
if(result.status=='SUCCESS'){
if(!type) {
stopTimerHandler()
ElMessage.success({message:'关注成功'})
location.reload()
}
}else if(result.status=='ERROR') {
if(!type) {
stopTimerHandler()
loseEffect.value = true
ElMessage.error({message:'二维码维码已失效,请重新获取'})
}
}
}
const goVipIntroduce = () =>{
......@@ -67,7 +131,24 @@ const goVipIntroduce = () =>{
path:`/p/show`
})
}
getQrcode()
watch(()=>props.show,(n,o)=>{
if(!n) stopTimerHandler()
if(n) getQrcode()
},{
immediate: true
})
onMounted( () => {
document.addEventListener('click', (e) => {
if (props.show&&followForm.value) {
followForm.value.click()
}
});
})
onBeforeUnmount(() => {
document.removeEventListener('click', () => {});
})
</script>
<style lang="scss" scoped>
......
......@@ -59,8 +59,8 @@ class UserServices {
}
static async WechatLoginAsync(scene_id: string): Promise<HttpResponse> {
let msg = { scene_id }
static async WechatLoginAsync(scene_id: string,islean:Number): Promise<HttpResponse> {
let msg = { scene_id,islean }
return Api.Post("Wechat_QrCode_GetSceneId", msg)
}
......
import Api,{ HttpResponse, Result } from './../utils/request';
class WechatSerice{
static async GetShowQrcode(params:any):Promise<HttpResponse>{
return Api.Post("Wechat_QrCode_GetShowQrcode",params)
}
}
export default WechatSerice;
\ No newline at end of file
......@@ -113,9 +113,9 @@ export const useUserStore = defineStore('user', {
this.userInfo.logo = ENTERPRISE_DEFAULT_HEADER
}
},
async setUserWechatLoginAsync(scene_id:string) {
async setUserWechatLoginAsync(scene_id:string,islean:any) {
try {
let response = await UserService.WechatLoginAsync(scene_id)
let response = await UserService.WechatLoginAsync(scene_id,islean)
if (response.data.resultCode == ApiResult.SUCCESS) {
if(!Array.isArray(response.data.data)) {
this.token = response.data.data.token
......
import type { Node, NodeType, ResolvedPos, Mark, MarkType } from 'prosemirror-model'
import type { EditorState, Selection } from 'prosemirror-state'
import { TextSelection, type EditorState, type Selection } from 'prosemirror-state'
import type { EditorView } from 'prosemirror-view'
import { selectAll } from 'prosemirror-commands'
import { selectAll} from 'prosemirror-commands'
export const autoSelectAll = (view: EditorView) => {
const { empty } = view.state.selection
if (empty) selectAll(view.state, view.dispatch)
}
export const clearSelection = (view: EditorView) => {
const { state, dispatch } = view
const { selection } = state
if (!selection.empty) {
const selectionWithoutRange = TextSelection.create(state.doc, selection.anchor)
const transaction = state.tr.setSelection(selectionWithoutRange)
dispatch(transaction)
}
}
export const addMark = (editorView: EditorView, mark: Mark, selection?: { from: number; to: number; }) => {
if (selection) {
editorView.dispatch(editorView.state.tr.addMark(selection.from, selection.to, mark))
......
......@@ -97,7 +97,7 @@
<div class="ServAgrelLoadL q-pr-lg">
您登录即同意<strong><a>用户服务协议、</a></strong>
<strong><a>隐私政策</a></strong>
<strong><a>授权许可协议</a></strong>,如您成为稿定设计会员,成为会员即视为同意
<strong><a>授权许可协议</a></strong>,如您成为设计会员,成为会员即视为同意
<strong><a>会员服务协议</a></strong>
</div>
<div class="ServAgrelLoadR q-pl-lg cursor-pointer" @click="redicetToRegist">邮箱注册</div>
......
......@@ -12,7 +12,8 @@
@click="() => getQrcode(1)"
/>
<Refresh v-else />
</el-icon></div>
</el-icon>
</div>
</div>
</template>
<script lang="ts" setup>
......@@ -50,14 +51,15 @@ const loseEffect = ref(false)
const beginTimerHandler = ()=>{
queryTimer.value = setInterval(async ()=>{
await userLoginHandler()
await userLoginHandler(0)
},3000)
}
const stopTimerHandler = ()=>{
const stopTimerHandler = async ()=>{
if(queryTimer.value){
clearInterval(queryTimer.value)
queryTimer.value=null
await userLoginHandler(1)
}
}
......@@ -77,9 +79,10 @@ const getQrcode = async (type:any) =>{
if(type)RefreshLoading.value = false
}
const userLoginHandler = async ()=>{
const result = await user.setUserWechatLoginAsync(scene_id.value)
const userLoginHandler = async (type:any)=>{
const result = await user.setUserWechatLoginAsync(scene_id.value,type)
if(result.status=='SUCCESS'){
if(!type) {
stopTimerHandler()
ElMessage.success({message:'登录成功'})
if(inviteInfo.value){
......@@ -87,11 +90,14 @@ const userLoginHandler = async ()=>{
localStorage.setItem('sure_invite',JSON.stringify(inviteInfo.value))
}
location.href='/space';
}
}else if(result.status=='ERROR') {
if(!type) {
stopTimerHandler()
loseEffect.value = true
ElMessage.error({message:'二维码维码已失效,请重新获取'})
}
}
}
......
......@@ -20,19 +20,19 @@ withDefaults(defineProps<{
height: 0;
left: 0;
top: 0;
border: 0 dashed $themeColor;
border: 0 solid $themeColor;
&.top {
border-top-width: 1px;
border-top-width: 2px;
}
&.bottom {
border-bottom-width: 1px;
border-bottom-width: 2px;
}
&.left {
border-left-width: 1px;
border-left-width: 2px;
}
&.right {
border-right-width: 1px;
border-right-width: 2px;
}
&.wide {
......
......@@ -31,15 +31,29 @@ const rotateClassName = computed(() => {
<style lang="scss" scoped>
.resize-handler {
position: absolute;
width: 10px;
height: 10px;
width:26px;
height: 26px;
left: 0;
top: 0;
margin: -5px 0 0 -5px;
border: 1px solid $themeColor;
margin: -12px 0 0 -12px;
// border: 1px solid $themeColor;
&::after{
width: 10px;
height: 10px;
border-radius: 10px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
background-color: #fff;
border-radius: 1px;
cursor: pointer;
cursor: inherit;
display: block;
content: ' ';
left: 8px;
top:8px;
position: absolute;
}
&.left-top.rotate-0,
&.right-bottom.rotate-0,
......@@ -49,7 +63,7 @@ const rotateClassName = computed(() => {
&.right-top.rotate-90,
&.top.rotate-135,
&.bottom.rotate-135 {
cursor: nwse-resize;
cursor: url('https://im.oytour.com/trip/cusor/8f76b0abb0a62213ab3795d3ebaf3c3e.svg') 16 16, nwse-resize;
}
&.top.rotate-0,
&.bottom.rotate-0,
......@@ -59,7 +73,7 @@ const rotateClassName = computed(() => {
&.right.rotate-90,
&.left-bottom.rotate-135,
&.right-top.rotate-135 {
cursor: ns-resize;
cursor: url('https://im.oytour.com/trip/cusor/4f7515dd177541d307de562bd6ee8f07.svg') 16 16, ns-resize;
}
&.left-bottom.rotate-0,
&.right-top.rotate-0,
......@@ -69,7 +83,7 @@ const rotateClassName = computed(() => {
&.right-bottom.rotate-90,
&.left.rotate-135,
&.right.rotate-135 {
cursor: nesw-resize;
cursor: url('https://im.oytour.com/trip/cusor/13cfd89732053891fab7d23547a6d4f0.svg') 16 16, nesw-resize;
}
&.left.rotate-0,
&.right.rotate-0,
......@@ -79,7 +93,17 @@ const rotateClassName = computed(() => {
&.bottom.rotate-90,
&.left-top.rotate-135,
&.right-bottom.rotate-135 {
cursor: ew-resize;
cursor: url('https://im.oytour.com/trip/cusor/7e6be5a8633602679325c01e745e53ef.svg') 16 16, ew-resize !important;
}
&.left.rotate-0::after,
&.right.rotate-0::after{
width:6px;
height: 14px;
border-radius: 6px;
left: 10px;
top: 6px;
cursor: url('https://im.oytour.com/trip/cusor/7e6be5a8633602679325c01e745e53ef.svg') 16 16, ew-resize !important;
// b7f2dba7d2a5c7631de984f35d15f2ee
}
}
</style>
\ No newline at end of file
......@@ -11,12 +11,13 @@
position: absolute;
width: 10px;
height: 10px;
border-radius: 10px;
top: -25px;
margin-left: -5px;
border: 1px solid $themeColor;
margin-left: -4px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
// border: 1px solid $themeColor;
background-color: #fff;
border-radius: 1px;
cursor: grab;
cursor: url('https://im.oytour.com/trip/cusor/b7f2dba7d2a5c7631de984f35d15f2ee.svg') 16 16, grab;
&:active {
cursor: grabbing;
......
......@@ -532,15 +532,12 @@ const GetTripTemplate = async () =>{
VIEWPORT_VER_SIZE.Value = 1240
}
// if(searchData.value.isTeamManage) mainStore.setToolbarState(ToolbarStates.EL_TEMPLATEDATA)
setTimeout(()=>{
loadingObj.close()
},300)
if(ConfigId.value==0) return
if(TempId.value&&!searchData.value.TempId) await GetTripConfig()
if(model.value!=3) await GetTripFiledData()
}else{
loadingObj.close()
}
loadingObj.close()
} catch (error) {
loadingObj.close()
}
......
<template>
<div class="element-data-mapping" v-if="handleElement && handleElement.dataMapping&&userInfo.isp==2">
<div class="element-data-mapping" v-if="handleElement && handleElement.dataMapping&&userInfo.isp">
<divider />
<div class="q-mb-md row items-center">
<div class="text-small col">数据绑定</div>
......
......@@ -170,7 +170,11 @@
<CopyFile v-if="isCopyTo"
:details="journeyAdsDetails"
@close="() => {journeyAdsDetails = '';isCopyTo=false}"></CopyFile>
@close="() => {journeyAdsDetails = '';isCopyTo=false}"
@success="() => {
journeyAdsDetails = '';
isCopyTo=false;
emit('success')}"></CopyFile>
<TreeFileRecover v-if="isTreeFileRecover"
:details="journeyAdsDetails"
......
......@@ -173,8 +173,8 @@ const handleClip = (data: ImageClipedEmitData | null) => {
.editable-element-image {
position: absolute;
&.lock .element-content {
cursor: default;
&.lock .element-content{
cursor: url('https://im.oytour.com/trip/cusor/c7ca2e93ad449598be9ead2d132dd05b.svg'), default;
}
}
.rotate-wrapper {
......
......@@ -15,7 +15,7 @@ import { useMainStore } from '@/store'
import type { EditorView } from 'prosemirror-view'
import { toggleMark, wrapIn, lift } from 'prosemirror-commands'
import { initProsemirrorEditor, createDocument } from '@/utils/prosemirror'
import { isActiveOfParentNodeType, findNodesWithSameMark, getTextAttrs, autoSelectAll, addMark, markActive, getFontsize } from '@/utils/prosemirror/utils'
import { isActiveOfParentNodeType, findNodesWithSameMark, getTextAttrs, autoSelectAll, addMark, markActive, getFontsize, clearSelection } from '@/utils/prosemirror/utils'
import emitter, { EmitterEvents, type RichTextAction, type RichTextCommand } from '@/utils/emitter'
import { alignmentCommand } from '@/utils/prosemirror/commands/setTextAlign'
import { indentCommand, textIndentCommand } from '@/utils/prosemirror/commands/setTextIndent'
......@@ -96,7 +96,8 @@ watch(() => props.editable, () => {
// 暴露 focus 方法
const focus = () => editorView.focus()
const selectAll = () => autoSelectAll(editorView)
defineExpose({ focus,selectAll })
const clearSelect = () => clearSelection(editorView)
defineExpose({ focus,selectAll,clearSelect })
// 执行富文本命令(可以是一个或多个)
// 部分命令在执行前先判断当前选区是否为空,如果选区为空先进行全选操作
......
......@@ -44,9 +44,10 @@
}"
/>
<!-- 当字号过大且行高较小时,会出现文字高度溢出的情况,导致拖拽区域无法被选中,因此添加了以下节点避免该情况 -->
<!-- 当字号过大且行高较小时,会出现文字高度溢出的情况,导致拖拽区域无法被选中,因此添加了以下节点避免该情况222 -->
<div class="drag-handler top"></div>
<div class="drag-handler bottom"></div>
<!-- <div class="drag-handler full"></div> -->
</div>
</div>
</div>
......@@ -74,6 +75,8 @@ const { shadowStyle } = useElementShadow(shadow)
&.lock .element-content {
cursor: default;
}
}
.rotate-wrapper {
width: 100%;
......@@ -102,12 +105,18 @@ const { shadowStyle } = useElementShadow(shadow)
position: absolute;
left: 0;
right: 0;
z-index: 100;
&.top {
top: 0;
}
&.bottom {
bottom: 0;
}
&.full{
top: 0;
bottom: 0;
height: unset;
}
}
.clip-box{
-webkit-background-clip: text !important;
......
......@@ -35,6 +35,7 @@
@mousedown="$event => handleSelectElement($event)"
@touchstart="$event => handleSelectElement($event)"
>
<div class="full-lock" v-if="fullLockVisible<2" @click="hideLockHandler"></div>
<ElementOutline
:width="elementInfo.width"
:height="elementInfo.height"
......@@ -55,7 +56,7 @@
ref="editorRef"
/>
<!-- 当字号过大且行高较小时,会出现文字高度溢出的情况,导致拖拽区域无法被选中,因此添加了以下节点避免该情况 -->
<!-- 当字号过大且行高较小时,会出现文字高度溢出的情况,导致拖拽区域无法被选中,因此添加了以下节点避免该情况111 -->
<template v-show="!activeGroupElementId">
<div class="drag-handler top" @dblclick="setEditorHandler"></div>
<div class="drag-handler bottom" @dblclick="setEditorHandler"></div>
......@@ -95,6 +96,7 @@ const editorRef = ref()
const shadow = computed(() => props.elementInfo.shadow)
const { shadowStyle } = useElementShadow(shadow)
const fullLockVisible = ref(0)
const handleSelectElement = (e: MouseEvent | TouchEvent, canMove = true) => {
if(e.button && e.button== 1) return
......@@ -130,6 +132,10 @@ watch(isScaling, () => {
}
})
const hideLockHandler = ()=>{
fullLockVisible.value++
}
const updateTextElementHeight = (entries: ResizeObserverEntry[]) => {
const contentRect = entries[0].contentRect
if (!elementRef.value) return
......@@ -187,7 +193,11 @@ const checkEmptyText = debounce(function() {
const isHandleElement = computed(() => handleElementId.value === props.elementInfo.id)
watch(isHandleElement, () => {
if (!isHandleElement.value) checkEmptyText()
if (!isHandleElement.value) {
checkEmptyText()
editorRef.value?.clearSelect()
fullLockVisible.value=0
}
})
</script>
......@@ -220,6 +230,16 @@ watch(isHandleElement, () => {
::v-deep(a) {
cursor: text;
}
.full-lock{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
cursor: url('https://im.oytour.com/trip/cusor/c7ca2e93ad449598be9ead2d132dd05b.svg'), default;
z-index: 99;
}
}
.drag-handler {
height: 20px;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment