Browse Source

test

master
cgx 1 year ago
parent
commit
46090291f6
55 changed files with 4626 additions and 220 deletions
  1. +156
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/controller/WebBannerController.java
  2. +76
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/entity/WebBanner.java
  3. +14
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/mapper/WebBannerMapper.java
  4. +5
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/mapper/xml/WebBannerMapper.xml
  5. +14
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/service/IWebBannerService.java
  6. +19
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/service/impl/WebBannerServiceImpl.java
  7. +197
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue/WebBannerList.vue
  8. +141
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue/modules/WebBannerForm.vue
  9. +84
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue/modules/WebBannerModal.Style#Drawer.vue
  10. +60
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue/modules/WebBannerModal.vue
  11. +61
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue3/WebBanner.api.ts
  12. +91
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue3/WebBanner.data.ts
  13. +162
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue3/WebBannerList.vue
  14. +58
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue3/components/WebBannerModal.vue
  15. +0
    -18
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/service/ApiLoginService.java
  16. +0
    -163
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/service/impl/ApiLoginServiceImpl.java
  17. +157
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/controller/TbConfController.java
  18. +77
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/entity/TbConf.java
  19. +14
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/mapper/TbConfMapper.java
  20. +5
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/mapper/xml/TbConfMapper.xml
  21. +14
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/service/ITbConfService.java
  22. +19
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/service/impl/TbConfServiceImpl.java
  23. +177
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue/TbConfList.vue
  24. +109
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue/modules/TbConfForm.vue
  25. +84
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue/modules/TbConfModal.Style#Drawer.vue
  26. +60
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue/modules/TbConfModal.vue
  27. +61
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue3/TbConf.api.ts
  28. +33
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue3/TbConf.data.ts
  29. +162
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue3/TbConfList.vue
  30. +58
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue3/components/TbConfModal.vue
  31. +156
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/controller/TbSuggestController.java
  32. +101
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/entity/TbSuggest.java
  33. +14
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/mapper/TbSuggestMapper.java
  34. +5
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/mapper/xml/TbSuggestMapper.xml
  35. +16
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/service/ITbSuggestService.java
  36. +19
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/service/impl/TbSuggestServiceImpl.java
  37. +219
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue/TbSuggestList.vue
  38. +124
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue/modules/TbSuggestForm.vue
  39. +84
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue/modules/TbSuggestModal.Style#Drawer.vue
  40. +60
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue/modules/TbSuggestModal.vue
  41. +61
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue3/TbSuggest.api.ts
  42. +81
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue3/TbSuggest.data.ts
  43. +162
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue3/TbSuggestList.vue
  44. +58
    -0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue3/components/TbSuggestModal.vue
  45. +44
    -0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/postBean/SuggestReq.java
  46. +0
    -39
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/UserController.java
  47. +79
    -0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/controller/IndexController.java
  48. +35
    -0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/controller/UserController.java
  49. +15
    -0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/service/AppletLoginService.java
  50. +18
    -0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/service/IndexService.java
  51. +238
    -0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/service/impl/AppletLoginServiceImpl.java
  52. +83
    -0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/service/impl/IndexServiceImpl.java
  53. +381
    -0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/utils/ValidateTool.java
  54. +37
    -0
      jeecg-boot-module-system/src/main/resources/application-dev.yml
  55. +368
    -0
      jeecg-boot-module-system/src/main/resources/application-prod.yml

+ 156
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/controller/WebBannerController.java View File

@ -0,0 +1,156 @@
package org.jeecg.modules.banner.controller;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.banner.entity.WebBanner;
import org.jeecg.modules.banner.service.IWebBannerService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
/**
* @Description: banner设置
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
@Api(tags="banner设置")
@RestController
@RequestMapping("/banner/webBanner")
@Slf4j
public class WebBannerController extends JeecgController<WebBanner, IWebBannerService> {
@Autowired
private IWebBannerService webBannerService;
/**
* 分页列表查询
*
* @param webBanner
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "banner设置-分页列表查询")
@ApiOperation(value="banner设置-分页列表查询", notes="banner设置-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<WebBanner>> queryPageList(WebBanner webBanner,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<WebBanner> queryWrapper = QueryGenerator.initQueryWrapper(webBanner, req.getParameterMap());
Page<WebBanner> page = new Page<WebBanner>(pageNo, pageSize);
IPage<WebBanner> pageList = webBannerService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param webBanner
* @return
*/
@AutoLog(value = "banner设置-添加")
@ApiOperation(value="banner设置-添加", notes="banner设置-添加")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody WebBanner webBanner) {
webBannerService.save(webBanner);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param webBanner
* @return
*/
@AutoLog(value = "banner设置-编辑")
@ApiOperation(value="banner设置-编辑", notes="banner设置-编辑")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody WebBanner webBanner) {
webBannerService.updateById(webBanner);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "banner设置-通过id删除")
@ApiOperation(value="banner设置-通过id删除", notes="banner设置-通过id删除")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
webBannerService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "banner设置-批量删除")
@ApiOperation(value="banner设置-批量删除", notes="banner设置-批量删除")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.webBannerService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "banner设置-通过id查询")
@ApiOperation(value="banner设置-通过id查询", notes="banner设置-通过id查询")
@GetMapping(value = "/queryById")
public Result<WebBanner> queryById(@RequestParam(name="id",required=true) String id) {
WebBanner webBanner = webBannerService.getById(id);
if(webBanner==null) {
return Result.error("未找到对应数据");
}
return Result.OK(webBanner);
}
/**
* 导出excel
*
* @param request
* @param webBanner
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, WebBanner webBanner) {
return super.exportXls(request, webBanner, WebBanner.class, "banner设置");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, WebBanner.class);
}
}

+ 76
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/entity/WebBanner.java View File

@ -0,0 +1,76 @@
package org.jeecg.modules.banner.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @Description: banner设置
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
@Data
@TableName("web_banner")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="web_banner对象", description="banner设置")
public class WebBanner implements Serializable {
private static final long serialVersionUID = 1L;
/**id*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "id")
private String id;
/**图片*/
@Excel(name = "图片", width = 15)
@ApiModelProperty(value = "图片")
private String image;
/**跳转地址*/
@Excel(name = "跳转地址", width = 15)
@ApiModelProperty(value = "跳转地址")
private String toUrl;
/**排序*/
@Excel(name = "排序", width = 15)
@ApiModelProperty(value = "排序")
private Integer sort;
/**0 首页上方banner轮播 1 首页第二处 2首页第三处*/
@Excel(name = "0 首页上方banner轮播 1 首页第二处 2首页第三处", width = 15, dicCode = "bannerType")
@Dict(dicCode = "bannerType")
@ApiModelProperty(value = "0 首页上方banner轮播 1 首页第二处 2首页第三处")
private Integer type;
/**是否删除 0否 1是*/
@Excel(name = "是否删除 0否 1是", width = 15, dicCode = "is_disable")
@Dict(dicCode = "is_disable")
@ApiModelProperty(value = "是否删除 0否 1是")
private Integer isDisable;
/**创建时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**修改时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "修改时间")
private Date updateTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**所属部门*/
@ApiModelProperty(value = "所属部门")
private String sysOrgCode;
}

+ 14
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/mapper/WebBannerMapper.java View File

@ -0,0 +1,14 @@
package org.jeecg.modules.banner.mapper;
import org.jeecg.modules.banner.entity.WebBanner;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: banner设置
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
public interface WebBannerMapper extends BaseMapper<WebBanner> {
}

+ 5
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/mapper/xml/WebBannerMapper.xml View File

@ -0,0 +1,5 @@
<?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="org.jeecg.modules.banner.mapper.WebBannerMapper">
</mapper>

+ 14
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/service/IWebBannerService.java View File

@ -0,0 +1,14 @@
package org.jeecg.modules.banner.service;
import org.jeecg.modules.banner.entity.WebBanner;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description: banner设置
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
public interface IWebBannerService extends IService<WebBanner> {
}

+ 19
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/service/impl/WebBannerServiceImpl.java View File

@ -0,0 +1,19 @@
package org.jeecg.modules.banner.service.impl;
import org.jeecg.modules.banner.entity.WebBanner;
import org.jeecg.modules.banner.mapper.WebBannerMapper;
import org.jeecg.modules.banner.service.IWebBannerService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: banner设置
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
@Service
public class WebBannerServiceImpl extends ServiceImpl<WebBannerMapper, WebBanner> implements IWebBannerService {
}

+ 197
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue/WebBannerList.vue View File

