zyy
2025-07-18 96e443a77b1d425d3e536c288fc271fe182f1496
app股票列表修改
14 files modified
1 files added
320 ■■■■ changed files
src/main/java/com/nq/controller/backend/AdminStockAiController.java 7 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/controller/protol/UserPositionController.java 21 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/dao/StockAiOrderPositionMapper.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/dao/UserPositionMapper.java 9 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/StockAIOrder.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/StockAIOrderPosition.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/UserPosition.java 7 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/IUserPositionService.java 9 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/StockAiServiceImpl.java 6 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/StockServiceImpl.java 10 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserPositionServiceImpl.java 76 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/utils/UserPointUtil.java 54 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/vo/position/UserPositionVO.java 5 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/StockAiOrderPositionMapper.xml 22 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/UserPositionMapper.xml 80 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/controller/backend/AdminStockAiController.java
@@ -101,14 +101,17 @@
     /**
      * 根据条件查询股票code 名称 或 spell
      * 根据条件查询股票
      * @param pageNum
      * @param pageSize
      * @param keyWords     code 名称 或 spell
      * @return
      */
     @PostMapping({"getStocksByKeyWords.do"})
     @ResponseBody
     public ServerResponse getStocksByKeyWords(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
                                               @RequestParam(value = "pageSize", defaultValue = "5") int pageSize,
                                               @RequestParam(value = "keyWords") String keyWords) {
                                               @RequestParam(value = "keyWords", required = false) String keyWords) {
         return stockService.getStocksByKeyWords(pageNum, pageSize, keyWords);
     }
 }
src/main/java/com/nq/controller/protol/UserPositionController.java
@@ -20,18 +20,35 @@
     @Autowired
     IUserPositionService iUserPositionService;
     //查询所有融资平仓/持仓信息
     /*//查询所有融资平仓/持仓信息
     @RequestMapping({"list.do"})
     @ResponseBody
     public ServerResponse list(HttpServletRequest request,
                                @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
                                @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
                                @RequestParam(value = "state", required = false) Integer state,
                                @RequestParam(value = "state", defaultValue = "0") Integer state,
                                @RequestParam(value = "stockCode", required = false) String stockCode,
                                @RequestParam(value = "stockSpell", required = false) String stockSpell,
                                @RequestParam(value = "stockType", required = false) String stockType
                                ) {
         return this.iUserPositionService.findMyPositionByCodeAndSpell(stockCode, stockSpell, state, request, pageNum, pageSize,stockType);
     }*/
     /**
      * 查询所有融资平仓/持仓信息
      * @param positionType   //0正常股票 2.新股 3.大宗 4.ai交易
      */
     @RequestMapping({"list.do"})
     @ResponseBody
     public ServerResponse findMyPositionByParam(HttpServletRequest request,
                                @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
                                @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
                                @RequestParam(value = "state", defaultValue = "0") Integer state,
                                @RequestParam(value = "stockCode", required = false) String stockCode,
                                @RequestParam(value = "stockSpell", required = false) String stockSpell,
                                @RequestParam(value = "stockType", required = false) String stockType,
                                @RequestParam(value = "positionType", required = false) Integer positionType) {
         return this.iUserPositionService.findMyPositionByParam(stockCode, stockSpell, state, request, pageNum, pageSize,stockType, positionType);
     }
     //查询账户市值和持仓收益
src/main/java/com/nq/dao/StockAiOrderPositionMapper.java
@@ -2,9 +2,17 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nq.pojo.StockAIOrderPosition;
import com.nq.vo.position.UserPositionVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface StockAiOrderPositionMapper extends BaseMapper<StockAIOrderPosition> {
    int updateStatusByOrderId(@Param("stockAiOrderId") Integer stockAiOrderId, @Param("status") Integer status);
    List<UserPositionVO> getAiPositionList(@Param("userId") Integer userId, @Param("status") Integer status);
}
src/main/java/com/nq/dao/UserPositionMapper.java
@@ -6,6 +6,7 @@
import java.util.Date;
import java.util.List;
import com.nq.vo.position.UserPositionVO;
import org.apache.ibatis.annotations.Param;
public interface UserPositionMapper extends BaseMapper<UserPosition> {
@@ -23,11 +24,17 @@
  
  UserPosition findPositionBySn(String paramString);
  
