diff --git a/app/assets/components/CodeMirror.tsx b/app/assets/components/CodeMirror.tsx
index 36864e7e..8f8d56c5 100644
--- a/app/assets/components/CodeMirror.tsx
+++ b/app/assets/components/CodeMirror.tsx
@@ -40,7 +40,7 @@ export default class ReactCodeMirror extends React.PureComponent<IProps, any> {
           if (stream.eatSpace()) {
             return null;
           }
-          stream.eatWhile(/[\$\w\u4e00-\u9fa5]/);
+          stream.eatWhile(/[\$:\w\u4e00-\u9fa5]/);
           const cur = stream.current();
           if (keyWords.some(item => item === cur)) {
             return 'keyword';
@@ -127,6 +127,7 @@ export default class ReactCodeMirror extends React.PureComponent<IProps, any> {
       change.preventDefault();
     }
   };
+
   codemirrorValueChange = (doc, change) => {
     if (change.origin !== 'setValue') {
       if (this.props.onChange) {
diff --git a/app/assets/components/OutputBox/index.tsx b/app/assets/components/OutputBox/index.tsx
index cf59cd9e..8fa774be 100644
--- a/app/assets/components/OutputBox/index.tsx
+++ b/app/assets/components/OutputBox/index.tsx
@@ -85,12 +85,22 @@ class OutputBox extends React.Component<IProps> {
   };
   render() {
     const { value, result = {} } = this.props;
-    let columns = [];
+    let columns = [] as any;
     let showSubgraphs = false;
-    const dataSource =
-      result.data && result.data.tables ? result.data.tables : [];
+    let dataSource = [] as any;
+    if (result.data && result.data.tables.length > 0) {
+      dataSource = result.data.tables;
+    } else if (result.data?.localParams) {
+      const params = {};
+      {
+        Object.entries(result.data?.localParams).forEach(
+          ([k, v]) => (params[k] = JSON.stringify(v)),
+        );
+      }
+      dataSource = [{ ...params }];
+    }
     if (result.code === 0) {
-      if (result.data && result.data.headers) {
+      if (result.data && result.data.headers.length > 0) {
         columns = result.data.headers.map(column => {
           return {
             title: column,
@@ -121,6 +131,24 @@ class OutputBox extends React.Component<IProps> {
               item._edgesParsedList ||
               item._pathsParsedList,
           ).length > 0;
+      } else if (result.data?.localParams) {
+        columns = Object.keys(result.data?.localParams).map(column => {
+          return {
+            title: column,
+            dataIndex: column,
+            render: value => {
+              if (typeof value === 'boolean') {
+                return value.toString();
+              } else if (
+                typeof value === 'number' ||
+                BigNumber.isBigNumber(value)
+              ) {
+                return value.toString();
+              }
+              return value;
+            },
+          };
+        });
       }
     }
     return (
diff --git a/app/assets/config/locale/en-US.json b/app/assets/config/locale/en-US.json
index fa336ed0..4f50862e 100644
--- a/app/assets/config/locale/en-US.json
+++ b/app/assets/config/locale/en-US.json
@@ -127,7 +127,8 @@
     "exportVertex": "Please choose the column representing vertex IDs from the table",
     "exportEdge": "Please choose the columns representing source vertex ID, destination vertex ID, and rank of an edge",
     "showSubgraphs": "View Subgraphs",
-    "deleteHistory": "Clear History"
+    "deleteHistory": "Clear History",
+    "parameterDisplay": "Custom Parameters Display"
   },
   "explore": {
     "clear": "Clear",
diff --git a/app/assets/config/locale/zh-CN.json b/app/assets/config/locale/zh-CN.json
index fd4f2b20..9742d2b5 100644
--- a/app/assets/config/locale/zh-CN.json
+++ b/app/assets/config/locale/zh-CN.json
@@ -126,7 +126,8 @@
     "exportVertex": "请选择表中代表点VID的列",
     "exportEdge": "请选择结果中分别代表边的起点(src_vid)、终点(dst_vid)和权重(rank)的列",
     "showSubgraphs": "查看子图",
-    "deleteHistory": "清除历史"
+    "deleteHistory": "清除历史",
+    "parameterDisplay": "自定义参数 展示"
   },
   "explore": {
     "clear": "清除",
diff --git a/app/assets/config/nebulaQL.ts b/app/assets/config/nebulaQL.ts
index 547536a8..950fdbaf 100644
--- a/app/assets/config/nebulaQL.ts
+++ b/app/assets/config/nebulaQL.ts
@@ -133,6 +133,9 @@ const nebulaWordsUppercase = [
   'USERS',
   'UUID',
   'VALUES',
+  'COMMENT',
+  ':PARAM',
+  ':PARAMS',
 ];
 
 export const ban = ['use', 'USE'];
@@ -217,6 +220,8 @@ export const operators = [
   'MINUS',
   // uuid
   'uuid',
+  // assignment
+  '=>',
 ];
 
 const nebulaWordsLowercase = nebulaWordsUppercase.map(w => w.toLowerCase());
diff --git a/app/assets/modules/Console/index.less b/app/assets/modules/Console/index.less
index ef66e093..4dee001a 100644
--- a/app/assets/modules/Console/index.less
+++ b/app/assets/modules/Console/index.less
@@ -16,10 +16,22 @@
 			flex-direction: column;
 			align-items: center;
 
-			> .CodeMirror {
+			.mirror-content {
 				width: 100%;
+				display: flex;
+				align-items: center;
+
+				.btn-drawer {
+					cursor: pointer;
+				}
+
+				> .CodeMirror {
+					min-height: 240px;
+					width: 100%;
+				}
 			}
 
+
 			.mirror-nav {
 				display: flex;
 				align-items: center;
@@ -79,7 +91,7 @@
 		flex: 1;
 		display: flex;
 		flex-direction: column;
-		margin: 32px 0;
+		margin: 15px 0;
 	}
 }
 
@@ -124,3 +136,18 @@
 	}
 }
 
+.param-box {
+	padding: 10px;
+	background-color: white;
+	height: 100%;
+	margin-left: 5px;
+	max-width: 320px;
+	overflow: auto;
+	max-height: 240px;
+
+	p {
+		font-size: 12px;
+		word-break: break-all;
+		margin-bottom: 8px;
+	}
+}
diff --git a/app/assets/modules/Console/index.tsx b/app/assets/modules/Console/index.tsx
index 2e040ead..961e6682 100644
--- a/app/assets/modules/Console/index.tsx
+++ b/app/assets/modules/Console/index.tsx
@@ -15,17 +15,20 @@ import SpaceSearchInput from './SpaceSearchInput';
 interface IState {
   isUpDown: boolean;
   history: boolean;
+  visible: boolean;
 }
 
 const mapState = (state: IRootState) => ({
   result: state._console.result,
   currentGQL: state._console.currentGQL,
+  paramsMap: state._console.paramsMap,
   currentSpace: state.nebula.currentSpace,
   runGQLLoading: state.loading.effects._console.asyncRunGQL,
 });
 
 const mapDispatch = (dispatch: IDispatch) => ({
   asyncRunGQL: dispatch._console.asyncRunGQL,
+  asyncGetParams: dispatch._console.asyncGetParams,
   updateCurrentGQL: gql =>
     dispatch._console.update({
       currentGQL: gql,
@@ -41,6 +44,8 @@ interface IProps
     ReturnType<typeof mapDispatch>,
     RouteComponentProps {}
 
+// split from semicolon out of quotation marks
+const SEMICOLON_REG = /((?:[^;'"]*(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*')[^;'"]*)+)|;/;
 class Console extends React.Component<IProps, IState> {
   codemirror;
   editor;
@@ -51,11 +56,13 @@ class Console extends React.Component<IProps, IState> {
     this.state = {
       isUpDown: true,
       history: false,
+      visible: false,
     };
   }
 
   componentDidMount() {
     trackPageView('/console');
+    this.props.asyncGetParams();
   }
 
   getLocalStorage = () => {
@@ -66,31 +73,35 @@ class Console extends React.Component<IProps, IState> {
     return [];
   };
 
+  handleSaveQuery = (query: string) => {
+    if (query !== '') {
+      const history = this.getLocalStorage();
+      history.push(query);
+      localStorage.setItem('history', JSON.stringify(history));
+    }
+  };
+
+  checkSwitchSpaceGql = (query: string) => {
+    const queryList = query.split(SEMICOLON_REG).filter(Boolean);
+    const reg = /^USE `?[0-9a-zA-Z_]+`?(?=[\s*;?]?)/gim;
+    if (queryList.some(sentence => sentence.trim().match(reg))) {
+      return intl.get('common.disablesUseToSwitchSpace');
+    }
+  };
   handleRun = async () => {
-    const gql = this.editor.getValue();
-    if (!gql) {
+    const query = this.editor.getValue();
+    if (!query) {
       message.error(intl.get('common.sorryNGQLCannotBeEmpty'));
       return;
     }
-    // Hack:
-    // replace the string in quotes with a constant, avoid special symbols in quotation marks from affecting regex match
-    // then split the gql entered by the user into sentences based on semicolons
-    // use regex to determine whether each sentence is a 'use space' statement
-    const _gql = gql
-      .replace(/[\r\n]/g, '')
-      .replace(/(["'])[^]*?\1/g, '_CONTENT_')
-      .toUpperCase();
-    const sentenceList = _gql.split(';');
-    const reg = /^USE `?[0-9a-zA-Z_]+`?(?=[\s*;?]?)/gm;
-    if (sentenceList.some(sentence => sentence.match(reg))) {
-      return message.error(intl.get('common.disablesUseToSwitchSpace'));
+    const errInfo = this.checkSwitchSpaceGql(query);
+    if (errInfo) {
+      return message.error(errInfo);
     }
-    this.editor.execCommand('goDocEnd');
-    const history = this.getLocalStorage();
-    history.push(gql);
-    localStorage.setItem('history', JSON.stringify(history));
 
-    await this.props.asyncRunGQL(gql);
+    this.editor.execCommand('goDocEnd');
+    this.handleSaveQuery(query);
+    await this.props.asyncRunGQL(query);
     this.setState({
       isUpDown: true,
     });
@@ -147,9 +158,22 @@ class Console extends React.Component<IProps, IState> {
     return str.substring(0, 300) + '...';
   };
 
+  toggleDrawer = () => {
+    const { visible } = this.state;
+    this.setState({
+      visible: !visible,
+    });
+  };
+
   render() {
     const { isUpDown, history } = this.state;
-    const { currentSpace, currentGQL, result, runGQLLoading } = this.props;
+    const {
+      currentSpace,
+      currentGQL,
+      result,
+      runGQLLoading,
+      paramsMap,
+    } = this.props;
     return (
       <div className="nebula-console padding-page">
         <div className="ngql-content">
@@ -191,19 +215,38 @@ class Console extends React.Component<IProps, IState> {
                 </Tooltip>
               </div>
             </div>
-            <CodeMirror
-              value={currentGQL}
-              onBlur={value => this.props.updateCurrentGQL(value)}
-              onChangeLine={this.handleLineCount}
-              ref={this.getInstance}
-              height={isUpDown ? '240px' : 24 * maxLineNum + 'px'}
-              onShiftEnter={this.handleRun}
-              options={{
-                keyMap: 'sublime',
-                fullScreen: true,
-                mode: 'nebula',
-              }}
-            />
+            <div className="mirror-content">
+              <Tooltip
+                title={intl.get('console.parameterDisplay')}
+                placement="right"
+              >
+                <Icon
+                  type="file-search"
+                  className="btn-drawer"
+                  onClick={this.toggleDrawer}
+                />
+              </Tooltip>
+              {this.state.visible && (
+                <div className="param-box">
+                  {Object.entries(paramsMap).map(([k, v]) => (
+                    <p key={k}>{`${k} => ${JSON.stringify(v)}`}</p>
+                  ))}
+                </div>
+              )}
+              <CodeMirror
+                value={currentGQL}
+                onBlur={value => this.props.updateCurrentGQL(value)}
+                onChangeLine={this.handleLineCount}
+                ref={this.getInstance}
+                height={isUpDown ? '240px' : 24 * maxLineNum + 'px'}
+                onShiftEnter={this.handleRun}
+                options={{
+                  keyMap: 'sublime',
+                  fullScreen: true,
+                  mode: 'nebula',
+                }}
+              />
+            </div>
           </div>
         </div>
         <div className="result-wrap">
diff --git a/app/assets/store/models/console.ts b/app/assets/store/models/console.ts
index 99c65942..ad9713ff 100644
--- a/app/assets/store/models/console.ts
+++ b/app/assets/store/models/console.ts
@@ -3,14 +3,37 @@ import { createModel } from '@rematch/core';
 import service from '#assets/config/service';
 
 interface IState {
-  version: string;
+  currentGQL: string;
+  result: any;
+  paramsMap: any;
 }
 
+// split from semicolon out of quotation marks
+const SEMICOLON_REG = /((?:[^;'"]*(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*')[^;'"]*)+)|;/;
+const splitQuery = (query: string) => {
+  const queryList = query.split(SEMICOLON_REG).filter(Boolean);
+  const paramList: string[] = [];
+  const gqlList: string[] = [];
+  queryList.forEach(query => {
+    const _query = query.trim();
+    if (_query.startsWith(':')) {
+      paramList.push(_query);
+    } else {
+      gqlList.push(_query);
+    }
+  });
+  return {
+    paramList,
+    gqlList,
+  };
+};
+
 export const _console = createModel({
   state: {
     currentGQL: 'SHOW SPACES;',
     result: {},
-  },
+    paramsMap: null,
+  } as IState,
   reducers: {
     update: (state: IState, payload: any) => {
       return {
@@ -21,8 +44,12 @@ export const _console = createModel({
   },
   effects: {
     async asyncRunGQL(gql) {
+      const { gqlList, paramList } = splitQuery(gql);
       const result = (await service.execNGQL(
-        { gql },
+        {
+          gql: gqlList.join(';'),
+          paramList,
+        },
         {
           trackEventConfig: {
             category: 'console',
@@ -30,10 +57,34 @@ export const _console = createModel({
           },
         },
       )) as any;
+      const updateQuerys = paramList.filter(item => {
+        const reg = /^\s*:params/gim;
+        return !reg.test(item);
+      });
+      if (updateQuerys.length > 0) {
+        await this.asyncGetParams();
+      }
       this.update({
         result,
         currentGQL: gql,
       });
     },
+    async asyncGetParams() {
+      const result = (await service.execNGQL(
+        {
+          gql: '',
+          paramList: [':params'],
+        },
+        {
+          trackEventConfig: {
+            category: 'console',
+            action: 'run_gql',
+          },
+        },
+      )) as any;
+      this.update({
+        paramsMap: result.data?.localParams || {},
+      });
+    },
   },
 });