Browse Source

管理后台

star7th 7 years ago
parent
commit
b3dcef7c2f

+ 6 - 0
Application/Home/Controller/UpdateController.class.php

@@ -185,6 +185,12 @@ class UpdateController extends BaseController {
             }
         }
 
+        //管理员账户和权限
+        if(D("User")->where("username = 'showdoc' ")->find()){
+            D("User")->where("username = 'showdoc' ")->save(array("groupid"=> 1)) ;
+        }else{
+             D("User")->add(array('username'=>"showdoc" ,"groupid"=>1,'password'=>"a89da13684490eb9ec9e613f91d24d00" , 'reg_time'=>time()));
+        }
 
         echo 'OK!';
     }

BIN
Sqlite/showdoc.db.php


+ 1 - 1
install/lang.en.php

@@ -11,7 +11,7 @@ return array(
   "db_password"=>' Database Password',
   "sqlite_tips"=>'Sqlite has supported by PHP and you just need to click the Go buttun',
   "go"=>'Go',
-  "install_success_help"=>'Installation success!Please delete the /install directory, avoid the script to be executed again.<br><a href="https://www.showdoc.cc/help-en" target="_blank">https://www.showdoc.cc/help-en</a>',
+  "install_success_help"=>'Installation success!The password of the default administrator account is showdoc/123456 ,After login, you can see the management backstage access in the upper right corner.In addition, it is strongly recommended to modify the administrator\'s initial password .<br>More help :<a href="https://www.showdoc.cc/help-en" target="_blank">https://www.showdoc.cc/help-en</a>',
   "home"=>'Website Home',
   "FAQ"=>'FAQ',
 

+ 1 - 1
install/lang.zh.php

@@ -11,7 +11,7 @@ return array(
   "db_password"=>'数据库密码',
   "sqlite_tips"=>'PHP内置支持Sqlite数据库,你无须再配置数据库,直接点击开始即可',
   "go"=>'开始',
-  "install_success_help"=>'安装成功!建议删除/install目录,以免安装脚本被再次执行。若再遇到问题,可参考ShowDoc帮助文档:<a href="https://www.showdoc.cc/help" target="_blank">https://www.showdoc.cc/help</a>',
+  "install_success_help"=>'安装成功!默认管理员账户密码是showdoc/123456。登录后,在右上角可以看到管理后台入口。此外,强烈建议修改管理员初始密码。若再遇到问题,可参考ShowDoc帮助文档:<a href="https://www.showdoc.cc/help" target="_blank">https://www.showdoc.cc/help</a>',
   "home"=>'进入网站首页',
   "FAQ"=>'常见问题',
 

+ 99 - 0
server/Application/Api/Controller/AdminItemController.class.php

@@ -0,0 +1,99 @@
+<?php
+namespace Api\Controller;
+use Think\Controller;
+class AdminItemController extends BaseController {
+
+
+    //获取所有项目列表
+    public function getList(){
+        $login_user = $this->checkLogin();
+        $this->checkAdmin();
+        $item_name = I("item_name");
+        $page = I("page/d");
+        $count = I("count/d");
+        $username = I("username");
+        $where = " 1 = 1 ";
+        if ($item_name) {
+            $item_name = mysql_escape_string($item_name);
+           $where .= " and item_name like '%{$item_name}%' ";
+        }
+        if ($username) {
+            $username = mysql_escape_string($username);
+           $where .= " and username like '%{$username}%' ";
+        }
+        $items = D("Item")->where($where)->order(" addtime desc  ")->page($page ,$count)->select();
+        $total = D("Item")->where($where)->count();
+        $item_members = D("ItemMember")->field("item_id , count(uid) as member_num")->group("item_id")->select();
+        $return = array() ;
+        $return['total'] = (int)$total ;
+        if ($items) {
+            foreach ($items as $key => &$value) {
+                $value['addtime'] = date("Y-m-d H:i:s" , $value['addtime']);
+                $value['member_num'] = $this->_get_member_num($item_members , $value['item_id']);
+            }
+            $return['items'] = $items ;
+            $this->sendResult($return);
+        }else{
+            $this->sendResult(array());
+        }
+    }
+
+    private function _get_member_num($item_members , $item_id){
+        if ($item_members ) {
+            foreach ($item_members as $key => $value) {
+               if ($value['item_id'] == $item_id ) {
+                   return $value['member_num'] + 1  ;
+               }
+            }
+        }
+        return 1 ;
+    }
+
+    //删除项目
+    public function deleteItem(){
+        $login_user = $this->checkLogin();
+        $this->checkAdmin();
+        $item_id = I("item_id/d");
+        $return = D("Item")->delete_item($item_id);
+        if (!$return) {
+            $this->sendError(10101);
+        }else{
+            $this->sendResult($return);
+        }
+    }
+
+    //转让项目
+    public function attorn(){
+        $login_user = $this->checkLogin();
+        $this->checkAdmin();
+        $username = I("username");
+        $item_id = I("item_id/d");
+
+        $item  = D("Item")->where("item_id = '$item_id' ")->find();
+
+
+        $member = D("User")->where(" username = '%s' ",array($username))->find();
+
+        if (!$member) {
+            $this->sendError(10209);
+            return ;
+        }
+
+        $data['username'] = $member['username'] ;
+        $data['uid'] = $member['uid'] ;
+        
+
+        $id = D("Item")->where(" item_id = '$item_id' ")->save($data);
+
+        $return = D("Item")->where("item_id = '$item_id' ")->find();
+
+        if (!$return) {
+            $this->sendError(10101);
+            return ;
+        }
+
+        $this->sendResult($return);
+    }
+
+
+}

+ 101 - 0
server/Application/Api/Controller/AdminUserController.class.php

@@ -0,0 +1,101 @@
+<?php
+namespace Api\Controller;
+use Think\Controller;
+class AdminUserController extends BaseController {
+
+
+    //获取所有用户列表
+    public function getList(){
+        $login_user = $this->checkLogin();
+        $this->checkAdmin();
+        $page = I("page/d");
+        $count = I("count/d");
+        $username = I("username");
+        $where = " 1 = 1 ";
+        if ($username) {
+            $username = mysql_escape_string($username);
+           $where .= " and username like '%{$username}%' ";
+        }
+        $Users = D("User")->where($where)->page($page ,$count)->order(" uid desc  ")->select();
+        $total = D("User")->where($where)->count();
+        $return = array() ;
+        $return['total'] = (int)$total ;
+        if ($Users) {
+            foreach ($Users as $key => &$value) {
+                $value['reg_time'] = date("Y-m-d H:i:s" , $value['reg_time']);
+                if($value['last_login_time']){
+                    $value['last_login_time'] = date("Y-m-d H:i:s" , $value['last_login_time']);
+                }else{
+                    $value['last_login_time'] = '';
+                }
+            }
+            $return['users'] = $Users ;
+            $this->sendResult($return);
+        }else{
+            $this->sendResult(array());
+        }
+    }
+
+    //删除项目
+    public function deleteUser(){
+        $login_user = $this->checkLogin();
+        $this->checkAdmin();
+        $uid = I("uid/d");
+
+        if (D("Item")->where("uid = '$uid' ")->find()) {
+           $this->sendError(10101,"该用户名下还有项目,不允许删除。请先将其项目删除或者重新分配/转让"); 
+           return ;
+        }
+        $return = D("User")->delete_user($uid);
+        if (!$return) {
+            $this->sendError(10101);
+        }else{
+            $this->sendResult($return);
+        }
+    }
+
+    //修改密码
+    public function changePassword(){
+        $login_user = $this->checkLogin();
+        $this->checkAdmin();
+        $uid = I("uid/d");
+        $new_password = I("new_password");
+
+        $return = D("User")->updatePwd($uid, $new_password);
+        if (!$return) {
+            $this->sendError(10101);
+        }else{
+            $this->sendResult($return);
+        }
+    }
+
+
+    //新增用户
+    public function addUser(){
+        $login_user = $this->checkLogin();
+        $this->checkAdmin();
+        $username = I("username");
+        $password = I("password");
+
+        if (D("User")->isExist($username)) {
+           $this->sendError(10101,L('username_exists'));
+           return ;
+        }
+        $new_uid = D("User")->register($username,$password);
+        if (!$new_uid) {
+            $this->sendError(10101);
+        }else{
+            $this->sendResult($return);
+        }
+    }
+
+    //检测showdoc版本更新
+    public function checkUpdate(){
+        header('Access-Control-Allow-Origin: *');//允许跨域请求
+        header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Connection, User-Agent, Cookie');
+        header('Access-Control-Allow-Credentials : true');//允许跨域请求
+        
+        //echo '{"version":"3.0","title":"检测到新版本,点击查看","description":"略","url":"https://www.showdoc.cc/page/14"}';
+    }
+
+}

+ 15 - 0
server/Application/Api/Controller/BaseController.class.php

@@ -29,6 +29,21 @@ class BaseController extends Controller {
 			return  session("login_user") ;
 		}
 	}
+	
+	//检查是否是管理员
+	public function checkAdmin($redirect = true){
+		$login_user = session("login_user") ;
+		if ($login_user) {
+			if ($login_user['groupid'] == 1 ) {
+				return true ;
+			}
+		}
+		if ($redirect) {
+			$this->sendError(10103);
+			exit();
+		}
+		return false;
+	}
 
 	/**
 	 * 返回json结果

+ 1 - 1
server/Application/Api/Controller/UserController.class.php

@@ -80,7 +80,7 @@ class UserController extends BaseController {
     public function info(){
         $login_user = $this->checkLogin();
         $uid = $login_user['uid'] ;
-        $field = "uid,username,email,name,avatar,avatar_small" ;
+        $field = "uid,username,email,name,avatar,avatar_small,groupid" ;
         $info = D("User")->where(" uid = '$uid' ")->field($field)->find();
         $this->sendResult($info); 
     }

+ 6 - 16
server/Application/Api/Model/ItemModel.class.php

@@ -179,24 +179,14 @@ class ItemModel extends BaseModel {
         return $this->import($this->export($item_id),$uid,$item_name,$item_description,$item_password,$item_domain);
     }
 
-    //清空项目内容,但不删除项目也不删除项目成员关系
-    public function empty_content($item_id){
+    //删除项目
+    public function delete_item($item_id){
+        D("Page")->where("item_id = '$item_id' ")->delete();
         D("Page")->where("item_id = '$item_id' ")->delete();
-        D("Page")->partitionTable($item_id)->where("item_id = '$item_id' ")->delete();
         D("Catalog")->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(1)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(2)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(3)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(4)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(5)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(6)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(7)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(8)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(9)->where("item_id = '$item_id' ")->delete();
-        D("PageHistory")->partitionTable(10)->where("item_id = '$item_id' ")->delete();
-        //删除菜单缓存
-        $redis = init_redis() ;
-        $redis->delete('showdoc_menu_cache_item_id_'.$item_id);
+        D("PageHistory")->where("item_id = '$item_id' ")->delete();
+        return D("Item")->where("item_id = '$item_id' ")->delete();
+
     }
     
 }

+ 11 - 0
server/Application/Api/Model/UserModel.class.php

@@ -49,4 +49,15 @@ class UserModel extends BaseModel {
     public function setLastTime($uid){
         return $this->where("uid='%s'",array($uid))->save(array("last_login_time"=>time()));
     }
+
+    //删除用户
+    public function delete_user($uid){
+        D("ItemMember")->where("uid = '$uid' ")->delete();
+        D("UserToken")->where("uid = '$uid' ")->delete();
+        D("Template")->where("uid = '$uid' ")->delete();
+        D("ItemTop")->where("uid = '$uid' ")->delete();
+        $return = D("User")->where("uid = '$uid' ")->delete();
+        return $return ;
+    }
+
 }

+ 2 - 2
web/index.html

@@ -1,7 +1,7 @@
-<!DOCTYPE html><html><head><meta charset=utf-8><meta name="renderer"  content="webkit"><meta name=viewport content="width=device-width,initial-scale=1"><title>ShowDoc</title><meta name=keywords content="在线API文档 技术文档 数据字典 在线手册"><meta name=description content=一个非常适合IT团队的在线API文档、技术文档工具。你可以使用Showdoc来编写在线API文档、技术文档、数据字典、在线手册><script type=text/javascript>//挂在window下的全局配置
+<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=renderer content=webkit><title>ShowDoc</title><meta name=keywords content="在线API文档 技术文档 数据字典 在线手册"><meta name=description content=一个非常适合IT团队的在线API文档、技术文档工具。你可以使用Showdoc来编写在线API文档、技术文档、数据字典、在线手册><script type=text/javascript>//挂在window下的全局配置
     window.DocConfig = {
       //"server":'http://127.0.0.1/showdoc/server/index.php?s=',
       "server": window.location.protocol +'//'+ window.location.host + window.location.pathname+ '../server/index.php?s=',
       //"lang" :'en'
       "lang" :'zh-cn'
-  }</script><link href=./static/css/app.1c5121052f0937e5cc2ab988d4421ef1.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.a3ffcf95dcfaded8b97d.js></script><script type=text/javascript src=./static/js/vendor.6ec312a9f1e4bcc005ef.js></script><script type=text/javascript src=./static/js/app.f277275803e45a4d95e3.js></script></body></html>
+  }</script><link href=./static/css/app.7bfef7255366bafdb4bc481cbd24ef4e.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.506682e59b10e0c39445.js></script><script type=text/javascript src=./static/js/vendor.6ec312a9f1e4bcc005ef.js></script><script type=text/javascript src=./static/js/app.8ef48ded3f253d82bb90.js></script></body></html>

File diff suppressed because it is too large
+ 0 - 0
web/static/css/app.1c5121052f0937e5cc2ab988d4421ef1.css


File diff suppressed because it is too large
+ 0 - 0
web/static/css/app.7bfef7255366bafdb4bc481cbd24ef4e.css


File diff suppressed because it is too large
+ 0 - 0
web/static/js/app.8ef48ded3f253d82bb90.js


File diff suppressed because it is too large
+ 0 - 0
web/static/js/app.f277275803e45a4d95e3.js


+ 1 - 1
web/static/js/manifest.a3ffcf95dcfaded8b97d.js → web/static/js/manifest.506682e59b10e0c39445.js

@@ -1 +1 @@
-!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var i,u,f,s=0,l=[];s<t.length;s++)u=t[s],o[u]&&l.push(o[u][0]),o[u]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(r&&r(t,c,a);l.length;)l.shift()();if(a)for(s=0;s<a.length;s++)f=n(n.s=a[s]);return f};var t={},o={2:0};n.e=function(e){function r(){i.onerror=i.onload=null,clearTimeout(u);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName("head")[0],i=document.createElement("script");i.type="text/javascript",i.charset="utf-8",i.async=!0,i.timeout=12e4,n.nc&&i.setAttribute("nonce",n.nc),i.src=n.p+"static/js/"+e+"."+{0:"6ec312a9f1e4bcc005ef",1:"f277275803e45a4d95e3"}[e]+".js";var u=setTimeout(r,12e4);return i.onerror=i.onload=r,a.appendChild(i),c},n.m=e,n.c=t,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="./",n.oe=function(e){throw console.error(e),e}}([]);
+!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var i,u,f,s=0,l=[];s<t.length;s++)u=t[s],o[u]&&l.push(o[u][0]),o[u]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(r&&r(t,c,a);l.length;)l.shift()();if(a)for(s=0;s<a.length;s++)f=n(n.s=a[s]);return f};var t={},o={2:0};n.e=function(e){function r(){i.onerror=i.onload=null,clearTimeout(u);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName("head")[0],i=document.createElement("script");i.type="text/javascript",i.charset="utf-8",i.async=!0,i.timeout=12e4,n.nc&&i.setAttribute("nonce",n.nc),i.src=n.p+"static/js/"+e+"."+{0:"6ec312a9f1e4bcc005ef",1:"8ef48ded3f253d82bb90"}[e]+".js";var u=setTimeout(r,12e4);return i.onerror=i.onload=r,a.appendChild(i),c},n.m=e,n.c=t,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="./",n.oe=function(e){throw console.error(e),e}}([]);

+ 8 - 1
web/static/lang/en.js

@@ -206,6 +206,13 @@ exports.default = {
 
     //其他
     "back_to_top":'back to top',
-    'draft_tips':"A draft that is automatically saved when you have the last editor was detected. Do you automatically fill in the last draft?"
+    'draft_tips':"A draft that is automatically saved when you have the last editor was detected. Do you automatically fill in the last draft?",
+
+    //管理后台
+    "management_backstage":"backstage" ,
+    "user_management":"users" ,
+    "item_management":"items" ,
+    "add_user":"add user" ,
+    "search":"search" ,
 
 };

+ 7 - 1
web/static/lang/zh-CN.js

@@ -211,6 +211,12 @@ exports.default = {
 
     //其他
     "back_to_top":'回到顶部',
-    'draft_tips':"检测到有上次编辑时自动保存的草稿。是否自动填充上次的草稿内容?"
+    'draft_tips':"检测到有上次编辑时自动保存的草稿。是否自动填充上次的草稿内容?",
 
+    //管理后台
+    "management_backstage":"管理后台" ,
+    "user_management":"用户管理" ,
+    "item_management":"项目管理" ,
+    "add_user":"新增用户" ,
+    "search":"查询" ,
 };

+ 2 - 2
web_src/src/components/Index.vue

@@ -72,7 +72,7 @@
               <h2></h2>
               <p>{{$t("section_description8")}}</p>
             <p>
-               <el-button><router-link to="/user/register">{{$t("section_title8")}}</router-link></el-button>
+               <el-button><router-link to="/user/login">{{$t("section_title8")}}</router-link></el-button>
             </p>
           </div>
         </el-carousel-item>
@@ -108,7 +108,7 @@ export default {
   mounted () {
     var that = this ;
     this.getHeight();
-    that.link = '/user/register';
+    that.link = '/user/login';
     that.link_text = that.$t("index_login_or_register");
     this.get_user_info(function(response){
       if (response.data.error_code === 0 ) {

+ 168 - 0
web_src/src/components/admin/Index.vue

@@ -0,0 +1,168 @@
+<template>
+
+  <div class="hello">
+
+
+    <el-container>
+      <el-header>
+      <div class="header_title">ShowDoc</div>
+      <router-link class="goback" to="/item/index">{{$t('goback')}}</router-link>
+    </el-header>
+      <el-container>
+        <el-aside width="150px">
+
+        <el-menu
+          default-active="1"
+          class="el-menu-vertical-demo"
+          background-color="#545c64"
+          text-color="#fff"
+          @select="select_menu"
+          active-text-color="#ffd04b">
+          <el-menu-item index="1">
+            <i class="el-icon-info"></i>
+            <span slot="title">{{$t('user_management')}}</span>
+          </el-menu-item>
+          <el-menu-item index="2">
+            <i class="el-icon-tickets"></i>
+            <span slot="title">{{$t('item_management')}}</span>
+          </el-menu-item>
+        </el-menu>
+
+      </el-aside>
+        <el-container>
+          <el-main>
+
+            <User v-if="open_menu_index == 1 "> </User>
+            <Item v-if="open_menu_index == 2 "> </Item> 
+            
+
+        </el-main>
+          <el-footer>
+            <!-- something -->
+        </el-footer>
+        </el-container>
+      </el-container>
+    </el-container>
+
+
+    </div>
+
+
+    
+  </div>
+</template>
+
+<style scoped>
+  .el-header {
+    background-color: #fff;
+    color: #333;
+    text-align: center;
+    line-height: 60px;
+    border-bottom:1px solid #ddd;
+    padding-left: 0px;
+
+  }
+
+   .el-footer {
+    color: #333;
+    text-align: center;
+    line-height: 60px;
+  }
+
+
+  .el-aside {
+    background-color: rgb(84, 92, 100);
+    color: #333;
+    text-align: center;
+    line-height: 200px;
+    height: calc(100% - 60px);
+    position: absolute;
+  }
+  
+  .el-main {
+    margin-left: 200px;
+  }
+  
+  body > .el-container {
+    position: absolute;
+    height: 100%;
+    width: 100%;
+
+  }
+  
+  .el-container:nth-child(5) .el-aside,
+  .el-container:nth-child(6) .el-aside {
+    line-height: 260px;
+  }
+  
+  .el-container:nth-child(7) .el-aside {
+    line-height: 320px;
+  }
+
+  .goback{
+    float: right;
+    margin-right: 20px;
+  }
+
+  .header_title{
+    float: left;
+    padding-right: 35px;
+    padding-left: 24px;
+    font-size: 20px;
+    border-right:1px solid #ddd;
+    background-color: rgb(84, 92, 100);
+    color: #fff;
+  }
+</style>
+
+<script>
+import Item from '@/components/admin/item/Index'
+import User from '@/components/admin/user/Index'
+
+export default {
+  data() {
+    return {
+      open_menu_index:1,
+    };
+  },
+  components:{
+    Item,
+    User,
+  },
+  methods:{
+    select_menu(index,indexPath){
+      this.open_menu_index = 0 ;
+      this.$nextTick(()=>{
+        this.open_menu_index = index ;
+      });
+      
+    },
+    check_upadte(){
+        var that = this ;
+        var url = DocConfig.server+'/api/adminUser/checkUpdate';
+          var params = new URLSearchParams();
+          that.axios.post(url, params)
+            .then(function (response) {
+              if (response.data.url) {
+                  that.$message({
+                    showClose: true,
+                    duration:10000,
+                    dangerouslyUseHTMLString: true,
+                    message: '<a target="_blank" href="'+response.data.url+'">'+response.data.title+'</a>'
+                  });
+              };
+
+            });
+    },
+  },
+  mounted () {
+    this.check_upadte();
+    
+  },
+  beforeDestroy(){
+    this.$message.closeAll();
+    /*去掉添加的背景色*/
+    document.body.removeAttribute("class","grey-bg");
+  }
+}
+</script>

