فهرست منبع

1. 新增企业实体类、服务类
2. 新增公司实体类、服务类
3. 新增企业一览页面
4. 完善前端页面

王育民 5 سال پیش
والد
کامیت
7144aef8d7
24فایلهای تغییر یافته به همراه831 افزوده شده و 15 حذف شده
  1. 61 0
      src/main/java/cn/minbb/job/controller/web/CompanyController.java
  2. 3 1
      src/main/java/cn/minbb/job/data/Const.java
  3. 52 0
      src/main/java/cn/minbb/job/model/Company.java
  4. 37 0
      src/main/java/cn/minbb/job/model/Industry.java
  5. 37 1
      src/main/java/cn/minbb/job/model/Resume.java
  6. 13 0
      src/main/java/cn/minbb/job/model/repository/CompanyRepository.java
  7. 7 0
      src/main/java/cn/minbb/job/model/repository/IndustryRepository.java
  8. 7 0
      src/main/java/cn/minbb/job/model/repository/ResumeRepository.java
  9. 17 0
      src/main/java/cn/minbb/job/service/CompanyService.java
  10. 11 0
      src/main/java/cn/minbb/job/service/IndustryService.java
  11. 4 0
      src/main/java/cn/minbb/job/service/ResumeService.java
  12. 49 0
      src/main/java/cn/minbb/job/service/impl/CompanyServiceImpl.java
  13. 33 0
      src/main/java/cn/minbb/job/service/impl/IndustryServiceImpl.java
  14. 15 0
      src/main/java/cn/minbb/job/service/impl/ResumeServiceImpl.java
  15. 31 0
      src/main/java/cn/minbb/job/util/PageHelper.java
  16. 112 0
      src/main/resources/templates/companies.html
  17. 120 0
      src/main/resources/templates/company.html
  18. 3 2
      src/main/resources/templates/fragments/footer.html
  19. 3 0
      src/main/resources/templates/fragments/header.html
  20. 4 5
      src/main/resources/templates/index.html
  21. 89 1
      src/main/resources/templates/job-full.html
  22. 98 1
      src/main/resources/templates/job-practice.html
  23. 23 2
      src/main/resources/templates/register.html
  24. 2 2
      src/main/resources/templates/sign-in.html

+ 61 - 0
src/main/java/cn/minbb/job/controller/web/CompanyController.java

@@ -0,0 +1,61 @@
+package cn.minbb.job.controller.web;
+
+import cn.minbb.job.data.Const;
+import cn.minbb.job.model.Company;
+import cn.minbb.job.model.Industry;
+import cn.minbb.job.service.CompanyService;
+import cn.minbb.job.service.IndustryService;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.data.domain.Page;
+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.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
+import java.util.List;
+
+@Controller
+@Log4j2
+@RequestMapping("/company")
+public class CompanyController {
+
+    private final CompanyService companyService;
+    private final IndustryService industryService;
+
+    public CompanyController(CompanyService companyService, IndustryService industryService) {
+        this.companyService = companyService;
+        this.industryService = industryService;
+    }
+
+    @GetMapping("")
+    public ModelAndView companyPage(
+            @RequestParam(name = "id", required = false) Integer id,
+            @RequestParam(name = "industry", required = false) Integer industryId,
+            @RequestParam(name = "page", defaultValue = "1", required = false) Integer page,
+            @RequestParam(name = "size", defaultValue = "12", required = false) Integer size,
+            ModelAndView modelAndView) {
+        Company company = companyService.findOneById(id);
+        if (null == company) {
+            List<Industry> industryList = industryService.findAll();
+            Industry industry = industryService.findOneById(industryId);
+            Page<Company> companyPage;
+            if (null != industry) {
+                companyPage = companyService.findAllByIndustryIn(industry, page, size);
+            } else {
+                companyPage = companyService.findAll(page, size);
+            }
+            List<Company> companyList = companyPage.getContent();
+            modelAndView.addObject("companyList", companyList);
+            modelAndView.addObject("industryList", industryList);
+            modelAndView.addObject(Const.Key.KEY_PAGE, companyPage.getNumber() + 1);
+            modelAndView.addObject(Const.Key.KEY_TOTAL_PAGES, companyPage.getTotalPages());
+            modelAndView.addObject(Const.Key.KEY_ACTIVE, Const.ViewName.VIEW_COMPANIES);
+            modelAndView.setViewName(Const.ViewName.VIEW_COMPANIES);
+        } else {
+            modelAndView.addObject("company", company);
+            modelAndView.setViewName(Const.ViewName.VIEW_COMPANY);
+        }
+        return modelAndView;
+    }
+}

+ 3 - 1
src/main/java/cn/minbb/job/data/Const.java

@@ -50,6 +50,8 @@ public class Const {
         String VIEW_ABOUT = "about";
         String VIEW_JOB_FULL = "job-full";
         String VIEW_JOB_PRACTICE = "job-practice";
+        String VIEW_COMPANY = "company";
+        String VIEW_COMPANIES = "companies";
         String VIEW_FEEDBACK = "feedback";
     }
 
