admin
2021-07-03 ea68e8f8c00c0178037a9f1cc6dc1663bde913b8
推送服务完善
1个文件已删除
3 文件已重命名
19个文件已修改
1 文件已复制
8个文件已添加
2046 ■■■■ 已修改文件
facade-push/src/main/java/com/ks/push/pojo/DO/BPushAppInfo.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
facade-push/src/main/java/com/ks/push/pojo/DO/BPushPlatformAppInfo.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
facade-push/src/main/java/com/ks/push/pojo/Query/BPushTaskQuery.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib-common/pom.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-goldcorn/pom.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/pom.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/config/WebSecurityConfig.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/controller/admin/AdminAppController.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/controller/admin/AdminPushPlatformAppController.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/controller/admin/AdminPushTaskController.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/dao/BPushAppInfoDao.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/dao/BPushPlatformAppInfoDao.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/dao/BPushTaskDao.java 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/entity/AdminUser.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/manager/PushExcuteResultManager.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/manager/PushManager.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/service/remote/BPushTaskServiceImpl.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/utils/PushTaskStateUtil.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/vo/BPushTaskFilterVO.java 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/java/com/ks/push/vo/BPushTaskVO.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/mapper/AdminUserMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/app-add.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/app-list.html 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/index.html 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/js/http.js 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/js/utils.js 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/pushplatform-appinfo-add.html 111 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/pushplatform-appinfo-list.html 116 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/pushtask-add.html 111 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/pushtask-list.html 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/main/resources/static/source-consume-add.html 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-push/src/test/java/com/ks/push/TaskTest.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
facade-push/src/main/java/com/ks/push/pojo/DO/BPushAppInfo.java
@@ -11,11 +11,19 @@
 */
@Document(collection = "bpushAppInfo")
public class BPushAppInfo implements Serializable {
    //有效
    public final static int STATE_NORMAL = 0;
    //无效
    public final static int STATE_INVALID = 1;
    @Id
    private String appCode;
    private String name;
    private String desc;
    private Integer state;
    private String stateDesc;
    private String remarks;
    private Date createTime;
    private Date updateTime;
@@ -58,4 +66,28 @@
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    public String getStateDesc() {
        return stateDesc;
    }
    public void setStateDesc(String stateDesc) {
        this.stateDesc = stateDesc;
    }
    public String getRemarks() {
        return remarks;
    }
    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }
}
facade-push/src/main/java/com/ks/push/pojo/DO/BPushPlatformAppInfo.java
@@ -4,6 +4,8 @@
import org.springframework.data.mongodb.core.mapping.Document;
import org.yeshi.utils.push.entity.PushAppInfo;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
@@ -15,12 +17,20 @@
    @Id
    private String id;
    @NotEmpty(message = "appCode不能为空")
    private String appCode;
    @NotNull(message = "platform不能为空")
    private PushPlatform platform;
    @NotNull(message = "pushAppInfo不能为空")
    private PushAppInfo pushAppInfo;
    private Date createTime;
    private Date updateTime;
    public static String createId(String appCode, PushPlatform platform) {
        return appCode + "-" + platform.name();
    }
    public String getId() {
        return id;
    }
facade-push/src/main/java/com/ks/push/pojo/Query/BPushTaskQuery.java
@@ -6,7 +6,7 @@
    public String appCode;
    public Integer state;
    private String messageTitle;
    public String messageTitle;
}
lib-common/pom.xml
@@ -15,7 +15,7 @@
        <dependency>
            <groupId>com.yeshi</groupId>
            <artifactId>utils</artifactId>
            <version>0.0.4</version>
            <version>0.0.6</version>
        </dependency>
    </dependencies>
service-goldcorn/pom.xml
@@ -155,7 +155,7 @@
        <dependency>
            <groupId>com.yeshi</groupId>
            <artifactId>utils</artifactId>
            <version>0.0.4</version>
            <version>0.0.6</version>
            <!--<scope>compile</scope>-->
        </dependency>
service-push/pom.xml
@@ -160,7 +160,7 @@
        <dependency>
            <groupId>com.yeshi</groupId>
            <artifactId>utils</artifactId>
            <version>0.0.5</version>
            <version>0.0.6</version>
            <scope>compile</scope>
        </dependency>
@@ -182,6 +182,14 @@
            <version>2.5</version>
        </dependency>
        <!--添加热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
            <scope>true</scope>
        </dependency>
    </dependencies>
@@ -191,7 +199,13 @@
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <!--热部署配置-->
                <configuration>
                    <!--fork:如果没有该项配置,整个devtools不会起作用-->
                    <fork>true</fork>
                </configuration>
            </plugin>
            <!-- MyBatis插件 -->
            <!--<plugin>-->
            <!--<groupId>org.mybatis.generator</groupId>-->