@ -0,0 +1,197 @@
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('banner设置')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<!-- 高级查询区域 -->
<j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
:scroll="{x:true}"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
class="j-table-force-nowrap"
@change="handleTableChange">
<template slot="htmlSlot" slot-scope="text">
<div v-html="text"></div>
</template>
<template slot="imgSlot" slot-scope="text,record">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="downloadFile(text)">
下载
</a-button>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a @click="handleDetail(record)">详情</a>
</a-menu-item>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<web-banner-modal ref="modalForm" @ok="modalFormOk"></web-banner-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import WebBannerModal from './modules/WebBannerModal'
import {filterMultiDictText} from '@/components/dict/JDictSelectUtil'
export default {
name: 'WebBannerList',
mixins:[JeecgListMixin, mixinDevice],
components: {
WebBannerModal
},
data () {
return {
description: 'banner设置管理页面',
//
columns: [
{
title: '#',
dataIndex: '',
key:'rowIndex',
width:60,
align:"center",
customRender:function (t,r,index) {
return parseInt(index)+1;
}
},
{
title:'图片',
align:"center",
dataIndex: 'image',
scopedSlots: {customRender: 'imgSlot'}
},
{
title:'跳转地址',
align:"center",
dataIndex: 'toUrl'
},
{
title:'排序',
align:"center",
dataIndex: 'sort'
},
{
title:'0 首页上方banner轮播 1 首页第二处 2首页第三处',
align:"center",
dataIndex: 'type_dictText'
},
{
title:'是否删除 0否 1是',
align:"center",
dataIndex: 'isDisable_dictText'
},
{
title: '操作',
dataIndex: 'action',
align:"center",
fixed:"right",
width:147,
scopedSlots: { customRender: 'action' }
}
],
url: {
list: "/banner/webBanner/list",
delete: "/banner/webBanner/delete",
deleteBatch: "/banner/webBanner/deleteBatch",
exportXlsUrl: "/banner/webBanner/exportXls",
importExcelUrl: "banner/webBanner/importExcel",
},
dictOptions:{},
superFieldList:[],
}
},
created() {
this.getSuperFieldList();
},
computed: {
importExcelUrl: function(){
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
},
},
methods: {
initDictConfig(){
},
getSuperFieldList(){
let fieldList=[];
fieldList.push({type:'string',value:'image',text:'图片',dictCode:''})
fieldList.push({type:'string',value:'toUrl',text:'跳转地址',dictCode:''})
fieldList.push({type:'popup',value:'sort',text:'排序', popup:{code:'',field:'',orgFields:'',destFields:''}})
fieldList.push({type:'int',value:'type',text:'0 首页上方banner轮播 1 首页第二处 2首页第三处',dictCode:'bannerType'})
fieldList.push({type:'int',value:'isDisable',text:'是否删除 0否 1是',dictCode:'is_disable'})
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>

+ 141
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue/modules/WebBannerForm.vue View File

@ -0,0 +1,141 @@
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<a-col :span="24">
<a-form-model-item label="图片" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="image">
<j-image-upload isMultiple v-model="model.image" ></j-image-upload>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="跳转地址" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="toUrl">
<a-input v-model="model.toUrl" placeholder="请输入跳转地址" ></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="排序" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="sort">
<j-popup
v-model="model.sort"
field="sort"
org-fields=""
dest-fields=""
code=""
:multi="true"
@input="popupCallback"
/>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="0 首页上方banner轮播 1 首页第二处 2首页第三处" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="type">
<j-dict-select-tag type="list" v-model="model.type" dictCode="bannerType" placeholder="请选择0 首页上方banner轮播 1 首页第二处 2首页第三处" />
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="是否删除 0否 1是" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="isDisable">
<j-dict-select-tag type="list" v-model="model.isDisable" dictCode="is_disable" placeholder="请选择是否删除 0否 1是" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
export default {
name: 'WebBannerForm',
components: {
},
props: {
//
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
model:{
},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules: {
sort: [
{ required: true, message: '请输入排序!'},
],
isDisable: [
{ required: true, message: '请输入是否删除 0否 1是!'},
],
},
url: {
add: "/banner/webBanner/add",
edit: "/banner/webBanner/edit",
queryById: "/banner/webBanner/queryById"
}
}
},
computed: {
formDisabled(){
return this.disabled
},
},
created () {
//model
this.modelDefault = JSON.parse(JSON.stringify(this.model));
},
methods: {
add () {
this.edit(this.modelDefault);
},
edit (record) {
this.model = Object.assign({}, record);
this.visible = true;
},
submitForm () {
const that = this;
//
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
popupCallback(value,row){
this.model = Object.assign(this.model, row);
},
}
}
</script>

+ 84
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue/modules/WebBannerModal.Style#Drawer.vue View File

@ -0,0 +1,84 @@
<template>
<a-drawer
:title="title"
:width="width"
placement="right"
:closable="false"
@close="close"
destroyOnClose
:visible="visible">
<web-banner-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit" normal></web-banner-form>
<div class="drawer-footer">
<a-button @click="handleCancel" style="margin-bottom: 0;">关闭</a-button>
<a-button v-if="!disableSubmit" @click="handleOk" type="primary" style="margin-bottom: 0;">提交</a-button>
</div>
</a-drawer>
</template>
<script>
import WebBannerForm from './WebBannerForm'
export default {
name: 'WebBannerModal',
components: {
WebBannerForm
},
data () {
return {
title:"操作",
width:800,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
});
},
close () {
this.$emit('close');
this.visible = false;
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
handleCancel () {
this.close()
}
}
}
</script>
<style lang="less" scoped>
/** Button按钮间距 */
.ant-btn {
margin-left: 30px;
margin-bottom: 30px;
float: right;
}
.drawer-footer{
position: absolute;
bottom: -8px;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
</style>

+ 60
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue/modules/WebBannerModal.vue View File

@ -0,0 +1,60 @@
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<web-banner-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></web-banner-form>
</j-modal>
</template>
<script>
import WebBannerForm from './WebBannerForm'
export default {
name: 'WebBannerModal',
components: {
WebBannerForm
},
data () {
return {
title:'',
width:800,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>

+ 61
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue3/WebBanner.api.ts View File

@ -0,0 +1,61 @@
import {defHttp} from '/@/utils/http/axios';
import {Modal} from 'ant-design-vue';
enum Api {
list = '/banner/webBanner/list',
save='/banner/webBanner/add',
edit='/banner/webBanner/edit',
deleteOne = '/banner/webBanner/delete',
deleteBatch = '/banner/webBanner/deleteBatch',
importExcel = '/banner/webBanner/importExcel',
exportXls = '/banner/webBanner/exportXls',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
*
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
*
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
*
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}

+ 91
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue3/WebBanner.data.ts View File

@ -0,0 +1,91 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '图片',
align:"center",
dataIndex: 'image',
customRender:render.renderAvatar,
},
{
title: '跳转地址',
align:"center",
dataIndex: 'toUrl'
},
{
title: '排序',
align:"center",
dataIndex: 'sort'
},
{
title: '0 首页上方banner轮播 1 首页第二处 2首页第三处',
align:"center",
dataIndex: 'type_dictText'
},
{
title: '是否删除 0否 1是',
align:"center",
dataIndex: 'isDisable_dictText'
},
];
//查询数据
export const searchFormSchema: FormSchema[] = [
];
//表单数据
export const formSchema: FormSchema[] = [
{
label: '图片',
field: 'image',
component: 'JImageUpload',
componentProps:{
},
},
{
label: '跳转地址',
field: 'toUrl',
component: 'Input',
},
{
label: '排序',
field: 'sort',
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"",
fieldConfig:,
multi:true,
}
},
dynamicRules: ({model,schema}) => {
return [
{ required: true, message: '请输入排序!'},
];
},
},
{
label: '0 首页上方banner轮播 1 首页第二处 2首页第三处',
field: 'type',
component: 'JDictSelectTag',
componentProps:{
dictCode:"bannerType"
},
},
{
label: '是否删除 0否 1是',
field: 'isDisable',
component: 'JDictSelectTag',
componentProps:{
dictCode:"is_disable"
},
dynamicRules: ({model,schema}) => {
return [
{ required: true, message: '请输入是否删除 0否 1是!'},
];
},
},
];

+ 162
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue3/WebBannerList.vue View File

@ -0,0 +1,162 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template #htmlSlot="{text}">
<div v-html="text"></div>
</template>
<template #fileSlot="{text}">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</template>
</BasicTable>
<!-- 表单区域 -->
<WebBannerModal @register="registerModal" @success="handleSuccess"></WebBannerModal>
</div>
</template>
<script lang="ts" name="banner-webBanner" setup>
import {ref, computed, unref} from 'vue';
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import {useModal} from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage'
import WebBannerModal from './components/WebBannerModal.vue'
import {columns, searchFormSchema} from './webBanner.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './webBanner.api';
const checkedKeys = ref<Array<string | number>>([]);
//model
const [registerModal, {openModal}] = useModal();
//table
const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
tableProps:{
title: 'banner设置',
api: list,
columns,
canResize:false,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToTime: [
],
},
actionColumn: {
width: 120,
},
},
exportConfig: {
name:"banner设置",
url: getExportUrl,
},
importConfig: {
url: getImportUrl
},
})
const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, reload);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: checkedKeys.value}, reload);
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record){
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
}
}
]
}
</script>
<style scoped>
</style>

+ 58
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/banner/vue3/components/WebBannerModal.vue View File

@ -0,0 +1,58 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
<BasicForm @register="registerForm"/>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import {formSchema} from '../webBanner.data';
import {saveOrUpdate} from '../webBanner.api';
// Emits
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
//
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
});
//
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//
await resetFields();
setModalProps({confirmLoading: false,showCancelBtn:!!data?.showFooter,showOkBtn:!!data?.showFooter});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//
await setFieldsValue({
...data.record,
});
}
//
setProps({ disabled: !data?.showFooter })
});
//
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//
await saveOrUpdate(values, isUpdate.value);
//
closeModal();
//
emit('success');
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
</style>

+ 0
- 18
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/service/ApiLoginService.java View File

@ -1,18 +0,0 @@
package org.jeecg.modules.service;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.bean.LoginReq;
public interface ApiLoginService {
/**
* 公众号授权登录
* @param loginReq
* @return
*/
Result<?> officialLogin(LoginReq loginReq);
}

+ 0
- 163
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/service/impl/ApiLoginServiceImpl.java View File