  List findMyPositionByCodeAndSpell(@Param("uid") Integer paramInteger1, @Param("stockCode") String paramString1,
  List<UserPosition> findMyPositionByCodeAndSpell(@Param("uid") Integer paramInteger1, @Param("stockCode") String paramString1,
                                    @Param("stockSpell") String paramString2, @Param("state") Integer paramInteger2,
                                    @Param("stockType") String stockType
  );
  List<UserPositionVO> findMyPositionByParam(@Param("uid") Integer paramInteger1, @Param("stockCode") String paramString1,
                                                    @Param("stockSpell") String paramString2, @Param("state") Integer paramInteger2,
                                                    @Param("stockType") String stockType, @Param("positionType") Integer positionType
  );
  
  List findPositionByUserIdAndSellIdIsNull(Integer paramInteger);
src/main/java/com/nq/pojo/StockAIOrder.java
@@ -29,7 +29,7 @@
    private Integer userId;
    //ai交易产品id
    private Long stockAiId;
    private Integer stockAiId;
    //买入时间
    private Date buyDate;
src/main/java/com/nq/pojo/StockAIOrderPosition.java
@@ -64,5 +64,9 @@
     */
    private BigDecimal earnings;
    /**
     * 建仓状态 0持仓   1已平仓
     */
    private Integer status;
}
src/main/java/com/nq/pojo/UserPosition.java
@@ -19,7 +19,7 @@
public class UserPosition implements Serializable {
    @TableId(type = IdType.AUTO,value = "id")
    private Integer id;
    //0正常股票 1新股 3大宗
    //0正常股票 1.模拟 2.新股 3.大宗
    private Integer positionType;
    private String positionSn;
    private Integer userId;
@@ -27,6 +27,7 @@
    private Integer agentId;
    private String stockName;
    private String stockCode;
    //存放股票类型
    private String stockGid;
    private String stockSpell;
    private String buyOrderId;
@@ -36,10 +37,6 @@
    private String sellOrderId;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date sellOrderTime;
    public void setId(Integer id) {
        this.id = id;
    }
    private BigDecimal sellOrderPrice;
    //
src/main/java/com/nq/service/IUserPositionService.java
@@ -27,9 +27,14 @@
  UserPositionVO findByPostionSn(String  positionSn);
  ServerResponse<PageInfo> findMyPositionByCodeAndSpell(String paramString1, String paramString2, Integer paramInteger,
  ServerResponse findMyPositionByCodeAndSpell(String stockCode, String stockSpell,
                                                     Integer state, HttpServletRequest request,
                                                     int pageNum, int pageSize, String stockType);
  ServerResponse findMyPositionByParam(String paramString1, String paramString2, Integer paramInteger,
                                                        HttpServletRequest paramHttpServletRequest,
                                                        int paramInt1, int paramInt2,String stockType);
                                                        int paramInt1, int paramInt2,String stockType, Integer positionType);
  
  PositionVO findUserPositionAllProfitAndLose(Integer paramInteger);
src/main/java/com/nq/service/impl/StockAiServiceImpl.java
@@ -126,7 +126,7 @@
                iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), user.getId(), EUserAssets.BUY_AI, buyNum);
                StockAIOrder stockAIOrder = new StockAIOrder();
                stockAIOrder.setUserId(user.getId());
                stockAIOrder.setStockAiId(id);
                stockAIOrder.setStockAiId(id.intValue());
                stockAIOrder.setBuyDate(new Date());
                stockAIOrder.setBuyAmount(buyNum);
                stockAIOrder.setRemainAmount(buyNum);
@@ -292,6 +292,7 @@
                BigDecimal earnings = model.getCoverPrice().subtract(model.getStockPrice()).multiply(BigDecimal.valueOf(model.getStockNum()));
                model.setCreatDate(new Date());
                model.setEarnings(earnings);
                model.setStatus(0);
                stockAIOrder.setRealEarning(stockAIOrder.getRealEarning().add(earnings));
                //保存
@@ -335,6 +336,7 @@
                    }
                    //结算 TODO结算建仓 计算收益
                    /*//所有建仓
                    List<StockAIOrderPosition> stockAIOrderPositionList = stockAiOrderPositionMapper
                            .selectList(new QueryWrapper<StockAIOrderPosition>()
                                    .eq("stock_ai_order_id", id));
@@ -349,6 +351,8 @@
                        amount = amount.add(earningsSUM);
                    }*/
                    StockAI stockAI = stockAiMapper.selectById(stockAIOrder.getStockAiId());
                    //结算修改为平仓状态
                    stockAiOrderPositionMapper.updateStatusByOrderId(stockAIOrder.getId(), 1);
                    //归还本金
                    iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), stockAIOrder.getUserId(), EUserAssets.AI_SETTLEMENT, stockAIOrder.getBuyAmount());
                    //收益