service-push/src/main/java/com/ks/push/config/WebSecurityConfig.java
New file
@@ -0,0 +1,232 @@
package com.ks.push.config;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import com.ks.push.entity.AdminUser;
import com.ks.push.manager.AdminUserManager;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.web.filter.OncePerRequestFilter;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Properties;
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
    @Resource
    private AdminUserManager adminUserManager;
    private final String LOGIN_PROCESSING_URL = "/admin/api/login";
    //图形验证码配置
    @Bean
    public Producer captcha() {
        Properties properties = new Properties();
        //图片的宽高
        properties.setProperty("kaptcha.image.width", "150");
        properties.setProperty("kaptcha.image.height", "50");
        //字符集
        properties.setProperty("kaptcha.textproducer.char.string", "0123456789");
        //字符长度
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        String color = "0,0,0";
        //边框颜色
        properties.setProperty("kaptcha.border.color", color);
        //字体颜色
        properties.setProperty("kaptcha.textproducer.font.color", color);
        //干扰颜色
        properties.setProperty("kaptcha.noise.color", color);
        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
    public class VerificationCodeException extends AuthenticationException {
        public VerificationCodeException() {
            super("图形验证码校验失败");
        }
    }
    //验证码过滤器
    class VerificationCodeFilter extends OncePerRequestFilter {
        private AuthenticationFailureHandler authenticationFailureHandler = new AuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                httpServletResponse.setContentType("application/json;charset=UTF-8");
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code", 11);
                jsonObject.put("msg", "验证码错误");
                httpServletResponse.getWriter().print(jsonObject);
            }
        };
        @Override
        protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
            if (!LOGIN_PROCESSING_URL.equalsIgnoreCase(httpServletRequest.getRequestURI())) {
                filterChain.doFilter(httpServletRequest, httpServletResponse);
            } else {
                try {
                    verificationCode(httpServletRequest);
                    filterChain.doFilter(httpServletRequest, httpServletResponse);
                } catch (VerificationCodeException e) {
                    authenticationFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e);
                }
            }
        }
        private void verificationCode(HttpServletRequest httpServletRequest) throws VerificationCodeException {
            String requestCode = httpServletRequest.getParameter("captcha");
            HttpSession httpSession = httpServletRequest.getSession();
            String captcha = httpSession.getAttribute("captcha") + "";
            httpSession.removeAttribute("captcha");
            if (StringUtil.isNullOrEmpty(captcha) || StringUtil.isNullOrEmpty(requestCode) || !captcha.equalsIgnoreCase(requestCode)) {
                throw new VerificationCodeException();
            }
        }
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers().frameOptions().disable();
        http.authorizeRequests()
                .antMatchers("/admin/api/captcha.jpg*").permitAll()
                .antMatchers("/admin/api/**", "/index.html").authenticated()
                .and()
                .formLogin()
                //自定义登录界面
                .loginPage("/login.html")
                //处理登录逻辑的url
                .loginProcessingUrl(LOGIN_PROCESSING_URL)
                //登录成功后的跳转
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        logger.info("successHandler");
                        httpServletResponse.setContentType("application/json;charset=UTF-8");
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("code", 200);
                        jsonObject.put("msg", "登录成功");
                        httpServletResponse.getWriter().print(jsonObject);
                    }
                })
                //登录失败后的处理
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        logger.info("failureHandler");
                        httpServletResponse.setContentType("application/json;charset=UTF-8");
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("code", 1);
                        if (e instanceof UsernameNotFoundException) {
                            jsonObject.put("msg", "用户不存在");
                        } else {
                            jsonObject.put("msg", e.getMessage());
                        }
                        httpServletResponse.getWriter().print(jsonObject);
                    }
                })
                .permitAll()
                .and()
                //退出登录
                .logout().logoutUrl("/admin/api/logout").logoutSuccessHandler(new LogoutSuccessHandler() {
            @Override
            public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                logger.info("onLogoutSuccess");
            }
        })
                .and()
                .csrf().disable()
                .rememberMe().userDetailsService(new MyUserDetailsService());
        http.addFilterBefore(new VerificationCodeFilter(), UsernamePasswordAuthenticationFilter.class);
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(new MyAuthenticationProvider(new MyUserDetailsService(), new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return charSequence.toString();
            }
            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return s.equalsIgnoreCase(charSequence.toString());
            }
        }));
    }
    class MyUserDetailsService implements UserDetailsService {
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            AdminUser adminUser = adminUserManager.selectByAccount(s);
            if (adminUser == null) {
                throw new UsernameNotFoundException("用户不存在");
            }
            //TODO 用户权限赋予
            return adminUser;
        }
    }
    class MyAuthenticationProvider extends DaoAuthenticationProvider {
        public MyAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
            this.setUserDetailsService(userDetailsService);
            this.setPasswordEncoder(passwordEncoder);
        }
        @Override
        protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
            if (usernamePasswordAuthenticationToken.getCredentials() == null) {
                throw new BadCredentialsException("密码不能为空");
            }
            String pwd = StringUtil.Md5(usernamePasswordAuthenticationToken.getCredentials().toString());
            if (!pwd.equalsIgnoreCase(userDetails.getPassword())) {
                throw new BadCredentialsException("密码错误");
            }
        }
    }
}
service-push/src/main/java/com/ks/push/controller/admin/AdminAppController.java
@@ -1,27 +1,96 @@
package com.ks.push.controller.admin;
import com.google.gson.*;
import com.ks.push.dao.BPushAppInfoDao;
import com.ks.push.pojo.DO.BPushAppInfo;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.TimeUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotEmpty;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("/admin/api/app")
public class AdminAppController {
    @Resource
    private BPushAppInfo adminUserManager;
    private BPushAppInfoDao bPushAppInfoDao;
    @ResponseBody
    @RequestMapping("list")
    public String list(@NotEmpty(message = "账号不能为空") String account, @NotEmpty(message = "密码不能为空") String pwd, @NotEmpty(message = "验证码不能为空") String code, BindingResult bindingResult, HttpSession session) {
    public String list(String key, int page, int limit) {
        BPushAppInfoDao.DaoQuery daoQuery = new BPushAppInfoDao.DaoQuery();
        daoQuery.name = key;
        daoQuery.start = (page - 1) * limit;
        daoQuery.count = limit;
        List<BPushAppInfo> list = bPushAppInfoDao.list(daoQuery);
        long count = bPushAppInfoDao.count(daoQuery);
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
        return null;
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).create();
        data.put("list", gson.toJson(list));
        data.put("count", count);
        return JsonUtil.loadTrueResult(data);
    }
    @ResponseBody
    @RequestMapping("delete")
    public String delete(String ids) {
        JSONArray array = JSONArray.fromObject(ids);
        for (int i = 0; i < array.size(); i++) {
            Query query = new Query();
            query.addCriteria(Criteria.where("appCode").is(array.optString(i)));
            bPushAppInfoDao.delete(query);
        }
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("update")
    public String update(BPushAppInfo app, HttpSession session) {
        if (app.getAppCode() == null) {
            return JsonUtil.loadFalseResult("ID不能为空");
        }
        bPushAppInfoDao.updateSelective(app);
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("add")
    public String add(BPushAppInfo app, HttpSession session) {
        if (app.getAppCode() == null) {
            return JsonUtil.loadFalseResult("appCode不能为空");
        }
        //查询是否存在
        BPushAppInfoDao.DaoQuery daoQuery = new BPushAppInfoDao.DaoQuery();
        daoQuery.appCode = app.getAppCode();
        if (bPushAppInfoDao.count(daoQuery) > 0) {
            return JsonUtil.loadFalseResult("appCode已经存在");
        }
        if (app.getCreateTime() == null) {
            app.setCreateTime(new Date());
        }
        bPushAppInfoDao.save(app);
        return JsonUtil.loadTrueResult("");
    }
service-push/src/main/java/com/ks/push/controller/admin/AdminPushPlatformAppController.java
New file
@@ -0,0 +1,124 @@
package com.ks.push.controller.admin;
import com.google.gson.*;
import com.ks.push.dao.BPushAppInfoDao;
import com.ks.push.dao.BPushPlatformAppInfoDao;
import com.ks.push.manager.BPushPlatformAppInfoManager;
import com.ks.push.pojo.DO.BPushAppInfo;
import com.ks.push.pojo.DO.BPushPlatformAppInfo;
import com.ks.push.pojo.DO.PushPlatform;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.TimeUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("/admin/api/pushplatform-app")
public class AdminPushPlatformAppController {
    @Resource
    private BPushPlatformAppInfoManager bPushPlatformAppInfoManager;
    @Resource
    private BPushPlatformAppInfoDao bPushPlatformAppInfoDao;
    @ResponseBody
    @RequestMapping("list")
    public String list(String key, String appCode, int page, int limit) {
        Query query = new Query();
        query.skip((page - 1) * limit);
        query.limit(limit);
        if (appCode != null) {
            query.addCriteria(Criteria.where("appCode").is(appCode));
        }
        List<BPushPlatformAppInfo> list = bPushPlatformAppInfoDao.findList(query);
        long count = bPushPlatformAppInfoDao.count(query);
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).registerTypeAdapter(PushPlatform.class, new JsonSerializer<PushPlatform>() {
            @Override
            public JsonElement serialize(PushPlatform platform, Type type, JsonSerializationContext jsonSerializationContext) {
                return platform == null ? new JsonPrimitive("") : new JsonPrimitive(platform.getName());
            }
        }).create();
        data.put("list", gson.toJson(list));
        data.put("count", count);
        return JsonUtil.loadTrueResult(data);
    }
    @ResponseBody
    @RequestMapping("delete")
    public String delete(String ids) {
        JSONArray array = JSONArray.fromObject(ids);
        for (int i = 0; i < array.size(); i++) {
            Query query = new Query();
            query.addCriteria(Criteria.where("id").is(array.optString(i)));
            bPushPlatformAppInfoDao.delete(query);
        }
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("update")
    public String update(@RequestBody BPushPlatformAppInfo app, HttpSession session) {
        if (app.getId() == null) {
            return JsonUtil.loadFalseResult("ID不能为空");
        }
        bPushPlatformAppInfoDao.updateSelective(app);
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("add")
    public String add(@RequestBody @Valid BPushPlatformAppInfo app, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return JsonUtil.loadFalseResult(bindingResult.getFieldError().getDefaultMessage());
        }
        if (app.getAppCode() == null) {
            return JsonUtil.loadFalseResult("appCode不能为空");
        }
        BPushPlatformAppInfo appInfo = bPushPlatformAppInfoManager.selectByAppCodeAndPlatform(app.getAppCode(), app.getPlatform());
        if (appInfo != null) {
            return JsonUtil.loadFalseResult("推送平台信息已存在");
        }
        if (app.getCreateTime() == null) {
            app.setCreateTime(new Date());
        }
        app.setId(BPushPlatformAppInfo.createId(app.getAppCode(), app.getPlatform()));
        bPushPlatformAppInfoDao.save(app);
        return JsonUtil.loadTrueResult("");
    }
}
service-push/src/main/java/com/ks/push/controller/admin/AdminPushTaskController.java
New file
@@ -0,0 +1,173 @@
package com.ks.push.controller.admin;
import com.google.gson.*;
import com.ks.push.dao.BPushAppInfoDao;
import com.ks.push.exception.BPushTaskException;
import com.ks.push.manager.PushExcuteResultManager;
import com.ks.push.pojo.DO.BPushAppInfo;
import com.ks.push.pojo.DO.BPushTask;
import com.ks.push.pojo.DO.BPushTaskExcuteResult;
import com.ks.push.pojo.DO.PushPlatform;
import com.ks.push.pojo.Query.BPushTaskQuery;
import com.ks.push.service.BPushTaskService;
import com.ks.push.utils.PushTaskStateUtil;
import com.ks.push.vo.BPushTaskFilterVO;
import com.ks.push.vo.BPushTaskVO;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.TimeUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("/admin/api/pushtask")
public class AdminPushTaskController {
    @Resource
    private BPushTaskService bPushTaskService;
    @Resource
    private PushExcuteResultManager pushExcuteResultManager;
    @ResponseBody
    @RequestMapping("list")
    public String list(String appCode, Integer state, String key, int page, int limit) {
        BPushTaskQuery query = new BPushTaskQuery();
        query.appCode = appCode;
        query.state = state;
        query.messageTitle = key;
        List<BPushTask> list = bPushTaskService.list(query, page, limit);
        List<BPushTaskVO> voList = new ArrayList<>();
        for (BPushTask task : list) {
            BPushTaskVO vo = new BPushTaskVO();
            vo.setAppCode(task.getAppCode());
            vo.setTitle(task.getMessage().getTitle());
            vo.setContent(task.getMessage().getContent());
            vo.setState(PushTaskStateUtil.getStateDesc(task.getState()));
            vo.setStateDesc(task.getStateDesc());
            vo.setTaskId(task.getId());
            vo.setCreateTime(task.getCreateTime());
            vo.setUpdateTime(task.getUpdateTime());
            List<BPushTaskVO.OperateState> operateStateList = new ArrayList<>();
            List<BPushTaskVO.Operator> operatorlist = PushTaskStateUtil.getTaskOperates(task.getState());
            for (BPushTaskVO.Operator operator : BPushTaskVO.Operator.values()) {
                BPushTaskVO.OperateState os = new BPushTaskVO.OperateState();
                os.setName(operator.getName());
                os.setOperator(operator);
                os.setValid(operatorlist.contains(operator));
                operateStateList.add(os);
            }
            vo.setOperateStates(operateStateList);
            voList.add(vo);
        }
        long count = bPushTaskService.count(query);
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).create();
        data.put("list", gson.toJson(voList));
        data.put("count", count);
        return JsonUtil.loadTrueResult(data);
    }
    @ResponseBody
    @RequestMapping("updateState")
    public String updateState(String id, BPushTaskVO.Operator operator) {
        BPushTask task = bPushTaskService.getTask(id);
        if (task == null) {
            return JsonUtil.loadFalseResult("推送任务不存在");
        }
        try {
            if (operator == BPushTaskVO.Operator.pausePush) {
                bPushTaskService.pausePush(id);
            } else if (operator == BPushTaskVO.Operator.cancelPush) {
                bPushTaskService.cancelPush(id);
            } else if (operator == BPushTaskVO.Operator.startPush) {
                bPushTaskService.startPush(id);
            } else if (operator == BPushTaskVO.Operator.reStartPush) {
                bPushTaskService.reStartPush(id);
            }
        } catch (BPushTaskException e) {
            e.printStackTrace();
            return JsonUtil.loadFalseResult(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return JsonUtil.loadFalseResult(e.getMessage());
        }
        return JsonUtil.loadTrueResult("");
    }
    /**
     * 获取推送条件
     *
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping("getPushFilter")
    public String getPushFilter(String id) {
        BPushTask task = bPushTaskService.getTask(id);
        if (task == null) {
            return JsonUtil.loadFalseResult("推送任务不存在");
        }
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).create();
        BPushTaskFilterVO vo = BPushTaskFilterVO.create(task.getFilter());
        return JsonUtil.loadTrueResult(gson.toJson(vo));
    }
    /**
     * 获取推送结果
     *
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping("getPushResult")
    public String getPushResult(String id) {
        BPushTask task = bPushTaskService.getTask(id);
        if (task == null) {
            return JsonUtil.loadFalseResult("推送任务不存在");
        }
        List<BPushTaskExcuteResult> list = pushExcuteResultManager.listByTaskId(task.getId());
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).registerTypeAdapter(PushPlatform.class, new JsonSerializer<PushPlatform>() {
            @Override
            public JsonElement serialize(PushPlatform platform, Type type, JsonSerializationContext jsonSerializationContext) {
                return platform == null ? new JsonPrimitive("") : new JsonPrimitive(platform.getName());
            }
        }).create();
        return JsonUtil.loadTrueResult(gson.toJson(list));
    }
}
service-push/src/main/java/com/ks/push/dao/BPushAppInfoDao.java
@@ -38,6 +38,10 @@
            andList.add(Criteria.where("appCode").is(daoQuery.appCode));
        }
        if (daoQuery.state != null) {
            andList.add(Criteria.where("state").is(daoQuery.state));
        }
        if (daoQuery.name != null) {
            andList.add(Criteria.where("name").regex(daoQuery.name));
        }
@@ -50,10 +54,16 @@
            andList.add(Criteria.where("createTime").lt(daoQuery.maxCreateTime));
        }
        if (daoQuery.state != null) {
            andList.add(Criteria.where("state").is(daoQuery.state));
        }
        Criteria[] ands = new Criteria[andList.size()];
        andList.toArray(ands);
        Query query = new Query();
        query.addCriteria(new Criteria().andOperator(ands));
        if (ands.length > 0) {
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
    }
@@ -73,6 +83,7 @@
    public static class DaoQuery {
        public String appCode;
        public String name;
        private Integer state;
        public Date minCreateTime;
        public Date maxCreateTime;
        public int start;
service-push/src/main/java/com/ks/push/dao/BPushPlatformAppInfoDao.java
@@ -10,25 +10,36 @@
import java.util.Date;
@Repository
public class BPushPlatformAppInfoDao extends MongodbBaseDao<BPushPlatformAppInfo>{
public class BPushPlatformAppInfoDao extends MongodbBaseDao<BPushPlatformAppInfo> {
  public void updateSelective(BPushPlatformAppInfo bean) {
    public void updateSelective(BPushPlatformAppInfo bean) {
        Query query = new Query();
        Update update=new Update();
        Update update = new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if(bean.getAppCode() != null) {
        if (bean.getAppCode() != null) {
            update.set("appCode", bean.getAppCode());
        }
        if(bean.getPlatform() != null) {
        if (bean.getPlatform() != null) {
            update.set("platform", bean.getPlatform());
        }
        if(bean.getPushAppInfo() != null) {
            update.set("pushAppInfo", bean.getPushAppInfo());
        if (bean.getPushAppInfo() != null) {
            if (bean.getPushAppInfo().getAppId() != null) {
                update.set("pushAppInfo.appId", bean.getPushAppInfo().getAppId());
            }
            if (bean.getPushAppInfo().getAppKey() != null) {
                update.set("pushAppInfo.appKey", bean.getPushAppInfo().getAppKey());
            }
            if (bean.getPushAppInfo().getAppSecret() != null) {
                update.set("pushAppInfo.appSecret", bean.getPushAppInfo().getAppSecret());
            }
            if (bean.getPushAppInfo().getPackageName() != null) {
                update.set("pushAppInfo.packageName", bean.getPushAppInfo().getPackageName());
            }
        }
        if(bean.getCreateTime() != null) {
        if (bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
  }
    }
}
service-push/src/main/java/com/ks/push/dao/BPushTaskDao.java
@@ -2,39 +2,78 @@
import com.ks.push.pojo.DO.BPushTask;
import com.ks.lib.common.dao.MongodbBaseDao;
import com.ks.push.pojo.Query.BPushTaskQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Repository
public class BPushTaskDao extends MongodbBaseDao<BPushTask>{
public class BPushTaskDao extends MongodbBaseDao<BPushTask> {
  public void updateSelective(BPushTask bean) {
    public void updateSelective(BPushTask bean) {
        Query query = new Query();
        Update update=new Update();
        Update update = new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if(bean.getAppCode() != null) {
        if (bean.getAppCode() != null) {
            update.set("appCode", bean.getAppCode());
        }
        if(bean.getState() != null) {
        if (bean.getState() != null) {
            update.set("state", bean.getState());
        }
        if(bean.getStateDesc() != null) {
        if (bean.getStateDesc() != null) {
            update.set("stateDesc", bean.getStateDesc());
        }
        if(bean.getFilter() != null) {
        if (bean.getFilter() != null) {
            update.set("filter", bean.getFilter());
        }
        if(bean.getMessage() != null) {
        if (bean.getMessage() != null) {
            update.set("message", bean.getMessage());
        }
        if(bean.getCreateTime() != null) {
        if (bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
  }
    }
    private Query getQuery(BPushTaskQuery daoQuery) {
        List<Criteria> andList = new ArrayList<>();
        if (daoQuery.state != null) {
            andList.add(Criteria.where("state").is(daoQuery.state));
        }
        if (daoQuery.appCode != null) {
            andList.add(Criteria.where("appCode").is(daoQuery.appCode));
        }
        if (daoQuery.messageTitle != null) {
            andList.add(Criteria.where("message.title").regex(daoQuery.messageTitle));
        }
        Query query = new Query();
        if (andList.size() > 0) {
            Criteria[] ands = new Criteria[andList.size()];
            andList.toArray(ands);
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
    }
    public List<BPushTask> list(BPushTaskQuery daoQuery, int start, int count) {
        Query query = getQuery(daoQuery);
        query.skip(start);
        query.limit(count);
        return findList(query);
    }
    public long count(BPushTaskQuery daoQuery) {
        Query query = getQuery(daoQuery);
        return count(query);
    }
}
service-push/src/main/java/com/ks/push/entity/AdminUser.java
@@ -1,9 +1,12 @@
package com.ks.push.entity;
import java.io.Serializable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Date;
public class AdminUser implements Serializable {
public class AdminUser implements UserDetails {
    private Long id;
@@ -55,4 +58,38 @@
        this.createTime = createTime;
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }
    @Override
    public String getPassword() {
        return pwd;
    }
    @Override
    public String getUsername() {
        return account;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    }
}
service-push/src/main/java/com/ks/push/manager/PushExcuteResultManager.java
@@ -153,5 +153,18 @@
        bPushTaskExcuteResultMapper.updateByPrimaryKeySelective(update);
    }
    /**
     * 根据任务ID查询推送结果
     *
     * @param taskId
     * @return
     */
    public List<BPushTaskExcuteResult> listByTaskId(String taskId) {
        BPushTaskExcuteResultMapper.DaoQuery daoQuery = new BPushTaskExcuteResultMapper.DaoQuery();
        daoQuery.taskId = taskId;
        daoQuery.count = 100;
        return bPushTaskExcuteResultMapper.list(daoQuery);
    }
}
service-push/src/main/java/com/ks/push/manager/PushManager.java
@@ -42,7 +42,6 @@
    private PushExcuteResultManager pushExcuteResultManager;
    /**
     * 创建推送任务
     *
@@ -55,6 +54,11 @@
            task.setCreateTime(new Date());
        }
        task.setId(BPushTask.createId());
        if (task.getState() == null) {
            task.setState(BPushTask.STATE_NOT_START);
        }
        bPushTaskDao.save(task);
        logger.info("创建推送成功#taskId:{}", task.getId());
        return task.getId();
service-push/src/main/java/com/ks/push/service/remote/BPushTaskServiceImpl.java
@@ -9,8 +9,11 @@
import com.ks.push.pojo.Query.BPushTaskQuery;
import com.ks.push.service.BPushTaskService;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Service(version = "1.0")
@@ -36,14 +39,16 @@
        return bPushTaskDao.get(taskId);
    }
    @Override
    public List<BPushTask> list(BPushTaskQuery query, int page, int pageSize) {
        return null;
        return bPushTaskDao.list(query, (page - 1) * pageSize, pageSize);
    }
    @Override
    public long count(BPushTaskQuery query) {
        return 0;
        return bPushTaskDao.count(query);
    }
    @Override
service-push/src/main/java/com/ks/push/utils/PushTaskStateUtil.java
New file
@@ -0,0 +1,69 @@
package com.ks.push.utils;
import com.ks.push.pojo.DO.BPushTask;
import com.ks.push.vo.BPushTaskVO;
import java.util.Arrays;
import java.util.List;
public class PushTaskStateUtil {
    public static String getStateDesc(Integer state) {
        if (state == null) {
            return "未知";
        }
        switch (state) {
            case BPushTask
                    .STATE_NOT_START:
                return "推送未开始";
            case BPushTask
                    .STATE_PUSHING:
                return "推送中";
            case BPushTask
                    .STATE_PAUSED:
                return "推送暂停";
            case BPushTask
                    .STATE_CANCELED:
                return "推送已取消";
            case BPushTask
                    .STATE_FINSIH:
                return "推送结束";
            default:
                return "未知状态";
        }
    }
    /**
     * 获取操作列表
     *
     * @param state
     * @return
     */
    public static List<BPushTaskVO.Operator> getTaskOperates(Integer state) {
        switch (state) {
            case BPushTask
                    .STATE_NOT_START:
                return Arrays.asList(new BPushTaskVO.Operator[]{BPushTaskVO.Operator.startPush});
            case BPushTask
                    .STATE_PUSHING:
                return Arrays.asList(new BPushTaskVO.Operator[]{BPushTaskVO.Operator.pausePush,BPushTaskVO.Operator.cancelPush});
            case BPushTask
                    .STATE_PAUSED:
                return Arrays.asList(new BPushTaskVO.Operator[]{BPushTaskVO.Operator.reStartPush,BPushTaskVO.Operator.cancelPush});
            case BPushTask
                    .STATE_CANCELED:
                return Arrays.asList(new BPushTaskVO.Operator[]{});
            case BPushTask
                    .STATE_FINSIH:
                return Arrays.asList(new BPushTaskVO.Operator[]{});
            default:
                return null;
        }
    }
}
service-push/src/main/java/com/ks/push/vo/BPushTaskFilterVO.java
New file
@@ -0,0 +1,151 @@
package com.ks.push.vo;
import com.ks.push.pojo.DO.BPushFilter;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.TimeUtil;
public class BPushTaskFilterVO {
    private String versionCodeList;
    private String uidList;
    private String deviceList;
    private String brandNameList;
    private String startPushTime;
    private String minActiveTime;
    private String maxActiveTime;
    private String minCreateTime;
    private String maxCreateTime;
    public String getVersionCodeList() {
        return versionCodeList;
    }
    public void setVersionCodeList(String versionCodeList) {
        this.versionCodeList = versionCodeList;
    }
    public String getUidList() {
        return uidList;
    }
    public void setUidList(String uidList) {
        this.uidList = uidList;
    }
    public String getDeviceList() {
        return deviceList;
    }
    public void setDeviceList(String deviceList) {
        this.deviceList = deviceList;
    }
    public String getBrandNameList() {
        return brandNameList;
    }
    public void setBrandNameList(String brandNameList) {
        this.brandNameList = brandNameList;
    }
    public String getStartPushTime() {
        return startPushTime;
    }
    public void setStartPushTime(String startPushTime) {
        this.startPushTime = startPushTime;
    }
    public String getMinActiveTime() {
        return minActiveTime;
    }
    public void setMinActiveTime(String minActiveTime) {
        this.minActiveTime = minActiveTime;
    }
    public String getMaxActiveTime() {
        return maxActiveTime;
    }
    public void setMaxActiveTime(String maxActiveTime) {
        this.maxActiveTime = maxActiveTime;
    }
    public String getMinCreateTime() {
        return minCreateTime;
    }
    public void setMinCreateTime(String minCreateTime) {
        this.minCreateTime = minCreateTime;
    }
    public String getMaxCreateTime() {
        return maxCreateTime;
    }
    public void setMaxCreateTime(String maxCreateTime) {
        this.maxCreateTime = maxCreateTime;
    }
    public static BPushTaskFilterVO create(BPushFilter filter) {
        BPushTaskFilterVO vo = new BPushTaskFilterVO();
        if (filter.getBrandNameList() == null) {
            vo.setBrandNameList("不限");
        } else {
            vo.setBrandNameList(StringUtil.concat(filter.getBrandNameList(), ","));
        }
        if (filter.getDeviceList() == null) {
            vo.setDeviceList("不限");
        } else {
            vo.setDeviceList(StringUtil.concat(filter.getDeviceList(), ","));
        }
        if (filter.getUidList() == null) {
            vo.setUidList("不限");
        } else {
            vo.setUidList(StringUtil.concat(filter.getUidList(), ","));
        }
        if (filter.getVersionCodeList() == null) {
            vo.setVersionCodeList("不限");
        } else {
            vo.setVersionCodeList(StringUtil.concat(filter.getVersionCodeList(), ","));
        }
        if (filter.getMinCreateTime() != null) {
            vo.setMinCreateTime(TimeUtil.getGernalTime(filter.getMinCreateTime().getTime(), "yyyy.MM.dd HH:mm"));
        } else {
            vo.setMinCreateTime("未设置");
        }
        if (filter.getMaxCreateTime() != null) {
            vo.setMaxCreateTime(TimeUtil.getGernalTime(filter.getMaxCreateTime().getTime(), "yyyy.MM.dd HH:mm"));
        } else {
            vo.setMaxCreateTime("未设置");
        }
        if (filter.getMinActiveTime() != null) {
            vo.setMinActiveTime(TimeUtil.getGernalTime(filter.getMinActiveTime().getTime(), "yyyy.MM.dd HH:mm"));
        } else {
            vo.setMinActiveTime("未设置");
        }
        if (filter.getMaxActiveTime() != null) {
            vo.setMaxActiveTime(TimeUtil.getGernalTime(filter.getMaxActiveTime().getTime(), "yyyy.MM.dd HH:mm"));
        } else {
            vo.setMaxActiveTime("未设置");
        }
        if (filter.getStartPushTime() != null) {
            vo.setStartPushTime(TimeUtil.getGernalTime(filter.getStartPushTime().getTime(), "yyyy.MM.dd HH:mm"));
        } else {
            vo.setStartPushTime("未设置");
        }
        return vo;
    }
}
service-push/src/main/java/com/ks/push/vo/BPushTaskVO.java
New file
@@ -0,0 +1,138 @@
package com.ks.push.vo;
import java.util.Date;
import java.util.List;
public class BPushTaskVO {
    private String taskId;
    private String appCode;
    private String title;
    private String content;
    private String state;
    private String stateDesc;
    private Date createTime;
    private Date updateTime;
    //操作
    private List<OperateState> operateStates;
    public String getTaskId() {
        return taskId;
    }
    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }
    public String getAppCode() {
        return appCode;
    }
    public void setAppCode(String appCode) {
        this.appCode = appCode;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public String getStateDesc() {
        return stateDesc;
    }
    public void setStateDesc(String stateDesc) {
        this.stateDesc = stateDesc;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public List<OperateState> getOperateStates() {
        return operateStates;
    }
    public void setOperateStates(List<OperateState> operateStates) {
        this.operateStates = operateStates;
    }
    public static class OperateState {
        private Operator operator;
        private String name;
        //是否有效
        private boolean valid;
        public Operator getOperator() {
            return operator;
        }
        public void setOperator(Operator operator) {
            this.operator = operator;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public boolean isValid() {
            return valid;
        }
        public void setValid(boolean valid) {
            this.valid = valid;
        }
    }
    public static enum Operator {
        startPush("开始推送"),
        pausePush("暂停推送"),
        cancelPush("取消推送"),
        reStartPush("重新开始推送");
        private String name;
        private Operator(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
    }
}
service-push/src/main/resources/mapper/AdminUserMapper.xml
@@ -25,14 +25,6 @@
        where `account` = #{0} limit 1
    </select>
    <select id="selectByAccount" resultMap="BaseResultMap" parameterType="java.lang.String">
        select
        <include refid="Base_Column_List"/>
        from ks_admin
        where account = #{0}
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    delete from ks_admin
    where id = #{id,jdbcType=BIGINT}
service-push/src/main/resources/static/app-add.html
@@ -38,7 +38,7 @@
                <label for="L_appName" class="layui-form-label">
                    <span class="x-red">*</span>应用名称</label>
                <div class="layui-input-inline">
                    <input type="text" id="L_appName" name="appName" required="" lay-verify="username"
                    <input type="text" id="L_appName" name="name" required="" lay-verify="username"
                           autocomplete="off" class="layui-input"></div>
            </div>
@@ -46,7 +46,7 @@
                <label for="L_desc" class="layui-form-label">
                    应用简介</label>
                <div class="layui-input-inline">
                    <textarea id="L_desc" name="appDesc" required="" lay-verify="desc"
                    <textarea id="L_desc" name="desc" required="" lay-verify="desc"
                              autocomplete="off" class="layui-textarea"></textarea></div>
            </div>
service-push/src/main/resources/static/app-list.html
@@ -74,11 +74,7 @@
<script type="text/html" id="deleteContainer">
    <div class="layui-btn-container">
        <a title="恢复" onclick="member_resume(this,{{d.LAY_INDEX }}, {{d.id}})" href="javascript:;">
            <i class="layui-icon">&#xe669;</i>
        </a>
        <a title="删除" onclick="member_del(this,{{d.LAY_INDEX }},{{d.id}})" href="javascript:;"
        <a title="删除" onclick="member_del(this,{{d.LAY_INDEX }},'{{d.appCode}}')" href="javascript:;"
           style="margin-left: 10px;">
            <i class="layui-icon">&#xe640;</i>
        </a>
@@ -99,11 +95,6 @@
    </div>
</script>
<script type="text/html" id="switchTpl">
    <!-- 这里的checked的状态只是演示 -->
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script>layui.use('laydate',
    function () {
        var laydate = layui.laydate;
@@ -130,13 +121,6 @@
        });
    }
    function member_resume(obj, index, id) {
        layer.confirm('确认要恢复吗?', function (index) {
            //发异步删除数据
            // $(obj).parents("tr").remove();
            layer.msg('已恢复!', {icon: 1, time: 1000});
        });
    }
</script>
@@ -172,7 +156,7 @@
                    });
                },
                update: function (id, params) {
                    params.id = id;
                    params.appCode = id;
                    ksapp.post("/admin/api/app/update", params, function (e) {
                        if (e.code == 0) {
                            layer.msg("修改成功");
@@ -201,7 +185,7 @@
            totalRow: true,
            cols: [
                [{type: 'checkbox', title: "ID"},
                    {field: 'id', width: 80, sort: true, title: "ID"},
                    {field: 'appCode', width: 80, sort: true, title: "ID"},
                    {field: 'appCode', width: 120, sort: true, title: "应用唯一标识"},
                    {field: 'name', edit: 'text', width: 150, title: "应用名称"},
                    {field: 'desc', edit: 'text', width: 200, title: "应用简介"},
@@ -218,7 +202,7 @@
                    "code": res.code, //解析接口状态
                    "msg": res.msg, //解析提示文本
                    "count": res.data.count, //解析数据长度
                    "data": res.data.data //解析数据列表
                    "data": res.data.list //解析数据列表
                };
            }
            //,…… //其他参数
@@ -230,10 +214,11 @@
                var value = obj.value, //得到修改后的值
                    data = obj.data, //得到所在行所有键值
                    field = obj.field; //得到字段
                console.log(data);
                //修改接口
                var params = {id: data.id};
                var params = {id: data.appCode};
                params[field] = value;
                app.update(data.id, params);
                app.update(data.appCode, params);
            });
        //头工具栏事件
service-push/src/main/resources/static/index.html
@@ -92,25 +92,30 @@
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>应用列表</cite></a>
                    </li>
                    <li>
                        <a onclick="xadmin.add_tab('三方平台','pushplatform-appinfo-list.html',true)">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>三方推送平台应用信息</cite></a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="javascript:;">
                    <i class="iconfont left-nav-li" lay-tips="来源管理">&#xe6b8;</i>
                    <cite>来源管理</cite>
                    <i class="iconfont left-nav-li" lay-tips="推送">&#xe6b8;</i>
                    <cite>推送任务</cite>
                    <i class="iconfont nav_right">&#xe697;</i></a>
                <ul class="sub-menu">
                    <li>
                        <a onclick="xadmin.add_tab('获取来源列表','source-get-list.html')">
                        <a onclick="xadmin.add_tab('推送任务列表','pushtask-list.html')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>获取来源列表</cite></a>
                            <cite>推送任务列表</cite></a>
                    </li>
                    <li>
                        <a onclick="xadmin.add_tab('消耗来源列表','source-consume-list.html')">
                        <a onclick="xadmin.add_tab('添加推送任务','pushplatform-appinfo-list.html')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>消耗来源列表</cite></a>
                            <cite>添加推送任务</cite></a>
                    </li>
                </ul>
            </li>
service-push/src/main/resources/static/js/http.js
@@ -1,35 +1,49 @@
var ksapp = {
    post: function(url, params, success, fail) {
        $.post({
            url: url,
            data: params,
            dataType:'json',
            success: function(data) {
                success(data);
            },
            fail: function(result) {
                fail(result);
            }
        });
    },
    get:function(params){
    post: function (url, params, success, fail) {
        $.post({
            url: url,
            data: params,
            dataType: 'json',
            success: function (data) {
                success(data);
            },
            fail: function (result) {
                fail(result);
            }
        });
    },
    postJSON: function (url, params, success, fail) {
        $.post({
            url: url,
            data: JSON.stringify(params),
            dataType: 'json',
            contentType: "application/json",
            success: function (data) {
                success(data);
            },
            fail: function (result) {
                fail(result);
            }
        });
    },
    get: function (params) {
        $.get({
            url: params.url,
            data: params.params,
            success: function(data) {
            success: function (data) {
                params.success(data);
            },
            fail: function(result) {
            fail: function (result) {
                params.fail(result);
            }
        });
    },
    getQueryParam:function(key){
    },
    getQueryParam: function (key) {
        var reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)", "i");
        var r = window.location.search.substr(1).match(reg);
        if (r != null) return decodeURIComponent(r[2]);
        return null;
    }
    }
};
service-push/src/main/resources/static/js/utils.js
New file
@@ -0,0 +1,65 @@
const formUtil = {
    /**
     * 将表单转为对象
     * @param fileds
     */
    formFieldsToJSON: function (fileds) {
        var finalResult = {};
        for (key in fileds) {
            var obj = {};
            obj[key] = fileds[key];
            var tempResult = this.formFieldToJSON(obj);
            var keys = new Array();
            while (Object.prototype.toString.call(tempResult) === '[object Object]') {
                var key = Object.keys(tempResult)[0];
                keys.push(key);
                tempResult = tempResult[key];
            }
            var temp = "finalResult";
            for (var i = 0; i < keys.length; i++) {
                temp += "['" + keys[i] + "']";
                if (i != keys.length - 1) {
                    if (eval(temp + "==undefined") == true) {
                        eval(temp + "={}");
                    }
                } else {
                    eval(temp + "=" + (isNaN(tempResult) ? "'" + tempResult + "'" : tempResult));
                }
            }
        }
        return finalResult;
    },
    formFieldToJSON: function (field) {
        var key = Object.keys(field)[0];
        var value = field[key];
        var keys = key.split(".");
        if (keys.length > 1) {
            var newValue = {};
            var k = keys[keys.length - 1];
            keys.splice(keys.length - 1, 1);
            newValue[k] = value;
            var final = {};
            final[keys.join(".")] = newValue;
            return this.formFieldToJSON(final);
        } else {
            return field;
        }
    },
    jsonToFormField: function (data) {
        var result = {};
        for (key in data) {
            if (Object.prototype.toString.call(data[key]) === '[object Object]') {
                for (ckey in data[key]) {
                    result[key + "." + ckey] = data[key][ckey];
                }
            } else {
                result[key] = data[key];
            }
        }
        return result;
    }
};
service-push/src/main/resources/static/pushplatform-appinfo-add.html
File was renamed from service-push/src/main/resources/static/source-get-add.html
@@ -3,7 +3,7 @@
<head>
    <meta charset="UTF-8">
    <title>欢迎页面-X-admin2.2</title>
    <title>新增推送平台参数</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
@@ -31,77 +31,52 @@
                <div class="layui-input-inline">
                    <select id="L_appCode" name="appCode" lay-verify="required" lay-search="">
                        <option value="">直接选择或搜索应用</option>
                        <option v-for="item in appList" :value="item.appCode">{{item.appName}}</option>
                        <option v-for="item in appList" :value="item.appCode">{{item.name}}</option>
                    </select>
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_name" class="layui-form-label">
                    <span class="x-red">*</span>来源名称</label>
                <label for="L_appCode" class="layui-form-label">
                    <span class="x-red">*</span>推送平台</label>
                <div class="layui-input-inline">
                    <input type="text" id="L_name" name="sourceName" required="" lay-verify="username"
                    <select id="L_appCode" name="platform" lay-verify="required" lay-search="">
                        <option v-for="item in platformList" :value="item.platform">{{item.name}}</option>
                    </select>
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_code" class="layui-form-label">
                    <span class="x-red">*</span>appId</label>
                <div class="layui-input-inline">
                    <input type="text" id="L_code" name="pushAppInfo.appId" lay-verify="code"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label for="L_code" class="layui-form-label">
                    <span class="x-red">*</span>来源标识</label>
                    <span class="x-red">*</span>appKey</label>
                <div class="layui-input-inline">
                    <input type="text" id="L_code" name="sourceCode" required="" lay-verify="code"
                           autocomplete="off" class="layui-input"></div>
                <div class="layui-form-mid layui-word-aux">
                    <span class="x-red">*</span>同一应用不能重复
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">
                    图标</label>
                <div class="layui-input-inline">
                    <input type="text" name="icon"
                    <input type="text" id="L_code" name="pushAppInfo.appKey" lay-verify="code"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">
                    <span class="x-red">*</span>金币数量</label>
                <label for="L_code" class="layui-form-label">
                    <span class="x-red">*</span>appSecret</label>
                <div class="layui-input-inline">
                    <input type="text" name="goldCorn" required="" lay-verify="number"
                    <input type="text" id="L_code" name="pushAppInfo.appSecret"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">
                    <span class="x-red">*</span>每日获取最大次数</label>
                <label for="L_code" class="layui-form-label">
                    <span class="x-red">*</span>包名</label>
                <div class="layui-input-inline">
                    <input type="text" name="maxDayCount" required="" lay-verify="number"
                    <input type="text" id="L_code" name="pushAppInfo.packageName" required="" lay-verify="packageName"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">
                    <span class="x-red">*</span>每次间隔时间(秒)</label>
                <div class="layui-input-inline">
                    <input type="text" name="minTimeSpan" required="" lay-verify="number"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label for="L_desc" class="layui-form-label">
                    来源简介</label>
                <div class="layui-input-inline">
                    <textarea id="L_desc" name="sourceDesc" required="" lay-verify="desc"
                              autocomplete="off" class="layui-textarea"></textarea></div>
            </div>
            <div class="layui-form-item">
                <label for="L_remarks" class="layui-form-label">
                    来源备注</label>
                <div class="layui-input-inline">
                    <textarea type="text" id="L_remarks" name="remarks" required="" lay-verify="remarks"
                              autocomplete="off" class="layui-textarea"></textarea></div>
            </div>
            <div class="layui-form-item">
@@ -116,7 +91,14 @@
    var app = new Vue({
        el: '.layui-form',
        data: {
            appList: []
            appList: [],
            platformList: [
                {name: "小米", platform: "xm"},
                {name: "华为", platform: "hw"},
                {name: "OPPO", platform: "oppo"},
                {name: "VIVO", platform: "vivo"},
                {name: "魅族", platform: "mz"}
            ]
        },
        created: function () {
            this.getAppList();
@@ -125,12 +107,13 @@
            appList: function () {
                app.render();
            }
        },
        methods: {
            getAppList: function () {
                ksapp.post("/admin/api/app/list", {page: 1, limit: 100}, function (e) {
                    if (e.code == 0) {
                        app.appList = e.data.data;
                        app.appList = e.data.list;
                    } else
                        layer.msg(e.msg);
                }, function (e) {
@@ -150,7 +133,14 @@
                                return '名称至少得3个字符';
                            }
                        },
                        code: [/^([A-Za-z0-9]|\-|_)+$/, '标识只能包含 数字、英文字符、_ 、-'],
                        code: function (value) {
                            if (value) {
                                if (!(/^([A-Za-z0-9]|\-|_)+$/).test(value)) {
                                    return '标识只能包含 数字、英文字符、_ 、-';
                                }
                            }
                        },
                        packageName: [/^([A-Za-z0-9]|\-|_|\.)+$/, '包名只能包含 数字、英文字符、_ 、-、.'],
                        desc: function (value) {
                            if (value != null && value.length > 128) {
                                return '简介最大为128个字符';
@@ -169,8 +159,21 @@
                    form.on('submit(add)',
                        function (data) {
                            console.log(data.field);
                            //转换json对象
                            for (key in data.field) {
                                if (key.indexOf(".") > -1) {
                                    var value = data.field[key];
                                    delete data.field[key];
                                    var onkeys = key.split(".");
                                    //创建对象
                                    if (data.field[onkeys[0]] == undefined) {
                                        data.field[onkeys[0]] = {};
                                    }
                                    data.field[onkeys[0]][onkeys[1]] = value;
                                }
                            }
                            //发异步,把数据提交给php
                            ksapp.post('/admin/api/source/get/add', data.field, function (res) {
                            ksapp.postJSON('/admin/api/pushplatform-app/add', data.field, function (res) {
                                if (res.code == 0) {
                                    layer.alert("增加成功", {
                                            icon: 6
service-push/src/main/resources/static/pushplatform-appinfo-list.html
File was renamed from service-push/src/main/resources/static/source-get-list.html
@@ -20,6 +20,18 @@
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="./js/utils.js"></script>
    <script>
        var form = {
            "app.id": 123,
            "app.name": "测试",
            id: 12312312,
            name: "测试123"
        };
        var obj = formUtil.formFieldsToJSON(form);
        console.log(JSON.stringify(obj));
    </script>
</head>
<body>
@@ -27,7 +39,7 @@
            <span class="layui-breadcrumb">
                <a href="">来源管理</a>
                <a>
                    <cite>获取来源列表</cite></a>
                    <cite>三方推送平台应用信息</cite></a>
            </span>
    <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right"
       onclick="location.reload()" title="刷新">
@@ -51,7 +63,7 @@
                        <div class="layui-inline layui-show-xs-block">
                            <select name="appCode" lay-verify="required" lay-search="">
                                <option value="">直接选择或搜索应用</option>
                                <option v-for="item in appList" :value="item.appCode">{{item.appName}}</option>
                                <option v-for="item in appList" :value="item.appCode">{{item.name}}</option>
                            </select>
                        </div>
@@ -75,7 +87,7 @@
</body>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn" onclick="xadmin.open('添加来源','./source-get-add.html',500,580)"><i
        <button class="layui-btn" onclick="xadmin.open('添加推送平台应用信息','./pushplatform-appinfo-add.html',500,580)"><i
                class="layui-icon"></i>添加
        </button>
@@ -92,7 +104,7 @@
        <!--<i class="layui-icon">&#xe669;</i>-->
        <!--</a>-->
        <a title="删除" onclick="member_del(this,{{d.LAY_INDEX }},{{d.id}})" href="javascript:;">
        <a title="删除" onclick="member_del(this,{{d.LAY_INDEX }},'{{d.id}}')" href="javascript:;">
            <i class="layui-icon">&#xe640;</i>
        </a>
    </div>
@@ -143,13 +155,6 @@
        });
    }
    function member_resume(obj, index, id) {
        layer.confirm('确认要恢复吗?', function (index) {
            //发异步删除数据
            // $(obj).parents("tr").remove();
            layer.msg('已恢复!', {icon: 1, time: 1000});
        });
    }
</script>
<script>
@@ -185,7 +190,7 @@
                    });
                },
                deleteList: function (ids, success) {
                    ksapp.post("/admin/api/source/get/delete", {ids: JSON.stringify(ids)}, function (e) {
                    ksapp.post("/admin/api/pushplatform-app/delete", {ids: JSON.stringify(ids)}, function (e) {
                        if (e.code == 0) {
                            success();
                        } else {
@@ -196,7 +201,7 @@
                },
                update: function (id, params) {
                    params.id = id;
                    ksapp.post("/admin/api/source/get/update", params, function (e) {
                    ksapp.postJSON("/admin/api/pushplatform-app/update", params, function (e) {
                        if (e.code == 0) {
                            layer.msg("修改成功");
                        } else
@@ -208,7 +213,7 @@
                getAppList: function () {//应用列表
                    ksapp.post("/admin/api/app/list", {page: 1, limit: 100}, function (e) {
                        if (e.code == 0) {
                            app.appList = e.data.data;
                            app.appList = e.data.list;
                            layui.use("form", function (e) {
                                var form = layui.form;
                                form.render();
@@ -243,7 +248,7 @@
                        app.start = ksapp.getQueryParam("start");
                        app.end = ksapp.getQueryParam("end");
                        var table = layui.table;
                        var url = "/admin/api/source/get/list";
                        var url = "/admin/api/pushplatform-app/list";
                        tableIns = table.render({
                            elem: '#table_list',
                            url: url,
@@ -251,23 +256,31 @@
                            totalRow: true,
                            cols: [
                                [{type: 'checkbox', title: "ID"},
                                    {field: 'id', width: 80, sort: true, title: "ID"},
                                    {field: 'icon', templet:'#iconTpl', edit: 'text', sort: true, width: 150, title: "图标"},
                                    {field: 'sourceName', edit: 'text', sort: true, width: 150, title: "来源名称"},
                                    {field: 'sourceCode', edit: 'text', sort: true, width: 120, title: "来源标识"},
                                    {field: 'state', edit: 'text',templet:'#stateTpl', sort: true, width: 120, title: "状态"},
                                    {field: 'weight', edit: 'text', sort: true, width: 80, title: "权重"},
                                    {field: 'goldCorn', edit: 'text', sort: true, width: 100, title: "金币数量"},
                                    {field: 'maxDayCount', edit: 'text', sort: true, width: 100, title: "每日最大次数"},
                                    {field: 'minTimeSpan', edit: 'text', sort: true, width: 100, title: "每次间隔时间(秒)"},
                                    {field: 'sourceDesc', edit: 'text', width: 200, title: "来源简介"},
                                    {field: 'remarks', edit: 'text', width: 200, title: "备注"},
                                    {field: 'createTime', sort: true, width: 150, title: "创建时间"},
                                    {field: 'updateTime', sort: true, width: 150, title: "修改时间"},
                                    {field: 'id', width: 120, sort: true, title: "ID"},
                                    {field: 'appCode', width: 120, title: "应用标识"},
                                    {field: 'appName', width: 120, title: "应用名称"},
                                    // {field: 'status', width: 80, title: "状态", templet: "#statusContainer"},
                                    {fixed: 'right', width: 150, title: "操作", toolbar: '#deleteContainer'},
                                    {field: 'platform', width: 80, title: "推送平台"},
                                    {
                                        field: "pushAppInfo.appId",
                                        edit: 'text',
                                        width: 200,
                                        title: "appId"
                                    },
                                    {
                                        field: 'pushAppInfo.appKey',
                                        edit: 'text',
                                        width: 120,
                                        title: "appKey"
                                    },
                                    {
                                        field: 'pushAppInfo.appSecret',
                                        edit: 'text',
                                        width: 200,
                                        title: "appSecret"
                                    },
                                    {field: 'pushAppInfo.packageName', edit: 'text', width: 120, title: "包名"},
                                    {field: 'createTime', sort: true, width: 140, title: "创建时间"},
                                    {field: 'updateTime', sort: true, width: 140, title: "修改时间"},
                                    {fixed: 'right', width: 80, title: "操作", toolbar: '#deleteContainer'},
                                ]
                            ],
@@ -275,18 +288,25 @@
                            parseData: function (res) { //res 即为原始返回的数据
                                if (res.code != 0)
                                    return;
                                if( res.data.data==null)
                                if (res.data.list == null)
                                    return;
                                for (var i = 0; i < res.data.data.length; i++) {
                                    res.data.data[i].appName = res.data.data[i].app.appName;
                                    res.data.data[i].appCode = res.data.data[i].app.appCode;
                                for (var i = 0; i < res.data.list.length; i++) {
                                    //将对象转换为属性
                                    var pushAppInfo = res.data.list[i].pushAppInfo;
                                    delete   res.data.list[i].pushAppInfo;
                                    for (key in pushAppInfo) {
                                        res.data.list[i]["pushAppInfo." + key] = pushAppInfo[key];
                                    }
                                }
                                console.log(res.data.list)
                                return {
                                    "code": res.code, //解析接口状态
                                    "msg": res.msg, //解析提示文本
                                    "count": res.data.count, //解析数据长度
                                    "data": res.data.data //解析数据列表
                                    "data": res.data.list //解析数据列表
                                };
                            }
                            //,…… //其他参数
@@ -299,7 +319,12 @@
                                    field = obj.field; //得到字段
                                //修改接口
                                var params = {id: data.id};
                                params[field] = value;
                                if (field.indexOf(".") > -1) {
                                    var keys = field.split(".");
                                    params[keys[0]] = {};
                                    params[keys[0]][keys[1]] = value;
                                } else
                                    params[field] = value;
                                app.update(data.id, params);
                            });
@@ -337,22 +362,7 @@
</script>
<script>
<script type="text/html" id="iconTpl">
    {{#  if(d.icon ){ }}
    <img src="{{d.icon}}" style="height:100%;" />
    {{#  } else { }}
    {{#  } }}
</script>
<script type="text/html" id="stateTpl">
    {{#  if(d.state==1 ){ }}
    <span>外显</span>
    {{#  } else if(d.state==2) { }}
    <span>不外显</span>
    {{#  } else { }}
    <span>禁用</span>
    {{#  } }}
</script>
</html>
service-push/src/main/resources/static/pushtask-add.html
copy from service-push/src/main/resources/static/source-get-add.html copy to service-push/src/main/resources/static/pushtask-add.html
File was copied from service-push/src/main/resources/static/source-get-add.html
@@ -3,7 +3,7 @@
<head>
    <meta charset="UTF-8">
    <title>欢迎页面-X-admin2.2</title>
    <title>新增推送平台参数</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
@@ -31,77 +31,52 @@
                <div class="layui-input-inline">
                    <select id="L_appCode" name="appCode" lay-verify="required" lay-search="">
                        <option value="">直接选择或搜索应用</option>
                        <option v-for="item in appList" :value="item.appCode">{{item.appName}}</option>
                        <option v-for="item in appList" :value="item.appCode">{{item.name}}</option>
                    </select>
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_name" class="layui-form-label">
                    <span class="x-red">*</span>来源名称</label>
                <label for="L_appCode" class="layui-form-label">
                    <span class="x-red">*</span>推送平台</label>
                <div class="layui-input-inline">
                    <input type="text" id="L_name" name="sourceName" required="" lay-verify="username"
                    <select id="L_appCode" name="platform" lay-verify="required" lay-search="">
                        <option v-for="item in platformList" :value="item.platform">{{item.name}}</option>
                    </select>
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_code" class="layui-form-label">
                    <span class="x-red">*</span>appId</label>
                <div class="layui-input-inline">
                    <input type="text" id="L_code" name="pushAppInfo.appId" lay-verify="code"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label for="L_code" class="layui-form-label">
                    <span class="x-red">*</span>来源标识</label>
                    <span class="x-red">*</span>appKey</label>
                <div class="layui-input-inline">
                    <input type="text" id="L_code" name="sourceCode" required="" lay-verify="code"
                           autocomplete="off" class="layui-input"></div>
                <div class="layui-form-mid layui-word-aux">
                    <span class="x-red">*</span>同一应用不能重复
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">
                    图标</label>
                <div class="layui-input-inline">
                    <input type="text" name="icon"
                    <input type="text" id="L_code" name="pushAppInfo.appKey" lay-verify="code"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">
                    <span class="x-red">*</span>金币数量</label>
                <label for="L_code" class="layui-form-label">
                    <span class="x-red">*</span>appSecret</label>
                <div class="layui-input-inline">
                    <input type="text" name="goldCorn" required="" lay-verify="number"
                    <input type="text" id="L_code" name="pushAppInfo.appSecret"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">
                    <span class="x-red">*</span>每日获取最大次数</label>
                <label for="L_code" class="layui-form-label">
                    <span class="x-red">*</span>包名</label>
                <div class="layui-input-inline">
                    <input type="text" name="maxDayCount" required="" lay-verify="number"
                    <input type="text" id="L_code" name="pushAppInfo.packageName" required="" lay-verify="packageName"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">
                    <span class="x-red">*</span>每次间隔时间(秒)</label>
                <div class="layui-input-inline">
                    <input type="text" name="minTimeSpan" required="" lay-verify="number"
                           autocomplete="off" class="layui-input"></div>
            </div>
            <div class="layui-form-item">
                <label for="L_desc" class="layui-form-label">
                    来源简介</label>
                <div class="layui-input-inline">
                    <textarea id="L_desc" name="sourceDesc" required="" lay-verify="desc"
                              autocomplete="off" class="layui-textarea"></textarea></div>
            </div>
            <div class="layui-form-item">
                <label for="L_remarks" class="layui-form-label">
                    来源备注</label>
                <div class="layui-input-inline">
                    <textarea type="text" id="L_remarks" name="remarks" required="" lay-verify="remarks"
                              autocomplete="off" class="layui-textarea"></textarea></div>
            </div>
            <div class="layui-form-item">
@@ -116,7 +91,14 @@
    var app = new Vue({
        el: '.layui-form',
        data: {
            appList: []
            appList: [],
            platformList: [
                {name: "小米", platform: "xm"},
                {name: "华为", platform: "hw"},
                {name: "OPPO", platform: "oppo"},
                {name: "VIVO", platform: "vivo"},
                {name: "魅族", platform: "mz"}
            ]
        },
        created: function () {
            this.getAppList();
@@ -125,12 +107,13 @@
            appList: function () {
                app.render();
            }
        },
        methods: {
            getAppList: function () {
                ksapp.post("/admin/api/app/list", {page: 1, limit: 100}, function (e) {
                    if (e.code == 0) {
                        app.appList = e.data.data;
                        app.appList = e.data.list;
                    } else
                        layer.msg(e.msg);
                }, function (e) {
@@ -150,7 +133,14 @@
                                return '名称至少得3个字符';
                            }
                        },
                        code: [/^([A-Za-z0-9]|\-|_)+$/, '标识只能包含 数字、英文字符、_ 、-'],
                        code: function (value) {
                            if (value) {
                                if (!(/^([A-Za-z0-9]|\-|_)+$/).test(value)) {
                                    return '标识只能包含 数字、英文字符、_ 、-';
                                }
                            }
                        },
                        packageName: [/^([A-Za-z0-9]|\-|_|\.)+$/, '包名只能包含 数字、英文字符、_ 、-、.'],
                        desc: function (value) {
                            if (value != null && value.length > 128) {
                                return '简介最大为128个字符';
@@ -169,8 +159,21 @@
                    form.on('submit(add)',
                        function (data) {
                            console.log(data.field);
                            //转换json对象
                            for (key in data.field) {
                                if (key.indexOf(".") > -1) {
                                    var value = data.field[key];
                                    delete data.field[key];
                                    var onkeys = key.split(".");
                                    //创建对象
                                    if (data.field[onkeys[0]] == undefined) {
                                        data.field[onkeys[0]] = {};
                                    }
                                    data.field[onkeys[0]][onkeys[1]] = value;
                                }
                            }
                            //发异步,把数据提交给php
                            ksapp.post('/admin/api/source/get/add', data.field, function (res) {
                            ksapp.postJSON('/admin/api/pushplatform-app/add', data.field, function (res) {
                                if (res.code == 0) {
                                    layer.alert("增加成功", {
                                            icon: 6
service-push/src/main/resources/static/pushtask-list.html
File was renamed from service-push/src/main/resources/static/source-consume-list.html
@@ -20,6 +20,18 @@
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="./js/utils.js"></script>
    <script>
        var form = {
            "app.id": 123,
            "app.name": "测试",
            id: 12312312,
            name: "测试123"
        };
        var obj = formUtil.formFieldsToJSON(form);
        console.log(JSON.stringify(obj));
    </script>
</head>
<body>
@@ -27,7 +39,7 @@
            <span class="layui-breadcrumb">
                <a href="">来源管理</a>
                <a>
                    <cite>消耗来源列表</cite></a>
                    <cite>三方推送平台应用信息</cite></a>
            </span>
    <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right"
       onclick="location.reload()" title="刷新">
@@ -51,12 +63,12 @@
                        <div class="layui-inline layui-show-xs-block">
                            <select name="appCode" lay-verify="required" lay-search="">
                                <option value="">直接选择或搜索应用</option>
                                <option v-for="item in appList" :value="item.appCode">{{item.appName}}</option>
                                <option v-for="item in appList" :value="item.appCode">{{item.name}}</option>
                            </select>
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                            <input type="text" name="key" placeholder="请输入应用名称" :value="key" autocomplete="off"
                            <input type="text" name="key" placeholder="请输入推送标题" :value="key" autocomplete="off"
                                   class="layui-input"></div>
                        <div class="layui-inline layui-show-xs-block">
                            <button class="layui-btn" lay-submit="" lay-filter="sreach">
@@ -75,26 +87,29 @@
</body>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn" onclick="xadmin.open('添加来源','./source-consume-add.html',500,580)"><i
                class="layui-icon"></i>添加
        </button>
        <button class="layui-btn layui-btn-danger" lay-event="delete">
            <i class="layui-icon">&#xe640;</i>
            删除
        </button>
    </div>
</script>
<script type="text/html" id="deleteContainer">
    <div class="layui-btn-container">
        <!-- <a title='恢复' onclick='member_resume(this,{{d.LAY_INDEX }}, {{d.id}})' href='javascript:;'> -->
        <!--<i class="layui-icon">&#xe669;</i>-->
        <!--</a>-->
        <a title="删除" onclick="member_del(this,{{d.LAY_INDEX }},{{d.id}})" href="javascript:;">
            <i class="layui-icon">&#xe640;</i>
        </a>
        <ul class="layui-nav left fast-add" lay-filter="">
            <li class="layui-nav-item">
                <a href="javascript:;">操作</a>
                <dl class="layui-nav-child">
                    <!-- 二级菜单 -->
                    {{# layui.each(d.operateStates, function(index, item){ console.log(d.operateStates) ;}}
                    <dd>
                        {{# if(item.invalid) { }}
                        <a class="layui-btn layui-btn-xs" lay-event="check">{{ item.name }}</a>
                        {{# } else { }}
                        <a class="layui-btn layui-btn-xs layui-btn-disabled" lay-event="check">{{ item.name }}</a>
                        {{# } }}
                    </dd>
                    {{# }); }}
                </dl>
            </li>
        </ul>
    </div>
</script>
@@ -143,13 +158,6 @@
        });
    }
    function member_resume(obj, index, id) {
        layer.confirm('确认要恢复吗?', function (index) {
            //发异步删除数据
            // $(obj).parents("tr").remove();
            layer.msg('已恢复!', {icon: 1, time: 1000});
        });
    }
</script>
<script>
@@ -185,7 +193,7 @@
                    });
                },
                deleteList: function (ids, success) {
                    ksapp.post("/admin/api/source/consume/delete", {ids: JSON.stringify(ids)}, function (e) {
                    ksapp.post("/admin/api/pushplatform-app/delete", {ids: JSON.stringify(ids)}, function (e) {
                        if (e.code == 0) {
                            success();
                        } else {
@@ -196,7 +204,7 @@
                },
                update: function (id, params) {
                    params.id = id;
                    ksapp.post("/admin/api/source/consume/update", params, function (e) {
                    ksapp.postJSON("/admin/api/pushplatform-app/update", params, function (e) {
                        if (e.code == 0) {
                            layer.msg("修改成功");
                        } else
@@ -208,7 +216,7 @@
                getAppList: function () {//应用列表
                    ksapp.post("/admin/api/app/list", {page: 1, limit: 100}, function (e) {
                        if (e.code == 0) {
                            app.appList = e.data.data;
                            app.appList = e.data.list;
                            layui.use("form", function (e) {
                                var form = layui.form;
                                form.render();
@@ -243,7 +251,7 @@
                        app.start = ksapp.getQueryParam("start");
                        app.end = ksapp.getQueryParam("end");
                        var table = layui.table;
                        var url = "/admin/api/source/consume/list";
                        var url = "/admin/api/pushtask/list";
                        tableIns = table.render({
                            elem: '#table_list',
                            url: url,
@@ -251,18 +259,31 @@
                            totalRow: true,
                            cols: [
                                [{type: 'checkbox', title: "ID"},
                                    {field: 'id', width: 80, sort: true, title: "ID"},
                                    {field: 'id', width: 120, sort: true, title: "ID"},
                                    {field: 'appCode', width: 120, title: "应用标识"},
                                    {field: 'appName', width: 120, title: "应用名称"},
                                    {field: 'sourceName', edit: 'text', sort: true, width: 150, title: "来源名称"},
                                    {field: 'sourceCode', edit: 'text', sort: true, width: 120, title: "来源标识"},
                                    {field: 'goldCorn', edit: 'text', sort: true, width: 100, title: "金币数量"},
                                    {field: 'sourceDesc', edit: 'text', width: 200, title: "来源简介"},
                                    {field: 'remarks', edit: 'text', width: 200, title: "备注"},
                                    {field: 'createTime', sort: true, width: 150, title: "创建时间"},
                                    {field: 'updateTime', sort: true, width: 150, title: "修改时间"},
                                    // {field: 'status', width: 80, title: "状态", templet: "#statusContainer"},
                                    {fixed: 'right', width: 150, title: "操作", toolbar: '#deleteContainer'},
                                    {
                                        field: "title",
                                        width: 200,
                                        title: "标题"
                                    },
                                    {
                                        field: 'content',
                                        width: 120,
                                        title: "内容"
                                    },
                                    {
                                        field: 'state',
                                        width: 120,
                                        title: "状态"
                                    },
                                    {
                                        field: 'stateDesc',
                                        width: 120,
                                        title: "状态描述"
                                    },
                                    {field: 'createTime', sort: true, width: 140, title: "创建时间"},
                                    {field: 'updateTime', sort: true, width: 140, title: "修改时间"},
                                    {fixed: 'right', width: 80, title: "操作", toolbar: '#deleteContainer'},
                                ]
                            ],
@@ -270,18 +291,14 @@
                            parseData: function (res) { //res 即为原始返回的数据
                                if (res.code != 0)
                                    return;
                                if( res.data.data==null)
                                if (res.data.list == null)
                                    return;
                                for (var i = 0; i < res.data.data.length; i++) {
                                    res.data.data[i].appName = res.data.data[i].app.appName;
                                    res.data.data[i].appCode = res.data.data[i].app.appCode;
                                }
                                console.log(res.data.list)
                                return {
                                    "code": res.code, //解析接口状态
                                    "msg": res.msg, //解析提示文本
                                    "count": res.data.count, //解析数据长度
                                    "data": res.data.data //解析数据列表
                                    "data": res.data.list //解析数据列表
                                };
                            }
                            //,…… //其他参数
@@ -294,7 +311,12 @@
                                    field = obj.field; //得到字段
                                //修改接口
                                var params = {id: data.id};
                                params[field] = value;
                                if (field.indexOf(".") > -1) {
                                    var keys = field.split(".");
                                    params[keys[0]] = {};
                                    params[keys[0]][keys[1]] = value;
                                } else
                                    params[field] = value;
                                app.update(data.id, params);
                            });
service-push/src/main/resources/static/source-consume-add.html
File was deleted
service-push/src/test/java/com/ks/push/TaskTest.java
New file
@@ -0,0 +1,40 @@
package com.ks.push;
import com.ks.push.exception.BPushTaskException;
import com.ks.push.pojo.DO.BPushFilter;
import com.ks.push.pojo.DO.BPushMessage;
import com.ks.push.pojo.DO.BPushTask;
import com.ks.push.service.BPushTaskService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import javax.annotation.Resource;
import java.util.Arrays;
@SpringBootTest(classes = PushApplication.class)
@ContextConfiguration
public class TaskTest {
    @Resource
    private BPushTaskService bPushTaskService;
    @Test
    public void addTask() throws BPushTaskException {
        BPushTask task = new BPushTask();
        BPushMessage message = new BPushMessage();
        message.setTitle("测试标题");
        message.setContent("测试内容");
        message.setAndroidActivity("com.tejia.lijin.app.ui.PushOpenClickActivity");
        message.setAndroidHostPath("com.huawei.codelabpush/deeplink");
        message.setAndroidActivityScheme("tejiapush");
        BPushFilter filter = new BPushFilter();
        filter.setUidList(Arrays.asList(new String[]{"123456"}));
        task.setMessage(message);
        task.setAppCode("tejia");
        task.setFilter(filter);
        bPushTaskService.createTask(task);
    }
}