@ -1,163 +0,0 @@
package org.jeecg.modules.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.xkcoding.http.config.HttpConfig;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.bean.ConvertUtils;
import org.jeecg.modules.bean.HttpConf;
import org.jeecg.modules.bean.LoginReq;
import org.jeecg.modules.hanHaiMember.entity.HanHaiMember;
import org.jeecg.modules.hanHaiMember.service.IHanHaiMemberService;
import org.jeecg.modules.service.ApiLoginService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Service
public class ApiLoginServiceImpl implements ApiLoginService {
//公共用户表
@Resource
private IHanHaiMemberService hanHaiMemberService;
//公共缓存类
@Resource
private RedisUtil redisUtil;
@Resource
private HttpConf httpConf;
/**
* 微信公众号-appid
*/
private String mpAppId = "wx15be4225a7e41a1e";
/**
* 微信公众号-appSecret
*/
private String mpAppSecret = "0fdb77429ffdf206c151af76a663041c";
/**
* 公众号授权登录注册
* @param loginReq
* @return
*/
@Override
@Transactional
public Result<?> officialLogin(LoginReq loginReq){
Map<Object, Object> loginMap = new HashMap<>();
if (StringUtils.isBlank(loginReq.getCode())) {
throw new JeecgBootException("code为空");
}
String loginUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" +mpAppId + "&secret=" + mpAppSecret + "&code=" + loginReq.getCode() + "&grant_type=authorization_code";
//使用工具类
JSONObject json_test = httpConf.getJSONObject(loginUrl);
log.info("{} {} -- {}", mpAppId, mpAppSecret, json_test);
String wxOpenid = json_test.getString("openid");
String wxUnionId = json_test.getString("unionid");
String access_token = json_test.getString("access_token");
if (StringUtils.isBlank(wxOpenid)) {
throw new JeecgBootException("未获取到openid");
}
HanHaiMember member = hanHaiMemberService.lambdaQuery().eq(HanHaiMember::getOfficialOpenid,wxOpenid).one();
if(member!=null){
// if (StringUtils.isBlank(member.getVid())){
// member.setVid(loginReq.getVid());
// member.setVtime(new Date());
// hanHaiMemberService.updateById(member);
// }
//开始获取用户信息
String memberUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token+"&openid="+wxOpenid+"&lang=zh_CN";
//使用工具类
JSONObject json_member = httpConf.getJSONObject(memberUrl);
String nickname = json_member.getString("nickname");
String headimgurl = json_member.getString("headimgurl");
try {
nickname = new String(nickname.getBytes("ISO-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
member.setNickName(nickname);
member.setHeadImage(headimgurl);
member.setWxUnionid(wxUnionId);
String token = JwtUtil.sign(member.getAccount(), member.getAccount());
member.setToken(token);
member.setUpdateTime(new Date());
hanHaiMemberService.updateById(member);
// 生成token返回
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
// 设置超时时间
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 100);
loginMap.put("token",token);
loginMap.put("userInfo",member);
return Result.OK("登录成功",loginMap);
}
//开始获取用户信息
String memberUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token+"&openid="+wxOpenid+"&lang=zh_CN";
//使用工具类
JSONObject json_member = httpConf.getJSONObject(memberUrl);
String nickname = json_member.getString("nickname");
String headimgurl = json_member.getString("headimgurl");
try {
nickname = new String(nickname.getBytes("ISO-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
HanHaiMember save = new HanHaiMember();
save.setAccount(wxOpenid);
save.setVid(loginReq.getVid());
save.setVtime(new Date());
save.setNickName(nickname);
save.setHeadImage(headimgurl);
save.setWxUnionid(wxUnionId);
//销售邀请者标识
save.setShareId(loginReq.getShareId());
save.setOfficialOpenid(wxOpenid);
save.setCreateTime(new Date());
//密码加密
String salt = ConvertUtils.randomGen(8);
String encrypt = PasswordUtil.encrypt(wxOpenid,"123456" , salt);
save.setPassword(encrypt);
save.setPasswordSalt(salt);
save.setDeleteFlag("N");
save.setRole("0");
// 生成token返回
String token = JwtUtil.sign(wxOpenid, wxOpenid);
save.setToken(token);
hanHaiMemberService.save(save);
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
// 设置超时时间
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 100);
loginMap.put("token",token);
loginMap.put("userInfo",save);
return Result.OK("登录成功",loginMap);
}
}

+ 157
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/controller/TbConfController.java View File

@ -0,0 +1,157 @@
package org.jeecg.modules.tbConf.controller;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.tbConf.entity.TbConf;
import org.jeecg.modules.tbConf.service.ITbConfService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
/**
* @Description: tb_conf
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
@Api(tags="tb_conf")
@RestController
@RequestMapping("/tbConf/tbConf")
@Slf4j
public class TbConfController extends JeecgController<TbConf, ITbConfService> {
@Autowired
private ITbConfService tbConfService;
/**
* 分页列表查询
*
* @param tbConf
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "tb_conf-分页列表查询")
@ApiOperation(value="tb_conf-分页列表查询", notes="tb_conf-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<TbConf>> queryPageList(TbConf tbConf,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<TbConf> queryWrapper = QueryGenerator.initQueryWrapper(tbConf, req.getParameterMap());
Page<TbConf> page = new Page<TbConf>(pageNo, pageSize);
queryWrapper.eq("dict_group","sys_word");
IPage<TbConf> pageList = tbConfService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param tbConf
* @return
*/
@AutoLog(value = "tb_conf-添加")
@ApiOperation(value="tb_conf-添加", notes="tb_conf-添加")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody TbConf tbConf) {
tbConfService.save(tbConf);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param tbConf
* @return
*/
@AutoLog(value = "tb_conf-编辑")
@ApiOperation(value="tb_conf-编辑", notes="tb_conf-编辑")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody TbConf tbConf) {
tbConfService.updateById(tbConf);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "tb_conf-通过id删除")
@ApiOperation(value="tb_conf-通过id删除", notes="tb_conf-通过id删除")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
tbConfService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "tb_conf-批量删除")
@ApiOperation(value="tb_conf-批量删除", notes="tb_conf-批量删除")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.tbConfService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "tb_conf-通过id查询")
@ApiOperation(value="tb_conf-通过id查询", notes="tb_conf-通过id查询")
@GetMapping(value = "/queryById")
public Result<TbConf> queryById(@RequestParam(name="id",required=true) String id) {
TbConf tbConf = tbConfService.getById(id);
if(tbConf==null) {
return Result.error("未找到对应数据");
}
return Result.OK(tbConf);
}
/**
* 导出excel
*
* @param request
* @param tbConf
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, TbConf tbConf) {
return super.exportXls(request, tbConf, TbConf.class, "tb_conf");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, TbConf.class);
}
}

+ 77
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/entity/TbConf.java View File

@ -0,0 +1,77 @@
package org.jeecg.modules.tbConf.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @Description: tb_conf
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
@Data
@TableName("tb_conf")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="tb_conf对象", description="tb_conf")
public class TbConf implements Serializable {
private static final long serialVersionUID = 1L;
/**id*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "id")
private Integer id;
/**key*/
@Excel(name = "key", width = 15)
@ApiModelProperty(value = "key")
private String name;
/**配置值*/
@Excel(name = "配置值", width = 15)
@ApiModelProperty(value = "配置值")
private String value;
/**配置项*/
@Excel(name = "配置项", width = 15)
@ApiModelProperty(value = "配置项")
private String info;
/**分组*/
@Excel(name = "分组", width = 15)
@ApiModelProperty(value = "分组")
private String dictGroup;
/**分组说明*/
@Excel(name = "分组说明", width = 15)
@ApiModelProperty(value = "分组说明")
private String dictGroupInfo;
/**创建时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**修改时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "修改时间")
private Date updateTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**创建人*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**所属部门*/
@ApiModelProperty(value = "所属部门")
private String sysOrgCode;
}

+ 14
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/mapper/TbConfMapper.java View File

@ -0,0 +1,14 @@
package org.jeecg.modules.tbConf.mapper;
import org.jeecg.modules.tbConf.entity.TbConf;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: tb_conf
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
public interface TbConfMapper extends BaseMapper<TbConf> {
}

+ 5
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/mapper/xml/TbConfMapper.xml View File

@ -0,0 +1,5 @@
<?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="org.jeecg.modules.tbConf.mapper.TbConfMapper">
</mapper>

+ 14
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/service/ITbConfService.java View File

@ -0,0 +1,14 @@
package org.jeecg.modules.tbConf.service;
import org.jeecg.modules.tbConf.entity.TbConf;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description: tb_conf
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
public interface ITbConfService extends IService<TbConf> {
}

+ 19
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/service/impl/TbConfServiceImpl.java View File

@ -0,0 +1,19 @@
package org.jeecg.modules.tbConf.service.impl;
import org.jeecg.modules.tbConf.entity.TbConf;
import org.jeecg.modules.tbConf.mapper.TbConfMapper;
import org.jeecg.modules.tbConf.service.ITbConfService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: tb_conf
* @Author: jeecg-boot
* @Date: 2024-10-28
* @Version: V1.0
*/
@Service
public class TbConfServiceImpl extends ServiceImpl<TbConfMapper, TbConf> implements ITbConfService {
}

+ 177
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue/TbConfList.vue View File

@ -0,0 +1,177 @@
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('tb_conf')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<!-- 高级查询区域 -->
<j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
:scroll="{x:true}"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
class="j-table-force-nowrap"
@change="handleTableChange">
<template slot="htmlSlot" slot-scope="text">
<div v-html="text"></div>
</template>
<template slot="imgSlot" slot-scope="text,record">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="downloadFile(text)">
下载
</a-button>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a @click="handleDetail(record)">详情</a>
</a-menu-item>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<tb-conf-modal ref="modalForm" @ok="modalFormOk"></tb-conf-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import TbConfModal from './modules/TbConfModal'
export default {
name: 'TbConfList',
mixins:[JeecgListMixin, mixinDevice],
components: {
TbConfModal
},
data () {
return {
description: 'tb_conf管理页面',
//
columns: [
{
title: '#',
dataIndex: '',
key:'rowIndex',
width:60,
align:"center",
customRender:function (t,r,index) {
return parseInt(index)+1;
}
},
{
title:'配置值',
align:"center",
dataIndex: 'value'
},
{
title:'配置项',
align:"center",
dataIndex: 'info'
},
{
title: '操作',
dataIndex: 'action',
align:"center",
fixed:"right",
width:147,
scopedSlots: { customRender: 'action' }
}
],
url: {
list: "/tbConf/tbConf/list",
delete: "/tbConf/tbConf/delete",
deleteBatch: "/tbConf/tbConf/deleteBatch",
exportXlsUrl: "/tbConf/tbConf/exportXls",
importExcelUrl: "tbConf/tbConf/importExcel",
},
dictOptions:{},
superFieldList:[],
}
},
created() {
this.getSuperFieldList();
},
computed: {
importExcelUrl: function(){
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
},
},
methods: {
initDictConfig(){
},
getSuperFieldList(){
let fieldList=[];
fieldList.push({type:'Text',value:'value',text:'配置值',dictCode:''})
fieldList.push({type:'string',value:'info',text:'配置项',dictCode:''})
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>

+ 109
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue/modules/TbConfForm.vue View File

@ -0,0 +1,109 @@
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<a-col :span="24">
<a-form-model-item label="配置值" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="value">
<a-input v-model="model.value" placeholder="请输入配置值" ></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="配置项" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="info">
<a-input v-model="model.info" placeholder="请输入配置项" ></a-input>
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
export default {
name: 'TbConfForm',
components: {
},
props: {
//
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
model:{
},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules: {
},
url: {
add: "/tbConf/tbConf/add",
edit: "/tbConf/tbConf/edit",
queryById: "/tbConf/tbConf/queryById"
}
}
},
computed: {
formDisabled(){
return this.disabled
},
},
created () {
//model
this.modelDefault = JSON.parse(JSON.stringify(this.model));
},
methods: {
add () {
this.edit(this.modelDefault);
},
edit (record) {
this.model = Object.assign({}, record);
this.visible = true;
},
submitForm () {
const that = this;
//
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
}
}
</script>

+ 84
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue/modules/TbConfModal.Style#Drawer.vue View File

@ -0,0 +1,84 @@
<template>
<a-drawer
:title="title"
:width="width"
placement="right"
:closable="false"
@close="close"
destroyOnClose
:visible="visible">
<tb-conf-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit" normal></tb-conf-form>
<div class="drawer-footer">
<a-button @click="handleCancel" style="margin-bottom: 0;">关闭</a-button>
<a-button v-if="!disableSubmit" @click="handleOk" type="primary" style="margin-bottom: 0;">提交</a-button>
</div>
</a-drawer>
</template>
<script>
import TbConfForm from './TbConfForm'
export default {
name: 'TbConfModal',
components: {
TbConfForm
},
data () {
return {
title:"操作",
width:800,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
});
},
close () {
this.$emit('close');
this.visible = false;
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
handleCancel () {
this.close()
}
}
}
</script>
<style lang="less" scoped>
/** Button按钮间距 */
.ant-btn {
margin-left: 30px;
margin-bottom: 30px;
float: right;
}
.drawer-footer{
position: absolute;
bottom: -8px;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
</style>

+ 60
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue/modules/TbConfModal.vue View File

@ -0,0 +1,60 @@
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<tb-conf-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></tb-conf-form>
</j-modal>
</template>
<script>
import TbConfForm from './TbConfForm'
export default {
name: 'TbConfModal',
components: {
TbConfForm
},
data () {
return {
title:'',
width:800,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>

+ 61
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue3/TbConf.api.ts View File

@ -0,0 +1,61 @@
import {defHttp} from '/@/utils/http/axios';
import {Modal} from 'ant-design-vue';
enum Api {
list = '/tbConf/tbConf/list',
save='/tbConf/tbConf/add',
edit='/tbConf/tbConf/edit',
deleteOne = '/tbConf/tbConf/delete',
deleteBatch = '/tbConf/tbConf/deleteBatch',
importExcel = '/tbConf/tbConf/importExcel',
exportXls = '/tbConf/tbConf/exportXls',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
*
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
*
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
*
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}

+ 33
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue3/TbConf.data.ts View File

@ -0,0 +1,33 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '配置值',
align:"center",
dataIndex: 'value'
},
{
title: '配置项',
align:"center",
dataIndex: 'info'
},
];
//查询数据
export const searchFormSchema: FormSchema[] = [
];
//表单数据
export const formSchema: FormSchema[] = [
{
label: '配置值',
field: 'value',
component: 'Input',
},
{
label: '配置项',
field: 'info',
component: 'Input',
},
];

+ 162
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue3/TbConfList.vue View File

@ -0,0 +1,162 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template #htmlSlot="{text}">
<div v-html="text"></div>
</template>
<template #fileSlot="{text}">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</template>
</BasicTable>
<!-- 表单区域 -->
<TbConfModal @register="registerModal" @success="handleSuccess"></TbConfModal>
</div>
</template>
<script lang="ts" name="tbConf-tbConf" setup>
import {ref, computed, unref} from 'vue';
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import {useModal} from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage'
import TbConfModal from './components/TbConfModal.vue'
import {columns, searchFormSchema} from './tbConf.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './tbConf.api';
const checkedKeys = ref<Array<string | number>>([]);
//model
const [registerModal, {openModal}] = useModal();
//table
const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
tableProps:{
title: 'tb_conf',
api: list,
columns,
canResize:false,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToTime: [
],
},
actionColumn: {
width: 120,
},
},
exportConfig: {
name:"tb_conf",
url: getExportUrl,
},
importConfig: {
url: getImportUrl
},
})
const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, reload);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: checkedKeys.value}, reload);
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record){
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
}
}
]
}
</script>
<style scoped>
</style>

