diff --git a/media/src/components/APIPage/API.tsx b/media/src/components/APIPage/API.tsx index 82f9edf..ec5424e 100644 --- a/media/src/components/APIPage/API.tsx +++ b/media/src/components/APIPage/API.tsx @@ -3,7 +3,7 @@ * @description */ import { Tab, Tag } from "@alicloud/console-components"; -import { Segmented } from "antd"; +import { Segmented, notification } from "antd"; import _ from "lodash"; import * as PontSpec from "pontx-spec"; import * as React from "react"; @@ -19,6 +19,7 @@ import { ApiParamsDoc } from "./APIDocument/ApiParamsDoc"; import { TryAPI } from "./TryAPI/TryAPI"; import TrySDK from "./TrySDK/TrySDK"; import { APIPageContext } from "./context"; +import { PontUIService } from "../../service/UIService"; export class APIProps { selectedApi?: PontSpec.PontAPI; @@ -141,7 +142,7 @@ export const API: React.FC = (props) => { const renderContent = React.useMemo(() => { const documentComp = (
- {selectedApi?.description ? ( + {selectedApi?.description && selectedApi?.description !== selectedApi?.summary ? (
@@ -226,6 +227,31 @@ export const API: React.FC = (props) => { } }, [mode, boxWidth, isExpand]); + const openNotification = () => { + notification.open({ + message: "体验调研", + duration: null, + description: ( + + 您对插件的使用体验满意吗?点击 + 体验问卷 + 进行吐槽或夸赞,您的反馈对我们十分重要! + + ), + onClose: () => { + PontUIService.updateQuestionnaireExpiration(14); + }, + }); + }; + + React.useEffect(() => { + PontUIService.getNoticeFlag().then((res) => { + if (res === true) { + openNotification(); + } + }); + }, []); + return (
{/* */} @@ -262,7 +288,7 @@ export const API: React.FC = (props) => {
{selectedApi?.summary ? ( -
+
{selectedApi?.summary}
) : null} diff --git a/media/src/components/main.tsx b/media/src/components/main.tsx index 3024e70..69b382c 100644 --- a/media/src/components/main.tsx +++ b/media/src/components/main.tsx @@ -37,7 +37,7 @@ export const App: React.FC = (props) => { const [appMeta, setAppMeta] = React.useState(props.routerMeta); const { pageType, schemaType, specName, modName, name, spec: metaSpec, remoteSpec } = appMeta || {}; - const {product:popcode,version} = getSpecInfoFromName(specName || ""); + const { product: popcode, version } = getSpecInfoFromName(specName || ""); const [itemMeta, setItemMeta] = React.useState(metaSpec); const [defs, setDefs] = React.useState({}); diff --git a/media/src/pages/_app.tsx b/media/src/pages/_app.tsx index 8c36329..43616fc 100644 --- a/media/src/pages/_app.tsx +++ b/media/src/pages/_app.tsx @@ -2,7 +2,7 @@ import type { AppProps } from "next/app"; import "./document/index.module.scss"; import "./document/index.scss"; import "../styles/globals.css"; -import "../main.css" +import "../main.css"; import "@alicloud/console-components/dist/wind.css"; import React from "react"; diff --git a/media/src/service/UIService.ts b/media/src/service/UIService.ts index 62862e3..b1403e4 100644 --- a/media/src/service/UIService.ts +++ b/media/src/service/UIService.ts @@ -4,67 +4,71 @@ import { MakeCodeResponse, OpenAPIResponse } from "../types/openAPI"; /** 不同使用场景,各自注册服务来源 */ const defaultSpecs: any[] = []; export const PontUIService = { - /** 获取本地元数据列表 */ - requestPontSpecs: async () => { - return { - localSpecs: defaultSpecs as any[] as PontSpec[], - remoteSpecs: defaultSpecs as any[] as PontSpec[], - currentOriginName: "", - }; - }, - - requestDefinitions: async (specName: string) => { - return {} as any; - }, - - /** 获取 本地/远程 的diff信息 */ - requestDiffs: async () => { - return [] as any; - }, - - /** 重新生成SDK */ - requestGenerateSdk: async (): Promise => {}, - - /** 重新拉取远程数据源 */ - syncRemoteSpec: async (specNames = ""): Promise => {}, - - updateLocalSpec: async (spec: PontSpec): Promise => {}, - - /** 更新本地数据源 */ - updateSpecBySpecNames: async (specNames = ""): Promise => {}, - - /** 更新本地模块 */ - updateMod: async (modName: string, specName = ""): Promise => {}, - - /** 更新本地 API */ - updateAPI: async (modName: string, apiName: string, specName = ""): Promise => {}, - - /** 更新类 */ - updateBaseClass: async (className: string, specName = ""): Promise => {}, - - openMeta: async (meta: { - name: string; - specName: string; - modName?: string; - type: string; - spec: any; - }): Promise => {}, + /** 获取本地元数据列表 */ + requestPontSpecs: async () => { + return { + localSpecs: defaultSpecs as any[] as PontSpec[], + remoteSpecs: defaultSpecs as any[] as PontSpec[], + currentOriginName: "", + }; + }, - /** request openapi */ - openAPIRequest: async (params = {}): Promise => new OpenAPIResponse, + requestDefinitions: async (specName: string) => { + return {} as any; + }, - /** get endpoints list */ - requestEndpoints: async (product: string) => { - return [] as any; - }, - /** get sdk demo */ - makeCodeRequest: async (params = {}): Promise => new MakeCodeResponse, - /** get local language */ - getLocalLanguage : async () => "", - /** update local language */ - updateLocalLanguage : async (language:string) => "", - /** open in ide */ - openInCode: async (codeInfo:{code:string,language:string}): Promise => {}, - /** save to file */ - saveToFile: async (code:string): Promise => {}, - }; \ No newline at end of file + /** 获取 本地/远程 的diff信息 */ + requestDiffs: async () => { + return [] as any; + }, + + /** 重新生成SDK */ + requestGenerateSdk: async (): Promise => {}, + + /** 重新拉取远程数据源 */ + syncRemoteSpec: async (specNames = ""): Promise => {}, + + updateLocalSpec: async (spec: PontSpec): Promise => {}, + + /** 更新本地数据源 */ + updateSpecBySpecNames: async (specNames = ""): Promise => {}, + + /** 更新本地模块 */ + updateMod: async (modName: string, specName = ""): Promise => {}, + + /** 更新本地 API */ + updateAPI: async (modName: string, apiName: string, specName = ""): Promise => {}, + + /** 更新类 */ + updateBaseClass: async (className: string, specName = ""): Promise => {}, + + openMeta: async (meta: { + name: string; + specName: string; + modName?: string; + type: string; + spec: any; + }): Promise => {}, + + /** request openapi */ + openAPIRequest: async (params = {}): Promise => new OpenAPIResponse(), + + /** get endpoints list */ + requestEndpoints: async (product: string) => { + return [] as any; + }, + /** get sdk demo */ + makeCodeRequest: async (params = {}): Promise => new MakeCodeResponse(), + /** get local language */ + getLocalLanguage: async () => "", + /** update local language */ + updateLocalLanguage: async (language: string) => "", + /** open in ide */ + openInCode: async (codeInfo: { code: string; language: string }): Promise => {}, + /** save to file */ + saveToFile: async (code: string): Promise => {}, + /** 是否弹出通知框 */ + getNoticeFlag: async (): Promise => true, + /** 更新体验弹窗弹出的时间 */ + updateQuestionnaireExpiration: async (days: number): Promise => {}, +}; diff --git a/package.json b/package.json index d631321..916f592 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,15 @@ "title": "导入依赖" }, { - "command": "alicloud.api.githubIssue", - "title": "feedback", + "command": "alicloud.api.feedback", + "title": "反馈", "icon": "$(feedback)" }, + { + "command": "alicloud.api.githubIssue", + "title": "Issues", + "icon": "$(issues)" + }, { "command": "alicloud.api.findInterface", "title": "查找 API", @@ -178,6 +183,11 @@ "command": "alicloud.api.githubIssue", "when": "view == alicloudApiExplorer", "group": "navigation@4" + }, + { + "command": "alicloud.api.feedback", + "when": "view == alicloudApiExplorer", + "group": "navigation@5" } ], "view/item/context": [ diff --git a/src/Service.ts b/src/Service.ts index 2e8e8e5..8927391 100644 --- a/src/Service.ts +++ b/src/Service.ts @@ -150,30 +150,31 @@ export class AlicloudAPIService { return res?.data?.endpoints || []; } - async openInCode(codeInfo:{code:string,language:string}){ - const {language, code} = codeInfo + async openInCode(codeInfo: { code: string; language: string }) { + const { language, code } = codeInfo; // 创建新的文件 - vscode.workspace.openTextDocument({ - content: code, - language: language?.toLocaleLowerCase(), - }).then(newDocument => { - vscode.window.showTextDocument(newDocument,{ - viewColumn: vscode.ViewColumn.Beside, + vscode.workspace + .openTextDocument({ + content: code, + language: language?.toLocaleLowerCase(), + }) + .then((newDocument) => { + vscode.window.showTextDocument(newDocument, { + viewColumn: vscode.ViewColumn.Beside, + }); }); - }); - return {} + return {}; } - async saveToFile(code:string){ + async saveToFile(code: string) { const uri = await vscode.window.showSaveDialog(); if (uri) { - const buf = Buffer.from(code, 'utf8'); - await vscode.workspace.fs.writeFile(uri, buf); + const buf = Buffer.from(code, "utf8"); + await vscode.workspace.fs.writeFile(uri, buf); } - return {} + return {}; } - async loadProfiles() { const configFilePath = path.join(os.homedir(), ".aliyun/config.json"); const { R_OK, W_OK } = fs.constants; @@ -188,11 +189,32 @@ export class AlicloudAPIService { } async updateLocalLanguage(lang) { - this.context.globalState.update('defaultLanguage', lang); + this.context.globalState.update("defaultLanguage", lang); } async getLocalLanguage() { - return this.context.globalState.get('defaultLanguage') + return this.context.globalState.get("defaultLanguage"); + } + + async getNoticeFlag() { + const globalState = this.context.globalState; + const experienceQuestionnaireKey = "questionnaireExpiration"; + const lastPromptKey = "lastPromptTime"; + // 检查上次提示的时间 + const lastPromptTime = globalState.get(lastPromptKey) as any; + const questionnaireExpiration = globalState.get(experienceQuestionnaireKey) as any; + if (!lastPromptTime || Date.now() - lastPromptTime > (questionnaireExpiration || 0) * 24 * 60 * 60 * 1000) { + return true; + } + return false; + } + + async updateQuestionnaireExpiration(days: number) { + const globalState = this.context.globalState; + const experienceQuestionnaireKey = "questionnaireExpiration"; + const lastPromptKey = "lastPromptTime"; + globalState.update(experienceQuestionnaireKey, days); + globalState.update(lastPromptKey, Date.now()); } async makeCodeRequest(requestData) { @@ -208,23 +230,22 @@ export class AlicloudAPIService { : "ak" : "ak"; const body = { - "apiName": apiMeta?.name, - "apiVersion": version, - "product": product, - "sdkType": "dara", - "params": newParamsValue || {}, - "regionId": regionId, - "endpoint": endpoint, - "credential": {type: defaultCredentialType}, - "runtimeOptions": {}, - "useCommon": false - } - const resStr = await fetch( - `https://api.aliyun.com/api/product/makeCode`, - {method: 'post', + apiName: apiMeta?.name, + apiVersion: version, + product: product, + sdkType: "dara", + params: newParamsValue || {}, + regionId: regionId, + endpoint: endpoint, + credential: { type: defaultCredentialType }, + runtimeOptions: {}, + useCommon: false, + }; + const resStr = await fetch(`https://api.aliyun.com/api/product/makeCode`, { + method: "post", body: JSON.stringify(body), - headers: {'Content-Type': 'application/json'}}, - ).then((res) => res.text()); + headers: { "Content-Type": "application/json" }, + }).then((res) => res.text()); const res = JSON.parse(resStr); return res; } @@ -247,7 +268,7 @@ export class AlicloudAPIService { : "ak" : "ak"; if (profiles?.length) { - const profile = profiles?.find(item=>item.name === profilesInfo.current) + const profile = profiles?.find((item) => item.name === profilesInfo.current); const start = Date.now(); try { data = await request({ @@ -260,7 +281,7 @@ export class AlicloudAPIService { productName: product, meta: apiMeta, bodyStyle: undefined, - credential: {type: defaultCredentialType}, + credential: { type: defaultCredentialType }, }); response = data; // 设置状态码 @@ -302,13 +323,13 @@ export class AlicloudAPIService { requestId: requestData.requestId, doc: `${product}::${version}::${apiMeta.name}`, type: "openAPIResponse", - response + response, }; - }else{ - let result = await vscode.window.showErrorMessage("请完成AK/SK配置后,再发起调用", "查看配置方法","取消"); - if (result === "查看配置方法") { - vscode.env.openExternal(vscode.Uri.parse('https://github.com/aliyun/aliyun-cli?tab=readme-ov-file#configure')); - } + } else { + let result = await vscode.window.showErrorMessage("请完成AK/SK配置后,再发起调用", "查看配置方法", "取消"); + if (result === "查看配置方法") { + vscode.env.openExternal(vscode.Uri.parse("https://github.com/aliyun/aliyun-cli?tab=readme-ov-file#configure")); + } } } diff --git a/src/commands.ts b/src/commands.ts index 68cef10..3c7eef1 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -78,7 +78,15 @@ export class AlicloudApiCommands { const service = alicloudAPIMessageService; vscode.commands.registerCommand("alicloud.api.githubIssue", async () => { - vscode.env.openExternal(vscode.Uri.parse("https://github.com/aliyun/alibabacloud-api-vscode-toolkit/issues")); + vscode.env.openExternal( + vscode.Uri.parse("https://github.com/aliyun/alibabacloud-api-vscode-toolkit/issues?q=is%3Aissue+is%3Aclosed"), + ); + }); + + vscode.commands.registerCommand("alicloud.api.feedback", async () => { + vscode.env.openExternal( + vscode.Uri.parse("https://g.alicdn.com/aes/tracker-survey-preview/0.0.13/survey.html?pid=fePxMy&id=3486"), + ); }); vscode.commands.registerCommand("alicloud.api.findInterface", () => { diff --git a/src/explorer.ts b/src/explorer.ts index c944abe..cb5ead1 100644 --- a/src/explorer.ts +++ b/src/explorer.ts @@ -348,7 +348,7 @@ export class AlicloudApiExplorer implements vscode.TreeDataProvider