Skip to content

Commit 94c32c1

Browse files
committed
Merge branch 'develop'
2 parents 9ccb809 + 11f80a7 commit 94c32c1

File tree

6 files changed

+350
-3
lines changed

6 files changed

+350
-3
lines changed

.github/workflows/deploy.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ jobs:
5656
sed -i "s#BOT_API#${{ secrets.BOT_API }}#g" ./chart/config.yaml
5757
5858
- name: k3s-apply-deployment
59-
uses: steebchen/kubectl@master
59+
uses: steebchen/kubectl@v2.0.0
6060
env:
6161
KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }}
6262
with:
63-
args: apply -f ./chart/config.yaml
63+
config: ${{ secrets.KUBE_CONFIG_DATA }}
64+
command: apply -f ./chart/config.yaml
6465
- name: wechat-work-bot-success-deploy
6566
if: ${{ success() }}
6667
uses: chf007/action-wechat-work@master
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Plugin } from "vue";
2+
3+
const injectKey = Symbol("VueMessage");
4+
5+
const Message: Plugin = App => {
6+
App.provide(injectKey, null);
7+
};
8+
9+
const useMessage = () => {};
10+
export default Message;
11+
export { useMessage };
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<template>
2+
<transition
3+
name="message-fade"
4+
@before-leave="beforeLeave"
5+
@after-leave="destroy"
6+
>
7+
<div
8+
v-show="visible"
9+
:class="['message-box', `message-box--${type}`]"
10+
:style="computedStyle"
11+
>
12+
<slot>
13+
<p v-if="!isHTML" class="message-content">
14+
{{ $props.content }}
15+
</p>
16+
<p v-else v-html="$props.content" class="message-content"></p>
17+
</slot>
18+
</div>
19+
</transition>
20+
</template>
21+
<script lang="ts" setup>
22+
import {
23+
ref,
24+
onMounted,
25+
onBeforeUnmount,
26+
defineProps,
27+
computed,
28+
defineEmit,
29+
} from "vue";
30+
// 是否可见
31+
const visible = ref(false);
32+
33+
const emit = defineEmit(["destroy"]);
34+
const destroy = () => emit("destroy");
35+
const props = defineProps({
36+
/**
37+
* 弹窗警告类型
38+
*/
39+
type: {
40+
validator: (v: string) => {
41+
return ["info", "warn", "error", "success"].includes(v);
42+
},
43+
default: "info",
44+
},
45+
/**
46+
* 弹窗文本内容
47+
*/
48+
content: {
49+
type: String,
50+
require: true,
51+
},
52+
/**
53+
* 是否是 HTML
54+
*/
55+
isHTML: Boolean, // 是否是html
56+
/**
57+
* 持续时长单位 秒
58+
*/
59+
duration: {
60+
type: Number,
61+
default: 3, //
62+
validator: (v: number) => {
63+
return +v > 0;
64+
},
65+
},
66+
/**
67+
* 弹窗关闭时的调用
68+
*/
69+
onClose: {
70+
type: Function,
71+
require: true,
72+
default: () => {},
73+
},
74+
/**
75+
* zIndex
76+
*/
77+
offset: { type: Number, default: 20 },
78+
zIndex: { type: Number, default: 0 },
79+
/**
80+
* 标识id
81+
*/
82+
id: {
83+
type: String,
84+
require: true,
85+
},
86+
});
87+
88+
// 开启弹窗
89+
const onOpen = () => {
90+
setTimeout(() => {
91+
visible.value = true;
92+
}, 10);
93+
setTimeout(() => {
94+
visible.value = false;
95+
}, props.duration * 1000);
96+
};
97+
98+
const beforeLeave = () => {
99+
props.onClose();
100+
};
101+
102+
const computedStyle = computed(() => {
103+
return {
104+
top: `${props.offset}px`,
105+
zIndex: props.zIndex,
106+
};
107+
});
108+
109+
onMounted(() => {
110+
onOpen();
111+
console.log("message box onMounted");
112+
});
113+
onBeforeUnmount(() => {
114+
console.log("message box onUnmounted");
115+
});
116+
</script>
117+
118+
<style scoped>
119+
.message-box {
120+
position: fixed;
121+
left: 50%;
122+
transform: translateX(-50%);
123+
transition: opacity 0.3s, transform 0.4s, top 0.4s;
124+
overflow: hidden;
125+
display: flex;
126+
align-items: center;
127+
background: #edf2fc;
128+
padding: 15px 15px 15px 20px;
129+
min-width: 280px;
130+
font-size: 16px;
131+
color: #606266;
132+
border: 1px solid #ebeef5;
133+
border-radius: 4px;
134+
overflow: hidden;
135+
}
136+
137+
p {
138+
margin: 0;
139+
}
140+
.message-box--info {
141+
background: #909399;
142+
}
143+
.message-box--warn {
144+
background: #f6a23c;
145+
}
146+
.message-box--error {
147+
background: #f56c6c;
148+
}
149+
.message-box--success {
150+
background: #67c23a;
151+
}
152+
.message-fade-enter-from,
153+
.message-fade-leave-to {
154+
opacity: 0;
155+
transform: translate(-50%, -100%);
156+
}
157+
</style>
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { createVNode, render } from "vue";
2+
import Ins from "./index.vue";
3+
import type {
4+
InstanceQueqe,
5+
MessageInstance,
6+
Options,
7+
InstanceComponent,
8+
InstanceOptions,
9+
} from "./type";
10+
11+
const isServer = typeof window === "undefined";
12+
13+
const Queqe: InstanceQueqe = [];
14+
let seed = 5201314;
15+
const Message: MessageInstance = (opts: InstanceOptions) => {
16+
if (isServer) return;
17+
let options: Options = {
18+
content: "",
19+
};
20+
if (typeof opts === "object") {
21+
options = Object.assign(options, opts);
22+
}
23+
if (typeof opts === "string") {
24+
if (opts.length == 0) throw new Error("不能弹出空消息框");
25+
options.content == opts;
26+
}
27+
28+
const id = "message_" + seed++;
29+
30+
const ContainerClassName = "happy__message_container_" + id;
31+
let container = document.createElement("div");
32+
container.className = ContainerClassName;
33+
let offset = options.offset || 20;
34+
35+
Queqe.forEach(v => {
36+
offset += (v.el?.offsetHeight || 0) + 16;
37+
});
38+
offset += 16;
39+
const userOnClose = options.onClose;
40+
options = {
41+
...options,
42+
id,
43+
offset,
44+
onClose: () => {
45+
remove(id, userOnClose);
46+
},
47+
};
48+
// console.log(options, Queqe);
49+
const vm = createVNode(Ins, options);
50+
(vm.props as any).onDestroy = () => {
51+
render(null, container);
52+
};
53+
render(vm, container);
54+
Queqe.push(vm);
55+
document.body.appendChild(container.firstElementChild as Element);
56+
return {
57+
close: () => {
58+
(vm.component?.proxy as InstanceComponent).visible = false;
59+
},
60+
} as any;
61+
};
62+
63+
Message.closeAll = () => {
64+
for (let i = Queqe.length - 1; i >= 0; i--) {
65+
const instance = Queqe[i].component as any;
66+
instance.ctx.close();
67+
}
68+
};
69+
70+
Message.warn = (options: InstanceOptions) => {
71+
const t = "warn";
72+
if (typeof options === "string") {
73+
options = {
74+
content: options,
75+
type: t,
76+
};
77+
} else {
78+
options.type = t;
79+
}
80+
return Message(options);
81+
};
82+
83+
Message.info = (options: InstanceOptions) => {
84+
const t = "info";
85+
if (typeof options === "string") {
86+
options = {
87+
content: options,
88+
type: t,
89+
};
90+
} else {
91+
options.type = t;
92+
}
93+
return Message(options);
94+
};
95+
96+
Message.error = (options: InstanceOptions) => {
97+
const t = "error";
98+
if (typeof options === "string") {
99+
options = {
100+
content: options,
101+
type: t,
102+
};
103+
} else {
104+
options.type = t;
105+
}
106+
return Message(options);
107+
};
108+
109+
Message.success = (options: InstanceOptions) => {
110+
const t = "success";
111+
if (typeof options === "string") {
112+
options = {
113+
content: options,
114+
type: t,
115+
};
116+
} else {
117+
options.type = t;
118+
}
119+
return Message(options);
120+
};
121+
const remove = (id: string, userOnclose?: () => void) => {
122+
const index = Queqe.findIndex(vm => {
123+
const tid = vm.component?.props.id;
124+
return tid == id;
125+
});
126+
if (index === -1) return;
127+
const vm = Queqe[index];
128+
if (!vm) return;
129+
userOnclose?.();
130+
const removedHeight = vm.el?.offsetHeight || 0;
131+
Queqe.splice(index, 1);
132+
const len = Queqe.length;
133+
if (len < 1) return;
134+
for (let i = index; i < len; i++) {
135+
const pos =
136+
parseInt((Queqe[i] as any).el.style["top"], 10) -
137+
removedHeight -
138+
16;
139+
(Queqe[i] as any).component.props.offset = pos;
140+
}
141+
};
142+
143+
export default Message;
144+
145+
export const useMessage = () => {
146+
return Message;
147+
};