+ 58
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbConf/vue3/components/TbConfModal.vue View File

@ -0,0 +1,58 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
<BasicForm @register="registerForm"/>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import {formSchema} from '../tbConf.data';
import {saveOrUpdate} from '../tbConf.api';
// Emits
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
//
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
});
//
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//
await resetFields();
setModalProps({confirmLoading: false,showCancelBtn:!!data?.showFooter,showOkBtn:!!data?.showFooter});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//
await setFieldsValue({
...data.record,
});
}
//
setProps({ disabled: !data?.showFooter })
});
//
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//
await saveOrUpdate(values, isUpdate.value);
//
closeModal();
//
emit('success');
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
</style>

+ 156
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/controller/TbSuggestController.java View File

@ -0,0 +1,156 @@
package org.jeecg.modules.tbSuggest.controller;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.tbSuggest.entity.TbSuggest;
import org.jeecg.modules.tbSuggest.service.ITbSuggestService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
/**
* @Description: 帮助与反馈
* @Author: jeecg-boot
* @Date: 2024-10-19
* @Version: V1.0
*/
@Api(tags="帮助与反馈")
@RestController
@RequestMapping("/tbSuggest/tbSuggest")
@Slf4j
public class TbSuggestController extends JeecgController<TbSuggest, ITbSuggestService> {
@Autowired
private ITbSuggestService tbSuggestService;
/**
* 分页列表查询
*
* @param tbSuggest
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "帮助与反馈-分页列表查询")
@ApiOperation(value="帮助与反馈-分页列表查询", notes="帮助与反馈-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<TbSuggest>> queryPageList(TbSuggest tbSuggest,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<TbSuggest> queryWrapper = QueryGenerator.initQueryWrapper(tbSuggest, req.getParameterMap());
Page<TbSuggest> page = new Page<TbSuggest>(pageNo, pageSize);
IPage<TbSuggest> pageList = tbSuggestService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param tbSuggest
* @return
*/
@AutoLog(value = "帮助与反馈-添加")
@ApiOperation(value="帮助与反馈-添加", notes="帮助与反馈-添加")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody TbSuggest tbSuggest) {
tbSuggestService.save(tbSuggest);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param tbSuggest
* @return
*/
@AutoLog(value = "帮助与反馈-编辑")
@ApiOperation(value="帮助与反馈-编辑", notes="帮助与反馈-编辑")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody TbSuggest tbSuggest) {
tbSuggestService.updateById(tbSuggest);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "帮助与反馈-通过id删除")
@ApiOperation(value="帮助与反馈-通过id删除", notes="帮助与反馈-通过id删除")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
tbSuggestService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "帮助与反馈-批量删除")
@ApiOperation(value="帮助与反馈-批量删除", notes="帮助与反馈-批量删除")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.tbSuggestService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "帮助与反馈-通过id查询")
@ApiOperation(value="帮助与反馈-通过id查询", notes="帮助与反馈-通过id查询")
@GetMapping(value = "/queryById")
public Result<TbSuggest> queryById(@RequestParam(name="id",required=true) String id) {
TbSuggest tbSuggest = tbSuggestService.getById(id);
if(tbSuggest==null) {
return Result.error("未找到对应数据");
}
return Result.OK(tbSuggest);
}
/**
* 导出excel
*
* @param request
* @param tbSuggest
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, TbSuggest tbSuggest) {
return super.exportXls(request, tbSuggest, TbSuggest.class, "帮助与反馈");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, TbSuggest.class);
}
}

+ 101
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/entity/TbSuggest.java View File

@ -0,0 +1,101 @@
package org.jeecg.modules.tbSuggest.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @Description: 帮助与反馈
* @Author: jeecg-boot
* @Date: 2024-10-19
* @Version: V1.0
*/
@Data
@TableName("tb_suggest")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="tb_suggest对象", description="帮助与反馈")
public class TbSuggest implements Serializable {
private static final long serialVersionUID = 1L;
/**主键编号*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键编号")
private String id;
/**用户id*/
@Excel(name = "用户id", width = 15)
@ApiModelProperty(value = "用户id")
private String userId;
/**用户名*/
@Excel(name = "用户名", width = 15)
@ApiModelProperty(value = "用户名")
private String userName;
/**用户手机号*/
@Excel(name = "用户手机号", width = 15)
@ApiModelProperty(value = "用户手机号")
private String userPhone;
/**问题描述*/
@Excel(name = "问题描述", width = 15)
@ApiModelProperty(value = "问题描述")
private String content;
/**问题截图*/
@Excel(name = "问题截图", width = 15)
@ApiModelProperty(value = "问题截图")
private String proofImg;
/**提交时间*/
@Excel(name = "提交时间", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "提交时间")
private Date submitTime;
/**是否回复(0:未回复 1:已回复)*/
@Excel(name = "是否回复(0:未回复 1:已回复)", width = 15)
@ApiModelProperty(value = "是否回复(0:未回复 1:已回复)")
private Integer isReply;
/**回复结果*/
@Excel(name = "回复结果", width = 15)
@ApiModelProperty(value = "回复结果")
private String replyMsg;
/**回复时间*/
@Excel(name = "回复时间", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "回复时间")
private Date replyTime;
/**回复人*/
@Excel(name = "回复人", width = 15)
@ApiModelProperty(value = "回复人")
private String replyId;
/**创建人*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**创建日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "创建日期")
private Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**更新日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "更新日期")
private Date updateTime;
/**所属部门*/
@ApiModelProperty(value = "所属部门")
private String sysOrgCode;
}

+ 14
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/mapper/TbSuggestMapper.java View File

@ -0,0 +1,14 @@
package org.jeecg.modules.tbSuggest.mapper;
import org.jeecg.modules.tbSuggest.entity.TbSuggest;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: 帮助与反馈
* @Author: jeecg-boot
* @Date: 2024-10-19
* @Version: V1.0
*/
public interface TbSuggestMapper extends BaseMapper<TbSuggest> {
}

+ 5
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/mapper/xml/TbSuggestMapper.xml View File

@ -0,0 +1,5 @@
<?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="org.jeecg.modules.tbSuggest.mapper.TbSuggestMapper">
</mapper>

+ 16
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/service/ITbSuggestService.java View File

@ -0,0 +1,16 @@
package org.jeecg.modules.tbSuggest.service;
import org.jeecg.modules.tbSuggest.entity.TbSuggest;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.stereotype.Service;
/**
* @Description: 帮助与反馈
* @Author: jeecg-boot
* @Date: 2024-10-19
* @Version: V1.0
*/
public interface ITbSuggestService extends IService<TbSuggest> {
}

+ 19
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/service/impl/TbSuggestServiceImpl.java View File

@ -0,0 +1,19 @@
package org.jeecg.modules.tbSuggest.service.impl;
import org.jeecg.modules.tbSuggest.entity.TbSuggest;
import org.jeecg.modules.tbSuggest.mapper.TbSuggestMapper;
import org.jeecg.modules.tbSuggest.service.ITbSuggestService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: 帮助与反馈
* @Author: jeecg-boot
* @Date: 2024-10-19
* @Version: V1.0
*/
@Service
public class TbSuggestServiceImpl extends ServiceImpl<TbSuggestMapper, TbSuggest> implements ITbSuggestService {
}

+ 219
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue/TbSuggestList.vue View File

