init
This commit is contained in:
34
.gitignore
vendored
Normal file
34
.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
run/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
111
pom.xml
Normal file
111
pom.xml
Normal file
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.7</version>
|
||||
</parent>
|
||||
<groupId>xyz.fortern</groupId>
|
||||
<artifactId>light-blog</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>light-blog</name>
|
||||
<description>light-blog</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Spring Boot Starter Data Redis -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
</dependency>
|
||||
<!-- MyBatis Plus -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.5.1</version>
|
||||
</dependency>
|
||||
<!-- MySQL Driver -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
<!-- Druid Spring Boot Starter -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>1.2.9</version>
|
||||
</dependency>
|
||||
<!-- Fastjson -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.80</version>
|
||||
</dependency>
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Apache Commons Codec -->
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<!-- SpringBoot注解处理器 -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- 阿里支付 -->
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>4.22.37.ALL</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<!-- spring-boot-starter-mail -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
<version>2.6.7</version>
|
||||
</dependency>
|
||||
<!-- ExpiringMap 一个带有有效期的Map -->
|
||||
<dependency>
|
||||
<groupId>net.jodah</groupId>
|
||||
<artifactId>expiringmap</artifactId>
|
||||
<version>0.5.10</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
19
src/main/java/xyz/fortern/LightBbsApplication.java
Normal file
19
src/main/java/xyz/fortern/LightBbsApplication.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package xyz.fortern;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("xyz.fortern.dao")
|
||||
@EnableWebSecurity
|
||||
@EnableAsync
|
||||
public class LightBbsApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LightBbsApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/xyz/fortern/annotation/LimitRequest.java
Normal file
26
src/main/java/xyz/fortern/annotation/LimitRequest.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package xyz.fortern.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Documented
|
||||
@Target(ElementType.METHOD) // 说明该注解只能放在方法上面
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface LimitRequest {
|
||||
/**
|
||||
* 获取限制操作的时间(秒)
|
||||
*
|
||||
* @return 限制操作的时间
|
||||
*/
|
||||
long time() default 5;
|
||||
|
||||
/**
|
||||
* 获取限制时间内,允许操作的最大次数
|
||||
*
|
||||
* @return 限制时间内,允许操作的最大次数
|
||||
*/
|
||||
int count() default 2;
|
||||
}
|
||||
56
src/main/java/xyz/fortern/aop/LimitRequestAspect.java
Normal file
56
src/main/java/xyz/fortern/aop/LimitRequestAspect.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package xyz.fortern.aop;
|
||||
|
||||
import net.jodah.expiringmap.ExpirationPolicy;
|
||||
import net.jodah.expiringmap.ExpiringMap;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import xyz.fortern.annotation.LimitRequest;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class LimitRequestAspect {
|
||||
//一个Map,key为用户访问的URI(String类型),value为用户的访问信息(ExpiringMap类型)
|
||||
private static final ConcurrentHashMap<String, ExpiringMap<String, Integer>> book = new ConcurrentHashMap<>();
|
||||
|
||||
// 定义切点
|
||||
// 让所有有@LimitRequest注解的方法都执行切面方法
|
||||
@Pointcut("@annotation(limitRequest)")
|
||||
public void executeService(LimitRequest limitRequest) {
|
||||
}
|
||||
|
||||
@Around(value = "executeService(limitRequest)", argNames = "point,limitRequest")
|
||||
@Order(100)//为多个切面配置优先级,值越小优先级越高,默认为Integer.MAX_VALUE
|
||||
public Object doAround(ProceedingJoinPoint point, LimitRequest limitRequest) throws Throwable {
|
||||
// 获得request对象
|
||||
var request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
var uri = request.getRequestURI();
|
||||
//获得Session对象
|
||||
var sessionId = request.getSession().getId();
|
||||
// 获取ExpiringMap对象, key为SessionId,value为最近访问次数
|
||||
var uc = book.get(uri);
|
||||
if(uc == null) {
|
||||
uc = ExpiringMap.builder().variableExpiration().build();
|
||||
book.put(uri, uc);
|
||||
}
|
||||
//该URI已经被访问的次数
|
||||
int count = uc.getOrDefault(sessionId, 0);
|
||||
if (count >= limitRequest.count())// 超过次数,不执行目标方法
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("访问过快,请稍后再试~");
|
||||
else if (count == 0)// 第一次请求时,设置有效时间
|
||||
uc.put(sessionId, count + 1, ExpirationPolicy.CREATED, limitRequest.time(), TimeUnit.SECONDS);
|
||||
else// 未超过次数, 记录加一
|
||||
uc.put(sessionId, count + 1);
|
||||
return point.proceed();// 执行被拦截的方法并返回
|
||||
}
|
||||
}
|
||||
9
src/main/java/xyz/fortern/bbs/SystemConstant.java
Normal file
9
src/main/java/xyz/fortern/bbs/SystemConstant.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package xyz.fortern.bbs;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SystemConstant {
|
||||
|
||||
public static final Pattern EMAIL_REGEX = Pattern.compile("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$");
|
||||
|
||||
}
|
||||
56
src/main/java/xyz/fortern/config/AlipayPayConfig.java
Normal file
56
src/main/java/xyz/fortern/config/AlipayPayConfig.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package xyz.fortern.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 支付宝支付配置类
|
||||
*
|
||||
* @author Fortern
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "ali.pay")
|
||||
public class AlipayPayConfig {
|
||||
|
||||
/**
|
||||
* 商户app_id
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 商户私钥
|
||||
*/
|
||||
private String merchantPrivateKey;
|
||||
|
||||
/**
|
||||
* 支付宝公钥
|
||||
*/
|
||||
private String alipayPublicKey;
|
||||
|
||||
/**
|
||||
* 支付宝异步通知回调
|
||||
*/
|
||||
private String notifyUrl;
|
||||
|
||||
/**
|
||||
* 商家支付成功的重定向页面,测试时可以用内网地址,因为是浏览器发起的请求
|
||||
*/
|
||||
private String returnUrl;
|
||||
|
||||
/**
|
||||
* 签名类型
|
||||
*/
|
||||
private String sign_type;
|
||||
|
||||
/**
|
||||
* 字符集
|
||||
*/
|
||||
private String charset;
|
||||
|
||||
/**
|
||||
* 支付宝网关
|
||||
*/
|
||||
private String gatewayUrl;
|
||||
}
|
||||
35
src/main/java/xyz/fortern/config/HttpConverterConfig.java
Normal file
35
src/main/java/xyz/fortern/config/HttpConverterConfig.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package xyz.fortern.config;
|
||||
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 使用fastjson作为消息转换器
|
||||
*
|
||||
* @author Fortern
|
||||
*/
|
||||
@Configuration
|
||||
public class HttpConverterConfig {
|
||||
|
||||
@Bean
|
||||
public HttpMessageConverters fastJsonHttpMessageConverters() {
|
||||
// 1.定义一个converters转换消息的对象
|
||||
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
|
||||
// 2.添加fastjson的配置信息,比如: 是否需要格式化返回的json数据
|
||||
FastJsonConfig fastJsonConfig = new FastJsonConfig();
|
||||
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.DisableCircularReferenceDetect);
|
||||
// 3.在converter中添加配置信息
|
||||
converter.setFastJsonConfig(fastJsonConfig);
|
||||
// 4.将converter赋值给HttpMessageConverter
|
||||
// 5.返回HttpMessageConverters对象
|
||||
converter.setSupportedMediaTypes(List.of(MediaType.APPLICATION_JSON));
|
||||
return new HttpMessageConverters(converter);
|
||||
}
|
||||
}
|
||||
68
src/main/java/xyz/fortern/config/RedisConfig.java
Normal file
68
src/main/java/xyz/fortern/config/RedisConfig.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package xyz.fortern.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
@Bean//("objectRedisTemplate")
|
||||
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
|
||||
//redis模板对象
|
||||
RedisTemplate<String,Object> template = new RedisTemplate<>();
|
||||
|
||||
//设置连接工厂
|
||||
template.setConnectionFactory(redisConnectionFactory);
|
||||
|
||||
//设置自定义序列化方式
|
||||
//key:字符串类型,使用string的序列化方式
|
||||
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
|
||||
//value是object类型,使用fastjson的序列化方式,直接序列化对象
|
||||
//FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||||
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
|
||||
|
||||
//指定序列化和反序列化方式
|
||||
template.setKeySerializer(stringRedisSerializer);
|
||||
template.setValueSerializer(jdkSerializationRedisSerializer);
|
||||
template.setHashKeySerializer(stringRedisSerializer);
|
||||
template.setHashValueSerializer(jdkSerializationRedisSerializer);
|
||||
|
||||
//初始化模板
|
||||
template.afterPropertiesSet();
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
//@Bean("hashRedisTemplate")
|
||||
public RedisTemplate<String, Object> hashRedisTemplate(RedisConnectionFactory redisConnectionFactory){
|
||||
//redis模板对象
|
||||
RedisTemplate<String,Object> template = new RedisTemplate<>();
|
||||
|
||||
//设置连接工厂
|
||||
template.setConnectionFactory(redisConnectionFactory);
|
||||
|
||||
//设置自定义序列化方式
|
||||
//key:字符串类型,使用string的序列化方式
|
||||
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
|
||||
//value是object类型,使用fastjson的序列化方式,直接序列化对象
|
||||
//FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||||
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
|
||||
|
||||
//指定序列化和反序列化方式
|
||||
template.setKeySerializer(stringRedisSerializer);
|
||||
template.setValueSerializer(jdkSerializationRedisSerializer);
|
||||
template.setHashKeySerializer(stringRedisSerializer);
|
||||
template.setHashValueSerializer(jdkSerializationRedisSerializer);
|
||||
|
||||
//初始化模板
|
||||
template.afterPropertiesSet();
|
||||
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
||||
43
src/main/java/xyz/fortern/config/SecurityConfig.java
Normal file
43
src/main/java/xyz/fortern/config/SecurityConfig.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package xyz.fortern.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
//创建BCryptPasswordEncoder注入容器
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
//关闭csrf
|
||||
http.csrf().disable()
|
||||
.authorizeRequests()
|
||||
//对于登录接口,仅允许未授权的访问
|
||||
.antMatchers("/account/login").anonymous()
|
||||
//以下接口直接放行
|
||||
.antMatchers(
|
||||
"/account/signup","/account/email_code","/test/**","/category/all",
|
||||
"/article/top","/article/notTop/**","/article/category/**","/article/search").permitAll()
|
||||
.regexMatchers(".+\\.[0-9a-zA-Z]+$").permitAll()
|
||||
//除上面外的所有请求全部需要鉴权验证
|
||||
.anyRequest().authenticated()
|
||||
.and().logout()
|
||||
.logoutSuccessUrl("/login.html");
|
||||
}
|
||||
}
|
||||
17
src/main/java/xyz/fortern/config/WebMvcConfig.java
Normal file
17
src/main/java/xyz/fortern/config/WebMvcConfig.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package xyz.fortern.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import xyz.fortern.converter.StringToDateConverter;
|
||||
|
||||
@Configuration
|
||||
@Import({WebMvcAutoConfiguration.class})
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
@Bean
|
||||
public StringToDateConverter stringToDateConverter() {
|
||||
return new StringToDateConverter();
|
||||
}
|
||||
}
|
||||
164
src/main/java/xyz/fortern/controller/AccountController.java
Normal file
164
src/main/java/xyz/fortern/controller/AccountController.java
Normal file
@@ -0,0 +1,164 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import xyz.fortern.annotation.LimitRequest;
|
||||
import xyz.fortern.pojo.Security;
|
||||
import xyz.fortern.service.AccountService;
|
||||
import xyz.fortern.service.EmailService;
|
||||
import xyz.fortern.service.UserService;
|
||||
import xyz.fortern.util.ForternUtil;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static xyz.fortern.bbs.SystemConstant.EMAIL_REGEX;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/account")
|
||||
public class AccountController {
|
||||
private final AccountService accountService;
|
||||
private final UserService userService;
|
||||
private final EmailService emailService;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public AccountController(AccountService accountService, UserService userService, EmailService emailService, RedisTemplate<String, Object> redisTemplate) {
|
||||
this.accountService = accountService;
|
||||
this.userService = userService;
|
||||
this.emailService = emailService;
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试是否在线的接口
|
||||
*
|
||||
* @return 200,表示在线,401表示不在线
|
||||
*/
|
||||
@GetMapping("/online")
|
||||
public ResponseEntity<?> online() {
|
||||
return ResponseEntity.ok("ok");
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录接口
|
||||
*
|
||||
* @param loginName 登录名
|
||||
* @param password 密码
|
||||
* @return 登录结果
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<String> login(@RequestParam("login_name") String loginName, @RequestParam String password, HttpSession session) {
|
||||
int i = accountService.login(loginName, password, session);
|
||||
switch (i) {
|
||||
case 1 -> {
|
||||
return ResponseEntity.ok("登录成功");
|
||||
}
|
||||
case -1 -> {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("密码错误");
|
||||
}
|
||||
case 0 -> {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("用户不存在");
|
||||
}
|
||||
case -2 -> {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("用户被锁定,不可登录");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册功能
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @param email 电子邮箱
|
||||
* @param emailCode 电子邮箱验证码
|
||||
* @param qqNumber QQ号
|
||||
* @param signupCode 注册码
|
||||
* @return 注册结果
|
||||
*/
|
||||
@PostMapping("/signup")
|
||||
public ResponseEntity<?> signUp(@RequestParam String username,
|
||||
@RequestParam String password,
|
||||
@RequestParam String email,
|
||||
@RequestParam("email_code") String emailCode,
|
||||
@RequestParam("qq") String qqNumber,
|
||||
@RequestParam("signup_code") String signupCode) {
|
||||
var correctSignupCode = (String) redisTemplate.opsForValue().get("signupCode:" + qqNumber);
|
||||
if (correctSignupCode == null || !correctSignupCode.equals(signupCode))
|
||||
return ResponseEntity.badRequest().body("注册码与QQ号不匹配!");
|
||||
var correctEmailCode = (String) redisTemplate.opsForValue().get("emailCode:" + email);
|
||||
if (correctEmailCode == null || !correctEmailCode.equals(emailCode))
|
||||
return ResponseEntity.badRequest().body("邮箱验证码错误!");
|
||||
if (userService.existUsername(username))
|
||||
return ResponseEntity.badRequest().body("用户名已存在");
|
||||
accountService.register(username, password, email, qqNumber);
|
||||
return ResponseEntity.ok("注册成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取电子邮箱验证码
|
||||
*
|
||||
* @param email 电子邮箱
|
||||
* @param qqNumber QQ号
|
||||
* @param signupCode 注册码
|
||||
* @return 电子邮箱验证码
|
||||
*/
|
||||
@LimitRequest(time = 60, count = 1)
|
||||
@PostMapping("/email_code")
|
||||
public ResponseEntity<String> getEmailCode(@RequestParam String email,
|
||||
@RequestParam(value = "qq", required = false) String qqNumber,
|
||||
@RequestParam(value = "signup_code", required = false) String signupCode,
|
||||
@RequestParam("signup") boolean signup,
|
||||
HttpSession session) {
|
||||
if (!signup) {//为了更新邮箱
|
||||
if (session.getAttribute("user") == null)//如果未登录
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("未登录");
|
||||
//已登录就直接生成验证码
|
||||
} else {//为了注册账号
|
||||
//先检验邀请码
|
||||
var correctSignupCode = (String) redisTemplate.opsForValue().get("signupCode:" + qqNumber);
|
||||
if (correctSignupCode == null || !correctSignupCode.equals(signupCode))
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("注册码与QQ号不匹配!");
|
||||
}
|
||||
if (!EMAIL_REGEX.matcher(email).matches())
|
||||
return ResponseEntity.badRequest().body("电子邮箱格式错误");
|
||||
//生成随机验证码存入Redis
|
||||
var randomIntStr = ForternUtil.randomIntStr();
|
||||
redisTemplate.opsForValue().set("emailCode:" + email, randomIntStr, 1, TimeUnit.HOURS);
|
||||
emailService.sendSimpleMail(email, "落星原服务器-邮箱验证码", randomIntStr);
|
||||
return ResponseEntity.ok().body("发送成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*
|
||||
* @param password 旧密码
|
||||
* @param newPassword 新密码
|
||||
* @return 更新结果
|
||||
*/
|
||||
@PostMapping("/change_pass")
|
||||
public ResponseEntity<String> changePassword(@RequestParam("password") String password,
|
||||
@RequestParam("new_password") String newPassword,
|
||||
@SessionAttribute("security") Security security,
|
||||
HttpSession session) {
|
||||
String encodedOldPassword = security.getPassword();
|
||||
if (!accountService.passwordMatches(password, encodedOldPassword))
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("旧密码错误");
|
||||
if (newPassword.length() < 6 || newPassword.length() > 18)
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("新密码不符合要求");
|
||||
int userId = security.getUserId();
|
||||
var new_security = accountService.changePassword(userId, newPassword);
|
||||
session.setAttribute("security", new_security);
|
||||
return ResponseEntity.ok("成功");
|
||||
}
|
||||
}
|
||||
247
src/main/java/xyz/fortern/controller/ArticleController.java
Normal file
247
src/main/java/xyz/fortern/controller/ArticleController.java
Normal file
@@ -0,0 +1,247 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import xyz.fortern.annotation.LimitRequest;
|
||||
import xyz.fortern.pojo.Article;
|
||||
import xyz.fortern.pojo.Security;
|
||||
import xyz.fortern.pojo.Tag;
|
||||
import xyz.fortern.pojo.User;
|
||||
import xyz.fortern.service.ArticleService;
|
||||
import xyz.fortern.util.ForternUtil;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/article")
|
||||
public class ArticleController {
|
||||
private final ArticleService articleService;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public ArticleController(ArticleService articleService, RedisTemplate<String, Object> redisTemplate) {
|
||||
this.articleService = articleService;
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文章详情
|
||||
*
|
||||
* @param id 文章id
|
||||
* @return 文章详情
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<?> getAllInfoById(@PathVariable int id, @SessionAttribute("security") Security security) {
|
||||
boolean isManager = security.getPosition() == Security.Position.MANAGER;
|
||||
Article article = articleService.getAllInfoById(id);
|
||||
if (article == null) return ResponseEntity.notFound().build();
|
||||
if (!isManager)
|
||||
if (!Objects.equals(article.getUid(), security.getUserId()) || !article.getVisible() || !article.getReviewed()) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();//未经授权的操作
|
||||
}
|
||||
return ResponseEntity.ok(article);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一篇新文章
|
||||
*
|
||||
* @param title 标题
|
||||
* @param summary 摘要
|
||||
* @param tagIds 标签id列表
|
||||
* @param categoryId 分类id
|
||||
* @param content 主体内容
|
||||
* @return 这篇文章的id
|
||||
*/
|
||||
@LimitRequest(time = 10, count = 1)
|
||||
@PostMapping("/new")
|
||||
public ResponseEntity<?> getAllInfoById(@RequestParam String title,
|
||||
@RequestParam String summary,
|
||||
@RequestParam(required = false) int[] tagIds,
|
||||
@RequestParam String categoryId,
|
||||
@RequestParam String content,
|
||||
@RequestParam Boolean visible,
|
||||
@RequestParam(required = false) Boolean reviewed,
|
||||
@RequestParam(required = false) Boolean top,
|
||||
@SessionAttribute("security") Security security) {
|
||||
List<Tag> tagList = tagIds == null ? new ArrayList<>(0) : Arrays.stream(tagIds).mapToObj(id -> new Tag(id, null)).toList();
|
||||
var article = Article.builder().title(title).categoryId(categoryId).summary(summary).tags(tagList).content(content).uid(security.getUserId()).build();
|
||||
if(security.getPosition()== Security.Position.MANAGER) {
|
||||
article.setReviewed(reviewed);
|
||||
article.setTop(top);
|
||||
}
|
||||
articleService.addNewArticle(article);
|
||||
return ResponseEntity.ok(article.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新一篇文章,本人与管理员可以操作
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @param title 标题
|
||||
* @param summary 摘要
|
||||
* @param tagIds 标签id列表
|
||||
* @param categoryId 分类id
|
||||
* @param content 主体内容
|
||||
* @return 这篇文章的id
|
||||
*/
|
||||
@LimitRequest(time = 10, count = 1)
|
||||
@PostMapping("/update/{aid}")
|
||||
public ResponseEntity<?> updateArticle(@PathVariable int aid,
|
||||
@RequestParam String title,
|
||||
@RequestParam String summary,
|
||||
@RequestParam(required = false) int[] tagIds,//标签不是必须的
|
||||
@RequestParam String categoryId,
|
||||
@RequestParam String content,
|
||||
@RequestParam boolean visible,
|
||||
@RequestParam boolean top,
|
||||
@RequestParam boolean reviewed,
|
||||
@SessionAttribute("security") Security security) {
|
||||
int auth_id = articleService.getUidByArticle(aid);
|
||||
int uid = security.getUserId();
|
||||
if (auth_id != uid && security.getPosition() != Security.Position.MANAGER)
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();//未经授权的操作
|
||||
List<Tag> tagList;
|
||||
if (tagIds == null)
|
||||
tagList = new ArrayList<>(0);
|
||||
else
|
||||
tagList = Arrays.stream(tagIds).mapToObj(id -> new Tag(id, null)).toList();
|
||||
var article = Article.builder().id(aid).title(title).categoryId(categoryId).summary(summary).tags(tagList).content(content).visible(visible).build();
|
||||
if (security.getPosition() == Security.Position.MANAGER) {
|
||||
article.setTop(top);
|
||||
article.setReviewed(reviewed);
|
||||
}
|
||||
articleService.updateArticle(article, uid);
|
||||
return ResponseEntity.ok(article.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取置顶文章列表,不含隐藏的和未审核的文章
|
||||
*
|
||||
* @return 置顶的文章列表
|
||||
*/
|
||||
@GetMapping("/top")
|
||||
public ResponseEntity<List<Article>> getArticlesTop() {
|
||||
var tops = articleService.getTops();
|
||||
return ResponseEntity.ok(tops);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取非置顶文章列表,不含隐藏的和未审核的文章
|
||||
*
|
||||
* @return 置顶的文章列表
|
||||
*/
|
||||
@GetMapping("/notTop/{page}")
|
||||
public ResponseEntity<PageInfo<Article>> getArticlesNotTop(@PathVariable Integer page) {
|
||||
var articles = articleService.getNotTops(page, 15);
|
||||
return ResponseEntity.ok(articles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 主页分类查询列表,不含隐藏的和未审核的文章
|
||||
*
|
||||
* @param cid 分类id
|
||||
* @param page 页码
|
||||
* @return 分类查询列表
|
||||
*/
|
||||
@GetMapping("/category/{cid}/{page}")
|
||||
public ResponseEntity<PageInfo<Article>> getByCategoryInIndex(@PathVariable String cid, @PathVariable int page) {
|
||||
var articlePageInfo = articleService.getByCategoryInIndex(cid, new PageInfo<Article>(page, 15));
|
||||
return ResponseEntity.ok(articlePageInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请删除一篇文章
|
||||
*
|
||||
* @param id 文章id
|
||||
* @return 一串确认代码
|
||||
*/
|
||||
@PostMapping("/request_deletion/{id}")
|
||||
public ResponseEntity<String> requestDeletion(@PathVariable int id, @SessionAttribute("security") Security security) {
|
||||
Integer auth_id = articleService.getUidByArticle(id);
|
||||
if (auth_id == null)
|
||||
return ResponseEntity.notFound().build();
|
||||
int userId = security.getUserId();
|
||||
if (userId != auth_id && security.getPosition() != Security.Position.MANAGER) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("无权执行此操作");
|
||||
}
|
||||
String code = ForternUtil.randomStr(6);
|
||||
//给这段代码设置120秒延迟
|
||||
redisTemplate.opsForValue().set("del_ar_code:" + userId + "." + id, code, 120, TimeUnit.SECONDS);
|
||||
return ResponseEntity.ok(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过输入确认码,确定删除文章
|
||||
*
|
||||
* @param id 文章id
|
||||
* @param code 确认码
|
||||
* @return 结果
|
||||
*/
|
||||
@DeleteMapping("/confirm_deletion/{id}")
|
||||
public ResponseEntity<String> confirmDeletion(@PathVariable int id, @RequestParam String code, @SessionAttribute("user") User user) {
|
||||
String realCode = (String) redisTemplate.opsForValue().get("del_ar_code:" + user.getId() + "." + id);
|
||||
if (realCode == null)
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("超时或非法操作");//403
|
||||
if (!realCode.equals(code))
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("确认码错误");//403
|
||||
if (articleService.delete(id))
|
||||
return ResponseEntity.ok("ok");
|
||||
else
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("服务器内部错误");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有文章列表,在文章管理界面
|
||||
*
|
||||
* @return 一页内的文章列表
|
||||
*/
|
||||
//TODO 待测
|
||||
@PostMapping("/all")
|
||||
public ResponseEntity<PageInfo<Article>> getAllByExample(
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer size,
|
||||
@RequestParam(value = "category_id", required = false) String categoryId,
|
||||
@RequestParam(value = "edit_time_begin", required = false) Date editTimeBegin,
|
||||
@RequestParam(value = "edit_time_end", required = false) Date editTimeEnd,
|
||||
@RequestParam(value = "reviewed", required = false) Boolean reviewed,
|
||||
@RequestParam(value = "visible", required = false) Boolean visible,
|
||||
@RequestParam(value = "top", required = false) Boolean top,
|
||||
@SessionAttribute("security") Security security) {
|
||||
var articleExample = Article.ArticleExample.builder().editTimeBegin(editTimeBegin).editTimeEnd(editTimeEnd).visible(visible).top(top).categoryId(categoryId).build();
|
||||
if(security.getPosition()== Security.Position.MANAGER) {
|
||||
articleExample.setReviewed(reviewed);
|
||||
} else {
|
||||
articleExample.setUserId(security.getUserId());
|
||||
}
|
||||
return ResponseEntity.ok(articleService.getAll(articleExample, new PageInfo<>(page, size)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索文章列表
|
||||
*
|
||||
* @param key 关键词
|
||||
* @param page 页码
|
||||
* @return 文章列表
|
||||
*/
|
||||
@PostMapping("/search")
|
||||
public ResponseEntity<PageInfo<Article>> searchByKey(@RequestParam String key, @RequestParam int page) {
|
||||
var pageInfo = articleService.search(key, new PageInfo<>(page, 10));
|
||||
return ResponseEntity.ok(pageInfo);
|
||||
}
|
||||
}
|
||||
79
src/main/java/xyz/fortern/controller/CategoryController.java
Normal file
79
src/main/java/xyz/fortern/controller/CategoryController.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import xyz.fortern.service.CategoryService;
|
||||
|
||||
/**
|
||||
* 分类(Category)操作接口,只有管理员可以操作
|
||||
*/
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/category")
|
||||
public class CategoryController {
|
||||
private final CategoryService categoryService;
|
||||
|
||||
public CategoryController(CategoryService categoryService) {
|
||||
this.categoryService = categoryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新加分类,分类名不能超过20个字符
|
||||
*
|
||||
* @param categoryName 分类名称
|
||||
* @param superiorId 父级分类的id
|
||||
* @return 新加分类的id
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('MANAGER')")
|
||||
@PostMapping("/add")
|
||||
public ResponseEntity<String> addNewCategory(@RequestParam("name") String categoryName, @RequestParam(value = "superior", required = false) String superiorId) {
|
||||
if (categoryName.length() > 20)
|
||||
return ResponseEntity.badRequest().body("参数错误");
|
||||
var categoryId = categoryService.addNewCategory(categoryName, superiorId);
|
||||
return ResponseEntity.ok(categoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个分类
|
||||
*
|
||||
* @param id 分类的id
|
||||
* @return 新加分类的id
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('MANAGER')")
|
||||
@DeleteMapping("/del/{id}")
|
||||
public ResponseEntity<String> deleteCategory(@PathVariable String id) {
|
||||
if (id.endsWith("_") && categoryService.deleteCategory(id)) {
|
||||
return ResponseEntity.ok(null);
|
||||
}
|
||||
return ResponseEntity.badRequest().body("删除失败,请确保该分类下没有内容");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有分类
|
||||
*
|
||||
* @return 所有分类的列表
|
||||
*/
|
||||
@GetMapping("/all")
|
||||
public ResponseEntity<?> getAll() {
|
||||
return ResponseEntity.ok(categoryService.getAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取分类名称
|
||||
*
|
||||
* @param id 分类的id
|
||||
* @return 分类名称
|
||||
*/
|
||||
@GetMapping("/id/{id}")
|
||||
public ResponseEntity<String> getNameById(@PathVariable String id) {
|
||||
return ResponseEntity.ok(categoryService.getNameById(id));
|
||||
}
|
||||
}
|
||||
91
src/main/java/xyz/fortern/controller/CommentController.java
Normal file
91
src/main/java/xyz/fortern/controller/CommentController.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import xyz.fortern.pojo.Comment;
|
||||
import xyz.fortern.pojo.Security;
|
||||
import xyz.fortern.service.CommentService;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/comment")
|
||||
public class CommentController {
|
||||
private final CommentService commentService;
|
||||
|
||||
public CommentController(CommentService commentService) {
|
||||
this.commentService = commentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文章评论列表接口
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @param page 页码
|
||||
* @param size 页容量
|
||||
* @return 一页的评论
|
||||
*/
|
||||
@PostMapping("/a")
|
||||
public ResponseEntity<PageInfo<Comment>> getCommentsByAid(@RequestParam Integer aid, @RequestParam Integer page, @RequestParam Integer size) {
|
||||
return ResponseEntity.ok(commentService.getCommentsByAid(aid, page, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户条件查询自己的评论信息
|
||||
*
|
||||
* @param commentExample 查询条件
|
||||
* @param page 页码
|
||||
* @param size 页容量
|
||||
* @return 评论列表
|
||||
*/
|
||||
@PostMapping("/i")
|
||||
public ResponseEntity<PageInfo<Comment>> getCommentsInPersonalCenter(@SessionAttribute("security") Security security, Comment.CommentExample commentExample, @RequestParam Integer page, @RequestParam Integer size) {
|
||||
//如果是普通用户,则只能查自己的
|
||||
if (security.getPosition() == Security.Position.USER)
|
||||
commentExample.setUserId(security.getUserId());
|
||||
var commentsByWrapper = commentService.getCommentsByWrapper(commentExample, page, size);
|
||||
return ResponseEntity.ok(commentsByWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增一条评论
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @param security 用户安全信息
|
||||
* @param content 内容
|
||||
* @return 处理结果
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('comment')")
|
||||
@PostMapping("/new/{aid}")
|
||||
public ResponseEntity<?> addNewComment(@PathVariable int aid,
|
||||
@SessionAttribute("security") Security security,
|
||||
@RequestParam String content) {
|
||||
var comment = Comment.builder().aid(aid).uid(security.getUserId()).content(content).build();
|
||||
commentService.addNewComment(comment);
|
||||
return ResponseEntity.ok("");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除评论
|
||||
*
|
||||
* @param id 评论id
|
||||
* @return 删除结果
|
||||
*/
|
||||
@DeleteMapping("/del/{id}")
|
||||
public ResponseEntity<?> delComment(@PathVariable int id, @SessionAttribute("security") Security security) {
|
||||
if(security.getPosition() == Security.Position.USER && commentService.getUserIdByCommentId(id) != security.getUserId()) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("你只能操作自己的数据");
|
||||
}
|
||||
commentService.delById(id);
|
||||
return ResponseEntity.ok("删除成功");
|
||||
}
|
||||
}
|
||||
42
src/main/java/xyz/fortern/controller/DonateController.java
Normal file
42
src/main/java/xyz/fortern/controller/DonateController.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import xyz.fortern.pojo.Donate;
|
||||
import xyz.fortern.pojo.Security;
|
||||
import xyz.fortern.service.DonateService;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/donate")
|
||||
public class DonateController {
|
||||
|
||||
private final DonateService donateService;
|
||||
|
||||
public DonateController(DonateService donateService) {
|
||||
this.donateService = donateService;
|
||||
}
|
||||
|
||||
@GetMapping("/all")
|
||||
public ResponseEntity<PageInfo<Donate>> getDonateList(
|
||||
@SessionAttribute("security") Security security,
|
||||
Integer page,
|
||||
Integer size) {
|
||||
var donatePageInfo = donateService.getDonateList(security.getPosition() == Security.Position.USER ? security.getUserId() : null, page, size);
|
||||
return ResponseEntity.ok(donatePageInfo);
|
||||
}
|
||||
|
||||
@GetMapping("/total")
|
||||
public ResponseEntity<BigDecimal> getTotal() {
|
||||
var total = donateService.getTotal();
|
||||
return ResponseEntity.ok(total);
|
||||
}
|
||||
|
||||
}
|
||||
30
src/main/java/xyz/fortern/controller/NewsController.java
Normal file
30
src/main/java/xyz/fortern/controller/NewsController.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import xyz.fortern.pojo.News;
|
||||
import xyz.fortern.service.NewsService;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/news")
|
||||
public class NewsController {
|
||||
private final NewsService newsService;
|
||||
|
||||
public NewsController(NewsService newsService) {
|
||||
this.newsService = newsService;
|
||||
}
|
||||
|
||||
@GetMapping("/{page}")
|
||||
public ResponseEntity<PageInfo<News>> getByPage(@PathVariable int page) {
|
||||
if(page < 1)
|
||||
return ResponseEntity.badRequest().build();
|
||||
return ResponseEntity.ok(newsService.getNewsByPage(page));
|
||||
}
|
||||
|
||||
}
|
||||
224
src/main/java/xyz/fortern/controller/PayController.java
Normal file
224
src/main/java/xyz/fortern/controller/PayController.java
Normal file
@@ -0,0 +1,224 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.alipay.api.request.AlipayTradePagePayRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import xyz.fortern.config.AlipayPayConfig;
|
||||
import xyz.fortern.pojo.Donate;
|
||||
import xyz.fortern.pojo.Security;
|
||||
import xyz.fortern.service.DonateService;
|
||||
import xyz.fortern.util.PayResult;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 支付接口,允许群员打赏,必须登录才能得到支付链接
|
||||
*
|
||||
* @author Fortern
|
||||
*/
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/pay")
|
||||
public class PayController {
|
||||
private final AlipayPayConfig payConfig;
|
||||
private final DonateService donateService;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private static final BigDecimal minAmount = new BigDecimal(1);
|
||||
private static final BigDecimal maxAmount = new BigDecimal(100);
|
||||
|
||||
public PayController(AlipayPayConfig payConfig, DonateService donateService, RedisTemplate<String, Object> redisTemplate) {
|
||||
this.payConfig = payConfig;
|
||||
this.donateService = donateService;
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单
|
||||
*
|
||||
* @param total 捐赠的金额
|
||||
* @param response http响应
|
||||
*/
|
||||
@PostMapping("/generate")
|
||||
public void toAlipay(@SessionAttribute("security") Security security,
|
||||
@RequestParam String total,
|
||||
HttpServletResponse response) throws Exception {
|
||||
int i = total.indexOf('.');
|
||||
if (i != -1) {
|
||||
int len = total.length();
|
||||
//小数点后面的位数
|
||||
int j = len - i - 1;
|
||||
total = total.substring(0, i + (j > 2 ? 3 : j + 1));
|
||||
}
|
||||
BigDecimal amount = new BigDecimal(total);
|
||||
if (amount.compareTo(minAmount) < 0 || amount.compareTo(maxAmount) > 0) {
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
String orderId = "donate" + System.currentTimeMillis();
|
||||
//无需设置时间,有默认值
|
||||
Donate donate = Donate.builder().amount(amount).id(orderId).userId(security.getUserId()).build();
|
||||
//订单数据存入Redis,等待处理
|
||||
redisTemplate.opsForValue().set("pre-order:" + orderId, donate, 21600, TimeUnit.SECONDS);
|
||||
//阿里客户端
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(
|
||||
payConfig.getGatewayUrl(), payConfig.getAppId(),
|
||||
payConfig.getMerchantPrivateKey(), "json", payConfig.getCharset(),
|
||||
payConfig.getAlipayPublicKey(), payConfig.getSign_type());
|
||||
// 设置请求参数
|
||||
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
|
||||
alipayRequest.setReturnUrl(payConfig.getReturnUrl());//支付成功响应后跳转地址
|
||||
alipayRequest.setNotifyUrl(payConfig.getNotifyUrl());//异步请求地址
|
||||
|
||||
/*FAST_INSTANT_TRADE_PAY 二维码瞬时支付
|
||||
* out_trade_no 订单号 total_amount 订单金额 subject 订单名称
|
||||
*/
|
||||
alipayRequest.setBizContent("{\"out_trade_no\":\"" + orderId
|
||||
+ "\",\"total_amount\":\"" + amount + "\",\"subject\":\""
|
||||
+ "给落星原的捐赠" + "\",\"body\":\"\","
|
||||
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
|
||||
// 请求
|
||||
try {
|
||||
//通过阿里客户端,发送支付页面请求
|
||||
String result = alipayClient.pageExecute(alipayRequest).getBody();
|
||||
response.setContentType("text/html;charset=UTF-8");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.getWriter().println(result);
|
||||
response.getWriter().flush();
|
||||
} catch (AlipayApiException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
response.getWriter().close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付成功后处理业务
|
||||
* 用户在支付成功后,会自动跳转到此页面,同时请求中包含了支付信息
|
||||
*
|
||||
* @return 用户跳转页面
|
||||
*/
|
||||
@RequestMapping("/alipay_return")
|
||||
public String alipayReturn(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession();
|
||||
if (verifyAlipayReturn(request)) {//验签成功后执行的自定义业务代码
|
||||
// 商户订单号
|
||||
String outTradeNo = new String(request.getParameter(
|
||||
"out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
// 支付宝交易号
|
||||
String tradeNo = new String(request.getParameter("trade_no")
|
||||
.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
// 付款金额
|
||||
String totalAmount = new String(request.getParameter(
|
||||
"total_amount").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
PayResult payResult = new PayResult(outTradeNo, tradeNo, totalAmount);
|
||||
if (donateService.paySuccess(outTradeNo, tradeNo))
|
||||
session.setAttribute("payResult", payResult);
|
||||
else
|
||||
session.setAttribute("payResult", "服务端错误,交易可能已经成功");
|
||||
} else {
|
||||
session.setAttribute("pay", "验签/支付失败");
|
||||
}
|
||||
return "redirect:/user.html";
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝异步通知
|
||||
*/
|
||||
@RequestMapping("/notify_url")
|
||||
public void alipayNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
// ——请在这里编写您的程序(以下代码仅作参考)——
|
||||
|
||||
/*
|
||||
* 实际验证过程建议商户务必添加以下校验: 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
|
||||
* 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
|
||||
* 3、校验通知中的seller_id(或者seller_email)
|
||||
* 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
|
||||
* 4、验证app_id是否为该商户本身。
|
||||
*/
|
||||
if (verifyAlipayReturn(request)) {// 验证成功
|
||||
// 商户订单号
|
||||
String out_trade_no = new String(request.getParameter(
|
||||
"out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
// 支付宝交易号
|
||||
String trade_no = new String(request.getParameter("trade_no")
|
||||
.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
// 交易状态
|
||||
String trade_status = new String(request.getParameter(
|
||||
"trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
|
||||
if (trade_status.equals("TRADE_FINISHED")) {
|
||||
// 判断该笔订单是否在商户网站中已经做过处理
|
||||
// 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
|
||||
// 如果有做过处理,不执行商户的业务程序
|
||||
// 注意:
|
||||
// 退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
|
||||
} else if (trade_status.equals("TRADE_SUCCESS")) {
|
||||
// 判断该笔订单是否在商户网站中已经做过处理
|
||||
// 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
|
||||
// 如果有做过处理,不执行商户的业务程序
|
||||
// 注意:
|
||||
// 付款完成后,支付宝系统发送该交易状态通知
|
||||
}
|
||||
|
||||
} else {// 验证失败
|
||||
response.setContentType("text/html;charset=UTF-8");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.getWriter().println("验签/支付失败!");
|
||||
response.getWriter().flush();
|
||||
response.getWriter().close();
|
||||
|
||||
// 调试用,写文本函数记录程序运行情况是否正常
|
||||
// String sWord = AlipaySignature.getSignCheckContentV1(params);
|
||||
// AlipayConfig.logResult(sWord);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证支付宝的反馈信息
|
||||
*
|
||||
* @return 校验结果
|
||||
*/
|
||||
private boolean verifyAlipayReturn(HttpServletRequest request) {
|
||||
// 获取支付宝回调反馈的信息
|
||||
Map<String, String> params = new HashMap<>();
|
||||
Map<String, String[]> requestParams = request.getParameterMap();
|
||||
for (String name : requestParams.keySet()) {
|
||||
String[] values = requestParams.get(name);
|
||||
String valueStr = "";
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
|
||||
}
|
||||
// 乱码解决,这段代码在出现乱码时使用
|
||||
valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
params.put(name, valueStr);
|
||||
}
|
||||
boolean signVerified = false;
|
||||
try {
|
||||
// 调用SDK验证签名
|
||||
signVerified = AlipaySignature.rsaCheckV1(params,
|
||||
payConfig.getAlipayPublicKey(), payConfig.getCharset(),
|
||||
payConfig.getSign_type());
|
||||
} catch (AlipayApiException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return signVerified;
|
||||
}
|
||||
|
||||
}
|
||||
60
src/main/java/xyz/fortern/controller/ReplyController.java
Normal file
60
src/main/java/xyz/fortern/controller/ReplyController.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import xyz.fortern.pojo.Reply;
|
||||
import xyz.fortern.pojo.User;
|
||||
import xyz.fortern.service.ReplyService;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/reply")
|
||||
public class ReplyController {
|
||||
private final ReplyService replyService;
|
||||
|
||||
public ReplyController(ReplyService replyService) {
|
||||
this.replyService = replyService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某评论下的所有回复
|
||||
*
|
||||
* @param cid 评论id
|
||||
* @param page 页码
|
||||
* @param orderByTime 时间排序规则,false旧的在前,true新的在前
|
||||
* @return 一页评论信息
|
||||
*/
|
||||
@GetMapping("/comment/{cid}")
|
||||
public ResponseEntity<PageInfo<Reply>> getByCommentId(@PathVariable int cid, Integer page, boolean orderByTime) {
|
||||
return ResponseEntity.ok(replyService.getByCommentId(cid, page, 10, orderByTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条评论
|
||||
*
|
||||
* @param cid 所属评论的id
|
||||
* @param rid 回复的那条回复的id
|
||||
* @param content 回复内容
|
||||
* @param user 操作用户
|
||||
* @return 操作结果
|
||||
*/
|
||||
//TODO 改变获取用户Id的方式
|
||||
@PostMapping("/new/{cid}")
|
||||
public ResponseEntity<?> addNewReply(@PathVariable int cid,
|
||||
@RequestParam(required = false) Integer rid,
|
||||
@RequestParam String content,
|
||||
@SessionAttribute("user") User user) {
|
||||
var reply = Reply.builder().cid(cid).rid(rid).uid(user.getId()).content(content).build();
|
||||
replyService.addNewReply(reply);
|
||||
return ResponseEntity.ok(reply);
|
||||
}
|
||||
|
||||
}
|
||||
35
src/main/java/xyz/fortern/controller/TagController.java
Normal file
35
src/main/java/xyz/fortern/controller/TagController.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import xyz.fortern.service.TagService;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/tag")
|
||||
public class TagController {
|
||||
private final TagService tagService;
|
||||
|
||||
public TagController(TagService tagService) {
|
||||
this.tagService = tagService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取或添加一个标签,返回这个标签的id
|
||||
*
|
||||
* @param name 标签名,最长 15 字符
|
||||
* @return 标签的id
|
||||
*/
|
||||
//TODO 此接口需要登录访问
|
||||
@PostMapping("/get_id")
|
||||
public ResponseEntity<?> getOrAddTag(@RequestParam("name") String name) {
|
||||
if(name.length() > 15) {
|
||||
return ResponseEntity.badRequest().body("标签名过长");
|
||||
}
|
||||
return ResponseEntity.ok(tagService.getIdByName(name));
|
||||
}
|
||||
}
|
||||
50
src/main/java/xyz/fortern/controller/TestController.java
Normal file
50
src/main/java/xyz/fortern/controller/TestController.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/test")
|
||||
public class TestController {
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public TestController(PasswordEncoder passwordEncoder, RedisTemplate<String, Object> redisTemplate) {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
@PostMapping("/noLogin")
|
||||
public ResponseEntity<?> needToLogin(String name) {
|
||||
return ResponseEntity.ok(name);
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<?> login(String name) {
|
||||
var authenticationToken = new UsernamePasswordAuthenticationToken(name, null, new ArrayList<>(0));
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
return ResponseEntity.ok(name);
|
||||
}
|
||||
|
||||
@PostMapping("/pass")
|
||||
public ResponseEntity<?> generatePassword(String password) {
|
||||
return ResponseEntity.ok(passwordEncoder.encode(password));
|
||||
}
|
||||
|
||||
@PostMapping("/redis")
|
||||
public ResponseEntity<?> insertIntoRedis(@RequestParam String key, @RequestParam String value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
return ResponseEntity.ok(null);
|
||||
}
|
||||
}
|
||||
143
src/main/java/xyz/fortern/controller/UserController.java
Normal file
143
src/main/java/xyz/fortern/controller/UserController.java
Normal file
@@ -0,0 +1,143 @@
|
||||
package xyz.fortern.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import xyz.fortern.pojo.Security;
|
||||
import xyz.fortern.pojo.User;
|
||||
import xyz.fortern.service.UserService;
|
||||
import xyz.fortern.util.ForternUtil;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
private final UserService userService;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public UserController(UserService userService, RedisTemplate<String, Object> redisTemplate) {
|
||||
this.userService = userService;
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户详情,一般用于管理员编辑数据
|
||||
*
|
||||
* @param uid 用户id
|
||||
* @return 用户详情
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('MANAGER')")
|
||||
@GetMapping("/{uid}")
|
||||
public ResponseEntity<Map<String, ?>> getUserInfoById(@PathVariable int uid) {
|
||||
var user = userService.getById(uid);
|
||||
var security = userService.getSecurityById(uid);
|
||||
if (user == null)
|
||||
return ResponseEntity.notFound().build();
|
||||
Map<String, Object> map = new HashMap<>(3);
|
||||
map.put("user", user);
|
||||
map.put("security", security);
|
||||
map.put("permission", ForternUtil.longToBinaryString(security.getPermissions()));
|
||||
security.setPermissions(null);
|
||||
return ResponseEntity.ok(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录者自己的详情
|
||||
*
|
||||
* @return 用户详情
|
||||
*/
|
||||
@GetMapping("/getMe")
|
||||
public ResponseEntity<Map<String, ?>> getUserInfoById(@SessionAttribute("user") User user, @SessionAttribute("security") Security security) {
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("user", user);
|
||||
map.put("security", security);
|
||||
return ResponseEntity.ok(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户更改自己的信息
|
||||
*
|
||||
* @return 用户详情
|
||||
*/
|
||||
@PostMapping("/updateMe")
|
||||
public ResponseEntity<String> updateMyself(@RequestParam String nickname,
|
||||
@RequestParam("qq") String qqNumber,
|
||||
@RequestParam String sign,
|
||||
@SessionAttribute("user") User user,
|
||||
HttpSession session) {
|
||||
var user_info = User.builder().id(user.getId()).nickname(nickname).qqNumber(qqNumber).sign(sign).build();
|
||||
userService.updateUserByUser(user_info);
|
||||
//更新session中的用户信息
|
||||
session.setAttribute("user",userService.getById(user.getId()));
|
||||
return ResponseEntity.ok("操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户更新自己的邮箱
|
||||
*
|
||||
* @return 更新结果
|
||||
*/
|
||||
@PostMapping("/email")
|
||||
public ResponseEntity<?> updateUEmail(@RequestParam("email") String email,
|
||||
@RequestParam("code") String code,
|
||||
@SessionAttribute("user") User user,
|
||||
HttpSession session) {
|
||||
var correctEmailCode = (String) redisTemplate.opsForValue().get("emailCode:" + email);
|
||||
if (correctEmailCode == null || !correctEmailCode.equals(code))
|
||||
return ResponseEntity.badRequest().body("邮箱验证码错误!");
|
||||
userService.updateUserByUser(User.builder().id(user.getId()).email(email).build());
|
||||
//更新session中的用户信息
|
||||
session.setAttribute("user",userService.getById(user.getId()));
|
||||
return ResponseEntity.ok("更新成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有用户数据
|
||||
*
|
||||
* @return 用户列表
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('MANAGER')")
|
||||
@PostMapping("/all")
|
||||
public ResponseEntity<?> getAll(Integer page, Integer size) {
|
||||
return ResponseEntity.ok(userService.getAll(page, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员更新用户详情
|
||||
*
|
||||
* @return 更新结果
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('MANAGER')")
|
||||
@PostMapping("/update")
|
||||
public ResponseEntity<?> updateUserAndSecurity(
|
||||
@RequestParam("user_id") int userId,
|
||||
@RequestParam("nickname") String nickname,
|
||||
@RequestParam("qq_number") String qqNumber,
|
||||
@RequestParam("email") String email,
|
||||
@RequestParam("locked") boolean locked,
|
||||
@RequestParam("permissions") String permissionsStr,
|
||||
@SessionAttribute("user") User user_info,
|
||||
HttpSession session) {
|
||||
long permissions = ForternUtil.parseLong(permissionsStr);
|
||||
var user = User.builder().id(userId).nickname(nickname).qqNumber(qqNumber).email(email).build();
|
||||
var security = Security.builder().userId(userId).locked(locked).permissions(permissions).build();
|
||||
userService.updateUserAndSecurityByManager(user, security);
|
||||
if(userId == user_info.getId()) {
|
||||
session.setAttribute("user", userService.getById(userId));
|
||||
session.setAttribute("security", userService.getSecurityById(userId));
|
||||
}
|
||||
return ResponseEntity.ok("更新成功");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package xyz.fortern.converter;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.Date;
|
||||
|
||||
public class StringToDateConverter implements Converter<String, Date> {
|
||||
private static final DateTimeFormatter DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
private static final DateTimeFormatter DATE_TIME_LOCAL = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
|
||||
|
||||
@Override
|
||||
public Date convert(String source) {
|
||||
if (source.trim().equals("")) {
|
||||
return null;
|
||||
}
|
||||
Date result = null;
|
||||
try {
|
||||
if (source.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$")) {
|
||||
source = source.replace('T', ' ');
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(source, DATE_TIME_LOCAL);
|
||||
result = Date.from(localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant());
|
||||
} else if (source.matches("^\\d{4}-\\d{2}-\\d{2}$")) {
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(source, DATE);
|
||||
result = Date.from(localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant());
|
||||
}
|
||||
else if (source.matches("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$")){
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(source, DATE_TIME);
|
||||
result = Date.from(localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant());
|
||||
}
|
||||
} catch (DateTimeParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
117
src/main/java/xyz/fortern/dao/ArticleMapper.java
Normal file
117
src/main/java/xyz/fortern/dao/ArticleMapper.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.One;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import xyz.fortern.pojo.Article;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ArticleMapper extends BaseMapper<Article> {
|
||||
//1. 新增一篇文章,MyBatisPlus已实现
|
||||
|
||||
//2. 删除一篇文章,MyBatisPlus已实现
|
||||
|
||||
//3. 修改一篇文章,MyBatisPlus已实现
|
||||
|
||||
//4. 获取文章详情
|
||||
@Select("select id, title, uid, category_id, floor, last_edit_time, summary, content, visible, reviewed, top from article where id = #{id}")
|
||||
@Results(id = "withContent", value = {
|
||||
@Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
|
||||
@Result(column = "title", property = "title", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "uid", property = "uid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "uid", property = "simpleUser", one = @One(select = "xyz.fortern.dao.UserMapper.selectSimpleInfoById")),
|
||||
@Result(column = "category_id", property = "categoryId", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "category_id", property = "category", one = @One(select = "xyz.fortern.dao.CategoryMapper.selectById")),
|
||||
@Result(column = "floor", property = "floor", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "last_edit_time", property = "lastEditTime", jdbcType = JdbcType.DATE),
|
||||
@Result(column = "summary", property = "summary", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "content", property = "content", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "top", property = "top", jdbcType = JdbcType.BIT),
|
||||
@Result(column = "visible", property = "visible", jdbcType = JdbcType.BIT),
|
||||
@Result(column = "reviewed", property = "reviewed", jdbcType = JdbcType.BIT),
|
||||
@Result(column = "id", property = "numOfComments", javaType = int.class, one = @One(select = "xyz.fortern.dao.CommentMapper.countByAid"))
|
||||
})
|
||||
Article selectDetailById(int id);
|
||||
|
||||
|
||||
//4. 查询符合条件的文章数量,MyBatisPlus已实现
|
||||
|
||||
//5. 条件查询文章列表,必须分页,支持排序
|
||||
|
||||
/**
|
||||
* 条件查询文章列表,必须分页,支持排序
|
||||
*
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 文章列表
|
||||
*/
|
||||
@Select("select id, title, uid, category_id, floor, last_edit_time, summary, visible, reviewed, top from article ${ew.customSqlSegment}")
|
||||
@Results(id = "withUserInfo", value = {
|
||||
@Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
|
||||
@Result(column = "title", property = "title", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "uid", property = "uid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "uid", property = "simpleUser", one = @One(select = "xyz.fortern.dao.UserMapper.selectSimpleInfoById")),
|
||||
@Result(column = "category_id", property = "categoryId", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "category_id", property = "category", one = @One(select = "xyz.fortern.dao.CategoryMapper.selectById")),
|
||||
@Result(column = "floor", property = "floor", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "last_edit_time", property = "lastEditTime", jdbcType = JdbcType.DATE),
|
||||
@Result(column = "summary", property = "summary", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "top", property = "top", jdbcType = JdbcType.BIT),
|
||||
@Result(column = "visible", property = "visible", jdbcType = JdbcType.BIT),
|
||||
@Result(column = "reviewed", property = "reviewed", jdbcType = JdbcType.BIT),
|
||||
@Result(column = "id", property = "numOfComments", javaType = int.class, one = @One(select = "xyz.fortern.dao.CommentMapper.countByAid"))
|
||||
})
|
||||
List<Article> selectListByWrapper(@Param(Constants.WRAPPER) Wrapper<Article> queryWrapper);
|
||||
|
||||
//6. 查询文章内容
|
||||
|
||||
/**
|
||||
* 查询文章内容
|
||||
*
|
||||
* @param id 文章id
|
||||
* @return 文章详情
|
||||
*/
|
||||
@Select("select content from article where id = #{id}")
|
||||
String getContentById(int id);
|
||||
|
||||
//7. 获取某文章的楼层数
|
||||
|
||||
/**
|
||||
* 获取某文章的楼层数
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @return 楼层数
|
||||
*/
|
||||
@Select("select floor from article where id = #{aid}")
|
||||
int getFloor(int aid);
|
||||
|
||||
//8. 文章的评论楼层自+1
|
||||
|
||||
/**
|
||||
* 文章的评论楼层自+1
|
||||
*
|
||||
* @param aid 文章id
|
||||
*/
|
||||
@Update("update article set floor = floor + 1 where id = #{aid}")
|
||||
void floorIncrease(int aid);
|
||||
|
||||
//9. 获取文章的作者信息
|
||||
|
||||
/**
|
||||
* 获取文章的作者信息
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @return 作者id
|
||||
*/
|
||||
@Select("select uid from article where id = #{aid}")
|
||||
int getUidByArticle(int aid);
|
||||
}
|
||||
58
src/main/java/xyz/fortern/dao/CategoryMapper.java
Normal file
58
src/main/java/xyz/fortern/dao/CategoryMapper.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import xyz.fortern.pojo.Category;
|
||||
|
||||
@Mapper
|
||||
public interface CategoryMapper extends BaseMapper<Category> {
|
||||
//1. 新增一个分类,MyBatisPlus已实现
|
||||
|
||||
//2. 删除一个分类,MyBatisPlus已实现,仅当该分类下没有文章且该分类下没有其他类别时才能删除该分类
|
||||
|
||||
//3. 修改一个分类,MyBatisPlus已实现
|
||||
|
||||
//4. 查询某个分类的名称,用于其他查询的分步查询,MyBatisPlus已实现
|
||||
|
||||
//5. 查询分类表,MyBatisPlus已实现
|
||||
|
||||
//6. 该分类的子级分类+1
|
||||
|
||||
/**
|
||||
* 该分类的子级分类+1
|
||||
* @param cid 分类id
|
||||
*/
|
||||
@Update("update category set children = children + 1 where id = #{cid}")
|
||||
void updateChildrenAdd(String cid);
|
||||
|
||||
//7. 查询一级分类的最大序号
|
||||
|
||||
/**
|
||||
* 查询一级分类的最大序号
|
||||
*
|
||||
* @return 一级分类的最大序号
|
||||
*/
|
||||
@Select("select children from category where id = '-1'")
|
||||
int getPrimaryCategoryNumber();
|
||||
|
||||
//7. 一级分类的最大序号自增1
|
||||
|
||||
/**
|
||||
* 一级分类的最大序号自增1
|
||||
*/
|
||||
@Select("update category set children = children + 1 where id = '-1'")
|
||||
void updatePrimaryCategoryNumber();
|
||||
|
||||
//8. 获取子级分类的数量,用于删除前的判断
|
||||
|
||||
/**
|
||||
* 获取子级分类的数量,用于删除前的判断
|
||||
* @param cid 分类id
|
||||
* @return 子级分类的数量,0表示没有这个分类,1表示这个分类没有子分类,2表示有子分类
|
||||
*/
|
||||
@Select("select count(*) from category where id like #{cid} '%' limit 2")
|
||||
int countChildren(String cid);
|
||||
|
||||
}
|
||||
110
src/main/java/xyz/fortern/dao/CommentMapper.java
Normal file
110
src/main/java/xyz/fortern/dao/CommentMapper.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.One;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import xyz.fortern.pojo.Comment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface CommentMapper extends BaseMapper<Comment> {
|
||||
//1. 根据id获取某个评论详情,一般没什么用。MyBatisPlus已实现。
|
||||
|
||||
//2. 评论一经发表,不应该再修改。因此不应使用修改功能。
|
||||
|
||||
//3. 发表评论。MyBatisPlus已实现。
|
||||
|
||||
//4. 删除评论。MyBatisPlus已实现。
|
||||
|
||||
//5. 查询某文章下的评论总数,为分页提供条件。MyBatis已实现。
|
||||
|
||||
//5.1 查询某文章下的评论总数,为分页提供条件。MyBatis已实现。此方法提供给
|
||||
@Select("select count(*) from comment where aid = #{aid}")
|
||||
int countByAid(int aid);
|
||||
|
||||
//6. 条件查询附带用户信息的评论信息,必须分页,支持排序。
|
||||
|
||||
/**
|
||||
* 条件查询附带用户信息的评论信息,必须分页,支持排序。
|
||||
* <p>
|
||||
* 使用场景之一:查询某文章下的所有评论
|
||||
*
|
||||
* @param queryWrapper 附加查询条件,如分页与排序
|
||||
* @return 评论列表
|
||||
*/
|
||||
@Select("select id, aid, uid, floor, content, time from comment ${ew.customSqlSegment}")
|
||||
@Results(id = "withUserInfo", value = {
|
||||
@Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
|
||||
@Result(column = "aid", property = "aid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "uid", property = "uid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "uid", property = "simpleUser", one = @One(select = "xyz.fortern.dao.UserMapper.selectSimpleInfoById")),
|
||||
@Result(column = "floor", property = "floor", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "content", property = "content", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "time", property = "time", jdbcType = JdbcType.DATE),
|
||||
@Result(column = "id", property = "numOfReply", one = @One(select = "xyz.fortern.dao.ReplyMapper.countByCid"))
|
||||
})
|
||||
List<Comment> selectByWrapperWithUserInfo(@Param(Constants.WRAPPER) Wrapper<Comment> queryWrapper);
|
||||
|
||||
//7. 查询附带文章信息用户信息的评论列表,必须分页,支持排序
|
||||
|
||||
/**
|
||||
* 查询附带文章信息用户信息的评论列表,必须分页,支持排序,一般用于后台管理查看某用户评论列表
|
||||
*
|
||||
* @param queryWrapper 附加查询条件,如分页与排序
|
||||
* @return 评论列表
|
||||
*/
|
||||
@Select("select id, aid, uid, floor, content, time from comment ${ew.customSqlSegment}")
|
||||
@Results(id = "withArticleInfo", value = {
|
||||
@Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
|
||||
@Result(column = "aid", property = "aid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "aid", property = "SimpleArticle", one = @One(select = "xyz.fortern.dao.ArticleMapper.selectSimpleInfoById")),
|
||||
@Result(column = "uid", property = "uid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "uid", property = "simpleUser", one = @One(select = "xyz.fortern.dao.UserMapper.selectSimpleInfoById")),
|
||||
@Result(column = "floor", property = "floor", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "content", property = "content", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "time", property = "time", jdbcType = JdbcType.DATE)
|
||||
})
|
||||
List<Comment> selectByWrapperWithUserAndArticleInfo(@Param(Constants.WRAPPER) Wrapper<Comment> queryWrapper);
|
||||
|
||||
//8. 获取某评论的楼层数
|
||||
|
||||
/**
|
||||
* 获取评论的楼层数
|
||||
*
|
||||
* @param cid 评论的id
|
||||
* @return 评论的楼层数
|
||||
*/
|
||||
@Select("select layer from comment where id = #{cid}")
|
||||
int getFloor(int cid);
|
||||
|
||||
//9. 评论的回复楼层数自增1
|
||||
|
||||
/**
|
||||
* 评论的回复楼层数自增1
|
||||
*
|
||||
* @param id 评论的id
|
||||
* @return 更新结果
|
||||
*/
|
||||
@Update("update comment set layer = layer + 1 where id = #{id}")
|
||||
int layerIncrease(int id);
|
||||
|
||||
//10. 根据评论获取用户信息
|
||||
|
||||
/**
|
||||
* 根据评论获取用户信息
|
||||
*
|
||||
* @param id 评论id
|
||||
* @return 用户id
|
||||
*/
|
||||
@Select("select uid from comment where id = #{id}")
|
||||
int getUserIdByCommentId(int id);
|
||||
}
|
||||
34
src/main/java/xyz/fortern/dao/DonateMapper.java
Normal file
34
src/main/java/xyz/fortern/dao/DonateMapper.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.One;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import xyz.fortern.pojo.Donate;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface DonateMapper extends BaseMapper<Donate> {
|
||||
|
||||
@Select("select * from donate ${ew.customSqlSegment}")
|
||||
@Results(id = "withUser", value = {
|
||||
@Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
|
||||
@Result(column = "amount", property = "amount", jdbcType = JdbcType.DECIMAL),
|
||||
@Result(column = "user_id", property = "userId", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "user_id", property = "simpleUser", one = @One(select = "xyz.fortern.dao.UserMapper.selectSimpleInfoById")),
|
||||
@Result(column = "time", property = "time", jdbcType = JdbcType.DATE),
|
||||
@Result(column = "trade_no", property = "tradeNo", jdbcType = JdbcType.VARCHAR)
|
||||
})
|
||||
List<Donate> selectListByWrapper(@Param(Constants.WRAPPER) Wrapper<Donate> queryWrapper);
|
||||
|
||||
@Select("select donate from statistics limit 1")
|
||||
BigDecimal selectAmount();
|
||||
}
|
||||
35
src/main/java/xyz/fortern/dao/NewsMapper.java
Normal file
35
src/main/java/xyz/fortern/dao/NewsMapper.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.One;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import xyz.fortern.pojo.News;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface NewsMapper extends BaseMapper<News> {
|
||||
//1. 分页查询动态
|
||||
|
||||
/**
|
||||
* 分页查询动态
|
||||
*
|
||||
* @param offset 偏移量
|
||||
* @param rows 查询数量
|
||||
*/
|
||||
@Select("select * from news limit #{offset}, #{rows}")
|
||||
@Results({
|
||||
@Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
|
||||
@Result(column = "uid", property = "uid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "uid", property = "simpleUser", one = @One(select = "xyz.fortern.dao.UserMapper.selectSimpleInfoById")),
|
||||
@Result(column = "aid", property = "aid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "aid", property = "SimpleArticle", one = @One(select = "xyz.fortern.dao.ArticleMapper.selectSimpleInfoById")),
|
||||
@Result(column = "time", property = "time", jdbcType = JdbcType.DATE),
|
||||
})
|
||||
List<News> getNews(@Param("offset") int offset, @Param("rows") int rows);
|
||||
}
|
||||
70
src/main/java/xyz/fortern/dao/ReplyMapper.java
Normal file
70
src/main/java/xyz/fortern/dao/ReplyMapper.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.One;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.ResultMap;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import xyz.fortern.pojo.Reply;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ReplyMapper extends BaseMapper<Reply> {
|
||||
//1. 添加一条回复,MyBatisPlus已实现
|
||||
|
||||
//2. 删除一条回复,MyBatisPlus已实现
|
||||
|
||||
//3. 回复不应该允许修改,虽然MyBatisPlus已实现
|
||||
|
||||
//4. 根据id查询一条评论,没什么使用场景,虽然MyBatisPlus已实现
|
||||
|
||||
//5. 查询某条评论下的所有回复,用户在文章详情页展示,需要附带用户信息,需要分页,默认按时间顺序展示
|
||||
|
||||
/**
|
||||
* 查询某条评论下的所有回复,用户在文章详情页展示,需要附带用户信息,需要分页,默认按时间顺序展示
|
||||
*
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@Select("select reply.id, reply.cid, reply.uid, reply.floor, reply.time, reply.rid, reply.content, r.uid replied_user_id from reply left join reply r on r.id = reply.rid ${ew.customSqlSegment}")
|
||||
@Results(id = "withUserInfo", value = {
|
||||
@Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
|
||||
@Result(column = "aid", property = "aid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "uid", property = "uid", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "uid", property = "simpleUserFrom", one = @One(select = "xyz.fortern.dao.UserMapper.selectSimpleInfoById")),
|
||||
@Result(column = "replied_user_id", property = "simpleUserTo", one = @One(select = "xyz.fortern.dao.UserMapper.selectSimpleInfoById")),
|
||||
@Result(column = "floor", property = "floor", jdbcType = JdbcType.INTEGER),
|
||||
@Result(column = "content", property = "content", jdbcType = JdbcType.VARCHAR),
|
||||
@Result(column = "time", property = "time", jdbcType = JdbcType.DATE)
|
||||
})
|
||||
List<Reply> selectByCid(@Param(Constants.WRAPPER) Wrapper<Reply> queryWrapper);
|
||||
|
||||
//6. 条件查询回复信息,必须分页,支持排序
|
||||
/**
|
||||
* 条件查询回复信息,必须分页,支持排序
|
||||
*
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@Select("select reply.id, reply.cid, reply.uid, reply.floor, reply.time, reply.rid, reply.content, r.uid replied_user_id from reply left join reply r on r.id = reply.rid ${ew.customSqlSegment}")
|
||||
@ResultMap("withUserInfo")
|
||||
List<Reply> selectByUid(@Param(Constants.WRAPPER) Wrapper<Reply> queryWrapper);
|
||||
|
||||
//7. 查询某条评论的回复数,用于评论信息的分步查询
|
||||
|
||||
/**
|
||||
* 查询某条评论的回复数,用于评论信息下回复信息的分步查询
|
||||
*
|
||||
* @param cid 评论id
|
||||
* @return 回复数量
|
||||
*/
|
||||
@Select("select count(*) from reply where cid = #{cid}")
|
||||
int countByCid(int cid);
|
||||
}
|
||||
29
src/main/java/xyz/fortern/dao/SecurityMapper.java
Normal file
29
src/main/java/xyz/fortern/dao/SecurityMapper.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import xyz.fortern.pojo.Security;
|
||||
|
||||
@Mapper
|
||||
public interface SecurityMapper extends BaseMapper<Security> {
|
||||
/**
|
||||
* 服务器内部查询用户安全信息
|
||||
*
|
||||
* @param loginName 登录名
|
||||
* @param column 登录名所属的列
|
||||
* @return 用户的安全信息
|
||||
*/
|
||||
@Select("select user_id, password, permissions, locked, position from user join security on security.user_id = user.id where ${column} = #{loginName} limit 1")
|
||||
Security selectSecurityInfoByLoginName(@Param("loginName") String loginName, @Param("column") String column);
|
||||
|
||||
/**
|
||||
* 前端询用户安全信息,隐去敏感信息
|
||||
*
|
||||
* @param id 用户id
|
||||
* @return 用户的安全信息
|
||||
*/
|
||||
@Select("select user_id, permissions, locked, position from user join security on security.user_id = user.id where user_id = #{id} limit 1")
|
||||
Security selectSecurityInfoById(int id);
|
||||
}
|
||||
77
src/main/java/xyz/fortern/dao/TagMapper.java
Normal file
77
src/main/java/xyz/fortern/dao/TagMapper.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import xyz.fortern.pojo.Tag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface TagMapper extends BaseMapper<Tag> {
|
||||
//1. 查询一个标签,MyBatisPlus已实现
|
||||
|
||||
//2. 新加一个标签,MyBatisPlus已实现
|
||||
|
||||
//3. 不应该使用更新标签信息的方法,虽然MyBatisPlus已实现
|
||||
|
||||
//4. 删除一个标签,MyBatisPlus已实现
|
||||
|
||||
//5. 查询某个文章的标签列表
|
||||
|
||||
/**
|
||||
* 查询某个文章的标签列表
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @return 文章的标签列表
|
||||
*/
|
||||
@Select("select tag.id, name from tag left join tag_article_relation on tag.id = tag_article_relation.tag_id where article_id = #{aid}")
|
||||
List<Tag> selectByAid(int aid);
|
||||
|
||||
//6. 查询某个标签是否存在
|
||||
|
||||
/**
|
||||
* 查询某个标签是否存在
|
||||
*
|
||||
* @param name 标签名称
|
||||
* @return 标签数量,0或1
|
||||
*/
|
||||
@Select("select count(*) from tag where name = #{name} limit 1")
|
||||
int countByName(String name);
|
||||
|
||||
//7. 添加标签与文章的对应关系
|
||||
|
||||
/**
|
||||
* 添加标签与文章的对应关系
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @param tid 标签id
|
||||
* @return 添加结果
|
||||
*/
|
||||
@Insert("insert into tag_article_relation (tag_id, article_id) values (#{tid}, #{aid})")
|
||||
int insertRelation(int aid, int tid);
|
||||
|
||||
//8. 通过name获取id
|
||||
|
||||
/**
|
||||
* 通过name获取id
|
||||
*
|
||||
* @param name 标签名
|
||||
*/
|
||||
@Select("select id from tag where name = #{name}")
|
||||
Integer selectIdByName(String name);
|
||||
|
||||
//9. 删除一些旧的对应关系
|
||||
|
||||
/**
|
||||
* 删除一些旧的对应关系
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @param oldIds 旧的标签id
|
||||
*/
|
||||
@Delete("delete from tag_article_relation where article_id = #{aid} and tag_id in (${oldIds})")
|
||||
void deleteRelation(@Param("aid") int aid, @Param("oldIds") String oldIds);
|
||||
}
|
||||
42
src/main/java/xyz/fortern/dao/UserMapper.java
Normal file
42
src/main/java/xyz/fortern/dao/UserMapper.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package xyz.fortern.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import xyz.fortern.pojo.User;
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
//1. 查看用户详情,MyBatisPlus已实现
|
||||
|
||||
//2. 查询用户列表,MyBatisPlus已实现,使用时必须分页
|
||||
|
||||
//3. 更新用户信息,MyBatisPlus已实现
|
||||
|
||||
//4. 新用户注册,添加一条用户信息,MyBatisPlus已实现
|
||||
|
||||
//5. 查询简单信息,自行实现
|
||||
|
||||
/**
|
||||
* 查询简单用户信息
|
||||
*
|
||||
* @param id 用户id
|
||||
* @return 用户简单信息
|
||||
*/
|
||||
@Select("select id, username, nickname, head_path as headPath from user where id = #{id}")
|
||||
User.SimpleUser selectSimpleInfoById(int id);
|
||||
|
||||
//6. 不应当使用删除用户的方法
|
||||
|
||||
//7. 用户名是否存在
|
||||
|
||||
/**
|
||||
* 用户名是否存在
|
||||
*
|
||||
* @param username 待检查的用户名
|
||||
* @return 该用户名存在的数量,0或1
|
||||
*/
|
||||
@Select("select count(*) from user where username = #{username} limit 1")
|
||||
int existUsername(String username);
|
||||
|
||||
}
|
||||
171
src/main/java/xyz/fortern/pojo/Article.java
Normal file
171
src/main/java/xyz/fortern/pojo/Article.java
Normal file
@@ -0,0 +1,171 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("article")
|
||||
public class Article implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@TableField("title")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@TableField("uid")
|
||||
private Integer uid;
|
||||
|
||||
/**
|
||||
* 简单用户信息,部分情况下获取该属性
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private User.SimpleUser simpleUser;
|
||||
|
||||
/**
|
||||
* 分类id
|
||||
*/
|
||||
@TableField("category_id")
|
||||
private String categoryId;
|
||||
|
||||
/**
|
||||
* 表示分类的对象
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Category category;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Tag> tags;
|
||||
|
||||
/**
|
||||
* 最大楼层数
|
||||
*/
|
||||
@TableField("floor")
|
||||
private Integer floor;
|
||||
|
||||
/**
|
||||
* 上次编辑时间
|
||||
*/
|
||||
@TableField("last_edit_time")
|
||||
private Date lastEditTime;
|
||||
|
||||
/**
|
||||
* 文章摘要
|
||||
*/
|
||||
@TableField("summary")
|
||||
private String summary;
|
||||
|
||||
/**
|
||||
* 文章主体内容,仅当查询文章详情时查询此字段
|
||||
*/
|
||||
@TableField(value = "content", select = false)
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 可见性
|
||||
* <p>
|
||||
* false:仅本人与管理员可见,true:任何人可见
|
||||
*/
|
||||
@TableField(value = "visible")
|
||||
private Boolean visible;
|
||||
|
||||
/**
|
||||
* 是否审核通过,true表示审核通过
|
||||
*/
|
||||
@TableField(value = "reviewed")
|
||||
private Boolean reviewed;
|
||||
|
||||
/**
|
||||
* 评论数,附加信息,通过分步查询得到
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer numOfComments;
|
||||
|
||||
/**
|
||||
* 是否置顶
|
||||
*/
|
||||
@TableField("top")
|
||||
private Boolean top;
|
||||
|
||||
/**
|
||||
* 简单文章信息,用于在特定位置显示简略信息
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SimpleArticle {
|
||||
/**
|
||||
* 文章id
|
||||
*/
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 文章标题
|
||||
*/
|
||||
private String title;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章的查询条件类
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class ArticleExample {
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 文章所属类别
|
||||
*/
|
||||
private String categoryId;
|
||||
/**
|
||||
* “编辑时间”的范围的最早时间
|
||||
*/
|
||||
private Date editTimeBegin;
|
||||
/**
|
||||
* “编辑时间”的范围的最晚时间
|
||||
*/
|
||||
private Date editTimeEnd;
|
||||
/**
|
||||
* 是否已审核
|
||||
*/
|
||||
private Boolean reviewed;
|
||||
/**
|
||||
* 可见性
|
||||
*/
|
||||
private Boolean visible;
|
||||
/**
|
||||
* 置顶
|
||||
*/
|
||||
private Boolean top;
|
||||
|
||||
}
|
||||
}
|
||||
37
src/main/java/xyz/fortern/pojo/Category.java
Normal file
37
src/main/java/xyz/fortern/pojo/Category.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 文章分类
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("category")
|
||||
public class Category implements Serializable {
|
||||
/**
|
||||
* 分类的主键id
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
@TableField("name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 子级类的最大序号,在添加分类时用到
|
||||
*/
|
||||
@TableField("children")
|
||||
private Integer children;
|
||||
}
|
||||
112
src/main/java/xyz/fortern/pojo/Comment.java
Normal file
112
src/main/java/xyz/fortern/pojo/Comment.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 文章评论实体类
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("comment")
|
||||
public class Comment implements Serializable {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 文章id
|
||||
*/
|
||||
@TableField("aid")
|
||||
private int aid;
|
||||
|
||||
/**
|
||||
* 简单文章信息
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Article.SimpleArticle simpleArticle;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@TableField("uid")
|
||||
private int uid;
|
||||
|
||||
/**
|
||||
* 简单用户信息
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private User.SimpleUser simpleUser;
|
||||
|
||||
/**
|
||||
* 楼层,数据库中有默认值0
|
||||
*/
|
||||
@TableField("floor")
|
||||
private int floor;
|
||||
|
||||
/**
|
||||
* 评论具体内容
|
||||
*/
|
||||
@TableField(value = "content")
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 评论时间
|
||||
*/
|
||||
@TableField("time")
|
||||
private Date time;
|
||||
|
||||
/**
|
||||
* 评论的回复数
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private int numOfReply;
|
||||
|
||||
/**
|
||||
* 用于前端封装查询条件的类
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class CommentExample {
|
||||
/**
|
||||
* 用户id,只有管理员能够根据id搜索
|
||||
*/
|
||||
private Integer userId;
|
||||
|
||||
/**
|
||||
* 时间范围,起始时间
|
||||
*/
|
||||
private Date createTimeBegin;
|
||||
|
||||
/**
|
||||
* 时间范围,结束时间
|
||||
*/
|
||||
private Date createTimeEnd;
|
||||
|
||||
/**
|
||||
* 文章id
|
||||
*/
|
||||
private Integer articleId;
|
||||
|
||||
/**
|
||||
* 时间排序规则,默认最新的在前
|
||||
*/
|
||||
private boolean orderByTime;
|
||||
}
|
||||
|
||||
}
|
||||
59
src/main/java/xyz/fortern/pojo/Donate.java
Normal file
59
src/main/java/xyz/fortern/pojo/Donate.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 捐赠信息实体类
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("donate")
|
||||
public class Donate implements Serializable {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId("id")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 捐赠金额
|
||||
*/
|
||||
@TableField("amount")
|
||||
private BigDecimal amount;
|
||||
|
||||
/**
|
||||
* 捐赠时间
|
||||
*/
|
||||
@TableField("time")
|
||||
private Date time;
|
||||
|
||||
/**
|
||||
* 捐赠者Id
|
||||
*/
|
||||
@TableField("user_id")
|
||||
private int userId;
|
||||
|
||||
/**
|
||||
* 捐赠者基本信息
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private User.SimpleUser simpleUser;
|
||||
|
||||
/**
|
||||
* 支付宝交易号
|
||||
*/
|
||||
@TableField("trade_no")
|
||||
private String tradeNo;
|
||||
}
|
||||
87
src/main/java/xyz/fortern/pojo/News.java
Normal file
87
src/main/java/xyz/fortern/pojo/News.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 动态,当用户进行某些操作时,会产生动态(News)。
|
||||
* News最多记录50条,产生新纪录则删除旧记录
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("news")
|
||||
public class News {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 动态生产者的id
|
||||
*/
|
||||
@TableField("user_id")
|
||||
private Integer userId;
|
||||
|
||||
/**
|
||||
* 动态生产者的简略信息
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private User.SimpleUser user;
|
||||
|
||||
/**
|
||||
* 用户的行为
|
||||
*/
|
||||
@TableField("action")
|
||||
private Action action;
|
||||
|
||||
/**
|
||||
* 该动态所操作的对象,一般来说是文章
|
||||
*/
|
||||
@TableField("target_id")
|
||||
private Integer targetId;
|
||||
|
||||
/**
|
||||
* 该动态产生的时间
|
||||
*/
|
||||
@TableField("time")
|
||||
private Date time;
|
||||
|
||||
/**
|
||||
* 简要文章信息
|
||||
*/
|
||||
private Article.SimpleArticle article;
|
||||
|
||||
/**
|
||||
* 用户的行为枚举
|
||||
*/
|
||||
public enum Action {
|
||||
/**
|
||||
* 注册
|
||||
*/
|
||||
REGISTER,
|
||||
/**
|
||||
* 编辑文章
|
||||
*/
|
||||
EDIT_ARTICLE,
|
||||
/**
|
||||
* 发布文章
|
||||
*/
|
||||
PUBLISH_ARTICLE,
|
||||
/**
|
||||
* 发布评论
|
||||
*/
|
||||
PUBLISH_COMMENT
|
||||
}
|
||||
|
||||
}
|
||||
15
src/main/java/xyz/fortern/pojo/PermissionKeyValue.java
Normal file
15
src/main/java/xyz/fortern/pojo/PermissionKeyValue.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
public enum PermissionKeyValue {
|
||||
ARTICLE("article", 0x8000000000000000L),
|
||||
COMMENT("comment", 0x4000000000000000L),
|
||||
PHOTO("photo", 0x2000000000000000L);
|
||||
|
||||
public final String name;
|
||||
public final long value;
|
||||
|
||||
PermissionKeyValue(String name, long value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
73
src/main/java/xyz/fortern/pojo/Reply.java
Normal file
73
src/main/java/xyz/fortern/pojo/Reply.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Reply {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 该回复所属的评论的id
|
||||
*/
|
||||
@TableField("cid")
|
||||
private int cid;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@TableField("uid")
|
||||
private int uid;
|
||||
|
||||
/**
|
||||
* 发表该回复的用户的简单信息
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private User.SimpleUser simpleUserFrom;
|
||||
|
||||
/**
|
||||
* 被回复者的简单信息
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private User.SimpleUser simpleUserTo;
|
||||
|
||||
/**
|
||||
* 该回复在当前评论下的楼层
|
||||
*/
|
||||
@TableField("floor")
|
||||
private int floor;
|
||||
|
||||
/**
|
||||
* 发表时间
|
||||
*/
|
||||
@TableField("time")
|
||||
private Date time;
|
||||
|
||||
/**
|
||||
* 回复的那条回复的id,如果为空表示在回复层主
|
||||
*/
|
||||
@TableField("rid")
|
||||
private Integer rid;
|
||||
|
||||
/**
|
||||
* 回复的具体内容
|
||||
*/
|
||||
@TableField("content")
|
||||
private String content;
|
||||
|
||||
}
|
||||
62
src/main/java/xyz/fortern/pojo/Security.java
Normal file
62
src/main/java/xyz/fortern/pojo/Security.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("security")
|
||||
public class Security {
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@TableId(value = "user_id", type = IdType.AUTO)
|
||||
private Integer userId;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@TableField("password")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 是否锁定
|
||||
*/
|
||||
@TableField("locked")
|
||||
private Boolean locked;
|
||||
|
||||
/**
|
||||
* 权限
|
||||
*/
|
||||
@TableField("permissions")
|
||||
private Long permissions;
|
||||
|
||||
/**
|
||||
* 身份信息
|
||||
*/
|
||||
@TableField("position")
|
||||
private Position position;
|
||||
|
||||
/**
|
||||
* 用来表示用户身份的内部枚举
|
||||
*/
|
||||
public enum Position {
|
||||
/**
|
||||
* USER表示普通玩家
|
||||
*/
|
||||
USER,
|
||||
/**
|
||||
* MANAGER表示管理员,但管理员也属于玩家
|
||||
*/
|
||||
MANAGER
|
||||
}
|
||||
}
|
||||
32
src/main/java/xyz/fortern/pojo/Tag.java
Normal file
32
src/main/java/xyz/fortern/pojo/Tag.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 标签类
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("tag")
|
||||
public class Tag {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
@TableField("name")
|
||||
private String name;
|
||||
}
|
||||
82
src/main/java/xyz/fortern/pojo/User.java
Normal file
82
src/main/java/xyz/fortern/pojo/User.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package xyz.fortern.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("user")
|
||||
public class User implements Serializable {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 用户名,唯一,不可更改
|
||||
*/
|
||||
@TableField("username")
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 电子邮箱
|
||||
*/
|
||||
@TableField("email")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* QQ号码,每个用户都应当有个QQ号(应该没有QQ号是以0开头的吧)
|
||||
*/
|
||||
@TableField("qq_number")
|
||||
private String qqNumber;
|
||||
|
||||
/**
|
||||
* 注册时间
|
||||
*/
|
||||
@TableField("registration_time")
|
||||
private Date registrationTime;
|
||||
|
||||
/**
|
||||
* 昵称,用户可以自由设置
|
||||
*/
|
||||
@TableField("nickname")
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 头像存放的路径
|
||||
*/
|
||||
@TableField("head_path")
|
||||
private String headPath;
|
||||
|
||||
/**
|
||||
* 个性签名
|
||||
*/
|
||||
@TableField("sign")
|
||||
private String sign;
|
||||
|
||||
/**
|
||||
* 简单用户信息,用于在查看文章、评论的列表时,展示简单的用户信息
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SimpleUser {
|
||||
private Integer id;
|
||||
private String username;
|
||||
private String nickname;
|
||||
private String headPath;
|
||||
}
|
||||
|
||||
}
|
||||
116
src/main/java/xyz/fortern/service/AccountService.java
Normal file
116
src/main/java/xyz/fortern/service/AccountService.java
Normal file
@@ -0,0 +1,116 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import xyz.fortern.dao.SecurityMapper;
|
||||
import xyz.fortern.dao.UserMapper;
|
||||
import xyz.fortern.pojo.PermissionKeyValue;
|
||||
import xyz.fortern.pojo.Security;
|
||||
import xyz.fortern.pojo.User;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static xyz.fortern.bbs.SystemConstant.EMAIL_REGEX;
|
||||
|
||||
@Service
|
||||
public class AccountService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final SecurityMapper securityMapper;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
public AccountService(UserMapper userMapper, SecurityMapper securityMapper, PasswordEncoder passwordEncoder) {
|
||||
this.userMapper = userMapper;
|
||||
this.securityMapper = securityMapper;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过登录名和密码登录
|
||||
*
|
||||
* @param loginName 登录名,可能是用户名和手机号
|
||||
* @param password 密码
|
||||
* @return 登录结果
|
||||
*/
|
||||
public int login(String loginName, String password, HttpSession session) {
|
||||
String column = EMAIL_REGEX.matcher(loginName).matches() ? "email" : "username";
|
||||
var security = securityMapper.selectSecurityInfoByLoginName(loginName, column);
|
||||
if (security == null)
|
||||
return 0;//用户不存在
|
||||
if (security.getLocked())
|
||||
return -2;//用户被锁定,不可登录
|
||||
if (passwordEncoder.matches(password, security.getPassword())) {
|
||||
int userId = security.getUserId();
|
||||
//如果密码匹配
|
||||
//获取用户基本信息
|
||||
var user = userMapper.selectById(userId);
|
||||
//设置权限信息
|
||||
var authorities = new HashSet<GrantedAuthority>();
|
||||
for (PermissionKeyValue permission : PermissionKeyValue.values()) {
|
||||
if ((permission.value ^ security.getPermissions()) == permission.value) {
|
||||
authorities.add(new SimpleGrantedAuthority(permission.name));
|
||||
}
|
||||
}
|
||||
if (security.getPosition() == Security.Position.MANAGER)
|
||||
authorities.add(new SimpleGrantedAuthority("manager"));
|
||||
var authenticationToken = new UsernamePasswordAuthenticationToken(userId, null, authorities);
|
||||
//将认证成功信息设置到安全上下文中
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
//用户相关信息放入Session中
|
||||
session.setAttribute("user", user);
|
||||
session.setAttribute("security", security);
|
||||
return 1;//登录成功
|
||||
} else {
|
||||
return -1;//密码错误
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册业务
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @param email 电子邮箱
|
||||
* @param qqNumber QQ号
|
||||
*/
|
||||
@Transactional
|
||||
public void register(String username, String password, String email, String qqNumber) {
|
||||
//先存用户,获取用户id
|
||||
var user = User.builder().username(username).email(email).qqNumber(qqNumber).build();
|
||||
userMapper.insert(user);
|
||||
//再存安全信息
|
||||
var security = Security.builder().password(passwordEncoder.encode(password)).userId(user.getId()).build();
|
||||
securityMapper.insert(security);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*
|
||||
* @param uid 用户id
|
||||
* @param newPassword 新密码(明文)
|
||||
*/
|
||||
@Transactional
|
||||
public Security changePassword(int uid, String newPassword) {
|
||||
var security = Security.builder().userId(uid).password(passwordEncoder.encode(newPassword)).build();
|
||||
securityMapper.updateById(security);
|
||||
return securityMapper.selectSecurityInfoByLoginName(Integer.toString(uid), "user_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验密码是否正确
|
||||
*
|
||||
* @param oldPassword 旧密码(明文)
|
||||
* @param encodedOldPassword 旧密码(密文)
|
||||
*/
|
||||
public boolean passwordMatches(@NonNull String oldPassword, @NonNull String encodedOldPassword) {
|
||||
return passwordEncoder.matches(oldPassword, encodedOldPassword);
|
||||
}
|
||||
|
||||
}
|
||||
258
src/main/java/xyz/fortern/service/ArticleService.java
Normal file
258
src/main/java/xyz/fortern/service/ArticleService.java
Normal file
@@ -0,0 +1,258 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import xyz.fortern.dao.ArticleMapper;
|
||||
import xyz.fortern.dao.NewsMapper;
|
||||
import xyz.fortern.dao.TagMapper;
|
||||
import xyz.fortern.pojo.Article;
|
||||
import xyz.fortern.pojo.News;
|
||||
import xyz.fortern.pojo.Tag;
|
||||
import xyz.fortern.util.ForternUtil;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ArticleService {
|
||||
private final ArticleMapper articleMapper;
|
||||
private final TagMapper tagMapper;
|
||||
private final NewsMapper newsMapper;
|
||||
|
||||
public ArticleService(ArticleMapper articleMapper, TagMapper tagMapper, NewsMapper newsMapper) {
|
||||
this.articleMapper = articleMapper;
|
||||
this.tagMapper = tagMapper;
|
||||
this.newsMapper = newsMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文章详情
|
||||
*
|
||||
* @param id 文章Id
|
||||
* @return 文章详情
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Article getAllInfoById(int id) {
|
||||
var article = articleMapper.selectDetailById(id);
|
||||
if (article == null)
|
||||
return null;
|
||||
// 给文章添加标签信息
|
||||
var tagList = tagMapper.selectByAid(id);
|
||||
article.setTags(tagList);
|
||||
return article;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一篇新文章
|
||||
*
|
||||
* @param article 文章详情
|
||||
*/
|
||||
@Transactional
|
||||
public void addNewArticle(Article article) {
|
||||
var date = new Date();
|
||||
article.setLastEditTime(date);
|
||||
//先添加文章,获取文章的id
|
||||
articleMapper.insert(article);
|
||||
var tags = article.getTags();
|
||||
//建立文章与标签的对应关系
|
||||
for (Tag tag : tags) {
|
||||
tagMapper.insertRelation(article.getId(), tag.getId());
|
||||
}
|
||||
//最后新增一条动态
|
||||
var news = News.builder().userId(article.getUid()).targetId(article.getId()).action(News.Action.PUBLISH_ARTICLE).time(date).build();
|
||||
newsMapper.insert(news);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新一篇文章,本人与管理员可以操作
|
||||
*
|
||||
* @param article 文章详情
|
||||
* @param uid 操作者id,并非原作者
|
||||
*/
|
||||
@Transactional
|
||||
public void updateArticle(Article article, int uid) {
|
||||
int aid = article.getId();
|
||||
var date = new Date();
|
||||
article.setLastEditTime(date);
|
||||
//获取旧的标签集合
|
||||
var oldIds = tagMapper.selectByAid(aid).stream().map(Tag::getId).collect(Collectors.toSet());
|
||||
//获取新的标签集合
|
||||
var newIds = article.getTags().stream().map(Tag::getId).collect(Collectors.toSet());
|
||||
//去除其中重复的元素
|
||||
ForternUtil.removeSame(oldIds, newIds);
|
||||
//删除不再需要的标签关系
|
||||
var s_oldIds = new StringBuilder();
|
||||
for (Integer id : oldIds) {
|
||||
s_oldIds.append(id).append(",");
|
||||
}
|
||||
if (!s_oldIds.isEmpty()) {
|
||||
s_oldIds.deleteCharAt(s_oldIds.length() - 1);
|
||||
tagMapper.deleteRelation(aid, s_oldIds.toString());
|
||||
}
|
||||
//建立文章与标签的新的对应关系
|
||||
for (Integer id : newIds) {
|
||||
tagMapper.insertRelation(article.getId(), id);
|
||||
}
|
||||
articleMapper.updateById(article);
|
||||
//最后新增一条动态
|
||||
var news = News.builder().userId(uid).targetId(aid).action(News.Action.EDIT_ARTICLE).time(date).build();
|
||||
newsMapper.insert(news);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主页置顶文章列表,不含隐藏和未审核的文章
|
||||
*
|
||||
* @return 主页置顶文章列表
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<Article> getTops() {
|
||||
LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Article::getTop, true);//置顶的
|
||||
wrapper.eq(Article::getVisible, true);//可见的
|
||||
wrapper.eq(Article::getReviewed, true);//审核通过的
|
||||
return articleMapper.selectListByWrapper(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主页未置顶文章列表,不含隐藏和未审核的文章
|
||||
*
|
||||
* @return 未置顶文章列表
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public PageInfo<Article> getNotTops(Integer page, Integer size) {
|
||||
LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Article::getTop, false);//未置顶的
|
||||
wrapper.eq(Article::getVisible, true);//可见的
|
||||
wrapper.eq(Article::getReviewed, true);//审核通过的
|
||||
//获取总数
|
||||
int total = Math.toIntExact(articleMapper.selectCount(wrapper));
|
||||
if (size == null || size < 1 || size > 100)
|
||||
size = 10;
|
||||
int pages = (total - 1) / size + 1;
|
||||
if (pages < page) page = pages;
|
||||
wrapper.last("limit " + (page - 1) * size + "," + size);
|
||||
var articles = articleMapper.selectListByWrapper(wrapper);
|
||||
return new PageInfo<>(page, size, total, articles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文章的作者信息
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @return 作者id
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Integer getUidByArticle(int aid) {
|
||||
return articleMapper.getUidByArticle(aid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一片文章
|
||||
*
|
||||
* @param id 文章id
|
||||
* @return 操作是否成功
|
||||
*/
|
||||
@Transactional
|
||||
public boolean delete(int id) {
|
||||
return articleMapper.deleteById(id) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员获取所有文章列表
|
||||
*
|
||||
* @return 所有文章列表
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public PageInfo<Article> getAll(Article.ArticleExample articleExample, @NonNull PageInfo<Article> pageInfo) {
|
||||
var queryWrapper = new QueryWrapper<Article>();
|
||||
exampleToWrapper(articleExample, queryWrapper);
|
||||
//获取总数
|
||||
int total = Math.toIntExact(articleMapper.selectCount(queryWrapper));
|
||||
int size = pageInfo.getPageSize();
|
||||
int pages = (total - 1) / size + 1;
|
||||
if (pages < pageInfo.getPageIndex()) pageInfo.setPageIndex(pages);
|
||||
queryWrapper.last("limit " + (pageInfo.getPageIndex() - 1) * size + "," + size);
|
||||
var articles = articleMapper.selectListByWrapper(queryWrapper);
|
||||
pageInfo.setTotalCount(total);
|
||||
pageInfo.setRecords(articles);
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主页分类查询列表,不含隐藏的和未审核的文章
|
||||
*
|
||||
* @param categoryId 分类id
|
||||
* @param pageInfo 分页信息
|
||||
* @return 一页的文章列表
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public PageInfo<Article> getByCategoryInIndex(String categoryId, @NonNull PageInfo<Article> pageInfo) {
|
||||
var queryWrapper = new LambdaQueryWrapper<Article>();
|
||||
queryWrapper.likeRight(Article::getCategoryId, categoryId);
|
||||
queryWrapper.eq(Article::getVisible, true);
|
||||
queryWrapper.eq(Article::getReviewed, true);
|
||||
int total = Math.toIntExact(articleMapper.selectCount(queryWrapper));
|
||||
int size = pageInfo.getPageSize();
|
||||
int pages = (total - 1) / size + 1;
|
||||
if (pages < pageInfo.getPageIndex()) pageInfo.setPageIndex(pages);
|
||||
queryWrapper.orderByDesc(Article::getLastEditTime);
|
||||
queryWrapper.last("limit " + (pageInfo.getPageIndex() - 1) * size + "," + size);
|
||||
var articles = articleMapper.selectListByWrapper(queryWrapper);
|
||||
pageInfo.setTotalCount(total);
|
||||
pageInfo.setRecords(articles);
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据关键词搜索文章,得到一页数据
|
||||
*
|
||||
* @param key 关键词
|
||||
* @param pageInfo 文分页信息
|
||||
* @return 搜索得到的一页的文章数据
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public PageInfo<Article> search(String key, PageInfo<Article> pageInfo) {
|
||||
var queryWrapper = new LambdaQueryWrapper<Article>();
|
||||
queryWrapper.eq(Article::getVisible, true).eq(Article::getReviewed, true);
|
||||
queryWrapper.and(wrapper -> wrapper
|
||||
.like(Article::getTitle, key).or()
|
||||
.like(Article::getTitle, key).or()
|
||||
.like(Article::getSummary, key).or()
|
||||
.like(Article::getContent, key)
|
||||
);
|
||||
int total = Math.toIntExact(articleMapper.selectCount(queryWrapper));
|
||||
int size = pageInfo.getPageSize();
|
||||
int pages = (total - 1) / size + 1;
|
||||
if (pages < pageInfo.getPageIndex()) pageInfo.setPageIndex(pages);
|
||||
queryWrapper.orderByDesc(Article::getLastEditTime);
|
||||
queryWrapper.last("limit " + (pageInfo.getPageIndex() - 1) * size + "," + size);
|
||||
var articles = articleMapper.selectListByWrapper(queryWrapper);
|
||||
pageInfo.setRecords(articles);
|
||||
pageInfo.setTotalCount(total);
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装查询条件
|
||||
*
|
||||
* @param articleExample 查询条件
|
||||
*/
|
||||
private void exampleToWrapper(Article.ArticleExample articleExample, QueryWrapper<Article> queryWrapper) {
|
||||
var lambda = queryWrapper.lambda();
|
||||
if (articleExample.getUserId() != null) lambda.eq(Article::getUid, articleExample.getUserId());
|
||||
if (articleExample.getCategoryId() != null) lambda.likeRight(Article::getCategoryId, articleExample.getCategoryId());
|
||||
if (articleExample.getEditTimeBegin() != null)
|
||||
lambda.ge(Article::getLastEditTime, articleExample.getEditTimeBegin());
|
||||
if (articleExample.getEditTimeEnd() != null)
|
||||
lambda.le(Article::getLastEditTime, articleExample.getEditTimeEnd());
|
||||
if (articleExample.getReviewed() != null) lambda.eq(Article::getReviewed, articleExample.getReviewed());
|
||||
if (articleExample.getVisible() != null) lambda.eq(Article::getVisible, articleExample.getVisible());
|
||||
if (articleExample.getTop() != null) lambda.eq(Article::getTop, articleExample.getTop());
|
||||
}
|
||||
|
||||
}
|
||||
105
src/main/java/xyz/fortern/service/CategoryService.java
Normal file
105
src/main/java/xyz/fortern/service/CategoryService.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import xyz.fortern.dao.ArticleMapper;
|
||||
import xyz.fortern.dao.CategoryMapper;
|
||||
import xyz.fortern.pojo.Article;
|
||||
import xyz.fortern.pojo.Category;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CategoryService {
|
||||
private final CategoryMapper categoryMapper;
|
||||
private final ArticleMapper articleMapper;
|
||||
|
||||
public CategoryService(CategoryMapper categoryMapper, ArticleMapper articleMapper) {
|
||||
this.categoryMapper = categoryMapper;
|
||||
this.articleMapper = articleMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个新的分类
|
||||
*
|
||||
* @param categoryName 分类名称
|
||||
* @param superiorId 父级分类的id
|
||||
* @return 添加结果
|
||||
*/
|
||||
@Transactional
|
||||
public String addNewCategory(String categoryName, String superiorId) {
|
||||
Category category;
|
||||
if (superiorId == null) {
|
||||
//此时添加一级分类
|
||||
//获取一级分类的最大序号
|
||||
int serial = categoryMapper.getPrimaryCategoryNumber();
|
||||
//更新一级分类的最大序号
|
||||
categoryMapper.updatePrimaryCategoryNumber();
|
||||
//添加一个一级分类
|
||||
category = new Category(Integer.toString(serial + 1), categoryName, null);
|
||||
} else {
|
||||
var superiorCategory = categoryMapper.selectById(superiorId);
|
||||
//如果父类id传入却不存在,返回null
|
||||
if (superiorCategory == null) return null;
|
||||
//获取子级分类的最大序号
|
||||
int serial = superiorCategory.getChildren();
|
||||
//子级分类的最大序号自增1
|
||||
categoryMapper.updateChildrenAdd(superiorCategory.getId());
|
||||
//插入新的分类
|
||||
category = new Category(superiorCategory.getId() + (serial + 1) + "_", categoryName, null);
|
||||
}
|
||||
//插入新的一级分类
|
||||
categoryMapper.insert(category);
|
||||
//返回新分类的id
|
||||
return category.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个分类
|
||||
*
|
||||
* @param id 要删除的分类的id
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Transactional
|
||||
public boolean deleteCategory(String id) {
|
||||
int countCategory = categoryMapper.countChildren(id);
|
||||
//该分类不存在或者该分类下有其他子分类
|
||||
if (countCategory != 1)
|
||||
return false;
|
||||
int articleCount = Math.toIntExact(articleMapper.selectCount(new LambdaQueryWrapper<Article>().eq(Article::getCategoryId, id).last("limit 1")));
|
||||
//该分类下仍有文章数据
|
||||
if (articleCount == 1)
|
||||
return false;
|
||||
categoryMapper.deleteById(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有分类
|
||||
*
|
||||
* @return 分类列表
|
||||
*/
|
||||
@Transactional
|
||||
public List<Category> getAll() {
|
||||
var queryWrapper = new QueryWrapper<Category>();
|
||||
queryWrapper.lambda().ne(Category::getId, "-1");
|
||||
var categories = categoryMapper.selectList(queryWrapper);
|
||||
categories.sort(Comparator.comparing(Category::getId));
|
||||
return categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取分类名称
|
||||
*
|
||||
* @param id 分类的id
|
||||
* @return 分类名称
|
||||
*/
|
||||
@Transactional
|
||||
public String getNameById(String id) {
|
||||
var category = categoryMapper.selectById(id);
|
||||
return category.getName();
|
||||
}
|
||||
}
|
||||
120
src/main/java/xyz/fortern/service/CommentService.java
Normal file
120
src/main/java/xyz/fortern/service/CommentService.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import xyz.fortern.dao.ArticleMapper;
|
||||
import xyz.fortern.dao.CommentMapper;
|
||||
import xyz.fortern.dao.NewsMapper;
|
||||
import xyz.fortern.pojo.Comment;
|
||||
import xyz.fortern.pojo.News;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 评论业务
|
||||
*/
|
||||
@Service
|
||||
public class CommentService extends ServiceImpl<CommentMapper, Comment> {
|
||||
private final CommentMapper commentMapper;
|
||||
private final ArticleMapper articleMapper;
|
||||
private final NewsMapper newsMapper;
|
||||
|
||||
public CommentService(CommentMapper commentMapper, ArticleMapper articleMapper, NewsMapper newsMapper) {
|
||||
this.commentMapper = commentMapper;
|
||||
this.articleMapper = articleMapper;
|
||||
this.newsMapper = newsMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某文章下的评论列表,必须分页
|
||||
*
|
||||
* @param aid 文章id
|
||||
* @param page 页码
|
||||
* @param size 页面容量
|
||||
* @return 评论列表
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public PageInfo<Comment> getCommentsByAid(int aid, int page, int size) {
|
||||
int total = commentMapper.countByAid(aid);
|
||||
int pages = (total - 1) / size + 1;
|
||||
if (page > pages) page = pages;
|
||||
if (size < 5 || size > 100) size = 5;
|
||||
var queryWrapper = new LambdaQueryWrapper<Comment>().eq(Comment::getAid, aid);
|
||||
queryWrapper.orderByDesc(Comment::getFloor);
|
||||
queryWrapper.last("limit " + size * (page - 1) + "," + size);
|
||||
var comments = commentMapper.selectByWrapperWithUserInfo(queryWrapper);
|
||||
return new PageInfo<>(page, size, total, comments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询评论列表
|
||||
*
|
||||
* @param example 查询条件
|
||||
* @param page 页码
|
||||
* @param size 页容量
|
||||
* @return 一页的评论
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public PageInfo<Comment> getCommentsByWrapper(Comment.CommentExample example, Integer page, Integer size) {
|
||||
var queryWrapper = new LambdaQueryWrapper<Comment>();
|
||||
if (example.getUserId() != null) queryWrapper.eq(Comment::getUid, example.getUserId());
|
||||
if (example.getArticleId() != null) queryWrapper.eq(Comment::getAid, example.getArticleId());
|
||||
if (example.getCreateTimeBegin() != null) queryWrapper.ge(Comment::getTime, example.getCreateTimeBegin());
|
||||
if (example.getCreateTimeEnd() != null) queryWrapper.le(Comment::getTime, example.getCreateTimeEnd());
|
||||
if (example.isOrderByTime())
|
||||
queryWrapper.orderByAsc(Comment::getTime);
|
||||
else
|
||||
queryWrapper.orderByDesc(Comment::getTime);
|
||||
int total = Math.toIntExact(commentMapper.selectCount(queryWrapper));
|
||||
int pages = (total - 1) / size + 1;
|
||||
if (page > pages) page = pages;
|
||||
queryWrapper.last("limit " + size * (page - 1) + "," + size);
|
||||
var comments = commentMapper.selectByWrapperWithUserInfo(queryWrapper);
|
||||
return new PageInfo<>(page, size, total, comments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条新评论
|
||||
*
|
||||
* @param comment 评论详情
|
||||
*/
|
||||
@Transactional
|
||||
public void addNewComment(Comment comment) {
|
||||
int aid = comment.getAid();
|
||||
//获取文章评论的最大楼层数
|
||||
int floor = articleMapper.getFloor(aid);
|
||||
comment.setFloor(floor + 1);
|
||||
Date date = new Date();
|
||||
comment.setTime(date);
|
||||
//插入Comment
|
||||
commentMapper.insert(comment);
|
||||
var news = News.builder().userId(comment.getUid()).targetId(aid).action(News.Action.PUBLISH_COMMENT).time(date).build();
|
||||
//文章的评论楼层+1
|
||||
articleMapper.floorIncrease(aid);
|
||||
//插入News
|
||||
newsMapper.insert(news);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据评论获取用户信息
|
||||
*
|
||||
* @param id 评论id
|
||||
* @return 用户id
|
||||
*/
|
||||
@Transactional
|
||||
public int getUserIdByCommentId(int id) {
|
||||
return commentMapper.getUserIdByCommentId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除评论
|
||||
*
|
||||
* @param id 评论id
|
||||
*/
|
||||
public void delById(int id) {
|
||||
commentMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
70
src/main/java/xyz/fortern/service/DonateService.java
Normal file
70
src/main/java/xyz/fortern/service/DonateService.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import xyz.fortern.dao.DonateMapper;
|
||||
import xyz.fortern.pojo.Donate;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DonateService {
|
||||
private final DonateMapper donateMapper;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public DonateService(DonateMapper donateMapper, RedisTemplate<String, Object> redisTemplate) {
|
||||
this.donateMapper = donateMapper;
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付成功后,数据加入数据库
|
||||
*
|
||||
* @param donate_id 商户订单号
|
||||
* @param tradeNo 支付宝交易号
|
||||
* @return 处理结果
|
||||
*/
|
||||
public boolean paySuccess(String donate_id, String tradeNo) {
|
||||
log.info("用户支付成功,订单号:{}", donate_id);
|
||||
var donate = (Donate) redisTemplate.opsForValue().get("pre-order:" + donate_id);
|
||||
if (donate == null) return false;
|
||||
donate.setTradeNo(tradeNo);
|
||||
donateMapper.insert(donate);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取某用户的捐赠列表或全部捐赠列表
|
||||
*
|
||||
* @param userId 用户id,如果为null则查询所有
|
||||
* @return 捐赠列表
|
||||
*/
|
||||
public PageInfo<Donate> getDonateList(Integer userId, Integer page, Integer size) {
|
||||
if (size == null || size < 0 || size > 100) size = 10;
|
||||
var donateQueryWrapper = new QueryWrapper<Donate>();
|
||||
if (userId != null) {
|
||||
donateQueryWrapper.lambda().eq(Donate::getUserId, userId);
|
||||
}
|
||||
int total = Math.toIntExact(donateMapper.selectCount(donateQueryWrapper));
|
||||
int pages = (total - 1) / size + 1;
|
||||
if(page == null) page = 1;
|
||||
if (page > pages) page = pages;
|
||||
donateQueryWrapper.last("limit " + size * (page - 1) + "," + size);
|
||||
var donates = donateMapper.selectListByWrapper(donateQueryWrapper);
|
||||
return new PageInfo<>(page, size, total, donates);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取捐赠总额
|
||||
*
|
||||
* @return 捐赠总额
|
||||
*/
|
||||
public BigDecimal getTotal() {
|
||||
return donateMapper.selectAmount();
|
||||
}
|
||||
}
|
||||
42
src/main/java/xyz/fortern/service/EmailService.java
Normal file
42
src/main/java/xyz/fortern/service/EmailService.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import org.springframework.mail.SimpleMailMessage;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Service
|
||||
public class EmailService {
|
||||
private final JavaMailSender javaMailSender;
|
||||
|
||||
public EmailService(JavaMailSender javaMailSender) {
|
||||
this.javaMailSender = javaMailSender;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步发送邮件
|
||||
*
|
||||
* @param address 目的地址
|
||||
* @param title 标题
|
||||
* @param text 内容
|
||||
*/
|
||||
@Async
|
||||
public void sendSimpleMail(String address, String title, String text) {
|
||||
// 构建一个邮件对象
|
||||
SimpleMailMessage message = new SimpleMailMessage();
|
||||
// 设置邮件主题
|
||||
message.setSubject(title);
|
||||
// 设置邮件发送者,这个跟application.yml中设置的要一致
|
||||
message.setFrom("落星原服务器<fortern@foxmail.com>");
|
||||
// 设置邮件接收者,可以有多个接收者,中间用逗号隔开,以下类似
|
||||
message.setTo(address);
|
||||
// 设置邮件发送日期
|
||||
message.setSentDate(new Date());
|
||||
// 设置邮件的正文
|
||||
message.setText(text);
|
||||
// 发送邮件
|
||||
javaMailSender.send(message);
|
||||
}
|
||||
}
|
||||
28
src/main/java/xyz/fortern/service/NewsService.java
Normal file
28
src/main/java/xyz/fortern/service/NewsService.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import xyz.fortern.dao.NewsMapper;
|
||||
import xyz.fortern.pojo.News;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
@Service
|
||||
public class NewsService {
|
||||
private final NewsMapper newsMapper;
|
||||
|
||||
public NewsService(NewsMapper newsMapper) {
|
||||
this.newsMapper = newsMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一页的动态,默认一页显示10条
|
||||
*
|
||||
* @param page 页码
|
||||
* @return 一页的动态信息
|
||||
*/
|
||||
public PageInfo<News> getNewsByPage(int page) {
|
||||
int size = 10;
|
||||
int total = Math.toIntExact(newsMapper.selectCount(null));
|
||||
var newsList = newsMapper.getNews(size * (page - 1), size);
|
||||
return new PageInfo<>(page, size, total, newsList);
|
||||
}
|
||||
}
|
||||
61
src/main/java/xyz/fortern/service/ReplyService.java
Normal file
61
src/main/java/xyz/fortern/service/ReplyService.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import xyz.fortern.dao.CommentMapper;
|
||||
import xyz.fortern.dao.ReplyMapper;
|
||||
import xyz.fortern.pojo.Reply;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
@Service
|
||||
public class ReplyService {
|
||||
private final ReplyMapper replyMapper;
|
||||
private final CommentMapper commentMapper;
|
||||
|
||||
public ReplyService(ReplyMapper replyMapper, CommentMapper commentMapper) {
|
||||
this.replyMapper = replyMapper;
|
||||
this.commentMapper = commentMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询某评论下的回复
|
||||
*
|
||||
* @param commentId 评论id
|
||||
* @param page 页码
|
||||
* @param size 页容量,默认为10
|
||||
* @param orderByTime 排序规则,true表示新的在前,false表示旧的在前
|
||||
* @return 回复列表
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public PageInfo<Reply> getByCommentId(int commentId, Integer page, Integer size, boolean orderByTime) {
|
||||
var queryWrapper = new QueryWrapper<Reply>();
|
||||
queryWrapper.eq("reply.cid", commentId);
|
||||
if (orderByTime)
|
||||
queryWrapper.orderByDesc("time");
|
||||
else
|
||||
queryWrapper.orderByAsc("time");
|
||||
int total = Math.toIntExact(replyMapper.selectCount(queryWrapper));
|
||||
int pages = (total - 1) / size + 1;
|
||||
if (page > pages) page = pages;
|
||||
queryWrapper.last("limit " + size * (page - 1) + "," + size);
|
||||
var comments = replyMapper.selectByCid(queryWrapper);
|
||||
return new PageInfo<>(page, size, total, comments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增一条回复
|
||||
*
|
||||
* @param reply 回复详情
|
||||
*/
|
||||
@Transactional
|
||||
public void addNewReply(Reply reply) {
|
||||
//获取评论的最大楼层
|
||||
int floor = commentMapper.getFloor(reply.getCid());
|
||||
reply.setFloor(floor + 1);
|
||||
//插入回复信息
|
||||
replyMapper.insert(reply);
|
||||
//评论的最大楼层+1
|
||||
commentMapper.layerIncrease(reply.getCid());
|
||||
}
|
||||
}
|
||||
31
src/main/java/xyz/fortern/service/TagService.java
Normal file
31
src/main/java/xyz/fortern/service/TagService.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import xyz.fortern.dao.TagMapper;
|
||||
import xyz.fortern.pojo.Tag;
|
||||
|
||||
@Service
|
||||
public class TagService {
|
||||
private final TagMapper tagMapper;
|
||||
|
||||
public TagService(TagMapper tagMapper) {
|
||||
this.tagMapper = tagMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据标签名获取标签id,如果标签不存在,则创建该标签
|
||||
*
|
||||
* @param name 标签名
|
||||
* @return 标签id
|
||||
*/
|
||||
public int getIdByName(String name) {
|
||||
var id = tagMapper.selectIdByName(name);
|
||||
//如果该标签存在,则返回该标签的id
|
||||
if(id != null) return id;
|
||||
//如果不存在,则创建该标签
|
||||
var tag = new Tag(null, name);
|
||||
tagMapper.insert(tag);
|
||||
//返回新标签的id
|
||||
return tag.getId();
|
||||
}
|
||||
}
|
||||
95
src/main/java/xyz/fortern/service/UserService.java
Normal file
95
src/main/java/xyz/fortern/service/UserService.java
Normal file
@@ -0,0 +1,95 @@
|
||||
package xyz.fortern.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import xyz.fortern.dao.SecurityMapper;
|
||||
import xyz.fortern.dao.UserMapper;
|
||||
import xyz.fortern.pojo.Security;
|
||||
import xyz.fortern.pojo.User;
|
||||
import xyz.fortern.util.PageInfo;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
private final UserMapper userMapper;
|
||||
private final SecurityMapper securityMapper;
|
||||
|
||||
public UserService(UserMapper userMapper, SecurityMapper securityMapper) {
|
||||
this.userMapper = userMapper;
|
||||
this.securityMapper = securityMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户详情信息
|
||||
*
|
||||
* @param uid 用户id
|
||||
* @return 用户详情
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public User getById(int uid) {
|
||||
return userMapper.selectById(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户安全信息
|
||||
*
|
||||
* @param uid 用户id
|
||||
* @return 用户详情
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Security getSecurityById(int uid) {
|
||||
return securityMapper.selectSecurityInfoById(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户名是否存在
|
||||
*
|
||||
* @param username 要检查的用户名
|
||||
* @return 判断结果
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public boolean existUsername(String username) {
|
||||
return userMapper.existUsername(username) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询用户列表
|
||||
*
|
||||
* @param page 页码
|
||||
* @param size 页容量
|
||||
* @return 一页的用户数据
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public PageInfo<User> getAll(Integer page, Integer size) {
|
||||
int total = Math.toIntExact(userMapper.selectCount(null));
|
||||
if (size == null || size < 5 || size > 100) size = 5;
|
||||
int pages = (total - 1) / size + 1;
|
||||
if (page == null || page > pages) page = pages;
|
||||
var queryWrapper = new QueryWrapper<User>();
|
||||
queryWrapper.last("limit " + size * (page - 1) + "," + size);
|
||||
var users = userMapper.selectList(queryWrapper);
|
||||
return new PageInfo<>(page, size, total, users);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新详细用户和安全信息
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param security 安全信息
|
||||
*/
|
||||
@Transactional()
|
||||
public void updateUserAndSecurityByManager(User user, Security security) {
|
||||
userMapper.updateById(user);
|
||||
securityMapper.updateById(security);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户更新自己的详情
|
||||
*
|
||||
* @param user 用户详情
|
||||
*/
|
||||
public void updateUserByUser(User user) {
|
||||
userMapper.updateById(user);
|
||||
}
|
||||
|
||||
}
|
||||
75
src/main/java/xyz/fortern/util/ForternUtil.java
Normal file
75
src/main/java/xyz/fortern/util/ForternUtil.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package xyz.fortern.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public class ForternUtil {
|
||||
private static final Random random = new Random();
|
||||
private static final String chars = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
public static void removeSame(Set<Integer> a, Set<Integer> b) {
|
||||
Set<Integer> set = new HashSet<>(a);
|
||||
a.removeAll(b);
|
||||
b.removeAll(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一定长度的随机字符串
|
||||
*
|
||||
* @param len 长度
|
||||
*/
|
||||
public static String randomStr(int len) {
|
||||
var string = new StringBuilder();
|
||||
for (int i = 0; i < len; i++) {
|
||||
string.append(chars.charAt(random.nextInt(36)));
|
||||
}
|
||||
return string.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成6位随机数字
|
||||
*
|
||||
* @return 6位随机数字
|
||||
*/
|
||||
public static String randomIntStr() {
|
||||
return String.format("%06d", random.nextInt(1000000));
|
||||
}
|
||||
|
||||
/**
|
||||
* 二进制无符号字符串转为long
|
||||
*
|
||||
* @param s 表示一个long的64二进制无符号字符串
|
||||
* @return long型数
|
||||
*/
|
||||
public static long parseLong(String s) {
|
||||
char first = s.charAt(0);
|
||||
String z = s.substring(1);
|
||||
if (first == '1') {
|
||||
long j = Long.parseLong(z, 2);//一定是正数
|
||||
if (j == 0) return Long.MIN_VALUE;
|
||||
long i = Long.MAX_VALUE - j + 1;
|
||||
return -i;
|
||||
} else if (first == '0') {
|
||||
return Long.parseLong(z, 2);
|
||||
} else {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个long转为一个64位二进制数字符串
|
||||
*
|
||||
* @param l 需要转换的long型数
|
||||
* @return 转换后的二进制数字符串
|
||||
*/
|
||||
public static String longToBinaryString(long l) {
|
||||
String s = Long.toBinaryString(l);
|
||||
int len = s.length();
|
||||
if (len == 64) return s;
|
||||
char[] chars = new char[64 - len];
|
||||
Arrays.fill(chars, '0');
|
||||
return String.valueOf(chars) + s;
|
||||
}
|
||||
}
|
||||
41
src/main/java/xyz/fortern/util/PageInfo.java
Normal file
41
src/main/java/xyz/fortern/util/PageInfo.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package xyz.fortern.util;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public class PageInfo<T> {
|
||||
|
||||
private int pageIndex = 1; //当前页码
|
||||
private int pageSize = 5; //页面大小
|
||||
private int totalCount; //总条数
|
||||
private List<T> records; //每页的数据集合
|
||||
|
||||
public PageInfo() {
|
||||
}
|
||||
|
||||
public PageInfo(Integer pageIndex, Integer pageSize) {
|
||||
if(pageIndex != null && pageIndex > 0) this.pageIndex = pageIndex;
|
||||
if(pageSize != null && pageSize > 0 && pageSize < 100) this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
public PageInfo(int pageIndex, int pageSize, int totalCount, List<T> records) {
|
||||
this.pageIndex = pageIndex;
|
||||
this.pageSize = pageSize;
|
||||
this.totalCount = totalCount;
|
||||
this.records = records;
|
||||
}
|
||||
|
||||
public void setPageIndex(int pageIndex) {
|
||||
this.pageIndex = pageIndex;
|
||||
}
|
||||
|
||||
public void setTotalCount(int totalCount) {
|
||||
this.totalCount = totalCount;
|
||||
}
|
||||
|
||||
public void setRecords(List<T> records) {
|
||||
this.records = records;
|
||||
}
|
||||
}
|
||||
24
src/main/java/xyz/fortern/util/PayResult.java
Normal file
24
src/main/java/xyz/fortern/util/PayResult.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package xyz.fortern.util;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayResult {
|
||||
/**
|
||||
* 商户订单号
|
||||
*/
|
||||
private String out_trade_no;
|
||||
/**
|
||||
* 支付宝交易号
|
||||
*/
|
||||
private String trade_no;
|
||||
/**
|
||||
* 付款金额
|
||||
*/
|
||||
private String total_amount;
|
||||
|
||||
}
|
||||
46
src/main/resources/application.yml
Normal file
46
src/main/resources/application.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
server:
|
||||
port: 80
|
||||
servlet:
|
||||
encoding:
|
||||
charset: UTF-8
|
||||
force: true
|
||||
enabled: true
|
||||
session:
|
||||
timeout: 1440m
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
druid:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost/light-bbs?serverTimezone=GMT%2B8&characterEncoding=utf-8
|
||||
username: root
|
||||
password: MySQL20868354
|
||||
redis:
|
||||
password: Redis20868354
|
||||
mail:
|
||||
host: smtp.qq.com
|
||||
username: fortern@foxmail.com
|
||||
password: tknouaznezhebeie
|
||||
port: 587
|
||||
default-encoding: UTF-8
|
||||
properties:
|
||||
mail:
|
||||
smtp:
|
||||
# 配置SSL 加密工厂
|
||||
socketFactoryClass: javax.net.ssl.SSLSocketFactory
|
||||
debug: true
|
||||
|
||||
logging:
|
||||
level:
|
||||
xyz.fortern.dao : debug
|
||||
|
||||
ali:
|
||||
pay:
|
||||
app-id: 2021000***
|
||||
merchant-private-key: MIIEvQIBADANBg***
|
||||
alipay-public-key: MIIBIjANBgkqhki***
|
||||
notify-url: http://localhost/pay/notify_url
|
||||
return-url: http://localhost/pay/alipay_return
|
||||
sign-type: RSA2
|
||||
charset: UTF-8
|
||||
gateway-url: https://openapi.alipaydev.com/gateway.do
|
||||
309
src/main/resources/light-bbs.sql
Normal file
309
src/main/resources/light-bbs.sql
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : 洛杉矶
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 80027
|
||||
Source Host : 173.82.110.253:3306
|
||||
Source Schema : light-bbs
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 80027
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 22/08/2022 13:51:54
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for article
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `article`;
|
||||
CREATE TABLE `article` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`title` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文章标题',
|
||||
`uid` int NOT NULL COMMENT '用户ID',
|
||||
`category_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '分类ID,可以没有分类',
|
||||
`floor` int NOT NULL COMMENT '最大楼层',
|
||||
`last_edit_time` datetime NOT NULL COMMENT '最后编辑时间',
|
||||
`summary` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '摘要',
|
||||
`content` varchar(15000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文章本体内容',
|
||||
`visible` bit(1) NOT NULL DEFAULT b'1' COMMENT '0.仅本人与管理员可见,1.任何人可见',
|
||||
`reviewed` bit(1) NOT NULL DEFAULT b'0' COMMENT '0.未审核,1.已审核,默认为0',
|
||||
`top` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否置顶,默认0',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `fk_uid`(`uid`) USING BTREE,
|
||||
INDEX `category_id`(`category_id`) USING BTREE,
|
||||
CONSTRAINT `article_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
|
||||
CONSTRAINT `fk_uid` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '文章的基本信息,不包含正文内容。正文在另一张表。' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of article
|
||||
-- ----------------------------
|
||||
INSERT INTO `article` VALUES (1, '好用模组分享', 10000, '4.1', 3, '2022-05-10 15:00:53', '好用的模组分享,都是大佬常用的', '好用的模组分享,都是大佬常用的,包括地图、投影、工具箱等一系列模组', b'1', b'1', b'0');
|
||||
INSERT INTO `article` VALUES (2, '落星原玩家守则', 10003, '2', 14, '2022-05-11 15:03:46', '任何加入服务器的玩家都必须遵守此规则', '1.关于财产的内容\r\n\r\n1.1无偿赞助说明: 我们接受玩家的无偿赞助,纯属自愿,金额随意,赞助后请勿索要OP,申请退款等,如果有以上行为,我们将会回还其赞助金额后将其踢出并且取消白名资格\r\n\r\n我们不会以任何方式向任何一个玩家强制征收RMB,不承担玩家任何经济损失的任何责任', b'1', b'1', b'1');
|
||||
INSERT INTO `article` VALUES (5, '全新猎人追杀模式已上线', 10003, '1.3', 1, '2022-05-11 16:12:35', '全新猎人追杀模式已上线,快来体验吧~', '全新猎人追杀模式已上线,快来体验吧!在这场紧张刺激的对战中,究竟是猎人追杀成功,还是速通者逃出生天,屠龙成功?让我们拭目以待吧!', b'1', b'1', b'0');
|
||||
INSERT INTO `article` VALUES (6, '潜影贝农场介绍', 10000, '1.2.2', 0, '2022-05-11 15:03:46', '咕了几个月的潜影贝农场终于来了', '这次的潜影贝农场是单维度的,效率高达1000/h,快去尽情挥霍吧~', b'1', b'1', b'0');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for category
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `category`;
|
||||
CREATE TABLE `category` (
|
||||
`id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键id',
|
||||
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '名称',
|
||||
`children` int NOT NULL DEFAULT 0 COMMENT '当前分类下的子分类的最大编号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `name`(`name`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of category
|
||||
-- ----------------------------
|
||||
INSERT INTO `category` VALUES ('-1', '总类', 5);
|
||||
INSERT INTO `category` VALUES ('1', '介绍', 3);
|
||||
INSERT INTO `category` VALUES ('1.1', '玩家介绍', 2);
|
||||
INSERT INTO `category` VALUES ('1.1.1', '小镇介绍', 0);
|
||||
INSERT INTO `category` VALUES ('1.1.2', '散人介绍', 0);
|
||||
INSERT INTO `category` VALUES ('1.2', '游戏内容介绍', 3);
|
||||
INSERT INTO `category` VALUES ('1.2.1', '机器', 0);
|
||||
INSERT INTO `category` VALUES ('1.2.2', '刷怪塔', 0);
|
||||
INSERT INTO `category` VALUES ('1.2.3', '建筑', 0);
|
||||
INSERT INTO `category` VALUES ('1.3', '游戏玩法介绍', 0);
|
||||
INSERT INTO `category` VALUES ('2', '规则', 0);
|
||||
INSERT INTO `category` VALUES ('3', '事务', 0);
|
||||
INSERT INTO `category` VALUES ('4', '资源分享', 3);
|
||||
INSERT INTO `category` VALUES ('4.1', '模组资源', 0);
|
||||
INSERT INTO `category` VALUES ('4.2', '光影与材质', 0);
|
||||
INSERT INTO `category` VALUES ('4.3', '工具与软件', 0);
|
||||
INSERT INTO `category` VALUES ('5', '一级分类测试', 3);
|
||||
INSERT INTO `category` VALUES ('5.1', '二级分类测试1', 0);
|
||||
INSERT INTO `category` VALUES ('5.2', '二级分类测试2', 2);
|
||||
INSERT INTO `category` VALUES ('5.2.1', '三级分类测试1', 0);
|
||||
INSERT INTO `category` VALUES ('5.2.2', '三级分类测试2', 0);
|
||||
INSERT INTO `category` VALUES ('5.3', '二级分类测试3', 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for comment
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `comment`;
|
||||
CREATE TABLE `comment` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||
`aid` int NOT NULL COMMENT '文章id',
|
||||
`uid` int NOT NULL COMMENT '用户id',
|
||||
`floor` int NOT NULL COMMENT '当前评论楼层',
|
||||
`content` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '评论的具体内容',
|
||||
`time` datetime NOT NULL COMMENT '评论发表时间',
|
||||
`layer` int NOT NULL DEFAULT 0 COMMENT '最大层数,用于标记回复的楼层',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `aid`(`aid`) USING BTREE,
|
||||
INDEX `uid`(`uid`) USING BTREE,
|
||||
CONSTRAINT `comment_ibfk_1` FOREIGN KEY (`aid`) REFERENCES `article` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
|
||||
CONSTRAINT `comment_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '这是一条评论。“回复”在另一个表。' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of comment
|
||||
-- ----------------------------
|
||||
INSERT INTO `comment` VALUES (1, 1, 10000, 1, '感谢!', '2022-05-08 21:36:00', 2);
|
||||
INSERT INTO `comment` VALUES (2, 1, 10001, 2, '太棒了!', '2022-05-08 21:36:24', 0);
|
||||
INSERT INTO `comment` VALUES (3, 1, 10002, 3, '感谢分享', '2022-05-08 21:36:45', 0);
|
||||
INSERT INTO `comment` VALUES (4, 2, 10000, 1, '测试评论1', '2022-05-10 11:26:45', 0);
|
||||
INSERT INTO `comment` VALUES (5, 2, 10000, 2, '我认为,应该要求玩家使用机器前阅读使用说明,损坏机器要负责维修。', '2022-05-10 11:27:12', 6);
|
||||
INSERT INTO `comment` VALUES (6, 2, 10000, 3, '测试评论3', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (7, 2, 10000, 4, '测试评论4', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (8, 2, 10000, 5, '测试评论5', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (9, 2, 10000, 6, '测试评论6', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (10, 2, 10000, 7, '测试评论7', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (11, 2, 10000, 8, '测试评论8', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (12, 2, 10000, 9, '测试评论9', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (13, 2, 10000, 10, '测试评论10', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (14, 2, 10000, 11, '测试评论11', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (15, 2, 10000, 12, '测试评论12', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (16, 2, 10000, 13, '测试评论13', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (17, 2, 10000, 14, '测试评论14', '2022-05-10 11:27:12', 0);
|
||||
INSERT INTO `comment` VALUES (18, 5, 10000, 1, '呜呜呜,真的太难了!', '2022-05-10 22:03:49', 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for news
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `news`;
|
||||
CREATE TABLE `news` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||
`user_id` int NOT NULL COMMENT '发起者',
|
||||
`action` enum('REGISTER','EDIT_ARTICLE','PUBLISH_ARTICLE','PUBLISH_COMMENT') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '操作类型',
|
||||
`target_id` int NULL DEFAULT NULL COMMENT '目标对象,一般来说是文章',
|
||||
`time` datetime NOT NULL COMMENT '发生时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `user_id`(`user_id`) USING BTREE,
|
||||
CONSTRAINT `news_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '动态(News)表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of news
|
||||
-- ----------------------------
|
||||
INSERT INTO `news` VALUES (1, 10000, 'PUBLISH_ARTICLE', 1, '2022-05-08 18:59:39');
|
||||
INSERT INTO `news` VALUES (2, 10003, 'PUBLISH_ARTICLE', 2, '2022-05-10 10:12:41');
|
||||
INSERT INTO `news` VALUES (3, 10000, 'PUBLISH_COMMENT', 2, '2022-05-10 11:27:12');
|
||||
INSERT INTO `news` VALUES (4, 10000, 'EDIT_ARTICLE', 1, '2022-05-10 14:20:47');
|
||||
INSERT INTO `news` VALUES (5, 10003, 'PUBLISH_ARTICLE', 5, '2022-05-10 20:54:06');
|
||||
INSERT INTO `news` VALUES (6, 10000, 'PUBLISH_COMMENT', 5, '2022-05-10 22:03:49');
|
||||
INSERT INTO `news` VALUES (7, 10000, 'PUBLISH_ARTICLE', 6, '2022-05-11 14:55:16');
|
||||
INSERT INTO `news` VALUES (8, 10003, 'EDIT_ARTICLE', 5, '2022-05-11 15:41:20');
|
||||
INSERT INTO `news` VALUES (9, 10003, 'EDIT_ARTICLE', 5, '2022-05-11 15:43:44');
|
||||
INSERT INTO `news` VALUES (10, 10003, 'EDIT_ARTICLE', 5, '2022-05-11 16:05:31');
|
||||
INSERT INTO `news` VALUES (11, 10003, 'EDIT_ARTICLE', 5, '2022-05-11 16:12:15');
|
||||
INSERT INTO `news` VALUES (12, 10003, 'EDIT_ARTICLE', 5, '2022-05-11 16:12:35');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for reply
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `reply`;
|
||||
CREATE TABLE `reply` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`cid` int NOT NULL COMMENT '所属评论的id',
|
||||
`uid` int NOT NULL COMMENT '发表此回复的用户',
|
||||
`floor` int NOT NULL COMMENT '评论的楼层',
|
||||
`time` datetime NOT NULL COMMENT '回复时间',
|
||||
`rid` int NULL DEFAULT NULL COMMENT '回复的那个回复的id,如果为空表示没有回复任何人,只是回复层主',
|
||||
`content` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '内容',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `cid`(`cid`) USING BTREE,
|
||||
INDEX `uid`(`uid`) USING BTREE,
|
||||
INDEX `rid`(`rid`) USING BTREE,
|
||||
CONSTRAINT `reply_ibfk_1` FOREIGN KEY (`cid`) REFERENCES `comment` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
|
||||
CONSTRAINT `reply_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
|
||||
CONSTRAINT `reply_ibfk_3` FOREIGN KEY (`rid`) REFERENCES `reply` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '所有的回复信息。回复属于评论。' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of reply
|
||||
-- ----------------------------
|
||||
INSERT INTO `reply` VALUES (1, 1, 10003, 1, '2022-05-09 09:41:18', NULL, '挺不错,但我认为还有改进的空间');
|
||||
INSERT INTO `reply` VALUES (2, 1, 10001, 2, '2022-05-09 09:43:01', 1, '那就交给你来做吧~');
|
||||
INSERT INTO `reply` VALUES (3, 5, 10002, 1, '2022-05-10 11:30:17', NULL, '非常赞同,不看使用说明应该打死!');
|
||||
INSERT INTO `reply` VALUES (4, 5, 10006, 2, '2022-05-10 11:31:04', 3, '你也太狠了吧~~');
|
||||
INSERT INTO `reply` VALUES (5, 5, 10002, 3, '2022-05-10 11:31:46', 4, '你不知道我要被那些笨笨的玩家气死了');
|
||||
INSERT INTO `reply` VALUES (7, 5, 10000, 5, '2022-05-10 22:45:58', 4, '最近的新玩家确实水平不高啊');
|
||||
INSERT INTO `reply` VALUES (8, 5, 10001, 6, '2022-05-10 22:50:42', 3, '太赞同了,我已经被那个新人气晕了');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for security
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `security`;
|
||||
CREATE TABLE `security` (
|
||||
`user_id` int NOT NULL COMMENT '用户id',
|
||||
`password` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码SHA1',
|
||||
`salt` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码的salt',
|
||||
`locked` bit(1) NOT NULL COMMENT '0.未锁定,可登录;1.锁定,不可登录',
|
||||
`permissions` bigint NOT NULL COMMENT '权限',
|
||||
PRIMARY KEY (`user_id`) USING BTREE,
|
||||
CONSTRAINT `security_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of security
|
||||
-- ----------------------------
|
||||
INSERT INTO `security` VALUES (10000, '208683', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10001, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10002, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10003, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10004, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10005, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10006, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10007, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10008, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10009, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10010, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
INSERT INTO `security` VALUES (10011, '123456', 'luoxingyuan', b'0', -4611686018427387904);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tag
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `tag`;
|
||||
CREATE TABLE `tag` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||
`name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '标签名称',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `name`(`name`) USING BTREE COMMENT '没个标签的名称都不能相同'
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '标签表。用户发表文章时可以为文章添加标签。' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tag
|
||||
-- ----------------------------
|
||||
INSERT INTO `tag` VALUES (11, '刷怪');
|
||||
INSERT INTO `tag` VALUES (5, '历史');
|
||||
INSERT INTO `tag` VALUES (12, '基建');
|
||||
INSERT INTO `tag` VALUES (2, '建筑');
|
||||
INSERT INTO `tag` VALUES (1, '机器');
|
||||
INSERT INTO `tag` VALUES (7, '特殊模式');
|
||||
INSERT INTO `tag` VALUES (6, '玩法');
|
||||
INSERT INTO `tag` VALUES (4, '红石');
|
||||
INSERT INTO `tag` VALUES (3, '规划');
|
||||
INSERT INTO `tag` VALUES (10, '规则');
|
||||
INSERT INTO `tag` VALUES (9, '趣味玩法');
|
||||
INSERT INTO `tag` VALUES (8, '骨粉');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tag_article_relation
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `tag_article_relation`;
|
||||
CREATE TABLE `tag_article_relation` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`tag_id` int NOT NULL COMMENT '标签id',
|
||||
`article_id` int NOT NULL COMMENT '文章id',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `article_id`(`article_id`) USING BTREE,
|
||||
INDEX `tag_id`(`tag_id`) USING BTREE,
|
||||
CONSTRAINT `tag_article_relation_ibfk_2` FOREIGN KEY (`article_id`) REFERENCES `article` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
|
||||
CONSTRAINT `tag_article_relation_ibfk_3` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '文章与标签的多对多关联关系表' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tag_article_relation
|
||||
-- ----------------------------
|
||||
INSERT INTO `tag_article_relation` VALUES (1, 1, 1);
|
||||
INSERT INTO `tag_article_relation` VALUES (2, 3, 1);
|
||||
INSERT INTO `tag_article_relation` VALUES (3, 4, 1);
|
||||
INSERT INTO `tag_article_relation` VALUES (13, 11, 6);
|
||||
INSERT INTO `tag_article_relation` VALUES (14, 12, 6);
|
||||
INSERT INTO `tag_article_relation` VALUES (15, 6, 5);
|
||||
INSERT INTO `tag_article_relation` VALUES (16, 7, 5);
|
||||
INSERT INTO `tag_article_relation` VALUES (17, 9, 5);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `user`;
|
||||
CREATE TABLE `user` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '电子邮箱',
|
||||
`qq_number` varchar(14) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'QQ号码,每个用户都应当有个QQ号(应该没有QQ号是以0开头的吧)',
|
||||
`registration_time` datetime NOT NULL COMMENT '注册时间',
|
||||
`nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '昵称',
|
||||
`head_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '头像存放的路径',
|
||||
`position` enum('USER','MANAGER') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '身份:0.玩家,1.管理员',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 10011 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户表,存放用户的基本信息,其中密码字段在MyBatisGenerator忽略,因为该字段只有登录的时候才需要被获取。头像profile字段将图片转为二进制存储。' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of user
|
||||
-- ----------------------------
|
||||
INSERT INTO `user` VALUES (10000, 'Fortern', 'fortern@foxmail.com', '1007305659', '2021-12-10 17:38:34', 'Fortern', NULL, 'MANAGER');
|
||||
INSERT INTO `user` VALUES (10001, 'MoooJoo', 'blueten.ki@gmail.com', '2077200122', '2022-05-08 21:33:11', 'MoooJoo', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10002, 'Main_n', 'maxinn.ki@gmail.com', '123456789', '2022-05-08 21:34:46', 'Main_n', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10003, 's_yh', 'violet@s-yh-china.com', '3512215909', '2022-05-09 09:31:32', 's_yh', NULL, 'MANAGER');
|
||||
INSERT INTO `user` VALUES (10004, 'Air', 'air@qq.com', '1068498498', '2022-05-09 18:21:40', 'air', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10005, 'Enders3730', 'endes@xx.com', '631403619', '2022-05-09 18:22:29', '末心', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10006, 'BoaHancuck', '1016261754@qq.com', '1016261754', '2022-05-09 18:24:20', '草莓', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10007, 'TianYu__', '1369112122@qq.com', '1369112122', '2022-05-09 18:25:04', '天宇', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10008, 'mjs2333', '1102690290@qq.com', '1102690290', '2022-05-09 18:26:01', 'mjs2333', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10009, 'KoisatoL', 'misaka_misaka@126.com', '2933077161', '2022-05-09 18:27:08', '恋恋', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10010, 'G_Xinnn', '3075105361@qq.com', '3075105361', '2022-05-09 18:27:43', '雨落', NULL, 'USER');
|
||||
INSERT INTO `user` VALUES (10011, 'wokao_whytsu', 'whytsu@qq.com', '942273897', '2022-05-10 00:16:27', '薇触', NULL, 'USER');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
5
src/main/resources/mapper/ArticleMapper.xml
Normal file
5
src/main/resources/mapper/ArticleMapper.xml
Normal 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="xyz.fortern.dao.ArticleMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/CategoryMapper.xml
Normal file
5
src/main/resources/mapper/CategoryMapper.xml
Normal 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="xyz.fortern.dao.CategoryMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/CommentMapper.xml
Normal file
5
src/main/resources/mapper/CommentMapper.xml
Normal 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="xyz.fortern.dao.CommentMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/DonateMapper.xml
Normal file
5
src/main/resources/mapper/DonateMapper.xml
Normal 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="xyz.fortern.dao.DonateMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/NewsMapper.xml
Normal file
5
src/main/resources/mapper/NewsMapper.xml
Normal 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="xyz.fortern.dao.NewsMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/ReplyMapper.xml
Normal file
5
src/main/resources/mapper/ReplyMapper.xml
Normal 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="xyz.fortern.dao.ReplyMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/SecurityMapper.xml
Normal file
5
src/main/resources/mapper/SecurityMapper.xml
Normal 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="xyz.fortern.dao.SecurityMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/TagMapper.xml
Normal file
5
src/main/resources/mapper/TagMapper.xml
Normal 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="xyz.fortern.dao.TagMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/UserMapper.xml
Normal file
5
src/main/resources/mapper/UserMapper.xml
Normal 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="xyz.fortern.dao.UserMapper">
|
||||
|
||||
</mapper>
|
||||
198
src/main/resources/static/article_detail.html
Normal file
198
src/main/resources/static/article_detail.html
Normal file
@@ -0,0 +1,198 @@
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>文章详情</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<script type="text/javascript" src="decimal/decimal.js"></script>
|
||||
<script type="text/javascript" src="moment/moment.js"></script>
|
||||
<script type="text/javascript" src="js/fortern.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
<link href="css/comment.css" rel="stylesheet"/>
|
||||
</head>
|
||||
|
||||
<body class="vsc-initialized">
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="blog-header">
|
||||
<h1 id="title" class="blog-title"></h1></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-8 blog-main">
|
||||
|
||||
<div class="blog-post">
|
||||
<p class="blog-post-meta">
|
||||
<span id="last_edit_time"></span> by
|
||||
<a href="#" data-jzz-gui-player="true" id="username"></a>
|
||||
</p>
|
||||
<p class="blog-post-meta">
|
||||
分类:<span id="category"></span>
|
||||
</p>
|
||||
<p class="lead blog-description" id="summary"></p>
|
||||
|
||||
<hr>
|
||||
<p id="content"></p>
|
||||
</div><!-- /.blog-post -->
|
||||
|
||||
</div><!-- /.blog-main -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="comment-send">
|
||||
<form id="commentForm">
|
||||
<span class="comment-avatar">
|
||||
<img id="user_head" src="" alt="avatar">
|
||||
</span>
|
||||
<label>
|
||||
<textarea id="comment_content" class="comment-send-input" name="comment" form="commentForm" cols="80" rows="5"
|
||||
placeholder="请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。"></textarea>
|
||||
</label>
|
||||
<input id="publish" class="comment-send-button" type="button" value="发表评论">
|
||||
</form>
|
||||
</div>
|
||||
<div class="comment-list" id="commentList">
|
||||
<!-- 评论列表 -->
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<!-- 分页信息 -->
|
||||
<div id="page_info_area" class="col-md-4">
|
||||
|
||||
</div>
|
||||
<div id="page_nav" class="col-md-6">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
</body>
|
||||
<script>
|
||||
let aid = getUrlParam("aid");
|
||||
let user;
|
||||
$(function () {
|
||||
$.ajax("/article/" + aid, {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
build_article(result);
|
||||
}
|
||||
});
|
||||
$.ajax("/user/getMe", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
user = result.user;
|
||||
$("#user_head").attr("src", user.headPath === "" ? "/img/默认头像.jpg" : user.headPath);
|
||||
}
|
||||
});
|
||||
to_c_page(1);
|
||||
})
|
||||
|
||||
function to_c_page(page) {
|
||||
$.ajax("/comment/a", {
|
||||
data: "aid=" + aid + "&page=" + page + "&size=5",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
//1、显示评论信息
|
||||
build_comment(result.records);
|
||||
let page_info = build_page_info(result.pageIndex, result.pageSize, result.totalCount);
|
||||
//2、解析并显示分页信息
|
||||
$("#page_info_area").empty().append("当前" + page_info.page + "页,共" + page_info.pages + "页,共" + page_info.total + "条记录");
|
||||
//3、解析显示分页条数据
|
||||
build_page_nav(page_info, $("#page_nav"));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//构建文章内容
|
||||
function build_article(result) {
|
||||
$("#title").text(result.title);
|
||||
$("#summary").text(result.summary);
|
||||
let content = result.content;
|
||||
content = content.replaceAll('\n', '<br>');
|
||||
$("#content").html(content);
|
||||
$("#category").text(result.category.name);
|
||||
$("#username").text(result.simpleUser.username);
|
||||
$("#last_edit_time").text(moment(new Date(result.lastEditTime)).format(time_format));
|
||||
}
|
||||
|
||||
//给分页条上的li绑定点击事件
|
||||
$(document).on("click", "#page_nav li:not('.disabled,.active')", function () {
|
||||
to_c_page($(this).val());
|
||||
});
|
||||
|
||||
//构建评论表
|
||||
function build_comment(comments) {
|
||||
$("#commentList").empty();
|
||||
$.each(comments, function (index, comment) {
|
||||
let head = $("<span class='comment-avatar'><img src='" + (comment.simpleUser.headPath === "" ? "/img/默认头像.jpg" : "comment.simpleUser.headPath") + "' alt='avatar'></span>");
|
||||
let p1 = $("<p class='comment-content-name'>" + comment.simpleUser.username + "</p>")
|
||||
let p2 = $("<p class='comment-content-article'>" + comment.content + "</p>")
|
||||
let p3 = $("<p class='comment-content-footer'><span class='comment-content-footer-id'>#" + comment.floor + "</span><span class='comment-content-footer-timestamp'>" + moment(new Date(comment.time)).format(time_format) + "</span></p>");
|
||||
//let replies = build_reply(1, comment.id);
|
||||
let div_content = $("<div class='comment-content'></div>");
|
||||
div_content.append(p1).append(p2).append(p3);
|
||||
// if (replies != null) {
|
||||
// div_content.append(replies);
|
||||
// }
|
||||
let div_cls = $("<div class='cls'></div>");
|
||||
let comment_div = $("<div class='comment " + (comments.length - 1 === index ? "comment-bottom" : "") + "'></div>");
|
||||
comment_div.append(head).append(div_content).append(div_cls);
|
||||
comment_div.appendTo("#commentList");
|
||||
})
|
||||
}
|
||||
|
||||
$("#publish").on("click", function () {
|
||||
$.ajax("/comment/new/" + aid, {
|
||||
data: "content=" + $("#comment_content").val(),
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
toastr.success("操作成功");
|
||||
setTimeout(function () {
|
||||
$(window).attr('location','/article_detail.html?aid=' + aid);
|
||||
}, 1500);
|
||||
},
|
||||
statusCode: {
|
||||
403: function (XMLHttpRequest) {
|
||||
toastr.warning("没有权限,可能已被禁言");
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
//
|
||||
// function build_replys(page, id) {
|
||||
// let replies;
|
||||
// let flag = false;
|
||||
// $.ajax("/reply/comment/" + id + "?page=" + page, {
|
||||
// type: "GET",
|
||||
// dataType: "json",
|
||||
// success: function (result) {
|
||||
// if (result.records.length !== 0){
|
||||
// let list_div = $("<div class='reply-list'></div>");
|
||||
// for (const reply of result.records) {
|
||||
// let reply_item = $("<div class='reply'></div>");
|
||||
// let p1 = $("<p class='comment-content-name'><a>" + reply.simpleUserFrom.username + "</a> " + (reply.simpleUserTo === undefined ? "" : "回复<a>" + reply.simpleUserTo.username + "</a>") + "</p>");
|
||||
// let p2 = $("<p class='comment-content-article'>" + reply.content + "</p>");
|
||||
// let p3 = $("<p class='comment-content-footer'><span class='comment-content-footer-id'>#" + reply.floor + "</span><span class='comment-content-footer-timestamp'>" + moment(new Date(reply.time)).format(time_format) + "</span></p>");
|
||||
// reply_item.append(p1).append(p2).append(p3).appendTo(list_div);
|
||||
// }
|
||||
// debugger
|
||||
// replies = list_div;
|
||||
// }
|
||||
// flag = true;
|
||||
// }
|
||||
// })
|
||||
// while (!flag) {
|
||||
// }
|
||||
// return replies;
|
||||
// }
|
||||
</script>
|
||||
</html>
|
||||
359
src/main/resources/static/article_list.html
Normal file
359
src/main/resources/static/article_list.html
Normal file
@@ -0,0 +1,359 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<title>文章列表</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<script type="text/javascript" src="decimal/decimal.js"></script>
|
||||
<script type="text/javascript" src="moment/moment.js"></script>
|
||||
<script type="text/javascript" src="js/fortern.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default">
|
||||
<!-- 导航条 -->
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<!-- 导航条左边头部 -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
|
||||
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<!-- 登录页 -->
|
||||
<a class="navbar-brand" href="index.html">落星原</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<!-- 导航条中间部分 -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<!-- 左侧导航连接 -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="edit_article.html">添加新文章 <span class="sr-only">(current)</span></a></li>
|
||||
<li><a href="user_list.html">用户管理</a></li>
|
||||
<li><a href="article_list.html">文章管理</a></li>
|
||||
<li><a href="comment_list.html">评论管理</a></li>
|
||||
<li><a href="category_list.html">分类管理</a></li>
|
||||
<li><a href="donate_list.html">捐赠管理</a></li>
|
||||
</ul>
|
||||
<!-- 搜索框 -->
|
||||
<form class="navbar-form navbar-left">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input id="search_key" type="text" class="form-control" placeholder="Search">
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default" onclick="to_search()" id="search_btn">搜索</button>
|
||||
</form>
|
||||
<!-- 右侧导航连接 -->
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">操作 <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<!-- 个人中心 -->
|
||||
<li><a href="user.html">个人中心</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="show_donate()">捐赠</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="logout()">注销</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
<!-- 搭建显示页面 -->
|
||||
<div class="container">
|
||||
<!-- 标题 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>文章列表</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 按钮 -->
|
||||
<div class="row">
|
||||
<!-- 此列向右偏移 -->
|
||||
<!-- 宽度4,左间距8 -->
|
||||
<div class="col-md-4 col-md-offset-8">
|
||||
</div>
|
||||
</div>
|
||||
<!-- 查询条件表单 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label for="category_id" class="col-sm-2 control-label">分类</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="category_id" class="form-control">
|
||||
<option value="">全部</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit_time_begin" class="col-sm-2 control-label">起始时间</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="datetime-local" class="form-control" id="edit_time_begin">
|
||||
<button class="btn btn-default" type="button" onclick="$('#edit_time_begin').val('')">重置此时间
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit_time_end" class="col-sm-2 control-label">结束时间</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="datetime-local" class="form-control" id="edit_time_end">
|
||||
<button class="btn btn-default" type="button" onclick="$('#edit_time_end').val('')">重置此时间
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="visible_div">
|
||||
<label class="col-sm-2 control-label">是否可见</label>
|
||||
<div class="col-sm-10">
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="visible" id="visible_all" value="" checked> 全部
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="visible" id="visible_true" value="true"> 是
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="visible" id="visible_false" value="false"> 否
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button type="button" class="btn btn-default" onclick="toArticlePage(1)">查询</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示表格数据库 -->
|
||||
<div class="row">
|
||||
<!-- 表格占12列 -->
|
||||
<div class="col-md-12">
|
||||
<table id="article_table" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<label><input id="check_all" type="checkbox"/></label>
|
||||
</th>
|
||||
<th>标题</th>
|
||||
<th>作者</th>
|
||||
<th>分类</th>
|
||||
<th>评论数</th>
|
||||
<th>最后编辑时间</th>
|
||||
<th>是否可见</th>
|
||||
<th>是否已审核</th>
|
||||
<th>是否置顶</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示分页信息 -->
|
||||
<div class="row">
|
||||
<!-- 分页信息 -->
|
||||
<div id="page_info_area" class="col-md-6">
|
||||
|
||||
</div>
|
||||
<div id="page_nav" class="col-md-6">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
let security;
|
||||
//1、页面加载完成以后,直接发送ajax请求,要到分页数据
|
||||
$(function () {
|
||||
$.ajax("/user/getMe", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (result) {
|
||||
security = result.security;
|
||||
if (security.position === "MANAGER") {
|
||||
let div1 = $("<div class='form-group' id='visible_div'></div>");
|
||||
let label1 = $("<label class='col-sm-2 control-label'>审核通过</label>")
|
||||
let radio1 = $("<div class='col-sm-10'>" +
|
||||
"<label class='radio-inline'><input type='radio' name='reviewed' id='reviewed_all' value='' checked> 全部</label>" +
|
||||
"<label class='radio-inline'><input type='radio' name='reviewed' id='reviewed_true' value='true'> 是</label>" +
|
||||
"<label class='radio-inline'><input type='radio' name='reviewed' id='reviewed_false' value='false'> 否</label>" +
|
||||
"</div>");
|
||||
div1.append(label1).append(radio1).insertAfter("#visible_div");
|
||||
let div2 = $("<div class='form-group' id='top_div'></div>");
|
||||
let label2 = $("<label class='col-sm-2 control-label'>是否置顶</label>")
|
||||
let radio2 = $("<div class='col-sm-10'>" +
|
||||
"<label class='radio-inline'><input type='radio' name='top' id='top_all' value='' checked> 全部</label>" +
|
||||
"<label class='radio-inline'><input type='radio' name='top' id='top_true' value='true'> 是</label>" +
|
||||
"<label class='radio-inline'><input type='radio' name='top' id='top_false' value='false'> 否</label>" +
|
||||
"</div>");
|
||||
div2.append(label2).append(radio2).insertAfter("#visible_div");
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
$(window).attr('location', '/index.html');
|
||||
}
|
||||
});
|
||||
//加载分类列表
|
||||
$.ajax("/category/all", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
for (const category of result) {
|
||||
let num = searchStrEach(category.id, "_");
|
||||
let str = "";
|
||||
for (let i = 1; i < num; i++) {
|
||||
str += " ";
|
||||
}
|
||||
str += category.name;
|
||||
$("<option value='" + category.id + "'>" + str + "</option>").appendTo("#category_id");
|
||||
}
|
||||
}
|
||||
})
|
||||
toArticlePage(1);
|
||||
});
|
||||
|
||||
//跳转到第pn页
|
||||
function toArticlePage(pn) {
|
||||
let _data = "page=" + pn + "&size=5";
|
||||
if ($('#category_id').find('option:selected').val() !== "")
|
||||
_data += ("&category_id=" + $('#category_id').find('option:selected').val());
|
||||
if ($("#edit_time_begin").val() !== "")
|
||||
_data += ("&edit_time_begin=" + $("#edit_time_begin").val());
|
||||
if ($("#edit_time_end").val() !== "")
|
||||
_data += ("&edit_time_end=" + $("#edit_time_end").val());
|
||||
if ($("input[name='visible']:checked").val() !== "")
|
||||
_data += ("&visible=" + $("input[name='visible']:checked").val());
|
||||
if ($("input[name='top']:checked").val() !== "")
|
||||
_data += ("&top=" + $("input[name='top']:checked").val());
|
||||
if ($("input[name='reviewed']:checked").val() !== "")
|
||||
_data += ("&reviewed=" + $("input[name='reviewed']:checked").val());
|
||||
$.ajax({
|
||||
url: "/article/all",
|
||||
data: _data,
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
//1、解析并显示文章数据
|
||||
build_article_table(result);
|
||||
let page_info = build_page_info(result.pageIndex, result.pageSize, result.totalCount);
|
||||
//2、解析并显示分页信息
|
||||
$("#page_info_area").empty().append("当前" + page_info.page + "页,共" + page_info.pages + "页,共" + page_info.total + "条记录");
|
||||
//3、解析显示分页条数据
|
||||
build_page_nav(page_info);
|
||||
},
|
||||
fail: function () {
|
||||
toastr.fail("加载数据失败");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//构建文章列表
|
||||
function build_article_table(result) {
|
||||
//先清空原有数据
|
||||
$("#article_table tbody").empty();
|
||||
$("#check_all").prop("checked", false);
|
||||
let articles = result.records;
|
||||
$.each(articles, function (index, item) {
|
||||
let checkBoxTd = $("<td></td>").append("<input type='checkbox' class='check_item'/>");
|
||||
let titleTd = $("<td><a href='article_detail.html?aid=" + item.id + "'>" + item.title + "</a></td>");
|
||||
let usernameTd = $("<td></td>").append(item.simpleUser.username);
|
||||
let categoryTd = $("<td></td>").append(item.category.name);
|
||||
let numTd = $("<td></td>").append(item.numOfComments);
|
||||
let timeTd = $("<td></td>").append(moment(new Date(item.lastEditTime)).format(time_format));
|
||||
let visibleTd = $("<td></td>").append("<span class='glyphicon " + (item.visible ? "glyphicon-ok" : "glyphicon-remove") + "' aria-hidden='true'></span>");
|
||||
let reviewedTd = $("<td></td>").append("<span class='glyphicon " + (item.reviewed ? "glyphicon-ok" : "glyphicon-remove") + "' aria-hidden='true'></span>");
|
||||
let topTd = $("<td></td>").append("<span class='glyphicon " + (item.top ? "glyphicon-ok" : "glyphicon-remove") + "' aria-hidden='true'></span>");
|
||||
let editBtn = $("<button data-id='" + item.id + "' class='btn btn-primary btn-sm edit_btn'></button>").append($("<span class='glyphicon glyphicon-pencil'></span>")).append("编辑");
|
||||
let btnTd = $("<td></td>").append(editBtn);
|
||||
$("<tr></tr>").attr("data-id", item.id).append(checkBoxTd).append(titleTd).append(usernameTd).append(categoryTd).append(numTd).append(timeTd).append(visibleTd).append(reviewedTd).append(topTd).append(btnTd).appendTo("#article_table tbody");
|
||||
});
|
||||
}
|
||||
|
||||
//构建分页条
|
||||
function build_page_nav(page_info) {
|
||||
$("#page_nav").empty();
|
||||
let ul = $("<ul></ul>").addClass("pagination");
|
||||
let firstPageLi = $("<li></li>").append($("<a></a>").append("首页"));
|
||||
let prePageLi = $("<li></li>").append($("<a></a>").append("«"));
|
||||
if (!page_info.hasPreviousPage) {
|
||||
firstPageLi.addClass("disabled");
|
||||
prePageLi.addClass("disabled");
|
||||
} else {
|
||||
firstPageLi.click(function () {
|
||||
toArticlePage(1);
|
||||
});
|
||||
prePageLi.click(function () {
|
||||
toArticlePage(page - 1);
|
||||
});
|
||||
}
|
||||
let lastPageLi = $("<li></li>").append($("<a></a>").append("末页"));
|
||||
let nextPageLi = $("<li></li>").append($("<a></a>").append("»"));
|
||||
if (page_info.hasNextPage === false) {
|
||||
lastPageLi.addClass("disabled");
|
||||
nextPageLi.addClass("disabled");
|
||||
} else {
|
||||
nextPageLi.click(function () {
|
||||
toArticlePage(page + 1);
|
||||
});
|
||||
lastPageLi.click(function () {
|
||||
toArticlePage(pages);
|
||||
});
|
||||
}
|
||||
ul.append(firstPageLi).append(prePageLi);
|
||||
$.each(page_info.beforePages, function (index, item) {
|
||||
let numLi = $("<li value='" + item + "'></li>").append($("<a></a>").append(item));
|
||||
numLi.appendTo(ul);
|
||||
numLi.click(function () {
|
||||
toArticlePage(item);
|
||||
})
|
||||
});
|
||||
ul.append("<li class='active'><a>" + page_info.page + "</a></li>");
|
||||
$.each(page_info.afterPages, function (index, item) {
|
||||
let numLi = $("<li value='" + item + "'></li>").append($("<a></a>").append(item));
|
||||
numLi.appendTo(ul);
|
||||
numLi.click(function () {
|
||||
toArticlePage(item);
|
||||
})
|
||||
});
|
||||
ul.append(nextPageLi).append(lastPageLi);
|
||||
let navEle = $("<nav></nav>").append(ul);
|
||||
navEle.appendTo("#page_nav");
|
||||
}
|
||||
|
||||
//给后来出现的“编辑”按钮添加绑定事件
|
||||
$(document).on("click", ".edit_btn", function () {
|
||||
let id = $(this).attr("data-id");
|
||||
$(window).attr('location', '/edit_article.html?aid=' + id);
|
||||
})
|
||||
|
||||
//给后来出现的“删除”按钮添加绑定事件
|
||||
$(document).on("click", ".del_btn", function () {
|
||||
|
||||
})
|
||||
|
||||
//给后来出现的“复选框”添加绑定事件
|
||||
$(document).on("click", ".check_item", function () {
|
||||
//判断全选框里是不是要有钩
|
||||
let flag = $(".check_item:checked").length === $(".check_item").length;
|
||||
$("#check_all").prop("checked", flag);
|
||||
})
|
||||
//全选
|
||||
$("#check_all").click(function () {
|
||||
//prop修改和获取原声属性的值
|
||||
//将所有复选框的checked属性设为和被点击的那个相同
|
||||
$(".check_item").prop("checked", $(this).prop("checked"));
|
||||
})
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
587
src/main/resources/static/bootstrap-3.3.7-dist/css/bootstrap-theme.css
vendored
Normal file
587
src/main/resources/static/bootstrap-3.3.7-dist/css/bootstrap-theme.css
vendored
Normal file
@@ -0,0 +1,587 @@
|
||||
/*!
|
||||
* Bootstrap v3.4.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
.btn-default,
|
||||
.btn-primary,
|
||||
.btn-success,
|
||||
.btn-info,
|
||||
.btn-warning,
|
||||
.btn-danger {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.btn-default:active,
|
||||
.btn-primary:active,
|
||||
.btn-success:active,
|
||||
.btn-info:active,
|
||||
.btn-warning:active,
|
||||
.btn-danger:active,
|
||||
.btn-default.active,
|
||||
.btn-primary.active,
|
||||
.btn-success.active,
|
||||
.btn-info.active,
|
||||
.btn-warning.active,
|
||||
.btn-danger.active {
|
||||
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
.btn-default.disabled,
|
||||
.btn-primary.disabled,
|
||||
.btn-success.disabled,
|
||||
.btn-info.disabled,
|
||||
.btn-warning.disabled,
|
||||
.btn-danger.disabled,
|
||||
.btn-default[disabled],
|
||||
.btn-primary[disabled],
|
||||
.btn-success[disabled],
|
||||
.btn-info[disabled],
|
||||
.btn-warning[disabled],
|
||||
.btn-danger[disabled],
|
||||
fieldset[disabled] .btn-default,
|
||||
fieldset[disabled] .btn-primary,
|
||||
fieldset[disabled] .btn-success,
|
||||
fieldset[disabled] .btn-info,
|
||||
fieldset[disabled] .btn-warning,
|
||||
fieldset[disabled] .btn-danger {
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.btn-default .badge,
|
||||
.btn-primary .badge,
|
||||
.btn-success .badge,
|
||||
.btn-info .badge,
|
||||
.btn-warning .badge,
|
||||
.btn-danger .badge {
|
||||
text-shadow: none;
|
||||
}
|
||||
.btn:active,
|
||||
.btn.active {
|
||||
background-image: none;
|
||||
}
|
||||
.btn-default {
|
||||
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
|
||||
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dbdbdb;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
border-color: #ccc;
|
||||
}
|
||||
.btn-default:hover,
|
||||
.btn-default:focus {
|
||||
background-color: #e0e0e0;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-default:active,
|
||||
.btn-default.active {
|
||||
background-color: #e0e0e0;
|
||||
border-color: #dbdbdb;
|
||||
}
|
||||
.btn-default.disabled,
|
||||
.btn-default[disabled],
|
||||
fieldset[disabled] .btn-default,
|
||||
.btn-default.disabled:hover,
|
||||
.btn-default[disabled]:hover,
|
||||
fieldset[disabled] .btn-default:hover,
|
||||
.btn-default.disabled:focus,
|
||||
.btn-default[disabled]:focus,
|
||||
fieldset[disabled] .btn-default:focus,
|
||||
.btn-default.disabled.focus,
|
||||
.btn-default[disabled].focus,
|
||||
fieldset[disabled] .btn-default.focus,
|
||||
.btn-default.disabled:active,
|
||||
.btn-default[disabled]:active,
|
||||
fieldset[disabled] .btn-default:active,
|
||||
.btn-default.disabled.active,
|
||||
.btn-default[disabled].active,
|
||||
fieldset[disabled] .btn-default.active {
|
||||
background-color: #e0e0e0;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-primary {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #245580;
|
||||
}
|
||||
.btn-primary:hover,
|
||||
.btn-primary:focus {
|
||||
background-color: #265a88;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-primary:active,
|
||||
.btn-primary.active {
|
||||
background-color: #265a88;
|
||||
border-color: #245580;
|
||||
}
|
||||
.btn-primary.disabled,
|
||||
.btn-primary[disabled],
|
||||
fieldset[disabled] .btn-primary,
|
||||
.btn-primary.disabled:hover,
|
||||
.btn-primary[disabled]:hover,
|
||||
fieldset[disabled] .btn-primary:hover,
|
||||
.btn-primary.disabled:focus,
|
||||
.btn-primary[disabled]:focus,
|
||||
fieldset[disabled] .btn-primary:focus,
|
||||
.btn-primary.disabled.focus,
|
||||
.btn-primary[disabled].focus,
|
||||
fieldset[disabled] .btn-primary.focus,
|
||||
.btn-primary.disabled:active,
|
||||
.btn-primary[disabled]:active,
|
||||
fieldset[disabled] .btn-primary:active,
|
||||
.btn-primary.disabled.active,
|
||||
.btn-primary[disabled].active,
|
||||
fieldset[disabled] .btn-primary.active {
|
||||
background-color: #265a88;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
.btn-success:hover,
|
||||
.btn-success:focus {
|
||||
background-color: #419641;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-success:active,
|
||||
.btn-success.active {
|
||||
background-color: #419641;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
.btn-success.disabled,
|
||||
.btn-success[disabled],
|
||||
fieldset[disabled] .btn-success,
|
||||
.btn-success.disabled:hover,
|
||||
.btn-success[disabled]:hover,
|
||||
fieldset[disabled] .btn-success:hover,
|
||||
.btn-success.disabled:focus,
|
||||
.btn-success[disabled]:focus,
|
||||
fieldset[disabled] .btn-success:focus,
|
||||
.btn-success.disabled.focus,
|
||||
.btn-success[disabled].focus,
|
||||
fieldset[disabled] .btn-success.focus,
|
||||
.btn-success.disabled:active,
|
||||
.btn-success[disabled]:active,
|
||||
fieldset[disabled] .btn-success:active,
|
||||
.btn-success.disabled.active,
|
||||
.btn-success[disabled].active,
|
||||
fieldset[disabled] .btn-success.active {
|
||||
background-color: #419641;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
.btn-info:hover,
|
||||
.btn-info:focus {
|
||||
background-color: #2aabd2;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-info:active,
|
||||
.btn-info.active {
|
||||
background-color: #2aabd2;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
.btn-info.disabled,
|
||||
.btn-info[disabled],
|
||||
fieldset[disabled] .btn-info,
|
||||
.btn-info.disabled:hover,
|
||||
.btn-info[disabled]:hover,
|
||||
fieldset[disabled] .btn-info:hover,
|
||||
.btn-info.disabled:focus,
|
||||
.btn-info[disabled]:focus,
|
||||
fieldset[disabled] .btn-info:focus,
|
||||
.btn-info.disabled.focus,
|
||||
.btn-info[disabled].focus,
|
||||
fieldset[disabled] .btn-info.focus,
|
||||
.btn-info.disabled:active,
|
||||
.btn-info[disabled]:active,
|
||||
fieldset[disabled] .btn-info:active,
|
||||
.btn-info.disabled.active,
|
||||
.btn-info[disabled].active,
|
||||
fieldset[disabled] .btn-info.active {
|
||||
background-color: #2aabd2;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
.btn-warning:hover,
|
||||
.btn-warning:focus {
|
||||
background-color: #eb9316;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-warning:active,
|
||||
.btn-warning.active {
|
||||
background-color: #eb9316;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
.btn-warning.disabled,
|
||||
.btn-warning[disabled],
|
||||
fieldset[disabled] .btn-warning,
|
||||
.btn-warning.disabled:hover,
|
||||
.btn-warning[disabled]:hover,
|
||||
fieldset[disabled] .btn-warning:hover,
|
||||
.btn-warning.disabled:focus,
|
||||
.btn-warning[disabled]:focus,
|
||||
fieldset[disabled] .btn-warning:focus,
|
||||
.btn-warning.disabled.focus,
|
||||
.btn-warning[disabled].focus,
|
||||
fieldset[disabled] .btn-warning.focus,
|
||||
.btn-warning.disabled:active,
|
||||
.btn-warning[disabled]:active,
|
||||
fieldset[disabled] .btn-warning:active,
|
||||
.btn-warning.disabled.active,
|
||||
.btn-warning[disabled].active,
|
||||
fieldset[disabled] .btn-warning.active {
|
||||
background-color: #eb9316;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
.btn-danger:hover,
|
||||
.btn-danger:focus {
|
||||
background-color: #c12e2a;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-danger:active,
|
||||
.btn-danger.active {
|
||||
background-color: #c12e2a;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
.btn-danger.disabled,
|
||||
.btn-danger[disabled],
|
||||
fieldset[disabled] .btn-danger,
|
||||
.btn-danger.disabled:hover,
|
||||
.btn-danger[disabled]:hover,
|
||||
fieldset[disabled] .btn-danger:hover,
|
||||
.btn-danger.disabled:focus,
|
||||
.btn-danger[disabled]:focus,
|
||||
fieldset[disabled] .btn-danger:focus,
|
||||
.btn-danger.disabled.focus,
|
||||
.btn-danger[disabled].focus,
|
||||
fieldset[disabled] .btn-danger.focus,
|
||||
.btn-danger.disabled:active,
|
||||
.btn-danger[disabled]:active,
|
||||
fieldset[disabled] .btn-danger:active,
|
||||
.btn-danger.disabled.active,
|
||||
.btn-danger[disabled].active,
|
||||
fieldset[disabled] .btn-danger.active {
|
||||
background-color: #c12e2a;
|
||||
background-image: none;
|
||||
}
|
||||
.thumbnail,
|
||||
.img-thumbnail {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
.dropdown-menu > .active > a,
|
||||
.dropdown-menu > .active > a:hover,
|
||||
.dropdown-menu > .active > a:focus {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
background-color: #2e6da4;
|
||||
}
|
||||
.navbar-default {
|
||||
background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||
background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));
|
||||
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.navbar-default .navbar-nav > .open > a,
|
||||
.navbar-default .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
|
||||
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.navbar-brand,
|
||||
.navbar-nav > li > a {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
.navbar-inverse {
|
||||
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
|
||||
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.navbar-inverse .navbar-nav > .open > a,
|
||||
.navbar-inverse .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
|
||||
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.navbar-inverse .navbar-brand,
|
||||
.navbar-inverse .navbar-nav > li > a {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.navbar-static-top,
|
||||
.navbar-fixed-top,
|
||||
.navbar-fixed-bottom {
|
||||
border-radius: 0;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a,
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
|
||||
color: #fff;
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
}
|
||||
.alert {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.alert-success {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b2dba1;
|
||||
}
|
||||
.alert-info {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #9acfea;
|
||||
}
|
||||
.alert-warning {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #f5e79e;
|
||||
}
|
||||
.alert-danger {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dca7a7;
|
||||
}
|
||||
.progress {
|
||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
|
||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-striped {
|
||||
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
}
|
||||
.list-group {
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.list-group-item.active,
|
||||
.list-group-item.active:hover,
|
||||
.list-group-item.active:focus {
|
||||
text-shadow: 0 -1px 0 #286090;
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #2b669a;
|
||||
}
|
||||
.list-group-item.active .badge,
|
||||
.list-group-item.active:hover .badge,
|
||||
.list-group-item.active:focus .badge {
|
||||
text-shadow: none;
|
||||
}
|
||||
.panel {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.panel-default > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-primary > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-success > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-info > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-warning > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-danger > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.well {
|
||||
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
|
||||
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dcdcdc;
|
||||
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-theme.css.map */
|
||||
File diff suppressed because one or more lines are too long
6
src/main/resources/static/bootstrap-3.3.7-dist/css/bootstrap-theme.min.css
vendored
Normal file
6
src/main/resources/static/bootstrap-3.3.7-dist/css/bootstrap-theme.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6834
src/main/resources/static/bootstrap-3.3.7-dist/css/bootstrap.css
vendored
Normal file
6834
src/main/resources/static/bootstrap-3.3.7-dist/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
6
src/main/resources/static/bootstrap-3.3.7-dist/css/bootstrap.min.css
vendored
Normal file
6
src/main/resources/static/bootstrap-3.3.7-dist/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1,288 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata></metadata>
|
||||
<defs>
|
||||
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
|
||||
<font-face units-per-em="1200" ascent="960" descent="-240" />
|
||||
<missing-glyph horiz-adv-x="500" />
|
||||
<glyph horiz-adv-x="0" />
|
||||
<glyph horiz-adv-x="400" />
|
||||
<glyph unicode=" " />
|
||||
<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
|
||||
<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode=" " />
|
||||
<glyph unicode="¥" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
|
||||
<glyph unicode=" " horiz-adv-x="650" />
|
||||
<glyph unicode=" " horiz-adv-x="1300" />
|
||||
<glyph unicode=" " horiz-adv-x="650" />
|
||||
<glyph unicode=" " horiz-adv-x="1300" />
|
||||
<glyph unicode=" " horiz-adv-x="433" />
|
||||
<glyph unicode=" " horiz-adv-x="325" />
|
||||
<glyph unicode=" " horiz-adv-x="216" />
|
||||
<glyph unicode=" " horiz-adv-x="216" />
|
||||
<glyph unicode=" " horiz-adv-x="162" />
|
||||
<glyph unicode=" " horiz-adv-x="260" />
|
||||
<glyph unicode=" " horiz-adv-x="72" />
|
||||
<glyph unicode=" " horiz-adv-x="260" />
|
||||
<glyph unicode=" " horiz-adv-x="325" />
|
||||
<glyph unicode="€" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
|
||||
<glyph unicode="₽" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
|
||||
<glyph unicode="−" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="⌛" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
|
||||
<glyph unicode="◼" horiz-adv-x="500" d="M0 0z" />
|
||||
<glyph unicode="☁" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
|
||||
<glyph unicode="⛺" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
|
||||
<glyph unicode="✉" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
|
||||
<glyph unicode="✏" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
|
||||
<glyph unicode="" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
|
||||
<glyph unicode="" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
|
||||
<glyph unicode="" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
|
||||
<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
|
||||
<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
|
||||
<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
|
||||
<glyph unicode="" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
|
||||
<glyph unicode="" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
|
||||
<glyph unicode="" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
|
||||
<glyph unicode="" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
|
||||
<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
|
||||
<glyph unicode="" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
|
||||
<glyph unicode="" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
|
||||
<glyph unicode="" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
|
||||
<glyph unicode="" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
|
||||
<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
|
||||
<glyph unicode="" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
|
||||
<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
|
||||
<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
|
||||
<glyph unicode="" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
|
||||
<glyph unicode="" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
|
||||
<glyph unicode="" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
|
||||
<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
|
||||
<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
|
||||
<glyph unicode="" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
|
||||
<glyph unicode="" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
|
||||
<glyph unicode="" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
|
||||
<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
|
||||
<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
|
||||
<glyph unicode="" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
|
||||
<glyph unicode="" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
|
||||
<glyph unicode="" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
|
||||
<glyph unicode="" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
|
||||
<glyph unicode="" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
|
||||
<glyph unicode="" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
|
||||
<glyph unicode="" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
|
||||
<glyph unicode="" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
|
||||
<glyph unicode="" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
|
||||
<glyph unicode="" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
|
||||
<glyph unicode="" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
|
||||
<glyph unicode="" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
|
||||
<glyph unicode="" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
|
||||
<glyph unicode="" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
|
||||
<glyph unicode="" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
|
||||
<glyph unicode="" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
|
||||
<glyph unicode="" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
|
||||
<glyph unicode="" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
|
||||
<glyph unicode="" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
|
||||
<glyph unicode="" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
|
||||
<glyph unicode="" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
|
||||
<glyph unicode="" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
|
||||
<glyph unicode="" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
|
||||
<glyph unicode="" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
|
||||
<glyph unicode="" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
|
||||
<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
|
||||
<glyph unicode="" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
|
||||
<glyph unicode="" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
|
||||
<glyph unicode="" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
|
||||
<glyph unicode="" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
|
||||
<glyph unicode="" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
|
||||
<glyph unicode="" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
|
||||
<glyph unicode="" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
|
||||
<glyph unicode="" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
|
||||
<glyph unicode="" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
|
||||
<glyph unicode="" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
|
||||
<glyph unicode="" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
|
||||
<glyph unicode="" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
|
||||
<glyph unicode="" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
|
||||
<glyph unicode="" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
|
||||
<glyph unicode="" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
|
||||
<glyph unicode="" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
|
||||
<glyph unicode="" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
|
||||
<glyph unicode="" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
|
||||
<glyph unicode="" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
|
||||
<glyph unicode="" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
|
||||
<glyph unicode="" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
|
||||
<glyph unicode="" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
|
||||
<glyph unicode="" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
|
||||
<glyph unicode="" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
|
||||
<glyph unicode="" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
|
||||
<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
|
||||
<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
|
||||
<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
|
||||
<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
|
||||
<glyph unicode="" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
|
||||
<glyph unicode="" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
|
||||
<glyph unicode="" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
|
||||
<glyph unicode="" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
|
||||
<glyph unicode="" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
|
||||
<glyph unicode="" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
|
||||
<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
|
||||
<glyph unicode="" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
|
||||
<glyph unicode="" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
|
||||
<glyph unicode="" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
|
||||
<glyph unicode="" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
|
||||
<glyph unicode="" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
|
||||
<glyph unicode="" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
|
||||
<glyph unicode="" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
|
||||
<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
|
||||
<glyph unicode="" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
|
||||
<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
|
||||
<glyph unicode="" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
|
||||
<glyph unicode="" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
|
||||
<glyph unicode="" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
|
||||
<glyph unicode="" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
|
||||
<glyph unicode="" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
|
||||
<glyph unicode="" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
|
||||
<glyph unicode="" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
|
||||
<glyph unicode="" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
|
||||
<glyph unicode="" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
|
||||
<glyph unicode="" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
|
||||
<glyph unicode="" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
|
||||
<glyph unicode="" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
|
||||
<glyph unicode="" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
|
||||
<glyph unicode="" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
|
||||
<glyph unicode="" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
|
||||
<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
|
||||
<glyph unicode="" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
|
||||
<glyph unicode="" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
|
||||
<glyph unicode="" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
|
||||
<glyph unicode="" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
|
||||
<glyph unicode="" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
|
||||
<glyph unicode="" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
|
||||
<glyph unicode="" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
|
||||
<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
|
||||
<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
|
||||
<glyph unicode="" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
|
||||
<glyph unicode="" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
|
||||
<glyph unicode="" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
|
||||
<glyph unicode="" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
|
||||
<glyph unicode="" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
|
||||
<glyph unicode="" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
|
||||
<glyph unicode="" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
|
||||
<glyph unicode="" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
|
||||
<glyph unicode="" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
|
||||
<glyph unicode="" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
|
||||
<glyph unicode="" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
|
||||
<glyph unicode="" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
|
||||
<glyph unicode="" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
|
||||
<glyph unicode="" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
|
||||
<glyph unicode="" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
|
||||
<glyph unicode="" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
|
||||
<glyph unicode="" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
|
||||
<glyph unicode="" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
|
||||
<glyph unicode="" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
|
||||
<glyph unicode="" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
|
||||
<glyph unicode="" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
|
||||
<glyph unicode="" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
|
||||
<glyph unicode="" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
|
||||
<glyph unicode="" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
|
||||
<glyph unicode="" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
|
||||
<glyph unicode="" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
|
||||
<glyph unicode="" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
|
||||
<glyph unicode="" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
|
||||
<glyph unicode="" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
|
||||
<glyph unicode="" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
|
||||
<glyph unicode="" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
|
||||
<glyph unicode="" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
|
||||
<glyph unicode="" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
|
||||
<glyph unicode="" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
|
||||
<glyph unicode="" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
|
||||
<glyph unicode="" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
|
||||
<glyph unicode="" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
|
||||
<glyph unicode="" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
|
||||
<glyph unicode="" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
|
||||
<glyph unicode="" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
|
||||
<glyph unicode="" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
|
||||
<glyph unicode="" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
|
||||
<glyph unicode="" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
|
||||
<glyph unicode="" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
|
||||
<glyph unicode="" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
|
||||
<glyph unicode="🔑" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
|
||||
<glyph unicode="🚪" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
After Width: | Height: | Size: 106 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
2580
src/main/resources/static/bootstrap-3.3.7-dist/js/bootstrap.js
vendored
Normal file
2580
src/main/resources/static/bootstrap-3.3.7-dist/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
src/main/resources/static/bootstrap-3.3.7-dist/js/bootstrap.min.js
vendored
Normal file
6
src/main/resources/static/bootstrap-3.3.7-dist/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
13
src/main/resources/static/bootstrap-3.3.7-dist/js/npm.js
vendored
Normal file
13
src/main/resources/static/bootstrap-3.3.7-dist/js/npm.js
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
|
||||
require('../../js/transition.js')
|
||||
require('../../js/alert.js')
|
||||
require('../../js/button.js')
|
||||
require('../../js/carousel.js')
|
||||
require('../../js/collapse.js')
|
||||
require('../../js/dropdown.js')
|
||||
require('../../js/modal.js')
|
||||
require('../../js/tooltip.js')
|
||||
require('../../js/popover.js')
|
||||
require('../../js/scrollspy.js')
|
||||
require('../../js/tab.js')
|
||||
require('../../js/affix.js')
|
||||
269
src/main/resources/static/category_list.html
Normal file
269
src/main/resources/static/category_list.html
Normal file
@@ -0,0 +1,269 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<title>分类列表</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<script type="text/javascript" src="decimal/decimal.js"></script>
|
||||
<script type="text/javascript" src="moment/moment.js"></script>
|
||||
<script type="text/javascript" src="js/fortern.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 模态框 -->
|
||||
<!-- 添加分类模态框 -->
|
||||
<div id="category_add_modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">添加分类</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="add_category_form" class="form-horizontal" autocomplete="off">
|
||||
<input id="user_id" name="id" type="hidden"/>
|
||||
<div class="form-group has-feedback">
|
||||
<label for="category_name" class="col-sm-2 control-label">分类名称</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="category_name" name="category_name" type="text" class="form-control" placeholder="新分类的名称">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="category_id" class="col-sm-2 control-label">父级分类</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="category_id" class="form-control">
|
||||
<option value="">-- 不选择父级分类 --</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
|
||||
<button id="category_add_btn" type="button" class="btn btn-primary">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 捐赠信息模态框 -->
|
||||
<div id="donate_modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">捐赠</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="donate_form" class="form-horizontal" autocomplete="off" action="/pay/generate" method="post">
|
||||
<div class="form-group has-feedback">
|
||||
<label for="total" class="col-sm-2 control-label">捐赠金额</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="total" name="total" type="text" class="form-control" placeholder="1-100之间的两位小数">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
|
||||
<button id="donate_btn" type="button" class="btn btn-primary">捐赠</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 导航栏 -->
|
||||
<nav class="navbar navbar-default">
|
||||
<!-- 导航条 -->
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<!-- 导航条左边头部 -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
|
||||
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<!-- 登录页 -->
|
||||
<a class="navbar-brand" href="index.html">落星原</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<!-- 导航条中间部分 -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<!-- 左侧导航连接 -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="edit_article.html">添加新文章 <span class="sr-only">(current)</span></a></li>
|
||||
<li><a href="user_list.html">用户管理</a></li>
|
||||
<li><a href="article_list.html">文章管理</a></li>
|
||||
<li><a href="comment_list.html">评论管理</a></li>
|
||||
<li><a href="category_list.html">分类管理</a></li>
|
||||
<li><a href="donate_list.html">捐赠管理</a></li>
|
||||
</ul>
|
||||
<!-- 搜索框 -->
|
||||
<form class="navbar-form navbar-left">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input id="search_key" type="text" class="form-control" placeholder="Search">
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default" onclick="to_search()" id="search_btn">搜索</button>
|
||||
</form>
|
||||
<!-- 右侧导航连接 -->
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">操作 <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<!-- 个人中心 -->
|
||||
<li><a href="user.html">个人中心</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="show_donate()">捐赠</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="logout()">注销</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
<!-- 搭建显示页面 -->
|
||||
<div class="container">
|
||||
<!-- 标题 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>分类管理</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 按钮 -->
|
||||
<div class="row">
|
||||
<!-- 此列向右偏移 -->
|
||||
<!-- 宽度4,左间距8 -->
|
||||
<div class="col-md-4 col-md-offset-8">
|
||||
<button id="add_category_btn" class="btn btn-primary">添加分类</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示表格数据库 -->
|
||||
<div class="row">
|
||||
<!-- 表格占12列 -->
|
||||
<div class="col-md-12">
|
||||
<table id="category_table" class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>ID</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
$(function () {
|
||||
$.ajax("/user/getMe", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function () {},
|
||||
error: function () {
|
||||
$(window).attr('location','/index.html');
|
||||
}
|
||||
});
|
||||
//加载分类列表
|
||||
$.ajax("/category/all", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
build_category_table(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//构建用户列表
|
||||
function build_category_table(categories) {
|
||||
//先清空原有数据
|
||||
$("#category_table tbody").empty();
|
||||
$.each(categories, function (index, item) {
|
||||
let num = searchStrEach(item.id, "_");
|
||||
let str = "";
|
||||
for (let i = 1; i < num; i++) {
|
||||
str += " ";
|
||||
}
|
||||
str += item.name;
|
||||
let nameTd = $("<td></td>").append(str);
|
||||
let idTd = $("<td></td>").append(item.id);
|
||||
let delBtn = $("<button class='btn btn-danger btn-sm del_btn'></button>").append($("<span class='glyphicon glyphicon-trash'></span>")).append("删除");
|
||||
let btnTd = $("<td></td>").append(delBtn);
|
||||
$("<tr></tr>").attr("data-id", item.id).append(nameTd).append(idTd).append(btnTd).appendTo("#category_table tbody");
|
||||
$("<option value='" + item.id + "'>" + str + "</option>").appendTo("#category_id");
|
||||
});
|
||||
}
|
||||
|
||||
//给后来出现的“删除”按钮添加绑定事件
|
||||
$(document).on("click", ".del_btn", function () {
|
||||
let category_name = $(this).parent().parent().find("td:eq(0)").text();
|
||||
if (confirm("确认删除【" + category_name + "】吗?")) {
|
||||
$.ajax({
|
||||
url: "category/del/" + $(this).parent().parent().find("td:eq(1)").text(),
|
||||
type: "DELETE",
|
||||
success: function () {
|
||||
toastr.success("删除成功");
|
||||
setTimeout(function () {
|
||||
$(window).attr('location', '/category_list.html');
|
||||
}, 1500);
|
||||
},
|
||||
statusCode: {
|
||||
400: function (XMLHttpRequest) {
|
||||
toastr.warning(XMLHttpRequest.responseJSON);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
//点击新增显示模态框
|
||||
$("#add_category_btn").on("click", function () {
|
||||
//0、重置模态框
|
||||
$("#add_category_form")[0].reset();
|
||||
$("#category_add_modal").modal({
|
||||
backdrop: "static"
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//添加按钮点击事件
|
||||
$("#category_add_btn").on("click", function () {
|
||||
let _data = "name=" + $("#category_name").val();
|
||||
let superior = $("#category_id").val();
|
||||
if(superior !== "")
|
||||
_data += ("&superior=" + superior);
|
||||
$.ajax({
|
||||
url: "/category/add",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: _data,
|
||||
success: function () {
|
||||
toastr.success("添加成功");
|
||||
setTimeout(function () {
|
||||
$(window).attr('location','/category_list.html');
|
||||
}, 1500);
|
||||
//关闭模态框
|
||||
},
|
||||
fail: function () {
|
||||
toastr.fail("未知原因更新失败");
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
268
src/main/resources/static/comment_list.html
Normal file
268
src/main/resources/static/comment_list.html
Normal file
@@ -0,0 +1,268 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<title>评论列表</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<script type="text/javascript" src="decimal/decimal.js"></script>
|
||||
<script type="text/javascript" src="moment/moment.js"></script>
|
||||
<script type="text/javascript" src="js/fortern.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default">
|
||||
<!-- 导航条 -->
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<!-- 导航条左边头部 -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
|
||||
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<!-- 登录页 -->
|
||||
<a class="navbar-brand" href="index.html">落星原</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<!-- 导航条中间部分 -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<!-- 左侧导航连接 -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="edit_article.html">添加新文章 <span class="sr-only">(current)</span></a></li>
|
||||
<li><a href="user_list.html">用户管理</a></li>
|
||||
<li><a href="article_list.html">文章管理</a></li>
|
||||
<li><a href="comment_list.html">评论管理</a></li>
|
||||
<li><a href="category_list.html">分类管理</a></li>
|
||||
<li><a href="donate_list.html">捐赠管理</a></li>
|
||||
</ul>
|
||||
<!-- 搜索框 -->
|
||||
<form class="navbar-form navbar-left">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input id="search_key" type="text" class="form-control" placeholder="Search">
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default" onclick="to_search()" id="search_btn">搜索</button>
|
||||
</form>
|
||||
<!-- 右侧导航连接 -->
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">操作 <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<!-- 个人中心 -->
|
||||
<li><a href="user.html">个人中心</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="show_donate()">捐赠</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="logout()">注销</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
<!-- 搭建显示页面 -->
|
||||
<div class="container">
|
||||
<!-- 标题 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>评论列表</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 按钮 -->
|
||||
<div class="row">
|
||||
<!-- 此列向右偏移 -->
|
||||
<!-- 宽度4,左间距8 -->
|
||||
<div class="col-md-4 col-md-offset-8">
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示表格数据库 -->
|
||||
<div class="row">
|
||||
<!-- 表格占12列 -->
|
||||
<div class="col-md-12">
|
||||
<table id="comment_table" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<label><input id="check_all" type="checkbox"/></label>
|
||||
</th>
|
||||
<th>文章id</th>
|
||||
<th>用户</th>
|
||||
<th>回复数</th>
|
||||
<th>内容</th>
|
||||
<th>发表时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示分页信息 -->
|
||||
<div class="row">
|
||||
<!-- 分页信息 -->
|
||||
<div id="page_info_area" class="col-md-6">
|
||||
|
||||
</div>
|
||||
<div id="page_nav" class="col-md-6">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
let security;
|
||||
//1、页面加载完成以后,直接发送ajax请求,要到分页数据
|
||||
$(function () {
|
||||
$.ajax({
|
||||
url: "/user/getMe",
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (result) {
|
||||
security = result.security;
|
||||
},
|
||||
statusCode: {
|
||||
403: function () {
|
||||
$(window).attr('location', '/login.html');
|
||||
}
|
||||
}
|
||||
});
|
||||
to_page(1);
|
||||
});
|
||||
|
||||
//跳转到第pn页
|
||||
function to_page(pn) {
|
||||
$.ajax({
|
||||
url: "/comment/i",
|
||||
data: "page=" + pn + "&size=5",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
//1、解析并显示评论数据
|
||||
build_comment_table(result);
|
||||
let page_info = build_page_info(result.pageIndex, result.pageSize, result.totalCount);
|
||||
//2、解析并显示分页信息
|
||||
$("#page_info_area").empty().append("当前" + page_info.page + "页,共" + page_info.pages + "页,共" + page_info.total + "条记录");
|
||||
//3、解析显示分页条数据
|
||||
build_page_nav(page_info);
|
||||
},
|
||||
fail: function () {
|
||||
toastr.fail("加载数据失败");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//构建评论列表
|
||||
function build_comment_table(result) {
|
||||
//先清空原有数据
|
||||
$("#comment_table tbody").empty();
|
||||
$("#check_all").prop("checked", false);
|
||||
let articles = result.records;
|
||||
$.each(articles, function (index, item) {
|
||||
let checkBoxTd = $("<td></td>").append("<input type='checkbox' class='check_item'/>");
|
||||
let aidTd = $("<td></td>").append(item.aid);
|
||||
let usernameTd = $("<td></td>").append(item.simpleUser.username);
|
||||
let numOfReplyTd = $("<td></td>").append(item.numOfReply);
|
||||
let contentTd = $("<td></td>").append(item.content);
|
||||
let timeTd = $("<td></td>").append(moment(new Date(item.time)).format(time_format));
|
||||
let editBtn = $("<button data-id='" + item.id + "' class='btn btn-danger btn-sm del_btn'></button>").append($("<span class='glyphicon glyphicon-trash'></span>")).append("删除");
|
||||
let btnTd = $("<td></td>").append(editBtn);
|
||||
$("<tr></tr>").attr("data-id", item.id).append(checkBoxTd).append(aidTd).append(usernameTd).append(numOfReplyTd).append(timeTd).append(contentTd).append(timeTd).append(btnTd).appendTo("#comment_table tbody");
|
||||
});
|
||||
}
|
||||
|
||||
//构建分页条
|
||||
function build_page_nav(page_info) {
|
||||
$("#page_nav").empty();
|
||||
let ul = $("<ul></ul>").addClass("pagination");
|
||||
let firstPageLi = $("<li></li>").append($("<a></a>").append("首页"));
|
||||
let prePageLi = $("<li></li>").append($("<a></a>").append("«"));
|
||||
if (!page_info.hasPreviousPage) {
|
||||
firstPageLi.addClass("disabled");
|
||||
prePageLi.addClass("disabled");
|
||||
} else {
|
||||
firstPageLi.click(function () {
|
||||
to_page(1);
|
||||
});
|
||||
prePageLi.click(function () {
|
||||
to_page(page - 1);
|
||||
});
|
||||
}
|
||||
let lastPageLi = $("<li></li>").append($("<a></a>").append("末页"));
|
||||
let nextPageLi = $("<li></li>").append($("<a></a>").append("»"));
|
||||
if (page_info.hasNextPage === false) {
|
||||
lastPageLi.addClass("disabled");
|
||||
nextPageLi.addClass("disabled");
|
||||
} else {
|
||||
nextPageLi.click(function () {
|
||||
to_page(page + 1);
|
||||
});
|
||||
lastPageLi.click(function () {
|
||||
to_page(pages);
|
||||
});
|
||||
}
|
||||
ul.append(firstPageLi).append(prePageLi);
|
||||
$.each(page_info.beforePages, function (index, item) {
|
||||
let numLi = $("<li value='" + item + "'></li>").append($("<a></a>").append(item));
|
||||
numLi.appendTo(ul);
|
||||
numLi.click(function () {
|
||||
to_page(item);
|
||||
})
|
||||
});
|
||||
ul.append("<li class='active'><a>" + page_info.page + "</a></li>");
|
||||
$.each(page_info.afterPages, function (index, item) {
|
||||
let numLi = $("<li value='" + item + "'></li>").append($("<a></a>").append(item));
|
||||
numLi.appendTo(ul);
|
||||
numLi.click(function () {
|
||||
to_page(item);
|
||||
})
|
||||
});
|
||||
ul.append(nextPageLi).append(lastPageLi);
|
||||
let navEle = $("<nav></nav>").append(ul);
|
||||
navEle.appendTo("#page_nav");
|
||||
}
|
||||
|
||||
//给后来出现的“编辑”按钮添加绑定事件
|
||||
$(document).on("click", ".edit_btn", function () {
|
||||
let id = $(this).attr("data-id");
|
||||
$(window).attr('location','/edit_article.html?aid=' + id);
|
||||
})
|
||||
|
||||
//给后来出现的“删除”按钮添加绑定事件
|
||||
$(document).on("click", ".del_btn", function () {
|
||||
let comment_id = $(this).attr("data-id");
|
||||
if (confirm("确认删除【" + comment_id + "】吗?")) {
|
||||
$.ajax({
|
||||
url: "/comment/del/" + comment_id,
|
||||
type: "DELETE",
|
||||
success: function (result) {
|
||||
toastr.success(result);
|
||||
to_page(1);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
//给后来出现的“复选框”添加绑定事件
|
||||
$(document).on("click", ".check_item", function () {
|
||||
//判断全选框里是不是要有钩
|
||||
let flag = $(".check_item:checked").length === $(".check_item").length;
|
||||
$("#check_all").prop("checked", flag);
|
||||
})
|
||||
//全选
|
||||
$("#check_all").click(function () {
|
||||
//prop修改和获取原声属性的值
|
||||
//将所有复选框的checked属性设为和被点击的那个相同
|
||||
$(".check_item").prop("checked", $(this).prop("checked"));
|
||||
})
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
227
src/main/resources/static/comment_test.html
Normal file
227
src/main/resources/static/comment_test.html
Normal file
@@ -0,0 +1,227 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>带头像三级评论回复html+css代码</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.feed {
|
||||
font-family: "微软雅黑",serif;
|
||||
width: 720px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 50px;
|
||||
float: left;
|
||||
margin: 0 8px 0 0;
|
||||
box-shadow: 0 0 3px #e0e0e0;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.feed .avatar img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.feed .box1 {
|
||||
width: 640px;
|
||||
float: left;
|
||||
background: #f6f6f6;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.feed .box1 .current {
|
||||
font-size: 14px;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.feed .box1 .info {
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
.feed .box1 .info span {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.feed .box1 .line {
|
||||
padding: 8px 0 0 0;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.feed .box1 .box2 {
|
||||
margin: 8px;
|
||||
padding: 0 0 8px 0;
|
||||
border-bottom: 1px dashed #ccc;
|
||||
}
|
||||
|
||||
.feed .box1 .box2_comments {
|
||||
width: 560px;
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.feed .box1 .say {
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.feed .box1 .box2_comments .box3 {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.feed .box1 .box2_comments .box3_comments {
|
||||
float: left;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.reply_area {
|
||||
border: 1px solid #e0e0e0;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
width: 620px;
|
||||
margin: 8px;
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
font-family: "微软雅黑",serif;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<li class="feed">
|
||||
<div class="avatar">
|
||||
<img src="images/user.jpg" alt="" />
|
||||
</div><!--第一层循环start-->
|
||||
<div class="box1">
|
||||
<p class='current'>
|
||||
<a href="">user</a>
|
||||
说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容
|
||||
</p>
|
||||
<p class='info'>
|
||||
<span><a href="">删除</a><a href="">评论</a></span>
|
||||
<strong>刚刚</strong>
|
||||
通过QQ空间
|
||||
</p>
|
||||
<p class="line">
|
||||
</p>
|
||||
<!--第二层循环start-->
|
||||
<div class="box2">
|
||||
<div class="avatar">
|
||||
<img src="images/user.jpg" alt="" />
|
||||
</div>
|
||||
<div class="box2_comments">
|
||||
<p class='say'>
|
||||
<a href="">user</a>
|
||||
说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容
|
||||
</p>
|
||||
<p>
|
||||
<strong>刚刚</strong>
|
||||
<a href="">删除</a>
|
||||
<a href="">回复</a>
|
||||
</p>
|
||||
<!--第三层循环start-->
|
||||
<div class="box3">
|
||||
<div class="avatar">
|
||||
<img src="images/user.jpg" alt="" />
|
||||
</div>
|
||||
<div class="box3_comments">
|
||||
<p class='say'>
|
||||
<a href="">user</a>
|
||||
说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容
|
||||
</p>
|
||||
<p>
|
||||
<strong>刚刚</strong>
|
||||
<a href="">删除</a>
|
||||
<a href="">回复</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="clear">
|
||||
</div>
|
||||
</div>
|
||||
<!--第三层循环end-->
|
||||
</div>
|
||||
<div class="clear">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box2">
|
||||
<div class="avatar">
|
||||
<img src="images/user.jpg" alt="" />
|
||||
</div>
|
||||
<div class="box2_comments">
|
||||
<p class='say'>
|
||||
<a href="">user</a>
|
||||
说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容
|
||||
</p>
|
||||
<p>
|
||||
<strong>刚刚</strong>
|
||||
<a href="">删除</a>
|
||||
<a href="">回复</a>
|
||||
</p>
|
||||
<!--第三层循环start-->
|
||||
<div class="box3">
|
||||
<div class="avatar">
|
||||
<img src="images/user.jpg" alt="" />
|
||||
</div>
|
||||
<div class="box3_comments">
|
||||
<p class='say'>
|
||||
<a href="">user</a>
|
||||
说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容
|
||||
</p>
|
||||
<p>
|
||||
<strong>刚刚</strong>
|
||||
<a href="">删除</a>
|
||||
<a href="">回复</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="clear">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box3">
|
||||
<div class="avatar">
|
||||
<img src="images/user.jpg" alt="" />
|
||||
</div>
|
||||
<div class="box3_comments">
|
||||
<p class='say'>
|
||||
<a href="">user</a>
|
||||
说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容说说内容
|
||||
</p>
|
||||
<p>
|
||||
<strong>刚刚</strong>
|
||||
<a href="">删除</a>
|
||||
<a href="">回复</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="clear">
|
||||
</div>
|
||||
</div>
|
||||
<!--第三层循环end-->
|
||||
</div>
|
||||
<div class="clear">
|
||||
</div>
|
||||
</div>
|
||||
<!--第二层循环end-->
|
||||
<p class="line">
|
||||
</p>
|
||||
<textarea name="" class="reply_area">
|
||||
我也说两句
|
||||
</textarea>
|
||||
</div>
|
||||
<!--第一层循环end-->
|
||||
<div class="clear">
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
121
src/main/resources/static/css/comment.css
Normal file
121
src/main/resources/static/css/comment.css
Normal file
@@ -0,0 +1,121 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Microsoft YaHei, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.cls {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 780px;
|
||||
min-height: 10px;
|
||||
margin: 50px auto;
|
||||
/* border: 1px solid #dfdfdf; */
|
||||
}
|
||||
|
||||
.comment {
|
||||
min-height: 60px;
|
||||
/* border: 1px solid red; */
|
||||
}
|
||||
|
||||
.comment-avatar img {
|
||||
margin: 20px 0 0 20px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.comment-content {
|
||||
float: right;
|
||||
width: 685px;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #dfdfdf;
|
||||
}
|
||||
|
||||
.comment-bottom > .comment-content {
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
}
|
||||
|
||||
.comment-content-name {
|
||||
color: #6d757a;
|
||||
font-size: 12px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.comment-content-article {
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.comment-content-footer {
|
||||
color: #6d757a;
|
||||
font-size: 12px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.comment-content-footer span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
.comment-send {
|
||||
position: relative;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.comment-send-input {
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
transition: all 0.3s;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 95px;
|
||||
resize: none;
|
||||
width: 605px;
|
||||
height: 65px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
background: #f4f5f7;
|
||||
border: 1px solid #e5e9ef;
|
||||
}
|
||||
|
||||
.comment-send-input:hover, .comment-send-input:active {
|
||||
background: #fff;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.comment-send-button {
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
transition: all 0.3s;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 0px;
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
border-radius: 4px;
|
||||
background: #1aa2d4;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.comment-send-button:hover {
|
||||
background: #1eb6e3;
|
||||
}
|
||||
|
||||
.reply-list {
|
||||
width: 685px;
|
||||
border-style: dotted;
|
||||
border-width: 1px;
|
||||
border-color: #7b7272;
|
||||
}
|
||||
|
||||
.reply {
|
||||
|
||||
}
|
||||
4934
src/main/resources/static/decimal/decimal.js
Normal file
4934
src/main/resources/static/decimal/decimal.js
Normal file
File diff suppressed because it is too large
Load Diff
248
src/main/resources/static/donate_list.html
Normal file
248
src/main/resources/static/donate_list.html
Normal file
@@ -0,0 +1,248 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<title>捐赠记录</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<script type="text/javascript" src="decimal/decimal.js"></script>
|
||||
<script type="text/javascript" src="moment/moment.js"></script>
|
||||
<script type="text/javascript" src="js/fortern.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 模态框 -->
|
||||
<!-- 捐赠信息模态框 -->
|
||||
<div id="donate_modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">捐赠</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="donate_form" class="form-horizontal" autocomplete="off" action="/pay/generate" method="post">
|
||||
<div class="form-group has-feedback">
|
||||
<label for="total" class="col-sm-2 control-label">捐赠金额</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="total" name="total" type="text" class="form-control" placeholder="1-100之间的两位小数">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
|
||||
<button id="donate_btn" type="button" class="btn btn-primary">捐赠</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="navbar navbar-default">
|
||||
<!-- 导航条 -->
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<!-- 导航条左边头部 -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
|
||||
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<!-- 登录页 -->
|
||||
<a class="navbar-brand" href="index.html">落星原</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<!-- 导航条中间部分 -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<!-- 左侧导航连接 -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="edit_article.html">添加新文章 <span class="sr-only">(current)</span></a></li>
|
||||
<li><a href="user_list.html">用户管理</a></li>
|
||||
<li><a href="article_list.html">文章管理</a></li>
|
||||
<li><a href="comment_list.html">评论管理</a></li>
|
||||
<li><a href="category_list.html">分类管理</a></li>
|
||||
<li><a href="donate_list.html">捐赠管理</a></li>
|
||||
</ul>
|
||||
<!-- 搜索框 -->
|
||||
<form class="navbar-form navbar-left">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input id="search_key" type="text" class="form-control" placeholder="Search">
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default" onclick="to_search()" id="search_btn">搜索</button>
|
||||
</form>
|
||||
<!-- 右侧导航连接 -->
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">操作 <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<!-- 个人中心 -->
|
||||
<li><a href="user.html">个人中心</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="show_donate()">捐赠</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="logout()">注销</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
<!-- 搭建显示页面 -->
|
||||
<div class="container">
|
||||
<!-- 标题 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>捐赠记录</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示表格数据库 -->
|
||||
<div class="row">
|
||||
<!-- 表格占12列 -->
|
||||
<div class="col-md-12">
|
||||
<table id="donate_table" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>用户名</th>
|
||||
<th>订单号</th>
|
||||
<th>捐赠金额</th>
|
||||
<th>捐赠时间</th>
|
||||
<th>支付宝交易号</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示分页信息 -->
|
||||
<div class="row">
|
||||
<!-- 统计信息 -->
|
||||
<div id="statistics" class="col-md-8">
|
||||
|
||||
</div>
|
||||
<!-- 分页信息 -->
|
||||
<div id="page_info_area" class="col-md-8">
|
||||
|
||||
</div>
|
||||
<div id="page_nav" class="col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
$(function () {
|
||||
$.ajax("/user/getMe", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function () {
|
||||
},
|
||||
error: function () {
|
||||
$(window).attr('location', '/index.html');
|
||||
}
|
||||
});
|
||||
//加载捐赠信息列表
|
||||
$.ajax("/donate/all", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
//1、构建列表
|
||||
build_donate_table(result.records);
|
||||
let page_info = build_page_info(result.pageIndex, result.pageSize, result.totalCount);
|
||||
//2、解析并显示分页信息
|
||||
$("#page_info_area").empty().append("当前" + page_info.page + "页,共" + page_info.pages + "页,共" + page_info.total + "条记录");
|
||||
//3、解析显示分页条数据
|
||||
build_page_nav(page_info, $("#page_nav"));
|
||||
}
|
||||
});
|
||||
$.ajax("/donate/total", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
let str = "服务器至今已收到 " + new Decimal(result).toFixed(2) + " 元的捐赠";
|
||||
$("#statistics").append(str);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//构建用户列表
|
||||
function build_donate_table(donates) {
|
||||
//先清空原有数据
|
||||
$("#donate_table tbody").empty();
|
||||
$.each(donates, function (index, item) {
|
||||
let usernameTd = $("<td></td>").append(item.simpleUser.username);
|
||||
let idTd = $("<td></td>").append(item.id);
|
||||
let amountTd = $("<td></td>").append(new Decimal(item.amount).toFixed(2));
|
||||
let timeTd = $("<td></td>").append(moment(new Date(item.time)).format(time_format));
|
||||
let noTd = $("<td></td>").append(item.tradeNo);
|
||||
$("<tr></tr>").attr("data-id", item.id).append(usernameTd).append(idTd).append(amountTd).append(timeTd).append(noTd).appendTo("#donate_table tbody");
|
||||
});
|
||||
}
|
||||
|
||||
//给后来出现的“删除”按钮添加绑定事件
|
||||
$(document).on("click", ".del_btn", function () {
|
||||
let category_name = $(this).parent().parent().find("td:eq(0)").text();
|
||||
if (confirm("确认删除【" + category_name + "】吗?")) {
|
||||
$.ajax({
|
||||
url: "category/del/" + $(this).parent().parent().find("td:eq(1)").text(),
|
||||
type: "DELETE",
|
||||
success: function () {
|
||||
toastr.success("删除成功");
|
||||
setTimeout(function () {
|
||||
$(window).attr('location', '/category_list.html');
|
||||
}, 1500);
|
||||
},
|
||||
statusCode: {
|
||||
400: function (XMLHttpRequest) {
|
||||
toastr.warning(XMLHttpRequest.responseJSON);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
//点击新增显示模态框
|
||||
$("#add_category_btn").on("click", function () {
|
||||
//0、重置模态框
|
||||
$("#add_category_form")[0].reset();
|
||||
$("#category_add_modal").modal({
|
||||
backdrop: "static"
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//添加按钮点击事件
|
||||
$("#category_add_btn").on("click", function () {
|
||||
let _data = "name=" + $("#category_name").val();
|
||||
let superior = $("#category_id").val();
|
||||
if (superior !== "")
|
||||
_data += ("&superior=" + superior);
|
||||
$.ajax({
|
||||
url: "/category/add",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: _data,
|
||||
success: function () {
|
||||
toastr.success("添加成功");
|
||||
setTimeout(function () {
|
||||
$(window).attr('location', '/category_list.html');
|
||||
}, 1500);
|
||||
//关闭模态框
|
||||
},
|
||||
fail: function () {
|
||||
toastr.fail("未知原因更新失败");
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
158
src/main/resources/static/edit_article.html
Normal file
158
src/main/resources/static/edit_article.html
Normal file
@@ -0,0 +1,158 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<title>文章编辑</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<script type="text/javascript" src="decimal/decimal.js"></script>
|
||||
<script type="text/javascript" src="moment/moment.js"></script>
|
||||
<script type="text/javascript" src="js/fortern.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 搭建显示页面 -->
|
||||
<div class="container">
|
||||
<!-- 标题 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>文章编辑</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 编辑表单 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<form id="edit_article" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-sm-2 control-label">标题</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="title" placeholder="标题">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="summary" class="col-sm-2 control-label">简介</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="summary" placeholder="简介">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="category" class="col-sm-2 control-label">分类</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="category" class="form-control">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="content" class="col-sm-2 control-label">内容</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="content" rows="20"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div id="options" class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="visible" type="checkbox"> 仅作者可见
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button id="save_btn" type="button" class="btn btn-default" onclick="save_article()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
let user;
|
||||
let security;
|
||||
let aid = getUrlParam("aid");
|
||||
let flag = false;//文章加载是否完成
|
||||
$(function () {
|
||||
check_login();
|
||||
//加载分类列表
|
||||
$.ajax("/category/all", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
for (const category of result) {
|
||||
let num = searchStrEach(category.id, "_");
|
||||
let str = "";
|
||||
for (let i = 1; i < num; i++) {
|
||||
str += " ";
|
||||
}
|
||||
str += category.name;
|
||||
$("<option value='" + category.id + "'>" + str + "</option>").appendTo("#category");
|
||||
}
|
||||
}
|
||||
})
|
||||
$.ajax({
|
||||
url: "/user/getMe",
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
user = result.user;
|
||||
security = result.security;
|
||||
if(security.position === "MANAGER") {
|
||||
$("#options").append("<div class='checkbox'><label><input id='reviewed' type='checkbox'> 审核通过</label></div>")
|
||||
.append("<div class='checkbox'><label><input id='top' type='checkbox'> 置顶</label></div>");
|
||||
}
|
||||
}
|
||||
});
|
||||
if (aid != null) {
|
||||
$.ajax({
|
||||
url: "/article/" + aid,
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
build_article_info(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
//填充文章信息
|
||||
function build_article_info(article) {
|
||||
$("#title").val(article.title);
|
||||
$("#summary").val(article.summary);
|
||||
$("#content").val(article.content);
|
||||
$("#visible").prop("checked", !article.visible);
|
||||
$("#category").val(article.categoryId)
|
||||
if (security.position === "MANAGER") {
|
||||
$("#reviewed").prop("checked", article.reviewed);
|
||||
$("#top").prop("checked", article.top);
|
||||
}
|
||||
}
|
||||
|
||||
//保存文章按钮。有aid表示编辑,没有表示更新。
|
||||
function save_article() {
|
||||
$("#save_btn").prop("disabled", true);
|
||||
let _data = "title=" + $("#title").val() + "&summary=" + $("#summary").val() + "&categoryId=" + $('#category').find('option:selected').val() + "&content=" + $("#content").val() + "&visible=" + !$("#visible").prop('checked');
|
||||
if (security.position === "MANAGER") {
|
||||
_data += ("&reviewed=" + $("#reviewed").prop('checked') + "&top=" + $("#top").prop('checked'));
|
||||
}
|
||||
$.ajax({
|
||||
url: "/article/" + (aid == null ? "new" : "update/" + aid),
|
||||
data: _data,
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
success: function () {
|
||||
toastr.success("成功!");
|
||||
},
|
||||
statusCode: {
|
||||
403: function (XMLHttpRequest) {
|
||||
toastr.warning(XMLHttpRequest.responseJSON);
|
||||
}
|
||||
}
|
||||
});
|
||||
setTimeout(function () {
|
||||
$("#save_btn").prop("disabled", false);
|
||||
}, 8000);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
src/main/resources/static/favicon.ico
Normal file
BIN
src/main/resources/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
src/main/resources/static/img/默认头像.jpg
Normal file
BIN
src/main/resources/static/img/默认头像.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
182
src/main/resources/static/index.html
Normal file
182
src/main/resources/static/index.html
Normal file
@@ -0,0 +1,182 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<title>首页</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<script type="text/javascript" src="decimal/decimal.js"></script>
|
||||
<script type="text/javascript" src="moment/moment.js"></script>
|
||||
<script type="text/javascript" src="js/fortern.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default">
|
||||
<!-- 导航条 -->
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<!-- 导航条左边头部 -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
|
||||
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<!-- 登录页 -->
|
||||
<a class="navbar-brand" href="index.html">落星原</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<!-- 导航条中间部分 -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<!-- 左侧导航连接 -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="edit_article.html">添加新文章 <span class="sr-only">(current)</span></a></li>
|
||||
<li><a href="user_list.html">用户管理</a></li>
|
||||
<li><a href="article_list.html">文章管理</a></li>
|
||||
<li><a href="comment_list.html">评论管理</a></li>
|
||||
<li><a href="category_list.html">分类管理</a></li>
|
||||
<li><a href="donate_list.html">捐赠管理</a></li>
|
||||
</ul>
|
||||
<!-- 搜索框 -->
|
||||
<form class="navbar-form navbar-left">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input id="search_key" type="text" class="form-control" placeholder="Search">
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default" onclick="to_search()" id="search_btn">搜索</button>
|
||||
</form>
|
||||
<!-- 右侧导航连接 -->
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">操作 <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<!-- 个人中心 -->
|
||||
<li><a href="user.html">个人中心</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="show_donate()">捐赠</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a onclick="logout()">注销</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
<!-- 搭建显示页面 -->
|
||||
<div class="container">
|
||||
<!-- 标题 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>落星原论坛</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 按钮 -->
|
||||
<div class="row">
|
||||
<!-- 此列向右偏移 -->
|
||||
<!-- 宽度4,左间距8 -->
|
||||
<div class="col-md-4 col-md-offset-8">
|
||||
<button id="to_add" class="btn btn-primary" onclick="location.href='/edit_article.html'">发布文章</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示文章信息 -->
|
||||
<div class="row">
|
||||
<!-- 左侧分类占3列 -->
|
||||
<div class="col-md-3">
|
||||
<h3>分类</h3>
|
||||
<ul id="categories" class="list-unstyled">
|
||||
<li id="li_all">全部</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 右侧文章列表占7列 -->
|
||||
<div class="col-md-7">
|
||||
<h3>全部</h3>
|
||||
<div id="tops">
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<div id="articles">
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<div id="page_info_area">
|
||||
|
||||
</div>
|
||||
<div id="page_nav">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
let categories;
|
||||
let category = undefined;//当前页中显示数据的分类id
|
||||
$(function () {
|
||||
//加载分类列表
|
||||
$.ajax("/category/all", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
categories = result;
|
||||
for (const category of categories) {
|
||||
let num = searchStrEach(category.id, "_");
|
||||
let str = "";
|
||||
for (let i = 1; i < num; i++) {
|
||||
str += " ";
|
||||
}
|
||||
str += category.name;
|
||||
$("<li value='" + category.id + "'><a href='javascript:void(0);'>" + str + "</a></li>").appendTo("#categories");
|
||||
}
|
||||
}
|
||||
});
|
||||
$.ajax("/article/top", {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
build_article_list(result, $("#tops"));
|
||||
}
|
||||
});
|
||||
to_article_page(1, undefined);
|
||||
})
|
||||
|
||||
/**
|
||||
* 构建某一页的数据
|
||||
*
|
||||
* @param pn 页码
|
||||
* @param category 带查的分类id
|
||||
*/
|
||||
function to_article_page(pn, category) {
|
||||
let url;
|
||||
if(category === undefined)
|
||||
url = "/article/notTop/" + pn;
|
||||
else
|
||||
url = "/article/category/" + category + "/" + pn;
|
||||
$.ajax(url, {
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (result) {
|
||||
build_article_list(result.records, $("#articles"));
|
||||
let page_info = build_page_info(result.pageIndex, result.pageSize, result.totalCount);
|
||||
$("#page_info_area").empty().append("当前" + page_info.page + "页,共" + page_info.pages + "页,共" + page_info.total + "条记录");
|
||||
build_page_nav(page_info, $("#page_nav"));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//给分页条上的li绑定点击事件
|
||||
$(document).on("click", "#page_nav li:not('.disabled,.active')", function () {
|
||||
to_article_page($(this).val(), category);
|
||||
});
|
||||
|
||||
//给分类表上的li绑定点击事件
|
||||
$(document).on("click", "#categories li", function () {
|
||||
to_article_page(1, $(this).attr("value"));
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
556
src/main/resources/static/index2.html
Normal file
556
src/main/resources/static/index2.html
Normal file
@@ -0,0 +1,556 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<title>员工列表</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<script type="text/javascript" src="decimal/decimal.js"></script>
|
||||
<script type="text/javascript" src="moment/moment.js"></script>
|
||||
<script type="text/javascript" src="js/fortern.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="emp_update_modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">修改员工信息</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="update_employee_form" class="form-horizontal" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<label for="emp_id_static" class="col-sm-2 control-label">ID</label>
|
||||
<div class="col-sm-10">
|
||||
<p id="emp_id_static" class="form-control-static"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="update_name" class="col-sm-2 control-label">姓名</label>
|
||||
<div class="col-sm-10 has-feedback">
|
||||
<input id="update_name" name="name" type="text" data-validated="0" class="form-control"
|
||||
placeholder="员工姓名">
|
||||
<span class="help-block"></span>
|
||||
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<label for="update_email" class="col-sm-2 control-label">Email</label>
|
||||
<div class="col-sm-10">
|
||||
<!-- 自定义data-validated属性,0表示校验不通过,1表示校验通过,2表示等待校验结果 -->
|
||||
<input id="update_email" name="email" type="email" data-validated="0" class="form-control"
|
||||
placeholder="Email">
|
||||
<span class="help-block"></span>
|
||||
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">性别</label>
|
||||
<div class="col-sm-10">
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="gender" id="update_gender_M" value="M" checked="checked"> 男
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="gender" id="update_gender_F" value="F"> 女
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="update_department" class="col-sm-2 control-label">部门</label>
|
||||
<div class="col-sm-4">
|
||||
<select class="form-control" name="deptId" id="update_department">
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
|
||||
<button id="emp_update_btn" type="button" class="btn btn-primary">更新</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 搭建显示页面 -->
|
||||
<div class="container">
|
||||
<!-- 标题 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>落星原论坛</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 按钮 -->
|
||||
<div class="row">
|
||||
<!-- 此列向右偏移 -->
|
||||
<!-- 宽度4,左间距8 -->
|
||||
<div class="col-md-4 col-md-offset-8">
|
||||
<button id="emp_add_btn" class="btn btn-primary">A</button>
|
||||
<button id="emps_del_btn" class="btn btn-danger">B</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示表格数据库 -->
|
||||
<div class="row">
|
||||
<!-- 左侧分类占3列 -->
|
||||
<div class="col-md-3">
|
||||
<ul>
|
||||
<li>1</li>
|
||||
<li>1</li>
|
||||
<li>1</li>
|
||||
<li>
|
||||
<ul>
|
||||
<li>2</li>
|
||||
<li>2</li>
|
||||
<li>2</li>
|
||||
<li>2</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>1</li>
|
||||
<li>1</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 右侧文章列表占7列 -->
|
||||
<div class="col-md-7">
|
||||
2
|
||||
</div>
|
||||
</div>
|
||||
<!-- 显示分页信息 -->
|
||||
<div class="row">
|
||||
<!-- 分页信息 -->
|
||||
<div id="page_info_area" class="col-md-6">
|
||||
|
||||
</div>
|
||||
<div id="page_nav" class="col-md-6">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
let pages;//全局变量,总页数
|
||||
let page;//当前页码
|
||||
//1、页面加载完成以后,直接发送ajax请求,要到分页数据
|
||||
$(function () {
|
||||
//to_page(1);
|
||||
});
|
||||
|
||||
function to_page(pn) {
|
||||
$.ajax({
|
||||
url: "${app_path}/emps",
|
||||
data: "pageNumber=" + pn,
|
||||
type: "GET",
|
||||
success: function (result) {
|
||||
//1、解析并显示员工数据
|
||||
build_emps_table(result);
|
||||
//2、解析并显示分页信息
|
||||
build_page_info(result);
|
||||
//3、解析显示分页条数据
|
||||
build_page_nav(result);
|
||||
},
|
||||
fail: function () {
|
||||
console.log("获取数据失败!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function build_emps_table(result) {
|
||||
//先清空原有数据
|
||||
$("#emps_table tbody").empty();
|
||||
$("#check_all").prop("checked", false);
|
||||
var emps = result.extend.pageInfo.list;
|
||||
$.each(emps, function (index, item) {
|
||||
var checkBoxTd = $("<td></td>").append("<input type='checkbox' class='check_item'/>");
|
||||
var empIdTd = $("<td></td>").append(item.id);
|
||||
var empNameTd = $("<td></td>").append(item.name);
|
||||
var genderTd = $("<td></td>").append(item.gender == "M" ? "男" : "女");
|
||||
var emailTd = $("<td></td>").append(item.email);
|
||||
var deptNameTd = $("<td></td>").append(item.department.deptName);
|
||||
var editBtn = $("<button></button>").addClass("btn btn-primary btn-sm edit_btn")
|
||||
.append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
|
||||
.append("编辑");
|
||||
var delBtn = $("<button></button>").addClass("btn btn-danger btn-sm del_btn")
|
||||
.append($("<span></span>").addClass("glyphicon glyphicon-trash"))
|
||||
.append("删除");
|
||||
var btnTd = $("<td></td>").append(editBtn).append(" ").append(delBtn);
|
||||
$("<tr></tr>").attr("data-id", item.id).append(checkBoxTd)
|
||||
.append(empIdTd)
|
||||
.append(empNameTd)
|
||||
.append(genderTd)
|
||||
.append(emailTd)
|
||||
.append(deptNameTd)
|
||||
.append(btnTd)
|
||||
.appendTo("#emps_table tbody");
|
||||
});
|
||||
}
|
||||
|
||||
function build_page_info(result) {
|
||||
$("#page_info_area").empty();
|
||||
$("#page_info_area").append("当前" + result.extend.pageInfo.pageNum + "页,共" +
|
||||
result.extend.pageInfo.pages + "页,共" +
|
||||
result.extend.pageInfo.total + "条记录");
|
||||
pages = result.extend.pageInfo.pages;
|
||||
page = result.extend.pageInfo.pageNum;
|
||||
}
|
||||
|
||||
function build_page_nav(result) {
|
||||
$("#page_nav").empty();
|
||||
var ul = $("<ul></ul>").addClass("pagination");
|
||||
var firstPageLi = $("<li></li>").append($("<a></a>").append("首页"));
|
||||
var prePageLi = $("<li></li>").append($("<a></a>").append("«"));
|
||||
if (result.extend.pageInfo.hasPreviousPage === false) {
|
||||
firstPageLi.addClass("disabled");
|
||||
prePageLi.addClass("disabled");
|
||||
} else {
|
||||
firstPageLi.click(function () {
|
||||
to_page(1);
|
||||
});
|
||||
prePageLi.click(function () {
|
||||
to_page(result.extend.pageInfo.pageNum - 1);
|
||||
});
|
||||
}
|
||||
var lastPageLi = $("<li></li>").append($("<a></a>").append("末页"));
|
||||
var nextPageLi = $("<li></li>").append($("<a></a>").append("»"));
|
||||
if (result.extend.pageInfo.hasNextPage === false) {
|
||||
lastPageLi.addClass("disabled");
|
||||
nextPageLi.addClass("disabled");
|
||||
} else {
|
||||
nextPageLi.click(function () {
|
||||
to_page(result.extend.pageInfo.pageNum + 1);
|
||||
});
|
||||
lastPageLi.click(function () {
|
||||
to_page(result.extend.pageInfo.pages);
|
||||
});
|
||||
}
|
||||
ul.append(firstPageLi).append(prePageLi);
|
||||
$.each(result.extend.pageInfo.navigatepageNums, function (index, item) {
|
||||
//item的内容是navigatepageNums的每一项,即该按钮要去的页码
|
||||
var numLi = $("<li></li>").append($("<a></a>").append(item));
|
||||
if (result.extend.pageInfo.pageNum !== item) {
|
||||
numLi.click(function () {
|
||||
to_page(item);
|
||||
})
|
||||
} else {
|
||||
numLi.addClass("active");
|
||||
}
|
||||
ul.append(numLi);
|
||||
});
|
||||
ul.append(nextPageLi).append(lastPageLi);
|
||||
var navEle = $("<nav></nav>").append(ul);
|
||||
navEle.appendTo("#page_nav");
|
||||
}
|
||||
|
||||
//获取部门列表
|
||||
function get_depts(ele) {
|
||||
$(ele).empty();
|
||||
$.ajax({
|
||||
url: "${app_path}/depts",
|
||||
type: "GET",
|
||||
async: false,//同步
|
||||
success: function (result) {
|
||||
//模态框中只有一个select,所以可以定位到,但最好还是用id
|
||||
$.each(result.extend.departments, function () {
|
||||
var optionEle = $("<option></option>").append(this.deptName).attr("value", this.id);
|
||||
optionEle.appendTo(ele);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
//获取某个员工数据
|
||||
function get_emp(id) {
|
||||
$.ajax({
|
||||
url: "${app_path}/emp/" + id,
|
||||
type: "GET",
|
||||
success: function (result) {
|
||||
var emp = result.extend.emp;
|
||||
$("#emp_id_static").text(emp.id);
|
||||
$("#update_name").val(emp.name);
|
||||
$("#update_email").val(emp.email);
|
||||
$("#emp_update_modal input[name=gender]").val([emp.gender]);
|
||||
$("#emp_update_modal select").val([emp.deptId]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//数据校验
|
||||
function validate(input) {
|
||||
var reg;
|
||||
if (input.attr("id") == "inputName" || input.attr("id") == "update_name") {
|
||||
//姓名的正则表达式
|
||||
reg = /(^[\u2E80-\u9FFF]{2,6}$)|(^[ a-zA-Z]{5,20}$)/;
|
||||
} else {
|
||||
//邮箱的正则表达式
|
||||
reg = /^[A-Za-z0-9]+([-_.][A-Za-z]+)*@([A-Za-z0-9]+[-.])+[A-Za-zd]{2,5}$/;
|
||||
}
|
||||
//检查文本框中的内容是否符合正则表达式
|
||||
return reg.test(input.val());
|
||||
}
|
||||
|
||||
//检查邮箱是否重复
|
||||
function check_email(input) {
|
||||
if (input.val() === "" || !validate(input)) {
|
||||
//文本框变红
|
||||
input.parent().removeClass("has-success").addClass("has-error");
|
||||
//错误信息提示
|
||||
input.next("span").text("请输入正确的邮箱");
|
||||
//去掉对号,添加叉号
|
||||
input.next("span").next("span").removeClass("glyphicon-ok").addClass("glyphicon-remove");
|
||||
//设置校验状态为校验不通过
|
||||
input.attr("data-validated", "0");
|
||||
return;
|
||||
}
|
||||
console.log(input);
|
||||
console.log($("#update_email"));
|
||||
console.log(input.attr("id"));
|
||||
console.log($("#emp_id_static").text());
|
||||
console.log(input.attr("id") == "update_email");
|
||||
$.ajax({
|
||||
//运算符优先级很迷?加了层括号才正常
|
||||
url: "${app_path}/checkemail" + (input.attr("id") == "update_email" ? "/" + $("#emp_id_static").text() : ""),
|
||||
type: "GET",
|
||||
data: "email=" + input.val(),
|
||||
success: function (result) {
|
||||
if (result.code === 100) {
|
||||
//不需要提示文本
|
||||
input.next("span").text("");
|
||||
//文本框变绿色
|
||||
input.parent().removeClass("has-error").addClass("has-success");
|
||||
//去掉叉号图标,添加对号图标
|
||||
input.next("span").next("span").removeClass("glyphicon-remove").addClass("glyphicon-ok");
|
||||
//设置校验状态为1
|
||||
input.attr("data-validated", "1");
|
||||
} else {
|
||||
//文本框变红
|
||||
input.parent().removeClass("has-success").addClass("has-error");
|
||||
//错误信息提示
|
||||
input.next("span").text("该邮箱已存在");
|
||||
//去掉对号,添加叉号
|
||||
input.next("span").next("span").removeClass("glyphicon-ok").addClass("glyphicon-remove");
|
||||
//设置校验状态为校验不通过
|
||||
input.attr("data-validated", "0");
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
//文本框变红
|
||||
input.parent().removeClass("has-success").addClass("has-error");
|
||||
//错误信息提示
|
||||
input.next("span").text("获取服务端数据失败!");
|
||||
//去掉对号,添加叉号
|
||||
input.next("span").next("span").removeClass("glyphicon-ok").addClass("glyphicon-remove");
|
||||
//设置校验状态为校验不通过
|
||||
input.attr("data-validated", "0");
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function update_name_input(input) {
|
||||
if (validate(input)) {
|
||||
//不需要提示文本
|
||||
input.next("span").text("");
|
||||
//文本框变绿色
|
||||
input.parent().removeClass("has-error").addClass("has-success");
|
||||
//去掉叉号图标,添加对号图标
|
||||
input.next("span").next("span").removeClass("glyphicon-remove").addClass("glyphicon-ok");
|
||||
//设置校验状态为1
|
||||
input.attr("data-validated", "1");
|
||||
} else {
|
||||
//文本框变红
|
||||
input.parent().removeClass("has-success").addClass("has-error");
|
||||
//去掉对号变成叉号
|
||||
input.next("span").next("span").removeClass("glyphicon-ok").addClass("glyphicon-remove");
|
||||
//设置校验状态为0
|
||||
input.attr("data-validated", "0");
|
||||
//错误信息
|
||||
input.next("span").text("姓名必须是必须是2-6位汉字或3-15为字母与空格");
|
||||
}
|
||||
}
|
||||
|
||||
function update_email_input(input) {
|
||||
//设置校验状态为等待
|
||||
input.attr("data-validated", "2");
|
||||
//去掉文本框的颜色
|
||||
input.parent().removeClass("has-error has-success");
|
||||
input.next("span").text("检查中");
|
||||
//检查邮箱是否重复,剩下的交给check_email()操作 (不知道为啥check_email()不返回值)
|
||||
check_email(input);
|
||||
}
|
||||
|
||||
//重置文本框
|
||||
function reset_input(input1, input2) {
|
||||
input1.val("");
|
||||
input1.parent().removeClass("has-success");
|
||||
input1.next("span").next("span").removeClass("glyphicon-ok");
|
||||
input2.val("");
|
||||
input2.parent().removeClass("has-success");
|
||||
input2.next("span").next("span").removeClass("glyphicon-ok");
|
||||
}
|
||||
|
||||
//为新增按钮添加绑定事件
|
||||
$("#emp_add_btn").click(function () {
|
||||
//先发送ajax请求查出部门信息,显示在下拉列表
|
||||
get_depts("#emp_add_modal select");
|
||||
//弹出模态框
|
||||
$('#emp_add_modal').modal({
|
||||
backdrop: 'static'
|
||||
});
|
||||
});
|
||||
//为保存按钮添加绑定事件
|
||||
$("#emp_save_btn").click(function () {
|
||||
const a = $("#inputName").attr("data-validated");
|
||||
const b = $("#inputEmail").attr("data-validated");
|
||||
if (a === "0") {
|
||||
update_name_input($("#inputName"), $("#inputEmail"));
|
||||
}
|
||||
if (b === "0") {
|
||||
update_email_input();
|
||||
}
|
||||
if (a !== "1" || b !== "1") {
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url: "${app_path}/emp",
|
||||
type: "POST",
|
||||
data: $("#emp_add_modal form").serialize(), //序列化表单中的数据为字符串
|
||||
success: function (result) {
|
||||
if (result.code === 100) {
|
||||
reset_input($("#inputName"), $("#inputEmail"));
|
||||
//关闭模态框
|
||||
$('#emp_add_modal').modal('hide');
|
||||
//来到最后一页
|
||||
to_page(pages + 1);
|
||||
} else {
|
||||
//如果错误信息不是未定义
|
||||
if (undefined != result.extend.errorFields.name) {
|
||||
//文本框变红
|
||||
$("#inputName").parent().removeClass("has-success").addClass("has-error");
|
||||
//去掉对号变成叉号
|
||||
$("#inputName").next("span").next("span").removeClass("glyphicon-ok").addClass("glyphicon-remove");
|
||||
//设置校验状态为0
|
||||
$("#inputName").attr("data-validated", "0");
|
||||
//错误信息
|
||||
$("#inputName").next("span").text("姓名必须是必须是2-6位汉字或3-15为字母与空格");
|
||||
}
|
||||
if (undefined != result.extend.errorFields.name) {
|
||||
//文本框变红
|
||||
$("#inputEmail").parent().removeClass("has-success").addClass("has-error");
|
||||
//错误信息提示
|
||||
$("#inputEmail").next("span").text("邮箱格式不正确");
|
||||
//去掉对号,添加叉号
|
||||
$("#inputEmail").next("span").next("span").removeClass("glyphicon-ok").addClass("glyphicon-remove");
|
||||
//设置校验状态为校验不通过
|
||||
$("#inputEmail").attr("data-validated", "0");
|
||||
}
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
alert("提交失败,请检查网络");
|
||||
}
|
||||
})
|
||||
})
|
||||
//更新按钮点击事件
|
||||
$("#emp_update_btn").click(function () {
|
||||
var a = $("#update_name").attr("data-validated");
|
||||
var b = $("#update_email").attr("data-validated");
|
||||
if (a == "0") {
|
||||
update_name_input($("#update_name"));
|
||||
}
|
||||
if (b == "0") {
|
||||
update_email_input($("#update_email"));
|
||||
}
|
||||
if (a != "1" || b != "1") {
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url: "${app_path}/emp/" + $("#emp_id_static").text(),
|
||||
type: "PUT",
|
||||
data: $("#emp_update_modal form").serialize(), //序列化表单中的数据为字符串
|
||||
success: function (result) {
|
||||
alert(result.msg);
|
||||
if (result.code == 100) {
|
||||
reset_input($("#update_name"), $("#update_email"));
|
||||
//关闭模态框
|
||||
$('#emp_update_modal').modal('hide');
|
||||
//来到最后一页
|
||||
to_page(page);
|
||||
} else {
|
||||
alert("数据校验不通过,请检查");
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
console.log("没有返回数据,请检查网络");
|
||||
}
|
||||
});
|
||||
});
|
||||
//姓名框失去焦点事件
|
||||
$("#inputName,#update_name").focusout(function () {
|
||||
update_name_input($(this));
|
||||
})
|
||||
//邮箱输入框失去焦点事件
|
||||
$("#inputEmail,#update_email").focusout(function () {
|
||||
update_email_input($(this));
|
||||
})
|
||||
//给后来新增的“编辑”按钮绑定单击事件
|
||||
$(document).on("click", ".edit_btn", function () {
|
||||
//0、重置模态框
|
||||
reset_input($("#update_name"), $("#update_email"));
|
||||
//1、查出部门信息,显示部门列表
|
||||
get_depts("#emp_update_modal select");
|
||||
//this是当前被点击的按钮
|
||||
//获取当前tr标签的data-id属性
|
||||
get_emp($(this).parent().parent().attr("data-id"));
|
||||
$("#emp_update_modal").modal({
|
||||
backdrop: "static"
|
||||
});
|
||||
})
|
||||
//给后来出现的“删除”按钮添加绑定事件
|
||||
$(document).on("click", ".del_btn", function () {
|
||||
var emp_name = $(this).parent().parent().find("td:eq(2)").text();
|
||||
if (confirm("确认删除【" + emp_name + "】吗?")) {
|
||||
$.ajax({
|
||||
url: "${app_path}/emp/" + $(this).parent().parent().attr("data-id"),
|
||||
type: "DELETE",
|
||||
success: function (result) {
|
||||
alert(result.msg);
|
||||
to_page(page);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
//给后来出现的“复选框”添加绑定事件
|
||||
$(document).on("click", ".check_item", function () {
|
||||
//判断全选框里是不是要有钩
|
||||
var flag = $(".check_item:checked").length == $(".check_item").length;
|
||||
$("#check_all").prop("checked", flag);
|
||||
})
|
||||
//全选
|
||||
$("#check_all").click(function () {
|
||||
//prop修改和获取原声属性的值
|
||||
//将所有复选框的checked属性设为和被点击的那个相同
|
||||
$(".check_item").prop("checked", $(this).prop("checked"));
|
||||
})
|
||||
//给“部分删除”按钮添加绑定事件
|
||||
$("#emps_del_btn").click(function () {
|
||||
var emp_ids = "";
|
||||
$.each($(".check_item:checked"), function () {
|
||||
emp_ids += $(this).parents("tr").find("td:eq(1)").text() + "-";
|
||||
})
|
||||
emp_ids = emp_ids.substring(0, emp_ids.length - 1);
|
||||
if (confirm("确认删除所选项吗?")) {
|
||||
$.ajax({
|
||||
url: "${app_path}/emp/" + emp_ids,
|
||||
type: "DELETE",
|
||||
success: function (result) {
|
||||
alert(result.msg);
|
||||
to_page(page);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
//“编辑模态框”的关闭按钮点击事件
|
||||
|
||||
//
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
2729
src/main/resources/static/jquery/jquery-1.12.4.min.js
vendored
Normal file
2729
src/main/resources/static/jquery/jquery-1.12.4.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2595
src/main/resources/static/jquery/jquery-3.6.0.min.js
vendored
Normal file
2595
src/main/resources/static/jquery/jquery-3.6.0.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
174
src/main/resources/static/js/fortern.js
Normal file
174
src/main/resources/static/js/fortern.js
Normal file
@@ -0,0 +1,174 @@
|
||||
let time_format = "YYYY-MM-DD HH:mm:ss";
|
||||
|
||||
//获取地址栏参数
|
||||
function getUrlParam(name) {
|
||||
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
|
||||
let r = window.location.search.substr(1).match(reg); //匹配目标参数
|
||||
if (r != null) return decodeURI(r[2]);
|
||||
return null; //返回参数值
|
||||
}
|
||||
|
||||
//构建文章列表
|
||||
function build_article_list(articles, position) {
|
||||
position.empty();
|
||||
$.each(articles, function (index, item) {
|
||||
let h = $("<h4><a href='article_detail.html?aid=" + item.id + "'>" + item.title + "</a><span>" + (item.top ? " [置顶]" : "") + "</span></h4>");
|
||||
let p1 = $("<p></p>").append(item.summary);
|
||||
let p2 = $("<p></p>").append("<span>分类:" + item.category.name + "</span><br>").append("<span>" + item.simpleUser.username + "</span> 最后修改于 <span>" + moment(new Date(item.lastEditTime)).format(time_format) + "</span>");
|
||||
$("<div></div>").css("padding-bottom", "3px").css("padding-top", "3px").append(h).append(p1).append(p2).appendTo(position);
|
||||
});
|
||||
}
|
||||
|
||||
//构建分页数据
|
||||
function build_page_info(pageIndex, pageSize, totalCount) {
|
||||
let _pages = Math.floor((totalCount - 1) / pageSize) + 1;
|
||||
let result = {
|
||||
page: pageIndex,
|
||||
size: pageSize,
|
||||
total: totalCount,
|
||||
pages: _pages,
|
||||
hasPreviousPage: pageIndex !== 1,
|
||||
hasNextPage: pageIndex < _pages,
|
||||
beforePages: [],
|
||||
afterPages: [],
|
||||
}
|
||||
for (let i = (pageIndex <= 3 ? 1 : pageIndex - 2); i < pageIndex; i++) {
|
||||
result.beforePages.push(i);
|
||||
}
|
||||
for (let i = pageIndex + 1; i <= (pageIndex <= result.pages - 2 ? pageIndex + 2 : _pages); i++) {
|
||||
result.afterPages.push(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//构建分页条
|
||||
function build_page_nav(page_info, position) {
|
||||
position.empty();
|
||||
let ul = $("<ul></ul>").addClass("pagination");
|
||||
let firstPageLi = $("<li></li>").append("<a>首页</a>").val(1);
|
||||
let prePageLi = $("<li></li>").append($("<a></a>").append("«")).val(page_info.page - 1);
|
||||
if (!page_info.hasPreviousPage) {
|
||||
firstPageLi.addClass("disabled");
|
||||
prePageLi.addClass("disabled");
|
||||
}
|
||||
let lastPageLi = $("<li></li>").append($("<a></a>").append("末页")).val(page_info.pages);
|
||||
let nextPageLi = $("<li></li>").append($("<a></a>").append("»")).val(page_info.page + 1);
|
||||
if (page_info.hasNextPage === false) {
|
||||
lastPageLi.addClass("disabled");
|
||||
nextPageLi.addClass("disabled");
|
||||
}
|
||||
ul.append(firstPageLi).append(prePageLi);
|
||||
$.each(page_info.beforePages, function (index, item) {
|
||||
let numLi = $("<li></li>").append("<a>" + item + "</a>").val(item);
|
||||
numLi.appendTo(ul);
|
||||
});
|
||||
ul.append("<li class='active'><a>" + page_info.page + "</a></li>");
|
||||
$.each(page_info.afterPages, function (index, item) {
|
||||
let numLi = $("<li></li>").append("<a>" + item + "</a>").val(item);
|
||||
numLi.appendTo(ul);
|
||||
});
|
||||
ul.append(nextPageLi).append(lastPageLi);
|
||||
let navEle = $("<nav></nav>").append(ul);
|
||||
navEle.appendTo(position);
|
||||
}
|
||||
|
||||
//注销
|
||||
function logout() {
|
||||
$.ajax("/logout", {
|
||||
type: "POST",
|
||||
success: function () {
|
||||
$(window).attr('location', '/login.html');
|
||||
},
|
||||
statusCode: {
|
||||
403: function () {
|
||||
$(window).attr('location', '/login.html');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//检查是否已登录
|
||||
function check_login() {
|
||||
$.ajax({
|
||||
url: "/account/online",
|
||||
type: "GET",
|
||||
async: false,
|
||||
statusCode: {
|
||||
403: function () {
|
||||
$(window).attr('location', '/login.html');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* str { String } 完整字符串
|
||||
* target { String } 目标对象,要查找的字符串
|
||||
*/
|
||||
function searchStrEach(str, target) {
|
||||
let sum = 0;
|
||||
for (let key of str) {
|
||||
if (key == target) {
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取邮箱验证码
|
||||
*/
|
||||
function getCode(flag) {
|
||||
let _data = "email=" + $("#new_email").val();
|
||||
let btn = $(this);
|
||||
btn.attr("disabled", true);
|
||||
if (flag) {
|
||||
_data += "qq=" + $("#qq_number").val() + "&signup_code=" + $("#signup_code").val() + "&signup=true";
|
||||
} else {
|
||||
_data += "&signup=false";
|
||||
}
|
||||
$.ajax("/account/email_code", {
|
||||
type: "POST",
|
||||
data: _data,
|
||||
dataType: 'json',
|
||||
success: function () {
|
||||
toastr.success("邮件已发送,请查收");
|
||||
setTimeout(function () {
|
||||
btn.attr('disabled', false);
|
||||
}, 30000);
|
||||
},
|
||||
statusCode: {
|
||||
400: function (XMLHttpRequest) {
|
||||
toastr.warning(XMLHttpRequest.responseJSON);
|
||||
btn.attr('disabled', true);
|
||||
},
|
||||
401: function (XMLHttpRequest) {
|
||||
toastr.warning(XMLHttpRequest.responseJSON);
|
||||
btn.attr('disabled', true);
|
||||
},
|
||||
403: function (XMLHttpRequest) {
|
||||
toastr.warning(XMLHttpRequest.responseJSON);
|
||||
btn.attr('disabled', true);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//显示捐赠模态框
|
||||
function show_donate() {
|
||||
$("#donate_form")[0].reset();
|
||||
$("#donate_modal").modal({
|
||||
backdrop: "static"
|
||||
});
|
||||
}
|
||||
|
||||
//捐赠表单提交点击事件
|
||||
$("#donate_btn").on("click", function () {
|
||||
$("#donate_form").submit();
|
||||
});
|
||||
|
||||
//搜索按钮点击事件
|
||||
function to_search() {
|
||||
$(window).attr("location","/search.html?key=" + $("#search_key").val());
|
||||
}
|
||||
51
src/main/resources/static/login.html
Normal file
51
src/main/resources/static/login.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>登录</title>
|
||||
<script type="text/javascript" src="jquery/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="toastr/toastr.min.js"></script>
|
||||
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="toastr/toastr.min.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<form id="login_form">
|
||||
<div class="form-group">
|
||||
<label for="login_name">登录名</label>
|
||||
<input type="text" class="form-control" id="login_name" placeholder="用户名/邮箱">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">密码</label>
|
||||
<input type="password" class="form-control" id="password" placeholder="密码">
|
||||
</div>
|
||||
<input class="btn btn-default" type="button" value="登录" onclick="login()">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
function login() {
|
||||
$.ajax("/account/login", {
|
||||
type: "POST",
|
||||
data: "login_name=" + $("#login_name").val() + "&password=" + $("#password").val(),
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
$(window).attr('location','/index.html');
|
||||
},
|
||||
statusCode: {
|
||||
401: function (XMLHttpRequest) {
|
||||
toastr.warning(XMLHttpRequest.responseJSON);
|
||||
},
|
||||
403: function () {
|
||||
toastr.warning("再次登录前请先注销");
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
4602
src/main/resources/static/moment/moment.js
Normal file
4602
src/main/resources/static/moment/moment.js
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user