Skip to content

Commit a706827

Browse files
committed
✨ 腾讯云触发器
1 parent af5bd71 commit a706827

File tree

7 files changed

+203
-42
lines changed

7 files changed

+203
-42
lines changed

src/pkg/sdk/tencent_cloud/client.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ export interface Api {
2222
version: string
2323
}
2424

25+
export interface Response {
26+
Error?: {
27+
Code: string
28+
Message: string
29+
}
30+
RequestId: string
31+
}
32+
33+
export interface JsonResponse<T> {
34+
Response: T
35+
}
36+
2537
export class Client {
2638
config: ClientConfig;
2739
api: Api
@@ -31,8 +43,8 @@ export class Client {
3143
this.api = api;
3244
}
3345

34-
protected request(action: string, req: AnyMap): Promise<AnyMap> {
35-
return new Promise(resolve => {
46+
protected request<T=Response>(action: string, req: AnyMap): Promise<JsonResponse<T>> {
47+
return new Promise((resolve) => {
3648

3749
const algorithm = 'TC3-HMAC-SHA256'
3850
const now = new Date();
@@ -69,21 +81,20 @@ export class Client {
6981
const handler = async () => {
7082
const headers: AnyMap = {
7183
'X-TC-Action': action,
72-
'X-TC-Region': this.config.region,
7384
'X-TC-Timestamp': unixTime(),
7485
'X-TC-Version': this.api.version,
86+
'X-TC-Language': 'zh-CN',
7587
'Authorization': Authorization,
7688
'Content-Type': 'application/json; charset=utf-8'
7789
};
78-
if (!this.config.region) {
79-
delete headers['X-TC-Region'];
90+
if (this.config.region) {
91+
headers['X-TC-Region'] = this.config.region;
8092
}
8193
const resp = await axios.post('https://' + this.api.url, payload, {
8294
headers: headers,
8395
responseType: 'json',
8496
});
85-
86-
resolve(<AnyMap>resp.data);
97+
resolve(<JsonResponse<T>>resp.data);
8798
}
8899
void handler();
89100
});

src/pkg/sdk/tencent_cloud/scf.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Client, ClientConfig } from './client';
1+
import { Client, ClientConfig, Response } from './client';
22

33
export interface CreateFunctionRequest {
44
FunctionName: string,
@@ -8,28 +8,47 @@ export interface CreateFunctionRequest {
88
},
99
Handler?: string
1010
Type?: 'Event'
11-
Runtime?: 'Python2.7' | 'Python3.6' | 'Nodejs10.15' | 'Nodejs12.16' | ' Php5' | ' Php7' | 'Go1' | 'Java8' | 'CustomRuntime'
11+
Runtime?: 'Python2.7' | 'Python3.6' | 'Nodejs10.15' | 'Nodejs12.16' | 'Php5' | 'Php7' | 'Go1' | 'Java8' | 'CustomRuntime'
1212
Description?: string
13+
InstallDependency?: 'TRUE' | 'FALSE'
14+
}
15+
16+
export interface CreateTriggerRequest {
17+
FunctionName: string,
18+
TriggerName: string
19+
Type: 'timer'
20+
TriggerDesc?: string
21+
}
22+
23+
export interface GetFunctionRequest {
24+
FunctionName: string
25+
}
26+
27+
export interface GetFunctionResponse extends Response {
28+
FunctionName: string
1329
}
1430

1531
export class ScfClient extends Client {
1632

1733
constructor(client: ClientConfig) {
18-
let url = 'scf';
19-
if (client.region != '') {
20-
url += '.' + client.region;
21-
}
22-
url += '.tencentcloudapi.com';
2334
super(client, {
24-
url: url,
35+
url: 'scf.tencentcloudapi.com',
2536
service: 'scf',
2637
version: '2018-04-16',
2738
});
2839
}
2940

41+
GetFunction(req: GetFunctionRequest) {
42+
return this.request<GetFunctionResponse>('GetFunction', req);
43+
}
44+
3045
// 创建新的函数
3146
CreateFunction(req: CreateFunctionRequest) {
3247
return this.request('CreateFunction', req);
3348
}
3449

50+
CreateTrigger(req: CreateTriggerRequest) {
51+
return this.request('CreateTrigger', req);
52+
}
53+
3554
}

src/pkg/utils/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export function isFirefox() {
5050
}
5151

5252
export function SendLogger(level: LOGGER_LEVEL, origin: string, msg: string, title = '', scriptId?: number) {
53-
top!.postMessage(
53+
top?.postMessage(
5454
{
5555
action: Logger,
5656
data: {

src/views/components/BgCloud.vue

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
</v-icon>
77
</template>
88
<template v-slot:default="dialog">
9+
<v-snackbar
10+
v-model="snackbar"
11+
timeout="5000"
12+
multi-line
13+
:color="snackbarColor"
14+
>
15+
{{ snackbarText }}
16+
<template v-slot:action="{ attrs }">
17+
<v-btn text v-bind="attrs" @click="snackbar = false"> 关闭 </v-btn>
18+
</template>
19+
</v-snackbar>
920
<v-card>
1021
<v-toolbar color="primary" dark>
1122
<v-toolbar-title>上传至云端执行</v-toolbar-title>
@@ -17,6 +28,9 @@
1728
</v-toolbar-items>
1829
</v-toolbar>
1930
<div style="padding: 10px; box-sizing: border-box">
31+
<a href="https://docs.scriptcat.org/dev/cloudcat.html" target="_blank"
32+
>云端执行文档</a
33+
>
2034
<v-input :v-model="exportConfig.uuid" disabled> </v-input>
2135
<v-select
2236
label="上传至"
@@ -41,6 +55,7 @@
4155
<v-text-field
4256
v-if="exportConfig.param"
4357
v-model="exportConfig.param.secretKey"
58+
type="password"
4459
label="SecretKey"
4560
>
4661
</v-text-field>
@@ -53,6 +68,7 @@
5368
item-value="key"
5469
hint="地域请查看 https://cloud.tencent.com/document/product/583/17237"
5570
persistent-hint
71+
return-object
5672
single-line
5773
></v-select>
5874
</div>
@@ -87,6 +103,9 @@
87103
<div v-else-if="exportConfig.dest == 'remote'"></div>
88104
</div>
89105
<v-card-actions class="justify-end">
106+
<v-btn text color="error" @click="clear">{{
107+
btnText[exportConfig.dest] || "清除配置"
108+
}}</v-btn>
90109
<v-btn text color="success" @click="submit">{{
91110
btnText[exportConfig.dest] || "提交"
92111
}}</v-btn>
@@ -122,7 +141,7 @@ import { ScfClient } from '@App/pkg/sdk/tencent_cloud/scf';
122141
interface TencentCloud {
123142
secretId: string;
124143
secretKey: string;
125-
region: { key: string; value: string };
144+
region: string;
126145
regionList: { key: string; value: string }[];
127146
}
128147
@@ -132,6 +151,10 @@ export default class BgCloud extends Vue {
132151
133152
icons = { mdiCloudUpload, mdiClose };
134153
154+
snackbar = false;
155+
snackbarText = '';
156+
snackbarColor = 'red';
157+
135158
@Prop()
136159
script!: Script;
137160
exportConfig: Export = {
@@ -160,9 +183,8 @@ export default class BgCloud extends Vue {
160183
param: <TencentCloud>{
161184
secretId: '',
162185
secretKey: '',
163-
region: { value: '就近地域接入', key: '' },
186+
region: 'ap-shanghai',
164187
regionList: [
165-
{ value: '就近地域接入', key: '' },
166188
{ value: '华东地区(上海)', key: 'ap-shanghai' },
167189
{ value: '华北地区(北京)', key: 'ap-beijing' },
168190
{ value: '西南地区(成都)', key: 'ap-chengdu' },
@@ -235,6 +257,17 @@ export default class BgCloud extends Vue {
235257
}
236258
}
237259
260+
async clear() {
261+
let e = await this.exportModel.findOne({
262+
scriptId: this.script.id,
263+
dest: this.exportDest.key,
264+
});
265+
if (e) {
266+
await this.exportModel.delete(e.id);
267+
}
268+
void this.onChangeDest();
269+
}
270+
238271
submit() {
239272
this.exportConfig.dest = <EXPORT_DEST>this.exportDest.key;
240273
switch (this.exportDest.key) {
@@ -249,32 +282,64 @@ export default class BgCloud extends Vue {
249282
}
250283
251284
async tencent() {
252-
const param = <TencentCloud>this.exportDest.param;
285+
let crontab =
286+
this.script.metadata['crontab'] && this.script.metadata['crontab'][0];
287+
if (!crontab) {
288+
this.message('未检测到@crontab声明暂时只支持定时脚本');
289+
return;
290+
}
291+
292+
const param = <TencentCloud>this.exportConfig.param;
253293
const clientConfig: ClientConfig = {
254294
credential: {
255295
secretId: param.secretId,
256296
secretKey: param.secretKey,
257297
},
258-
region: param.region.key,
298+
region: param.region,
259299
profile: {
260300
httpProfile: {
261-
reqMethod: 'POST', // 请求方法
262-
reqTimeout: 30, // 请求超时时间,默认60s
301+
reqMethod: 'POST',
302+
reqTimeout: 30,
263303
},
264304
},
265305
};
266306
const cli = new ScfClient(clientConfig);
267307
let zip = await this.pack();
268-
void zip.generateAsync({ type: 'base64' }).then((content) => {
269-
void cli.CreateFunction({
270-
FunctionName: 'test',
308+
void zip.generateAsync({ type: 'base64' }).then(async (content) => {
309+
const resp = await cli.CreateFunction({
310+
FunctionName: this.script.uuid,
271311
Code: {
272312
ZipFile: content,
273313
},
314+
Handler: 'utils.run',
315+
Type: 'Event',
316+
Runtime: 'Nodejs12.16',
317+
Description:
318+
this.script.name +
319+
' ' +
320+
(this.script.metadata['description'] &&
321+
this.script.metadata['description'][0]),
322+
InstallDependency: 'TRUE',
274323
});
324+
if (resp.Response.Error) {
325+
this.message(
326+
'上传失败! ' +
327+
resp.Response.Error.Code +
328+
': ' +
329+
resp.Response.Error.Message
330+
);
331+
return;
332+
}
333+
this.message('上传成功!请前往云函数控制台查看详情!', 'success');
275334
});
276335
}
277336
337+
message(text: string, color = 'red') {
338+
this.snackbar = true;
339+
this.snackbarText = text;
340+
this.snackbarColor = color;
341+
}
342+
278343
async local() {
279344
let zip = await this.pack();
280345
void zip.generateAsync({ type: 'blob' }).then((content) => {

src/views/pages/utils.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,53 @@ export function parseStorageValue(str: string): any {
9595
return str;
9696
}
9797
}
98+
99+
100+
// 处理once的crontab表达式,将once之前的时间替换成最小值运行.
101+
export function parseOnceCrontab(crontab: string): string {
102+
const ss = crontab.split(' ');
103+
switch (ss.length) {
104+
case 5:
105+
ss.unshift('0');
106+
break;
107+
case 6:
108+
break;
109+
default:
110+
return '';
111+
}
112+
const cron: string[] = [];
113+
for (let i = 0; i < ss.length; i++) {
114+
if (ss[i] == 'once') {
115+
cron.push('*');
116+
// 将之前的时间替换为最小值
117+
let n = i - 1;
118+
for (; n >= 0; n--) {
119+
if (cron[n][0] == '*') {
120+
// 为*替换为当前位最小值
121+
switch (n) {
122+
// 秒 分 时
123+
case 0:
124+
case 1:
125+
case 2:
126+
cron[n] = '0'
127+
break
128+
// 日 月
129+
case 3:
130+
case 4:
131+
cron[n] = '1'
132+
break
133+
}
134+
} else if (cron[n].indexOf('-') !== -1) {
135+
// 为一个范围,替换为范围内最小值
136+
cron[n] = cron[n].split('-')[0];
137+
} else if (cron[n].indexOf(',') !== -1) {
138+
// 取第一个分割
139+
cron[n] = cron[n].split(',')[0];
140+
}
141+
}
142+
} else {
143+
cron.push(ss[i]);
144+
}
145+
}
146+
return cron.join(' ');
147+
}

0 commit comments

Comments
 (0)