@ -0,0 +1,219 @@
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="用户名">
<a-input placeholder="请输入用户名" v-model="queryParam.userName"></a-input>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="用户手机号">
<a-input placeholder="请输入用户手机号" v-model="queryParam.userPhone"></a-input>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
<a @click="handleToggleSearch" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
</a>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('帮助与反馈')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<!-- 高级查询区域 -->
<j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
:scroll="{x:true}"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
class="j-table-force-nowrap"
@change="handleTableChange">
<template slot="htmlSlot" slot-scope="text">
<div v-html="text"></div>
</template>
<template slot="imgSlot" slot-scope="text,record">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="downloadFile(text)">
下载
</a-button>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a @click="handleDetail(record)">详情</a>
</a-menu-item>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<tb-suggest-modal ref="modalForm" @ok="modalFormOk"></tb-suggest-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import TbSuggestModal from './modules/TbSuggestModal'
export default {
name: 'TbSuggestList',
mixins:[JeecgListMixin, mixinDevice],
components: {
TbSuggestModal
},
data () {
return {
description: '帮助与反馈管理页面',
//
columns: [
{
title: '#',
dataIndex: '',
key:'rowIndex',
width:60,
align:"center",
customRender:function (t,r,index) {
return parseInt(index)+1;
}
},
{
title:'用户名',
align:"center",
dataIndex: 'userName'
},
{
title:'用户手机号',
align:"center",
dataIndex: 'userPhone'
},
{
title:'问题描述',
align:"center",
dataIndex: 'content'
},
{
title:'问题截图',
align:"center",
dataIndex: 'proofImg',
scopedSlots: {customRender: 'imgSlot'}
},
{
title:'提交时间',
align:"center",
dataIndex: 'submitTime',
customRender:function (text) {
return !text?"":(text.length>10?text.substr(0,10):text)
}
},
{
title: '操作',
dataIndex: 'action',
align:"center",
fixed:"right",
width:147,
scopedSlots: { customRender: 'action' }
}
],
url: {
list: "/tbSuggest/tbSuggest/list",
delete: "/tbSuggest/tbSuggest/delete",
deleteBatch: "/tbSuggest/tbSuggest/deleteBatch",
exportXlsUrl: "/tbSuggest/tbSuggest/exportXls",
importExcelUrl: "tbSuggest/tbSuggest/importExcel",
},
dictOptions:{},
superFieldList:[],
}
},
created() {
this.getSuperFieldList();
},
computed: {
importExcelUrl: function(){
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
},
},
methods: {
initDictConfig(){
},
getSuperFieldList(){
let fieldList=[];
fieldList.push({type:'string',value:'userName',text:'用户名',dictCode:''})
fieldList.push({type:'string',value:'userPhone',text:'用户手机号',dictCode:''})
fieldList.push({type:'Text',value:'content',text:'问题描述',dictCode:''})
fieldList.push({type:'Text',value:'proofImg',text:'问题截图',dictCode:''})
fieldList.push({type:'date',value:'submitTime',text:'提交时间'})
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>

+ 124
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue/modules/TbSuggestForm.vue View File

@ -0,0 +1,124 @@
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<a-col :span="24">
<a-form-model-item label="用户名" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="userName">
<a-input v-model="model.userName" placeholder="请输入用户名" ></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="用户手机号" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="userPhone">
<a-input v-model="model.userPhone" placeholder="请输入用户手机号" ></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="问题描述" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="content">
<a-input v-model="model.content" placeholder="请输入问题描述" ></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="问题截图" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="proofImg">
<j-image-upload isMultiple v-model="model.proofImg" ></j-image-upload>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="提交时间" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="submitTime">
<j-date placeholder="请选择提交时间" v-model="model.submitTime" style="width: 100%" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
export default {
name: 'TbSuggestForm',
components: {
},
props: {
//
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
model:{
},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules: {
},
url: {
add: "/tbSuggest/tbSuggest/add",
edit: "/tbSuggest/tbSuggest/edit",
queryById: "/tbSuggest/tbSuggest/queryById"
}
}
},
computed: {
formDisabled(){
return this.disabled
},
},
created () {
//model
this.modelDefault = JSON.parse(JSON.stringify(this.model));
},
methods: {
add () {
this.edit(this.modelDefault);
},
edit (record) {
this.model = Object.assign({}, record);
this.visible = true;
},
submitForm () {
const that = this;
//
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
}
}
</script>

+ 84
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue/modules/TbSuggestModal.Style#Drawer.vue View File

@ -0,0 +1,84 @@
<template>
<a-drawer
:title="title"
:width="width"
placement="right"
:closable="false"
@close="close"
destroyOnClose
:visible="visible">
<tb-suggest-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit" normal></tb-suggest-form>
<div class="drawer-footer">
<a-button @click="handleCancel" style="margin-bottom: 0;">关闭</a-button>
<a-button v-if="!disableSubmit" @click="handleOk" type="primary" style="margin-bottom: 0;">提交</a-button>
</div>
</a-drawer>
</template>
<script>
import TbSuggestForm from './TbSuggestForm'
export default {
name: 'TbSuggestModal',
components: {
TbSuggestForm
},
data () {
return {
title:"操作",
width:800,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
});
},
close () {
this.$emit('close');
this.visible = false;
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
handleCancel () {
this.close()
}
}
}
</script>
<style lang="less" scoped>
/** Button按钮间距 */
.ant-btn {
margin-left: 30px;
margin-bottom: 30px;
float: right;
}
.drawer-footer{
position: absolute;
bottom: -8px;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
</style>

+ 60
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue/modules/TbSuggestModal.vue View File

@ -0,0 +1,60 @@
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<tb-suggest-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></tb-suggest-form>
</j-modal>
</template>
<script>
import TbSuggestForm from './TbSuggestForm'
export default {
name: 'TbSuggestModal',
components: {
TbSuggestForm
},
data () {
return {
title:'',
width:800,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>

+ 61
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue3/TbSuggest.api.ts View File

@ -0,0 +1,61 @@
import {defHttp} from '/@/utils/http/axios';
import {Modal} from 'ant-design-vue';
enum Api {
list = '/tbSuggest/tbSuggest/list',
save='/tbSuggest/tbSuggest/add',
edit='/tbSuggest/tbSuggest/edit',
deleteOne = '/tbSuggest/tbSuggest/delete',
deleteBatch = '/tbSuggest/tbSuggest/deleteBatch',
importExcel = '/tbSuggest/tbSuggest/importExcel',
exportXls = '/tbSuggest/tbSuggest/exportXls',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
*
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
*
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
*
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}

+ 81
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue3/TbSuggest.data.ts View File

@ -0,0 +1,81 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '用户名',
align:"center",
dataIndex: 'userName'
},
{
title: '用户手机号',
align:"center",
dataIndex: 'userPhone'
},
{
title: '问题描述',
align:"center",
dataIndex: 'content'
},
{
title: '问题截图',
align:"center",
dataIndex: 'proofImg',
customRender:render.renderAvatar,
},
{
title: '提交时间',
align:"center",
dataIndex: 'submitTime',
customRender:({text}) =>{
return !text?"":(text.length>10?text.substr(0,10):text)
},
},
];
//查询数据
export const searchFormSchema: FormSchema[] = [
{
label: "用户名",
field: "userName",
component: 'Input',
colProps: {span: 6},
},
{
label: "用户手机号",
field: "userPhone",
component: 'Input',
colProps: {span: 6},
},
];
//表单数据
export const formSchema: FormSchema[] = [
{
label: '用户名',
field: 'userName',
component: 'Input',
},
{
label: '用户手机号',
field: 'userPhone',
component: 'Input',
},
{
label: '问题描述',
field: 'content',
component: 'Input',
},
{
label: '问题截图',
field: 'proofImg',
component: 'JImageUpload',
componentProps:{
},
},
{
label: '提交时间',
field: 'submitTime',
component: 'DatePicker',
},
];

+ 162
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue3/TbSuggestList.vue View File

@ -0,0 +1,162 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template #htmlSlot="{text}">
<div v-html="text"></div>
</template>
<template #fileSlot="{text}">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</template>
</BasicTable>
<!-- 表单区域 -->
<TbSuggestModal @register="registerModal" @success="handleSuccess"></TbSuggestModal>
</div>
</template>
<script lang="ts" name="tbSuggest-tbSuggest" setup>
import {ref, computed, unref} from 'vue';
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import {useModal} from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage'
import TbSuggestModal from './components/TbSuggestModal.vue'
import {columns, searchFormSchema} from './tbSuggest.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './tbSuggest.api';
const checkedKeys = ref<Array<string | number>>([]);
//model
const [registerModal, {openModal}] = useModal();
//table
const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
tableProps:{
title: '帮助与反馈',
api: list,
columns,
canResize:false,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToTime: [
],
},
actionColumn: {
width: 120,
},
},
exportConfig: {
name:"帮助与反馈",
url: getExportUrl,
},
importConfig: {
url: getImportUrl
},
})
const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, reload);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: checkedKeys.value}, reload);
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record){
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
}
}
]
}
</script>
<style scoped>
</style>

+ 58
- 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/tbSuggest/vue3/components/TbSuggestModal.vue View File

@ -0,0 +1,58 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
<BasicForm @register="registerForm"/>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import {formSchema} from '../tbSuggest.data';
import {saveOrUpdate} from '../tbSuggest.api';
// Emits
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
//
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
});
//
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//
await resetFields();
setModalProps({confirmLoading: false,showCancelBtn:!!data?.showFooter,showOkBtn:!!data?.showFooter});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//
await setFieldsValue({
...data.record,
});
}
//
setProps({ disabled: !data?.showFooter })
});
//
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//
await saveOrUpdate(values, isUpdate.value);
//
closeModal();
//
emit('success');
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
</style>

+ 44
- 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/postBean/SuggestReq.java View File

@ -0,0 +1,44 @@
package org.jeecg.modules.postBean;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
import java.io.Serializable;
/**
* @Description: 帮助与反馈
* @Author: jeecg-boot
* @Date: 2024-10-19
* @Version: V1.0
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="问题反馈", description="帮助与反馈")
public class SuggestReq implements Serializable {
private static final long serialVersionUID = 1L;
/**用户名*/
@Excel(name = "用户名", width = 15)
@ApiModelProperty(value = "用户名")
private String userName;
/**用户手机号*/
@Excel(name = "用户手机号", width = 15)
@ApiModelProperty(value = "用户手机号")
private String userPhone;
/**问题描述*/
@Excel(name = "问题描述", width = 15)
@ApiModelProperty(value = "问题描述")
private String content;
/**问题截图*/
@Excel(name = "问题截图", width = 15)
@ApiModelProperty(value = "问题截图")
private String proofImg;
}