@@ -62,7 +64,7 @@ public class Const {
         String KEY_TITLE = "TITLE";
         String KEY_SUBTITLE = "SUBTITLE";
         String KEY_PAGE = "PAGE";
-        String KEY_TOTAL = "TOTAL";
+        String KEY_TOTAL_PAGES = "TOTAL_PAGES";
         String KEY_APP_NAME = "APP_NAME";
         String KEY_DATA = "DATA";
         String KEY_DATASET = "DATASET";

+ 52 - 0
src/main/java/cn/minbb/job/model/Company.java

@@ -0,0 +1,52 @@
+package cn.minbb.job.model;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.util.List;
+
+/**
+ * 企业
+ */
+@Data
+@Entity
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@Table(name = "company",
+        indexes = {
+                @Index(name = "index_name", columnList = "name")
+        }
+)
+public class Company extends Auditable {
+
+    @Column(name = "name", nullable = false, columnDefinition = "VARCHAR(32) COMMENT '标题'")
+    private String name;
+
+    @Column(name = "brand", nullable = false, columnDefinition = "VARCHAR(255) COMMENT '商标'")
+    private String brand;
+
+    @Column(name = "introduction", columnDefinition = "VARCHAR(500) COMMENT '简介'")
+    private String introduction;
+
+    @Column(name = "description", columnDefinition = "VARCHAR(1000) COMMENT '描述'")
+    private String description;
+
+    @Column(name = "priority", columnDefinition = "INT COMMENT '优先级'")
+    private Integer priority;
+
+    @Column(name = "is_enabled", nullable = false, columnDefinition = "TINYINT DEFAULT '1' COMMENT '启用'")
+    private Boolean isEnabled;
+
+    @ManyToMany(cascade = {CascadeType.MERGE})
+    @JoinTable(name = "company_industry",
+            joinColumns = {@JoinColumn(name = "company_id", referencedColumnName = "id", columnDefinition = "INT COMMENT '企业ID'")},
+            inverseJoinColumns = {@JoinColumn(name = "industry_id", referencedColumnName = "id", columnDefinition = "INT COMMENT '行业ID'")},
+            indexes = {
+                    @Index(name = "index_company_id", columnList = "company_id"),
+                    @Index(name = "index_industry_id", columnList = "industry_id")
+            }
+    )
+    private List<Industry> industryList;
+}

+ 37 - 0
src/main/java/cn/minbb/job/model/Industry.java

@@ -0,0 +1,37 @@
+package cn.minbb.job.model;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Index;
+import javax.persistence.Table;
+
+/**
+ * 行业
+ */
+@Data
+@Entity
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@Table(name = "industry",
+        indexes = {
+                @Index(name = "index_name", columnList = "name")
+        }
+)
+public class Industry extends Auditable {
+
+    @Column(name = "name", nullable = false, columnDefinition = "VARCHAR(32) COMMENT '标题'")
+    private String name;
+
+    @Column(name = "description", columnDefinition = "VARCHAR(1000) COMMENT '描述'")
+    private String description;
+
+    @Column(name = "priority", columnDefinition = "INT COMMENT '优先级'")
+    private Integer priority;
+
+    @Column(name = "is_enabled", nullable = false, columnDefinition = "TINYINT DEFAULT '1' COMMENT '启用'")
+    private Boolean isEnabled;
+}

+ 37 - 1
src/main/java/cn/minbb/job/model/Resume.java

@@ -1,4 +1,40 @@
 package cn.minbb.job.model;
 
-public class Resume {
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Index;
+import javax.persistence.Table;
+
+/**
+ * 简历
+ */
+@Data
+@Entity
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@Table(name = "resume",
+        indexes = {
+                @Index(name = "index_name", columnList = "name")
+        }
+)
+public class Resume extends Auditable {
+
+    @Column(name = "name", nullable = false, columnDefinition = "VARCHAR(32) COMMENT '标题'")
+    private String name;
+
+    @Column(name = "photo", nullable = false, columnDefinition = "VARCHAR(255) COMMENT '照片'")
+    private String photo;
+
+    @Column(name = "age", columnDefinition = "INT COMMENT '年龄'")
+    private Integer age;
+
+    @Column(name = "description", columnDefinition = "VARCHAR(1000) COMMENT '描述'")
+    private String description;
+
+    @Column(name = "is_enabled", nullable = false, columnDefinition = "TINYINT DEFAULT '1' COMMENT '启用'")
+    private Boolean isEnabled;
 }

+ 13 - 0
src/main/java/cn/minbb/job/model/repository/CompanyRepository.java

@@ -0,0 +1,13 @@
+package cn.minbb.job.model.repository;
+
+import cn.minbb.job.model.Company;
+import cn.minbb.job.model.Industry;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface CompanyRepository extends JpaRepository<Company, Integer> {
+    Page<Company> findAllByIndustryListInAndIsEnabledTrue(List<Industry> industryList, Pageable pageable);
+}

+ 7 - 0
src/main/java/cn/minbb/job/model/repository/IndustryRepository.java

@@ -0,0 +1,7 @@
+package cn.minbb.job.model.repository;
+
+import cn.minbb.job.model.Industry;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface IndustryRepository extends JpaRepository<Industry, Integer> {
+}

+ 7 - 0
src/main/java/cn/minbb/job/model/repository/ResumeRepository.java

@@ -0,0 +1,7 @@
+package cn.minbb.job.model.repository;
+
+import cn.minbb.job.model.Resume;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface ResumeRepository extends JpaRepository<Resume, Integer> {
+}

+ 17 - 0
src/main/java/cn/minbb/job/service/CompanyService.java

@@ -0,0 +1,17 @@
+package cn.minbb.job.service;
+
+import cn.minbb.job.model.Company;
+import cn.minbb.job.model.Industry;
+import org.springframework.data.domain.Page;
+
+import java.util.List;
+
+public interface CompanyService {
+    Company findOneById(Integer id);
+
+    Page<Company> findAll(Integer page, Integer size);
+
+    Page<Company> findAllByIndustryIn(Industry industry, Integer page, Integer size);
+
+    Page<Company> findAllByIndustryListIn(List<Industry> industryList, Integer page, Integer size);
+}

+ 11 - 0
src/main/java/cn/minbb/job/service/IndustryService.java

@@ -0,0 +1,11 @@
+package cn.minbb.job.service;
+
+import cn.minbb.job.model.Industry;
+
+import java.util.List;
+
+public interface IndustryService {
+    Industry findOneById(Integer id);
+
+    List<Industry> findAll();
+}

+ 4 - 0
src/main/java/cn/minbb/job/service/ResumeService.java

@@ -0,0 +1,4 @@
+package cn.minbb.job.service;
+
+public interface ResumeService {
+}

+ 49 - 0
src/main/java/cn/minbb/job/service/impl/CompanyServiceImpl.java

@@ -0,0 +1,49 @@
+package cn.minbb.job.service.impl;
+
+import cn.minbb.job.model.Company;
+import cn.minbb.job.model.Industry;
+import cn.minbb.job.model.repository.CompanyRepository;
+import cn.minbb.job.service.CompanyService;
+import cn.minbb.job.util.PageHelper;
+import cn.minbb.job.util.SortTool;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class CompanyServiceImpl implements CompanyService {
+
+    private final CompanyRepository companyRepository;
+
+    public CompanyServiceImpl(CompanyRepository companyRepository) {
+        this.companyRepository = companyRepository;
+    }
+
+    @Override
+    public Company findOneById(Integer id) {
+        if (null == id) return null;
+        return companyRepository.findById(id).orElse(null);
+    }
+
+    @Override
+    public Page<Company> findAll(Integer page, Integer size) {
+        Company company = new Company();
+        company.setIsEnabled(Boolean.TRUE);
+        return companyRepository.findAll(Example.of(company), PageHelper.of(page, size, SortTool.priorityDown()));
+    }
+
+    @Override
+    public Page<Company> findAllByIndustryIn(Industry industry, Integer page, Integer size) {
+        List<Industry> industryList = new ArrayList<>(1);
+        industryList.add(industry);
+        return findAllByIndustryListIn(industryList, page, size);
+    }
+
+    @Override
+    public Page<Company> findAllByIndustryListIn(List<Industry> industryList, Integer page, Integer size) {
+        return companyRepository.findAllByIndustryListInAndIsEnabledTrue(industryList, PageHelper.of(page, size, SortTool.priorityDown()));
+    }
+}

+ 33 - 0
src/main/java/cn/minbb/job/service/impl/IndustryServiceImpl.java

@@ -0,0 +1,33 @@
+package cn.minbb.job.service.impl;
+
+import cn.minbb.job.model.Industry;
+import cn.minbb.job.model.repository.IndustryRepository;
+import cn.minbb.job.service.IndustryService;
+import cn.minbb.job.util.SortTool;
+import org.springframework.data.domain.Example;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class IndustryServiceImpl implements IndustryService {
+
+    private final IndustryRepository industryRepository;
+
+    public IndustryServiceImpl(IndustryRepository industryRepository) {
+        this.industryRepository = industryRepository;
+    }
+
+    @Override
+    public Industry findOneById(Integer id) {
+        if (null == id) return null;
+        return industryRepository.findById(id).orElse(null);
+    }
+
+    @Override
+    public List<Industry> findAll() {
+        Industry industry = new Industry();
+        industry.setIsEnabled(Boolean.TRUE);
+        return industryRepository.findAll(Example.of(industry), SortTool.priorityDown());
+    }
+}

+ 15 - 0
src/main/java/cn/minbb/job/service/impl/ResumeServiceImpl.java

@@ -0,0 +1,15 @@
+package cn.minbb.job.service.impl;
+
+import cn.minbb.job.model.repository.ResumeRepository;
+import cn.minbb.job.service.ResumeService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ResumeServiceImpl implements ResumeService {
+
+    private final ResumeRepository resumeRepository;
+
+    public ResumeServiceImpl(ResumeRepository resumeRepository) {
+        this.resumeRepository = resumeRepository;
+    }
+}

+ 31 - 0
src/main/java/cn/minbb/job/util/PageHelper.java

@@ -0,0 +1,31 @@
+package cn.minbb.job.util;
+
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+
+/**
+ * JPA 分页 - 页码从 0 开始
+ */
+public class PageHelper {
+
+    private PageHelper() {
+    }
+
+    public static Pageable of(Integer page, Integer size) {
+        page = formatParam(page - 1);
+        size = formatParam(size);
+        return PageRequest.of(page, size);
+    }
+
+    public static Pageable of(Integer page, Integer size, Sort sort) {
+        page = formatParam(page - 1);
+        size = formatParam(size);
+        return PageRequest.of(page, size, sort);
+    }
+
+    private static Integer formatParam(Integer param) {
+        if (null == param || param < 0) param = 0;
+        return param;
+    }
+}

+ 112 - 0
src/main/resources/templates/companies.html

@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/html"
+      xmlns:th="http://www.thymeleaf.org"
+      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+      layout:decorate="~{layouts/layout}">
+<head>
+    <meta charset="UTF-8"/>
+    <title>企业一览 - [[${APP_NAME}]]</title>
+
+    <style>
+        :root {
+            --jumbotron-padding-y: 1.5rem;
+        }
+
+        .jumbotron {
+            padding-top: var(--jumbotron-padding-y);
+            padding-bottom: var(--jumbotron-padding-y);
+            margin-bottom: 0;
+            background-color: #fff;
+        }
+
+        @media (min-width: 768px) {
+            .jumbotron {
+                padding-top: calc(var(--jumbotron-padding-y) * 2);
+                padding-bottom: calc(var(--jumbotron-padding-y) * 2);
+            }
+        }
+
+        .jumbotron p:last-child {
+            margin-bottom: 0;
+        }
+
+        .jumbotron-heading {
+            font-weight: 300;
+        }
+
+        .jumbotron .container {
+            max-width: 40rem;
+        }
+
+        .box-shadow {
+            box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
+        }
+    </style>
+</head>
+<body>
+<th:block layout:fragment="content">
+    <div class="container" th:if="${industryList.size() != 0}">
+        <div class="nav-scroller py-1 mb-2" style="margin-bottom: 0!important;">
+            <nav class="nav d-flex justify-content-between">
+                <a class="p-2 text-muted" th:each="industry, stat : ${industryList}" th:href="${'/company?industry=' + industry.getId()}" th:text="${industry.getName()}"></a>
+            </nav>
+        </div>
+    </div>
+
+    <div class="album py-5 bg-light">
+        <div class="container">
+            <div class="row">
+                <div class="col text-center" th:if="${companyList.size() == 0}">暂无数据</div>
+                <div class="col-sm-12 col-md-6 col-lg-4" th:each="company, stat : ${companyList}">
+                    <div class="card mb-4 box-shadow">
+                        <img class="card-img-top" data-src="holder.js/100px225?theme=thumb&amp;bg=55595c&amp;fg=eceeef&amp;text=Thumbnail" alt="Thumbnail [100%x225]"
+                             style="height: 225px; width: 100%; display: block;"
+                             src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22210%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20210%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_171aaebd1cf%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A11pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_171aaebd1cf%22%3E%3Crect%20width%3D%22210%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2267.9453125%22%20y%3D%22117.3%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"
+                             data-holder-rendered="true">
+                        <div class="card-body">
+                            <h2 th:text="${company.getName()}"></h2>
+                            <p class="card-text" style="height: 72px; overflow: hidden;" th:text="${company.getIntroduction()}"></p>
+                            <div class="d-flex justify-content-between align-items-center">
+                                <div class="btn-group">
+                                    <a class="btn btn-sm btn-outline-secondary" type="button" th:href="${'/company?id=' + company.getId()}">查看</a>
+                                </div>
+                                <small class="text-muted" th:text="${'热度:' + company.getPriority()}"></small>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <nav aria-label="Page navigation" style="margin-top: 24px;" th:if="${TOTAL_PAGES != 0}">
+                <ul class="pagination justify-content-center">
+                    <li class="page-item disabled">
+                        <a class="page-link" href="#!" tabindex="-1" th:href="${'?page=' + (PAGE - 1)}">&laquo;</a>
+                    </li>
+                    <li class="page-item" th:each="i : ${#numbers.sequence(1, TOTAL_PAGES)}" th:classappend="${PAGE == i}? 'active'">
+                        <a class="page-link" th:href="${'?page=' + i}" th:text="${i}">1</a>
+                    </li>
+                    <li class="page-item active">
+                        <a class="page-link" href="#!">2 <span class="sr-only"></span></a>
+                    </li>
+                    <li class="page-item"><a class="page-link" href="#!">3</a></li>
+                    <li class="page-item">
+                        <a class="page-link" href="#!" th:href="${'?page=' + (PAGE + 1)}">&raquo;</a>
+                    </li>
+                </ul>
+            </nav>
+        </div>
+    </div>
+
+    <section class="jumbotron text-center">
+        <div class="container">
+            <h1 class="jumbotron-heading">优秀企业合作</h1>
+            <p class="lead text-muted">如果您想在我们的平台长期招聘合作或使用更加优质的简历筛选功能,请联系我们!</p>
+            <p>
+                <a href="#" class="btn btn-primary my-2">长期招聘</a>
+                <a href="#" class="btn btn-secondary my-2">简历检索</a>
+            </p>
+        </div>
+    </section>
+</th:block>
+</body>
+</html>

+ 120 - 0
src/main/resources/templates/company.html

@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/html"
+      xmlns:th="http://www.thymeleaf.org"
+      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+      layout:decorate="~{layouts/layout}">
+<head>
+    <meta charset="UTF-8"/>
+    <title>[[${company.getName()}]] - [[${APP_NAME}]]</title>
+
+    <style>
+        .container {
+            max-width: 960px;
+        }
+
+        /*
+         * 自定义半透明网站标题
+         */
+        .site-header {
+            background-color: rgba(0, 0, 0, .85);
+            -webkit-backdrop-filter: saturate(180%) blur(20px);
+            backdrop-filter: saturate(180%) blur(20px);
+        }
+
+        .site-header a {
+            color: #999;
+            transition: ease-in-out color .15s;
+        }
+
+        .site-header a:hover {
+            color: #fff;
+            text-decoration: none;
+        }
+
+        /*
+         * 虚拟设备(用您自己的设备或其他完全替换的设备!)
+         */
+        .product-device {
+            position: absolute;
+            right: 10%;
+            bottom: -30%;
+            width: 300px;
+            height: 540px;
+            background-color: #333;
+            border-radius: 21px;
+            -webkit-transform: rotate(30deg);
+            transform: rotate(30deg);
+        }
+
+        .product-device::before {
+            position: absolute;
+            top: 10%;
+            right: 10px;
+            bottom: 10%;
+            left: 10px;
+            content: "";
+            background-color: rgba(255, 255, 255, .1);
+            border-radius: 5px;
+        }
+
+        .product-device-2 {
+            top: -25%;
+            right: auto;
+            bottom: 0;
+            left: 5%;
+            background-color: #e5e5e5;
+        }
+
+        .border-top {
+            border-top: 1px solid #e5e5e5;
+        }
+
+        .border-bottom {
+            border-bottom: 1px solid #e5e5e5;
+        }
+
+        .box-shadow {
+            box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
+        }
+
+        .flex-equal > * {
+            -ms-flex: 1;
+            -webkit-box-flex: 1;
+            flex: 1;
+        }
+
+        @media (min-width: 768px) {
+            .flex-md-equal > * {
+                -ms-flex: 1;
+                -webkit-box-flex: 1;
+                flex: 1;
+            }
+        }
+
+        .overflow-hidden {
+            overflow: hidden;
+        }
+    </style>
+</head>
+<body th:with="company=${company}">
+<th:block layout:fragment="content">
+    <div class="position-relative overflow-hidden p-3 p-md-5 m-md-3 text-center bg-light">
+        <div class="col-md-7 p-lg-5 mx-auto my-5" style="z-index: 1;">
+            <h1 class="display-4 font-weight-normal" th:text="${company.getName()}"></h1>
+            <p class="lead font-weight-normal" th:text="${company.getIntroduction()}"></p>
+            <a class="btn btn-outline-secondary" href="#!">支持我们</a>
+        </div>
+        <div class="product-device box-shadow d-none d-md-block"></div>
+        <div class="product-device product-device-2 box-shadow d-none d-md-block"></div>
+    </div>
+
+    <div class="container">
+        <div class="row">
+            <div class="col">
+                ...
+            </div>
+        </div>
+    </div>
+</th:block>
+</body>
+</html>

+ 3 - 2
src/main/resources/templates/fragments/footer.html

@@ -25,15 +25,16 @@
                     <li><a class="" href="/">系统管理</a></li>
                 </ul>
             </div>
-            <div class="col col-xs-12 col-sm-6 col-md-3 col-lg-2 offset-md-1 offset-lg-1">
+            <div class="col col-xs-12 col-sm-6 col-md-3 col-lg-2">
                 <h5>更多</h5>
                 <ul>
                     <li><a class="" href="/">招商引资</a></li>
+                    <li><a class="" href="/">长期合作</a></li>
                     <li><a class="" href="/">加入我们</a></li>
                 </ul>
             </div>
         </div>
-        <div class="row" id="tail" style="background-color: #111111; padding: 12px 16px; font-size: 14px;">
+        <div class="row" id="tail" style="background-color: #111111; padding: 12px 24px; font-size: 14px;">
             <span>&copy; 2020 <a href="/"> 校园招聘网</a></span>
             <div class="col text-right" style="padding: 0;"><a href="/">豫ICP备16029895号-6</a></div>
         </div>

+ 3 - 0
src/main/resources/templates/fragments/header.html

@@ -27,6 +27,9 @@
             <li class="nav-item" th:classappend="${ACTIVE == 'job-practice'}? 'active'">
                 <a class="nav-link" href="/job/practice">实习招聘</a>
             </li>
+            <li class="nav-item" th:classappend="${ACTIVE == 'companies'}? 'active'">
+                <a class="nav-link" href="/company/">企业一览</a>
+            </li>
             <li class="nav-item" th:class="${ACTIVE == 'about'}? 'active'">
                 <a class="nav-link" href="/about">关于</a>
             </li>

+ 4 - 5
src/main/resources/templates/index.html

@@ -84,8 +84,7 @@
     <!-- 首页轮播图 -->
     <div class="carousel slide" id="index-carousel" data-ride="carousel">
         <ol class="carousel-indicators">
-            <li data-target="#index-carousel" th:each="banner, stat : ${bannerList}"
-                th:data-slide-to="${stat.index}" th:class="${stat.index == 0}? 'active'"></li>
+            <li data-target="#index-carousel" th:each="banner, stat : ${bannerList}" th:data-slide-to="${stat.index}" th:class="${stat.index == 0}? 'active'"></li>
         </ol>
         <div class="carousel-inner">
             <div class="carousel-item" th:each="banner, stat : ${bannerList}" th:classappend="${stat.index == 0}? 'active'">
@@ -112,9 +111,9 @@
     <div class="container" style="margin-top: 24px;">
         <div class="row mb-2">
             <div class="col-md-12">
-                <h3 class="pb-3 mb-4 font-italic border-bottom">推荐公司</h3>
+                <h3 class="pb-3 mb-4 font-italic border-bottom">推荐企业</h3>
             </div>
-            <div class="col-md-6">
+            <div class="col-lg-6">
                 <div class="card flex-md-row mb-4 box-shadow h-md-250">
                     <div class="card-body d-flex flex-column align-items-start">
                         <strong class="d-inline-block mb-2 text-primary">IT/互联网</strong>
@@ -130,7 +129,7 @@
                          data-holder-rendered="true" style="width: 200px; height: 250px;">
                 </div>
             </div>
-            <div class="col-md-6">
+            <div class="col-lg-6">
                 <div class="card flex-md-row mb-4 box-shadow h-md-250">
                     <div class="card-body d-flex flex-column align-items-start">
                         <strong class="d-inline-block mb-2 text-success">通信/互联网</strong>

+ 89 - 1
src/main/resources/templates/job-full.html

@@ -10,7 +10,95 @@
 <body>
 <th:block layout:fragment="content">
     <div class="container">
-        全职招聘
+        <div class="row" style="margin-top: 24px;"></div>
+
+        <div class="row">
+            <div class="col-md-8">
+                <h3 class="pb-3 mb-4 font-italic border-bottom">全职职位</h3>
+
+                <div class="my-3 p-3 bg-white rounded box-shadow">
+                    <h5 class="border-bottom border-gray pb-2 mb-0">全职招聘</h5>
+                    <div class="media text-muted pt-3">
+                        <img data-src="holder.js/32x32?theme=thumb&amp;bg=007bff&amp;fg=007bff&amp;size=1" alt="32x32" class="mr-2 rounded"
+                             src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2232%22%20height%3D%2232%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_171a7c745cd%20text%20%7B%20fill%3A%23007bff%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A2pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_171a7c745cd%22%3E%3Crect%20width%3D%2232%22%20height%3D%2232%22%20fill%3D%22%23007bff%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2211.5390625%22%20y%3D%2216.9%22%3E32x32%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"
+                             data-holder-rendered="true" style="width: 32px; height: 32px;">
+                        <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
+                            <div class="d-flex justify-content-between align-items-center w-100">
+                                <strong class="text-gray-dark">解决方案专家</strong>
+                                <a href="#">查看</a>
+                            </div>
+                            <span class="d-block">解决方案专家</span>
+                        </div>
+                    </div>
+                    <div class="media text-muted pt-3">
+                        <img data-src="holder.js/32x32?theme=thumb&amp;bg=007bff&amp;fg=007bff&amp;size=1" alt="32x32" class="mr-2 rounded"
+                             src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2232%22%20height%3D%2232%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_171a7c745ce%20text%20%7B%20fill%3A%23007bff%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A2pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_171a7c745ce%22%3E%3Crect%20width%3D%2232%22%20height%3D%2232%22%20fill%3D%22%23007bff%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2211.5390625%22%20y%3D%2216.9%22%3E32x32%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"
+                             data-holder-rendered="true" style="width: 32px; height: 32px;">
+                        <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
+                            <div class="d-flex justify-content-between align-items-center w-100">
+                                <strong class="text-gray-dark">项目经理</strong>
+                                <a href="#">查看</a>
+                            </div>
+                            <span class="d-block">项目经理</span>
+                        </div>
+                    </div>
+                    <div class="media text-muted pt-3">
+                        <img data-src="holder.js/32x32?theme=thumb&amp;bg=007bff&amp;fg=007bff&amp;size=1" alt="32x32" class="mr-2 rounded"
+                             src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2232%22%20height%3D%2232%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_171a7c745ce%20text%20%7B%20fill%3A%23007bff%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A2pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_171a7c745ce%22%3E%3Crect%20width%3D%2232%22%20height%3D%2232%22%20fill%3D%22%23007bff%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2211.5390625%22%20y%3D%2216.9%22%3E32x32%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"
+                             data-holder-rendered="true" style="width: 32px; height: 32px;">
+                        <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
+                            <div class="d-flex justify-content-between align-items-center w-100">
+                                <strong class="text-gray-dark">销售总监</strong>
+                                <a href="#">查看</a>
+                            </div>
+                            <span class="d-block">销售总监</span>
+                        </div>
+                    </div>
+                    <small class="d-block text-right mt-3">
+                        <a href="/company">查看企业</a>
+                    </small>
+                </div>
+
+                <nav aria-label="Page navigation" style="margin-top: 24px;">
+                    <ul class="pagination justify-content-center">
+                        <li class="page-item disabled">
+                            <a class="page-link" href="#!" tabindex="-1">&laquo;</a>
+                        </li>
+                        <li class="page-item"><a class="page-link" href="#!">1</a></li>
+                        <li class="page-item active">
+                            <a class="page-link" href="#!">2 <span class="sr-only">(current)</span></a>
+                        </li>
+                        <li class="page-item"><a class="page-link" href="#!">3</a></li>
+                        <li class="page-item">
+                            <a class="page-link" href="#!">&raquo;</a>
+                        </li>
+                    </ul>
+                </nav>
+            </div>
+
+            <div class="col-md-4">
+                <div class="p-3">
+                    <h4 class="font-italic">推荐职位</h4>
+                    <ol class="list-unstyled mb-0">
+                        <li><a href="#">Java开发资深工程师</a></li>
+                        <li><a href="#">前端开发工程师</a></li>
+                        <li><a href="#">自动化运维</a></li>
+                        <li><a href="#">会计</a></li>
+                        <li><a href="#">销售总监</a></li>
+                        <li><a href="#">解决方案专家</a></li>
+                        <li><a href="#">项目经理</a></li>
+                    </ol>
+                </div>
+                <div class="p-3">
+                    <h4 class="font-italic">推荐企业</h4>
+                    <ol class="list-unstyled">
+                        <li><a href="#">南京亚信软件有限公司</a></li>
+                        <li><a href="#">中移在线服务有限公司</a></li>
+                        <li><a href="#">中国移动通信</a></li>
+                    </ol>
+                </div>
+            </div>
+        </div>
     </div>
 </th:block>
 </body>

+ 98 - 1
src/main/resources/templates/job-practice.html

@@ -6,11 +6,108 @@
 <head>
     <meta charset="UTF-8"/>
     <title>实习招聘 - [[${APP_NAME}]]</title>
+
+    <style>
+        .nav-scroller nav a {
+            padding: 8px 16px !important;
+        }
+    </style>
 </head>
 <body>
 <th:block layout:fragment="content">
     <div class="container">
-        实习招聘
+        <div class="nav-scroller py-1 mb-2" style="margin-bottom: 0!important;">
+            <nav class="nav d-flex">
+                <a class="p-2 text-muted" href="#">校园招聘</a>
+                <a class="p-2 text-muted" href="#">兼职实习</a>
+                <a class="p-2 text-muted" href="#">社会实践</a>
+                <a class="p-2 text-muted" href="#">无薪实习</a>
+            </nav>
+        </div>
+    </div>
+
+    <div class="container">
+        <div class="row" style="margin-top: 24px;"></div>
+
+        <div class="row">
+            <div class="col-md-8">
+                <h3 class="pb-3 mb-4 font-italic border-bottom">校园招聘</h3>
+
+                <div class="my-3 p-3 bg-white rounded box-shadow">
+                    <h5 class="border-bottom border-gray pb-2 mb-0">全职招聘</h5>
+                    <div class="media text-muted pt-3">
+                        <img data-src="holder.js/32x32?theme=thumb&amp;bg=007bff&amp;fg=007bff&amp;size=1" alt="32x32" class="mr-2 rounded"
+                             src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2232%22%20height%3D%2232%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_171a7c745cd%20text%20%7B%20fill%3A%23007bff%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A2pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_171a7c745cd%22%3E%3Crect%20width%3D%2232%22%20height%3D%2232%22%20fill%3D%22%23007bff%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2211.5390625%22%20y%3D%2216.9%22%3E32x32%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"
+                             data-holder-rendered="true" style="width: 32px; height: 32px;">
+                        <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
+                            <div class="d-flex justify-content-between align-items-center w-100">
+                                <strong class="text-gray-dark">解决方案专家</strong>
+                                <a href="#">查看</a>
+                            </div>
+                            <span class="d-block">解决方案专家</span>
+                        </div>
+                    </div>
+                    <div class="media text-muted pt-3">
+                        <img data-src="holder.js/32x32?theme=thumb&amp;bg=007bff&amp;fg=007bff&amp;size=1" alt="32x32" class="mr-2 rounded"
+                             src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2232%22%20height%3D%2232%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_171a7c745ce%20text%20%7B%20fill%3A%23007bff%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A2pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_171a7c745ce%22%3E%3Crect%20width%3D%2232%22%20height%3D%2232%22%20fill%3D%22%23007bff%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2211.5390625%22%20y%3D%2216.9%22%3E32x32%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"
+                             data-holder-rendered="true" style="width: 32px; height: 32px;">
+                        <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
+                            <div class="d-flex justify-content-between align-items-center w-100">
+                                <strong class="text-gray-dark">项目经理</strong>
+                                <a href="#">查看</a>
+                            </div>
+                            <span class="d-block">项目经理</span>
+                        </div>
+                    </div>
+                    <div class="media text-muted pt-3">
+                        <img data-src="holder.js/32x32?theme=thumb&amp;bg=007bff&amp;fg=007bff&amp;size=1" alt="32x32" class="mr-2 rounded"
+                             src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2232%22%20height%3D%2232%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_171a7c745ce%20text%20%7B%20fill%3A%23007bff%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A2pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_171a7c745ce%22%3E%3Crect%20width%3D%2232%22%20height%3D%2232%22%20fill%3D%22%23007bff%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2211.5390625%22%20y%3D%2216.9%22%3E32x32%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"
+                             data-holder-rendered="true" style="width: 32px; height: 32px;">
+                        <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
+                            <div class="d-flex justify-content-between align-items-center w-100">
+                                <strong class="text-gray-dark">销售总监</strong>
+                                <a href="#">查看</a>
+                            </div>
+                            <span class="d-block">销售总监</span>
+                        </div>
+                    </div>
+                    <small class="d-block text-right mt-3">
+                        <a href="/company">查看企业</a>
+                    </small>
+                </div>
+
+                <nav aria-label="Page navigation" style="margin-top: 24px;">
+                    <ul class="pagination justify-content-center">
+                        <li class="page-item disabled">
+                            <a class="page-link" href="#!" tabindex="-1">&laquo;</a>
+                        </li>
+                        <li class="page-item"><a class="page-link" href="#!">1</a></li>
+                        <li class="page-item active">
+                            <a class="page-link" href="#!">2 <span class="sr-only">(current)</span></a>
+                        </li>
+                        <li class="page-item"><a class="page-link" href="#!">3</a></li>
+                        <li class="page-item">
+                            <a class="page-link" href="#!">&raquo;</a>
+                        </li>
+                    </ul>
+                </nav>
+            </div>
+
+            <div class="col-md-4">
+                <div class="p-3">
+                    <h4 class="font-italic">推荐职位</h4>
+                    <ol class="list-unstyled mb-0">
+                        <li><a href="#">Java开发资深工程师</a></li>
+                        <li><a href="#">前端开发工程师</a></li>
+                        <li><a href="#">自动化运维</a></li>
+                        <li><a href="#">会计</a></li>
+                        <li><a href="#">销售总监</a></li>
+                        <li><a href="#">解决方案专家</a></li>
+                        <li><a href="#">项目经理</a></li>
+                    </ol>
+                </div>
+            </div>
+        </div>
     </div>
 </th:block>
 </body>

+ 23 - 2
src/main/resources/templates/register.html

@@ -79,7 +79,7 @@
                         <li>就业咨询</li>
                         <li>保障就业</li>
                     </ul>
-                    <button class="btn btn-lg btn-block btn-primary" type="button" onclick="window.location.href = '/register/school'">立即注册</button>
+                    <a class="btn btn-lg btn-block btn-primary" type="button" href="#modal-school" data-toggle="modal">立即注册</a>
                 </div>
             </div>
             <div class="card mb-4 box-shadow">
@@ -94,7 +94,7 @@
                         <li>检索简历</li>
                         <li>定向招工</li>
                     </ul>
-                    <button class="btn btn-lg btn-block btn-primary" type="button" onclick="window.location.href = '/register/company'">立即注册</button>
+                    <button class="btn btn-lg btn-block btn-outline-primary" type="button" onclick="window.location.href = '/register/company'">立即注册</button>
                 </div>
             </div>
         </div>
@@ -107,6 +107,27 @@
             </div>
         </div>
     </div>
+
+    <!-- Modal -->
+    <div class="modal fade" id="modal-school" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">学校用户注册</h5>
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">&times;</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    学校用户注册功能暂未开放,请留意官网通知。谢谢关注。
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" class="btn btn-primary" data-dismiss="modal">好的</button>
+                </div>
+            </div>
+        </div>
+    </div>
 </th:block>
 </body>
 </html>

+ 2 - 2
src/main/resources/templates/sign-in.html

@@ -35,14 +35,14 @@
 
     <div class="mb-3 text-center">
         <a href="/register" style="margin-right: 36px;">注册账号</a>
-        <a href="#password-modal" data-toggle="modal">忘记密码</a>
+        <a href="#modal-password" data-toggle="modal">忘记密码</a>
     </div>
     <button class="btn btn-lg btn-success btn-block" type="submit">登录</button>
     <p class="text-center mt-5 mb-3 text-muted">&copy; 2020 校园招聘网</p>
 </form>
 
 <!-- Modal -->
-<div class="modal fade" id="password-modal" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true">
+<div class="modal fade" id="modal-password" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true">
     <div class="modal-dialog" role="document">
         <div class="modal-content">
             <div class="modal-header">