diff --git a/catch/apimanager/ApimanagerService.php b/catch/apimanager/ApimanagerService.php
new file mode 100644
index 0000000..0c48bde
--- /dev/null
+++ b/catch/apimanager/ApimanagerService.php
@@ -0,0 +1,23 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager;
+
+use catcher\ModuleService;
+
+class ApimanagerService extends ModuleService
+{
+ public function loadRouteFrom()
+ {
+ // TODO: Implement loadRouteFrom() method.
+ return __DIR__ . DIRECTORY_SEPARATOR . 'route.php';
+ }
+}
diff --git a/catch/apimanager/README.md b/catch/apimanager/README.md
new file mode 100644
index 0000000..d924fed
--- /dev/null
+++ b/catch/apimanager/README.md
@@ -0,0 +1,90 @@
+apimanager 模块是一个用于API管理、测试的模块。
+
+# 概述
+
+ 本模块的设计目标是提供开发人员、产品人员等相关角色,可以管理和测试API,可以将系统内部或外部API信息保存在系统内,使得产品具有自完备的特性和持续交付的特性,并可进行灵活的二次开发。
+
+## 主要特性
+
+1. 支持API分类管理,支持自定义用户环境变量,支持API测试用例管理。
+2. 支持HTTP、HTTPS接口测试用例的在线运行。(更多协议支持规划在模块roadmap中)
+3. 支持接口文档管理。
+4. 已集成微信第三方平台相关接口测试用例,开发者可快速进行第三方平台应用开发。
+5. 支持多帐号多应用使用环境,易于团队协作,不限制接口数量、用户数量、请求数量。
+6. 基于catchadmin开发,模块安装简单,使用便捷,支持模块数据导入导出。
+7. 开源开放易于二次开发,测试用例可共享,形成产品API知识库。
+8. 支持私有化部署、云原生部署。
+
+ 演示地址:www.uctoo.com 控制台使用demo帐号登录
+ 模块使用界面截图:
+
+
+  |
+
+
+  |
+
+
+  |
+
+
+  |
+
+
+  |
+
+
+  |
+
+
+  |
+
+
+
+## 产品架构
+1. 基于catchadmin标准模块开发方式开发,可在管理后台一键安装模块和初始化模块数据。
+2. 前端采用axios技术选型,前端可形成标准客户端接口库。
+3. 本地接口(数据源类型local)主要沿用catchadmin基于用户身份的接口鉴权方案,需在API测试用例header添加authorization参数,其值为登录接口返回的值。
+4. 在扫码登录后注册用户帐号接口测试用例,演示了采用微信扫码登录后获取到的用户access_token进行接口鉴权的示例。
+5. 微信相关开发使用了[uctoo/think-easywechat SDK](https://gitee.com/UCT/think-easywechat) 集成catchadmin (TP6+VUE) 和 easywechat 4,支持微信第三方平台、微信小程序云开发、微信支付服务商等特性。
+
+## 安装教程
+
+### 运行环境依赖
+
+ PHP >= 7.1.0
+ Mysql >= 5.5.0 (需支持innodb引擎)
+ PDO PHP Extension
+ MBstring PHP Extension
+ CURL PHP Extension
+ ZIP Extension
+ Composer
+ catchadmin
+
+### 分步骤安装
+1. 从https://gitee.com/jaguarjack/catchAdmin 或 https://gitee.com/uctoo/uctoo 下载https://gitee.com/uctoo/uctoo/tree/master/catch/apimanager 目录模块,复制到catchadmin对应目录
+2. apimanager/catch-admin-vue 目录内是模块前端vue项目代码,复制到前端VUE项目对应目录,注意如和原前端vue项目目录的文件有冲突,需自行合并代码版本。
+3. 前端package.json文件请谨慎覆盖原项目文件。请使用命令 npm install --save @smallwei/avue ,npm install --save vue-json-editor ,npm install --save vue-json-views 添加模块依赖(等效于手动合并package.json版本)。如模块新依赖了第三方组件,需要在前端项目目录重新运行 yarn install 命令。
+3. 登录管理后台,在系统管理->模块管理启用API管理模块,即可安装模块和初始化模块数据。
+
+## 使用手册
+1. 可以通过API管理->API分类功能增删改查API分类。
+2. 可以通过API环境变量功能增删改查用户环境变量。环境变量的key值以{{key}}方式定义,在API测试用例中对应的{{key}}值将替换为环境变量的value值。每个用户可以创建多组环境变量,可以切换当前选中的环境变量组。
+3. 可以通过API列表功能增删改查API测试用例。api_url、header、body、query、auth字段支持环境变量。
+4. 可以对已添加的API测试用例执行测试操作,在API测试界面,可以对api_url、header、body、query、auth等字段进行自定义编辑。发送按钮可以实际执行API测试用例,获得接口返回值。
+
+ 具体请参考 https://www.kancloud.cn/doc_uctoo/manual
+
+## 开发说明
+### 模块roadmap
+
+1. 通过解析路由文件router.php中的数据,自动生成系统接口(system类型)的所有测试用例。即实现系统接口的可视化测试。
+2. 实现API管理功能,即可通过界面配置进行基于appid的接口权限管理,OAUTH2接口鉴权方案。
+3. 实现API测试用例中API文档字段支持markdown编辑和展示。
+4. 实现除POST、GET、PUT、DELETE之外的其他接口请求方式。
+5. 实现全部content-type类型的支持。
+6. 实现测试数据的保存、历史记录等功能。
+7. 实现notify类型接口的测试,目前还没有在市面上见过类似功能的产品,但是实际开发中notify类型的接口在微信第三方平台、各种支付回调、硬件数据上传等很多场景都有遇到。
+8. 实现API测试用例的公开(共享)、私有、保护(有偿获取)等特性。
+
+ 具体请参考开源版开发手册 https://www.kancloud.cn/doc_uctoo/uctoo_dev 及 本开源项目示例
\ No newline at end of file
diff --git a/catch/apimanager/catch-admin-vue/package.json b/catch/apimanager/catch-admin-vue/package.json
new file mode 100644
index 0000000..37d0ef3
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/package.json
@@ -0,0 +1,116 @@
+{
+ "name": "catch-admin",
+ "version": "4.4.0",
+ "description": "catch-admin manage system on element-admin-vue",
+ "author": "JaguarJack ",
+ "scripts": {
+ "dev": "vue-cli-service serve",
+ "lint": "eslint --ext .js,.vue src",
+ "build:prod": "vue-cli-service build",
+ "build:stage": "vue-cli-service build --mode staging",
+ "preview": "node build/index.js --preview",
+ "new": "plop",
+ "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
+ "test:unit": "jest --clearCache && vue-cli-service test:unit",
+ "test:ci": "npm run lint && npm run test:unit"
+ },
+ "dependencies": {
+ "@form-create/element-ui": "^2.5.4",
+ "axios": "0.18.1",
+ "clipboard": "2.0.4",
+ "codemirror": "5.45.0",
+ "core-js": "3.6.5",
+ "driver.js": "0.9.5",
+ "dropzone": "5.5.1",
+ "echarts": "4.2.1",
+ "element-ui": "2.13.2",
+ "file-saver": "2.0.1",
+ "fuse.js": "3.4.4",
+ "js-cookie": "2.2.0",
+ "jsonlint": "1.6.3",
+ "jszip": "3.2.1",
+ "normalize.css": "7.0.0",
+ "nprogress": "0.2.0",
+ "path-to-regexp": "2.4.0",
+ "screenfull": "4.2.0",
+ "script-loader": "0.7.2",
+ "sortablejs": "1.8.4",
+ "vue": "2.6.10",
+ "vue-count-to": "1.0.13",
+ "vue-highlightjs": "^1.3.3",
+ "vue-router": "3.0.2",
+ "vue-splitpane": "1.0.4",
+ "vuedraggable": "2.20.0",
+ "vuex": "3.1.0",
+ "xlsx": "0.14.1"
+ },
+ "devDependencies": {
+ "@smallwei/avue": "^2.8.17",
+ "@vue/cli-plugin-babel": "4.4.4",
+ "@vue/cli-plugin-eslint": "4.4.4",
+ "@vue/cli-plugin-unit-jest": "4.4.4",
+ "@vue/cli-service": "4.4.4",
+ "@vue/test-utils": "1.0.0-beta.29",
+ "autoprefixer": "9.5.1",
+ "babel-eslint": "10.1.0",
+ "babel-jest": "^26.3.0",
+ "babel-plugin-dynamic-import-node": "2.3.3",
+ "chalk": "2.4.2",
+ "chokidar": "2.1.5",
+ "connect": "3.6.6",
+ "eslint": "6.7.2",
+ "eslint-plugin-vue": "6.2.2",
+ "highlight.js": "^10.2.0",
+ "html-webpack-plugin": "3.2.0",
+ "husky": "1.3.1",
+ "lint-staged": "8.1.5",
+ "lodash": "^4.17.20",
+ "mockjs": "1.0.1-beta3",
+ "plop": "2.3.0",
+ "runjs": "4.3.2",
+ "sass": "1.26.2",
+ "sass-loader": "8.0.2",
+ "script-ext-html-webpack-plugin": "2.1.3",
+ "serve-static": "1.13.2",
+ "svg-sprite-loader": "4.1.3",
+ "svgo": "1.2.0",
+ "vue-highlight.js": "^3.1.0",
+ "vue-json-editor": "^1.4.3",
+ "vue-json-views": "^1.3.0",
+ "vue-template-compiler": "2.6.10"
+ },
+ "browserslist": [
+ "> 1%",
+ "last 2 versions"
+ ],
+ "bugs": {
+ "url": "https://github.com/JaguarJack/catch-admin-vue/issues"
+ },
+ "engines": {
+ "node": ">=8.9",
+ "npm": ">= 3.0.0"
+ },
+ "keywords": [
+ "vue",
+ "admin",
+ "dashboard",
+ "element-ui",
+ "boilerplate",
+ "admin-template",
+ "management-system"
+ ],
+ "license": "MIT",
+ "lint-staged": {
+ "src/**/*.{js,vue}": [
+ "eslint --fix",
+ "git add"
+ ]
+ },
+ "husky": {
+ "hooks": {}
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/JaguarJack/catch-admin-vue"
+ }
+}
diff --git a/catch/apimanager/catch-admin-vue/src/api/userenv.js b/catch/apimanager/catch-admin-vue/src/api/userenv.js
new file mode 100644
index 0000000..0679ef0
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/src/api/userenv.js
@@ -0,0 +1,7 @@
+import request from "@/utils/request";
+export function userenvList() {
+ return request({
+ url: "/apiTesterUserenv",
+ method: "get"
+ });
+}
diff --git a/catch/apimanager/catch-admin-vue/src/main.js b/catch/apimanager/catch-admin-vue/src/main.js
new file mode 100644
index 0000000..30784ad
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/src/main.js
@@ -0,0 +1,48 @@
+import Vue from 'vue'
+
+import 'normalize.css/normalize.css' // a modern alternative to CSS resets
+
+import Element from 'element-ui'
+import Avue from '@smallwei/avue'
+import 'element-ui/lib/theme-chalk/index.css'
+import './styles/element-variables.scss'
+
+// import enLang from 'element-ui/lib/locale/lang/en'// 如果使用中文语言包请默认支持,无需额外引入,请删除该依赖
+
+import '@/styles/index.scss' // global css
+
+import App from './App'
+import store from './store'
+import router from './router'
+
+import './icons' // icon
+import './permission' // permission control
+import './utils/error-log' // error log
+import request from '@/utils/request'
+import * as filters from './filters' // global filters
+import catchAdmin from '@/components/Catch'
+
+Vue.use(Element, {
+ size: 'small'// set element-ui default size
+ // locale: enLang // 如果使用中文,无需设置,请删除
+})
+window.axios = request;
+Vue.use(Avue, { request });
+// register global utility filters
+Object.keys(filters).forEach(key => {
+ Vue.filter(key, filters[key])
+})
+
+// 后台启动
+catchAdmin.boot()
+
+Vue.config.productionTip = false
+Vue.prototype.$http = request
+Vue.prototype.admin = catchAdmin
+
+new Vue({
+ el: '#app',
+ router,
+ store,
+ render: h => h(App)
+})
diff --git a/catch/apimanager/catch-admin-vue/src/views/apimanager/apicategory/index.vue b/catch/apimanager/catch-admin-vue/src/views/apimanager/apicategory/index.vue
new file mode 100644
index 0000000..54ce67f
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/src/views/apimanager/apicategory/index.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
diff --git a/catch/apimanager/catch-admin-vue/src/views/apimanager/apienv/index.vue b/catch/apimanager/catch-admin-vue/src/views/apimanager/apienv/index.vue
new file mode 100644
index 0000000..f80a3d0
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/src/views/apimanager/apienv/index.vue
@@ -0,0 +1,270 @@
+
+
+
+
+
+ 搜索
+
+
+ 重置
+
+
+ 新增
+
+
+
+
+
+
+
+
+
+
+
+ 切换
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.$cellEdit ? "自定义保存" : "自定义修改" }}
+
+
+
+
+
+
+
+
+
diff --git a/catch/apimanager/catch-admin-vue/src/views/apimanager/apirun/index.vue b/catch/apimanager/catch-admin-vue/src/views/apimanager/apirun/index.vue
new file mode 100644
index 0000000..addbf8a
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/src/views/apimanager/apirun/index.vue
@@ -0,0 +1,659 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 发送
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ none
+ form-data
+ x-www-form-urlencoded
+ json
+ raw(json)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/catch/apimanager/catch-admin-vue/src/views/apimanager/apirun/itemBtn.vue b/catch/apimanager/catch-admin-vue/src/views/apimanager/apirun/itemBtn.vue
new file mode 100644
index 0000000..29f45d1
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/src/views/apimanager/apirun/itemBtn.vue
@@ -0,0 +1,114 @@
+
+
+
+
+ {{ value }}
+ this.$emit('input', value)"
+ >
+
+
+ {{
+ filename
+ }}
+
+ 点击上传
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/catch/apimanager/catch-admin-vue/src/views/apimanager/apitester/index.vue b/catch/apimanager/catch-admin-vue/src/views/apimanager/apitester/index.vue
new file mode 100644
index 0000000..e1a8153
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/src/views/apimanager/apitester/index.vue
@@ -0,0 +1,816 @@
+
+
+
+
+
+
+ 分类
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 重置
+
+
+ 搜索
+
+
+
+
+
+
+
+ 新增
+
+
+
+
+ 批量删除
+
+
+
+
+ {{ api.row.api_title }}
+
+
+
+
+
+
+ remote
+ local
+
+
+
+
+
+ 测试
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.$cellEdit ? "自定义保存" : "自定义修改" }}
+
+
+
+
+
+
+ {{ row.$cellEdit ? "自定义保存" : "自定义修改" }}
+
+
+
+
+
+
+ {{ row.$cellEdit ? "自定义保存" : "自定义修改" }}
+
+
+
+
+
+
+ {{ row.$cellEdit ? "自定义保存" : "自定义修改" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已完成
+ 待开发
+ 开发中
+ 已废弃
+
+
+
+
+
+
+
+
+
diff --git a/catch/apimanager/catch-admin-vue/src/views/apimanager/router.js b/catch/apimanager/catch-admin-vue/src/views/apimanager/router.js
new file mode 100644
index 0000000..554a808
--- /dev/null
+++ b/catch/apimanager/catch-admin-vue/src/views/apimanager/router.js
@@ -0,0 +1,8 @@
+export default {
+ // api分类
+ apicategory: () => import('@/views/apimanager/apicategory'),
+ // api测试
+ apitester: () => import('@/views/apimanager/apitester'),
+ apirun: () => import('@/views/apimanager/apirun'),
+ apienv: () => import('@/views/apimanager/apienv')
+}
diff --git a/catch/apimanager/controller/ApiCategory.php b/catch/apimanager/controller/ApiCategory.php
new file mode 100644
index 0000000..46ff8eb
--- /dev/null
+++ b/catch/apimanager/controller/ApiCategory.php
@@ -0,0 +1,83 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\controller;
+
+
+use catcher\base\CatchController;
+use catchAdmin\apimanager\model\ApiCategory as ApiCategoryModel;
+use catcher\base\CatchRequest as Request;
+use catcher\CatchResponse;
+use catcher\exceptions\FailedException;
+
+class ApiCategory extends CatchController
+{
+ protected $ApiCategoryModel;
+
+ public function __construct(ApiCategoryModel $ApiCategoryModel)
+ {
+ $this->ApiCategoryModel = $ApiCategoryModel;
+ }
+
+ /**
+ * 列表
+ * @time 2021年05月19日 15:21
+ * @param Request $request
+ */
+ public function index(): \think\response\Json
+ {
+ return CatchResponse::success($this->ApiCategoryModel->getList());
+ }
+
+ /**
+ * 保存信息
+ * @time 2021年05月19日 15:21
+ * @param Request $request
+ */
+ public function save(Request $request) : \think\response\Json
+ {
+ return CatchResponse::success($this->ApiCategoryModel->storeBy($request->post()));
+ }
+
+ /**
+ * 读取
+ * @time 2021年05月19日 15:21
+ * @param $id
+ */
+ public function read($id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiCategoryModel->findBy($id));
+ }
+
+ /**
+ * 更新
+ * @time 2021年05月19日 15:21
+ * @param Request $request
+ * @param $id
+ */
+ public function update(Request $request, $id) : \think\response\Json
+ {
+ return CatchResponse::success($this->ApiCategoryModel->updateBy($id, $request->post()));
+ }
+
+ /**
+ * 删除
+ * @time 2021年05月19日 15:21
+ * @param $id
+ */
+ public function delete($id) : \think\Response
+ {
+ if ($this->ApiCategoryModel->where('parent_id', $id)->find()) {
+ throw new FailedException('存在子分类,无法删除');
+ }
+ return CatchResponse::success($this->ApiCategoryModel->deleteBy($id));
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/controller/ApiTester.php b/catch/apimanager/controller/ApiTester.php
new file mode 100644
index 0000000..8fc72b3
--- /dev/null
+++ b/catch/apimanager/controller/ApiTester.php
@@ -0,0 +1,79 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\controller;
+
+use catcher\base\CatchRequest as Request;
+use catcher\CatchResponse;
+use catcher\base\CatchController;
+use catchAdmin\apimanager\model\ApiTester as ApiTesterModel;
+use catchAdmin\apimanager\model\ApiCategory;
+
+class ApiTester extends CatchController
+{
+ protected $ApiTesterModel;
+
+ public function __construct(ApiTesterModel $ApiTesterModel)
+ {
+ $this->ApiTesterModel = $ApiTesterModel;
+ }
+
+ /**
+ * 列表
+ * @time 2021年05月20日 11:41
+ * @param Request $request
+ */
+ public function index(Request $request) : \think\Response
+ {
+ return CatchResponse::paginate($this->ApiTesterModel->getList());
+ }
+
+ /**
+ * 保存信息
+ * @time 2021年05月20日 11:41
+ * @param Request $request
+ */
+ public function save(Request $request) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterModel->storeBy($request->post()));
+ }
+
+ /**
+ * 读取
+ * @time 2021年05月20日 11:41
+ * @param $id
+ */
+ public function read($id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterModel->findBy($id));
+ }
+
+ /**
+ * 更新
+ * @time 2021年05月20日 11:41
+ * @param Request $request
+ * @param $id
+ */
+ public function update(Request $request, $id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterModel->updateBy($id, $request->post()));
+ }
+
+ /**
+ * 删除
+ * @time 2021年05月20日 11:41
+ * @param $id
+ */
+ public function delete($id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterModel->deleteBy($id));
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/controller/ApiTesterLog.php b/catch/apimanager/controller/ApiTesterLog.php
new file mode 100644
index 0000000..40499bf
--- /dev/null
+++ b/catch/apimanager/controller/ApiTesterLog.php
@@ -0,0 +1,78 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\controller;
+
+use catcher\base\CatchRequest as Request;
+use catcher\CatchResponse;
+use catcher\base\CatchController;
+use catchAdmin\apimanager\model\ApiTesterLog as ApiTesterLogModel;
+
+class ApiTesterLog extends CatchController
+{
+ protected $ApiTesterLogModel;
+
+ public function __construct(ApiTesterLogModel $ApiTesterLogModel)
+ {
+ $this->ApiTesterLogModel = $ApiTesterLogModel;
+ }
+
+ /**
+ * 列表
+ * @time 2021年06月10日 19:20
+ * @param Request $request
+ */
+ public function index(Request $request) : \think\Response
+ {
+ return CatchResponse::paginate($this->ApiTesterLogModel->getList());
+ }
+
+ /**
+ * 保存信息
+ * @time 2021年06月10日 19:20
+ * @param Request $request
+ */
+ public function save(Request $request) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterLogModel->storeBy($request->post()));
+ }
+
+ /**
+ * 读取
+ * @time 2021年06月10日 19:20
+ * @param $id
+ */
+ public function read($id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterLogModel->findBy($id));
+ }
+
+ /**
+ * 更新
+ * @time 2021年06月10日 19:20
+ * @param Request $request
+ * @param $id
+ */
+ public function update(Request $request, $id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterLogModel->updateBy($id, $request->post()));
+ }
+
+ /**
+ * 删除
+ * @time 2021年06月10日 19:20
+ * @param $id
+ */
+ public function delete($id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterLogModel->deleteBy($id));
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/controller/ApiTesterUserenv.php b/catch/apimanager/controller/ApiTesterUserenv.php
new file mode 100644
index 0000000..d88e9f4
--- /dev/null
+++ b/catch/apimanager/controller/ApiTesterUserenv.php
@@ -0,0 +1,99 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\controller;
+
+use catcher\base\CatchRequest as Request;
+use catcher\CatchResponse;
+use catcher\base\CatchController;
+use catchAdmin\apimanager\model\ApiTesterUserenv as ApiTesterUserenvModel;
+use think\facade\Log;
+
+class ApiTesterUserenv extends CatchController
+{
+ protected $ApiTesterUserenvModel;
+
+ public function __construct(ApiTesterUserenvModel $ApiTesterUserenvModel)
+ {
+ $this->ApiTesterUserenvModel = $ApiTesterUserenvModel;
+ }
+
+ /**
+ * 列表
+ * @time 2021年05月26日 18:28
+ * @param Request $request
+ */
+ public function index(Request $request) : \think\Response
+ {
+ return CatchResponse::paginate($this->ApiTesterUserenvModel->getList());
+ }
+
+ /**
+ * 保存信息
+ * @time 2021年05月26日 18:28
+ * @param Request $request
+ */
+ public function save(Request $request) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterUserenvModel->storeBy($request->post()));
+ }
+
+ /**
+ * 读取
+ * @time 2021年05月26日 18:28
+ * @param $id
+ */
+ public function read($id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterUserenvModel->findBy($id));
+ }
+
+ /**
+ * 更新
+ * @time 2021年05月26日 18:28
+ * @param Request $request
+ * @param $id
+ */
+ public function update(Request $request, $id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterUserenvModel->updateBy($id, $request->post()));
+ }
+
+ /**
+ * 删除
+ * @time 2021年05月26日 18:28
+ * @param $id
+ */
+ public function delete($id) : \think\Response
+ {
+ return CatchResponse::success($this->ApiTesterUserenvModel->deleteBy($id));
+ }
+
+ /**
+ * 切换API环境
+ * @param Request $request
+ * @param $id
+ */
+ public function selectAPIenv(Request $request,$id = "") : \think\Response
+ {
+ if ($id)
+ {
+ $creator_id = $request->user()->id;
+ $this->ApiTesterUserenvModel->update(['selected' => 0], ['creator_id' => $creator_id]); //全不选
+ $res = $this->ApiTesterUserenvModel->update(['selected' => 1], ['id' => $id]); //选中当前
+ //设置为管理员当前选中的applet
+ if($res){
+ return CatchResponse::success($res,'切换API环境成功');
+ }
+ }
+ return CatchResponse::fail('切换API环境错误');
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/database/migrations/20210519152117_api_category.php b/catch/apimanager/database/migrations/20210519152117_api_category.php
new file mode 100644
index 0000000..6077226
--- /dev/null
+++ b/catch/apimanager/database/migrations/20210519152117_api_category.php
@@ -0,0 +1,45 @@
+table('api_category', ['engine' => 'InnoDB', 'collation' => 'utf8mb4_general_ci', 'comment' => 'API分类' ,'id' => 'id' ,'primary_key' => ['id']]);
+ $table->addColumn('category_title', 'string', ['limit' => 64,'null' => false,'default' => '','signed' => true,'comment' => '分类标题',])
+ ->addColumn('parent_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '父级ID',])
+ ->addColumn('category_name', 'string', ['limit' => 128,'null' => false,'default' => '','signed' => true,'comment' => '分类唯一标识',])
+ ->addColumn('status', 'boolean', ['null' => false,'default' => 1,'signed' => true,'comment' => '状态:1=正常;2=停用',])
+ ->addColumn('sort', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '排序字段',])
+ ->addColumn('created_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '创建时间',])
+ ->addColumn('updated_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '更新时间',])
+ ->addColumn('deleted_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '软删除字段',])
+ ->addColumn('creator_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '创建人ID',])
+ ->addIndex(['category_name'], ['unique' => true,'name' => 'api_category_category_name'])
+ ->create();
+ }
+}
diff --git a/catch/apimanager/database/migrations/20210520114151_api_tester.php b/catch/apimanager/database/migrations/20210520114151_api_tester.php
new file mode 100644
index 0000000..1bb7504
--- /dev/null
+++ b/catch/apimanager/database/migrations/20210520114151_api_tester.php
@@ -0,0 +1,60 @@
+table('api_tester', ['engine' => 'InnoDB', 'collation' => 'utf8mb4_general_ci', 'comment' => 'api测试表' ,'id' => 'id' ,'primary_key' => ['id']]);
+ $table->addColumn('api_title', 'string', ['limit' => 128,'null' => false,'default' => '新建接口','signed' => true,'comment' => '标题',])
+ ->addColumn('api_name', 'string', ['limit' => 128,'null' => false,'default' => '','signed' => true,'comment' => '英文唯一标识',])
+ ->addColumn('category_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '分类',])
+ ->addColumn('type', 'boolean', ['null' => false,'default' => 1,'signed' => true,'comment' => '数据源类型:1=remote,2=local',])
+ ->addColumn('appid', 'string', ['limit' => 64,'null' => true,'signed' => true,'comment' => 'appid',])
+ ->addColumn('project_id', 'string', ['limit' => 64,'null' => true,'signed' => true,'comment' => '项目ID',])
+ ->addColumn('api_url', 'string', ['limit' => 512,'null' => false,'default' => 'https://127.0.0.1','signed' => true,'comment' => 'API URL',])
+ ->addColumn('methods', 'string', ['limit' => 128,'null' => false,'default' => 'POST','signed' => true,'comment' => '方法:POST,GET,PUT,PATCH,DELETE,COPY,HEAD,OPTIONS',])
+ ->addColumn('auth', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => '鉴权',])
+ ->addColumn('header', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => 'header',])
+ ->addColumn('query', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => 'query',])
+ ->addColumn('body', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => 'body',])
+ ->addColumn('doc_url', 'string', ['limit' => 512,'null' => true,'signed' => true,'comment' => '文档URL',])
+ ->addColumn('document', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => '文档',])
+ ->addColumn('sample_data', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => '示例数据',])
+ ->addColumn('sample_result', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => '示例返回数据',])
+ ->addColumn('sort', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => true,'signed' => true,'comment' => '排序',])
+ ->addColumn('status', 'boolean', ['null' => false,'default' => 1,'signed' => true,'comment' => '状态:1=已完成,2=待开发,3=开发中,4=已废弃',])
+ ->addColumn('content_type', 'string', ['limit' => 128,'null' => false,'default' => 'application/x-www-form-urlencoded','signed' => true,'comment' => 'content-type:application/x-www-form-urlencoded,multipart/form-data,raw',])
+ ->addColumn('env_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => true,'signed' => true,'comment' => '环境ID',])
+ ->addColumn('memo', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => '备注',])
+ ->addColumn('created_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '创建时间',])
+ ->addColumn('updated_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '更新时间',])
+ ->addColumn('deleted_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '软删除字段',])
+ ->addColumn('creator_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '创建人ID',])
+ ->create();
+ }
+}
diff --git a/catch/apimanager/database/migrations/20210526182843_api_tester_userenv.php b/catch/apimanager/database/migrations/20210526182843_api_tester_userenv.php
new file mode 100644
index 0000000..53524e9
--- /dev/null
+++ b/catch/apimanager/database/migrations/20210526182843_api_tester_userenv.php
@@ -0,0 +1,44 @@
+table('api_tester_userenv', ['engine' => 'InnoDB', 'collation' => 'utf8mb4_general_ci', 'comment' => 'API测试用户环境' ,'id' => 'id' ,'primary_key' => ['id']]);
+ $table->addColumn('env_name', 'string', ['limit' => 128,'null' => false,'default' => '','signed' => true,'comment' => '环境名称',])
+ ->addColumn('appid', 'string', ['limit' => 64,'null' => false,'default' => '','signed' => true,'comment' => 'appid',])
+ ->addColumn('project_id', 'string', ['limit' => 64,'null' => false,'default' => '','signed' => true,'comment' => '项目ID',])
+ ->addColumn('env_json', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => false,'signed' => true,'comment' => '环境变量json',])
+ ->addColumn('selected', 'boolean', ['null' => false,'default' => 0,'signed' => true,'comment' => '是否当前选中:0=否,1=是',])
+ ->addColumn('created_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '创建时间',])
+ ->addColumn('updated_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '更新时间',])
+ ->addColumn('deleted_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '软删除字段',])
+ ->addColumn('creator_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '创建人ID',])
+ ->create();
+ }
+}
diff --git a/catch/apimanager/database/migrations/20210610192033_api_tester_log.php b/catch/apimanager/database/migrations/20210610192033_api_tester_log.php
new file mode 100644
index 0000000..cb09bb1
--- /dev/null
+++ b/catch/apimanager/database/migrations/20210610192033_api_tester_log.php
@@ -0,0 +1,46 @@
+table('api_tester_log', ['engine' => 'InnoDB', 'collation' => 'utf8mb4_general_ci', 'comment' => 'API测试记录' ,'id' => 'id' ,'primary_key' => ['id']]);
+ $table->addColumn('appid', 'string', ['limit' => 50,'null' => true,'signed' => true,'comment' => 'appid',])
+ ->addColumn('user_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => true,'signed' => true,'comment' => 'users表id',])
+ ->addColumn('api_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => true,'signed' => true,'comment' => 'api_tester表id',])
+ ->addColumn('params', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => 'api参数',])
+ ->addColumn('result', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => '返回值',])
+ ->addColumn('request_data', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => '请求数据',])
+ ->addColumn('response_data', 'text', ['limit' => MysqlAdapter::TEXT_REGULAR,'null' => true,'signed' => true,'comment' => '响应数据',])
+ ->addColumn('created_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '创建时间',])
+ ->addColumn('updated_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '更新时间',])
+ ->addColumn('deleted_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '软删除字段',])
+ ->addColumn('creator_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => false,'comment' => '创建人ID',])
+ ->create();
+ }
+}
diff --git a/catch/apimanager/database/seeds/ApiCategorySeed.php b/catch/apimanager/database/seeds/ApiCategorySeed.php
new file mode 100644
index 0000000..fef8d01
--- /dev/null
+++ b/catch/apimanager/database/seeds/ApiCategorySeed.php
@@ -0,0 +1,98 @@
+
+// +----------------------------------------------------------------------
+
+use think\migration\Seeder;
+
+class ApiCategorySeed extends Seeder
+{
+ /**
+ * Run Method.
+ *
+ * Write your database seeder using this method.
+ *
+ * More information on writing seeders is available here:
+ * http://docs.phinx.org/en/latest/seeding.html
+ */
+ public function run()
+ {
+ $data = array (
+ 0 =>
+ array (
+ 'id' => 1,
+ 'category_title' => '微信第三方平台',
+ 'parent_id' => 0,
+ 'category_name' => 'wechatopen',
+ 'status' => 1,
+ 'sort' => 1,
+ 'created_at' => 1621414770,
+ 'updated_at' => 1621414770,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 1 =>
+ array (
+ 'id' => 2,
+ 'category_title' => '微信交易组件标准版',
+ 'parent_id' => 1,
+ 'category_name' => 'MiniShop_Base',
+ 'status' => 1,
+ 'sort' => 1,
+ 'created_at' => 1621415897,
+ 'updated_at' => 1621415897,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 2 =>
+ array (
+ 'id' => 3,
+ 'category_title' => '腾讯AI开放平台',
+ 'parent_id' => 0,
+ 'category_name' => 'tencentAI',
+ 'status' => 1,
+ 'sort' => 1,
+ 'created_at' => 1621493345,
+ 'updated_at' => 1621493345,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 3 =>
+ array (
+ 'id' => 4,
+ 'category_title' => '批量代云开发',
+ 'parent_id' => 1,
+ 'category_name' => 'componenttcb',
+ 'status' => 1,
+ 'sort' => 1,
+ 'created_at' => 1621494287,
+ 'updated_at' => 1621494287,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 4 =>
+ array (
+ 'id' => 5,
+ 'category_title' => '本地接口',
+ 'parent_id' => 0,
+ 'category_name' => 'local',
+ 'status' => 1,
+ 'sort' => 2,
+ 'created_at' => 1621494287,
+ 'updated_at' => 1621494287,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+);
+
+ foreach ($data as $item) {
+ \catchAdmin\apimanager\model\ApiCategory::create($item);
+ }
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/database/seeds/ApiTesterSeed.php b/catch/apimanager/database/seeds/ApiTesterSeed.php
new file mode 100644
index 0000000..f00bc82
--- /dev/null
+++ b/catch/apimanager/database/seeds/ApiTesterSeed.php
@@ -0,0 +1,785 @@
+
+// +----------------------------------------------------------------------
+
+use think\migration\Seeder;
+
+class ApiTesterSeed extends Seeder
+{
+ /**
+ * Run Method.
+ *
+ * Write your database seeder using this method.
+ *
+ * More information on writing seeders is available here:
+ * http://docs.phinx.org/en/latest/seeding.html
+ */
+ public function run()
+ {
+ $data = array (
+ 0 =>
+ array (
+ 'id' => 1,
+ 'api_title' => '获取类目详情',
+ 'api_name' => 'product/category/get',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/category/get',
+ 'methods' => 'POST',
+ 'auth' => NULL,
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/cat/get_cat_list.html',
+ 'document' => '参考文档url',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 2,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => NULL,
+ 'created_at' => 1621484754,
+ 'updated_at' => 1622461634,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 1 =>
+ array (
+ 'id' => 2,
+ 'api_title' => '获取品牌列表',
+ 'api_name' => 'product/brand/get',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/brand/get',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/cat/get_brand.html',
+ 'document' => '详见文档url地址',
+ 'sample_data' => '无',
+ 'sample_result' => '返回',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => NULL,
+ 'created_at' => 1621485017,
+ 'updated_at' => 1622378856,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 2 =>
+ array (
+ 'id' => 3,
+ 'api_title' => '登录日志',
+ 'api_name' => '/log/login',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/log/login',
+ 'methods' => 'GET',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '',
+ 'body' => '',
+ 'doc_url' => 'http://apidoc.catchadmin.com/web/#/5?page_id=23',
+ 'document' => '无',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1621598744,
+ 'updated_at' => 1622965477,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 3 =>
+ array (
+ 'id' => 4,
+ 'api_title' => '操作日志',
+ 'api_name' => 'log/operate',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/log/operate',
+ 'methods' => 'GET',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '',
+ 'body' => '',
+ 'doc_url' => 'http://apidoc.catchadmin.com/web/#/5?page_id=53',
+ 'document' => '无',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1621598935,
+ 'updated_at' => 1622965460,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 4 =>
+ array (
+ 'id' => 5,
+ 'api_title' => '获取运费模板',
+ 'api_name' => 'product/delivery/get_freight_template',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/delivery/get_freight_template',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '',
+ 'doc_url' => 'https://developers.weixin.qq.com/doc/ministore/minishopopencomponent/API/cat/get_freight_template.html',
+ 'document' => '详见文档URL',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1621599469,
+ 'updated_at' => 1622378826,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 5 =>
+ array (
+ 'id' => 6,
+ 'api_title' => '获取店铺的商品分类',
+ 'api_name' => 'product/store/get_shopcat',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/store/get_shopcat',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/store/get_shopcat.html',
+ 'document' => '参考文档url',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1621762669,
+ 'updated_at' => 1622378816,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 6 =>
+ array (
+ 'id' => 7,
+ 'api_title' => '添加商品',
+ 'api_name' => 'product/spu/add',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/spu/add',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '{
+ "out_product_id": "1234566",
+ "title": "任天堂 Nintendo Switch 国行续航增强版 NS家用体感游戏机掌机 便携掌上游戏机 红蓝主机",
+ "sub_title": "JD自营更放心】【国行Switch,更安心的保修服务,更快的国行服务器】一台主机三种模式,游戏掌机,随时随地,一起趣玩。",
+ "head_img":
+ [
+ "http://img10.360buyimg.com/n1/s450x450_jfs/t1/85865/39/13611/488083/5e590a40E4bdf69c0/55c9bf645ea2b727.jpg"
+ ],
+ "desc_info":
+ {
+ "imgs":
+ [
+ "http://img10.360buyimg.com/n1/s450x450_jfs/t1/85865/39/13611/488083/5e590a40E4bdf69c0/55c9bf645ea2b727.jpg"
+ ]
+ },
+ "brand_id": 2100000000,
+ "cats":
+ [
+ {
+ "cat_id": 6033,
+ "level": 1
+ },
+ {
+ "cat_id": 6057,
+ "level": 2
+ },
+ {
+ "cat_id": 6091,
+ "level": 3
+ }
+ ],
+ "attrs":
+ [
+ {
+ "attr_key": "商品毛重",
+ "attr_value": "380g"
+ },
+ {
+ "attr_key": "商品产地",
+ "attr_value": "中国大陆"
+ }
+ ],
+ "model": "国行续航增强版",
+ "express_info":
+ {
+ "template_id": 5189
+ },
+ "skus":
+ [
+ {
+ "out_product_id": "1234566",
+ "out_sku_id": "1024",
+ "thumb_img": "http://img10.360buyimg.com/n1/s450x450_jfs/t1/100778/17/13648/424215/5e590a40E2d68e774/e171d222a0c9b763.jpg",
+ "sale_price": 1300,
+ "market_price": 1500,
+ "stock_num": 100,
+ "sku_code": "A24525252",
+ "barcode": "13251454",
+ "sku_attrs":
+ [
+ {
+ "attr_key": "选择颜色",
+ "attr_value": "红蓝主机"
+ },
+ {
+ "attr_key": "选择套装",
+ "attr_value": "主机+保护套"
+ }
+ ]
+ }
+ ]
+}',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/spu/add_spu.html',
+ 'document' => '参考文档url',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1621764682,
+ 'updated_at' => 1622378805,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 7 =>
+ array (
+ 'id' => 8,
+ 'api_title' => '获取商品',
+ 'api_name' => 'product/spu/get',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/spu/get',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '{\'product_id\':\'31334398\'}',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/spu/get_spu.html',
+ 'document' => '参考文档URL',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1621774347,
+ 'updated_at' => 1622378781,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 8 =>
+ array (
+ 'id' => 9,
+ 'api_title' => '获取商品列表',
+ 'api_name' => 'product/spu/get_list',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/spu/get_list',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '{"status":5}',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/spu/get_spu_list.html',
+ 'document' => '参考文档URL',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1621777668,
+ 'updated_at' => 1622378754,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 9 =>
+ array (
+ 'id' => 10,
+ 'api_title' => '搜索商品',
+ 'api_name' => 'product/spu/search',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/spu/search',
+ 'methods' => 'POST',
+ 'auth' => NULL,
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '{\'status\':5,\'keyword\':\'UI\',\'page\':1}',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/spu/search_spu.html',
+ 'document' => '参考文档url',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 1,
+ 'memo' => NULL,
+ 'created_at' => 1622000389,
+ 'updated_at' => 1622378719,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 10 =>
+ array (
+ 'id' => 11,
+ 'api_title' => '上架商品',
+ 'api_name' => 'product/spu/listing',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/spu/listing',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '{\'product_id\':\'33541981\'}',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/spu/up_spu_listing.html',
+ 'document' => '参考文档URL',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622019456,
+ 'updated_at' => 1622378710,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 11 =>
+ array (
+ 'id' => 12,
+ 'api_title' => '下架商品',
+ 'api_name' => 'product/spu/delisting',
+ 'category_id' => 2,
+ 'type' => 1,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/api/wechatopen/product/spu/delisting',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{"appid":"{{appid}}"}',
+ 'body' => '{\'product_id\':33541981}',
+ 'doc_url' => 'https://developers.weixin.qq.com/miniprogram/dev/framework/ministore/minishopopencomponent/API/spu/up_spu_delisting.html',
+ 'document' => '参考文档URL',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622019791,
+ 'updated_at' => 1622378701,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 12 =>
+ array (
+ 'id' => 13,
+ 'api_title' => 'API测试用户环境新增',
+ 'api_name' => 'ApiTesterUserenv/save',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/apiTesterUserenv',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '',
+ 'body' => '{\'env_name\':\'api.server.local\',\'appid\':\'wx407e\',\'project_id\':1,\'selected\':0}',
+ 'doc_url' => '无',
+ 'document' => '新增一条API测试用户环境数据',
+ 'sample_data' => '{\'env_name\':\'appapi.uctoo.local\',\'appid\':\'wx407e\',\'project_id\':1,\'env_json\':\'{"{{host}}":"api.server.local","{{appid}}":"wx407e","{{authorization}}":"BearereyJ0eXA"}\',\'selected\':0}',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 4,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 1,
+ 'memo' => '',
+ 'created_at' => 1622030621,
+ 'updated_at' => 1622965370,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 13 =>
+ array (
+ 'id' => 14,
+ 'api_title' => 'API测试用户环境列表',
+ 'api_name' => 'apiTesterUserenv/index',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/apiTesterUserenv',
+ 'methods' => 'GET',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{\'creator\':\'admin\'}',
+ 'body' => '',
+ 'doc_url' => '无',
+ 'document' => 'API测试用户环境列表。可以按用户名检索环境列表,在query部分增加creator筛选字段。',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622031131,
+ 'updated_at' => 1622965325,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 14 =>
+ array (
+ 'id' => 15,
+ 'api_title' => 'API测试用户环境更新',
+ 'api_name' => 'apiTesterUserenv/update',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/apiTesterUserenv/3',
+ 'methods' => 'PUT',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '',
+ 'body' => '{\'selected\':1}',
+ 'doc_url' => '无',
+ 'document' => 'API地址:http://127.0.0.1/apiTesterUserenv/{id}
+id为数据主键。body部分为要更新的字段。',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622033581,
+ 'updated_at' => 1622965309,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 15 =>
+ array (
+ 'id' => 16,
+ 'api_title' => '微应用列表',
+ 'api_name' => 'applet/index',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/applet',
+ 'methods' => 'GET',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '{\'creator\':\'demo\'}',
+ 'body' => '',
+ 'doc_url' => '无',
+ 'document' => '可在query字段用creator用户名、name应用名称、appid字段进行筛选。',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622083381,
+ 'updated_at' => 1622965295,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 16 =>
+ array (
+ 'id' => 17,
+ 'api_title' => '设置选中微应用',
+ 'api_name' => 'applet/setapplet/',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/applet/setapplet/1',
+ 'methods' => 'GET',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '',
+ 'body' => '',
+ 'doc_url' => '无',
+ 'document' => '参数为数据主键',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622085296,
+ 'updated_at' => 1622965277,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 17 =>
+ array (
+ 'id' => 18,
+ 'api_title' => '获取当前选中应用',
+ 'api_name' => 'admin/applet/',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/admin/applet/1',
+ 'methods' => 'GET',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '',
+ 'body' => '',
+ 'doc_url' => '无',
+ 'document' => '参数是后台用户主键ID',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622097323,
+ 'updated_at' => 1622965263,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 18 =>
+ array (
+ 'id' => 19,
+ 'api_title' => '切换API环境',
+ 'api_name' => 'apiTesterUserenv/selectAPIenv/',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/apiTesterUserenv/selectAPIenv/1',
+ 'methods' => 'GET',
+ 'auth' => '',
+ 'header' => '{"authorization":"{{authorization}}"}',
+ 'query' => '',
+ 'body' => '',
+ 'doc_url' => '无',
+ 'document' => '为API环境数据主键',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622176574,
+ 'updated_at' => 1622965231,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 19 =>
+ array (
+ 'id' => 20,
+ 'api_title' => '帐号登录',
+ 'api_name' => 'login',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/login',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '',
+ 'query' => '',
+ 'body' => '{"email":"catch@admin.com","password":"catchadmin"}',
+ 'doc_url' => 'http://apidoc.catchadmin.com/web/#/5?page_id=24',
+ 'document' => '无',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/json; charset=utf-8',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622429937,
+ 'updated_at' => 1622460840,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 20 =>
+ array (
+ 'id' => 21,
+ 'api_title' => '微信扫码登录后获取后台帐号',
+ 'api_name' => 'wechatlogin/wechatoauth',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/wechatlogin/wechatoauth',
+ 'methods' => 'GET',
+ 'auth' => '',
+ 'header' => '',
+ 'query' => '{"code":"0712VE1"}',
+ 'body' => '',
+ 'doc_url' => 'https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html',
+ 'document' => '微信扫码登录后,在跳转到的页面需要先调用此接口获取微信用户关联的后台管理员帐号列表。根据此接口返回的帐号列表信息,展示帐号名,用户可以点选登录对应帐号。如此接口返回空值,则展示用户注册后台帐号页面。
+Query参数:
+必填参数
+code:微信扫码登录后,微信服务器通知跳转到redirect_url时添加的code参数,用于获取微信用户access_token
+非必填参数
+state:扫码登录时添加的随机验证字符串。前端自定义。前端自验证。
+
+返回值:accountList 包含扫码登录后获得的 openid,access_token以及关联的后台帐号列表
+',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/x-www-form-urlencoded',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622539671,
+ 'updated_at' => 1622709792,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 21 =>
+ array (
+ 'id' => 22,
+ 'api_title' => '扫码登录后注册用户帐号',
+ 'api_name' => 'wechatlogin/wechatregist',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/wechatlogin/wechatregist',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '',
+ 'query' => '',
+ 'body' => '{"username":"13688888888","password":"123456","email":"demo@uctoo.com","openid":"openid","access_token":"access_token"}',
+ 'doc_url' => '无',
+ 'document' => 'openid和access_token是微信扫码登录后获取到的值,用于调用帐号注册接口权限验证。
+username建议采用用户手机号码并进行短信验证。
+password建议校验密码复杂度。
+email建议进行邮箱验证。可作为密码找回方式之一。',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/json; charset=utf-8',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622710277,
+ 'updated_at' => 1622876680,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 22 =>
+ array (
+ 'id' => 23,
+ 'api_title' => '微信扫码登录后选择帐号登录',
+ 'api_name' => 'wechatlogin/wechatlogin',
+ 'category_id' => 5,
+ 'type' => 2,
+ 'appid' => '',
+ 'project_id' => '',
+ 'api_url' => '{{host}}/wechatlogin/wechatlogin',
+ 'methods' => 'POST',
+ 'auth' => '',
+ 'header' => '',
+ 'query' => '',
+ 'body' => '{"email":"demo@uctoo.com","openid":"openid","access_token":"access_token","password":"any"}',
+ 'doc_url' => '无',
+ 'document' => '微信扫码后,选择帐号登录。
+openid和access_token是在扫码授权后,获得。
+password参数必须传,可以是任意值,不做验证。',
+ 'sample_data' => '无',
+ 'sample_result' => '无',
+ 'sort' => 1,
+ 'status' => 1,
+ 'content_type' => 'application/json; charset=utf-8',
+ 'env_id' => 0,
+ 'memo' => '',
+ 'created_at' => 1622713987,
+ 'updated_at' => 1622876660,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+);
+
+ foreach ($data as $item) {
+ \catchAdmin\apimanager\model\ApiTester::create($item);
+ }
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/database/seeds/ApiTesterUserenvSeed.php b/catch/apimanager/database/seeds/ApiTesterUserenvSeed.php
new file mode 100644
index 0000000..234d14f
--- /dev/null
+++ b/catch/apimanager/database/seeds/ApiTesterUserenvSeed.php
@@ -0,0 +1,59 @@
+
+// +----------------------------------------------------------------------
+
+use think\migration\Seeder;
+
+class ApiTesterUserenvSeed extends Seeder
+{
+ /**
+ * Run Method.
+ *
+ * Write your database seeder using this method.
+ *
+ * More information on writing seeders is available here:
+ * http://docs.phinx.org/en/latest/seeding.html
+ */
+ public function run()
+ {
+ $data = array (
+ 0 =>
+ array (
+ 'id' => 1,
+ 'env_name' => 'localhost',
+ 'appid' => 'wx407e4',
+ 'project_id' => '1',
+ 'env_json' => '{"{{host}}":"http://127.0.0.1:8000","{{status}}":"5","{{appid}}":"wx407","{{authorization}}":"Bearer{{手动替换为login接口的token}}"}',
+ 'selected' => 1,
+ 'created_at' => 1622029539,
+ 'updated_at' => 1622386890,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+ 1 =>
+ array (
+ 'id' => 2,
+ 'env_name' => 'api.server.local',
+ 'appid' => 'wx407',
+ 'project_id' => '1',
+ 'env_json' => '{"{{host}}":"http://api.server.local"}',
+ 'selected' => 0,
+ 'created_at' => 1622030904,
+ 'updated_at' => 1622386890,
+ 'deleted_at' => 0,
+ 'creator_id' => 1,
+ ),
+);
+
+ foreach ($data as $item) {
+ \catchAdmin\apimanager\model\ApiTesterUserenv::create($item);
+ }
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/database/seeds/ApimanagerMenusSeed.php b/catch/apimanager/database/seeds/ApimanagerMenusSeed.php
new file mode 100644
index 0000000..79e06c2
--- /dev/null
+++ b/catch/apimanager/database/seeds/ApimanagerMenusSeed.php
@@ -0,0 +1,144 @@
+
+// +----------------------------------------------------------------------
+
+use think\facade\Log;
+use think\migration\Seeder;
+
+class ApimanagerMenusSeed extends Seeder
+{
+ /**
+ * Run Method.
+ *
+ * Write your database seeder using this method.
+ *
+ * More information on writing seeders is available here:
+ * http://docs.phinx.org/en/latest/seeding.html
+ */
+ public function run()
+ {
+ Log::write("ApimanagerMenusSeed",'debug');
+ \catcher\Utils::importTreeData($this->getPermissions(), 'permissions', 'parent_id');
+ }
+
+ protected function getPermissions()
+ {
+ return array (
+ 0 =>
+ array (
+ 'id' => 136,
+ 'permission_name' => 'API管理',
+ 'parent_id' => 0,
+ 'level' => '',
+ 'route' => '/apimanager',
+ 'icon' => 'el-icon-sort',
+ 'module' => 'apimanager',
+ 'creator_id' => 1,
+ 'permission_mark' => 'apimanager',
+ 'component' => 'layout',
+ 'redirect' => '',
+ 'keepalive' => 1,
+ 'type' => 1,
+ 'hidden' => 1,
+ 'sort' => 10,
+ 'created_at' => 1622926698,
+ 'updated_at' => 1622959419,
+ 'deleted_at' => 0,
+ 'children' =>
+ array (
+ 0 =>
+ array (
+ 'id' => 137,
+ 'permission_name' => 'API分类',
+ 'parent_id' => 136,
+ 'level' => '',
+ 'route' => '/apicategory',
+ 'icon' => 'el-icon-s-grid',
+ 'module' => 'apimanager',
+ 'creator_id' => 1,
+ 'permission_mark' => 'apicategory',
+ 'component' => 'apicategory',
+ 'redirect' => '',
+ 'keepalive' => 1,
+ 'type' => 1,
+ 'hidden' => 1,
+ 'sort' => 10,
+ 'created_at' => 1622928640,
+ 'updated_at' => 1622959419,
+ 'deleted_at' => 0,
+ ),
+ 1 =>
+ array (
+ 'id' => 138,
+ 'permission_name' => 'API环境变量',
+ 'parent_id' => 136,
+ 'level' => '',
+ 'route' => '/apienv',
+ 'icon' => 'el-icon-setting',
+ 'module' => 'apimanager',
+ 'creator_id' => 1,
+ 'permission_mark' => 'apienv',
+ 'component' => 'apienv',
+ 'redirect' => '',
+ 'keepalive' => 1,
+ 'type' => 1,
+ 'hidden' => 1,
+ 'sort' => 9,
+ 'created_at' => 1622930243,
+ 'updated_at' => 1622959419,
+ 'deleted_at' => 0,
+ ),
+ 2 =>
+ array (
+ 'id' => 140,
+ 'permission_name' => 'API测试列表',
+ 'parent_id' => 136,
+ 'level' => '',
+ 'route' => '/apitester',
+ 'icon' => 'el-icon-stopwatch',
+ 'module' => 'apimanager',
+ 'creator_id' => 1,
+ 'permission_mark' => 'apitester',
+ 'component' => 'apitester',
+ 'redirect' => '',
+ 'keepalive' => 1,
+ 'type' => 1,
+ 'hidden' => 1,
+ 'sort' => 8,
+ 'created_at' => 1622951640,
+ 'updated_at' => 1622959419,
+ 'deleted_at' => 0,
+ ),
+ 3 =>
+ array (
+ 'id' => 141,
+ 'permission_name' => 'API运行',
+ 'parent_id' => 136,
+ 'level' => '',
+ 'route' => '/apimanager/apirun',
+ 'icon' => 'el-icon-position',
+ 'module' => 'apimanager',
+ 'creator_id' => 1,
+ 'permission_mark' => 'apirun',
+ 'component' => 'apirun',
+ 'redirect' => '',
+ 'keepalive' => 1,
+ 'type' => 1,
+ 'hidden' => 2,
+ 'sort' => 1,
+ 'created_at' => 1622951894,
+ 'updated_at' => 1622959419,
+ 'deleted_at' => 0,
+ ),
+ ),
+ ),
+);
+ }
+}
diff --git a/catch/apimanager/model/ApiCategory.php b/catch/apimanager/model/ApiCategory.php
new file mode 100644
index 0000000..f780bbd
--- /dev/null
+++ b/catch/apimanager/model/ApiCategory.php
@@ -0,0 +1,92 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\model;
+
+use catchAdmin\apimanager\model\search\ApiCategorySearch;
+use catcher\base\CatchModel as Model;
+use think\db\exception\DbException;
+/**
+ *
+ * @property int $id
+ * @property string $category_title
+ * @property int $parent_id
+ * @property string $category_name
+ * @property int $status
+ * @property int $sort
+ * @property int $created_at
+ * @property int $updated_at
+ * @property int $deleted_at
+ * @property int $creator_id
+ */
+class ApiCategory extends Model
+{
+ use ApiCategorySearch;
+ // 表名
+ public $name = 'api_category';
+ // 数据库字段映射
+ public $field = array(
+ 'id',
+ // 分类标题
+ 'category_title',
+ // 父级ID
+ 'parent_id',
+ // 分类唯一标识
+ 'category_name',
+ // 状态:1=正常;2=停用
+ 'status',
+ // 排序字段
+ 'sort',
+ // 创建时间
+ 'created_at',
+ // 更新时间
+ 'updated_at',
+ // 软删除字段
+ 'deleted_at',
+ // 创建人ID
+ 'creator_id',
+ );
+
+ protected $updateChildrenFields = 'status';
+
+ /**
+ * 列表数据
+ *
+ * @time 2020年01月09日
+ * @return array
+ * @throws DbException
+ */
+ public function getList(): array
+ {
+ return $this->catchSearch()
+ ->catchOrder()
+ ->select()->toTree();
+ }
+
+ /**
+ * 获取子分类IDS
+ *
+ * @time 2020年11月04日
+ * @param $id
+ * @throws DbException
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @return mixed
+ */
+ public static function getChildrenCategoryIds($id)
+ {
+ $categoryIds = ApiCategory::field(['id', 'parent_id'])->select()->getAllChildrenIds([$id]);
+
+ $categoryIds[] = $id;
+
+ return $categoryIds;
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/model/ApiTester.php b/catch/apimanager/model/ApiTester.php
new file mode 100644
index 0000000..20d0618
--- /dev/null
+++ b/catch/apimanager/model/ApiTester.php
@@ -0,0 +1,104 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\model;
+
+use catcher\base\CatchModel as Model;
+use catchAdmin\apimanager\model\search\ApiTesterSearch;
+/**
+ *
+ * @property int $id
+ * @property string $api_title
+ * @property string $api_name
+ * @property int $category_id
+ * @property int $type
+ * @property string $appid
+ * @property string $project_id
+ * @property string $api_url
+ * @property string $methods
+ * @property string $auth
+ * @property string $header
+ * @property string $query
+ * @property string $body
+ * @property string $doc_url
+ * @property string $document
+ * @property string $sample_data
+ * @property string $sample_result
+ * @property int $sort
+ * @property int $status
+ * @property string $content_type
+ * @property int $env_id
+ * @property string $memo
+ * @property int $created_at
+ * @property int $updated_at
+ * @property int $deleted_at
+ * @property int $creator_id
+ */
+class ApiTester extends Model
+{
+ use ApiTesterSearch;
+ // 表名
+ public $name = 'api_tester';
+ // 数据库字段映射
+ public $field = array(
+ 'id',
+ // 标题
+ 'api_title',
+ // 英文唯一标识
+ 'api_name',
+ // 分类
+ 'category_id',
+ // 数据源类型:1=remote,2=local
+ 'type',
+ // appid
+ 'appid',
+ // 项目ID
+ 'project_id',
+ // API URL
+ 'api_url',
+ // 方法:POST,GET,PUT,PATCH,DELETE,COPY,HEAD,OPTIONS
+ 'methods',
+ // 鉴权
+ 'auth',
+ // header
+ 'header',
+ // query
+ 'query',
+ // body
+ 'body',
+ // 文档URL
+ 'doc_url',
+ // 文档
+ 'document',
+ // 示例数据
+ 'sample_data',
+ // 示例返回数据
+ 'sample_result',
+ // 排序
+ 'sort',
+ // 状态:1=已完成,2=待开发,3=开发中,4=已废弃
+ 'status',
+ // content-type:application/x-www-form-urlencoded,multipart/form-data,raw
+ 'content_type',
+ // 环境ID
+ 'env_id',
+ // 备注
+ 'memo',
+ // 创建时间
+ 'created_at',
+ // 更新时间
+ 'updated_at',
+ // 软删除字段
+ 'deleted_at',
+ // 创建人ID
+ 'creator_id',
+ );
+}
\ No newline at end of file
diff --git a/catch/apimanager/model/ApiTesterLog.php b/catch/apimanager/model/ApiTesterLog.php
new file mode 100644
index 0000000..d621cd4
--- /dev/null
+++ b/catch/apimanager/model/ApiTesterLog.php
@@ -0,0 +1,60 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\model;
+
+use catcher\base\CatchModel as Model;
+/**
+ *
+ * @property int $id
+ * @property string $appid
+ * @property int $user_id
+ * @property int $api_id
+ * @property string $params
+ * @property string $result
+ * @property string $request_data
+ * @property string $response_data
+ * @property int $created_at
+ * @property int $updated_at
+ * @property int $deleted_at
+ * @property int $creator_id
+ */
+class ApiTesterLog extends Model
+{
+ // 表名
+ public $name = 'api_tester_log';
+ // 数据库字段映射
+ public $field = array(
+ 'id',
+ // appid
+ 'appid',
+ // users表id
+ 'user_id',
+ // api_tester表id
+ 'api_id',
+ // api参数
+ 'params',
+ // 返回值
+ 'result',
+ // 请求数据
+ 'request_data',
+ // 响应数据
+ 'response_data',
+ // 创建时间
+ 'created_at',
+ // 更新时间
+ 'updated_at',
+ // 软删除字段
+ 'deleted_at',
+ // 创建人ID
+ 'creator_id',
+ );
+}
\ No newline at end of file
diff --git a/catch/apimanager/model/ApiTesterUserenv.php b/catch/apimanager/model/ApiTesterUserenv.php
new file mode 100644
index 0000000..4c1b4a1
--- /dev/null
+++ b/catch/apimanager/model/ApiTesterUserenv.php
@@ -0,0 +1,76 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\model;
+
+use catchAdmin\permissions\model\DataRangScopeTrait;
+use catchAdmin\permissions\model\Users;
+use catchAdmin\apimanager\model\search\ApiTesterUserenvSearch;
+use catcher\base\CatchModel as Model;
+/**
+ *
+ * @property int $id
+ * @property string $env_name
+ * @property string $appid
+ * @property string $project_id
+ * @property string $env_json
+ * @property int $selected
+ * @property int $created_at
+ * @property int $updated_at
+ * @property int $deleted_at
+ * @property int $creator_id
+ */
+class ApiTesterUserenv extends Model
+{
+ use ApiTesterUserenvSearch;
+ use DataRangScopeTrait;
+ // 表名
+ public $name = 'api_tester_userenv';
+ // 数据库字段映射
+ public $field = array(
+ 'id',
+ // 环境名称
+ 'env_name',
+ // appid
+ 'appid',
+ // 项目ID
+ 'project_id',
+ // 环境变量json
+ 'env_json',
+ // 是否当前选中:0=否,1=是
+ 'selected',
+ // 创建时间
+ 'created_at',
+ // 更新时间
+ 'updated_at',
+ // 软删除字段
+ 'deleted_at',
+ // 创建人ID
+ 'creator_id',
+ );
+
+ /**
+ * get list
+ *
+ * @time 2020年04月28日
+ * @param $params
+ * @throws \think\db\exception\DbException
+ * @return void
+ */
+ public function getList()
+ {
+ return $this->dataRange()->field([$this->aliasField('*')])
+ ->catchJoin(Users::class, 'id', 'creator_id', ['username as creator'])
+ ->catchSearch()
+ ->order($this->aliasField('id'), 'desc')
+ ->paginate();
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/model/search/ApiCategorySearch.php b/catch/apimanager/model/search/ApiCategorySearch.php
new file mode 100644
index 0000000..c7bef08
--- /dev/null
+++ b/catch/apimanager/model/search/ApiCategorySearch.php
@@ -0,0 +1,25 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\model\search;
+
+trait ApiCategorySearch
+{
+ public function searchCategoryTitleAttr($query, $value, $data)
+ {
+ return $query->whereLike('category_title', $value);
+ }
+
+ public function searchStatusAttr($query, $value, $data)
+ {
+ return $query->where('status', $value);
+ }
+}
diff --git a/catch/apimanager/model/search/ApiTesterSearch.php b/catch/apimanager/model/search/ApiTesterSearch.php
new file mode 100644
index 0000000..172c3ab
--- /dev/null
+++ b/catch/apimanager/model/search/ApiTesterSearch.php
@@ -0,0 +1,54 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\model\search;
+
+use catchAdmin\apimanager\model\ApiCategory;
+
+trait ApiTesterSearch
+{
+ public function searchApiTitleAttr($query, $value, $data)
+ {
+ return $query->whereLike('api_title', $value);
+ }
+
+ public function searchApiNameAttr($query, $value, $data)
+ {
+ return $query->whereLike('api_name', $value);
+ }
+
+ public function searchStatusAttr($query, $value, $data)
+ {
+ return $query->where($this->aliasField('status'), $value);
+ }
+
+ public function searchTypeAttr($query, $value, $data)
+ {
+ return $query->where($this->aliasField('type'), $value);
+ }
+
+ /**
+ * 查询分类下的API
+ *
+ * @time 2021年05月20日
+ * @param $query
+ * @param $value
+ * @param $data
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @return mixed
+ */
+ public function searchCategoryIdAttr($query, $value, $data)
+ {
+ return $query->whereIn($this->aliasField('category_id'), ApiCategory::getChildrenCategoryIds($value));
+ }
+}
diff --git a/catch/apimanager/model/search/ApiTesterUserenvSearch.php b/catch/apimanager/model/search/ApiTesterUserenvSearch.php
new file mode 100644
index 0000000..30a5311
--- /dev/null
+++ b/catch/apimanager/model/search/ApiTesterUserenvSearch.php
@@ -0,0 +1,28 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\model\search;
+
+use catchAdmin\permissions\model\Users;
+
+trait ApiTesterUserenvSearch
+{
+ public function searchCreatorAttr($query, $value, $data)
+ {
+ return $query->whereLike(app(Users::class)->getTable() . '.username', $value);
+ }
+
+ public function searchEnvNameAttr($query, $value, $data)
+ {
+ return $query->whereLike('env_name', $value);
+ }
+
+}
diff --git a/catch/apimanager/module.json b/catch/apimanager/module.json
new file mode 100644
index 0000000..e0bdd83
--- /dev/null
+++ b/catch/apimanager/module.json
@@ -0,0 +1,17 @@
+{
+ "name": "API管理",
+ "alias": "apimanager",
+ "description": "UCToo API管理",
+ "version": "1.0.0",
+ "keywords": [
+ "API"
+ ],
+ "order": 0,
+ "services": [
+ "\\catchAdmin\\apimanager\\ApimanagerService"
+ ],
+ "aliases": [],
+ "files": [],
+ "requires": [],
+ "enable": true
+}
\ No newline at end of file
diff --git a/catch/apimanager/route.php b/catch/apimanager/route.php
new file mode 100644
index 0000000..5729c6d
--- /dev/null
+++ b/catch/apimanager/route.php
@@ -0,0 +1,26 @@
+
+// +----------------------------------------------------------------------
+
+// you should use `$router`
+/* @var think\Route $router */
+
+$router->group(function () use ($router){
+ // apiCategory路由
+ $router->resource('apicategory', '\catchAdmin\apimanager\controller\ApiCategory');
+ // apiTester路由
+ $router->resource('apitester', '\catchAdmin\apimanager\controller\ApiTester');
+ // apiTesterUserenv路由
+ $router->resource('apiTesterUserenv', '\catchAdmin\apimanager\controller\ApiTesterUserenv');
+ // 切换API环境
+ $router->get('apiTesterUserenv/selectAPIenv/', '\catchAdmin\apimanager\controller\ApiTesterUserenv@selectAPIenv');
+ // apiTesterLog路由
+ $router->resource('apiTesterLog', '\catchAdmin\apimanager\controller\ApiTesterLog');
+})->middleware('auth');
\ No newline at end of file
diff --git a/catch/apimanager/tables/ApiCategory.php b/catch/apimanager/tables/ApiCategory.php
new file mode 100644
index 0000000..f86f2ca
--- /dev/null
+++ b/catch/apimanager/tables/ApiCategory.php
@@ -0,0 +1,61 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\tables;
+
+use catchAdmin\apimanager\tables\forms\Factory;
+use catcher\CatchTable;
+use catcher\library\table\Actions;
+use catcher\library\table\HeaderItem;
+use catcher\library\table\Search;
+use catcher\library\table\Table;
+
+class ApiCategory extends CatchTable
+{
+ /**
+ * table
+ *
+ * @time 2021年03月29日
+ * @return array
+ */
+ protected function table(): array
+ {
+ // TODO: Implement table() method.
+ return $this->getTable('api_category')->header([
+ HeaderItem::label('分类标题')->prop('category_title'),
+ HeaderItem::label('分类唯一标识')->prop('category_name'),
+ HeaderItem::label('排序')->prop('sort')->withEditNumberComponent(),
+ HeaderItem::label('状态')->prop('status')->withSwitchComponent(),
+ HeaderItem::label('创建时间')->prop('created_at'),
+ HeaderItem::label('操作')->width(260)->actions([
+ Actions::update(),
+ Actions::delete(),
+ ])
+ ])->withApiRoute('apicategory')->withActions([
+ Actions::create()
+ ])->withSearch([
+ Search::label('分类标题')->text('category_title', '请输入分类标题'),
+ Search::label('状态')->status()
+ ])->withDialogWidth('35%')
+ ->toTreeTable()->render();
+ }
+
+ /**
+ * form 方式
+ *
+ * @time 2021年03月29日
+ * @return array
+ */
+ protected function form(): array
+ {
+ return Factory::create('ApiCategory');
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/tables/forms/ApiCategory.php b/catch/apimanager/tables/forms/ApiCategory.php
new file mode 100644
index 0000000..647e498
--- /dev/null
+++ b/catch/apimanager/tables/forms/ApiCategory.php
@@ -0,0 +1,40 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\tables\forms;
+
+use catchAdmin\apimanager\model\ApiCategory as ApiCategoryModel;
+use catcher\library\form\Form;
+
+class ApiCategory extends Form
+{
+ public function fields(): array
+ {
+ return [
+ // TODO: Implement fields() method
+ Form::cascader('parent_id', '上级分类', [0])->options(
+ ApiCategoryModel::field(['id', 'parent_id', 'category_title'])->select()->toTree()
+ )->clearable(true)->filterable(true)->props([
+ 'props' => [
+ 'value' => 'id',
+ 'label' => 'category_title',
+ 'checkStrictly' => true
+ ],
+ ])->style(['width' => '100%']),
+ Form::input('category_title', '分类标题')->required()->placeholder('分类标题'),
+ Form::input('category_name', '分类唯一标识'),
+ Form::radio('status', '状态')->value(1)->options(
+ Form::options()->add('启用', 1)->add('禁用', 2)->render()
+ ),
+ Form::number('sort', '排序')->value(1)->min(1)->max(10000),
+ ];
+ }
+}
\ No newline at end of file
diff --git a/catch/apimanager/tables/forms/Factory.php b/catch/apimanager/tables/forms/Factory.php
new file mode 100644
index 0000000..c9476be
--- /dev/null
+++ b/catch/apimanager/tables/forms/Factory.php
@@ -0,0 +1,22 @@
+
+// +----------------------------------------------------------------------
+
+namespace catchAdmin\apimanager\tables\forms;
+
+use catcher\library\form\FormFactory;
+
+class Factory extends FormFactory
+{
+ public static function from(): string
+ {
+ return __NAMESPACE__;
+ }
+}
\ No newline at end of file