+ 0
- 39
jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/UserController.java View File

@ -1,39 +0,0 @@
package org.jeecg.modules.user;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 服务化 system模块 对外接口请求类
* @author: jeecg-boot
*/
@Slf4j
@RestController
@RequestMapping("/user/")
public class UserController {
@Autowired
private SysBaseApiImpl sysBaseApi;
@Autowired
private ISysUserService sysUserService;
/**
* 发送系统消息
* @param message 使用构造器赋值参数 如果不设置category(消息类型)则默认为2 发送系统消息
*/
@PostMapping("/sendSysAnnouncement")
public void sendSysAnnouncement(@RequestBody MessageDTO message){
sysBaseApi.sendSysAnnouncement(message);
}
}

+ 79
- 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/controller/IndexController.java View File

@ -0,0 +1,79 @@
package org.jeecg.modules.user.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xkcoding.http.HttpUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.config.shiro.ShiroRealm;
import org.jeecg.modules.user.service.IndexService;
import org.jeecg.modules.banner.entity.WebBanner;
import org.jeecg.modules.hanHaiMember.entity.HanHaiMember;
import org.jeecg.modules.postBean.SuggestReq;
import org.jeecg.modules.tbSuggest.entity.TbSuggest;
import org.jeecg.modules.tbSuggest.service.ITbSuggestService;
import org.jeecg.modules.utils.ValidateTool;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Author scott
* @since 2018-12-17
*/
@RestController
@RequestMapping("/index")
@Api(tags = "首页等展示接口")
@Slf4j
public class IndexController {
@Resource
private ITbSuggestService tbSuggestService;
@Resource
private IndexService indexService;
@Resource
private ShiroRealm shiroRealm;
@Resource
private RedisUtil redisUtil;
@ApiOperation(value = "我的头像昵称,平台客户电话等信息")
@RequestMapping(value = "/index", method = RequestMethod.POST)
public Result index(@RequestHeader("X-Access-Token") String token) {
Result<?> indexInfo = indexService.getIndexInfo(token);
return indexInfo;
}
@ApiOperation(value = "获取banner列表")
@RequestMapping(value = "/bannerList", method = RequestMethod.POST)
public Result<Map<Integer, List<WebBanner>>> bannerList(@RequestHeader("X-Access-Token") String token) {
return indexService.bannerList();
}
@ApiOperation(value = "帮助与反馈", notes = "帮助与反馈")
@PostMapping(value = "/addSuggest")
public Result<String> addSuggest(@RequestBody SuggestReq tbSuggest, @RequestHeader("X-Access-Token") String token) {
HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiAccount(token);
TbSuggest tbSuggest1 = new TbSuggest();
BeanUtils.copyProperties(tbSuggest, tbSuggest1);
tbSuggest1.setUserId(hanHaiMember.getId());
tbSuggestService.save(tbSuggest1);
return Result.OK("添加成功!");
}
}

+ 35
- 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/controller/UserController.java View File

@ -0,0 +1,35 @@
package org.jeecg.modules.user.controller;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.bean.LoginReq;
import org.jeecg.modules.user.service.AppletLoginService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 服务化 system模块 对外接口请求类
* @author: jeecg-boot
*/
@Slf4j
@RestController
@RequestMapping("/user/")
public class UserController {
@Resource
private AppletLoginService appletLoginService;
//小程序授权登录
@ApiOperation(value="小程序-登录接口", notes="小程序-登录接口")
@GetMapping("/login")
public Result<?> login(LoginReq loginReq){
return appletLoginService.appletLogin(loginReq);
}
}

+ 15
- 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/service/AppletLoginService.java View File

@ -0,0 +1,15 @@
package org.jeecg.modules.user.service;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.bean.LoginReq;
public interface AppletLoginService {
/**
* 微信小程序登录接口
* @param loginReq
* @return
*/
Result<Object> appletLogin(LoginReq loginReq);
}

+ 18
- 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/service/IndexService.java View File

@ -0,0 +1,18 @@
package org.jeecg.modules.user.service;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.banner.entity.WebBanner;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public interface IndexService {
//获取首页基础信息
Result<?> getIndexInfo(String token);
Result<Map<Integer, List<WebBanner>>> bannerList();
}

+ 238
- 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/service/impl/AppletLoginServiceImpl.java View File

@ -0,0 +1,238 @@
package org.jeecg.modules.user.service.impl;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.bean.HttpConf;
import org.jeecg.modules.bean.LoginReq;
import org.jeecg.modules.hanHaiMember.entity.HanHaiMember;
import org.jeecg.modules.hanHaiMember.service.IHanHaiMemberService;
import org.jeecg.modules.user.service.AppletLoginService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Service
public class AppletLoginServiceImpl implements AppletLoginService {
@Value("${wechat.mpAppId}")
private String mpAppId;
@Value("${wechat.mpAppSecret}")
private String mpAppSecret;
@Resource
private IHanHaiMemberService memberService;
@Resource
private RedisUtil redisUtil;
@Resource
private HttpConf httpConf;
/**
* 微信小程序登录接口
* @param loginReq
* @return
*/
@Transactional(rollbackFor = {Exception.class})
public Result<Object> appletLogin(LoginReq loginReq) {
Result<Object> result = new Result<>();
Map<String, Object> map = new HashMap<>();
if (StringUtils.isBlank(loginReq.getCode())) {
throw new JeecgBootException("小程序code为空");
}
String loginUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + mpAppId + "&secret=" + mpAppSecret+ "&js_code=" + loginReq.getCode() + "&grant_type=authorization_code";
//使用工具类
JSONObject json_test = httpConf.getJSONObject(loginUrl);
String wxOpenid = json_test.getString("openid");
String sessionKey = json_test.getString("session_key");
if (StringUtils.isBlank(wxOpenid)) {
throw new JeecgBootException("未获取到openid");
}
HanHaiMember member = memberService.lambdaQuery().eq(HanHaiMember::getAppletOpenid,wxOpenid).one();
if (member == null) {
//如果user等于null说明该用户第一次登录数据库没有该用户信息
loginReq.setOpenid(wxOpenid);
loginReq.setSession_key(sessionKey);
member = new HanHaiMember();
// member.setSesssionKey(sessionKey);
member.setAppletOpenid(wxOpenid);
member.setNickName(loginReq.getNickName());
member.setHeadImage(loginReq.getHeadimgurl());
// 生成token返回给小程序端
String token = JwtUtil.sign(member.getAppletOpenid(), wxOpenid);
memberService.save(member);
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
// 设置超时时间
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 100);
map.put("userInfo", member);
map.put("token", token);
result.setCode(200);
result.setResult(map);
return result;
} else {
// member.setHeadImage(loginReq.getHeadimgurl());
// member.setSessionKey(sessionKey);
// memberService.saveOrUpdate(member);
// 生成token返回给小程序端
String token = JwtUtil.sign(member.getAppletOpenid(), wxOpenid);
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
// 设置超时时间
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 100);
map.put("userInfo", member);
map.put("token", token);
//用户id做im账号
result.setResult(map);
result.setCode(200);
// result.setMessage(member.getNickName()+"已于"+member.getCreateTime()+"注册成功!请勿重复注册!");
// // 未绑定手机号跳转授权绑定手机号
// if (StringUtils.isBlank(member.getPhone())) {
// result.setMessage("该微信用户尚未绑定手机号,请授权手机进行绑定");
// result.setCode(905);
// result.setResult(map);
// return result;
// }
}
return result;
}
// /**
// * 微信小程序登录绑定手机号码接口
// * @param loginReq
// * @return
// */
// @Transactional(rollbackFor = Exception.class)
// @Override
// public Result<Object> bindPhone(LoginReq loginReq) {
// Result<Object> result = new Result<>();
// if (StringUtils.isEmpty(loginReq.getEncryptedData())) {
// result.setCode(500);
// result.setMessage("请授权手机号");
// return result;
// }
// String loginUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + mpAppId + "&secret=" + mpAppSecret+ "&js_code=" + loginReq.getCode() + "&grant_type=authorization_code";
// CloseableHttpClient client = null;
// CloseableHttpResponse response = null;
// try {
// // 创建http GET请求
// HttpGet httpGet = new HttpGet(loginUrl);
// client = HttpClients.createDefault();
// // 执行请求
// response = client.execute(httpGet);
// HttpEntity entity = response.getEntity();//得到返回数据
// String resultStr = EntityUtils.toString(entity);
// JSONObject json_test = JSONObject.parseObject(resultStr);
// String wxOpenid = json_test.getString("openid");
// if (StringUtils.isEmpty(wxOpenid)) {
// return result.error500("未获取到openid");
// }
// String sessionKey = json_test.getString("session_key");
// // 保存sessionKey,用于解析手机号码
// loginReq.setOpenid(wxOpenid);
// loginReq.setSession_key(sessionKey);
// String userPhone = getPhoneNumber(loginReq);
// HanHaiMember one = memberService.lambdaQuery().eq(HanHaiMember::getAppletOpenid, wxOpenid).one();
// if(one!=null){
// return result.OK("请不要重复注册");
// }
// HanHaiMember member = new HanHaiMember();
// member.setSessionKey(sessionKey);
// member.setAppletOpenid(wxOpenid);
// member.setNickName(loginReq.getNickName());
// member.setHeadImage(loginReq.getHeadimgurl());
// member.setPhone(userPhone);
//
//
// //判断用户是否存在
// HanHaiMember boolOne = memberService.lambdaQuery().eq(HanHaiMember::getAccount, loginReq.geta()).one();
// boolean bool = false;
// if(one != null){
// bool = true;
// }
//
// if(!bool){
// member.setId(boolOne.getId());
// memberService.updateById(member);
// }else{
// memberService.save(member);
// }
//
//
//
// return result.OK("注册成功",member);
// }catch(Exception e) {
// e.printStackTrace();
// return Result.error("操作失败,请联系系统管理员!");
// }
//
// }
//
//
//
// /**
// * 解析电话号码
// * @param loginReq
// * @return
// */
// public String getPhoneNumber(LoginReq loginReq) {
// String encryptedData = loginReq.getEncryptedData();
// String session_key = loginReq.getSession_key();
// String iv = loginReq.getIv();
// // 被加密的数据
// byte[] dataByte = Base64.decodeBase64(encryptedData);
// // 加密秘钥
// byte[] keyByte = Base64.decodeBase64(session_key);
// // 偏移量
// byte[] ivByte = Base64.decodeBase64(iv);
// try {
// // 如果密钥不足16位那么就补足. 这个if 中的内容很重要
// int base = 16;
// if (keyByte.length % base != 0) {
// int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
// byte[] temp = new byte[groups * base];
// Arrays.fill(temp, (byte) 0);
// System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
// keyByte = temp;
// }
// // 初始化
// Security.addProvider(new BouncyCastleProvider());
// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
// SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
// AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
// parameters.init(new IvParameterSpec(ivByte));
// cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
// byte[] resultByte = cipher.doFinal(dataByte);
// if (null != resultByte && resultByte.length > 0) {
// String result = new String(resultByte, "UTF-8");
// JSONObject userPhoneObj = JSONObject.parseObject(result);
// Map<String, Object> userMap = new HashMap<>();
// for (Map.Entry<String, Object> entry : userPhoneObj.entrySet()) {
// userMap.put(entry.getKey(), entry.getValue());
// }
// // 获取phoneNumber 带区号
// String userPhone = (String) userMap.get("phoneNumber");
// return userPhone;
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// return null;
// }
}