+ 231 - 0
web_src/src/components/admin/item/Index.vue

@@ -0,0 +1,231 @@
+<template>
+
+<div class="hello">
+<el-form :inline="true"  class="demo-form-inline">
+  <el-form-item label="">
+    <el-input v-model="item_name" placeholder="项目名"></el-input>
+  </el-form-item>
+  <el-form-item label="">
+    <el-input v-model="username" placeholder="所有者"></el-input>
+  </el-form-item>
+<!--   <el-form-item label="活动区域">
+    <el-select v-model="formInline.region" placeholder="活动区域">
+      <el-option label="区域一" value="shanghai"></el-option>
+      <el-option label="区域二" value="beijing"></el-option>
+    </el-select>
+  </el-form-item> -->
+  <el-form-item>
+    <el-button  @click="onSubmit">查询</el-button>
+  </el-form-item>
+</el-form>
+
+ <el-table
+      :data="itemList"
+      style="width: 100%">
+      <el-table-column
+        prop="item_name"
+        label="项目名"
+        width="140">
+      </el-table-column>
+      <el-table-column
+        prop="item_description"
+        label="项目描述"
+        width="140">
+      </el-table-column>
+      <el-table-column
+        prop="password"
+        label="私密性"
+        :formatter="formatPrivacy"
+        width="80">
+      </el-table-column>
+
+      <el-table-column
+        prop="item_id"
+        label="访问链接"
+        width="100">
+          <template slot-scope="scope">
+            <el-button @click="jump_to_item(scope.row)" type="text" size="small">查看</el-button>
+          </template>
+      </el-table-column>
+      <el-table-column
+        prop="username"
+        label="所有者"
+        width="160">
+      </el-table-column>
+      <el-table-column
+        prop="member_num"
+        label="成员数"
+        width="80">
+      </el-table-column>
+      <el-table-column
+        prop="addtime"
+        label="创建时间"
+        width="160">
+      </el-table-column>
+      <el-table-column
+        prop="item_domain"
+        label="操作">
+          <template slot-scope="scope">
+            <el-button  @click="click_attorn_item(scope.row)" type="text" size="small">{{$t('attorn')}}</el-button>
+            <el-button @click="delete_item(scope.row)" type="text" size="small">{{$t('delete')}}</el-button>
+          </template>
+      </el-table-column>
+    </el-table>
+
+  <div class="block">
+    <span class="demonstration"></span>
+      <el-pagination
+        @current-change="handleCurrentChange"
+        :page-size="count"
+        layout="total, prev, pager, next"
+        :total="total">
+      </el-pagination>
+  </div>
+
+  <el-dialog :visible.sync="dialogAttornVisible" :modal="false" width="300px">
+    <el-form >
+        <el-form-item label="" >
+          <el-input  :placeholder="$t('attorn_username')" v-model="attornForm.username"></el-input>
+        </el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogAttornVisible = false">{{$t('cancel')}}</el-button>
+      <el-button type="primary" @click="attorn" >{{$t('attorn')}}</el-button>
+    </div>
+  </el-dialog>
+
+</div>
+
+</template>
+
+<style scoped>
+
+
+
+</style>
+
+<script>
+
+export default {
+  data() {
+    return {
+      page:1,
+      count:7,
+      item_name:'',
+      username:'',
+      itemList:[],
+      total:0,
+      dialogAttornVisible:false,
+      attornForm:{
+        username:'',
+      },
+      attorn_item_id:''
+    };
+  },
+  methods:{
+    get_item_list(){
+        var that = this ;
+        var url = DocConfig.server+'/api/adminItem/getList';
+
+        var params = new URLSearchParams();
+        params.append('item_name', this.item_name);
+        params.append('username', this.username);
+        params.append('page', this.page);
+        params.append('count', this.count);
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              //that.$message.success("加载成功");
+              var json = response.data.data ;
+              that.itemList = json.items ;
+              that.total = json.total;
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          });
+    },
+    formatPrivacy(row, column){
+      if (row ) {
+        if (row.password.length > 0 ) {
+          return "密码访问";
+        }else{
+          return "公开访问";
+        }
+      };
+    },
+    //跳转到项目
+    jump_to_item(row){
+      let url = '#/'+row.item_id;
+      window.open(url);
+    },
+    handleCurrentChange(currentPage){
+      this.page = currentPage ;
+      this.get_item_list();
+    },
+    onSubmit(){
+      this.page = 1 ;
+      this.get_item_list();
+    },
+    delete_item(row){
+        var that = this ;
+        var url = DocConfig.server+'/api/adminItem/deleteItem';
+          this.$confirm(that.$t('confirm_delete'), ' ', {
+            confirmButtonText: that.$t('confirm'),
+            cancelButtonText: that.$t('cancel'),
+            type: 'warning'
+          }).then(() => {
+            var params = new URLSearchParams();
+            params.append('item_id', row.item_id);
+            that.axios.post(url, params)
+              .then(function (response) {
+                if (response.data.error_code === 0 ) {
+                  that.$message.success("删除成功");
+                  that.get_item_list();
+                }else{
+                  that.$alert(response.data.error_message);
+                }
+                
+              });
+          })
+    },
+    click_attorn_item(row){
+      this.dialogAttornVisible = true ;
+      this.attorn_item_id = row.item_id
+    },
+    attorn(){
+      var that = this ;
+      var url = DocConfig.server+'/api/adminItem/attorn';
+
+      var params = new URLSearchParams();
+      params.append('item_id',  that.attorn_item_id);
+      params.append('username', this.attornForm.username);
+
+      that.axios.post(url, params)
+        .then(function (response) {
+          if (response.data.error_code === 0 ) {
+            that.dialogAttornVisible = false;
+              that.$message.success(that.$t("success"));
+              that.get_item_list();
+              
+          }else{
+            that.$alert(response.data.error_message);
+          }
+          
+        })
+        .catch(function (error) {
+          console.log(error);
+        });
+    }
+  },
+  mounted () {
+    this.get_item_list();
+    
+  },
+  beforeDestroy(){
+    this.$message.closeAll();
+    /*去掉添加的背景色*/
+    document.body.removeAttribute("class","grey-bg");
+  }
+}
+</script>

