微信小程序——简单的售后服务单
使用工具:HBuilder X、微信开发者工具
使用框架:uniapp+uview
一、数据库设计
feedback(用于存储反馈信息)
id int 11 0 0 0 -1 0 0 0 0 0 -1 0 0
userid varchar 255 0 0 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
ptype varchar 255 0 0 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
descr varchar 255 0 0 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
comp varchar 255 0 0 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
uname varchar 255 0 0 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
phone varchar 255 0 0 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
ftime varchar 255 0 0 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
pictu(用于存储图片信息)
id int 11 0 0 0 -1 0 0 0 0 0 -1 0 0
pic varchar 255 0 -1 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
time varchar 255 0 -1 0 0 0 utf8 utf8_general_ci 0 0 0 0 0 0 0
注:因为能力有限,所以只能存储图片到本地,并未将反馈图片返回到前端,并且后台只能通过时间确定pictu与feedback是否为同一条反馈
二、后端设计(springboot)
1、新建boot项目
2、配置pom.xml文件(直接复制食用,可能有些没用的)
<properties>
<java.version>1.8</java.version>
<repackage.classifier/>
<spring-native.version>0.10.2</spring-native.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
<version>${spring-native.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!--引入druid数据源-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- 自定义配置的提示 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.sql</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<!-- mvn mybatis-generator:generate -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
<classifier>${repackage.classifier}</classifier>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
</env>
</image>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<version>${spring-native.version}</version>
<executions>
<execution>
<id>test-generate</id>
<goals>
<goal>test-generate</goal>
</goals>
</execution>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<profiles>
<profile>
<id>native</id>
<properties>
<repackage.classifier>exec</repackage.classifier>
<native-buildtools.version>0.9.1</native-buildtools.version>
</properties>
</profile>
</profiles>
</project>
3、新建generatorConfig.xml(resources中,用于mybatis生成dao、mapper、domain三层)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
<classPathEntry
location="C:\Users\chenghao\.m2\repository\mysql\mysql-connector-java\8.0.26\mysql-connector-java-8.0.26.jar" />
//这个路径是你的这个jar包的本地路径,需要自己配置
<context id="context1" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/weixintest?useSSL=false& serverTimezone=Hongkong& characterEncoding=utf-8& autoReconnect=true"
//里面的weixintest是我自己的数据库名,改成你的,下面的userID、password同样改成你的
userId="root"
password="root"/>
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!--生成实体类 指定包名 以及生成的地址 (可以自定义地址,但是路径不存在不会自动创建 使用Maven生成在target目录下,会自动创建) -->
<javaModelGenerator targetPackage="com.ch.domain" targetProject="MAVEN">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!--生成SQLMAP文件 -->
<sqlMapGenerator targetPackage="com.ch.mapper" targetProject="MAVEN" >
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!--生成Dao文件 可以配置 type="XMLMAPPER"生成xml的dao实现 context id="DB2Tables" 修改targetRuntime="MyBatis3" -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.ch.dao" targetProject="MAVEN" >
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<table tableName="feedback" enableCountByExample="false" enableUpdateByExample="false"
//tableName是数据库表的名字,生成一个之后,更改这个名字,再生成另一个
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false">
</table>
</context>
</generatorConfiguration>
4、配置Alibaba—Druid连接池
在resources中新建application.yml,里面可能有些没用的
server:
port: 8090
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/weixintest?characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址: https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:
mapper-locations:
- classpath:mapper/*.xml
- classpath*:com/**/mapper/*.xml
type-aliases-package: com.ch.domian
configuration:
default-statement-timeout: 100
在java包中新建druid.DruidConfig配置类(这是个类)
package com.ch.druid;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2018/8/20 0020.
* Druid 数据源配置类
*/
@Configuration
public class DruidConfig {
/**
* 将自定义的 Druid 数据源添加到容器中,不再让 Spring Boot 自动创建
* 这样做的目的是:绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource
* 从而让它们生效
*
* @return
* @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中 前缀为 spring.datasource
* 的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
/**
* 配置 Druid 监控 之 管理后台的 Servlet
* 内置 Servler 容器时没有web.xml 文件,所以使用 Spring Boot 的注册 Servlet 方式
*/
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),
"/druid/*");
/**
* loginUsername:Druid 后台管理界面的登录账号
* loginPassword:Druid 后台管理界面的登录密码
* allow:Druid 后台允许谁可以访问
* initParams.put("allow", "localhost"):表示只有本机可以访问
* initParams.put("allow", ""):为空或者为null时,表示允许所有访问
* deny:Druid 后台拒绝谁访问
* initParams.put("deny", "192.168.1.20");表示禁止此ip访问
*/
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "123456");
initParams.put("allow", "");
/*initParams.put("deny", "192.168.1.20");*/
/** 设置初始化参数*/
bean.setInitParameters(initParams);
return bean;
}
}
5、service层书写(只写自己要用的方法,我写了三个,不要忘记加@Service)
新建VxService接口
package com.ch.vxService;
import com.ch.domain.Feedback;
import com.ch.domain.GetFeedback;
import com.ch.domain.Pictu;
import com.ch.domain.Qcuser;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public interface VxService {
int insert(Feedback record);
int insert(Pictu record);
List<GetFeedback> selectByUserId(String userid);
}
新建接口实现类
package com.ch.vxService.impl;
import com.ch.dao.FeedbackMapper;
import com.ch.dao.PictuMapper;
import com.ch.dao.QcuserMapper;
import com.ch.domain.Feedback;
import com.ch.domain.GetFeedback;
import com.ch.domain.Pictu;
import com.ch.domain.Qcuser;
import com.ch.vxService.VxService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class VxServiceImpl implements VxService {
@Autowired
FeedbackMapper feedbackMapper;
@Autowired
PictuMapper pictuMapper;
@Override
public int insert(Feedback record) {
feedbackMapper.insert(record);
return 1;
}
@Override
public int insert(Pictu record) {
pictuMapper.insert(record);
return 1;
}
@Override
public List<GetFeedback> selectByUserId(String userid) {
return feedbackMapper.selectByPrimaryKey(userid);
}
}
6、controller层书写(我的业务逻辑写在controller层了,一般要写在Service层,我嫌麻烦没改)
package com.ch.vxController;
import com.ch.domain.Feedback;
import com.ch.domain.GetFeedback;
import com.ch.domain.Pictu;
import com.ch.domain.model;
import com.ch.utils.picUtil;
import com.ch.vxService.VxService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Controller
@RestController
@ResponseBody
@SpringBootTest
@RunWith(SpringRunner.class)
public class VxController {
@Autowired
VxService vxService;
SimpleDateFormat f = new SimpleDateFormat("yyyy年MM月dd日-HH点mm分");
public String filePath="C:/Users/chenghao/Desktop/test/"; //定义上传文件的存放位置
// @Test
// public void t(){
// SimpleDateFormat f = new SimpleDateFormat("yyyy年MM月dd日-HH点mm分");
// System.out.println(f.format(new Date()));
// }
@ResponseBody
@PostMapping(value = "/fb")
public String putfb(@RequestBody model m){
SimpleDateFormat f = new SimpleDateFormat("yyyy年MM月dd日-HH点mm分");
Feedback feedback = new Feedback();
feedback.setUserid(m.getUserid());
feedback.setPtype(m.getPtype());
feedback.setDescr(m.getIntro());
feedback.setComp(m.getCompany());
feedback.setUname(m.getContacts());
feedback.setPhone(m.getPhone());
feedback.setFtime(f.format(new Date()));
vxService.insert(feedback);
return feedback.toString();
}
@ResponseBody
@PostMapping(value = "/pic")
@CrossOrigin
public String putpic(@RequestParam("file") MultipartFile file){
if ((file.getOriginalFilename().isEmpty())) {
return "插入失败";
} else {
Pictu pictu = new Pictu();
String fileName = file.getOriginalFilename();
String fileAddress = filePath + fileName;
try {
picUtil.uploadFile(file.getBytes(), filePath, fileName);
System.out.println(filePath);
pictu.setUserid(1);
pictu.setPic(fileAddress);
pictu.setTime(f.format(new Date()));
vxService.insert(pictu);
} catch (Exception e) {
e.printStackTrace();
} finally {
return "插入成功";
}
}
}
@ResponseBody
@GetMapping(value = "/gfb")
public List<GetFeedback> getFeedback(String id) {
return vxService.selectByUserId(id);
}
}
7、新建utils.picUtil工具类(用于接收并存储前端发送的图片)
package com.ch.utils;
import java.io.File;
import java.io.FileOutputStream;
public class picUtil {
//上传文件的工具类
public static void uploadFile(byte[] file, String filePath, String fileName) throws Exception {
File targetFile = new File(filePath);
if(!targetFile.exists()){
targetFile.mkdirs();
}
FileOutputStream out = new FileOutputStream(filePath+fileName);
out.write(file);
out.flush();
out.close();
}
}
8、新建config.CorsConfig配置类(前后端传值可能存在跨域问题)
package com.ch.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configurationpublic
class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //大坑
.allowedOriginPatterns("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.maxAge(3600)
.allowCredentials(true);
}}
9、新建model类(用于接收前端发来的Json格式,model类包含的属性与前端定义的相同)
private String userid;
private String ptype;
private String intro;
private String company;
private String contacts;
private String phone;
10、新建GetFeedback类(用于发送前端指定信息的类,直接将此类New的对象发送上去)
private String ftime;
private String descr;
11、修改mapper.xml中的SQL语句
添加到文件头中,这个作用是设计对象所包含的属性
<resultMap id="GetResultMap" type="com.ch.domain.GetFeedback" >
<result column="descr" property="descr" jdbcType="VARCHAR" />
<result column="ftime" property="ftime" jdbcType="VARCHAR" />
</resultMap>
查询语句:
<select id="selectByPrimaryKey" resultMap="GetResultMap" parameterType="java.lang.String" >
select descr,ftime <include refid="Base_Column_List" />
from feedback
where userid = #{id,jdbcType=VARCHAR}
</select>
12、新建log4j.properties(在resources中,不加运行时可能会报warning)
log4j.rootLogger=DEBUG, stdoutlog4j.appender.stdout=org.apache.
log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.
log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
13、注解书写
dao中的mapper文件:
@Repository(value = "FeedbackMapper")
@Repository(value = "PictuMapper")
主程序中:
@SpringBootApplication
@MapperScan("com.ch.dao")
三、前端设计
不多逼逼直接四个界面代码
pages/center/index.vue
{{pic}} {{nickName}}pages/index/index.vue
pages/login/test.vue
pages/query/myQuery.vue
{{pic}} {{ res.ftime }} {{res.descr}}pages.json
“pages”: [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
“path”: “pages/login/test”,
“style”: {
“navigationBarTitleText”: “登录”
}
},
{
“path”: “pages/index/index”,
“style”: {
“navigationBarTitleText”: “客户售后反馈”
}
},
{
“path”: “pages/center/index”,
“style”: {
“navigationBarTitleText”: “个人中心”
}
},
{
“path”: “pages/query/myQuery”,
“style”: {
“navigationBarTitleText”: “我的问题”
}
}
]
main.js
import Vue from ‘vue’
import App from ‘./App’
// 引入全局uView
import uView from ‘uview-ui’
import axios from ‘./utils/request/request.js’
import WXBizDataCrypt from ‘@/static/WXBizDataCrypt.js’;
//WXBizDataCrypt.js官网的工具包
Vue.use(uView);
Vue.config.productionTip = false
Vue.prototype.$axios = axios
App.mpType = ‘app’
const app = new Vue({
…App
})
app.$mount()