+ 83
- 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/user/service/impl/IndexServiceImpl.java View File

@ -0,0 +1,83 @@
package org.jeecg.modules.user.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.config.shiro.ShiroRealm;
import org.jeecg.modules.banner.entity.WebBanner;
import org.jeecg.modules.banner.service.IWebBannerService;
import org.jeecg.modules.hanHaiMember.entity.HanHaiMember;
import org.jeecg.modules.tbConf.entity.TbConf;
import org.jeecg.modules.tbConf.service.ITbConfService;
import org.jeecg.modules.user.service.IndexService;
import org.jeecg.modules.utils.ValidateTool;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class IndexServiceImpl implements IndexService {
@Resource
private IWebBannerService webBannerService;
@Resource
private ITbConfService tbConfService;
@Resource
private ShiroRealm shiroRealm;
// @Resource
// private ITbUserRoleService tbUserRoleService;
@Resource
private RedisUtil redisUtil;
@Override
public Result<?> getIndexInfo(String token) {
HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiAccount(token);
hanHaiMember.setPasswordSalt(null);
JSONObject jsonObject = new JSONObject();
QueryWrapper<TbConf> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.eq("name", "sys_phone");
TbConf one = tbConfService.getOne(objectQueryWrapper);
//平台客户电话号码
jsonObject.put("phone", ValidateTool.isNull(one) ? "19198239116" : one.getValue());
jsonObject.put("my", hanHaiMember);
//清关背景图
QueryWrapper<TbConf> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "sys_pic_qg");
TbConf pic = tbConfService.getOne(queryWrapper);
jsonObject.put("pic", ValidateTool.isNull(pic) ? "https://dianpin-img.xzaiyp.top/temp/组478612x_1730704228537.png" : pic.getValue());
// LambdaQueryWrapper<TbUserRole> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
// objectLambdaQueryWrapper.eq(TbUserRole::getUserId, hanHaiMember.getId()).
// eq(TbUserRole::getRole, 0).eq(TbUserRole::getAuditStatus, 1);
// TbUserRole cg = tbUserRoleService.getOne(objectLambdaQueryWrapper);
// LambdaQueryWrapper<TbUserRole> queryWrapper1 = new LambdaQueryWrapper<>();
// queryWrapper1.eq(TbUserRole::getUserId, hanHaiMember.getId()).
// eq(TbUserRole::getRole, 1).eq(TbUserRole::getAuditStatus, 1);
// TbUserRole shop = tbUserRoleService.getOne(queryWrapper1);
//// 返回采购商身份信息
// jsonObject.put("buy", cg);
//// 返回供应商身份信息
// jsonObject.put("shop", shop);
return Result.OK(jsonObject);
}
@Override
public Result<Map<Integer, List<WebBanner>>> bannerList() {
//获取banner
QueryWrapper<WebBanner> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.eq("is_disable", 0).orderByDesc("sort");
List<WebBanner> bannerList = webBannerService.list(objectQueryWrapper);
//分组排序返回
Map<Integer, List<WebBanner>> collect = bannerList.stream().sorted(Comparator.comparing(WebBanner::getSort).reversed()).collect(Collectors.groupingBy(WebBanner::getType));
return Result.ok(collect);
}
}

+ 381
- 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/utils/ValidateTool.java View File

@ -0,0 +1,381 @@
package org.jeecg.modules.utils;
import org.jeecg.common.exception.JeecgBootException;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ValidateTool {
public static boolean isEmpty(Collection coll) {
return coll == null || coll.isEmpty();
}
public static boolean isEmpty(CharSequence cs) {
return cs == null || cs.length() == 0;
}
public static boolean isNotEmpty(Collection coll) {
return !isEmpty(coll);
}
public static boolean isNotEmpty(CharSequence cs) {
return !isEmpty(cs);
}
/**
* 是否为空白字符串 字符串仅为空格回车换行制表符空字符串... 返回false
* @param cs
* @return
*/
public static boolean isBlank(CharSequence cs) {
int strLen = length(cs);
if (strLen == 0) {
return true;
} else {
for(int i = 0; i < strLen; ++i) {
if (!Character.isWhitespace(cs.charAt(i))) {
return false;
}
}
return true;
}
}
public static boolean isNotBlank(CharSequence cs) {
return !isBlank(cs);
}
public static int length(CharSequence cs) {
return cs == null ? 0 : cs.length();
}
/**
* 验证参数是否为空
*
* @param obj
* @return 不为?:true,为空false
* @throws
*/
public static boolean checkIsNull(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof String) {
if (((String) obj).trim().equals("")) {
return false;
}
}
return true;
}
public static boolean isNull(Object obj) {
if (obj == null) {
return true;
}
if (obj instanceof String) {
if (((String) obj).trim().equals("")) {
return true;
}
}
return false;
}
public static boolean isNotNull(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof String) {
if (((String) obj).trim().equals("")) {
return false;
}
}
return true;
}
// String regName = "^[A-Za-z0-9]{6,40}$";
// if (!userCustomerModel.getUsername().matches(regName)) {
// throw new JeecgBootException(MessageUtil.getMessage("COMMON_CHEECKNAME_ERROR_CODE"), MessageUtil.getMessage("COMMON_CHEECKNAME_ERROR"));
// }
public static boolean checkIsWX(String str){
//微信号码
// 微信号规则微信账号仅支持6-20个字母数字下划线或减号以字母开头解释一下只要是字母开头可以是纯字母hjqzHJQZhongjiqiezi或字母数字混合
String pattern = "^[a-zA-Z]{1}[-_a-zA-Z0-9]{5,19}+$";
boolean isMatch = Pattern.matches(pattern, str);
if (isMatch==false) {
throw new JeecgBootException("微信号不合法");
}
return true;
};
public static boolean checkIsQQ(String str){
//数字范围5-14个之间
String pattern = "[1-9][0-9]{4,14}";
boolean isMatch = Pattern.matches(pattern, str);
if (isMatch==false) {
throw new JeecgBootException("QQ号不合法");
}
return true;
}
//
//^[a-zA-Z][a-zA-Z0-9_]{4,15}$
public static boolean checkIsName(String str){
Pattern p = Pattern.compile("[\\u4e00-\\u9fa5]");
Matcher m = p.matcher(str);
if (m.matches()) {
return true;
} else {
throw new JeecgBootException("用户名不合法");
}
}
/**
* 验证参数长度
*
* @param code 参数名称
* @param obj
* @param begin
* @param end
* @return boolean
* @throws
*/
public static boolean checkParamLength(String code, Object obj, int begin, int end) {
if (!checkIsNull(obj)) {
throw new JeecgBootException(format("{0}不能为空,请确认", code));
}
if (obj instanceof String) {
if (!checkLength((String) obj, begin, end)) {
throw new JeecgBootException(format("验证码错误", code));
}
}
return true;
}
/**
* @description 验证参数是否为空以及参数长度是否符合要求
* @param code, obj, begin, end
* @return boolean
* @date 2019/6/24/024
*/
public static boolean checkParam(String code, Object obj, int begin, int end) {
if (!checkIsNull(obj)) {
throw new JeecgBootException(format("{0}不能为空,请确认", code));
}
if (obj instanceof String) {
if (!checkLength((String) obj, begin, end)) {
throw new JeecgBootException(format("{0}长度不符合格式", code));
}
}
return true;
}
public static String format(String message, Object... arg) {
MessageFormat formatter = new MessageFormat(message);
String output = formatter.format(arg);
return output;
}
public static int totalLength(String content) {
String regex = "[\u4e00-\u9fa5]";
int length = content.length();
int chineseLength = content.length() - content.replaceAll(regex, "").length();
return length+chineseLength;
}
/**
* @description 判断字符串是不是汉字
* @param: con
* @param: ignore 是否忽略 · 这个符号
* @return boolean
* @date 2019/9/20/020
*/
public static boolean isChinese(String con,boolean ignore) {
for (int i = 0; i < con.length(); i = i + 1) {
if (ignore){
if (!Pattern.compile("[\u4e00-\u9fa5]").matcher(
String.valueOf(con.charAt(i))).find() && !"·".equals(String.valueOf(con.charAt(i)))) {
return false;
}
}else {
if (!Pattern.compile("[\u4e00-\u9fa5]").matcher(
String.valueOf(con.charAt(i))).find()) {
return false;
}
}
}
return true;
}
/**
* @description 判断是不是中文或英文字母
* @param: con
* @return boolean
* @date 2019/9/20/020
*/
public static boolean conValidate(String con) {
if (null != con && !"".equals(con)) {
if ((isChinese(con,true) || con.matches("^[A-Za-z]+$"))) {
return true;
}
}
return false;
}
/**
* 验证参数长度
*
* @param code 参数名称
* @param obj
* @return boolean
* @throws
*/
public static boolean checkParamIsNull(String code, Object obj) {
if (!checkIsNull(obj)) {
throw new JeecgBootException(format("{0}不能为空,请确认", code));
}
return true;
}
public static boolean checkLength(String str, int begin, int end) {
if (str == null) {
return false;
}
if (str.length() <= end && str.length() >= begin) {
return true;
}
return false;
}
/**
* 验证是否为手机号?
*
* @throws JeecgBootException
*/
public static boolean checkParamIsMobile(String mobile) {
if (mobile == null || mobile == "") {
throw new JeecgBootException( "请填写手机号");
}
if (!isMobileNO(mobile)) {
throw new JeecgBootException( "手机号错误");
}
return true;
}
//验证手机号码格式
public static boolean isMobileNO(String mobiles) {
// if (mobiles == null ) {
// return false;
// }
// else {
// return true;
// }
if (!checkIsNull(mobiles)) {
return false;
}
String pattern = "(0|86)?(13[0-9]|14[0-9]|15[0-9]|16[012345689]|17[2-9]|18[0-9]|19[0-9])[0-9]{8}";
//手机号码
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(mobiles);
if (m.matches()) {
return true;
} else {
return false;
}
}
/**
* 验证输入的邮箱格式是否符合
*
* @param email
* @return 是否合法
*/
public static boolean emailFormat(String email) {
boolean tag = true;
final String pattern1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
final Pattern pattern = Pattern.compile(pattern1);
final Matcher mat = pattern.matcher(email);
if (!mat.find()) {
tag = false;
}
return tag;
}
public static boolean isNum(String code, String value) {
if (value == null) {
throw new JeecgBootException(format("{0}不能为空,请确认", code));
}
String pattern = "^[0-9]+$";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(value);
if (!m.matches()) {
throw new JeecgBootException(format("{0}数据不符合格式", code));
}
return true;
}
public static boolean isBankCard(String value) {
if (isNull(value)) {
throw new JeecgBootException("银行卡号不能为空,请确认");
}
String pattern = "^[0-9]+$";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(value);
if (!m.matches()) {
throw new JeecgBootException("银行卡号格式错误");
}
if (value.length()<16 || value.length()>19) {
throw new JeecgBootException("银行卡号格式错误");
}
return true;
}
public static boolean isDecimalValid(String code, String str, int start, int end) {
checkParamIsNull(code, str);
int s = 0;
try {
s = Integer.parseInt(str);
} catch (Exception e) {
throw new JeecgBootException(format("{0}数据不符合格式", code));
}
if (end == start) {
if (end == s) {
return true;
} else {
throw new JeecgBootException(format("{0}数据不符合格式", code));
}
} else {
if (s <= end && s >= start) {
return true;
}
}
throw new JeecgBootException(format("{0}数据不符合格式", code));
}
}