+ 259 - 0
web_src/src/components/admin/user/Index.vue

@@ -0,0 +1,259 @@
+<template>
+
+<div class="hello">
+<el-form :inline="true"  class="demo-form-inline">
+  <el-form-item label="">
+    <el-input v-model="username" placeholder="用户名"></el-input>
+  </el-form-item>
+<!--   <el-form-item label="活动区域">
+    <el-select v-model="formInline.region" placeholder="活动区域">
+      <el-option label="区域一" value="shanghai"></el-option>
+      <el-option label="区域二" value="beijing"></el-option>
+    </el-select>
+  </el-form-item> -->
+  <el-form-item>
+    <el-button @click="onSubmit">{{$t('search')}}</el-button>
+  </el-form-item>
+</el-form>
+  <el-button  type="primary" @click="dialogAddVisible = true" >{{$t('add_user')}}</el-button>
+ <el-table
+      :data="itemList"
+      style="width: 100%">
+      <el-table-column
+        prop="username"
+        label="用户名"
+        width="200">
+      </el-table-column>
+      <el-table-column
+        prop="groupid"
+        label="用户角色"
+        :formatter="formatGroup"
+        width="100">
+      </el-table-column>
+      <el-table-column
+        prop="reg_time"
+        label="注册时间"
+        width="160">
+      </el-table-column>
+      <el-table-column
+        prop="last_login_time"
+        label="最后登录时间"
+        width="160">
+      </el-table-column>
+      <el-table-column
+        prop="item_domain"
+        label="操作">
+          <template slot-scope="scope">
+            <el-button @click="click_password(scope.row)" type="text" size="small">修改密码</el-button>
+            <el-button @click="delete_user(scope.row)" type="text" size="small">删除</el-button>
+          </template>
+      </el-table-column>
+    </el-table>
+
+  <div class="block">
+    <span class="demonstration"></span>
+      <el-pagination
+        @current-change="handleCurrentChange"
+        :page-size="count"
+        layout="total, prev, pager, next"
+        :total="total">
+      </el-pagination>
+  </div>
+
+  <el-dialog :visible.sync="dialogVisible" :modal="false" width="300px">
+    <el-form >
+        <el-form-item label="" >
+          <el-input type="password"  placeholder="新密码" v-model="Form.new_password"></el-input>
+        </el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogVisible = false">{{$t('cancel')}}</el-button>
+      <el-button type="primary" @click="change_password" >{{$t('confirm')}}</el-button>
+    </div>
+  </el-dialog>
+
+  <el-dialog :visible.sync="dialogAddVisible" :modal="false" width="300px">
+    <el-form >
+        <el-form-item label="" >
+          <el-input type="text"  placeholder="登录名" v-model="addForm.username"></el-input>
+        </el-form-item>
+        <el-form-item label="" >
+          <el-input type="password"  placeholder="密码" v-model="addForm.password"></el-input>
+        </el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogAddVisible = false">{{$t('cancel')}}</el-button>
+      <el-button type="primary" @click="add_user" >{{$t('confirm')}}</el-button>
+    </div>
+  </el-dialog>
+
+</div>
+
+</template>
+
+<style scoped>
+
+
+
+</style>
+
+<script>
+
+export default {
+  data() {
+    return {
+      itemList:[],
+      username:'',
+      page:1 ,
+      count: 7 ,
+      total:0,
+      Form:{
+        new_password:''
+      },
+      addForm:{
+        username:'',
+        password:'',
+      },
+      dialogVisible:false,
+      dialogAddVisible:false,
+      password_uid:''
+    };
+  },
+  methods:{
+    get_user_list(){
+        var that = this ;
+        var url = DocConfig.server+'/api/adminUser/getList';
+
+        var params = new URLSearchParams();
+        params.append('username', this.username);
+        params.append('page', this.page);
+        params.append('count', this.count);
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              //that.$message.success("加载成功");
+              var json = response.data.data ;
+              that.itemList = json.users ;
+              that.total = json.total;
+
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          });
+    },
+    formatGroup(row, column){
+      if (row ) {
+        if (row.groupid == 1 ) {
+          return "管理员";
+        }
+        else if (row.groupid == 2 ) {
+          return "普通用户";
+        }
+        else{
+          return "未知";
+        }
+      };
+    },
+    //跳转到项目
+    jump_to_item(row){
+      let url = '#/'+row.item_id;
+      window.open(url);
+    },
+    handleCurrentChange(currentPage){
+      this.page = currentPage ;
+      this.get_user_list();
+    },
+    onSubmit(){
+      this.page = 1 ;
+      this.get_user_list();
+    },
+    delete_user(row){
+        var that = this ;
+        var url = DocConfig.server+'/api/adminUser/deleteUser';
+          this.$confirm(that.$t('confirm_delete'), ' ', {
+            confirmButtonText: that.$t('confirm'),
+            cancelButtonText: that.$t('cancel'),
+            type: 'warning'
+          }).then(() => {
+            var params = new URLSearchParams();
+            params.append('uid', row.uid);
+            that.axios.post(url, params)
+              .then(function (response) {
+                if (response.data.error_code === 0 ) {
+                  that.$message.success("删除成功");
+                  that.get_user_list();
+                  that.username = '';
+                }else{
+                  that.$alert(response.data.error_message);
+                }
+                
+              });
+          })
+    },
+    click_password(row){
+      this.dialogVisible = true ;
+      this.password_uid = row.uid
+    },
+    change_password(){
+      var that = this ;
+      var url = DocConfig.server+'/api/adminUser/changePassword';
+
+      var params = new URLSearchParams();
+      params.append('uid',  that.password_uid);
+      params.append('new_password', this.Form.new_password);
+
+      that.axios.post(url, params)
+        .then(function (response) {
+          if (response.data.error_code === 0 ) {
+              that.dialogVisible = false;
+              that.Form.new_password = '';
+              that.$message.success(that.$t("success"));
+
+          }else{
+            that.$alert(response.data.error_message);
+          }
+          
+        })
+        .catch(function (error) {
+          console.log(error);
+        });
+    },
+    add_user(){
+      var that = this ;
+      var url = DocConfig.server+'/api/adminUser/addUser';
+
+      var params = new URLSearchParams();
+      params.append('username',  that.addForm.username);
+      params.append('password', this.addForm.password);
+
+      that.axios.post(url, params)
+        .then(function (response) {
+          if (response.data.error_code === 0 ) {
+              that.dialogAddVisible = false;
+              that.addForm.password = '';
+              that.addForm.username = '';
+              that.$message.success(that.$t("success"));
+              that.get_user_list();
+
+          }else{
+            that.$alert(response.data.error_message);
+          }
+          
+        })
+        .catch(function (error) {
+          console.log(error);
+        });
+    }
+  },
+  mounted () {
+    this.get_user_list();
+    
+  },
+  beforeDestroy(){
+    this.$message.closeAll();
+    /*去掉添加的背景色*/
+    document.body.removeAttribute("class","grey-bg");
+  }
+}
+</script>