src/main/java/com/nq/service/impl/StockServiceImpl.java
@@ -828,16 +828,16 @@
     */
    @Override
    public ServerResponse getStocksByKeyWords(int pageNum, int pageSize, String keyWords) {
        try {
            PageHelper.startPage(pageNum, pageSize);
            List<StockVOQuery> stocks = stockMapper.findStocksQuery(keyWords);
            // 获取分页信息
            PageInfo<StockVOQuery> pageInfo = new PageInfo<>(stocks);
            /*if (!pageInfo.getList().isEmpty()) {
            }*/
            if (!pageInfo.getList().isEmpty()) {
                pageInfo.getList().forEach(stock -> {
                    stock.setNowPrice(iPriceServices.getNowPrice(stock.getStockCode()));
                });
            }
            return ServerResponse.createBySuccess(pageInfo);
        } catch (Exception e) {
            log.error("StockAiService getStocksByKeyWords error", e);
src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
@@ -690,6 +690,68 @@
        return ServerResponse.createBySuccess(pageInfo);
    }
    public ServerResponse findMyPositionByParam(String stockCode, String stockSpell,
                                                       Integer state, HttpServletRequest request,
                                                       int pageNum, int pageSize, String stockType, Integer positionType) {
        try {
            User user = iUserService.getCurrentUser(request);
            if (user == null ){
                return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(),"请先登录", request);
            }
            PageHelper.startPage(pageNum, pageSize);
            List<UserPositionVO> userPositions = userPositionMapper.findMyPositionByParam(user.getId(),
                            stockCode, stockSpell, state, stockType, positionType);
            PageInfo<UserPositionVO> pageInfo = new PageInfo<>(userPositions);
            List<UserPositionVO> resultUserPositions = new ArrayList<>();
            if (!pageInfo.getList().isEmpty()) {
                for (UserPositionVO position : userPositions) {
                    UserPositionVO userPositionVO = position;
                    if (position.getPositionType() != 4) {
                        BigDecimal nowPrice;
                        if(state == 0){
                            nowPrice = priceServices.getNowPrice(position.getStockCode());
                        }else{
                            nowPrice = position.getSellOrderPrice();
                        }
                        userPositionVO = UserPointUtil.assembleUserPositionVO2(position,nowPrice);
                        userPositionVO.setOrderTotalPrice(userPositionVO.getOrderTotalPrice().multiply(new BigDecimal(userPositionVO.getOrderLever())));
                        StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new LambdaQueryWrapper<StockSubscribe>()
                                .eq(StockSubscribe::getCode, userPositionVO.getStockCode()));
                        if(position.getSellOrderId() == null){
                            if (null != stockSubscribe && DateUtil.date().before(stockSubscribe.getListDate())) {
                                userPositionVO.setProfitAndLose(BigDecimal.ZERO);
                                userPositionVO.setProfitAndLoseParent("0%");
                                userPositionVO.setIsListed(false);
                            }else{
                                userPositionVO.setIsListed(true);
                                userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose().multiply(new BigDecimal(userPositionVO.getOrderLever())));
                            }
                        }else{
                            userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose().multiply(new BigDecimal(userPositionVO.getOrderLever())));
                        }
                    } else {
                        //ai交易 计算收益率 收益/本金*100
                        BigDecimal profitAndLose = userPositionVO.getProfitAndLose()
                                .divide(userPositionVO.getOrderTotalPrice())
                                .multiply(new BigDecimal(100))
                                .setScale(2, BigDecimal.ROUND_DOWN);
                        userPositionVO.setProfitAndLoseParent(profitAndLose + "%");
                    }
                    resultUserPositions.add(userPositionVO);
                }
            }
            pageInfo.setList(resultUserPositions);
            return ServerResponse.createBySuccess(pageInfo);
        } catch (Exception e) {
            log.error("IUserPositionService findMyPositionByParam  {}", e.getMessage());
        }
        return ServerResponse.createByError();
    }
    public PositionVO findUserPositionAllProfitAndLose(Integer userId) {
        List<UserPosition> userPositions = this.userPositionMapper.findPositionByUserIdAndSellIdIsNull(userId);
@@ -958,7 +1020,7 @@
        userPosition.setAgentId(user.getAgentId());
        userPosition.setStockCode(stock.getStockCode());
        userPosition.setStockName(stock.getStockName());
        userPosition.setStockGid(stock.getStockGid());
        userPosition.setStockGid(stock.getStockType());
        userPosition.setStockSpell(stock.getStockSpell());
        userPosition.setBuyOrderId(GeneratePosition.getPositionId());
        userPosition.setBuyOrderTime(DateTimeUtil.strToDate(buyTime));
@@ -1341,7 +1403,7 @@
                stockType = stock.getStockType();
            }
            userPosition.setPositionType(1);
            userPosition.setPositionType(2);
            userPosition.setPositionSn(KeyUtils.getUniqueKey());
            userPosition.setUserId(userStockSubscribe.getUserId());
            userPosition.setNickName(userStockSubscribe.getRealName());