+ 37
- 0
jeecg-boot-module-system/src/main/resources/application-dev.yml View File

@ -329,3 +329,40 @@ third-app:
client-secret: ??
agent-id: ??
#配置微信
wechat:
mpAppId: wxe631bce44d54667e
mpAppSecret: 2f19c405ea9bb523f350b5a9fd01b878
mchId:
mchKey:
keyPath: /usr/local/cert/apiclient_cert.p12
notifyUrl:
page: /pages/loginAgreement/login
codeImg: /usr/codeImage
savePath: WxCodeFile
keyPemPath: apiclient_key.pem
serialNo:
apiV3Key:
baseUrl: https://api.mch.weixin.qq.com/v3
wxpay:
#应用编号
appId:
#商户号
mchId:
# APIv2密钥
apiKey:
# APIv3密钥
apiV3Key:
# 微信支付V3-url前缀
baseUrl: https://api.mch.weixin.qq.com/v3
# 密钥路径,resources根目录下
keyPemPath: apiclient_key.pem
#商户证书序列号
serialNo:
# 支付通知回调, pjm6m9.natappfree.cc 为内网穿透地址
notifyUrl:
# 退款通知回调, pjm6m9.natappfree.cc 为内网穿透地址
refundNotifyUrl:

+ 368
- 0
jeecg-boot-module-system/src/main/resources/application-prod.yml View File

@ -0,0 +1,368 @@
server:
port: 8000
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
servlet:
context-path: /employ-admin
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
management:
endpoints:
web:
exposure:
include: metrics,httptrace
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
mail:
host: smtp.qq.com
username:
password:
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
## quartz定时任务,采用数据库方式
quartz:
job-store-type: jdbc
initialize-schema: embedded
#定时任务启动开关,true-开 false-关
auto-startup: true
#启动时更新己存在的Job
overwrite-existing-jobs: true
properties:
org:
quartz:
scheduler:
instanceName: MyScheduler
instanceId: AUTO
jobStore:
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
misfireThreshold: 60000
clusterCheckinInterval: 10000
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
#json 时间戳统一转换
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
jpa:
open-in-view: false
activiti:
check-process-definitions: false
#启用作业执行器
async-executor-activate: false
#启用异步执行器
job-executor-activate: false
aop:
proxy-target-class: true
#配置freemarker
freemarker:
# 设置模板后缀名
suffix: .ftl
# 设置文档类型
content-type: text/html
# 设置页面编码格式
charset: UTF-8
# 设置页面缓存
cache: false
prefer-file-system-access: false
# 设置ftl文件路径
template-loader-path:
- classpath:/templates
# 设置静态文件路径,js,css等
mvc:
static-path-pattern: /**
#Spring Boot 2.6+后映射匹配的默认策略已从AntPathMatcher更改为PathPatternParser,需要手动指定为ant-path-matcher
pathmatch:
matching-strategy: ant_path_matcher
resource:
static-locations: classpath:/static/,classpath:/public/
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
datasource:
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: 123456
allow:
web-stat-filter:
enabled: true
dynamic:
druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
# 连接池的配置信息
# 初始化大小,最小,最大
initial-size: 5
min-idle: 5
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
# connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
datasource:
master:
url: jdbc:mysql://8.138.162.67:3306/employ2?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false
username: root
password: Fk4q*h@V
driver-class-name: com.mysql.cj.jdbc.Driver
# 多数据源配置
#multi-datasource1:
#url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
#username: root
#password: root
#driver-class-name: com.mysql.cj.jdbc.Driver
#redis 配置
redis:
database: 4
host: 8.138.162.67
lettuce:
pool:
max-active: -1 #最大连接数据库连接数,设 -1 为没有限制
max-idle: 0 #最大等待连接中的数量,设 0 为没有限制
max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
shutdown-timeout: 1000ms
password: 'gmmGMM@2024'
port: 6379
#mybatis plus 设置
mybatis-plus:
mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml
global-config:
# 关闭MP3.0自带的banner
banner: false
db-config:
#主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";
id-type: ASSIGN_ID
# 默认数据库表下划线命名
table-underline: true
configuration:
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 返回类型为Map,显示null对应的字段
call-setters-on-nulls: true
#jeecg专用配置
minidao :
base-package: org.jeecg.modules.jmreport.*
jeecg :
# 是否启用安全模式
safeMode: false
# 签名密钥串(前后端要一致,正式发布请自行修改)
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
# 本地:local\Minio:minio\阿里云:alioss
uploadType: alioss
path :
#文件上传根目录 设置
upload: /opt/upFiles
#webapp文件路径
webapp: /opt/webapp
shiro:
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**
#阿里云oss存储和大鱼短信秘钥配置
oss:
accessKey: LTAI5tPfZo39q2r9Sr5mW84u
secretKey: XxExGallsV4O9nERHpVsQg2XtPCU7r
endpoint: oss-cn-guangzhou.aliyuncs.com
bucketName: augcl
staticDomain: https://img.augcl.com
# ElasticSearch 6设置
elasticsearch:
cluster-name: jeecg-ES
cluster-nodes: 127.0.0.1:9200
check-enabled: false
# 表单设计器配置
desform:
# 主题颜色(仅支持 16进制颜色代码)
theme-color: "#1890ff"
# 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)
upload-type: system
map:
# 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home
baidu: ??
# 在线预览文件服务器地址配置
file-view-domain: 127.0.0.1:8012
# minio文件上传
minio:
minio_url: http://minio.jeecg.com
minio_name: ??
minio_pass: ??
bucketName: otatest
#大屏报表参数设置
jmreport:
mode: dev
#数据字典是否进行saas数据隔离,自己看自己的字典
saas: false
#是否需要校验token
is_verify_token: true
#必须校验方法
verify_methods: remove,delete,save,add,update
#自定义项目前缀
customPrePath:
pageSize:
- 10
- 20
- 30
- 40
#Wps在线文档
wps:
domain: https://wwo.wps.cn/office/
appid: ??
appsecret: ??
#xxl-job配置
xxljob:
enabled: false
adminAddresses: http://127.0.0.1:9080/xxl-job-admin
appname: ${spring.application.name}
accessToken: ''
address: 127.0.0.1:30007
ip: 127.0.0.1
port: 30007
logPath: logs/jeecg/job/jobhandler/
logRetentionDays: 30
route:
config:
data-id: jeecg-gateway-router
group: DEFAULT_GROUP
#自定义路由配置 yml nacos database
data-type: database
#分布式锁配置
redisson:
address: 127.0.0.1:6379
password:
type: STANDALONE
enabled: true
#cas单点登录
cas:
prefixUrl: http://cas.example.org:8443/cas
#Mybatis输出sql日志
logging:
level:
org.jeecg.modules.system.mapper : info
#swagger
knife4j:
#开启增强配置
enable: true
#开启生产环境屏蔽
production: false
basic:
enable: false
username: jeecg
password: jeecg1314
#第三方登录
justauth:
enabled: true
type:
GITHUB:
client-id: ??
client-secret: ??
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/github/callback
WECHAT_ENTERPRISE:
client-id: ??
client-secret: ??
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_enterprise/callback
agent-id: ??
DINGTALK:
client-id: ??
client-secret: ??
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/dingtalk/callback
WECHAT_OPEN:
client-id: ??
client-secret: ??
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_open/callback
cache:
type: default
prefix: 'demo::'
timeout: 1h
#第三方APP对接
third-app:
enabled: false
type:
#企业微信
WECHAT_ENTERPRISE:
enabled: false
#CORP_ID
client-id: ??
#SECRET
client-secret: ??
#自建应用id
agent-id: ??
#自建应用秘钥(新版企微需要配置)
# agent-app-secret: ??
#钉钉
DINGTALK:
enabled: false
# appKey
client-id: ??
# appSecret
client-secret: ??
agent-id: ??
#配置微信
wechat:
mpAppId:
mpAppSecret:
mchId:
mchKey:
keyPath: /usr/local/cert/apiclient_cert.p12
notifyUrl:
page: /pages/loginAgreement/login
codeImg: /usr/codeImage
savePath: WxCodeFile
keyPemPath: apiclient_key.pem
serialNo:
apiV3Key:
baseUrl: https://api.mch.weixin.qq.com/v3
wxpay:
#应用编号
appId:
#商户号
mchId:
# APIv2密钥
apiKey:
# APIv3密钥
apiV3Key:
# 微信支付V3-url前缀
baseUrl: https://api.mch.weixin.qq.com/v3
# 密钥路径,resources根目录下
keyPemPath: apiclient_key.pem
#商户证书序列号
serialNo:
# 支付通知回调, pjm6m9.natappfree.cc 为内网穿透地址
notifyUrl:
# 退款通知回调, pjm6m9.natappfree.cc 为内网穿透地址
refundNotifyUrl:

Loading…
Cancel
Save