Commit ebb1713e by zhangle

refactor index page. add favorites function module

parent 86371916
package com.ctrip.framework.apollo.portal.controller; package com.ctrip.framework.apollo.portal.controller;
import com.google.common.collect.Sets;
import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.http.MultiResponseEntity; import com.ctrip.framework.apollo.common.http.MultiResponseEntity;
...@@ -17,12 +19,15 @@ import com.ctrip.framework.apollo.portal.service.UserService; ...@@ -17,12 +19,15 @@ import com.ctrip.framework.apollo.portal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
...@@ -46,8 +51,19 @@ public class AppController { ...@@ -46,8 +51,19 @@ public class AppController {
private UserService userService; private UserService userService;
@RequestMapping("") @RequestMapping("")
public List<App> findAllApp() { public List<App> findApps(@RequestParam(value = "appIds", required = false) String appIds) {
return appService.findAll(); if (StringUtils.isEmpty(appIds)){
return appService.findAll();
}else {
return appService.findByAppIds(Sets.newHashSet(appIds.split(",")));
}
}
@RequestMapping("/by-owner")
public List<App> findAppsByOwner(@RequestParam("owner") String owner, Pageable page){
return appService.findByOwnerName(owner, page);
} }
@RequestMapping("/{appId}/navtree") @RequestMapping("/{appId}/navtree")
......
package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.portal.entity.po.Favorite;
import com.ctrip.framework.apollo.portal.service.FavoriteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class FavoriteController {
@Autowired
private FavoriteService favoriteService;
@RequestMapping(value = "/favorites", method = RequestMethod.POST)
public Favorite addFavorite(@RequestBody Favorite favorite) {
return favoriteService.addFavorite(favorite);
}
@RequestMapping("/favorites")
public List<Favorite> findFavorites(@RequestParam(value = "userId", required = false) String userId,
@RequestParam(value = "appId", required = false) String appId,
Pageable page) {
return favoriteService.search(userId, appId, page);
}
@RequestMapping(value = "/favorites/{favoriteId}", method = RequestMethod.DELETE)
public void deleteFavorite(@PathVariable long favoriteId) {
favoriteService.deleteFavorite(favoriteId);
}
@RequestMapping(value = "/favorites/{favoriteId}", method = RequestMethod.PUT)
public void toTop(@PathVariable long favoriteId) {
favoriteService.adjustFavoriteToFirst(favoriteId);
}
}
package com.ctrip.framework.apollo.portal.entity.po;
import com.ctrip.framework.apollo.common.entity.BaseEntity;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "Favorite")
@SQLDelete(sql = "Update Favorite set isDeleted = 1 where id = ?")
@Where(clause = "isDeleted = 0")
public class Favorite extends BaseEntity {
@Column(name = "AppId", nullable = false)
private String appId;
@Column(name = "UserId", nullable = false)
private String userId;
@Column(name = "Position")
private long position;
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public long getPosition() {
return position;
}
public void setPosition(long position) {
this.position = position;
}
}
package com.ctrip.framework.apollo.portal.entity.po; package com.ctrip.framework.apollo.portal.entity.po;
public class UserInfo { public class UserInfo {
private String userId; private String userId;
private String name; private String name;
private String email; private String email;
...@@ -28,4 +29,20 @@ public class UserInfo { ...@@ -28,4 +29,20 @@ public class UserInfo {
public void setEmail(String email) { public void setEmail(String email) {
this.email = email; this.email = email;
} }
@Override
public boolean equals(Object o) {
if (o instanceof UserInfo) {
if (o == this){
return true;
}
UserInfo anotherUser = (UserInfo) o;
return userId.equals(anotherUser.userId);
} else {
return false;
}
}
} }
...@@ -2,11 +2,19 @@ package com.ctrip.framework.apollo.portal.repository; ...@@ -2,11 +2,19 @@ package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.entity.App;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
import java.util.Set;
public interface AppRepository extends PagingAndSortingRepository<App, Long> { public interface AppRepository extends PagingAndSortingRepository<App, Long> {
App findByAppId(String appId); App findByAppId(String appId);
List<App> findByOwnerName(String ownerName, Pageable page);
List<App> findByAppIdIn(Set<String> appIds);
} }
package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.portal.entity.po.Favorite;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
public interface FavoriteRepository extends PagingAndSortingRepository<Favorite, Long> {
List<Favorite> findByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(String userId, Pageable page);
List<Favorite> findByAppIdOrderByPositionAscDataChangeCreatedTimeAsc(String appId, Pageable page);
Favorite findFirst1ByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(String userId);
Favorite findByUserIdAndAppId(String userId, String appId);
}
...@@ -18,12 +18,14 @@ import com.dianping.cat.Cat; ...@@ -18,12 +18,14 @@ import com.dianping.cat.Cat;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.HttpStatusCodeException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
@Service @Service
public class AppService { public class AppService {
...@@ -54,6 +56,14 @@ public class AppService { ...@@ -54,6 +56,14 @@ public class AppService {
return Lists.newArrayList((apps)); return Lists.newArrayList((apps));
} }
public List<App> findByAppIds(Set<String> appIds){
return appRepository.findByAppIdIn(appIds);
}
public List<App> findByOwnerName(String ownerName, Pageable page){
return appRepository.findByOwnerName(ownerName, page);
}
public App load(String appId) { public App load(String appId) {
App app = appRepository.findByAppId(appId); App app = appRepository.findByAppId(appId);
if (app == null) { if (app == null) {
......
package com.ctrip.framework.apollo.portal.service;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.po.Favorite;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import com.ctrip.framework.apollo.portal.repository.FavoriteRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@Service
public class FavoriteService {
public static final long POSITION_DEFAULT = 10000;
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private FavoriteRepository favoriteRepository;
@Autowired
private UserService userService;
public Favorite addFavorite(Favorite favorite) {
UserInfo user = userService.findByUserId(favorite.getUserId());
if (user == null) {
throw new BadRequestException("user not exist");
}
UserInfo loginUser = userInfoHolder.getUser();
//user can only add himself favorite app
if (!loginUser.equals(user)) {
throw new BadRequestException("add favorite fail. "
+ "because favorite's user is not current login user.");
}
Favorite checkedFavorite = favoriteRepository.findByUserIdAndAppId(loginUser.getUserId(), favorite.getAppId());
if (checkedFavorite != null) {
throw new BadRequestException("Duplicate add favorite");
}
favorite.setPosition(POSITION_DEFAULT);
favorite.setDataChangeCreatedBy(user.getUserId());
favorite.setDataChangeLastModifiedBy(user.getUserId());
return favoriteRepository.save(favorite);
}
public List<Favorite> search(String userId, String appId, Pageable page) {
boolean isUserIdEmpty = StringUtils.isEmpty(userId);
boolean isAppIdEmpty = StringUtils.isEmpty(appId);
if (isAppIdEmpty && isUserIdEmpty) {
throw new BadRequestException("user id and app id can't be empty at the same time");
}
//search by userId
if (isAppIdEmpty && !isUserIdEmpty) {
return favoriteRepository.findByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(userId, page);
}
//search by appId
if (!isAppIdEmpty && isUserIdEmpty) {
return favoriteRepository.findByAppIdOrderByPositionAscDataChangeCreatedTimeAsc(appId, page);
}
//search by userId and appId
return Arrays.asList(favoriteRepository.findByUserIdAndAppId(userId, appId));
}
public void deleteFavorite(long favoriteId) {
Favorite favorite = favoriteRepository.findOne(favoriteId);
checkUserOperatePermission(favorite);
favoriteRepository.delete(favorite);
}
public void adjustFavoriteToFirst(long favoriteId) {
Favorite favorite = favoriteRepository.findOne(favoriteId);
checkUserOperatePermission(favorite);
String userId = favorite.getUserId();
Favorite firstFavorite = favoriteRepository.findFirst1ByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(userId);
long minPosition = firstFavorite.getPosition();
favorite.setPosition(minPosition - 1);
favoriteRepository.save(favorite);
}
private void checkUserOperatePermission(Favorite favorite) {
if (favorite == null) {
throw new BadRequestException("favorite not exist");
}
if (!Objects.equals(userInfoHolder.getUser().getUserId(), favorite.getUserId())) {
throw new BadRequestException("can not operate other person's favorite");
}
}
}
...@@ -86,7 +86,6 @@ ...@@ -86,7 +86,6 @@
<!--angular--> <!--angular-->
<script src="vendor/angular/angular.min.js"></script> <script src="vendor/angular/angular.min.js"></script>
<script src="vendor/angular/angular-route.min.js"></script>
<script src="vendor/angular/angular-resource.min.js"></script> <script src="vendor/angular/angular-resource.min.js"></script>
<script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script> <script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="vendor/angular/loading-bar.min.js"></script> <script src="vendor/angular/loading-bar.min.js"></script>
......
...@@ -106,7 +106,6 @@ ...@@ -106,7 +106,6 @@
<!--angular--> <!--angular-->
<script src="vendor/angular/angular.min.js"></script> <script src="vendor/angular/angular.min.js"></script>
<script src="vendor/angular/angular-route.min.js"></script>
<script src="vendor/angular/angular-resource.min.js"></script> <script src="vendor/angular/angular-resource.min.js"></script>
<script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script> <script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="vendor/angular/loading-bar.min.js"></script> <script src="vendor/angular/loading-bar.min.js"></script>
......
...@@ -31,13 +31,31 @@ ...@@ -31,13 +31,31 @@
</div> </div>
<div class="J_appFound hidden col-md-3 col-xs-3 col-sm-3" ng-show="!notFoundApp"> <div class="J_appFound hidden col-md-3 col-xs-3 col-sm-3" ng-show="!notFoundApp">
<div id="treeview"></div> <section class="panel">
<header class="panel-heading">
<img src="img/env.png" class="i-20">&nbsp;环境列表
<span class="pull-right"
data-tooltip="tooltip" data-placement="bottom" title="通过切换环境、集群来管理不同环境、集群的配置">
<img src="img/question.png" class="i-20"/>
</span>
</header>
<div id="treeview" class="no-radius"></div>
</section>
<!--app info--> <!--app info-->
<section class="panel"> <section class="panel">
<header class="panel-heading"> <header class="panel-heading">
<img src="img/info.png" class="i-25-20"/> 应用信息 <img src="img/info.png" class="i-25-20"/> 项目信息
<span class="tools pull-right"> <span class="pull-right cursor-pointer">
<a href="javascript:;" class="icon-chevron-down"></a> <a ng-if="!favoriteId" ng-click="addFavorite()"
data-tooltip="tooltip" data-placement="bottom" title="收藏">
<img src="img/unlike.png" class="i-20"/>
</a>
<a ng-if="favoriteId" ng-click="deleteFavorite()"
data-tooltip="tooltip" data-placement="bottom" title="取消收藏">
<img src="img/like.png" class="i-20"/>
</a>
</span> </span>
</header> </header>
<div class="panel-body"> <div class="panel-body">
...@@ -525,7 +543,6 @@ ...@@ -525,7 +543,6 @@
<!--angular--> <!--angular-->
<script src="vendor/angular/angular.min.js"></script> <script src="vendor/angular/angular.min.js"></script>
<script src="vendor/angular/angular-ui-router.min.js"></script>
<script src="vendor/angular/angular-resource.min.js"></script> <script src="vendor/angular/angular-resource.min.js"></script>
<script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script> <script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="vendor/angular/loading-bar.min.js"></script> <script src="vendor/angular/loading-bar.min.js"></script>
...@@ -556,6 +573,7 @@ ...@@ -556,6 +573,7 @@
<script type="application/javascript" src="scripts/services/CommitService.js"></script> <script type="application/javascript" src="scripts/services/CommitService.js"></script>
<script type="application/javascript" src="scripts/services/NamespaceLockService.js"></script> <script type="application/javascript" src="scripts/services/NamespaceLockService.js"></script>
<script type="application/javascript" src="scripts/services/InstanceService.js"></script> <script type="application/javascript" src="scripts/services/InstanceService.js"></script>
<script type="application/javascript" src="scripts/services/FavoriteService.js"></script>
<script type="application/javascript" src="scripts/AppUtils.js"></script> <script type="application/javascript" src="scripts/AppUtils.js"></script>
......
...@@ -97,7 +97,6 @@ ...@@ -97,7 +97,6 @@
<!--angular--> <!--angular-->
<script src="../vendor/angular/angular.min.js"></script> <script src="../vendor/angular/angular.min.js"></script>
<script src="../vendor/angular/angular-route.min.js"></script>
<script src="../vendor/angular/angular-resource.min.js"></script> <script src="../vendor/angular/angular-resource.min.js"></script>
<script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script> <script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="../vendor/angular/loading-bar.min.js"></script> <script src="../vendor/angular/loading-bar.min.js"></script>
......
...@@ -233,7 +233,6 @@ ...@@ -233,7 +233,6 @@
<!--angular--> <!--angular-->
<script src="../vendor/angular/angular.min.js"></script> <script src="../vendor/angular/angular.min.js"></script>
<script src="../vendor/angular/angular-route.min.js"></script>
<script src="../vendor/angular/angular-resource.min.js"></script> <script src="../vendor/angular/angular-resource.min.js"></script>
<script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script> <script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="../vendor/angular/loading-bar.min.js"></script> <script src="../vendor/angular/loading-bar.min.js"></script>
......
...@@ -13,55 +13,112 @@ ...@@ -13,55 +13,112 @@
<title>apollo</title> <title>apollo</title>
</head> </head>
<body ng-controller="IndexController"> <body>
<div class="site-notice"><label>当前站点支持</label><label ng-repeat="env in envs" ng-bind="env" style="margin-left: 5px;"></label> <apollonav></apollonav>
环境
</div>
<header class="site-header jumbotron">
<div class="container">
<div class="row">
<div class="col-xs-12"><h1>Apollo</h1>
<p>携程统一配置中心<br>
<span class="package-amount">共收录了 <strong ng-bind="appsCount"></strong> 个项目</span>
<a class="btn btn-success" href="app.html">创建项目</a>
</p>
<form class="" role="search">
<div class="form-group"><input type="text" class="form-control search clearable"
placeholder="搜索App, 例如:apollo" ng-model="searchKey"
ng-change="search()"></div>
</form>
</div>
</div> <div id="app-list" ng-controller="IndexController">
</div>
</header> <section class="media create-app-list">
<aside class="media-left text-center">
<div class="container-fluid apollo-container"> <h5>我的项目</h5>
<div class="list-group apps"> </aside>
<a class="package list-group-item" href="config.html?#/appid={{app.appId}}" <aside class="media-body">
ng-repeat="app in apps "> <div class="col-md-2 text-center" ng-click="goToCreateAppPage()">
<div class="row"> <div href="#" class="thumbnail create-btn hover cursor-pointer">
<div class="col-md-3"><h4 class="apps-name" ng-bind="app.appId"></h4></div> <img src="img/plus-white.png"/>
<div class="col-md-7 hidden-xs"> <h5>创建项目</h5>
<p class="apps-description" ng-bind="app.name"></p>
</div> </div>
<div class="col-md-2"> </div>
<p class="apps-description"> <div class="col-md-2 text-center" ng-repeat="app in createdApps" ng-click="goToAppHomePage(app.appId)">
<span ng-bind="app.ownerName"></span> <div href="#" class="thumbnail hover cursor-pointer">
<br> <h4 ng-bind="app.appId"></h4>
<span ng-bind="app.ownerEmail"></span> <h5 ng-bind="app.name"></h5>
</div>
</div>
<div class="col-md-2 text-center" ng-show="hasMoreCreatedApps"
ng-click="getUserCreatedApps()">
<div href="#" class="thumbnail hover cursor-pointer">
<img class="more-img" src="img/more.png"/>
<h5>加载更多</h5>
</div>
</div>
</aside>
</section>
<section class="media favorites-app-list">
<aside class="media-left text-center">
<h5>收藏的项目</h5>
</aside>
<aside class="media-body">
<div class="app-panel col-md-2 text-center"
ng-repeat="app in favorites"
ng-click="goToAppHomePage(app.appId)"
ng-mouseover="toggleOperationBtn(app)"
ng-mouseout="toggleOperationBtn(app)">
<div class="thumbnail hover">
<h4 ng-bind="app.appId"></h4>
<h5 ng-bind="app.name"></h5>
<p class="operate-panel" ng-show="app.showOperationBtn">
<button class="btn btn-default btn-xs" title="置顶"
ng-click="toTop(app.favoriteId);$event.stopPropagation();">
<img src="img/top.png" class="i-15">
</button>
<button class="btn btn-default btn-xs" title="取消收藏"
ng-click="deleteFavorite(app.favoriteId);$event.stopPropagation();">
<img src="img/like.png" class="i-15">
</button>
</p> </p>
</div>
</div>
<div class="col-md-2 text-center" ng-show="hasMoreFavorites"
ng-click="getUserFavorites()">
<div href="#" class="thumbnail hover cursor-pointer">
<img class="more-img" src="img/more.png"/>
<h5>加载更多</h5>
</div>
</div>
<div class="no-favorites text-center" ng-show="!favorites || favorites.length == 0">
<h4>您还没有收藏过任何项目,在项目主页可以收藏项目哟~</h4>
</div>
</aside>
</section>
<section class="media visit-app-list" ng-show="visitedApps && visitedApps.length">
<aside class="media-left text-center">
<h5>最近浏览的项目</h5>
</aside>
<aside class="media-body">
<div class="app-panel col-md-2 text-center"
ng-repeat="app in visitedApps"
ng-click="goToAppHomePage(app.appId)"
ng-mouseover="toggleOperationBtn(app)"
ng-mouseout="toggleOperationBtn(app)">
<div class="thumbnail hover">
<h4 ng-bind="app.appId"></h4>
<h5 ng-bind="app.name"></h5>
<p class="operate-panel" ng-show="app.showOperationBtn">
<button class="btn btn-default btn-xs" title="收藏"
ng-click="addFavorite(app.appId);$event.stopPropagation();">
<img src="img/unlike.png" class="i-15">
</button>
</p>
</div> </div>
</div> </div>
</a> <!--<div class="col-md-2 text-center" ng-repeat="appId in visitedApps"-->
</div> <!--ng-click="goToAppHomePage(appId)">-->
<!--<div class="thumbnail hover cursor-pointer">-->
<!--<h4 ng-bind="appId"></h4>-->
<!--</div>-->
<!--</div>-->
</aside>
</section>
</div> </div>
<div ng-include="'views/common/footer.html'"></div> <div ng-include="'views/common/footer.html'"></div>
<!--angular--> <!--angular-->
...@@ -82,7 +139,11 @@ ...@@ -82,7 +139,11 @@
<script type="application/javascript" src="scripts/app.js"></script> <script type="application/javascript" src="scripts/app.js"></script>
<script type="application/javascript" src="scripts/services/AppService.js"></script> <script type="application/javascript" src="scripts/services/AppService.js"></script>
<script type="application/javascript" src="scripts/services/EnvService.js"></script> <script type="application/javascript" src="scripts/services/EnvService.js"></script>
<script type="application/javascript" src="scripts/services/UserService.js"></script>
<script type="application/javascript" src="scripts/services/FavoriteService.js"></script>
<script type="application/javascript" src="scripts/AppUtils.js"></script> <script type="application/javascript" src="scripts/AppUtils.js"></script>
<script type="application/javascript" src="scripts/directive/directive.js"></script>
<script type="application/javascript" src="scripts/controller/IndexController.js"></script> <script type="application/javascript" src="scripts/controller/IndexController.js"></script>
</body> </body>
......
...@@ -107,7 +107,6 @@ ...@@ -107,7 +107,6 @@
<!--angular--> <!--angular-->
<script src="../vendor/angular/angular.min.js"></script> <script src="../vendor/angular/angular.min.js"></script>
<script src="../vendor/angular/angular-route.min.js"></script>
<script src="../vendor/angular/angular-resource.min.js"></script> <script src="../vendor/angular/angular-resource.min.js"></script>
<script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script> <script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="../vendor/angular/loading-bar.min.js"></script> <script src="../vendor/angular/loading-bar.min.js"></script>
......
...@@ -9,7 +9,7 @@ var directive_module = angular.module('apollo.directive', ['app.service', 'app.u ...@@ -9,7 +9,7 @@ var directive_module = angular.module('apollo.directive', ['app.service', 'app.u
/** page module 定义*/ /** page module 定义*/
// 首页 // 首页
var index_module = angular.module('index', ['toastr', 'app.service', 'app.util', 'angular-loading-bar']); var index_module = angular.module('index', ['toastr', 'app.service', 'apollo.directive', 'app.util', 'angular-loading-bar']);
//项目主页 //项目主页
var application_module = angular.module('application', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']); var application_module = angular.module('application', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']);
//创建项目页面 //创建项目页面
......
index_module.controller('IndexController', ['$scope', '$window', 'toastr', 'AppService', 'AppUtil', 'EnvService', index_module.controller('IndexController', ['$scope', '$window', 'toastr', 'AppUtil', 'AppService',
function ($scope, $window, toastr, AppService, AppUtil, EnvService) { 'UserService', 'FavoriteService',
IndexController]);
$scope.envs = [];
$scope.selectedEnv = '';
EnvService.find_all_envs().then(function (result) {
$scope.envs = result;
//default select first env
$scope.switchEnv($scope.envs[0]);
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "load env error");
});
function IndexController($scope, $window, toastr, AppUtil, AppService, UserService, FavoriteService) {
$scope.userId = '';
$scope.switchEnv = function (env) { $scope.getUserCreatedApps = getUserCreatedApps;
$scope.selectedEnv = env; $scope.getUserFavorites = getUserFavorites;
loadApps(env); $scope.addFavorite = addFavorite;
};
var sourceApps = []; $scope.goToAppHomePage = goToAppHomePage;
$scope.goToCreateAppPage = goToCreateAppPage;
$scope.toggleOperationBtn = toggleOperationBtn;
$scope.toTop = toTop;
$scope.deleteFavorite = deleteFavorite;
function loadApps(env){ UserService.load_user().then(function (result) {
AppService.find_all_app(env).then(function (result) { $scope.userId = result.userId;
sourceApps = sortApps(result);
$scope.apps = sourceApps; $scope.createdAppPage = 0;
$scope.appsCount = sourceApps.length; $scope.createdApps = [];
$scope.selectedEnv = env; $scope.hasMoreCreatedApps = true;
}, function (result) { $scope.favoritesPage = 0;
toastr.error(AppUtil.errorMsg(result), "load apps error"); $scope.favorites = [];
}); $scope.hasMoreFavorites = true;
} $scope.visitedApps = [];
var VISITED_APPS_STORAGE_KEY = "VisitedApps"; getUserCreatedApps();
//访问过的App放在列表最前面,方便用户选择
function sortApps(sourceApps) { getUserFavorites();
var visitedApps = JSON.parse(localStorage.getItem(VISITED_APPS_STORAGE_KEY));
if (!visitedApps){ initUserVisitedApps();
return sourceApps; });
function getUserCreatedApps() {
var size = 10;
AppService.find_app_by_owner($scope.userId, $scope.createdAppPage, size)
.then(function (result) {
$scope.createdAppPage += 1;
$scope.hasMoreCreatedApps = result.length == size;
if (!result || result.length == 0) {
return;
} }
var existedVisitedAppsMap = {}; result.forEach(function (app) {
visitedApps.forEach(function (app) { $scope.createdApps.push(app);
existedVisitedAppsMap[app] = true;
}); });
var sortedApps = []; })
sourceApps.forEach(function (app) { }
if (existedVisitedAppsMap[app.appId]){
sortedApps.push(app); function getUserFavorites() {
} var size = 11;
}); FavoriteService.findFavorites($scope.userId, '', $scope.favoritesPage, size)
sourceApps.forEach(function (app) { .then(function (result) {
if (!existedVisitedAppsMap[app.appId]){ $scope.favoritesPage += 1;
sortedApps.push(app); $scope.hasMoreFavorites = result.length == size;
}
if (!result || result.length == 0) {
return;
}
var appIds = [];
result.forEach(function (favorite) {
appIds.push(favorite.appId);
}); });
return sortedApps;
} AppService.find_apps(appIds.join(","))
.then(function (apps) {
$scope.search = function () { //sort
var key = $scope.searchKey.toLocaleLowerCase(); var appIdMapApp = {};
if (key == '') { apps.forEach(function (app) {
$scope.apps = sourceApps; appIdMapApp[app.appId] = app;
return; });
} result.forEach(function (favorite) {
var result = []; var app = appIdMapApp[favorite.appId];
sourceApps.forEach(function (item) { app.favoriteId = favorite.id;
if (item.appId.toLocaleLowerCase().indexOf(key) >= 0 || $scope.favorites.push(app);
item.name.toLocaleLowerCase().indexOf(key) >= 0) { });
result.push(item);
}
}); });
})
}
function initUserVisitedApps() {
var VISITED_APPS_STORAGE_KEY = "VisitedAppsV2";
var visitedAppsObject = JSON.parse(localStorage.getItem(VISITED_APPS_STORAGE_KEY));
if (!visitedAppsObject) {
visitedAppsObject = {};
}
var userVisitedApps = visitedAppsObject[$scope.userId];
if (userVisitedApps && userVisitedApps.length > 0) {
AppService.find_apps(userVisitedApps.join(","))
.then(function (apps) {
apps.forEach(function (app) {
$scope.visitedApps.push(app);
});
});
}
}
function addFavorite(appId) {
var favorite = {
userId: $scope.userId,
appId: appId
};
FavoriteService.addFavorite(favorite)
.then(function (result) {
$scope.favoriteId = result.id;
toastr.success("收藏成功");
reload();
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "收藏失败");
})
};
function goToCreateAppPage() {
$window.location.href = "/app.html";
}
function goToAppHomePage(appId) {
$window.location.href = "/config.html?#/appid=" + appId;
}
function toggleOperationBtn(app) {
app.showOperationBtn = !app.showOperationBtn;
}
function toTop(favoriteId) {
FavoriteService.toTop(favoriteId).then(function () {
toastr.success("置顶成功");
reload();
})
}
function deleteFavorite(favoriteId) {
FavoriteService.deleteFavorite(favoriteId).then(function () {
toastr.success("取消收藏成功");
reload();
})
}
function reload() {
setTimeout(function () {
$window.location.reload();
}, 500);
$scope.apps = result; }
};
}]); }
...@@ -10,7 +10,7 @@ directive_module.directive('apollonav', function ($compile, $window, toastr, App ...@@ -10,7 +10,7 @@ directive_module.directive('apollonav', function ($compile, $window, toastr, App
scope.sourceApps = []; scope.sourceApps = [];
scope.copyedApps = []; scope.copyedApps = [];
AppService.find_all_app().then(function (result) { AppService.find_apps().then(function (result) {
result.forEach(function (app) { result.forEach(function (app) {
app.selected = false; app.selected = false;
scope.sourceApps.push(app); scope.sourceApps.push(app);
......
appService.service('AppService', ['$resource', '$q', function ($resource, $q) { appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
var app_resource = $resource('/apps/:appId', {}, { var app_resource = $resource('/apps/:appId', {}, {
find_all_app:{ find_apps: {
method: 'GET', method: 'GET',
isArray: true, isArray: true,
url:'/apps' url: '/apps'
},
find_app_by_owner: {
method: 'GET',
isArray: true,
url: '/apps/by-owner'
}, },
load_navtree:{ load_navtree: {
methode: 'GET', methode: 'GET',
isArray:false, isArray: false,
url:'/apps/:appId/navtree' url: '/apps/:appId/navtree'
}, },
load_app: { load_app: {
method: 'GET', method: 'GET',
...@@ -28,24 +33,38 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { ...@@ -28,24 +33,38 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
} }
}); });
return { return {
find_all_app: function () { find_apps: function (appIds) {
if (!appIds) {
appIds = '';
}
var d = $q.defer(); var d = $q.defer();
app_resource.find_all_app({ app_resource.find_apps({appIds: appIds}, function (result) {
}, function (result) {
d.resolve(result); d.resolve(result);
}, function (result) { }, function (result) {
d.reject(result); d.reject(result);
}); });
return d.promise; return d.promise;
}, },
load_nav_tree: function (appId){ find_app_by_owner: function (owner, page, size) {
var d = $q.defer();
app_resource.find_app_by_owner({
owner: owner,
page: page,
size: size
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
load_nav_tree: function (appId) {
var d = $q.defer(); var d = $q.defer();
app_resource.load_navtree({ app_resource.load_navtree({
appId: appId appId: appId
}, function(result){ }, function (result) {
d.resolve(result); d.resolve(result);
}, function(result){ }, function (result) {
d.reject(result); d.reject(result);
}); });
return d.promise; return d.promise;
...@@ -61,7 +80,7 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { ...@@ -61,7 +80,7 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
}, },
create_remote: function (env, app) { create_remote: function (env, app) {
var d = $q.defer(); var d = $q.defer();
app_resource.create_app_remote({env:env}, app, function (result) { app_resource.create_app_remote({env: env}, app, function (result) {
d.resolve(result); d.resolve(result);
}, function (result) { }, function (result) {
d.reject(result); d.reject(result);
...@@ -71,8 +90,8 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { ...@@ -71,8 +90,8 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
load: function (appId) { load: function (appId) {
var d = $q.defer(); var d = $q.defer();
app_resource.load_app({ app_resource.load_app({
appId: appId appId: appId
}, function (result) { }, function (result) {
d.resolve(result); d.resolve(result);
}, function (result) { }, function (result) {
d.reject(result); d.reject(result);
...@@ -82,7 +101,7 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { ...@@ -82,7 +101,7 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
find_miss_envs: function (appId) { find_miss_envs: function (appId) {
var d = $q.defer(); var d = $q.defer();
app_resource.find_miss_envs({ app_resource.find_miss_envs({
appId: appId appId: appId
}, function (result) { }, function (result) {
d.resolve(result); d.resolve(result);
}, function (result) { }, function (result) {
......
appService.service('FavoriteService', ['$resource', '$q', function ($resource, $q) {
var resource = $resource('', {}, {
find_favorites: {
method: 'GET',
url: '/favorites',
isArray: true
},
add_favorite: {
method: 'POST',
url: '/favorites'
},
delete_favorite: {
method: 'DELETE',
url: '/favorites/:favoriteId'
},
to_top: {
method: 'PUT',
url: '/favorites/:favoriteId'
}
});
return {
findFavorites: function (userId, appId, page, size) {
var d = $q.defer();
resource.find_favorites({
userId: userId,
appId: appId,
page: page,
size: size
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
addFavorite: function (favorite) {
var d = $q.defer();
resource.add_favorite({}, favorite, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
deleteFavorite: function (favoriteId) {
var d = $q.defer();
resource.delete_favorite({
favoriteId: favoriteId
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
toTop: function (favoriteId) {
var d = $q.defer();
resource.to_top({
favoriteId: favoriteId
}, {}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
}
}]);
...@@ -67,7 +67,6 @@ ...@@ -67,7 +67,6 @@
<!--angular--> <!--angular-->
<script src="vendor/angular/angular.min.js"></script> <script src="vendor/angular/angular.min.js"></script>
<script src="vendor/angular/angular-route.min.js"></script>
<script src="vendor/angular/angular-resource.min.js"></script> <script src="vendor/angular/angular-resource.min.js"></script>
<script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script> <script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="vendor/angular/loading-bar.min.js"></script> <script src="vendor/angular/loading-bar.min.js"></script>
......
...@@ -25,23 +25,27 @@ p, td, span { ...@@ -25,23 +25,27 @@ p, td, span {
word-break: break-all; word-break: break-all;
} }
.no-radius { .no-radius {
border-radius: 0; border-radius: 0;
} }
.cursor-pointer{ .no-margin {
margin: 0;
}
.cursor-pointer {
cursor: pointer; cursor: pointer;
} }
pre { pre {
white-space: pre-wrap; /* Since CSS 2.1 */ white-space: pre-wrap; /* Since CSS 2.1 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */ white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */ white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */ word-wrap: break-word; /* Internet Explorer 5.5+ */
} }
.hover:hover{ .hover:hover {
background: #f5f5f5; background: #f5f5f5;
cursor: pointer cursor: pointer
} }
...@@ -75,7 +79,7 @@ pre { ...@@ -75,7 +79,7 @@ pre {
width: 15px; width: 15px;
} }
.badge{ .badge {
padding: 1px 4px; padding: 1px 4px;
} }
...@@ -89,7 +93,7 @@ pre { ...@@ -89,7 +93,7 @@ pre {
color: #0f0f0f; color: #0f0f0f;
} }
.panel-default > .panel-heading .badge{ .panel-default > .panel-heading .badge {
} }
...@@ -210,6 +214,14 @@ table th { ...@@ -210,6 +214,14 @@ table th {
min-width: 405px; min-width: 405px;
} }
#treeview .list-group{
margin: 0;
}
#treeview .list-group .list-group-item{
border: 0;
border-top: 1px solid #eff2f7;
}
.project-info th { .project-info th {
text-align: right; text-align: right;
padding: 4px 6px; padding: 4px 6px;
...@@ -225,11 +237,11 @@ table th { ...@@ -225,11 +237,11 @@ table th {
min-height: 500px; min-height: 500px;
} }
#itemModal .modal-dialog{ #itemModal .modal-dialog {
width: 860px; width: 860px;
} }
#itemModal .modal-body{ #itemModal .modal-body {
padding-bottom: 0; padding-bottom: 0;
} }
...@@ -350,12 +362,12 @@ table th { ...@@ -350,12 +362,12 @@ table th {
} }
.instance-view .btn-primary .badge{ .instance-view .btn-primary .badge {
color: #337ab7; color: #337ab7;
background-color: #fff; background-color: #fff;
} }
.instance-view .btn-default .badge{ .instance-view .btn-default .badge {
background: #777; background: #777;
color: #fff; color: #fff;
} }
...@@ -546,3 +558,64 @@ table th { ...@@ -546,3 +558,64 @@ table th {
font-size: 18px; font-size: 18px;
} }
/*index page*/
#app-list .media-body {
padding-top: 15px;
}
#app-list .media {
background: #fff;
display: table;
}
#app-list .media-left {
width: 1000px;
color: #fff;
display: table-cell;
vertical-align: middle;
}
#app-list .more-img {
width: 30px;
height: 30px;
}
#app-list .app-panel {
position: relative;
}
#app-list .operate-panel {
position: absolute;
top: 5px;
right: 20px;
}
.create-app-list .media-left {
background: #a9d96c;
}
.create-app-list .create-btn {
background: #a9d96c;
color: #fff
}
.create-app-list .create-btn:hover {
background: #81AB56;
}
.create-app-list .create-btn img {
width: 26px;
height: 26px
}
.favorites-app-list .media-left {
background: #57c8f2;
}
.favorites-app-list .no-favorites{
padding-bottom: 15px;
}
.visit-app-list .media-left {
background: #41cac0;
}
package com.ctrip.framework.apollo.portal.service;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.portal.AbstractIntegrationTest;
import com.ctrip.framework.apollo.portal.entity.po.Favorite;
import com.ctrip.framework.apollo.portal.repository.FavoriteRepository;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.jdbc.Sql;
import java.util.List;
public class FavoriteServiceTest extends AbstractIntegrationTest {
@Autowired
private FavoriteService favoriteService;
@Autowired
private FavoriteRepository favoriteRepository;
private String testUser = "apollo";
@Test
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testAddNormalFavorite() {
String testApp = "testApp";
Favorite favorite = instanceOfFavorite(testUser, testApp);
favoriteService.addFavorite(favorite);
List<Favorite> createdFavorites = favoriteService.search(testUser, testApp, new PageRequest(0, 10));
Assert.assertEquals(1, createdFavorites.size());
Assert.assertEquals(FavoriteService.POSITION_DEFAULT, createdFavorites.get(0).getPosition());
Assert.assertEquals(testUser, createdFavorites.get(0).getUserId());
Assert.assertEquals(testApp, createdFavorites.get(0).getAppId());
}
@Test(expected = BadRequestException.class)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testAddFavoriteErrorUser() {
String testApp = "testApp";
Favorite favorite = instanceOfFavorite("errorUser", testApp);
favoriteService.addFavorite(favorite);
}
@Test
@Sql(scripts = "/sql/favorites/favorites.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testSearchByUserId() {
List<Favorite> favorites = favoriteService.search(testUser, null, new PageRequest(0, 10));
Assert.assertEquals(4, favorites.size());
}
@Test
@Sql(scripts = "/sql/favorites/favorites.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testSearchByAppId() {
List<Favorite> favorites = favoriteService.search(null, "test0621-04", new PageRequest(0, 10));
Assert.assertEquals(3, favorites.size());
}
@Test
@Sql(scripts = "/sql/favorites/favorites.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testSearchByAppIdAndUserId() {
List<Favorite> favorites = favoriteService.search(testUser, "test0621-04", new PageRequest(0, 10));
Assert.assertEquals(1, favorites.size());
}
@Test(expected = BadRequestException.class)
@Sql(scripts = "/sql/favorites/favorites.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testSearchWithErrorParams() {
favoriteService.search(null, null, new PageRequest(0, 10));
}
@Test
@Sql(scripts = "/sql/favorites/favorites.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testDeleteFavorite() {
long legalFavoriteId = 21L;
favoriteService.deleteFavorite(legalFavoriteId);
Assert.assertNull(favoriteRepository.findOne(legalFavoriteId));
}
@Test(expected = BadRequestException.class)
@Sql(scripts = "/sql/favorites/favorites.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testDeleteFavoriteFail() {
long anotherPersonFavoriteId = 23L;
favoriteService.deleteFavorite(anotherPersonFavoriteId);
Assert.assertNull(favoriteRepository.findOne(anotherPersonFavoriteId));
}
@Test(expected = BadRequestException.class)
@Sql(scripts = "/sql/favorites/favorites.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testAdjustFavoriteError() {
long anotherPersonFavoriteId = 23;
favoriteService.adjustFavoriteToFirst(anotherPersonFavoriteId);
}
@Test
@Sql(scripts = "/sql/favorites/favorites.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testAdjustFavorite() {
long toAdjustFavoriteId = 20;
favoriteService.adjustFavoriteToFirst(toAdjustFavoriteId);
List<Favorite> favorites = favoriteService.search(testUser, null, new PageRequest(0, 10));
Favorite firstFavorite = favorites.get(0);
Favorite secondFavorite = favorites.get(1);
Assert.assertEquals(toAdjustFavoriteId, firstFavorite.getId());
Assert.assertEquals(firstFavorite.getPosition() + 1, secondFavorite.getPosition());
}
private Favorite instanceOfFavorite(String userId, String appId) {
Favorite favorite = new Favorite();
favorite.setAppId(appId);
favorite.setUserId(userId);
favorite.setDataChangeCreatedBy(userId);
favorite.setDataChangeLastModifiedBy(userId);
return favorite;
}
}
...@@ -3,4 +3,3 @@ spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy ...@@ -3,4 +3,3 @@ spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy
spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.show_sql=true
spring.h2.console.enabled = true spring.h2.console.enabled = true
spring.h2.console.settings.web-allow-others=true spring.h2.console.settings.web-allow-others=true
...@@ -3,3 +3,4 @@ delete from Role; ...@@ -3,3 +3,4 @@ delete from Role;
delete from RolePermission; delete from RolePermission;
delete from UserRole; delete from UserRole;
delete from AppNamespace; delete from AppNamespace;
DELETE FROM Favorite;
INSERT INTO `favorite` (`Id`, `UserId`, `AppId`, `Position`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_CreatedTime`, `DataChange_LastModifiedBy`, `DataChange_LastTime`)
VALUES
(18, 'apollo', 'test0621-03', 10000, 0, 'apollo', '2016-10-10 17:45:30', 'apollo', '2016-10-10 17:45:30'),
(19, 'apollo', '100003173', 9999, 0, 'apollo', '2016-10-10 17:45:42', 'apollo', '2016-10-10 17:51:12'),
(20, 'apollo', 'test0621-01', 10000, 00000000, 'apollo', '2016-10-10 17:50:57', 'apollo', '2016-10-10 17:50:57'),
(21, 'apollo', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:03', 'apollo', '2016-10-10 17:55:03'),
(22, 'apollo2', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:21', 'apollo', '2016-10-10 17:55:21'),
(23, 'apollo3', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:21', 'apollo', '2016-10-10 17:55:21');
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment