Merge branch 'main' of http://18.167.251.121:10003/aidlab/Code-Create
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>test-ssg</title>
|
||||
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_4403230_bui5mtufs1c.css" />
|
||||
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_4403230_2woxf8yp826.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<RouterView />
|
||||
<MainFooter />
|
||||
<BackTop />
|
||||
|
||||
<VideoModel />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -10,6 +12,7 @@
|
||||
import MainHeader from "./components/main-header.vue";
|
||||
import MainFooter from "./components/main-footer.vue";
|
||||
import BackTop from "./components/back-top.vue";
|
||||
import VideoModel from "./components/video-model.vue";
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
// .main {
|
||||
|
||||
74
src/components/video-model.vue
Normal file
74
src/components/video-model.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
import MyEvent from "@/directives/myEvents";
|
||||
//const props = defineProps({
|
||||
//})
|
||||
//const emit = defineEmits([
|
||||
//])
|
||||
const isVideoShow = ref(true)
|
||||
const url = ref('')
|
||||
const poster = ref('')
|
||||
const playVideo = (data)=>{
|
||||
url.value = data.url || ''
|
||||
poster.value = data.poster || ''
|
||||
isVideoShow.value = true
|
||||
}
|
||||
const closeVideoModel = ()=>{
|
||||
url.value = ''
|
||||
poster.value = ''
|
||||
isVideoShow.value = false
|
||||
}
|
||||
onMounted(()=>{
|
||||
MyEvent.add("playVideo",playVideo);
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
defineExpose({})
|
||||
</script>
|
||||
<template>
|
||||
<div class="vide-model" v-if="isVideoShow">
|
||||
<div class="mask"></div>
|
||||
<video :src="url" autoplay controls preload="metadata" controlslist="nodownload" :poster="poster"></video>
|
||||
<div class="close-btn">
|
||||
<span class="iconfont icon-close" @click="closeVideoModel"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.vide-model{
|
||||
z-index: 99999;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
> .mask{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
background-color: rgba(0,0,0,.8);
|
||||
}
|
||||
> video{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
max-height: 80vh;
|
||||
max-width: 80vw;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
> .close-btn{
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
font-size: 30px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
span{
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
39
src/directives/myEvents.ts
Normal file
39
src/directives/myEvents.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
class MyEvent {
|
||||
private events: Map<string, Array<(data: any) => void>>;
|
||||
constructor() {
|
||||
// 使用 Object 或 Map 存储,实现 O(1) 级别的查找
|
||||
this.events = new Map()
|
||||
}
|
||||
add(name: string, call: (data: any) => void) {
|
||||
if (!this.events.has(name)) {
|
||||
this.events.set(name, [])
|
||||
}
|
||||
this.events.get(name)!.push(call)
|
||||
}
|
||||
remove(name: string, call?: (data: any) => void) {
|
||||
if (!this.events.has(name)) return
|
||||
|
||||
if (!call) {
|
||||
this.events.delete(name)
|
||||
} else {
|
||||
const callbacks = this.events.get(name)
|
||||
const index = callbacks.indexOf(call)
|
||||
if (index !== -1) {
|
||||
callbacks.splice(index, 1)
|
||||
}
|
||||
// 如果该事件没有监听者了,彻底清理 key
|
||||
if (callbacks.length === 0) {
|
||||
this.events.delete(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
emit(name: string, data?: any) {
|
||||
const callbacks = this.events.get(name)
|
||||
if (callbacks) {
|
||||
// 使用 slice() 镜像一份副本,防止在执行回调过程中有 remove 操作导致索引错乱
|
||||
callbacks.slice().forEach((cb) => cb(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
export default new MyEvent()
|
||||
@@ -1,4 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import MyEvent from "@/directives/myEvents";
|
||||
let videoUrl = 'https://code-create.com.hk/wp-content/uploads/2023/05/codec_brand_vid_16x9_ENG.mp4'
|
||||
let videoPosterUrl = 'https://code-create.com.hk/wp-content/uploads/revslider/video-media/codec_brand_vid_16x9_ENG_11_layer.jpeg'
|
||||
const playVideo = ()=>{
|
||||
MyEvent.emit("playVideo",{
|
||||
url: videoUrl,
|
||||
poster: videoPosterUrl,
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
</script>
|
||||
<template>
|
||||
@@ -11,6 +22,8 @@ defineExpose({})
|
||||
</section>
|
||||
<section class="ecosystem-video">
|
||||
<div class="content">
|
||||
<img src="https://code-create.com.hk/wp-content/uploads/revslider/video-media/codec_brand_vid_16x9_ENG_11_layer.jpeg" alt="">
|
||||
<span class="iconfont icon-bofang" @click="playVideo"></span>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -48,6 +61,36 @@ defineExpose({})
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 100px 0;
|
||||
position: relative;
|
||||
> img{
|
||||
width: 100%;
|
||||
}
|
||||
> .icon-bofang{
|
||||
font-size: 100px;
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
animation: identifier 2s ease-in-out infinite;
|
||||
// box-shadow: 0 0 10px #fff;
|
||||
transition: .3s all;
|
||||
cursor: pointer;
|
||||
@keyframes identifier {
|
||||
0% {
|
||||
transform: translate(-50%,-50%) scale(1);
|
||||
filter: drop-shadow(0px 0px 8px rgba(255, 255, 255, 1));
|
||||
}
|
||||
50% {
|
||||
transform: translate(-50%,-50%) scale(.95);
|
||||
filter: drop-shadow(0px 0px 0px rgba(255, 255, 255, 1));
|
||||
}
|
||||
100% {
|
||||
transform: translate(-50%,-50%) scale(1);
|
||||
filter: drop-shadow(0px 0px 8px rgba(255, 255, 255, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -14,6 +14,7 @@ export const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
{
|
||||
path: 'about-us',
|
||||
name: 'about-us',
|
||||
component: AboutView
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,7 +1,26 @@
|
||||
{
|
||||
"files": [],
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue", "src/types/**/*.d.ts"],
|
||||
"compilerOptions": {
|
||||
"forceConsistentCasingInFileNames": false, // ⚠️ 禁用大小写检查
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
"types": ["node", "unplugin-vue-define-options/macros-global"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
"_c/*": ["./src/components/*"]
|
||||
},
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"noEmit": true,
|
||||
"noImplicitAny": false,
|
||||
"noEmitOnError": false
|
||||
},
|
||||
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user