浏览代码

support runapi client

star7th 5 年之前
父节点
当前提交
a7e0a2196a

+ 6 - 0
server/Application/Api/Controller/CatalogController.class.php

@@ -235,6 +235,12 @@ class CatalogController extends BaseController {
                         "s_number" => $value['s_number'] ,
                         ));
                 }
+                if ($value['page_id'] > 0) {
+                    $ret = D("Page")->where(" page_id = '$value[page_id]' and item_id = '$item_id' ")->save(array(
+                        "cat_id" => $value['parent_cat_id'] ,
+                        "s_number" => $value['s_number'] ,
+                        ));
+                }
 
             }
         }

+ 7 - 0
server/Application/Api/Controller/CommonController.class.php

@@ -88,5 +88,12 @@ class CommonController extends BaseController {
             );
         $this->sendResult($array);
     }
+
+    //返回showdoc版本
+    public function version(){
+      $file = file_get_contents('../composer.json');
+      $json = json_decode($file , 1 );
+      $this->sendResult(array("version"=>$json['version']));
+    }
     
 }

+ 158 - 8
server/Application/Api/Controller/ImportPostmanController.class.php

@@ -34,10 +34,10 @@ class ImportPostmanController extends BaseController {
 
         // TODO 这里需要检查下合法性。比如关键字检查/黑名单检查/字符串过滤
 
-
+        $from = I("from") ? I("from") : '' ;
         $item_array = array(
             "item_name" => $json_array['name'] ? $json_array['name'] : 'from postman' ,
-            "item_type" => '1' ,
+            "item_type" =>   ($from == 'runapi') ? '3': '1' ,
             "item_description" => $json_array['description'] ? $json_array['description'] :'',
             "password" => time().rand(),
             "members" => array(),
@@ -72,11 +72,12 @@ class ImportPostmanController extends BaseController {
 
         }
 
-        D("Item")->import( json_encode($item_array) , $login_user['uid'] );
+        $item_id = D("Item")->import( json_encode($item_array) , $login_user['uid'] );
         
         //echo D("Item")->export(196053901215026 );
         //echo json_encode($item_array);
-        $this->sendResult(array());
+        $this->sendResult(array("item_id"=>$item_id));
+
 
 
     }
@@ -120,6 +121,11 @@ class ImportPostmanController extends BaseController {
 
 
     private function _requestToDoc($request){
+        $from = I("from") ? I("from") : '' ;
+        if($from == 'runapi'){
+            return $this->_requestToApi($request);
+            //如果是来自runapi的导入请求,则已经return不再执行下面
+        }
         $return = array() ;
         $return['page_title'] = $request['name'] ;
         $return['id'] = $request['id'] ;
@@ -187,6 +193,75 @@ $content .='
 
     }
 
+    //转成runapi所需要的api格式
+    private function _requestToApi($request){
+        $return = array() ;
+        $return['page_title'] = $request['name'] ;
+        $return['id'] = $request['id'] ;
+        $return['s_number'] = 99 ;
+        $return['page_comments'] = '' ;
+        //若$return['page_title'] 为很长的url,则做一些特殊处理
+        $tmp_title_array = explode("/", $return['page_title']);
+        if ($tmp_title_array) {
+            $tmp_title_array = array_slice($tmp_title_array, -2);// 倒数2个
+            if($tmp_title_array[1])$return['page_title'] = $tmp_title_array[0]."/".$tmp_title_array[1] ;
+        }
+        
+        $content_array = array(
+                "info"=>array(
+                    "from" =>  'runapi'  ,
+                    "type" =>  'api'  ,
+                    "title" =>  $request['name']  ,
+                    "description" =>  $request['description']  ,
+                    "method" =>  strtolower($request['method'])  ,
+                    "url" =>  $request['url']  ,
+                    "remark" =>  '' ,
+                ),
+                "request" =>array(
+                    "params"=> array(
+                        'mode' => "urlencoded",
+                        'json' => "",
+                        'urlencoded' => array(),
+                        'formdata' => array(),
+                    ),
+                    "headers"=> array(),
+                    "cookies"=> array(),
+                    "auth"=> array(),
+                ),
+                "response" =>array(),
+                "extend" =>array(),
+            );
+
+        if ($request['headerData']) {
+            $tmp_array = array();
+            foreach ($request['headerData'] as $key => $value) {
+                 $content_array['request']['headers'][] = array(
+                        "name" =>$value["key"],
+                        "type" =>'string',
+                        "value" =>$value["value"],
+                        "require" =>'1',
+                        "remark" =>'',
+                    );
+            }
+        }
+
+        if ($request['data']) {
+
+            foreach ($request['data'] as $key => $value) {
+                 $content_array['request']['params']['urlencoded'][] = array(
+                        "name" =>$value["key"],
+                        "type" =>'string',
+                        "value" =>$value["value"],
+                        "require" =>'1',
+                        "remark" =>'',
+                    );
+            }
+        }
+
+        $return['page_content'] = json_encode($content_array) ;
+        return $return ;
+    }
+
 
     //从postman导入(v2版本)
     private function _fromPostmanV2($json_array){
@@ -195,10 +270,10 @@ $content .='
 
         // TODO 这里需要检查下合法性。比如关键字检查/黑名单检查/字符串过滤
 
-
+        $from = I("from") ? I("from") : '' ;
         $item_array = array(
             "item_name" => $json_array['info']['name'] ? $json_array['info']['name']  : 'from postman' ,
-            "item_type" => '1' ,
+            "item_type" => ($from=='runapi') ? '3' : '1' ,
             "item_description" => $json_array['info']['description'] ? $json_array['info']['description'] :'',
             "password" => time().rand(),
             "members" => array(),
@@ -210,11 +285,11 @@ $content .='
         $level = 2 ;
         $item_array['pages']['pages'] = $this->_getPageByItem($json_array['item'] );
         $item_array['pages']['catalogs'] = $this->_getItemByItem($json_array['item'] , 2 );
-        D("Item")->import( json_encode($item_array) , $login_user['uid'] );
+        $item_id =  D("Item")->import( json_encode($item_array) , $login_user['uid'] );
         
         //echo D("Item")->export(196053901215026 );
         //echo json_encode($item_array);
-        $this->sendResult(array());
+        $this->sendResult(array("item_id"=>$item_id));
 
 
     }
@@ -255,6 +330,11 @@ $content .='
     }
 
     private function _requestToDocV2($name , $request){
+        $from = I("from") ? I("from") : '' ;
+        if($from == 'runapi'){
+            return $this->_requestToApiV2($name , $request);
+            //如果是来自runapi的导入请求,则已经return不再执行下面
+        }
         $return = array() ;
         $return['page_title'] = $name ;
         $return['s_number'] = 99 ;
@@ -324,4 +404,74 @@ $content .='
 
     }
 
+    //转成runapi所需要的api格式
+    private function _requestToApiV2($name , $request){
+        $return = array() ;
+        $return['page_title'] = $name ;
+        $return['s_number'] = 99 ;
+        $return['page_comments'] = '' ;
+        //若$return['page_title'] 为很长的url,则做一些特殊处理
+        $tmp_title_array = explode("/", $return['page_title']);
+        if ($tmp_title_array) {
+            $tmp_title_array = array_slice($tmp_title_array, -2);// 倒数2个
+            if($tmp_title_array[1])$return['page_title'] = $tmp_title_array[0]."/".$tmp_title_array[1] ;
+        }
+        $url = is_array($request['url']) ? $request['url']['raw'] : $request['url'] ;
+        $rawModeData = $request['body']['mode'] == 'raw' ? $request['body']['raw']  : $request['rawModeData'] ;
+
+        $content_array = array(
+                "info"=>array(
+                    "from" =>  'runapi'  ,
+                    "type" =>  'api'  ,
+                    "title" =>  $name ,
+                    "description" =>  $request['description']  ,
+                    "method" =>  strtolower($request['method'])  ,
+                    "url" =>  $url ,
+                    "remark" =>  '' ,
+                ),
+                "request" =>array(
+                    "params"=> array(
+                        'mode' => "formdata",
+                        'json' => "",
+                        'urlencoded' => array(),
+                        'formdata' => array(),
+                    ),
+                    "headers"=> array(),
+                    "cookies"=> array(),
+                    "auth"=> array(),
+                ),
+                "response" =>array(),
+                "extend" =>array(),
+            );
+
+        if ($request['header']) {
+            $tmp_array = array();
+            foreach ($request['header'] as $key => $value) {
+                 $content_array['request']['headers'][] = array(
+                        "name" =>$value["key"],
+                        "type" =>'string',
+                        "value" =>$value["value"],
+                        "require" =>'1',
+                        "remark" =>'',
+                    );
+            }
+        }
+
+        if ($request['body']['formdata']) {
+            foreach ($request['body']['formdata'] as $key => $value) {
+                 $content_array['request']['params']['formdata'][] = array(
+                        "name" =>$value["key"],
+                        "type" =>'string',
+                        "value" =>$value["value"],
+                        "require" =>'1',
+                        "remark" =>'',
+                    );
+            }
+        }
+
+        $return['page_content'] = json_encode($content_array) ;
+
+        return $return ;
+    }
+
 }

+ 78 - 5
server/Application/Api/Controller/ImportSwaggerController.class.php

@@ -26,7 +26,7 @@ class ImportSwaggerController extends BaseController {
 
         // TODO 这里需要检查下合法性。比如关键字检查/黑名单检查/字符串过滤
 
-
+        $from = I("from") ? I("from") : '' ;
         $item_array = array(
             "item_name" => $json_array['info']['title'] ? $json_array['info']['title']  : 'from swagger' ,
             "item_type" => '1' ,
@@ -35,16 +35,21 @@ class ImportSwaggerController extends BaseController {
             "members" => array(),
             "pages" =>array(
                     "pages" => array(),
-                    "catalogs" => array()
+                    "catalogs" => array(
+                            array(
+                                "cat_name" =>'from swagger',
+                                "pages" =>array()
+                            )
+                        )
                 )
             ) ;
         $level = 2 ;
-        $item_array['pages']['pages'] = $this->_getPageByPaths($json_array );
-        D("Item")->import( json_encode($item_array) , $login_user['uid'] );
+        $item_array['pages']['catalogs'][0]['pages'] = $this->_getPageByPaths($json_array);
+        $item_id = D("Item")->import( json_encode($item_array) , $login_user['uid'] );
         
         //echo D("Item")->export(196053901215026 );
         //echo json_encode($item_array);
-        $this->sendResult(array());
+        $this->sendResult(array('item_id' => $item_id));
 
     }
 
@@ -61,6 +66,11 @@ class ImportSwaggerController extends BaseController {
     }
 
     private function _requestToDoc($method , $url , $request , $json_array){
+        $from = I("from") ? I("from") : '' ;
+        if($from == 'runapi'){
+            return $this->_requestToApi($method , $url , $request , $json_array);
+            //如果是来自runapi的导入请求,则已经return不再执行下面
+        }
         $return = array() ;
         $return['page_title'] = $request['summary'] ;
         $return['s_number'] = 99 ;
@@ -160,6 +170,69 @@ $content .= '
 
     }
 
+    private function _requestToApi($method , $url , $request , $json_array){
+        $return = array() ;
+        $return['page_title'] = $request['summary'] ;
+        $return['s_number'] = 99 ;
+        $return['page_comments'] = '' ;
+        
+        $content_array = array(
+                "info"=>array(
+                    "from" =>  'runapi'  ,
+                    "type" =>  'api'  ,
+                    "title" => $request['summary']  ,
+                    "description" =>  $request['description']  ,
+                    "method" =>  strtolower($method)  ,
+                    "url" =>  $url  ,
+                    "remark" =>  '' ,
+                ),
+                "request" =>array(
+                    "params"=> array(
+                        'mode' => "formdata",
+                        'json' => "",
+                        'urlencoded' => array(),
+                        'formdata' => array(),
+                    ),
+                    "headers"=> array(),
+                    "cookies"=> array(),
+                    "auth"=> array(),
+                ),
+                "response" =>array(),
+                "extend" =>array(),
+            );
+
+        if ($request['headerData']) {
+            $tmp_array = array();
+            foreach ($request['headerData'] as $key => $value) {
+                 $content_array['request']['headers'][] = array(
+                        "name" =>$value["key"],
+                        "type" =>'string',
+                        "value" =>$value["value"],
+                        "require" =>'1',
+                        "remark" =>'',
+                    );
+            }
+        }
+
+        if ($request['parameters']) {
+
+            foreach ($request['parameters'] as $key => $value) {
+                 $content_array['request']['params']['formdata'][] = array(
+                        "name" =>$value["name"],
+                        "type" =>'string',
+                        "value" =>$value["value"],
+                        "require" =>'1',
+                        "remark" =>$value["description"],
+                    );
+            }
+        }
+
+        $return['page_content'] = json_encode($content_array);
+        return $return ;
+
+    }
+
+
     /**
      * Indents a flat JSON string to make it more human-readable.
      *

+ 7 - 6
server/Application/Api/Controller/ItemController.class.php

@@ -124,7 +124,7 @@ class ItemController extends BaseController {
             "default_cat_id3"=>$default_cat_id3 ,
             "default_cat_id4"=>$default_cat_id4 ,
             "unread_count"=>$unread_count ,
-            "item_type"=>1 ,
+            "item_type"=>$item['item_type'] ,
             "menu"=>$menu ,
             "is_login"=>$is_login,
             "ItemPermn"=>$ItemPermn ,
@@ -197,6 +197,7 @@ class ItemController extends BaseController {
                $items[$key]['creator'] = 1 ;
             }else{
                $items[$key]['creator'] = 0 ;
+               unset($items[$key]['password']);
             }
             //判断是否为私密项目
             if ($value['password']) {
@@ -204,7 +205,7 @@ class ItemController extends BaseController {
             }else{
                 $items[$key]['is_private'] = 0 ; 
             }
-            unset($items[$key]['password']);
+            
             //如果项目已标识为删除
             if ($value['is_del'] == 1) {
                 unset($items[$key]);
@@ -558,9 +559,9 @@ class ItemController extends BaseController {
                 $this->sendError(10103);
                 return;
             }
-            $ret = D("Item")->copy($copy_item_id,$login_user['uid'],$item_name,$item_description,$password,$item_domain);
-            if ($ret) {
-                $this->sendResult(array());             
+            $item_id = D("Item")->copy($copy_item_id,$login_user['uid'],$item_name,$item_description,$password,$item_domain);
+            if ($item_id) {
+                $this->sendResult(array("item_id"=>$item_id));               
             }else{
                 $this->sendError(10101);
             }
@@ -593,7 +594,7 @@ class ItemController extends BaseController {
                     );
                 $page_id = D("Page")->add($insert);
             }
-            $this->sendResult(array());               
+            $this->sendResult(array("item_id"=>$item_id));               
         }else{
             $this->sendError(10101);
         }

+ 76 - 0
server/Application/Api/Controller/ItemVariableController.class.php

@@ -0,0 +1,76 @@
+<?php
+namespace Api\Controller;
+use Think\Controller;
+class ItemVariableController extends BaseController {
+
+
+    //保存
+    public function save(){ 
+        $item_id = I("item_id/d");  
+        $var_name = I("var_name");  
+        $var_value = I("var_value");  
+        $login_user = $this->checkLogin();
+        $uid = $login_user['uid'] ;
+        if(!$this->checkItemPermn($uid , $item_id)){
+            $this->sendError(10303);
+            return ;
+        } 
+        $data = array() ;
+        $data['var_name'] = $var_name ;
+        $data['uid'] = $uid ;
+        $data['var_value'] = $var_value ;
+        $data['item_id'] = $item_id ;
+        $data['addtime'] = time() ;
+
+        $id = D("ItemVariable")->add($data);
+
+        if (!$id) {
+            $this->sendError(10101);
+        }else{
+            $this->sendResult($id);
+        }
+        
+    }
+
+    //获取列表
+    public function getList(){
+        $item_id = I("item_id/d");  
+        $login_user = $this->checkLogin();
+        $uid = $login_user['uid'] ;
+        if(!$this->checkItemPermn($uid , $item_id)){
+            $this->sendError(10303);
+            return ;
+        } 
+        if ($item_id > 0 ) {
+            $ret = D("ItemVariable")->where(" item_id = '$item_id' ")->order(" addtime asc  ")->select();
+        }
+        if ($ret) {
+            foreach ($ret as $key => &$value) {
+                $value['addtime'] = date("Y-m-d H:i:s",$value['addtime']);
+            }
+        }
+        $this->sendResult($ret);
+    }
+
+    //删除
+    public function delete(){
+        $item_id = I("item_id/d");  
+        $id = I("id/d");  
+        $login_user = $this->checkLogin();
+        $uid = $login_user['uid'] ;
+        if(!$this->checkItemCreator($uid , $item_id)){
+            $this->sendError(10303);
+            return ;
+        } 
+         $ret = D("ItemVariable")->where(" item_id = '%d' and id = '%d'  ",array($item_id,$id))->delete();
+        if ($ret) {
+           $this->sendResult($ret);
+        }else{
+            $this->sendError(10101);
+        }
+    }
+
+
+
+
+}

+ 12 - 0
server/Application/Home/Controller/UpdateController.class.php

@@ -261,6 +261,18 @@ class UpdateController extends BaseController {
             D("User")->execute($sql);
         }
 
+        //创建item_variable表
+        $sql = "CREATE TABLE IF NOT EXISTS `item_variable` (
+            `id`  INTEGER PRIMARY KEY ,
+            `var_name` CHAR(2000) NOT NULL DEFAULT '',
+            `var_value` CHAR(2000) NOT NULL DEFAULT '',
+            `uid` int(11) NOT NULL DEFAULT '0',
+            `item_id` int(11) NOT NULL DEFAULT '0',
+            `addtime` int(11) NOT NULL DEFAULT '0'
+            )";
+        D("User")->execute($sql);
+
+
         echo "OK!\n";
     }
 

+ 6 - 3
web_src/src/components/item/Index.vue

@@ -28,6 +28,12 @@
             </a>
           </el-tooltip>
 
+          <el-tooltip v-if="lang =='zh-cn'" class="item" effect="dark" content="接口开发调试工具RunApi" placement="top">
+            <a target="_blank" href="https://www.showdoc.cc/runapi">
+              <i class="el-icon-connection"></i>
+            </a>
+          </el-tooltip>
+
           <el-tooltip class="item" effect="dark" :content="$t('team_mamage')" placement="top">
             <router-link to="/team/index">
               <i class="el-icon-s-flag"></i>
@@ -54,9 +60,6 @@
                 <el-dropdown-item>
                   <router-link to="/user/setting">{{$t("personal_setting")}}</router-link>
                 </el-dropdown-item>
-                <el-dropdown-item>
-                  <a target="_blank" v-if="lang =='zh-cn'" href="http://runapi.showdoc.cc/">RunApi</a>
-                </el-dropdown-item>
                 <el-dropdown-item :command="logout">{{$t("logout")}}</el-dropdown-item>
               </el-dropdown-menu>
             </el-dropdown>

+ 5 - 1
web_src/src/components/item/show/Index.vue

@@ -7,7 +7,7 @@
       :item_info="item_info"
       :search_item="search_item"
       :keyword="keyword"
-      v-if="item_info && item_info.item_type == 1 "
+      v-if="item_info && (item_info.item_type == 1 || item_info.item_type == 3 ) "
     ></ShowRegularItem>
 
     <!-- 展示单页项目 -->
@@ -61,6 +61,10 @@ export default {
               json.default_page_id = json.menu.pages[0].page_id
             }
           }
+          //如果是irunapi类型项目,则去掉编辑权限。只允许在runapi里编辑
+          if(json.item_type == 3){
+            json.ItemCreator = json.ItemPermn = false;  
+          }
           that.item_info = json
           document.title = that.item_info.item_name + '--ShowDoc'
           if (json.unread_count > 0) {

+ 2 - 1
web_src/src/components/item/show/show_regular_item/Index.vue

@@ -71,6 +71,7 @@ import Toc from '@/components/item/show/show_regular_item/Toc'
 import LeftMenu from '@/components/item/show/show_regular_item/LeftMenu'
 import OpBar from '@/components/item/show/show_regular_item/OpBar'
 import AttachmentList from '@/components/page/edit/AttachmentList'
+import { rederPageContent } from '@/models/page'
 
 export default {
   props: {
@@ -114,7 +115,7 @@ export default {
       that.axios.post(url, params).then(function(response) {
         // loading.close();
         if (response.data.error_code === 0) {
-          that.content = response.data.data.page_content
+           that.content = rederPageContent(response.data.data.page_content)
 
           that.page_title = response.data.data.page_title
           that.page_info = response.data.data

+ 2 - 1
web_src/src/components/page/edit/Index.vue

@@ -171,6 +171,7 @@ import AttachmentList from '@/components/page/edit/AttachmentList'
 import PasteTable from '@/components/page/edit/PasteTable'
 import SortPage from '@/components/page/edit/SortPage'
 import { Base64 } from 'js-base64'
+import { rederPageContent } from '@/models/page'
 
 export default {
   data() {
@@ -250,7 +251,7 @@ export default {
         .then(function(response) {
           if (response.data.error_code === 0) {
             // that.$message.success("加载成功");
-            that.content = response.data.data.page_content
+            that.content = rederPageContent(response.data.data.page_content)
             setTimeout(function() {
               that.insertValue(that.content, 1)
               document.body.scrollTop = document.documentElement.scrollTop = 0 // 回到顶部

+ 133 - 0
web_src/src/models/page.js

@@ -0,0 +1,133 @@
+// 处理页面数据相关的逻辑
+
+// 渲染来自runapi的文档
+const rederPageContent = (page_content) => {
+  let obj
+  // 先定义一个html反转义的函数
+  const unescapeHTML = (str) =>
+    str.replace(
+      /&amp;|&lt;|&gt;|&#39;|&quot;/g,
+      (tag) =>
+        ({
+          '&amp;': '&',
+          '&lt;': '<',
+          '&gt;': '>',
+          '&#39;': "'",
+          '&quot;': '"'
+        }[tag] || tag)
+    )
+  page_content = unescapeHTML(page_content)
+  try {
+    obj = JSON.parse(page_content)
+  } catch (e) {
+    // console.log(`不支持解析的页面内容:${page_content}`);
+  }
+  if (!obj || !obj.info || !obj.info.url) {
+    return page_content
+  }
+  console.log(obj)
+  let newContent = `
+
+**简要描述:**
+  - ${obj.info.description ? obj.info.description : '无'}
+
+**请求URL:**
+
+  - \` ${obj.info.url} \`
+
+**请求方式:**
+  - ${obj.info.method}
+ `
+
+  if (
+    obj.request.headers &&
+    obj.request.headers[0] &&
+    obj.request.headers[0].name
+  ) {
+    newContent += `
+**Header**
+
+|header|必选|类型|说明|
+|:-----  |:-----|-----|
+`
+    const headers = obj.request.headers
+    headers.map((one) => {
+      newContent += `|${one.name} |${one.require > 0 ? '是' : '否'} |${one.type} |${
+        one.remark ? one.remark : '无'
+        }   |
+`
+    })
+  }
+  const params = obj.request.params[obj.request.params.mode]
+
+  if (
+    params &&
+    params[0] &&
+    params[0].name
+  ) {
+    newContent += `
+**请求参数**
+
+|参数名|必选|类型|说明|
+|:-----  |:-----|-----|
+`
+    params.map((one) => {
+      newContent += `|${one.name} |${one.require > 0 ? '是' : '否'} |${one.type} |${
+        one.remark ? one.remark : '无'
+        }   |
+`
+    })
+  }
+
+  if (
+    obj.request.params.mode == 'json' && params
+  ) {
+    newContent += `
+**请求参数示例**
+\`\`\`
+${params}
+\`\`\`
+
+`
+  }
+
+  if (obj.response.responseExample) {
+    newContent += `
+** 返回示例 **
+\`\`\`
+${obj.response.responseExample}
+   \`\`\`
+   `
+  }
+
+  if (
+    obj.response.responseParamsDesc &&
+    obj.response.responseParamsDesc[0] &&
+    obj.response.responseParamsDesc[0].name
+  ) {
+    newContent += `
+**返回参数说明**
+
+|参数名|类型|说明|
+|:-----  |:-----|-----|
+`
+    const returnParams = obj.response.responseParamsDesc
+    returnParams.map((one) => {
+      newContent += `|${one.name} |${one.type} |${
+        one.remark ? one.remark : '无'
+        }   |
+`
+    })
+  }
+
+  newContent += `
+   **备注**
+
+  - ${obj.info.remark}
+
+`
+
+  return newContent
+}
+
+export { rederPageContent }

+ 1 - 0
web_src/src/models/readme.md

@@ -0,0 +1 @@
+showdoc 一开始只是个很简单的工具,采用单文件组件独立的方式,在单文件里包含组件的所有方法(视图和数据处理逻辑等)。后来随着复杂度上升,觉得可以把一些数据加工逻辑独立出来,方便分层和复用。