@@ -1599,7 +1661,7 @@
        userPosition.setAgentId(user.getAgentId());
        userPosition.setStockCode(stock.getStockCode());
        userPosition.setStockName(stock.getStockName());
        userPosition.setStockGid(stock.getStockGid());
        userPosition.setStockGid(stock.getStockType());
        userPosition.setStockSpell(stock.getStockSpell());
        userPosition.setBuyOrderId(GeneratePosition.getPositionId());
        userPosition.setBuyOrderTime(new Date());
@@ -2042,14 +2104,14 @@
            BigDecimal usPositionEarningsParent = BigDecimal.ZERO; //美股持仓收益百分比
            BigDecimal mxPositionEarningsParent = BigDecimal.ZERO; //墨西哥持仓收益百分比
            if (userPositions.size() > 0) {
            if (!userPositions.isEmpty()) {
                for (UserPosition position : userPositions) {
                    BigDecimal nowPrice;
                    if(state == 0){
                    BigDecimal nowPrice = priceServices.getNowPrice(position.getStockCode());
                    /*if(state == 0){
                        nowPrice = priceServices.getNowPrice(position.getStockCode());
                    }else{
                        nowPrice = position.getSellOrderPrice();
                    }
                    }*/
                    UserPositionVO userPositionVO = UserPointUtil.assembleUserPositionVO(position,nowPrice);
                    userPositionVO.setOrderTotalPrice(userPositionVO.getOrderTotalPrice().multiply(new BigDecimal(userPositionVO.getOrderLever())));
src/main/java/com/nq/utils/UserPointUtil.java
@@ -66,6 +66,29 @@
        return userPositionVO;
    }
    /**
     * 返回当前 仓位表 实时数据
     * */
    public  static  UserPositionVO assembleUserPositionVO2(UserPositionVO userPositionVO,BigDecimal nowPrice) {
        PositionProfitVO positionProfitVO = getPositionProfitVO2(userPositionVO, nowPrice);
        BigDecimal ss =  positionProfitVO.getProfitAndLose().divide(userPositionVO.getOrderTotalPrice(),BigDecimal.ROUND_CEILING)
                .multiply(new BigDecimal(100));
        ss = ss.setScale(2, BigDecimal.ROUND_DOWN);
        userPositionVO.setProfitAndLoseParent(ss+"%");
        userPositionVO.setProfitAndLoseParent2(ss);
        userPositionVO.setProfitAndLose(positionProfitVO.getProfitAndLose());
        userPositionVO.setAllProfitAndLose(positionProfitVO.getAllProfitAndLose());
        if(StringUtil.isEmpty(userPositionVO.getSellOrderId())){
            userPositionVO.setNow_price(nowPrice.toString());
        }else{
            userPositionVO.setNow_price(userPositionVO.getSellOrderPrice().toString());
        }
        userPositionVO.setAmountToBeCovered(userPositionVO.getAmountToBeCovered());
        return userPositionVO;
    }
    /**
     * 计算仓位盈亏计算方法
     * */
@@ -96,4 +119,35 @@
        positionProfitVO.setNowPrice(nowPrice.setScale(5,BigDecimal.ROUND_UP).toString());
        return positionProfitVO;
    }
    /**
     * 计算仓位盈亏计算方法
     * */
    public static PositionProfitVO getPositionProfitVO2(UserPositionVO position,BigDecimal nowPrice) {
        BigDecimal profitAndLose = new BigDecimal("0");
        BigDecimal allProfitAndLose = new BigDecimal("0");
        if (position.getSellOrderId() != null) {
            BigDecimal subPrice = position.getSellOrderPrice().subtract(position.getBuyOrderPrice());
            profitAndLose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue()));
            if ("买跌".equals(position.getOrderDirection())) {
                profitAndLose = profitAndLose.negate();
            }
            allProfitAndLose = profitAndLose.subtract(position.getOrderSpread()).subtract(position.getOrderStayFee()).subtract(position.getSpreadRatePrice());
        } else {
            BigDecimal subPrice = nowPrice.subtract(position.getBuyOrderPrice());
            profitAndLose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue()));
            if ("买跌".equals(position.getOrderDirection())) {
                profitAndLose = profitAndLose.negate();
            }
            //总盈亏= 浮动盈亏 – 手续费 – 印花税 – 留仓费 – 点差费
            allProfitAndLose = profitAndLose.subtract(position.getOrderSpread()).subtract(position.getOrderStayFee()).subtract(position.getSpreadRatePrice());
        }
        PositionProfitVO positionProfitVO = new PositionProfitVO();
        positionProfitVO.setProfitAndLose(profitAndLose);
        positionProfitVO.setAllProfitAndLose(allProfitAndLose);
        positionProfitVO.setNowPrice(nowPrice.setScale(5,BigDecimal.ROUND_UP).toString());
        return positionProfitVO;
    }
}
src/main/java/com/nq/vo/position/UserPositionVO.java
@@ -34,11 +34,6 @@
    private Date sellOrderTime;
    public void setId(Integer id) {
        this.id = id;
    }
    private BigDecimal sellOrderPrice;
    private BigDecimal profitTargetPrice;
    private BigDecimal stopTargetPrice;
