fix build error and index page

Signed-off-by: Puqns67 <me@puqns67.icu>
This commit is contained in:
Puqns67 2023-09-15 17:12:25 +08:00
parent 88ebc71684
commit e34ea37964
Signed by: Puqns67
GPG Key ID: 9669DF042554F536
41 changed files with 732 additions and 777 deletions

View File

@ -11,6 +11,7 @@
<description>A demo project for fruit and vegetable store using Spring Boot.</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<kotlin.version>1.9.10</kotlin.version>
</properties>
@ -69,6 +70,10 @@
<artifactId>fastjson2-kotlin</artifactId>
<version>2.0.40</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Other -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>

View File

@ -5,14 +5,8 @@ import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@SpringBootApplication
class FruitableApplication {
@RequestMapping("/")
fun home(): String {
return "Hello World!"
}
}
class FruitableApplication
fun main(args: Array<String>) {
runApplication<FruitableApplication>(*args)

View File

@ -0,0 +1,90 @@
package team8.fruitable.controller.action
import jakarta.servlet.http.Cookie
import jakarta.servlet.http.HttpServletResponse
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.CookieValue
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.servlet.mvc.support.RedirectAttributes
import team8.fruitable.datebase.entity.User
import team8.fruitable.datebase.repository.AccountRepository
@Controller
@RequestMapping("/action/account")
class Account(private val repository: AccountRepository) {
private fun getCurrentUser(token: String?): User? {
return token?.let(repository::findByToken)
}
private fun hasAdminPermissions(token: String?): Boolean {
return this.getCurrentUser(token)?.isAdmin ?: false
}
private fun updateToken(response: HttpServletResponse, token: String, path: String = "/", age: Int = 2678400) {
val cookie = Cookie("TOKEN", token)
cookie.path = path
cookie.maxAge = age
response.addCookie(cookie)
}
fun error(
redirectAttributes: RedirectAttributes,
title: String,
message: String,
redirect: String = "redirect:/"
): String {
redirectAttributes.addFlashAttribute("title", title)
redirectAttributes.addFlashAttribute("message", message)
redirectAttributes.addFlashAttribute("redirect", redirect)
return "redirect:/error"
}
@PostMapping("/login")
fun login(
response: HttpServletResponse,
attributes: RedirectAttributes,
@CookieValue(value = "TOKEN", required = false) token: String?,
@RequestParam(name = "name") name: String,
@RequestParam(name = "password") password: String
): String {
if (this.getCurrentUser(token) != null) return error(attributes, "登录", "当前已登录账户")
val user = repository.findByName(name) ?: return error(attributes, "登录", "账户不存在")
if (!user.testPassword(password)) return error(attributes, "登录", "密码错误")
user.updateToken()
user.updateLoginTime()
repository.save(user)
updateToken(response, user.token)
return "redirect:/";
}
@PostMapping("/register")
fun register(
response: HttpServletResponse,
attributes: RedirectAttributes,
@CookieValue(value = "TOKEN", required = false) token: String?,
@RequestParam(name = "name") name: String,
@RequestParam(name = "password") password: String,
@RequestParam(name = "age", required = false) age: Int?,
@RequestParam(name = "gender", required = false) gender: String?,
@RequestParam(name = "phone", required = false) phone: String?,
@RequestParam(name = "email", required = false) email: String?,
@RequestParam(name = "address", required = false) address: String?
): String {
if (this.getCurrentUser(token) != null) return error(attributes, "登录", "当前已登录账户")
val user = repository.save(User(name, password, age, gender, phone, email, address))
updateToken(response, user.token)
return "redirect:/";
}
@RequestMapping("/logout")
fun logout(
response: HttpServletResponse,
@RequestParam("redirect", required = false) redirect: String?
): String {
updateToken(response, "", age = 0)
redirect?.let { return it }
return "redirect:/"
}
}

View File

@ -5,11 +5,12 @@ import jakarta.servlet.http.HttpServletResponse
import org.springframework.web.bind.annotation.*
import team8.fruitable.constant.UserType
import team8.fruitable.datebase.entity.User
import team8.fruitable.datebase.repository.UserRepository
import team8.fruitable.util.ResultBuilder
import team8.fruitable.datebase.repository.AccountRepository
import team8.fruitable.util.ResultBuilderJson
@RestController
class Account(private val repository: UserRepository) {
@RequestMapping("/api/v1/account")
class AccountApi(private val repository: AccountRepository) {
private fun getCurrentUser(token: String?): User? {
return token?.let(repository::findByToken)
}
@ -25,50 +26,50 @@ class Account(private val repository: UserRepository) {
response.addCookie(cookie)
}
@GetMapping("/api/v1/account/info", produces = ["application/json"])
@GetMapping("/info", produces = ["application/json"])
fun infoMe(
@CookieValue(value = "TOKEN", required = false) token: String?
): String {
val user = this.getCurrentUser(token) ?: return ResultBuilder<Any>("账户未登录").toJson()
return ResultBuilder(user.asMap(UserType.User)).toJson()
val user = this.getCurrentUser(token) ?: return ResultBuilderJson<Any>("账户未登录").toJson()
return ResultBuilderJson(user.asMap(UserType.User)).toJson()
}
@GetMapping("/api/v1/account/info/{id}", produces = ["application/json"])
@GetMapping("/info/{id}", produces = ["application/json"])
fun info(
@CookieValue(value = "TOKEN", required = false) token: String?, @PathVariable id: Long
): String {
val queryUser = repository.findById(id).orElse(null) ?: return ResultBuilder<Any>("账户不存在").toJson()
val queryUser = repository.findById(id).orElse(null) ?: return ResultBuilderJson<Any>("账户不存在").toJson()
val currentUser = this.getCurrentUser(token)
return ResultBuilder(
return ResultBuilderJson(
queryUser.asMap(if (currentUser != null && (currentUser.id == id || currentUser.isAdmin)) UserType.User else UserType.Guest)
).toJson()
}
//@PostMapping
@RequestMapping("/api/v1/account/login", produces = ["application/json"])
@RequestMapping("/login", produces = ["application/json"])
fun login(
response: HttpServletResponse,
@CookieValue(value = "TOKEN", required = false) token: String?,
@RequestParam(name = "name") name: String,
@RequestParam(name = "password") password: String
): String {
if (this.getCurrentUser(token) != null) return ResultBuilder<Any>("当前已登录账户").toJson()
val user = repository.findByName(name) ?: return ResultBuilder<Any>("账户不存在").toJson()
if (!user.testPassword(password)) return ResultBuilder<Any>("密码错误").toJson()
if (this.getCurrentUser(token) != null) return ResultBuilderJson<Any>("当前已登录账户").toJson()
val user = repository.findByName(name) ?: return ResultBuilderJson<Any>("账户不存在").toJson()
if (!user.testPassword(password)) return ResultBuilderJson<Any>("密码错误").toJson()
user.updateToken()
user.updateLoginTime()
repository.save(user)
updateToken(response, user.token)
return ResultBuilder<Any>("success", "登录成功").toJson()
return ResultBuilderJson<Any>("success", "登录成功").toJson()
}
@RequestMapping("/api/v1/account/logout", produces = ["application/json"])
@RequestMapping("/logout", produces = ["application/json"])
fun logout(response: HttpServletResponse): String {
updateToken(response, "", age = 0)
return ResultBuilder<Any>("success", "注销成功").toJson()
return ResultBuilderJson<Any>("success", "注销成功").toJson()
}
@RequestMapping("/api/v1/account/register", produces = ["application/json"])
@RequestMapping("/register", produces = ["application/json"])
fun register(
response: HttpServletResponse,
@CookieValue(value = "TOKEN", required = false) token: String?,
@ -80,13 +81,13 @@ class Account(private val repository: UserRepository) {
@RequestParam(name = "email", required = false) email: String?,
@RequestParam(name = "address", required = false) address: String?
): String {
if (this.getCurrentUser(token) != null) return ResultBuilder<Any>("当前已登录账户").toJson()
if (this.getCurrentUser(token) != null) return ResultBuilderJson<Any>("当前已登录账户").toJson()
val user = repository.save(User(name, password, age, gender, phone, email, address))
updateToken(response, user.token)
return ResultBuilder<Any>("success", "注册成功").toJson()
return ResultBuilderJson<Any>("success", "注册成功").toJson()
}
@RequestMapping("/api/v1/account/update", produces = ["application/json"])
@RequestMapping("/update", produces = ["application/json"])
fun update(
response: HttpServletResponse,
@CookieValue(name = "TOKEN", required = false) token: String?,
@ -98,33 +99,33 @@ class Account(private val repository: UserRepository) {
@RequestParam(name = "email", required = false) email: String?,
@RequestParam(name = "address", required = false) address: String?
): String {
val user = this.getCurrentUser(token) ?: return ResultBuilder<Any>("账户未登录").toJson()
val user = this.getCurrentUser(token) ?: return ResultBuilderJson<Any>("账户未登录").toJson()
user.update(name, password, age, gender, phone, email, address)
repository.save(user)
updateToken(response, user.token)
return ResultBuilder<Any>("success", "更新账户信息成功").toJson()
return ResultBuilderJson<Any>("success", "更新账户信息成功").toJson()
}
@GetMapping("/api/v1/account/admin/info/{id}", produces = ["application/json"])
@GetMapping("/admin/info/{id}", produces = ["application/json"])
fun infoAdmin(
@CookieValue(value = "TOKEN", required = false) token: String?,
@PathVariable id: Long,
): String {
if (this.hasAdminPermissions(token)) return ResultBuilder<Any>("无管理员权限").toJson()
return ResultBuilder(repository.findById(id)).toJson()
if (this.hasAdminPermissions(token)) return ResultBuilderJson<Any>("无管理员权限").toJson()
return ResultBuilderJson(repository.findById(id)).toJson()
}
@DeleteMapping("/api/v1/account/admin/remove/{id}", produces = ["application/json"])
@DeleteMapping("/admin/remove/{id}", produces = ["application/json"])
fun removeAdmin(
@CookieValue(value = "TOKEN", required = false) token: String?,
@PathVariable id: Long,
): String {
if (this.hasAdminPermissions(token)) return ResultBuilder<Any>("无管理员权限").toJson()
if (this.hasAdminPermissions(token)) return ResultBuilderJson<Any>("无管理员权限").toJson()
// TODO: 完成管理员删除方法
return ResultBuilder(repository.findById(id)).toJson()
return ResultBuilderJson(repository.findById(id)).toJson()
}
@PostMapping("/api/v1/account/admin/update/{id}", produces = ["application/json"])
@PostMapping("/admin/update/{id}", produces = ["application/json"])
fun updateAdmin(
@CookieValue(value = "TOKEN", required = false) token: String?,
@PathVariable id: Long,
@ -136,8 +137,8 @@ class Account(private val repository: UserRepository) {
@RequestParam(name = "email", required = false) email: String?,
@RequestParam(name = "address", required = false) address: String?
): String {
if (this.hasAdminPermissions(token)) return ResultBuilder<Any>("无管理员权限").toJson()
if (this.hasAdminPermissions(token)) return ResultBuilderJson<Any>("无管理员权限").toJson()
// TODO: 完成管理员更新账户数据方法
return ResultBuilder(repository.findById(id)).toJson()
return ResultBuilderJson(repository.findById(id)).toJson()
}
}

View File

@ -5,11 +5,11 @@ import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RestController
import team8.fruitable.datebase.entity.User
import team8.fruitable.datebase.repository.ItemRepository
import team8.fruitable.datebase.repository.UserRepository
import team8.fruitable.util.ResultBuilder
import team8.fruitable.datebase.repository.AccountRepository
import team8.fruitable.util.ResultBuilderJson
@RestController
class Item(private val itemRepository: ItemRepository, private val userRepository: UserRepository) {
class Item(private val itemRepository: ItemRepository, private val userRepository: AccountRepository) {
private fun getCurrentUser(token: String?): User? {
return token?.let(userRepository::findByToken)
}
@ -20,6 +20,6 @@ class Item(private val itemRepository: ItemRepository, private val userRepositor
@GetMapping("/api/v1/item/info/{id}", produces = ["application/json"])
fun info(@PathVariable id: Long): String {
return ResultBuilder(itemRepository.findById(id).orElse(null)).toJson()
return ResultBuilderJson(itemRepository.findById(id).orElse(null)).toJson()
}
}

View File

@ -0,0 +1,32 @@
package team8.fruitable.controller.page
import org.springframework.boot.web.servlet.error.ErrorController
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.ui.set
import org.springframework.web.bind.annotation.CookieValue
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.RequestMapping
import team8.fruitable.datebase.repository.AccountRepository
@Controller
class Error(private val repository: AccountRepository) : ErrorController {
@RequestMapping("/error")
fun error(
model: Model,
@CookieValue("TOKEN", required = false) token: String?,
@ModelAttribute("title") title: String?,
@ModelAttribute("message") message: String?,
@ModelAttribute("redirect") redirect: String?
): Model {
token?.let(repository::findByToken)?.let { model["user"] = it }
model["error"] = mapOf(
"title" to title,
"message" to message,
"redirect" to redirect
)
return model
}
}

View File

@ -0,0 +1,52 @@
package team8.fruitable.controller.page
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.ui.set
import org.springframework.web.bind.annotation.CookieValue
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.servlet.ModelAndView
import team8.fruitable.datebase.entity.User
import team8.fruitable.datebase.repository.AccountRepository
@Controller
class Pages(private val repository: AccountRepository) {
private fun getCurrentUser(token: String?): User? {
return token?.let(repository::findByToken)
}
private fun hasAdminPermissions(token: String?): Boolean {
return this.getCurrentUser(token)?.isAdmin ?: false
}
@RequestMapping("/")
fun index(
model: Model,
@CookieValue("TOKEN", required = false) token: String?
): String {
model["isIndex"] = true
this.getCurrentUser(token)?.let { model["user"] = it }
return "index"
}
@RequestMapping("/login")
fun login(
model: Model,
@CookieValue("TOKEN", required = false) token: String?
): String {
model["isLogin"] = true
this.getCurrentUser(token)?.let { model["user"] = it }
return "login"
}
@RequestMapping("/register")
fun register(
model: Model,
@CookieValue("TOKEN", required = false) token: String?
): String {
model["isRegister"] = true
this.getCurrentUser(token)?.let { model["user"] = it }
return "register"
}
}

View File

@ -1,5 +1,6 @@
package team8.fruitable.datebase.entity
import com.fasterxml.jackson.annotation.JsonView
import jakarta.persistence.*
import team8.fruitable.constant.UserType
import team8.fruitable.util.Util
@ -13,47 +14,65 @@ class User(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
@JsonView(UserView::class)
var id: Long? = null,
@Column(name = "name", length = 16, nullable = false)
@JsonView(GuestView::class)
var name: String? = null,
@Column(name = "password", length = 64, nullable = false)
@JsonView(AdminView::class)
var password: String? = null,
@Column(name = "time_create", nullable = false)
@JsonView(UserView::class)
var createTime: LocalDateTime = LocalDateTime.now(),
@Column(name = "time_login", nullable = false)
@JsonView(UserView::class)
var loginTime: LocalDateTime = LocalDateTime.now(),
@Column(name = "token", length = 36)
@JsonView(AdminView::class)
var token: String = UUID.randomUUID().toString(),
@Column(name = "age")
@JsonView(GuestView::class)
var age: Int? = null,
@Column(name = "gender", length = 1)
@JsonView(GuestView::class)
var gender: String? = null,
@Column(name = "phone", length = 11)
@JsonView(UserView::class)
var phone: String? = null,
@Column(name = "email", length = 64)
@JsonView(GuestView::class)
var email: String? = null,
@Column(name = "address", length = 64)
@JsonView(UserView::class)
var address: String? = null,
@Column(name = "is_admin", nullable = false)
@JsonView(AdminView::class)
var isAdmin: Boolean = false,
@OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.LAZY, mappedBy = "carted")
var carts: MutableList<Item> = mutableListOf<Item>(),
@JsonView(UserView::class)
var carts: MutableList<Item> = mutableListOf(),
@OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.LAZY, mappedBy = "user")
var orders: MutableList<Order> = mutableListOf<Order>()
@JsonView(UserView::class)
var orders: MutableList<Order> = mutableListOf()
) {
interface GuestView
interface UserView : GuestView
interface AdminView : UserView
constructor(name: String, password: String) : this() {
this.name = name
this.password = this.genPassword(password)

View File

@ -3,7 +3,7 @@ package team8.fruitable.datebase.repository
import org.springframework.data.repository.CrudRepository
import team8.fruitable.datebase.entity.User
interface UserRepository : CrudRepository<User, Long> {
interface AccountRepository : CrudRepository<User, Long> {
fun findByName(name: String): User?
fun findByToken(token: String): User?
}

View File

@ -4,7 +4,7 @@ import com.alibaba.fastjson2.toJSONString
import java.time.LocalDateTime
import java.util.*
class ResultBuilder<T> {
class ResultBuilderJson<T> {
var status: String = "auto"
var message: String = ""
val timestamp: LocalDateTime = LocalDateTime.now()

View File

@ -7,3 +7,8 @@ spring:
show-sql: true
hibernate:
ddl-auto: update
server:
servlet:
encoding:
charset: UTF-8
force-response: true

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 503.945 503.945" style="enable-background:new 0 0 503.945 503.945;" xml:space="preserve">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px"
y="0px" viewBox="0 0 503.945 503.945" style="enable-background:new 0 0 503.945 503.945;" xml:space="preserve">
<path style="fill:#18456D;" d="M455.173,345.073l48-152.8c1.6-6.4,0.8-12.8-3.2-18.4s-10.4-8.8-16.8-8.8h-462.4
c-6.4,0-12.8,3.2-16.8,8.8s-4.8,12-3.2,18.4l48,152.8c0,3.2,0.8,5.6,2.4,8.8l20.8,66.4c2.4,8.8,10.4,14.4,20,14.4h320
c8.8,0,16.8-5.6,20-14.4l20.8-66.4L455.173,345.073z M73.573,285.073h356.8l-12,37.6h-333.6L73.573,285.073z M455.173,206.673

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 495 495" style="enable-background:new 0 0 495 495;" xml:space="preserve">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px"
y="0px" viewBox="0 0 495 495" style="enable-background:new 0 0 495 495;" xml:space="preserve">
<polygon style="fill:#004FAC;" points="181.112,81.833 168.742,166.012 168.742,222.068 326.258,222.068 326.258,166.012
313.888,81.833 " />
<polygon style="fill:#005ECE;" points="446.663,81.833 313.888,81.833 326.258,166.012 326.258,222.068 483.774,222.068

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Pin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve">
<svg version="1.1" id="Pin" xmlns="http://www.w3.org/2000/svg" x="0px"
y="0px" viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve">
<path d="M499.505,128.508l-72.045-72.045c-3.163-3.162-8.293-3.162-11.455,0c-3.163,3.164-3.163,8.293,0,11.456l72.045,72.044
c10.2,10.201,10.2,27.222,0,37.422c-10.201,10.2-27.221,10.2-37.421-0.001L334.614,61.371c-10.2-10.199-10.2-27.22,0-37.419
c10.2-10.201,27.221-10.201,37.421,0l23.986,23.984c3.163,3.162,8.293,3.163,11.455-0.001c3.163-3.163,3.163-8.293,0-11.455

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 503.945 503.945" style="enable-background:new 0 0 503.945 503.945;" xml:space="preserve">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px"
y="0px" viewBox="0 0 503.945 503.945" style="enable-background:new 0 0 503.945 503.945;" xml:space="preserve">
<path style="fill:#18456D;" d="M455.173,345.073l48-152.8c1.6-6.4,0.8-12.8-3.2-18.4s-10.4-8.8-16.8-8.8h-462.4
c-6.4,0-12.8,3.2-16.8,8.8s-4.8,12-3.2,18.4l48,152.8c0,3.2,0.8,5.6,2.4,8.8l20.8,66.4c2.4,8.8,10.4,14.4,20,14.4h320
c8.8,0,16.8-5.6,20-14.4l20.8-66.4L455.173,345.073z M73.573,285.073h356.8l-12,37.6h-333.6L73.573,285.073z M455.173,206.673

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="30.021px" height="30.021px" viewBox="0 0 30.021 30.021"
style="enable-background:new 0 0 30.021 30.021;" xml:space="preserve">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" x="0px"
y="0px" width="30.021px" height="30.021px" viewBox="0 0 30.021 30.021"
style="enable-background:new 0 0 30.021 30.021;" xml:space="preserve">
<path d="M29.069,22.276c-0.791,0.932-1.917,1.409-3.052,1.409c-0.913,0-1.834-0.312-2.587-0.949l-8.42-7.152l-8.42,7.151
c-1.683,1.43-4.208,1.225-5.639-0.459c-1.43-1.686-1.224-4.208,0.46-5.64l11.01-9.351c1.493-1.269,3.686-1.269,5.178,0
l11.011,9.351C30.294,18.068,30.499,20.591,29.069,22.276z" />

Before

Width:  |  Height:  |  Size: 800 B

After

Width:  |  Height:  |  Size: 765 B

View File

@ -7,7 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { getItems, getNextItem, hasNextItem, indexOf, loadItem, } from "./items.js";
import {getItems, getNextItem, hasNextItem, indexOf, loadItem,} from "./items.js";
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// 源数据
let rawBanners = [];
@ -135,7 +136,7 @@ function updateItems() {
return __awaiter(this, void 0, void 0, function* () {
let ID = this.getAttribute("item_id");
if (ID != null) {
window.location.href = `item.jsp?item_id=${ID}`;
window.location.href = `item/${ID}`;
}
});
});

View File

@ -7,7 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { getItem, loadItem } from "./items.js";
import {getItem, loadItem} from "./items.js";
let ID;
let TheItem;
window.addEventListener("DOMContentLoaded", () => __awaiter(void 0, void 0, void 0, function* () {
@ -64,7 +65,7 @@ window.addEventListener("DOMContentLoaded", () => __awaiter(void 0, void 0, void
});
// 为选项添加点击事件
Array.from(OptionDisplayer.children).forEach((v) => {
let contants = v.querySelector(".Contants");
let contants = v.querySelector(".Contents");
Array.from(contants.children).forEach((v) => {
v.addEventListener("click", function () {
return __awaiter(this, void 0, void 0, function* () {

View File

@ -7,7 +7,7 @@
width: 140px;
color: rgb(0, 255, 90);
text-align: center;
font-family: "LcdD";
font-family: "LcdD", serif;
border: 3px solid black;
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.5);

View File

@ -20,7 +20,7 @@ div {
height: 500px;
}
#Contents > .Editor {
#Contents > .Editors {
flex: 4 0 0;
flex-direction: column;
justify-content: space-between;
@ -32,31 +32,31 @@ div {
border-radius: 15px;
}
#Contents > .Editor > .Title {
#Contents > .Editors > .Title {
justify-content: space-between;
}
#Contents > .Editor > .Result {
#Contents > .Editors > .Result {
color: wheat;
border: 3px solid skyblue;
border-spacing: 0;
border-radius: 10px;
}
#Contents > .Editor > .Result td {
#Contents > .Editors > .Result td {
white-space: nowrap;
border: 1px solid cornflowerblue;
}
#Contents > .Editor > .Result > thead {
#Contents > .Editors > .Result > thead {
background-color: #044488;
}
#Contents > .Editor > .Result > tbody {
#Contents > .Editors > .Result > tbody {
background-color: #008080;
}
#Contents > .Editor > .Pages > * {
#Contents > .Editors > .Pages > * {
color: wheat;
margin-right: 3px;
border: 3px solid skyblue;
@ -64,15 +64,15 @@ div {
background-color: cadetblue;
}
#Contents > .Editor > .Pages > *:last-child {
#Contents > .Editors > .Pages > *:last-child {
margin-right: inherit;
}
#Contents > .Editor > .Pages > span {
#Contents > .Editors > .Pages > span {
color: green;
}
#Contents > .UserEditor {
#Contents > .EditPanel {
flex: 1 0 0;
margin: 5px;
padding: 5px;
@ -81,8 +81,8 @@ div {
border-radius: 15px;
}
#Contents > .UserEditor > .Displayer {
border: 0px;
#Contents > .EditPanel > .Panel {
border: 0;
}
@media (min-width: 1280px) {

View File

@ -35,7 +35,7 @@ div {
margin-top: 10px;
margin-bottom: 10px;
color: wheat;
font-family: "Normal";
font-family: "Normal", system-ui;
}
.ErrorTitle {
@ -46,7 +46,7 @@ div {
.ErrorRedirectButton {
margin: 20px 15px;
padding: 8px 0px;
padding: 8px 0;
border: 3px solid skyblue;
border-radius: 10px;
font-size: 18px;

View File

@ -47,23 +47,23 @@ div {
}
.Item .Infos > * {
margin: 10px 0px;
margin: 10px 0;
}
.Item .Infos > .Title {
font-size: 30px;
font-weight: bold;
font-family: "Normal";
font-family: "Normal", system-ui;
}
.Item .Infos .Description {
font-size: 20px;
font-family: "Normal";
font-family: "Normal", system-ui;
}
.Item .Infos .Prices {
align-items: baseline;
font-family: "Normal";
font-family: "Normal", system-ui;
}
.Item .Infos .Prices .VipPrice {
@ -79,7 +79,7 @@ div {
}
.Item .Infos .Prices .Price[has_vip_price] {
color: gray;
color: grey;
font-size: 16px;
font-weight: lighter;
font-style: italic;
@ -92,32 +92,32 @@ div {
.Item .Infos .Options > .Option {
flex-direction: row;
margin: 5px 0px;
margin: 5px 0;
border: 1px solid rgba(0, 120, 255, 0.8);
border-radius: 5px;
}
.Item .Infos .Options > .Option .Title {
font-weight: bold;
padding: 0px 10px;
border-radius: 5px 0px 0px 5px;
padding: 0 10px;
border-radius: 5px 0 0 5px;
background: green;
font-size: 20px;
}
.Item .Infos .Options > .Option .Contants {
.Item .Infos .Options > .Option .Contents {
flex-wrap: wrap;
align-items: stretch;
}
.Item .Infos .Options > .Option .Contants .Option {
.Item .Infos .Options > .Option .Contents .Option {
font-size: 18px;
padding: 0px 5px;
padding: 0 5px;
align-items: center;
background-color: #355ae8;
}
.Item .Infos .Options > .Option .Contants .Option[selected] {
.Item .Infos .Options > .Option .Contents .Option[selected] {
font-weight: bold;
background-color: #489dff;
}

View File

@ -65,14 +65,14 @@
<!-- 页面内容 -->
<div id="Contents">
<div class="Editor">
<div class="Editors">
<div class="Title">
<form class="Search" action="edit.jsp" method="post">
<s:select name="type" list="#{'ALL': '搜索全部', 'ID': '以ID搜索', 'USERNAME': '以用户名搜索', 'CREATE_DATE': '以帐户注册时间搜索', 'LAST_LOGIN_DATE': '以最后登录时间搜索', 'AGE': '以年龄搜索', 'GENDER': '以性别搜索', 'EMAIL': '以邮箱搜索', 'IS_ADMIN': '以管理员状态搜索'}" value="%{#EditInfo.SearchType}" />
<s:textfield name="search" placeholder="请在此处输入你想要搜索的内容..." value="%{#EditInfo.Search}" />
<button type="submit">搜索</button>
</form>
<button onclick="javascript:location.reload();">刷新</button>
</div>
@ -109,7 +109,7 @@
</s:iterator>
</tbody>
</table>
<div class="Pages">
<a href="edit.jsp?page=0">首页</a>
<s:iterator begin="%{#EditInfo.StartPage}" end="%{#EditInfo.StopPage}" var="PageNumber">
@ -123,9 +123,9 @@
<a href="edit.jsp?page=<s:property value="%{#EditInfo.EndPage}" />">尾页</a>
</div>
</div>
<div class="UserEditor">
<iframe id="Displayer" class="Displayer" name="displayer"></iframe>
<div class="EditPanel">
<iframe id="Displayer" class="Panel" name="displayer"></iframe>
</div>
</div>

View File

@ -0,0 +1,19 @@
{{> header }}
<!-- 页面内容 -->
<div id="Contents">
<div class="Editors">
{{# userEditor }}
{{> editor/user }}
{{/ userEditor }}
{{# itemEditor }}
{{> editor/item }}
{{/ itemEditor }}
</div>
<div class="EditPanel">
<iframe id="Panel" class="Panel" name="panel"></iframe>
</div>
</div>
{{> footer }}

View File

@ -0,0 +1,37 @@
{{> header }}
<!-- 页面内容 -->
<div id="Contents">
<div class="Item">
<div class="Picture">
<img alt="商品图片" src=""/>
</div>
<div class="Infos">
<span class="Title"></span>
<div class="Prices">
<div class="VipPrice"></div>
<div class="Price"></div>
</div>
<span class="Description"></span>
<div class="Options">
<div class="Option">
<div class="Title">数量</div>
<div class="Contents">
<div class="Option" selected>&nbsp;1&nbsp;</div>
<div class="Option">&nbsp;2&nbsp;</div>
<div class="Option">&nbsp;3&nbsp;</div>
<div class="Option">&nbsp;4&nbsp;</div>
<div class="Option">&nbsp;5&nbsp;</div>
<div class="Option">&nbsp;6&nbsp;</div>
</div>
</div>
</div>
<div class="Buttons">
<span class="Button">立即购买</span>
<span class="Button">加入购物车</span>
</div>
</div>
</div>
</div>
{{> footer }}

View File

@ -0,0 +1,69 @@
<div class="Title">
<form class="Search" action="edit" method="post">
<input type="hidden" name="edit" value="user"/>
{{!
list="#{'ALL': '搜索全部', 'ID': '以ID搜索', 'USERNAME': '以用户名搜索', 'CREATE_DATE': '以帐户注册时间搜索', 'LAST_LOGIN_DATE': '以最后登录时间搜索', 'AGE': '以年龄搜索', 'GENDER': '以性别搜索', 'EMAIL': '以邮箱搜索', 'IS_ADMIN': '以管理员状态搜索'}"
}}
<select name="type">
{{#Editor.Selects}}
<option value="{{key}}">{{value}}</option>
{{/Editor.Selects}}
</select>
<label>
<input name="search" placeholder="请在此处输入你想要搜索的内容..." value="{{Editor.Searching}}"/>
</label>
<button type="submit">搜索</button>
</form>
<button onclick="location.reload();">刷新</button>
</div>
<table class="Result">
<thead>
<tr>
<td>ID</td>
<td>用户名</td>
<td>帐户创建时间</td>
<td>最后登录时间</td>
<td>年龄</td>
<td>性别</td>
<td>邮箱</td>
<td>管理员</td>
<td>操作</td>
</tr>
</thead>
<tbody>
{{#Users}}
<tr id="{{ Id }}">
<td>{{ Id }}</td>
<td>{{ UserName }}</td>
<td>{{ CreateDate }}</td>
<td>{{ LastLoginDate }}</td>
<td>{{ Age }}</td>
<td>{{ Gender }}</td>
<td>{{ Phone }}</td>
<td>{{ Email }}</td>
<td>{{ Address }}</td>
<td>{{ IsAdmin }}</td>
<td>
<button class="update">编辑</button>
<button class="remove">删除</button>
</td>
</tr>
{{/Users}}
</tbody>
</table>
<div class="Pages">
<a href="edit?page=0">首页</a>
<s:iterator begin="%{#EditInfo.StartPage}" end="%{#EditInfo.StopPage}" var="PageNumber">
<s:if test="%{#PageNumber == #EditInfo.NowPageStr}">
<span>第 <s:property value="%{#PageNumber + 1}" 页</span>
</s:if>
<s:else>
<a href=" edit.jsp?page=<s:property value="%{#PageNumber} }}">第 <s:property
value="%{#PageNumber + 1}"/> 页</a>
</s:else>
</s:iterator>
<a href="edit.jsp?page=<s:property value=" %{#EditInfo.EndPage} }}">尾页</a>
</div>

View File

@ -1,109 +0,0 @@
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:action name="auth" var="AuthInfo" />
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<s:if test="%{#ErrorRedirectTo != \"none\"}">
<meta http-equiv="refresh" content="3;url=<s:property value="ErrorRedirectTo" />">
</s:if>
<title>出错啦! - 67购物网站</title>
<script type="text/javascript" src="../static/scripts/header.js"></script>
<script type="text/javascript" src="../static/scripts/clock.js"></script>
<script type="text/javascript" src="../static/scripts/top.js"></script>
<script type="text/javascript" src="../static/scripts/footer.js"></script>
<link type="image/x-icon" rel="icon" href="../static/images/favicon.ico">
<link type="text/css" rel="stylesheet" href="../static/styles/header.css">
<link type="text/css" rel="stylesheet" href="../static/styles/clock.css">
<link type="text/css" rel="stylesheet" href="../static/styles/top.css">
<link type="text/css" rel="stylesheet" href="../static/styles/footer.css">
<link type="text/css" rel="stylesheet" href="../static/styles/error.css">
<!-- 外部小组件 -->
<script src="../static/scripts/lib/anime.min.js"></script>
<script async src="../static/scripts/lib/explosion.min.js"></script>
</head>
<body>
<!-- 头部内容 -->
<div id="Header">
<div class="List Special Title">67购物网站</div>
<div class="List Link" href="index.jsp">
<span class="Text">首页</span>
</div>
<div class="List Link" this>
<span class="Text">活动</span>
</div>
<div class="List Blank"></div>
<div class="List Special SearchBar">
<input class="InputBar" type="text" />
</div>
<div class="List Blank"></div>
<div class="List Button"><span class="Text">历史记录</span></div>
<div class="List Button"><span class="Text">购物车</span></div>
<s:if test="%{#AuthInfo.IsLogined}">
<div class="List Button Link" href="logout.action"><span class="Text">注销</span></div>
<s:if test="%{#AuthInfo.UserInfo.IsAdmin}">
<div class="List Button Link" href="edit.jsp"><span class="Text">编辑</span></div>
</s:if>
<div class="List Button Link" href="account.jsp"><span class="Text">账户</span></div>
</s:if>
<s:else>
<div class="List Button Link" href="login.jsp"><span class="Text">登录</span></div>
<div class="List Button Link" href="register.jsp"><span class="Text">注册</span></div>
</s:else>
<div class="List Special Clock">
<span class="CLOCK"></span>
</div>
<div class="List Special PinHeader">
<img class="PIN" src="../static/images/pin.svg" checked />
</div>
</div>
<!-- 页面内容 -->
<div id="Contents">
<div class="ErrorInfo">
<div class="ErrorTitle"><s:property value="ErrorFrom" />失败</div>
<div class="ErrorMessage">原因: <s:property value="ErrorMessage" /></div>
<s:if test="%{#ErrorRedirectTo != \"none\"}">
<div class="ErrorRedirectMessage">将在三秒后跳转至页面: <s:property value="ErrorRedirectTo" /></div>
<button class="ErrorRedirectButton" onclick="javascript:window.location.replace('<s:property value="ErrorRedirectTo" />')">点此立即跳转</button>
</s:if>
</div>
</div>
<!-- 页尾内容 -->
<div id="Footer">
<div class="Infos">
<div class="Icon"><img src="../static/images/icon.svg" /></div>
<div class="Title">67购物网站</div>
<div class="Contents">
<span>只做高质量商品销售~</span>
</div>
</div>
<div class="Links">
<div class="Title"></div>
<div class="Contents"></div>
</div>
</div>
<!-- 浮动内容 -->
<div id="Floater">
<!-- 回到顶层 -->
<div class="TOP"></div>
<canvas
class="fireworks"
style="
position: fixed;
left: 0;
top: 0;
z-index: 1;
pointer-events: none;
"
></canvas>
</div>
</body>
</html>

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>主页 - 在线果蔬商城</title>
<script type="text/javascript" src="scripts/header.js"></script>
<script type="text/javascript" src="scripts/clock.js"></script>
<script type="text/javascript" src="scripts/top.js"></script>
<script type="module" src="scripts/resources.js"></script>
<script type="module" src="scripts/items.js"></script>
<script type="module" src="scripts/index.js"></script>
<link type="image/x-icon" rel="icon" href="images/favicon.ico">
<!-- 页面公共的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/header.css">
<link type="text/css" rel="stylesheet" href="styles/clock.css">
<link type="text/css" rel="stylesheet" href="styles/top.css">
<link type="text/css" rel="stylesheet" href="styles/footer.css">
<link type="text/css" rel="stylesheet" href="styles/loading.css">
<!-- 页面特定的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/error.css">
<!-- 外部小组件 -->
<script src="scripts/lib/anime.min.js"></script>
<script async src="scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header }}
<div class="ErrorInfo">
<div class="ErrorTitle">{{ title }} 失败</div>
<div class="ErrorMessage">原因: {{ message }}</div>
{{# redirect }}
<div class="ErrorRedirectMessage">将在三秒后跳转至页面: {{ redirect }}</div>
<button class="ErrorRedirectButton" onclick="window.location.replace('{{ redirect }}')">点此立即跳转</button>
{{/ redirect }}
</div>
{{> footer }}
</body>
</html>

View File

@ -1,7 +1,7 @@
<!-- 页尾内容 -->
<div id="Footer">
<div class="Infos">
<div class="Icon"><img src="../static/images/icon.svg" /></div>
<div class="Icon"><img alt="图标" src="images/icon.svg" /></div>
<div class="Title">果蔬销售商城</div>
<div class="Contents">
<span>只做高质量商品销售~</span>
@ -28,6 +28,3 @@
"
></canvas>
</div>
</body>
</html>

View File

@ -1,58 +1,35 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>主页 - 67购物网站</title>
<script type="text/javascript" src="scripts/header.js"></script>
<script type="text/javascript" src="scripts/clock.js"></script>
<script type="text/javascript" src="scripts/top.js"></script>
<script type="module" src="scripts/resources.js"></script>
<script type="module" src="scripts/items.js"></script>
<script type="module" src="scripts/index.js"></script>
<link type="image/x-icon" rel="icon" href="images/favicon.ico">
<link type="text/css" rel="stylesheet" href="styles/header.css">
<link type="text/css" rel="stylesheet" href="styles/clock.css">
<link type="text/css" rel="stylesheet" href="styles/top.css">
<link type="text/css" rel="stylesheet" href="styles/footer.css">
<link type="text/css" rel="stylesheet" href="styles/loading.css">
<link type="text/css" rel="stylesheet" href="styles/index.css">
<!-- 外部小组件 -->
<script src="scripts/lib/anime.min.js"></script>
<script async src="scripts/lib/explosion.min.js"></script>
</head>
<body>
<!-- 头部内容 -->
<div id="Header">
<div class="List Special Title">67购物网站</div>
<div class="List Link" this>
<div class="List Link" {{#isIndex}}this{{/isIndex}}{{^isIndex}}href="/"{{/isIndex}}>
<span class="Text">首页</span>
</div>
<div class="List Link" href="activity.jsp">
<span class="Text">活动</span>
<div class="List Link" {{#isItem}}this{{/isItem}}{{^isItem}}href="/items"{{/isItem}}>
<span class="Text">商品</span>
</div>
<div class="List Blank"></div>
<div class="List Special SearchBar">
<input class="InputBar" type="text"/>
<label>
<input class="InputBar" type="text"/>
</label>
</div>
<div class="List Blank"></div>
<div class="List Button"><span class="Text">历史记录</span></div>
<div class="List Button"><span class="Text">购物车</span></div>
{{#isLogined}}
<div class="List Button Link" href="logout.action"><span class="Text">注销</span></div>
{{#user}}
<div class="List Button Link" {{#isCart}}this{{/isCart}}{{^isCart}}href="/cart"{{/isCart}}><span class="Text">购物车</span></div>
<div class="List Button Link" href="/action/account/logout"><span class="Text">注销</span></div>
{{#isAdmin}}
<div class="List Button Link" href="edit.jsp"><span class="Text">编辑</span></div>
<div class="List Button Link" {{#isEditor}}this{{/isEditor}}{{^isEditor}}href="/editor"{{/isEditor}}><span class="Text">编辑</span></div>
{{/isAdmin}}
<div class="List Button Link" href="account.jsp"><span class="Text">账户</span></div>
{{/isLogined}}
{{^isLogined}}
<div class="List Button Link" href="login.jsp"><span class="Text">登录</span></div>
<div class="List Button Link" href="register.jsp"><span class="Text">注册</span></div>
{{/isLogined}}
<div class="List Button Link" {{#isAccount}}this{{/isAccount}}{{^isAccount}}href="/account"{{/isAccount}}><span class="Text">账户</span></div>
{{/user}}
{{^user}}
<div class="List Button Link" {{#isLogin}}this{{/isLogin}}{{^isLogin}}href="/login"{{/isLogin}}><span class="Text">登录</span></div>
<div class="List Button Link" {{#isRegister}}this{{/isRegister}}{{^isRegister}}href="/register"{{/isRegister}}><span class="Text">注册</span></div>
{{/user}}
<div class="List Special Clock">
<span class="CLOCK"></span>
</div>
<div class="List Special PinHeader">
<img class="PIN" src="images/pin.svg" checked/>
<img class="PIN" src="images/pin.svg" alt="固定图标" checked/>
</div>
</div>

View File

@ -1,128 +0,0 @@
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:action name="auth" var="AuthInfo" />
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>主页 - 67购物网站</title>
<script type="text/javascript" src="../static/scripts/header.js"></script>
<script type="text/javascript" src="../static/scripts/clock.js"></script>
<script type="text/javascript" src="../static/scripts/top.js"></script>
<script type="module" src="../static/scripts/resources.js"></script>
<script type="module" src="../static/scripts/items.js"></script>
<script type="module" src="../static/jss/index.js"></script>
<link type="image/x-icon" rel="icon" href="../static/images/favicon.ico">
<link type="text/css" rel="stylesheet" href="../static/styles/header.css">
<link type="text/css" rel="stylesheet" href="../static/styles/clock.css">
<link type="text/css" rel="stylesheet" href="../static/styles/top.css">
<link type="text/css" rel="stylesheet" href="../static/styles/footer.css">
<link type="text/css" rel="stylesheet" href="../static/styles/loading.css">
<link type="text/css" rel="stylesheet" href="../static/styles/index.css">
<!-- 外部小组件 -->
<script src="../static/scripts/lib/anime.min.js"></script>
<script async src="../static/scripts/lib/explosion.min.js"></script>
</head>
<body>
<!-- 头部内容 -->
<div id="Header">
<div class="List Special Title">67购物网站</div>
<div class="List Link" this>
<span class="Text">首页</span>
</div>
<div class="List Link" href="activity.jsp">
<span class="Text">活动</span>
</div>
<div class="List Blank"></div>
<div class="List Special SearchBar">
<input class="InputBar" type="text" />
</div>
<div class="List Blank"></div>
<div class="List Button"><span class="Text">历史记录</span></div>
<div class="List Button"><span class="Text">购物车</span></div>
<s:if test="%{#AuthInfo.IsLogined}">
<div class="List Button Link" href="logout.action"><span class="Text">注销</span></div>
<s:if test="%{#AuthInfo.UserInfo.IsAdmin}">
<div class="List Button Link" href="edit.jsp"><span class="Text">编辑</span></div>
</s:if>
<div class="List Button Link" href="account.jsp"><span class="Text">账户</span></div>
</s:if>
<s:else>
<div class="List Button Link" href="login.jsp"><span class="Text">登录</span></div>
<div class="List Button Link" href="register.jsp"><span class="Text">注册</span></div>
</s:else>
<div class="List Special Clock">
<span class="CLOCK"></span>
</div>
<div class="List Special PinHeader">
<img class="PIN" src="../static/images/pin.svg" checked />
</div>
</div>
<!-- 页面内容 -->
<div id="Contents">
<!-- 内容头 -->
<div class="ContentHeader">
<!-- 滚动横幅 -->
<div class="RollingBanner">
<div class="BannerImage">
<img />
</div>
<div class="Infos">
<span class="Title"></span>
<div class="Selecter"></div>
</div>
</div>
<!-- 推荐商品集 -->
<div class="RecommendItems"></div>
</div>
<!-- 内容本身 -->
<div class="Items"></div>
<!-- 内容为尾 -->
<div class="ContentFooter">
<div class="Loading">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<span class="Info">恭喜你找到了一个彩蛋!</span>
</div>
</div>
<!-- 页尾内容 -->
<div id="Footer">
<div class="Infos">
<div class="Icon"><img src="../static/images/icon.svg" /></div>
<div class="Title">67购物网站</div>
<div class="Contents">
<span>只做高质量商品销售~</span>
</div>
</div>
<div class="Links">
<div class="Title"></div>
<div class="Contents"></div>
</div>
</div>
<!-- 浮动内容 -->
<div id="Floater">
<!-- 回到顶层 -->
<div class="TOP"></div>
<canvas
class="fireworks"
style="
position: fixed;
left: 0;
top: 0;
z-index: 1;
pointer-events: none;
"
></canvas>
</div>
</body>
</html>

View File

@ -1,4 +1,31 @@
{{> header}}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>主页 - 在线果蔬商城</title>
<script type="text/javascript" src="scripts/header.js"></script>
<script type="text/javascript" src="scripts/clock.js"></script>
<script type="text/javascript" src="scripts/top.js"></script>
<script type="module" src="scripts/resources.js"></script>
<script type="module" src="scripts/items.js"></script>
<script type="module" src="scripts/index.js"></script>
<link type="image/x-icon" rel="icon" href="images/favicon.ico">
<!-- 页面公共的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/header.css">
<link type="text/css" rel="stylesheet" href="styles/clock.css">
<link type="text/css" rel="stylesheet" href="styles/top.css">
<link type="text/css" rel="stylesheet" href="styles/footer.css">
<link type="text/css" rel="stylesheet" href="styles/loading.css">
<!-- 页面特定的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/index.css">
<!-- 外部小组件 -->
<script src="scripts/lib/anime.min.js"></script>
<script async src="scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header }}
<!-- 页面内容 -->
<div id="Contents">
@ -7,7 +34,7 @@
<!-- 滚动横幅 -->
<div class="RollingBanner">
<div class="BannerImage">
<img />
<img alt="滚动横幅图片" src=""/>
</div>
<div class="Infos">
<span class="Title"></span>
@ -33,4 +60,7 @@
</div>
</div>
{{> footer}}
{{> footer }}
</body>
</html>

View File

@ -1,129 +0,0 @@
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:action name="auth" var="AuthInfo" />
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>商品 - 67购物网站</title>
<script type="text/javascript" src="../static/scripts/header.js"></script>
<script type="text/javascript" src="../static/scripts/clock.js"></script>
<script type="text/javascript" src="../static/scripts/top.js"></script>
<script type="text/javascript" src="../static/scripts/footer.js"></script>
<script type="module" src="../static/scripts/resources.js"></script>
<script type="module" src="../static/scripts/items.js"></script>
<script type="module" src="../static/scripts/item.js"></script>
<link type="image/x-icon" rel="icon" href="../static/images/favicon.ico">
<link type="text/css" rel="stylesheet" href="../static/styles/header.css">
<link type="text/css" rel="stylesheet" href="../static/styles/clock.css">
<link type="text/css" rel="stylesheet" href="../static/styles/top.css">
<link type="text/css" rel="stylesheet" href="../static/styles/footer.css">
<link type="text/css" rel="stylesheet" href="../static/styles/item.css">
<!-- 外部小组件 -->
<script src="../static/scripts/lib/anime.min.js"></script>
<script async src="../static/scripts/lib/explosion.min.js"></script>
</head>
<body>
<!-- 头部内容 -->
<div id="Header">
<div class="List Special Title">67购物网站</div>
<div class="List Link" href="index.jsp">
<span class="Text">首页</span>
</div>
<div class="List Link" href="activity.jsp">
<span class="Text">活动</span>
</div>
<div class="List Blank"></div>
<div class="List Special SearchBar">
<input class="InputBar" type="text" />
</div>
<div class="List Blank"></div>
<div class="List Button"><span class="Text">历史记录</span></div>
<div class="List Button"><span class="Text">购物车</span></div>
<s:if test="%{#AuthInfo.IsLogined}">
<div class="List Button Link" href="logout.action"><span class="Text">注销</span></div>
<s:if test="%{#AuthInfo.UserInfo.IsAdmin}">
<div class="List Button Link" href="edit.jsp"><span class="Text">编辑</span></div>
</s:if>
<div class="List Button Link" href="account.jsp"><span class="Text">账户</span></div>
</s:if>
<s:else>
<div class="List Button Link" href="login.jsp"><span class="Text">登录</span></div>
<div class="List Button Link" href="register.jsp"><span class="Text">注册</span></div>
</s:else>
<div class="List Special Clock">
<span class="CLOCK"></span>
</div>
<div class="List Special PinHeader">
<img class="PIN" src="../static/images/pin.svg" checked />
</div>
</div>
<!-- 页面内容 -->
<div id="Contents">
<div class="Item">
<div class="Picture">
<img />
</div>
<div class="Infos">
<span class="Title"></span>
<div class="Prices">
<div class="VipPrice"></div>
<div class="Price"></div>
</div>
<span class="Description"></span>
<div class="Options">
<div class="Option">
<div class="Title">数量</div>
<div class="Contants">
<div class="Option" selected>&nbsp;1&nbsp;</div>
<div class="Option">&nbsp;2&nbsp;</div>
<div class="Option">&nbsp;3&nbsp;</div>
<div class="Option">&nbsp;4&nbsp;</div>
<div class="Option">&nbsp;5&nbsp;</div>
<div class="Option">&nbsp;6&nbsp;</div>
</div>
</div>
</div>
<div class="Buttons">
<span class="Button">立即购买</span>
<span class="Button">加入购物车</span>
</div>
</div>
</div>
</div>
<!-- 页尾内容 -->
<div id="Footer">
<div class="Infos">
<div class="Icon"><img src="../static/images/icon.svg" /></div>
<div class="Title">67购物网站</div>
<div class="Contents">
<span>只做高质量商品销售~</span>
</div>
</div>
<div class="Links">
<div class="Title"></div>
<div class="Contents"></div>
</div>
</div>
<!-- 浮动内容 -->
<div id="Floater">
<!-- 回到顶层 -->
<div class="TOP"></div>
<canvas
class="fireworks"
style="
position: fixed;
left: 0;
top: 0;
z-index: 1;
pointer-events: none;
"
></canvas>
</div>
</body>
</html>

View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>主页 - 在线果蔬商城</title>
<script type="text/javascript" src="scripts/header.js"></script>
<script type="text/javascript" src="scripts/clock.js"></script>
<script type="text/javascript" src="scripts/top.js"></script>
<script type="text/javascript" src="scripts/footer.js"></script>
<script type="module" src="scripts/resources.js"></script>
<script type="module" src="scripts/items.js"></script>
<script type="module" src="scripts/item.js"></script>
<link type="image/x-icon" rel="icon" href="images/favicon.ico">
<!-- 页面公共的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/header.css">
<link type="text/css" rel="stylesheet" href="styles/clock.css">
<link type="text/css" rel="stylesheet" href="styles/top.css">
<link type="text/css" rel="stylesheet" href="styles/footer.css">
<link type="text/css" rel="stylesheet" href="styles/loading.css">
<!-- 页面特定的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/item.css">
<!-- 外部小组件 -->
<script src="scripts/lib/anime.min.js"></script>
<script async src="scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header }}
<!-- 页面内容 -->
<div id="Contents">
<div class="Item">
<div class="Picture">
<img alt="商品图片" src=""/>
</div>
<div class="Infos">
<span class="Title"></span>
<div class="Prices">
<div class="VipPrice"></div>
<div class="Price"></div>
</div>
<span class="Description"></span>
<div class="Options">
<div class="Option">
<div class="Title">数量</div>
<div class="Contents">
<div class="Option" selected>&nbsp;1&nbsp;</div>
<div class="Option">&nbsp;2&nbsp;</div>
<div class="Option">&nbsp;3&nbsp;</div>
<div class="Option">&nbsp;4&nbsp;</div>
<div class="Option">&nbsp;5&nbsp;</div>
<div class="Option">&nbsp;6&nbsp;</div>
</div>
</div>
</div>
<div class="Buttons">
<span class="Button">立即购买</span>
<span class="Button">加入购物车</span>
</div>
</div>
</div>
</div>
{{> footer }}
</body>
</html>

View File

@ -1,116 +0,0 @@
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:action name="auth" var="AuthInfo" />
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<title>登录 - 67购物网站</title>
<script type="text/javascript" src="../static/scripts/header.js"></script>
<script type="text/javascript" src="../static/scripts/clock.js"></script>
<script type="text/javascript" src="../static/scripts/top.js"></script>
<script type="text/javascript" src="../static/scripts/footer.js"></script>
<link type="image/x-icon" rel="icon" href="../static/images/favicon.ico">
<link type="text/css" rel="stylesheet" href="../static/styles/header.css">
<link type="text/css" rel="stylesheet" href="../static/styles/clock.css">
<link type="text/css" rel="stylesheet" href="../static/styles/top.css">
<link type="text/css" rel="stylesheet" href="../static/styles/footer.css">
<link type="text/css" rel="stylesheet" href="../static/styles/form.css">
<link type="text/css" rel="stylesheet" href="../static/styles/user.css">
<!-- 外部小组件 -->
<script src="../static/scripts/lib/anime.min.js"></script>
<script async src="../static/scripts/lib/explosion.min.js"></script>
</head>
<body>
<!-- 头部内容 -->
<div id="Header">
<div class="List Special Title">67购物网站</div>
<div class="List Link" href="index.jsp">
<span class="Text">首页</span>
</div>
<div class="List Link" href="activity.jsp">
<span class="Text">活动</span>
</div>
<div class="List Blank"></div>
<div class="List Special SearchBar">
<input class="InputBar" type="text" />
</div>
<div class="List Blank"></div>
<div class="List Button"><span class="Text">历史记录</span></div>
<div class="List Button"><span class="Text">购物车</span></div>
<s:if test="%{#AuthInfo.IsLogined}">
<div class="List Button Link" href="logout.action"><span class="Text">注销</span></div>
<s:if test="%{#AuthInfo.UserInfo.IsAdmin}">
<div class="List Button Link" href="edit.jsp"><span class="Text">编辑</span></div>
</s:if>
<div class="List Button Link" href="account.jsp"><span class="Text">账户</span></div>
</s:if>
<s:else>
<div class="List Button Link" this><span class="Text">登录</span></div>
<div class="List Button Link" href="register.jsp"><span class="Text">注册</span></div>
</s:else>
<div class="List Special Clock">
<span class="CLOCK"></span>
</div>
<div class="List Special PinHeader">
<img class="PIN" src="../static/images/pin.svg" checked />
</div>
</div>
<!-- 页面内容 -->
<div id="Contents">
<form class="TabForm" action="login.action" method="post">
<div class="TabTitle">登录</div>
<div class="TabFormItems">
<div class="TabFormItem">
<label class="ItemName" for="username">用户名</label>
<input class="ItemInput" id="username" type="text" name="username" placeholder="请输入用户名" required />
</div>
<div class="TabFormItem">
<label class="ItemName" for="password">密码</label>
<input class="ItemInput" id="password" type="password" name="password" placeholder="请输入密码" required />
</div>
</div>
<div class="TabButtons">
<button class="TabButton" type="reset">重置</button>
<button class="TabButton" type="submit">登录</button>
</div>
</form>
</div>
<!-- 页尾内容 -->
<div id="Footer">
<div class="Infos">
<div class="Icon"><img src="../static/images/icon.svg" /></div>
<div class="Title">67购物网站</div>
<div class="Contents">
<span>只做高质量商品销售~</span>
</div>
</div>
<div class="Links">
<div class="Title"></div>
<div class="Contents"></div>
</div>
</div>
<!-- 浮动内容 -->
<div id="Floater">
<!-- 回到顶层 -->
<div class="TOP"></div>
<canvas
class="fireworks"
style="
position: fixed;
left: 0;
top: 0;
z-index: 1;
pointer-events: none;
"
></canvas>
</div>
</body>
</html>

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>主页 - 在线果蔬商城</title>
<script type="text/javascript" src="scripts/header.js"></script>
<script type="text/javascript" src="scripts/clock.js"></script>
<script type="text/javascript" src="scripts/top.js"></script>
<script type="module" src="scripts/resources.js"></script>
<script type="module" src="scripts/items.js"></script>
<script type="module" src="scripts/index.js"></script>
<link type="image/x-icon" rel="icon" href="images/favicon.ico">
<!-- 页面公共的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/header.css">
<link type="text/css" rel="stylesheet" href="styles/clock.css">
<link type="text/css" rel="stylesheet" href="styles/top.css">
<link type="text/css" rel="stylesheet" href="styles/footer.css">
<link type="text/css" rel="stylesheet" href="styles/loading.css">
<link type="text/css" rel="stylesheet" href="styles/form.css">
<!-- 页面特定的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/user.css">
<!-- 外部小组件 -->
<script src="scripts/lib/anime.min.js"></script>
<script async src="scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header}}
<!-- 页面内容 -->
<div id="Contents">
<form class="TabForm" action="action/account/login" method="post">
<div class="TabTitle">登录</div>
<div class="TabFormItems">
<div class="TabFormItem">
<label class="ItemName" for="name">用户名</label>
<input class="ItemInput" id="name" type="text" name="name" placeholder="请输入用户名" required/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="password">密码</label>
<input class="ItemInput" id="password" type="password" name="password" placeholder="请输入密码"
required/>
</div>
</div>
<div class="TabButtons">
<button class="TabButton" type="reset">重置</button>
<button class="TabButton" type="submit">登录</button>
</div>
</form>
</div>
{{> footer}}
</body>
</html>

View File

@ -1,141 +0,0 @@
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:action name="auth" var="AuthInfo" />
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<title>注册 - 67购物网站</title>
<script type="text/javascript" src="../static/scripts/header.js"></script>
<script type="text/javascript" src="../static/scripts/clock.js"></script>
<script type="text/javascript" src="../static/scripts/top.js"></script>
<script type="text/javascript" src="../static/scripts/footer.js"></script>
<link type="image/x-icon" rel="icon" href="../static/images/favicon.ico">
<link type="text/css" rel="stylesheet" href="../static/styles/header.css">
<link type="text/css" rel="stylesheet" href="../static/styles/clock.css">
<link type="text/css" rel="stylesheet" href="../static/styles/top.css">
<link type="text/css" rel="stylesheet" href="../static/styles/footer.css">
<link type="text/css" rel="stylesheet" href="../static/styles/form.css">
<link type="text/css" rel="stylesheet" href="../static/styles/user.css">
<!-- 外部小组件 -->
<script src="../static/scripts/lib/anime.min.js"></script>
<script async src="../static/scripts/lib/explosion.min.js"></script>
</head>
<body>
<!-- 头部内容 -->
<div id="Header">
<div class="List Special Title">67购物网站</div>
<div class="List Link" href="index.jsp">
<span class="Text">首页</span>
</div>
<div class="List Link" href="activity.jsp">
<span class="Text">活动</span>
</div>
<div class="List Blank"></div>
<div class="List Special SearchBar">
<input class="InputBar" type="text" />
</div>
<div class="List Blank"></div>
<div class="List Button"><span class="Text">历史记录</span></div>
<div class="List Button"><span class="Text">购物车</span></div>
<s:if test="%{#AuthInfo.IsLogined}">
<div class="List Button Link" href="logout.action"><span class="Text">注销</span></div>
<s:if test="%{#AuthInfo.UserInfo.IsAdmin}">
<div class="List Button Link" href="edit.jsp"><span class="Text">编辑</span></div>
</s:if>
<div class="List Button Link" href="account.jsp"><span class="Text">账户</span></div>
</s:if>
<s:else>
<div class="List Button Link" href="login.jsp"><span class="Text">登录</span></div>
<div class="List Button Link" this><span class="Text">注册</span></div>
</s:else>
<div class="List Special Clock">
<span class="CLOCK"></span>
</div>
<div class="List Special PinHeader">
<img class="PIN" src="../static/images/pin.svg" checked />
</div>
</div>
<!-- 页面内容 -->
<div id="Contents">
<form class="TabForm" action="register.action" method="post">
<div class="TabTitle">注册</div>
<div class="TabFormItems">
<div class="TabFormItem">
<label class="ItemName" for="username">用户名</label>
<input class="ItemInput" id="username" type="text" name="username" placeholder="请输入用户名" required />
</div>
<div class="TabFormItem">
<label class="ItemName" for="password">密码</label>
<input class="ItemInput" id="password" type="password" name="password" placeholder="请输入密码" required />
</div>
<div class="TabFormItem">
<label class="ItemName" for="passwrod">确认密码</label>
<input class="ItemInput" id="password_confirm" type="password" name="password_confirm" placeholder="请输入确认密码" required />
</div>
<div class="TabFormItem">
<label class="ItemName" for="age">年龄</label>
<input class="ItemInput" id="age" type="number" name="age" placeholder="请输入年龄" />
</div>
<div class="TabFormItem">
<label class="ItemName" for="email">邮箱</label>
<input class="ItemInput" id="email" type="email" name="email" placeholder="请输入邮箱" />
</div>
<div class="TabFormItem">
<input class="ItemInput" id="gender_null" type="radio" name="gender" value="N" checked />
<label class="ItemName" for="gender_null">未知</label>
<input class="ItemInput"id="gender_male" type="radio" name="gender" value="M" />
<label class="ItemName" for="gender_male">男性</label>
<input class="ItemInput"id="gender_female" type="radio" name="gender" value="F" />
<label class="ItemName" for="gender_female">女性</label>
</div>
</div>
<div class="TabButtons">
<button class="TabButton" type="reset">重置</button>
<button class="TabButton" type="submit">注册并登录</button>
</div>
</form>
</div>
<!-- 页尾内容 -->
<div id="Footer">
<div class="Infos">
<div class="Icon"><img src="../static/images/icon.svg" /></div>
<div class="Title">67购物网站</div>
<div class="Contents">
<span>只做高质量商品销售~</span>
</div>
</div>
<div class="Links">
<div class="Title"></div>
<div class="Contents"></div>
</div>
</div>
<!-- 浮动内容 -->
<div id="Floater">
<!-- 回到顶层 -->
<div class="TOP"></div>
<canvas
class="fireworks"
style="
position: fixed;
left: 0;
top: 0;
z-index: 1;
pointer-events: none;
"
></canvas>
</div>
</body>
</html>

View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>主页 - 在线果蔬商城</title>
<script type="text/javascript" src="scripts/header.js"></script>
<script type="text/javascript" src="scripts/clock.js"></script>
<script type="text/javascript" src="scripts/top.js"></script>
<script type="module" src="scripts/resources.js"></script>
<script type="module" src="scripts/items.js"></script>
<script type="module" src="scripts/index.js"></script>
<link type="image/x-icon" rel="icon" href="images/favicon.ico">
<!-- 页面公共的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/header.css">
<link type="text/css" rel="stylesheet" href="styles/clock.css">
<link type="text/css" rel="stylesheet" href="styles/top.css">
<link type="text/css" rel="stylesheet" href="styles/footer.css">
<link type="text/css" rel="stylesheet" href="styles/loading.css">
<link type="text/css" rel="stylesheet" href="styles/form.css">
<!-- 页面特定的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/user.css">
<!-- 外部小组件 -->
<script src="scripts/lib/anime.min.js"></script>
<script async src="scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header }}
<!-- 页面内容 -->
<div id="Contents">
<form class="TabForm" action="action/account/register" method="post">
<div class="TabTitle">注册</div>
<div class="TabFormItems">
<div class="TabFormItem">
<label class="ItemName" for="name">用户名</label>
<input class="ItemInput" id="name" type="text" name="username" placeholder="请输入用户名" required/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="password">密码</label>
<input class="ItemInput" id="password" type="password" name="password" placeholder="请输入密码"
required/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="password_confirm">确认密码</label>
<input class="ItemInput" id="password_confirm" type="password" name="password_confirm"
placeholder="请输入确认密码" required/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="age">年龄</label>
<input class="ItemInput" id="age" type="number" name="age" placeholder="请输入年龄"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="phone">邮箱</label>
<input class="ItemInput" id="phone" type="text" name="phone" placeholder="请输入手机号"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="email">邮箱</label>
<input class="ItemInput" id="email" type="email" name="email" placeholder="请输入邮箱"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="address">邮箱</label>
<input class="ItemInput" id="address" type="text" name="address" placeholder="请输入邮箱"/>
</div>
<div class="TabFormItem">
<input class="ItemInput" id="gender_null" type="radio" name="gender" value="N" checked/>
<label class="ItemName" for="gender_null">未知</label>
<input class="ItemInput" id="gender_male" type="radio" name="gender" value="M"/>
<label class="ItemName" for="gender_male">男性</label>
<input class="ItemInput" id="gender_female" type="radio" name="gender" value="F"/>
<label class="ItemName" for="gender_female">女性</label>
</div>
</div>
<div class="TabButtons">
<button class="TabButton" type="reset">重置</button>
<button class="TabButton" type="submit">注册并登录</button>
</div>
</form>
</div>
{{> footer }}
</body>
</html>

View File

@ -1,13 +0,0 @@
package team8.fruitable
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest
class FruitableApplicationTests {
@Test
fun contextLoads() {
}
}