src/components/common/Message/type.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { VNode, ComponentPublicInstance } from "vue";
2+
3+
export type MessageType = "warn" | "error" | "success" | "info";
4+
5+
export type MessageInstance = {
6+
(opt: InstanceOptions): InstanceHandle;
7+
warn: (opt: InstanceOptions) => InstanceHandle;
8+
error: (opt: InstanceOptions) => InstanceHandle;
9+
success: (opt: InstanceOptions) => InstanceHandle;
10+
info: (opt: InstanceOptions) => InstanceHandle;
11+
closeAll(): void;
12+
};
13+
14+
export type Options = {
15+
content: string; // 文字类型
16+
isHTML?: boolean; // 是否是html
17+
duration?: number; // 显示时长
18+
onClose?: () => void; // 关闭时的调用
19+
type?: MessageType;
20+
offset?: number; // 垂直偏移
21+
id?: string;
22+
};
23+
24+
export type InstanceComponent = ComponentPublicInstance<{ visible: boolean }>;
25+
26+
export type InstanceQueqe = Array<VNode>;
27+
28+
export type InstanceOptions = Options | string;
29+
30+
export interface InstanceHandle {
31+
close: () => void;
32+
}

src/views/home/index.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script lang="ts" setup="">
22
import { defineProps, onMounted, reactive } from "vue";
33
import { useHead } from "@vueuse/head";
4-
54
import { GetArticles } from "~/api/article";
65
import ContentLayout from "~/components/layouts/Content/index.vue";
76
import DefaultLayout from "~/components/layouts/Default/index.vue";

0 commit comments

Comments
 (0)