+ 16 - 1
web_src/src/components/item/Index.vue

@@ -11,6 +11,8 @@
           </div>
           <div class="header-btn-group pull-right">
             <el-button type="text"  @click="feedback">{{$t("feedback")}}</el-button>
+            
+            <router-link to="/admin/index" v-if="isAdmin">&nbsp;&nbsp;&nbsp;{{$t("management_backstage")}}</router-link>
             &nbsp;&nbsp;&nbsp;
             <el-dropdown @command="dropdown_callback">
               <span class="el-dropdown-link">
@@ -161,7 +163,8 @@ export default {
   data() {
     return {
       currentDate: new Date(),
-      itemList:{}
+      itemList:{},
+      isAdmin:false
     };
   },
   methods:{
@@ -258,7 +261,18 @@ export default {
             
           });
     },
+    
+    user_info(){
+        var that = this ;
+        this.get_user_info(function(response){
+          if (response.data.error_code === 0 ) {
+            if (response.data.data.groupid == 1 ) {
+              that.isAdmin = true ;
+            };
+          }
+        });
 
+    },
     dropdown_callback(data){
       if (data) {
         data();
@@ -267,6 +281,7 @@ export default {
   },
   mounted () {
     this.get_item_list();
+    this.user_info();
     
   },
   beforeDestroy(){

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

@@ -18,6 +18,7 @@
 
             <div class="header-right">
               <!-- 登录的事情下 -->
+               <router-link v-if="item_info.is_login" to="/item/index" >{{$t('goback')}} </router-link>
               <el-dropdown @command="dropdown_callback" v-if="item_info.is_login">
                 <span class="el-dropdown-link">
                   {{$t('item')}}<i class="el-icon-arrow-down el-icon--right"></i>
@@ -26,7 +27,6 @@
                   <el-dropdown-item :command="share_item">{{$t('share')}}</el-dropdown-item>
                   <router-link :to="'/item/export/'+item_info.item_id" v-if="item_info.ItemPermn"><el-dropdown-item>{{$t('export')}}</el-dropdown-item></router-link>
                   <router-link :to="'/item/setting/'+item_info.item_id"  v-if="item_info.ItemCreator"><el-dropdown-item>{{$t('item_setting')}}</el-dropdown-item></router-link>
-                  <router-link to="/item/index"><el-dropdown-item >{{$t('goback')}}</el-dropdown-item></router-link>
                 </el-dropdown-menu>
               </el-dropdown>
 

+ 6 - 1
web_src/src/router/index.js

@@ -17,7 +17,7 @@ import PageEdit from '@/components/page/edit/Index'
 import PageDiff from '@/components/page/Diff'
 import Catalog from '@/components/catalog/Index'
 import Notice from '@/components/notice/Index'
-
+import Admin from '@/components/admin/Index'
 
 Vue.use(Router)
 
@@ -108,5 +108,10 @@ export default new Router({
       name: 'Notice',
       component: Notice
     },
+    {
+      path: '/admin/index',
+      name: 'Admin',
+      component: Admin
+    },
   ]
 })

+ 8 - 1
web_src/static/lang/en.js

@@ -206,6 +206,13 @@ exports.default = {
 
     //其他
     "back_to_top":'back to top',
-    'draft_tips':"A draft that is automatically saved when you have the last editor was detected. Do you automatically fill in the last draft?"
+    'draft_tips':"A draft that is automatically saved when you have the last editor was detected. Do you automatically fill in the last draft?",
+
+    //管理后台
+    "management_backstage":"backstage" ,
+    "user_management":"users" ,
+    "item_management":"items" ,
+    "add_user":"add user" ,
+    "search":"search" ,
 
 };

+ 7 - 1
web_src/static/lang/zh-CN.js

@@ -211,6 +211,12 @@ exports.default = {
 
     //其他
     "back_to_top":'回到顶部',
-    'draft_tips':"检测到有上次编辑时自动保存的草稿。是否自动填充上次的草稿内容?"
+    'draft_tips':"检测到有上次编辑时自动保存的草稿。是否自动填充上次的草稿内容?",
 
+    //管理后台
+    "management_backstage":"管理后台" ,
+    "user_management":"用户管理" ,
+    "item_management":"项目管理" ,
+    "add_user":"新增用户" ,
+    "search":"查询" ,
 };

Some files were not shown because too many files changed in this diff