src/main/resources/mapper/StockAiOrderPositionMapper.xml
New file
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nq.dao.StockAiOrderPositionMapper">
    <update id="updateStatusByOrderId">
        update stock_ai_order_position
        set status = #{status}
        where stock_ai_order_id = #{stockAiOrderId}
    </update>
    <select id="getAiPositionList" resultType="com.nq.vo.position.UserPositionVO">
        SELECT * FROM stock_ai_order_position
        WHERE stock_ai_order_id IN (SELECT id FROM stock_ai_order WHERE
            user_id = #{userId} and status='passed' )
          <if test="status != null">
              AND status = #{status}
          </if>
        ORDER BY creat_date DESC
    </select>
</mapper>
src/main/resources/mapper/UserPositionMapper.xml
@@ -387,8 +387,7 @@
<!--      <if test="stockType != null and stockType!= ''">-->
<!--        and stock_gid = #{stockType}-->
<!--      </if>-->
      and position_type != 1
    </where>
    ORDER BY id DESC
  </select>
@@ -542,6 +541,83 @@
    limit 1
  </select>
  <select id="findMyPositionByParam" parameterType="map" resultType="com.nq.vo.position.UserPositionVO">
    SELECT a.* FROM (SELECT
    *
    FROM user_position
    WHERE
    user_id = #{uid}
    UNION ALL
    SELECT
    p.id,
    4 position_type,
    null position_sn,
    null user_id,
    null nick_name,
    null agent_id,
    s.stock_name,
    s.stock_code,
    s.stock_gid,
    s.stock_spell,
    p.stock_ai_order_id buy_order_id,
    p.creat_date buy_order_time,
    p.stock_price buy_order_price,
    null sell_order_id,
    null sell_order_time,
    p.cover_price sell_order_price,
    null profit_target_price,
    null stop_target_price,
    null order_direction,
    p.stock_num order_num,
    null order_lever,
    p.stock_num*p.stock_price order_total_price,
    0 order_fee,
    0 order_spread,
    0 order_stay_fee,
    null order_stay_days,
    p.earnings profit_and_lose,
    p.earnings all_profit_and_lose,
    0 is_lock,
    null lock_msg,
    null stock_plate,
    0 spread_rate_price,
    0 margin_add,
    null dz_id,
    null new_id,
    0 amount_to_be_covered
    FROM stock_ai_order_position p
    LEFT JOIN stock s ON s.id = p.stock_id
    WHERE p.stock_ai_order_id IN (SELECT id FROM stock_ai_order WHERE
    user_id = #{uid} and status='passed' )
    <if test="state != null ">
      <if test="state == 0">
        and p.status = 0
      </if>
      <if test="state == 1">
        and p.status = 1
      </if>
    </if>
    ) a
    WHERE a.position_type != 1
    <if test="state != null ">
      <if test="state == 0">
        and a.sell_order_id is null
      </if>
      <if test="state == 1">
        and a.sell_order_id is not null
      </if>
    </if>
    <if test="stockCode != null and stockCode != '' ">
      and a.stock_code like CONCAT('%','${stockCode}','%')
    </if>
    <if test="stockSpell != null and stockSpell != '' ">
      and a.stock_spell like CONCAT('%','${stockSpell}','%')
    </if>
    <if test="positionType != null">
      and a.position_type = #{positionType}
    </if>
    ORDER BY a.buy_order_time DESC
  </select>
</mapper>